19

I want to perform a color space conversion of my video frame before converting it to an opengl texture with the following code:

struct SwsContext * pSwsCtx = sws_getCachedContext(NULL,width, height, codec->pix_fmt, width, height, AV_PIX_FMT_RGBA, SWS_POINT, NULL, NULL, NULL);

Each time the sws_getCachedContext() function is called I got the following warning:

[swscaler @ 0x10506fa00] deprecated pixel format used, make sure you did set range correctly

Here is my ffmpeg output for version information:

ffmpeg version 2.2 Copyright (c) 2000-2014 the FFmpeg developers
  built on Mar 26 2014 15:29:01 with Apple LLVM version 5.1 (clang-503.0.38) (based on LLVM 3.4svn)
  configuration: --prefix=/usr/local/Cellar/ffmpeg/2.2 --enable-shared --enable-pthreads --enable-gpl --enable-version3 --enable-nonfree --enable-hardcoded-tables --enable-avresample --enable-vda --cc=clang --host-cflags= --host-ldflags= --enable-libx264 --enable-libfaac --enable-libmp3lame --enable-libxvid
  libavutil      52. 66.100 / 52. 66.100
  libavcodec     55. 52.102 / 55. 52.102
  libavformat    55. 33.100 / 55. 33.100
  libavdevice    55. 10.100 / 55. 10.100
  libavfilter     4.  2.100 /  4.  2.100
  libavresample   1.  2.  0 /  1.  2.  0
  libswscale      2.  5.102 /  2.  5.102
  libswresample   0. 18.100 /  0. 18.100
  libpostproc    52.  3.100 / 52.  3.100
Hyper fast Audio and Video encoder

Any idea to disable this warning? How to set the color range correctly?

Martin Delille
  • 11,360
  • 15
  • 65
  • 132

2 Answers2

14

It seems you're trying to read AV_PIX_FMT_YUVJXXXP frames which are deprecated (see the libav doc). You can use this workaround to manage it :

AVPixelFormat pixFormat;
switch (_videoStream->codec->pix_fmt) {
case AV_PIX_FMT_YUVJ420P :
    pixFormat = AV_PIX_FMT_YUV420P;
    break;
case AV_PIX_FMT_YUVJ422P  :
    pixFormat = AV_PIX_FMT_YUV422P;
    break;
case AV_PIX_FMT_YUVJ444P   :
    pixFormat = AV_PIX_FMT_YUV444P;
    break;
case AV_PIX_FMT_YUVJ440P :
    pixFormat = AV_PIX_FMT_YUV440P;
    break;
default:
    pixFormat = _videoStream->codec->codec->pix_fmts;
    break;
}
Phi
  • 467
  • 5
  • 16
Thomas Ayoub
  • 29,063
  • 15
  • 95
  • 142
  • My video stream AVPixelFormat is AV_PIX_FMT_YUVJ420P. Using the above workaround, It gets converted to AV_PIX_FMT_YUV420P. "[swscaler @ 0dd9e620] deprecated pixel format used, make sure you did set range correctly". How can I resolve it? – Tariq Jun 19 '15 at 10:17
  • yes. I get RTSP video stream, decode it using FFMpeg and then convert it to cv::MAT. – Tariq Jun 19 '15 at 10:47
  • @Tariq you should post another question with more code, I can't help you with just this – Thomas Ayoub Jun 19 '15 at 10:58
  • Thanks for your suggestion Thomas; I posted this problem as another question with sample code at http://stackoverflow.com/questions/30937688/swscaler0dd9e620-deprecated-pixel-format-used-make-sure-you-did-set-range-cor – Tariq Jun 19 '15 at 12:09
  • @ThomasAyoub what are the implications of using this W/A - indeed it will eliminate the warning, but about the conversion per-se to RGB ? – Shmil The Cat Feb 13 '18 at 18:42
12

It is long time since the question was asked, but as I hit the same problem then I looked at it and tried to find also the answer to the second part (How to set the color range correctly?). I am extending the Thomas Ayoub's answer:

AVCodecContext* pCodecCtx = _videoStream->codec;
AVPixelFormat pixFormat;
bool changeColorspaceDetails = false;
switch (pCodecCtx->pix_fmt)
  {
    case AV_PIX_FMT_YUVJ420P:
      pixFormat = AV_PIX_FMT_YUV420P;
      changeColorspaceDetails = true;
      break;
    case AV_PIX_FMT_YUVJ422P:
      pixFormat = AV_PIX_FMT_YUV422P;
      changeColorspaceDetails = true;
      break;
    case AV_PIX_FMT_YUVJ444P:
      pixFormat = AV_PIX_FMT_YUV444P;
      changeColorspaceDetails = true;
      break;
    case AV_PIX_FMT_YUVJ440P:
      pixFormat = AV_PIX_FMT_YUV440P;
      changeColorspaceDetails = true;
      break;
    default:
      pixFormat = pCodecCtx->pix_fmt;
  }
// initialize SWS context for software scaling
SwsContext *swsCtx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pixFormat, pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_RGB24, SWS_BILINEAR, NULL, NULL, NULL);

if (changeColorspaceDetails)
{
    // change the range of input data by first reading the current color space and then setting it's range as yuvj.
    int dummy[4];
    int srcRange, dstRange;
    int brightness, contrast, saturation;
    sws_getColorspaceDetails(swsCtx, (int**)&dummy, &srcRange, (int**)&dummy, &dstRange, &brightness, &contrast, &saturation);
    const int* coefs = sws_getCoefficients(SWS_CS_DEFAULT);
    srcRange = 1; // this marks that values are according to yuvj
    sws_setColorspaceDetails(swsCtx, coefs, srcRange, coefs, dstRange,
                               brightness, contrast, saturation);
}

What is it about the ranges? The YUV pixel format has values in ranges: Y 16..235, UV 16..240. The YUVJ is extended one and all YUV are 0 ... 255. So setting

srcRange = 1

forces the libav to use extended input data range. If you do not make any changes in the range then probably you only experience exaggerated contrast. It should still scale the input data to RGB color space.

psalong
  • 389
  • 6
  • 12
  • 2
    I very much prefer your answer because it explains the differences in formats and how to fully navigate them. – Mad Physicist May 23 '19 at 20:51
  • One tweak: `if (pixFormat != pCodecCtx->pix_fmt) srcRange = 1;` would make it only treat the src range as 0..255 if the stream pixel format is YUVJ, right? – Raptor007 Jul 16 '21 at 01:41
  • Raptor007: you are right. Updated the answer so that the range is changed only in cases the pixel format was changed. – psalong Jul 19 '21 at 09:40