[FFmpeg-devel] [PATCH 4/4] concatdec: add support for injecting packet metadata

Marton Balint cus at passwd.hu
Tue Jul 7 00:19:34 CEST 2015



On Mon, 6 Jul 2015, Nicolas George wrote:

> L'octidi 18 messidor, an CCXXIII, Marton Balint a écrit :
>> Signed-off-by: Marton Balint <cus at passwd.hu>
>> ---
>>  doc/demuxers.texi       |  4 ++++
>>  libavformat/concatdec.c | 30 ++++++++++++++++++++++++++++++
>>  2 files changed, 34 insertions(+)
>>
>> diff --git a/doc/demuxers.texi b/doc/demuxers.texi
>> index 4ba797e..28244f3 100644
>> --- a/doc/demuxers.texi
>> +++ b/doc/demuxers.texi
>> @@ -142,6 +142,10 @@ before the specified Out point.
>>  The duration of the files (if not specified by the @code{duration}
>>  directive) will be reduced based on their specified Out point.
>>
>> + at item @code{metadata @var{string}}
>> +Metadata of the file. The specified metadata (which consists of
>> + at code{key=value} pairs seperated by commas) will be set for each file packet.
>
> This looks like a step into escaping hell.
>
> 	metadata foo=bar,baz=qux
>
> 	metadata foo=bar
> 	metadata baz=qux
>
> Would the second form be ok for you?

Ok.

>
>> +
>>  @item @code{stream}
>>  Introduce a stream in the virtual file.
>>  All subsequent stream-related directives apply to the last introduced
>> diff --git a/libavformat/concatdec.c b/libavformat/concatdec.c
>> index eaf34b0..66e81c8 100644
>> --- a/libavformat/concatdec.c
>> +++ b/libavformat/concatdec.c
>> @@ -45,6 +45,8 @@ typedef struct {
>>      ConcatStream *streams;
>>      int64_t inpoint;
>>      int64_t outpoint;
>> +    char *metadata;
>> +    int metadata_len;
>>      int nb_streams;
>>  } ConcatFile;
>>
>> @@ -329,6 +331,7 @@ static int concat_read_close(AVFormatContext *avf)
>>          avformat_close_input(&cat->avf);
>>      for (i = 0; i < cat->nb_files; i++) {
>>          av_freep(&cat->files[i].url);
>> +        av_freep(&cat->files[i].metadata);
>>          av_freep(&cat->files[i].streams);
>>      }
>>      av_freep(&cat->files);
>> @@ -381,6 +384,27 @@ static int concat_read_header(AVFormatContext *avf)
>>                  file->inpoint = dur;
>>              else if (!strcmp(keyword, "out"))
>>                  file->outpoint = dur;
>> +        } else if (!strcmp(keyword, "metadata")) {
>> +            AVDictionary *opts = NULL;
>> +            char *metadata;
>> +            if (file->metadata) {
>> +                av_log(avf, AV_LOG_ERROR, "Line %d: metadata is already provided\n", line);
>> +                FAIL(AVERROR_INVALIDDATA);
>> +            }
>> +            metadata = av_get_token((const char **)&cursor, SPACE_CHARS);
>> +            if (!metadata) {
>> +                av_log(avf, AV_LOG_ERROR, "Line %d: metadata required\n", line);
>> +                FAIL(AVERROR_INVALIDDATA);
>> +            }
>> +            if ((ret = av_dict_parse_string(&opts, metadata, "=", ",", 0)) < 0) {
>> +                av_log(avf, AV_LOG_ERROR, "Line %d: failed to parse metadata string\n", line);
>> +                av_freep(&metadata);
>> +                av_dict_free(&opts);
>> +                FAIL(AVERROR_INVALIDDATA);
>> +            }
>> +            file->metadata = av_packet_pack_dictionary(opts, &file->metadata_len);
>> +            av_freep(&metadata);
>> +            av_dict_free(&opts);
>>          } else if (!strcmp(keyword, "stream")) {
>>              if (!avformat_new_stream(avf, NULL))
>>                  FAIL(AVERROR(ENOMEM));
>> @@ -576,6 +600,12 @@ static int concat_read_packet(AVFormatContext *avf, AVPacket *pkt)
>>      av_log(avf, AV_LOG_DEBUG, " -> pts:%s pts_time:%s dts:%s dts_time:%s\n",
>>             av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &st->time_base),
>>             av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &st->time_base));
>> +    if (cat->cur_file->metadata) {
>> +        uint8_t* metadata;
>> +        if (!(metadata = av_packet_new_side_data(pkt, AV_PKT_DATA_STRINGS_METADATA, cat->cur_file->metadata_len)))
>> +            return AVERROR(ENOMEM);
>> +        memcpy(metadata, cat->cur_file->metadata, cat->cur_file->metadata_len);
>> +    }
>>      return ret;
>>  }
>>
>
> No other objection, but can you explain the use case? Packet metadata is not
> very common.

Actually I have one more patch I have not yet sent to the list, which adds 
support to select frames by metadata to the select filters.

With that, you can cut frame accurately from XDCAM HD files if you 
overshoot outpoint a bit and store the useful timecodes in the packet 
metadata:

ffconcat version 1.0
file 'XDCAMHD.mxf'
in 01:04.00
out  01:05.12
metadata select.from=0
metadata select.until=0.96
duration 1
file 'XDCAMHD.mxf'
in 01:06.00
out  01:07.12
duration 1
metadata select.from=1
metadata select.until=1.96

./ffmpeg -copyts -vsync 0 -i test.concat
-vf "select='between(t,meta(0),meta(1)):meta_keys=select.from|select.until'" 
-af "aselect='between(t,meta(0),meta(1)):meta_keys=select.from|select.until'"

Regards,
Marton


More information about the ffmpeg-devel mailing list