concatdec: add support for specifying outpoint of files

Reviewed-by: Nicolas George <george@nsup.org>
Signed-off-by: Marton Balint <cus@passwd.hu>
This commit is contained in:
Marton Balint 2015-07-02 20:35:04 +02:00 committed by Michael Niedermayer
parent 12d82004c5
commit 25a6711c25
2 changed files with 44 additions and 4 deletions

View File

@ -129,6 +129,25 @@ 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{outpoint @var{timestamp}}
Out point of the file. When the demuxer reaches the specified decoding
timestamp in any of the streams, it handles it as an end of file condition and
skips the current and all the remaining packets from all streams.
Out point is exclusive, which means that the demuxer will not output packets
with a decoding timestamp greater or equal to Out point.
This directive works best with intra frame codecs and formats where all streams
are tightly interleaved. For non-intra frame codecs you will usually get
additional packets with presentation timestamp after Out point therefore the
decoded content will most likely contain frames after Out point too. If your
streams are not tightly interleaved you may not get all the packets from all
streams before Out point and you may only will be able to decode the earliest
stream until Out point.
The duration of the files (if not specified by the @code{duration}
directive) will be reduced based on their specified Out point.
@item @code{stream}
Introduce a stream in the virtual file.
All subsequent stream-related directives apply to the last introduced

View File

@ -46,6 +46,7 @@ typedef struct {
int64_t duration;
ConcatStream *streams;
int64_t inpoint;
int64_t outpoint;
int nb_streams;
} ConcatFile;
@ -147,6 +148,7 @@ static int add_file(AVFormatContext *avf, char *filename, ConcatFile **rfile,
file->start_time = AV_NOPTS_VALUE;
file->duration = AV_NOPTS_VALUE;
file->inpoint = AV_NOPTS_VALUE;
file->outpoint = AV_NOPTS_VALUE;
return 0;
@ -364,7 +366,7 @@ 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") || !strcmp(keyword, "inpoint")) {
} else if (!strcmp(keyword, "duration") || !strcmp(keyword, "inpoint") || !strcmp(keyword, "outpoint")) {
char *dur_str = get_keyword(&cursor);
int64_t dur;
if (!file) {
@ -381,6 +383,8 @@ static int concat_read_header(AVFormatContext *avf)
file->duration = dur;
else if (!strcmp(keyword, "inpoint"))
file->inpoint = dur;
else if (!strcmp(keyword, "outpoint"))
file->outpoint = dur;
} else if (!strcmp(keyword, "stream")) {
if (!avformat_new_stream(avf, NULL))
FAIL(AVERROR(ENOMEM));
@ -417,8 +421,11 @@ static int concat_read_header(AVFormatContext *avf)
cat->files[i].start_time = time;
else
time = cat->files[i].start_time;
if (cat->files[i].duration == AV_NOPTS_VALUE)
break;
if (cat->files[i].duration == AV_NOPTS_VALUE) {
if (cat->files[i].inpoint == AV_NOPTS_VALUE || cat->files[i].outpoint == AV_NOPTS_VALUE)
break;
cat->files[i].duration = cat->files[i].outpoint - cat->files[i].inpoint;
}
time += cat->files[i].duration;
}
if (i == cat->nb_files) {
@ -446,6 +453,8 @@ static int open_next_file(AVFormatContext *avf)
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 (cat->cur_file->outpoint != AV_NOPTS_VALUE)
cat->cur_file->duration -= cat->avf->duration - (cat->cur_file->outpoint - cat->cur_file->file_start_time);
}
if (++fileno >= cat->nb_files) {
@ -495,6 +504,16 @@ static int filter_packet(AVFormatContext *avf, ConcatStream *cs, AVPacket *pkt)
return 0;
}
/* Returns true if the packet dts is greater or equal to the specified outpoint. */
static int packet_after_outpoint(ConcatContext *cat, AVPacket *pkt)
{
if (cat->cur_file->outpoint != AV_NOPTS_VALUE && pkt->dts != AV_NOPTS_VALUE) {
return av_compare_ts(pkt->dts, cat->avf->streams[pkt->stream_index]->time_base,
cat->cur_file->outpoint, AV_TIME_BASE_Q) >= 0;
}
return 0;
}
static int concat_read_packet(AVFormatContext *avf, AVPacket *pkt)
{
ConcatContext *cat = avf->priv_data;
@ -511,7 +530,9 @@ static int concat_read_packet(AVFormatContext *avf, AVPacket *pkt)
while (1) {
ret = av_read_frame(cat->avf, pkt);
if (ret == AVERROR_EOF) {
if (ret == AVERROR_EOF || packet_after_outpoint(cat, pkt)) {
if (ret == 0)
av_packet_unref(pkt);
if ((ret = open_next_file(avf)) < 0)
return ret;
continue;