c - FFMpeg、libav、sws_scale 和 yuv 到 rgb 转换的问题 - 颜色不正确

标签 c delphi ffmpeg libav

我一直在尝试在 Delphi 中创建自己的视频播放器,并且 ffmpeg 效果很好,直到我遇到了色彩空间或颜色转换的障碍。
这几天一直在尝试一切,但无法弄清楚。
我正在使用 AV_PIX_FMT_RGB48LE 作为输出...
旧上下文创建:

      videoConvContext := sws_getContext(AVStreamInit.codec.width, AVStreamInit.codec.height, AVStreamInit.codec.pix_fmt, AVStreamInit.codec.width, AVStreamInit.codec.height, AV_PIX_FMT_RGB48LE, SWS_POINT, nil, nil, nil);
新的上下文创建:
    dstRange := 1;
    srcRange := 1;
    if AVStreamInit.codec.color_range = AVCOL_RANGE_MPEG then
      srcRange := 0;

    videoConvContext := sws_alloc_context();

    av_opt_set_int(videoConvContext, 'sws_flags', SWS_POINT or SWS_PRINT_INFO, 0);

    av_opt_set_int(videoConvContext, 'srcw', AVStreamInit.codec.width, 0);
    av_opt_set_int(videoConvContext, 'srch', AVStreamInit.codec.height, 0);
    av_opt_set_int(videoConvContext, 'src_format', Integer(AVStreamInit.codec.pix_fmt), 0);

    av_opt_set_int(videoConvContext, 'dstw', AVStreamInit.codec.width, 0);
    av_opt_set_int(videoConvContext, 'dsth', AVStreamInit.codec.height, 0);
    av_opt_set_int(videoConvContext, 'dst_format', Integer(AV_PIX_FMT_RGB48LE), 0);

    i1 := sws_getCoefficients2(Integer(AVStreamInit.codec.colorspace));
    i2 := sws_getCoefficients2(SWS_CS_ITU709);

    ret := sws_setColorspaceDetails2(videoConvContext, i1, srcRange, i2, dstRange, 0, 1 shl 16, 1 shl 16);

    sws_init_context(videoConvContext, nil, nil);
结果完全一样......
sws_scale 的输出没有正确的颜色,这里是 2 个屏幕截图
好的 - 来自 mpc-hc
ok
不行 - 从我的播放器通过 sws_scale (直接原始提取,所以没有完成颜色处理)
not ok
该视频有 pix_fmt AV_PIX_FMT_YUV420P10LE ,但它发生在其他 YUV 输入上,但不是那么明显。同样在其他 RGB 输出(8 位等)...
这里的 Netflix 标志是纯红色的,但 sws_scale 输出是橙色的……
Sws_scale 代码仅供引用:
sws_scale(videoConvContext, @AVPacketBuffer.AVFrameCopy.Data, @AVPacketBuffer.AVFrameCopy.linesize, 0, AVStream.codec.height, @BitmapXBuffer.data, @linesize);
BitmapXBuffer.data 是一个大小正确的单一缓冲区...
AVFrameCopy - 是原始帧的副本,完成:
  if Assigned(AVPacketBuffer.AVFrameCopy) then
      av_frame_free(@AVPacketBuffer.AVFrameCopy);

    AVPacketBuffer.AVFrameCopy := av_frame_alloc();
    AVPacketBuffer.AVFrameCopy.format := AVPacketBuffer.AVFrame.format;
    AVPacketBuffer.AVFrameCopy.width := AVPacketBuffer.AVFrame.width;
    AVPacketBuffer.AVFrameCopy.height := AVPacketBuffer.AVFrame.height;
    AVPacketBuffer.AVFrameCopy.channels := AVPacketBuffer.AVFrame.channels;
    AVPacketBuffer.AVFrameCopy.channel_layout := AVPacketBuffer.AVFrame.channel_layout;
    AVPacketBuffer.AVFrameCopy.nb_samples := AVPacketBuffer.AVFrame.nb_samples;
    av_frame_get_buffer(AVPacketBuffer.AVFrameCopy, 32);
    av_frame_copy(AVPacketBuffer.AVFrameCopy, AVPacketBuffer.AVFrame);
    av_frame_copy_props(AVPacketBuffer.AVFrameCopy, AVPacketBuffer.AVFrame);
谢谢!

最佳答案

回答我自己的问题 - 上面的代码是正确的,
让我感到困惑的是 dst_table,但只有当目标颜色空间是 YUV 时它才有意义。
Netflix 的标志也是橙色的,但不是正确的橙色。从 sRGB 转换为线性 RGB 为我解决了这个问题,但这仅适用于我的情况。
所以,以上面的代码为例:D

关于c - FFMpeg、libav、sws_scale 和 yuv 到 rgb 转换的问题 - 颜色不正确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62985672/

相关文章:

c - 如何将全0设置为通过结构(C)声明的数组?

.net - Linq 查询从该 XML 解析/获取内容 (WSDL)

android - 调试C native 函数android ndk - sendto()

delphi - Delphi 中消息传递过程的现有过程类型?

Delphi - 如何重新启用调试器异常通知?

android-ndk - 使用 Gradle 2.2.1 加载共享库

c - 表达式 "j =++(i | i); 和 j =++(i & i); 应该是左值错误?

delphi - 打印 TDBGrid

node.js - 在 10M ffmpeg 停止在 nodejs 上保存视频之后

python - 在 Raspberry PI 上用 Python 执行 FFmpeg 命令