int64_t file_start_time;
int64_t file_inpoint;
int64_t duration;
+ int64_t user_duration;
int64_t next_dts;
ConcatStream *streams;
int64_t inpoint;
int segment_time_metadata;
} ConcatContext;
-static int concat_probe(AVProbeData *probe)
+static int concat_probe(const AVProbeData *probe)
{
return memcmp(probe->buf, "ffconcat version 1.0", 20) ?
0 : AVPROBE_SCORE_MAX;
file->next_dts = AV_NOPTS_VALUE;
file->inpoint = AV_NOPTS_VALUE;
file->outpoint = AV_NOPTS_VALUE;
+ file->user_duration = AV_NOPTS_VALUE;
return 0;
if (st->codecpar->codec_id || !source_st->codecpar->codec_id) {
if (st->codecpar->extradata_size < source_st->codecpar->extradata_size) {
- if (st->codecpar->extradata) {
- av_freep(&st->codecpar->extradata);
- st->codecpar->extradata_size = 0;
- }
ret = ff_alloc_extradata(st->codecpar,
source_st->codecpar->extradata_size);
if (ret < 0)
return 0;
}
+static int64_t get_best_effort_duration(ConcatFile *file, AVFormatContext *avf)
+{
+ if (file->user_duration != AV_NOPTS_VALUE)
+ return file->user_duration;
+ if (file->outpoint != AV_NOPTS_VALUE)
+ return file->outpoint - file->file_inpoint;
+ if (avf->duration > 0)
+ return avf->duration - (file->file_inpoint - file->file_start_time);
+ if (file->next_dts != AV_NOPTS_VALUE)
+ return file->next_dts - file->file_inpoint;
+ return AV_NOPTS_VALUE;
+}
+
static int open_file(AVFormatContext *avf, unsigned fileno)
{
ConcatContext *cat = avf->priv_data;
return ret;
}
cat->cur_file = file;
- if (file->start_time == AV_NOPTS_VALUE)
- file->start_time = !fileno ? 0 :
- cat->files[fileno - 1].start_time +
- cat->files[fileno - 1].duration;
+ file->start_time = !fileno ? 0 :
+ cat->files[fileno - 1].start_time +
+ cat->files[fileno - 1].duration;
file->file_start_time = (cat->avf->start_time == AV_NOPTS_VALUE) ? 0 : cat->avf->start_time;
file->file_inpoint = (file->inpoint == AV_NOPTS_VALUE) ? file->file_start_time : file->inpoint;
- if (file->duration == AV_NOPTS_VALUE && file->outpoint != AV_NOPTS_VALUE)
- file->duration = file->outpoint - file->file_inpoint;
+ file->duration = get_best_effort_duration(file, cat->avf);
if (cat->segment_time_metadata) {
av_dict_set_int(&file->metadata, "lavf.concatdec.start_time", file->start_time, 0);
goto fail;
}
if (!strcmp(keyword, "duration"))
- file->duration = dur;
+ file->user_duration = dur;
else if (!strcmp(keyword, "inpoint"))
file->inpoint = dur;
else if (!strcmp(keyword, "outpoint"))
cat->files[i].start_time = time;
else
time = cat->files[i].start_time;
- if (cat->files[i].duration == AV_NOPTS_VALUE) {
+ if (cat->files[i].user_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;
+ cat->files[i].user_duration = cat->files[i].outpoint - cat->files[i].inpoint;
}
- time += cat->files[i].duration;
+ cat->files[i].duration = cat->files[i].user_duration;
+ time += cat->files[i].user_duration;
}
if (i == cat->nb_files) {
avf->duration = time;
ConcatContext *cat = avf->priv_data;
unsigned fileno = cat->cur_file - cat->files;
- if (cat->cur_file->duration == AV_NOPTS_VALUE) {
- if (cat->avf->duration > 0 || cat->cur_file->next_dts == AV_NOPTS_VALUE) {
- cat->cur_file->duration = cat->avf->duration;
- } else {
- cat->cur_file->duration = cat->cur_file->next_dts;
- }
- cat->cur_file->duration -= (cat->cur_file->file_inpoint - cat->cur_file->file_start_time);
- }
+ cat->cur_file->duration = get_best_effort_duration(cat->cur_file, cat->avf);
if (++fileno >= cat->nb_files) {
cat->eof = 1;
if (ret < 0) {
av_log(avf, AV_LOG_ERROR, "h264_mp4toannexb filter "
"failed to send input packet\n");
- av_packet_unref(pkt);
return ret;
}
if (ret < 0)
return ret;
if ((ret = match_streams(avf)) < 0) {
- av_packet_unref(pkt);
return ret;
}
if (packet_after_outpoint(cat, pkt)) {
}
break;
}
- if ((ret = filter_packet(avf, cs, pkt)))
+ if ((ret = filter_packet(avf, cs, pkt)) < 0)
return ret;
st = cat->avf->streams[pkt->stream_index];
left = 0;
right = cat->nb_files;
+
+ /* Always support seek to start */
+ if (ts <= 0)
+ right = 1;
+ else if (!cat->seekable)
+ return AVERROR(ESPIPE); /* XXX: can we use it? */
+
while (right - left > 1) {
int mid = (left + right) / 2;
if (ts < cat->files[mid].start_time)
AVFormatContext *cur_avf_saved = cat->avf;
int ret;
- if (!cat->seekable)
- return AVERROR(ESPIPE); /* XXX: can we use it? */
if (flags & (AVSEEK_FLAG_BYTE | AVSEEK_FLAG_FRAME))
return AVERROR(ENOSYS);
cat->avf = NULL;