[Libav-user] movflags/faststart flag for avcodec_open2

Michael Armes michael.armes at gmail.com
Tue May 8 19:48:09 EEST 2018


>
>
> Hello,
>>>>>
>>>>> I am trying to ensure that I have the moov metadata for H.264 encoded
>>>>> video at the beginning of the file. I have seen examples online that
>>>>> indicate I need to give ffmpeg the "-movflags +faststart"  option, but I am
>>>>> coding against libav*. How do these options translate to the options given
>>>>> to the AVDictionary parameter of avcodec_open2? Or rather, am I barking up
>>>>> the wrong tree entirely?
>>>>>
>>>>> I assumed that it was trivially a dictionary entry with key "movflags"
>>>>> and value "faststart" after I inspected movenc.c in libavformat, but this
>>>>> is not currently working for me and I need to determine what I have wrong
>>>>> (the "how" or the "what"). I appreciate any help.
>>>>>
>>>>> --michael
>>>>>
>>>>> _______________________________________________
>>>>> Libav-user mailing list
>>>>> Libav-user at ffmpeg.org
>>>>> http://ffmpeg.org/mailman/listinfo/libav-user
>>>>>
>>>>>
>>>> You can search in dict.h and use: int av_dict_set(AVDictionary **pm,
>>>> const char *key, const char *value, int flags).
>>>>
>>>> Example:
>>>>
>>>> AVDictionary* myOptions;
>>>> av_dict_set( &myOptions, "movflags", "+faststart", 0 );
>>>>
>>>> av_dict_set will allocate the dictionary for you.
>>>>
>>>> To understand how this all works:  there is a bunch of code in ffmpeg
>>>> that deals with AVOptions (and these dictionaries) and converts human
>>>> readable data into the right flags.  In the ffmpeg source code, in
>>>> libavformat/movenc.c you can find:
>>>>
>>>> static const AVOption options[] = {
>>>>     { "movflags", "MOV muxer flags", offsetof(MOVMuxContext, flags),
>>>> AV_OPT_TYPE_FLAGS, {.i64 = 0}, INT_MIN, INT_MAX,
>>>> AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
>>>> ...
>>>>     { "faststart", "Run a second pass to put the index (moov atom) at
>>>> the beginning of the file", 0, AV_OPT_TYPE_CONST, {.i64 =
>>>> FF_MOV_FLAG_FASTSTART}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM,
>>>> "movflags" },
>>>>
>>>> The first one defines the human-readable "movflags" to access the
>>>> "flags" member variable, and the one further down that ends with "movflags"
>>>> is a way of saying the "faststart" string refers to a flag that applies to
>>>> the variable movflags.  In opt.c you'll find special code for
>>>> AV_OPT_TYPE_FLAGS that deals with prefixing with "+" or "-" which will add
>>>> or remove flags from the variable specified.  Once you know all of this,
>>>> the code (and settings) become quite readable which is nice.
>>>>
>>>> Everything that is an AVClass can be accessed using these types of
>>>> options through the AVOptions interfaces (libavutil/opt.h), or passing in
>>>> an AVDictionary with the options when creating it, as you've found.  I've
>>>> found it helpful when starting out to use the AVOptions interface rather
>>>> than AVDictionary.  The reason being, there's more immediately feedback
>>>> through the return code of av_opt_set, and you can grab the configuration
>>>> of an object through av_opt_serialize.  This will help you catch errors
>>>> like setting movflags on the stream rather than the muxer.
>>>>
>>>> Cheers.
>>>>
>>>> _______________________________________________
>>>> Libav-user mailing list
>>>> Libav-user at ffmpeg.org
>>>> http://ffmpeg.org/mailman/listinfo/libav-user
>>>>
>>>>
>>>
>> On Thu, May 3, 2018 at 3:31 PM, Michael Armes <michael.armes at gmail.com>
>> wrote:
>>
>>> Jordan,
>>>
>>> Thanks for the reply. It's great to know that I'm on track with the
>>> option name/value and my use of av_dict_set. Also good to know that the -/+
>>> logic applies here.
>>>
>>> Can you confirm that:
>>> AVDictionary* myOptions;
>>> av_dict_set( &myOptions, "movflags", "+faststart", 0 );
>>> avcodec_open2(context, codec, &myOptions);
>>>
>>> should set the option on the muxer?
>>>
>>> Interestingly, if I use av_opt_serialize on the AvCodecContext after
>>> opening
>>> av_opt_serialize(context, 0, 0, &buffer, ':', ';');
>>>
>>> after opening the codec, I don't see the flag set.
>>>
>>> b:1216000;ab:1216000;bt:4000000;flags:0x80400000;me_method:-
>>> 1;time_base:1/20;g:12;ar:0;ac:0;cutoff:0;frame_size:0;frame_
>>> number:0;delay:0;qcomp:-1.00000
>>>
>>> I'm looking for the 7th bit (128) to be set on flags, yes?
>>>
>>>
>>> On Wed, May 2, 2018 at 5:45 PM, Jodon Karlik <jodonk at gmail.com> wrote:
>>>
>>>>
>>>> My apologizes. Here is the full list of options from the serialize. I
>> do appreciate any help. Heads up that I will be away starting tomorrow
>> until Monday. If I don't respond timely, it doesn't mean I don't care. :-)
>>
>>
>> b:1216000;ab:1216000;bt:4000000;flags:0x80400000;me_method:-
>> 1;time_base:1/20;g:12;ar:0;ac:0;cutoff:0;frame_size:0;frame_
>> number:0;delay:0;qcomp:-1.000000;qblur:-1.000000;qmin:-1;qma
>> x:-1;qdiff:-1;bf:0;b_qfactor:-1.000000;rc_strategy:0;b_strat
>> egy:-1;ps:0;mv_bits:0;header_bits:0;i_tex_bits:0;p_tex_
>> bits:0;i_count:0;p_count:0;skip_count:0;misc_bits:0;frame
>> _bits:0;codec_tag:0;bug:0x00000001;strict:0;b_qoffset:1.
>> 250000;err_detect:0x00000000;has_b_frames:2;block_align:0;m
>> peg_quant:0;qsquish:0.000000;rc_qmod_amp:0.000000;rc_qmod_fr
>> eq:0;rc_override_count:0;rc_eq:;maxrate:0;minrate:0;bufsize:
>> 0;rc_buf_aggressivity:1.000000;i_qfactor:-1.000000;i_
>> qoffset:0.000000;rc_init_cplx:0.000000;dct:0;lumi_mask:0.
>> 000000;tcplx_mask:0.000000;scplx_mask:0.000000;p_mask:0.0000
>> 00;dark_mask:0.000000;idct:0;slice_count:0;ec:0x00000003;
>> bits_per_coded_sample:0;pred:0;aspect:0/1;sar:0/1;debug:
>> 0x00000000;vismv:0x00000000;cmp:-1;subcmp:0;mbcmp:0;
>> ildctcmp:8;dia_size:0;last_pred:0;preme:0;precmp:0;pre_
>> dia_size:0;subq:-1;dtg_active_format:0;me_range:-1;ibias:
>> 999999;pbias:999999;global_quality:0;coder:-1;context:0;
>> slice_flags:0;xvmc_acceleration:0;mbd:0;stream_
>> codec_tag:0;sc_threshold:-1;lmin:0;lmax:0;nr:-1;rc_init_
>> occupancy:-1;flags2:0x00000000;error:0;threads:0;
>> me_threshold:0;mb_threshold:0;dc:0;nssew:8;skip_top:0;skip_
>> bottom:0;profile:-99;level:-99;lowres:0;skip_threshold:0;
>> skip_factor:0;skip_exp:0;skipcmp:13;border_mask:0.
>> 000000;mblmin:236;mblmax:3658;mepc:256;skip_loop_filter:0;
>> skip_idct:0;skip_frame:0;bidir_refine:1;brd_scale:0;
>> keyint_min:-1;refs:-1;chromaoffset:0;trellis:-1;sc_
>> factor:6;mv0_threshold:256;b_sensitivity:40;compression_
>> level:-1;min_prediction_order:0;max_prediction_order:0;
>> timecode_frame_start:-1;bits_per_raw_sample:0;channel_
>> layout:0;request_channel_layout:0;rc_max_vbv_use:0.
>> 000000;rc_min_vbv_use:3.000000;ticks_per_frame:2;
>> color_primaries:2;color_trc:2;colorspace:2;color_range:0;
>> chroma_sample_location:0;log_level_offset:0;slices:0;
>> thread_type:0x00000000;audio_service_type:0;request_sample_
>> fmt:u8;pkt_timebase:0/1;sub_charenc:;sub_charenc_mode:
>> 0x00000000;sub_text_format:0;refcounted_frames:false;side_
>> data_only_packets:true;skip_alpha:false;field_order:0;
>> dump_separator:;codec_whitelist:;pixel_format:yuv420p;video_size:1204x338
>>
>>
> Heads-up the rule here is to not "top post" (i.e. put replies below the
> original message) and the mods are quite strict on it.  I was hoping
> someone with more experience would chime in, but I'll give this a shot:
>
> I think you're applying the dictionary to the wrong object.  If you look
> at the previous code you're targeting ("faststart" in movenc.c) you'll
> notice it has a bunch of variables that are nowhere to be found (e.g.
> min_frag_duration).  This indicates to me that you're inspecting an object
> that doesn't have the ability for faststart which you're requesting.  It
> could be that you're writing an AVI as opposed to an MP4 or a MOV, or
> what's being applied is to the AVCodecContext as opposed to the
> AVFormatContext (I didn't read into the avcodec_open2, but that would make
> sense).  For my stuff, I wrote my own C++ wrapper which applies these
> things in descending order:  Muxer (AVFormatContext), the Stream
> (AVCodecContext->stream pointers of AVStream), and the Codec itself
> (AVCodecContext which I think is what you're doing here).  Again, I use
> av_opt which would catch these things.
>
> Cheers.
>

Thank you for the help. I think I finally have a handle on what is going
on. Firstly, I need to pass the dictionary to avformat_write_header. There
are some children on the AVFormatContext that need the option set and this
will handle that through avformat_init_output. However, this is only part
of the way there. Now I am getting invalid mp4s without the moov atom
entirely.

 Secondly, I have a custom IO callbacks that I hooked up
through avio_alloc_context. This is necessary because I am in the cloud and
do not have a filesystem. The faststart second pass attempts to reopen the
file for reading to avoid some read/seek loops. This open is failing. My
guess is that I also need to supply custom io_open and io_close callbacks
to my AVFormatContext.

I will take it from here.

Cheers,
Michael
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://ffmpeg.org/pipermail/libav-user/attachments/20180508/c495d8f4/attachment.html>


More information about the Libav-user mailing list