swscaler警告:使用了已弃用的像素格式

19

在将视频帧转换为OpenGL纹理之前,我想对其进行颜色空间转换,使用以下代码:

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

每次调用sws_getCachedContext()函数时,我都会收到以下警告:
[swscaler @ 0x10506fa00] deprecated pixel format used, make sure you did set range correctly

以下是我的FFmpeg版本信息输出:

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

有什么办法可以禁用这个警告?如何正确设置颜色范围?


你的ffmpeg版本有多新?https://trac.ffmpeg.org/ticket/3242 http://trac.ffmpeg.org/ticket/3094 - njahnke
你在sww_getContext上得到了相同的结果吗? - nmxprime
@nmxprime 我用sws_getContext也是得到同样的结果。 - Martin Delille
2个回答

13

虽然问题提出已久,但由于我遇到了同样的问题,所以我仔细研究并尝试找到第二部分的答案(如何正确设置颜色范围)。这里是对Thomas Ayoub答案的扩展:

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);
}

关于范围是什么意思呢?YUV像素格式的值在范围内:Y 16..235, UV 16..240。YUVJ是扩展的一种,所有的YUV都是0 ... 255。所以设置

srcRange = 1

强制libav使用扩展的输入数据范围。如果您没有改变范围,则可能只会体验到夸张的对比度。它仍应将输入数据缩放到RGB颜色空间。


2
我非常喜欢你的回答,因为它解释了格式之间的差异以及如何完全地浏览它们。 - Mad Physicist
一个小调整:if (pixFormat != pCodecCtx->pix_fmt) srcRange = 1; 只有在流像素格式为YUVJ时,它才会将src范围视为0..255,对吗? - Raptor007
Raptor007:你说得对。更新了答案,以便仅在像素格式更改的情况下更改范围。 - psalong
这是一个有帮助的回答,但它没有解释为什么将表格和逆表格设置为sws_getCoefficients(SWS_CS_DEFAULT),而不是dummy。为什么我们不使用现有的表格和逆表格?当srcRange改变时,它们是否会失效? - undefined

13

看起来您正在尝试读取已弃用的 AV_PIX_FMT_YUVJXXXP 帧(请参阅 libav 文档)。您可以使用以下解决方法进行管理:

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;
}

我的视频流AVPixelFormat是AV_PIX_FMT_YUVJ420P。使用上述解决方法,它会被转换为AV_PIX_FMT_YUV420P。 "[swscaler @ 0dd9e620] 使用了过时的像素格式,请确保您正确设置了范围"。我该如何解决这个问题? - Tariq
是的。我获得了RTSP视频流,使用FFMpeg进行解码,然后将其转换为cv :: MAT。 - Tariq
@Tariq,你应该发布另一个带有更多代码的问题,我无法仅凭这个来帮助你。 - Thomas Ayoub
感谢您的建议,Thomas;我已经在http://stackoverflow.com/questions/30937688/swscaler0dd9e620-deprecated-pixel-format-used-make-sure-you-did-set-range-cor上发布了这个问题,并提供了示例代码。 - Tariq
@ThomasAyoub,使用这个W/A的影响是什么?确实可以消除警告,但是对于RGB的转换本身呢? - Shmil The Cat

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接