【发布时间】:2020-07-19 21:06:29
【问题描述】:
我一直在尝试在 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
不好 - 从我的播放器通过 sws_scale (直接原始提取,所以没有完成颜色处理)
此视频有 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);
谢谢!
【问题讨论】:
-
从黑暗中拍摄(我正在处理类似的事情,但仍然不理解您的一半代码):也许两个颜色通道被切换了。您是否尝试过 AV_PIX_FMT_BGR48LE?但既然你什么都试过了,这可能不是正确的答案......
-
抱歉,on 的 rgb 值在 bg 上总是像 fe0000, 0000,在坏的时候像 ce5000,我找不到 ligic :)
-
也许你不应该碰色彩空间。
-
这是我做的第一件事。结果相同。