From patchwork Sat Sep 10 02:07:31 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rodger Combs X-Patchwork-Id: 507 Delivered-To: ffmpegpatchwork@gmail.com Received: by 10.103.140.134 with SMTP id o128csp597530vsd; Fri, 9 Sep 2016 19:08:17 -0700 (PDT) X-Received: by 10.28.208.130 with SMTP id h124mr870002wmg.101.1473473297540; Fri, 09 Sep 2016 19:08:17 -0700 (PDT) Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id yv8si5498185wjb.134.2016.09.09.19.08.15; Fri, 09 Sep 2016 19:08:17 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE dis=NONE) header.from=gmail.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id AF04E689E5D; Sat, 10 Sep 2016 05:07:53 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-oi0-f68.google.com (mail-oi0-f68.google.com [209.85.218.68]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 8922F689D9E for ; Sat, 10 Sep 2016 05:07:47 +0300 (EEST) Received: by mail-oi0-f68.google.com with SMTP id 2so12870451oif.2 for ; Fri, 09 Sep 2016 19:07:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:subject:date:message-id:in-reply-to:references; bh=52mxoxSg6GASiyV6YYsIqi2HvnCtW3zY+TLD75oHTkA=; b=jZLZITIGGgElTBTEfK4wnREwSg47BPNjPasJ9sA1fBcWQajsqhYiHpUhnfXJKIIKlJ j2VODu8jVXgE9NWDwzSXmD+onqJaGMmmTQAKba6TCzR14pXcm/7erJq4IgdRjY+sHwfa W97guR5NbI2bEVJkCBw7lmTlMctA7bOtj2cWmekr2R1MvizkwOqoipS9Jp81weIXqw+d g0nsyuD4AZyVSlMERZj8P9qumlEJ+7itaMLjnD3Te0zygx8WIi19z+OVEqvCl3GzWVtL XvLfGtXi9yzFzf3bdzSS9tG4MRvDrulTUYrvGjoZZn/n2f1dLT+Z83az/0bhZOUBHxIg O1lw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references; bh=52mxoxSg6GASiyV6YYsIqi2HvnCtW3zY+TLD75oHTkA=; b=NsAaoB55ujyJLsH2QX5YMkrv3dbycAajUW03iGqjRa8OPLYjOnmEzbCEyBpdqEqN1h UWtuRzmpZLNNZUoMjKFCQ38a/0qS8apobztUCYMMjVwK+mjmttcAuu2dwXSYid++UJtq z3k+rwz9M7ZZ2nRGbsyUimQRZO8AqQWfyZu8eOIySSJYahjHoGqm5Zr+5TiBvPkHXWAM kxZMYbx2fv+Pjm89zwEGrwIhW7quaDpNs8UlBIWhj1SeZBZylLB6fXRN5bAiQQlJ+zS1 rOMrmeP0QcZyQ2B9ljrl/0mKQJMaL303qFmqPsJx4BgnBJQz9CcJ4g+8nQYRDwRd/Qpi v9hw== X-Gm-Message-State: AE9vXwP7TAhjCMV6mfpv/8bZyONfGWhjImErWBrNaXugjmXrp89WEr3mEsbOwXs00Ub+IQ== X-Received: by 10.202.72.139 with SMTP id v133mr9465962oia.62.1473473277153; Fri, 09 Sep 2016 19:07:57 -0700 (PDT) Received: from Rodgers-MacBook-Pro.local.net (c-73-209-137-129.hsd1.il.comcast.net. [73.209.137.129]) by smtp.gmail.com with ESMTPSA id h63sm3271182ita.12.2016.09.09.19.07.55 for (version=TLS1 cipher=AES128-SHA bits=128/128); Fri, 09 Sep 2016 19:07:55 -0700 (PDT) From: Rodger Combs To: ffmpeg-devel@ffmpeg.org Date: Fri, 9 Sep 2016 21:07:31 -0500 Message-Id: <20160910020732.24359-2-rodger.combs@gmail.com> X-Mailer: git-send-email 2.10.0 In-Reply-To: <20160910020732.24359-1-rodger.combs@gmail.com> References: <20160910020732.24359-1-rodger.combs@gmail.com> Subject: [FFmpeg-devel] [PATCH 2/3] lavf/mov: improve `tref/chap` chapter handling X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" 3 parts: - Supports multiple chapter streams - Exports regular text chapter streams as opaque data. This prevents consumers from showing chapters as if they were regular subtitle streams. - Exports video chapter streams as thumbnails, and provides the first one as an attached_pic. --- libavformat/isom.h | 3 ++- libavformat/mov.c | 52 +++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 47 insertions(+), 8 deletions(-) diff --git a/libavformat/isom.h b/libavformat/isom.h index 2246fed..9038057 100644 --- a/libavformat/isom.h +++ b/libavformat/isom.h @@ -210,7 +210,8 @@ typedef struct MOVContext { unsigned trex_count; int itunes_metadata; ///< metadata are itunes style int handbrake_version; - int chapter_track; + int *chapter_tracks; + unsigned int nb_chapter_tracks; int use_absolute_path; int ignore_editlist; int ignore_chapters; diff --git a/libavformat/mov.c b/libavformat/mov.c index 6e80b93..22ca809 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -3574,7 +3574,18 @@ static int mov_read_tfhd(MOVContext *c, AVIOContext *pb, MOVAtom atom) static int mov_read_chap(MOVContext *c, AVIOContext *pb, MOVAtom atom) { - c->chapter_track = avio_rb32(pb); + unsigned i, num; + av_free(c->chapter_tracks); + + num = atom.size / 4; + if (!(c->chapter_tracks = av_malloc(num * 4))) + return AVERROR(ENOMEM); + + c->nb_chapter_tracks = num; + + for (i = 0; i < num; i++) + c->chapter_tracks[i] = avio_rb32(pb); + return 0; } @@ -4637,25 +4648,50 @@ static int mov_probe(AVProbeData *p) static void mov_read_chapters(AVFormatContext *s) { MOVContext *mov = s->priv_data; - AVStream *st = NULL; + AVStream *st; MOVStreamContext *sc; int64_t cur_pos; - int i; + int i, j; + int chapter_track; + for (j = 0; j < mov->nb_chapter_tracks; j++) { + chapter_track = mov->chapter_tracks[j]; + st = NULL; for (i = 0; i < s->nb_streams; i++) - if (s->streams[i]->id == mov->chapter_track) { + if (s->streams[i]->id == chapter_track) { st = s->streams[i]; break; } if (!st) { av_log(s, AV_LOG_ERROR, "Referenced QT chapter track not found\n"); - return; + continue; } - st->discard = AVDISCARD_ALL; sc = st->priv_data; cur_pos = avio_tell(sc->pb); + if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { + st->disposition |= AV_DISPOSITION_ATTACHED_PIC | AV_DISPOSITION_TIMED_THUMBNAILS; + if (st->nb_index_entries) { + // Retrieve the first frame, if possible + AVPacket pkt; + AVIndexEntry *sample = &st->index_entries[0]; + if (avio_seek(sc->pb, sample->pos, SEEK_SET) != sample->pos) { + av_log(s, AV_LOG_ERROR, "Failed to retrieve first frame\n"); + goto finish; + } + + if (av_get_packet(sc->pb, &pkt, sample->size) < 0) + goto finish; + + st->attached_pic = pkt; + st->attached_pic.stream_index = st->index; + st->attached_pic.flags |= AV_PKT_FLAG_KEY; + } + } else { + st->codec->codec_type = AVMEDIA_TYPE_DATA; + st->codec->codec_id = AV_CODEC_ID_BIN_DATA; + st->discard = AVDISCARD_ALL; for (i = 0; i < st->nb_index_entries; i++) { AVIndexEntry *sample = &st->index_entries[i]; int64_t end = i+1 < st->nb_index_entries ? st->index_entries[i+1].timestamp : st->duration; @@ -4704,8 +4740,10 @@ static void mov_read_chapters(AVFormatContext *s) avpriv_new_chapter(s, i, st->time_base, sample->timestamp, end, title); av_freep(&title); } + } finish: avio_seek(sc->pb, cur_pos, SEEK_SET); + } } static int parse_timecode_in_framenum_format(AVFormatContext *s, AVStream *st, @@ -5028,7 +5066,7 @@ static int mov_read_header(AVFormatContext *s) av_log(mov->fc, AV_LOG_TRACE, "on_parse_exit_offset=%"PRId64"\n", avio_tell(pb)); if (pb->seekable) { - if (mov->chapter_track > 0 && !mov->ignore_chapters) + if (mov->nb_chapter_tracks > 0 && !mov->ignore_chapters) mov_read_chapters(s); for (i = 0; i < s->nb_streams; i++) if (s->streams[i]->codecpar->codec_tag == AV_RL32("tmcd")) {