concatdec: add support for specifying inpoint of files
authorMarton Balint <cus@passwd.hu>
Thu, 2 Jul 2015 17:56:25 +0000 (19:56 +0200)
committerMichael Niedermayer <michael@niedermayer.cc>
Thu, 16 Jul 2015 22:12:04 +0000 (00:12 +0200)
Reviewed-by: Nicolas George <george@nsup.org>
Signed-off-by: Marton Balint <cus@passwd.hu>
doc/demuxers.texi
libavformat/concatdec.c

index 35a1561..27a9409 100644 (file)
@@ -112,6 +112,23 @@ file is not available or accurate.
 If the duration is set for all files, then it is possible to seek in the
 whole concatenated video.
 
+@item @code{inpoint @var{timestamp}}
+In point of the file. When the demuxer opens the file it instantly seeks to the
+specified timestamp. Seeking is done so that all streams can be presented
+successfully at In point.
+
+This directive works best with intra frame codecs, because for non-intra frame
+ones you will usually get extra packets before the actual In point and the
+decoded content will most likely contain frames before In point too.
+
+For each file, packets before the file In point will have timestamps less than
+the calculated start timestamp of the file (negative in case of the first
+file), and the duration of the files (if not specified by the @code{duration}
+directive) will be reduced based on their specified In point.
+
+Because of potential packets before the specified In point, packet timestamps
+may overlap between two concatenated files.
+
 @item @code{stream}
 Introduce a stream in the virtual file.
 All subsequent stream-related directives apply to the last introduced
index e95ff34..685b157 100644 (file)
@@ -41,8 +41,11 @@ typedef struct ConcatStream {
 typedef struct {
     char *url;
     int64_t start_time;
+    int64_t file_start_time;
+    int64_t file_inpoint;
     int64_t duration;
     ConcatStream *streams;
+    int64_t inpoint;
     int nb_streams;
 } ConcatFile;
 
@@ -142,6 +145,7 @@ static int add_file(AVFormatContext *avf, char *filename, ConcatFile **rfile,
     file->url        = url;
     file->start_time = AV_NOPTS_VALUE;
     file->duration   = AV_NOPTS_VALUE;
+    file->inpoint    = AV_NOPTS_VALUE;
 
     return 0;
 
@@ -306,8 +310,14 @@ static int open_file(AVFormatContext *avf, unsigned fileno)
         file->start_time = !fileno ? 0 :
                            cat->files[fileno - 1].start_time +
                            cat->files[fileno - 1].duration;
+    file->file_start_time = (avf->start_time == AV_NOPTS_VALUE) ? 0 : avf->start_time;
+    file->file_inpoint = (file->file_inpoint == AV_NOPTS_VALUE) ? file->file_start_time : file->inpoint;
     if ((ret = match_streams(avf)) < 0)
         return ret;
+    if (file->inpoint != AV_NOPTS_VALUE) {
+       if ((ret = avformat_seek_file(cat->avf, -1, INT64_MIN, file->inpoint, file->inpoint, 0)) < 0)
+           return ret;
+    }
     return 0;
 }
 
@@ -353,20 +363,23 @@ static int concat_read_header(AVFormatContext *avf)
             }
             if ((ret = add_file(avf, filename, &file, &nb_files_alloc)) < 0)
                 goto fail;
-        } else if (!strcmp(keyword, "duration")) {
+        } else if (!strcmp(keyword, "duration") || !strcmp(keyword, "inpoint")) {
             char *dur_str = get_keyword(&cursor);
             int64_t dur;
             if (!file) {
-                av_log(avf, AV_LOG_ERROR, "Line %d: duration without file\n",
-                       line);
+                av_log(avf, AV_LOG_ERROR, "Line %d: %s without file\n",
+                       line, keyword);
                 FAIL(AVERROR_INVALIDDATA);
             }
             if ((ret = av_parse_time(&dur, dur_str, 1)) < 0) {
-                av_log(avf, AV_LOG_ERROR, "Line %d: invalid duration '%s'\n",
-                       line, dur_str);
+                av_log(avf, AV_LOG_ERROR, "Line %d: invalid %s '%s'\n",
+                       line, keyword, dur_str);
                 goto fail;
             }
-            file->duration = dur;
+            if (!strcmp(keyword, "duration"))
+                file->duration = dur;
+            else if (!strcmp(keyword, "inpoint"))
+                file->inpoint = dur;
         } else if (!strcmp(keyword, "stream")) {
             if (!avformat_new_stream(avf, NULL))
                 FAIL(AVERROR(ENOMEM));
@@ -428,8 +441,11 @@ static int open_next_file(AVFormatContext *avf)
     ConcatContext *cat = avf->priv_data;
     unsigned fileno = cat->cur_file - cat->files;
 
-    if (cat->cur_file->duration == AV_NOPTS_VALUE)
+    if (cat->cur_file->duration == AV_NOPTS_VALUE) {
         cat->cur_file->duration = cat->avf->duration;
+        if (cat->cur_file->inpoint != AV_NOPTS_VALUE)
+            cat->cur_file->duration -= (cat->cur_file->inpoint - cat->cur_file->file_start_time);
+    }
 
     if (++fileno >= cat->nb_files)
         return AVERROR_EOF;
@@ -480,7 +496,7 @@ static int concat_read_packet(AVFormatContext *avf, AVPacket *pkt)
 {
     ConcatContext *cat = avf->priv_data;
     int ret;
-    int64_t file_start_time, delta;
+    int64_t delta;
     ConcatStream *cs;
     AVStream *st;
 
@@ -517,10 +533,7 @@ static int concat_read_packet(AVFormatContext *avf, AVPacket *pkt)
            av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &st->time_base),
            av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &st->time_base));
 
-    file_start_time = cat->avf->start_time;
-    if (file_start_time == AV_NOPTS_VALUE)
-        file_start_time = 0;
-    delta = av_rescale_q(cat->cur_file->start_time - file_start_time,
+    delta = av_rescale_q(cat->cur_file->start_time - cat->cur_file->file_inpoint,
                          AV_TIME_BASE_Q,
                          cat->avf->streams[pkt->stream_index]->time_base);
     if (pkt->pts != AV_NOPTS_VALUE)
@@ -547,7 +560,7 @@ static int try_seek(AVFormatContext *avf, int stream,
                     int64_t min_ts, int64_t ts, int64_t max_ts, int flags)
 {
     ConcatContext *cat = avf->priv_data;
-    int64_t t0 = cat->cur_file->start_time - cat->avf->start_time;
+    int64_t t0 = cat->cur_file->start_time - cat->cur_file->file_inpoint;
 
     ts -= t0;
     min_ts = min_ts == INT64_MIN ? INT64_MIN : min_ts - t0;