Message ID | E1gUKEE-001Z0L-2T@pannekake.samfundet.no |
---|---|
State | New |
Headers | show |
On Wed, Dec 05, 2018 at 12:31:10AM +0100, Steinar H. Gunderson wrote: > Some demuxers, like Matroska, allow for sending colorspace information > that override MJPEG defaults when it comes to Y'CbCr coefficients or > chroma location. Don't override such data if the demuxer already has > set it; this allows decoding such MJPEG streams correctly. > > Also document in avcodec.h that these fields are actually set first by > libavformat, even if libavcodec is usually the one to set them. This is > not new behavior; e.g., dnxhd already works this way. Attaching the FATE test file used (created by myself; it's just a black MJPEG frame, although with the special CS=ITU601 tag set to get TV range). /* Steinar */
On Wed, Dec 5, 2018 at 12:35 AM Steinar H. Gunderson <steinar+ffmpeg@gunderson.no> wrote: > > Some demuxers, like Matroska, allow for sending colorspace information > that override MJPEG defaults when it comes to Y'CbCr coefficients or > chroma location. Don't override such data if the demuxer already has > set it; this allows decoding such MJPEG streams correctly. > > Also document in avcodec.h that these fields are actually set first by > libavformat, even if libavcodec is usually the one to set them. This is > not new behavior; e.g., dnxhd already works this way. > --- > libavcodec/avcodec.h | 10 +++++----- > libavcodec/mjpegdec.c | 8 ++++++-- > tests/fate/matroska.mak | 3 +++ > tests/ref/fate/matroska-mjpeg-color-space | 22 ++++++++++++++++++++++ > 4 files changed, 36 insertions(+), 7 deletions(-) > create mode 100644 tests/ref/fate/matroska-mjpeg-color-space > > diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h > index 3922e89331..b7ea99d8ab 100644 > --- a/libavcodec/avcodec.h > +++ b/libavcodec/avcodec.h > @@ -2145,35 +2145,35 @@ typedef struct AVCodecContext { > /** > * Chromaticity coordinates of the source primaries. > * - encoding: Set by user > - * - decoding: Set by libavcodec > + * - decoding: Set by libavformat and/or libavcodec > */ > enum AVColorPrimaries color_primaries; > > /** > * Color Transfer Characteristic. > * - encoding: Set by user > - * - decoding: Set by libavcodec > + * - decoding: Set by libavformat and/or libavcodec > */ > enum AVColorTransferCharacteristic color_trc; > > /** > * YUV colorspace type. > * - encoding: Set by user > - * - decoding: Set by libavcodec > + * - decoding: Set by libavformat and/or libavcodec > */ > enum AVColorSpace colorspace; > > /** > * MPEG vs JPEG YUV range. > * - encoding: Set by user > - * - decoding: Set by libavcodec > + * - decoding: Set by libavformat and/or libavcodec > */ > enum AVColorRange color_range; > > /** > * This defines the location of chroma samples. > * - encoding: Set by user > - * - decoding: Set by libavcodec > + * - decoding: Set by libavformat and/or libavcodec > */ > enum AVChromaLocation chroma_sample_location; > These comments are not accurate. avformat does not fill these values, because outside of deprecated code it does not expose such a struct to the user. - Hendrik
On Wed, Dec 05, 2018 at 12:57:43AM +0100, Hendrik Leppkes wrote: > These comments are not accurate. avformat does not fill these values, > because outside of deprecated code it does not expose such a struct to > the user. Hm, I was asked on #ffmpeg-devel to update it :-) But I suppose maybe it sets them in AVCodecParameters instead? /* Steinar */
On Wed, Dec 5, 2018 at 1:14 AM Steinar H. Gunderson <steinar+ffmpeg@gunderson.no> wrote: > > On Wed, Dec 05, 2018 at 12:57:43AM +0100, Hendrik Leppkes wrote: > > These comments are not accurate. avformat does not fill these values, > > because outside of deprecated code it does not expose such a struct to > > the user. > > Hm, I was asked on #ffmpeg-devel to update it :-) But I suppose maybe it sets > them in AVCodecParameters instead? > It would. And that struct is only ever filled by avformat (or a user), and not avcodec, so there is no overlap there either. The real problem is that its impossible to know which component to really trust. Why does a demuxer have more authority on the color format then a decoder? Or vice-versa? We don't have a solution for that, and its really something the user application currently has to solve. - Hendrik
On Wed, Dec 05, 2018 at 01:33:12AM +0100, Hendrik Leppkes wrote: > The real problem is that its impossible to know which component to > really trust. Why does a demuxer have more authority on the color > format then a decoder? Or vice-versa? You can make this arbitrarily complicated, of course, but if the codec has no info apart from defaults (as in this case), I'd say the decision is fairly simple. The one with the more specific information wins, which is the demuxer. There's a corner case where you can't specify _explicitly_ in the mux “I don't know, but it's probably not the defaults” (since there's no distinction between “unspecified because the format doesn't say so” and “unspecified because the user explicitly told us to”), but I can't see what an application would do in that case except use the codec defaults anyway. > We don't have a solution for that, and its really something the user > application currently has to solve. The user application doesn't feel like the right place for this. How would it be in a better position than FFmpeg to know? And if it really is in the position to set a policy here, it can read out the information of the codec parameter struct and override it, no matter what libavcodec decided to do. /* Steinar */
On Wed, Dec 05, 2018 at 09:31:48AM +0100, Steinar H. Gunderson wrote: >> We don't have a solution for that, and its really something the user >> application currently has to solve. > The user application doesn't feel like the right place for this. How would it > be in a better position than FFmpeg to know? And if it really is in the > position to set a policy here, it can read out the information of the codec > parameter struct and override it, no matter what libavcodec decided to do. What's the status of this patch? Is it rejected on the basis of “this is the wrong thing to do” and nedes a larger rework of the rest of FFmpeg, or could it be merged with some changes? /* Steinar */
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 3922e89331..b7ea99d8ab 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -2145,35 +2145,35 @@ typedef struct AVCodecContext { /** * Chromaticity coordinates of the source primaries. * - encoding: Set by user - * - decoding: Set by libavcodec + * - decoding: Set by libavformat and/or libavcodec */ enum AVColorPrimaries color_primaries; /** * Color Transfer Characteristic. * - encoding: Set by user - * - decoding: Set by libavcodec + * - decoding: Set by libavformat and/or libavcodec */ enum AVColorTransferCharacteristic color_trc; /** * YUV colorspace type. * - encoding: Set by user - * - decoding: Set by libavcodec + * - decoding: Set by libavformat and/or libavcodec */ enum AVColorSpace colorspace; /** * MPEG vs JPEG YUV range. * - encoding: Set by user - * - decoding: Set by libavcodec + * - decoding: Set by libavformat and/or libavcodec */ enum AVColorRange color_range; /** * This defines the location of chroma samples. * - encoding: Set by user - * - decoding: Set by libavcodec + * - decoding: Set by libavformat and/or libavcodec */ enum AVChromaLocation chroma_sample_location; diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c index 2f1635838a..9ee2daadf8 100644 --- a/libavcodec/mjpegdec.c +++ b/libavcodec/mjpegdec.c @@ -158,8 +158,12 @@ av_cold int ff_mjpeg_decode_init(AVCodecContext *avctx) s->first_picture = 1; s->got_picture = 0; s->org_height = avctx->coded_height; - avctx->chroma_sample_location = AVCHROMA_LOC_CENTER; - avctx->colorspace = AVCOL_SPC_BT470BG; + if (avctx->chroma_sample_location == AVCHROMA_LOC_UNSPECIFIED) { + avctx->chroma_sample_location = AVCHROMA_LOC_CENTER; + } + if (avctx->colorspace == AVCOL_SPC_UNSPECIFIED) { + avctx->colorspace = AVCOL_SPC_BT470BG; + } s->hwaccel_pix_fmt = s->hwaccel_sw_pix_fmt = AV_PIX_FMT_NONE; if ((ret = init_default_huffman_tables(s)) < 0) diff --git a/tests/fate/matroska.mak b/tests/fate/matroska.mak index 2747496e1e..1768ce6ee2 100644 --- a/tests/fate/matroska.mak +++ b/tests/fate/matroska.mak @@ -9,5 +9,8 @@ fate-matroska-remux: REF = 1ed49a4f2b6790357fac268938357353 FATE_MATROSKA_FFPROBE-$(call ALLYES, MATROSKA_DEMUXER) += fate-matroska-spherical-mono fate-matroska-spherical-mono: CMD = run ffprobe$(PROGSSUF)$(EXESUF) -show_entries stream_side_data_list -select_streams v -v 0 $(TARGET_SAMPLES)/mkv/spherical.mkv +FATE_MATROSKA_FFPROBE-$(call ALLYES, MATROSKA_DEMUXER) += fate-matroska-mjpeg-color-space +fate-matroska-mjpeg-color-space: CMD = run ffprobe$(PROGSSUF)$(EXESUF) -show_entries frame=color_range,color_space,color_primaries,color_transfer,chroma_location $(TARGET_SAMPLES)/mkv/mjpeg-color-space.mkv + FATE_SAMPLES_AVCONV += $(FATE_MATROSKA-yes) FATE_SAMPLES_FFPROBE += $(FATE_MATROSKA_FFPROBE-yes) diff --git a/tests/ref/fate/matroska-mjpeg-color-space b/tests/ref/fate/matroska-mjpeg-color-space new file mode 100644 index 0000000000..d3cd39f967 --- /dev/null +++ b/tests/ref/fate/matroska-mjpeg-color-space @@ -0,0 +1,22 @@ +[FRAME] +color_range=tv +color_space=bt709 +color_primaries=bt709 +color_transfer=iec61966-2-1 +chroma_location=left +[SIDE_DATA] +[/SIDE_DATA] +[SIDE_DATA] +[/SIDE_DATA] +[/FRAME] +[FRAME] +color_range=tv +color_space=bt709 +color_primaries=bt709 +color_transfer=iec61966-2-1 +chroma_location=left +[SIDE_DATA] +[/SIDE_DATA] +[SIDE_DATA] +[/SIDE_DATA] +[/FRAME]