[FFmpeg-devel] Towards YUVJ removal

Niklas Haas ffmpeg at haasn.xyz
Tue Dec 13 13:23:47 EET 2022


On Fri, 09 Dec 2022 17:50:11 +0100 Michael Niedermayer <michael at niedermayer.cc> wrote:
> On Fri, Dec 09, 2022 at 12:49:41PM +0100, Niklas Haas wrote:
> > So, as was discussed at the last meeting, we should move towards
> > removing YUVJ. I want to gather feedback on what appears to be to the
> > major hurdle, and possible ways to solve it.
> > 
> > The basic major issue is how to handle the case of combining limited
> > range input with an encoder for a format that only accepts full range
> > data. The common case, for example, would be converting a frame from a
> > typical video file to a JPEG:
> > 
> > $ ffmpeg -f lavfi -i smptebars -vframes 1 output.jpg
> > 
> > Currently, this works because the JPEG encoder only advertises YUVJ
> > pixel formats, and therefore ffmpeg auto-inserts swscaler to convert
> > from limited range to full range. But this depends on conflating color
> > range and pixel formats, which is exactly what has been marked
> > deprecated for an eternity.
> > 
> > Now, there are some solutions I can see for how to handle this case in
> > a non-YUVJ world:
> > 
> > 1. Simply output an error, and rely on the user to insert a conversion
> >    filter, e.g.:
> > 
> >    $ ffmpeg -f lavfi -i smptebars -vframes 1 output.jpg
> >    error: inputs to jpeg encoder must be full range
> > 
> >    $ ffmpeg -f lavfi -i smptebars -vframes 1 -vf scale=out_range=jpeg output.jpg
> >    ... works
> > 
> > 2. Have the JPEG encoder take care of range conversion internally, by
> >    using sws to convert limited to full range.
> > 
> > 3. Allow filters to start exposing color space metadata as part of
> >    filter negotiation, and then auto-insert swscaler whenever colorspace
> >    conversion needs to happen as a result of filters not accepting the
> >    corresponding color metadata. This would also allow more than just
> >    conversion between limited/full range.
> > 
> > 4. Combine approach 1 with an encoder flag for "supports full range
> >    only", and have ffmpeg.c auto-insert a scale filter as the last step
> >    before the encoder if this flag is set (and input is limited range).
> > 
> > 1 would be the most explicit but would break any existing pipeline that
> > includes conversion to jpeg, which is probably a very large number.
> > 
> > 2 would be the least work, but violates abstraction boundaries.
> > 
> > 3 would be the most work and is, IMO, of questionable gain.
> > 
> > 4 would be both explicit and not break existing workflows.
> 
> 3 is nice but is hard as it draws filter negotiation in and that has
> to do something even for non trivial filter networks.
> 
> 4 with the complexity in jpeg as disscussed elsewhere in this thread
> also may or may not be as clean as it sounds here
> 
> but both 3 and 4 with some amendment sound reasonable to me
> another option would be to either improve 
> 
> A. general "supported value" information
> a encoder should be able to tell the caller what it supports depending
> on some parameter, for example depending on profile and level
> or std compliance. This would mean implementing AVClass.query_ranges()
> and using av_opt_query_ranges() IIRC
> 
> 
> B. error reporting so that 
> failures become machiene readable. 
> aka, "this failed because color range is not X || std complicance is > Y"
> the lib user could then retry by applying the change if that is within what
> the usecase wants
> 
> Both A and B obvioulsy have a much broader use than YUVJ removal
> 
> thx

So, the biggest roadblock I see with regards to making color range etc.
part of filter negotiation is that, currently, color range (and
colorspace and so on) are part of AVFrame, which can (in theory and
possibly also in practice) change suddenly mid-stream.

So we can't somehow *statically* negotiate the appropriate conversion
filter into the filter graph depending on a value that is only known
after filter negotiation is complete. Fortunately, there is not
currently any filter in ffmpeg that only supports one color range, so we
don't actually *need* filter negotiation for YUVJ removal.

It's straight-forward to add a list of supported color ranges (even
depending on compliance level) into `AVCodec`, but of course, this still
relies on API users knowing to check this new field in order to avoid
potential regressions.

How about having a special conversion layer exist only in front of
encoders (e.g. inside avcodec_send_frame) to deal with incoming frames
that have mismatched metadata relative to what the encoder supports?
With an option to turn it on/off in AVCodecContext.

This would NOT take care of pix_fmt conversion (since the filter chain
already handles that), but merely deal with mismatches between sent
AVFrames and AVCodec advertised capabilities.


More information about the ffmpeg-devel mailing list