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:
parent
12d82004c5
commit
25a6711c25
@ -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
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user