PyAV icon indicating copy to clipboard operation
PyAV copied to clipboard

Add method to update CodecContext options at runtime

Open sirf opened this issue 3 years ago • 9 comments

Expose methods to manipulate options in CodecContext at runtime. To change the h.264 constant rate factor for example

sirf avatar Sep 22 '22 09:09 sirf

Why can't you use CodecContext.options ?

jlaine avatar Oct 17 '22 12:10 jlaine

I want to manipulate options while CodecContext is open, i.e. after avcodec_open2 has been called, to facilitate features like automatic adjustment of crf and other properties depending on dynamic conditions such as available bandwidth and CPU/GPU resources. Is that possible with CodecContext.options or through some other existing method? If so then awesome! Any help would greatly appreciated.

sirf avatar Oct 17 '22 14:10 sirf

Ah, updating options after the codec has been opened is another matter, we definitely don't support it right now as our options are only passed when we call avcodec_open2().

Do you know if there is a "high level" API to update options? My concern is that I'd rather not add all possible "opt_set_XXX" calls if there is a higher level API.

jlaine avatar Oct 17 '22 14:10 jlaine

Good point about all possible av_opt_set/get_xxx.

CodecContext.options must have string keys and string values because it's converted to an AVDictionary under the hood, so how about we simply implement opt_set, i.e. this one https://ffmpeg.org/doxygen/trunk/group__opt__set__funcs.html#ga5fd4b92bdf4f392a2847f711676a7537

That would be consistent with how the options dictionary currently works, in the sense that you need to convert all values to strings.

sirf avatar Oct 17 '22 14:10 sirf

I think av_opt_set_dict() might be what we are looking for.

We could for instance have an update_options() method which would allow us to update multiple options at once, regardless of their type. I'm not too sure of the exact API, as we already have a "self.options", and it's not clear to me what we should do with it.

jlaine avatar Oct 17 '22 15:10 jlaine

It would be neat if CodecContext.options was a custom dict-like object that calls av_opt_set when __setitem__ is called, and calls av_opt_set_dict when update() is called :)

Would of course also work on all the other AV* structs that has options.

sirf avatar Oct 17 '22 15:10 sirf

It would be neat if CodecContext.options was a custom dict-like object that calls av_opt_set when __setitem__ is called, and calls av_opt_set_dict when update() is called :)

Would of course also work on all the other AV* structs that has options.

Sure that would be great, I'm just not too sure:

  • whether av_opt_set_dict "patches" existing options or fully replaces them
  • how we can have this "magic" options dict in Cython

Still, I think it would be worth you experimenting with some form of API (e.g. an update_options() method) to check whether you are actually able to change crf as you desire.

jlaine avatar Oct 17 '22 21:10 jlaine

How about this then:

A method named update_options that has the exact same semantics as dict.update / collections.abc.MutableMapping.update, e.g. you can update one or many options from an existing dict, update one or many options through keyword arguments, from a list of tuples, etc.

codec.update_options(crf="20")

opts = { "crf": "20", "some_other_option": "123" }
codec.update_options(opts)

I did an implementation and updated the code in this PR. It works, and it avoids the creation of an intermediary AVDictionary that av_opt_set_dict would have needed.

sirf avatar Oct 18 '22 09:10 sirf

This needs a unit test, even if it's a basic one. Everything else looks fine.

WyattBlue avatar Feb 02 '24 07:02 WyattBlue

This PR is too old

WyattBlue avatar Mar 05 '24 18:03 WyattBlue