gpt4 book ai didi

ffmpeg:RGB 到 YUV 的转换会丢失颜色和比例

转载 作者:行者123 更新时间:2023-12-04 22:51:23 24 4
gpt4 key购买 nike

我正在尝试将 RGB 帧转换为 ffmpeg/libav 中的 YUV420P 格式。以下是转换代码以及转换前后的图像。转换后的图像会丢失所有颜色信息,并且比例也会发生显着变化。有人知道如何处理吗?我对 ffmpeg/libav 完全陌生!

// Did we get a video frame?
if(frameFinished)
{
i++;
sws_scale(img_convert_ctx, (const uint8_t * const *)pFrame->data,
pFrame->linesize, 0, pCodecCtx->height,
pFrameRGB->data, pFrameRGB->linesize);

//==============================================================
AVFrame *pFrameYUV = avcodec_alloc_frame();
// Determine required buffer size and allocate buffer
int numBytes2 = avpicture_get_size(PIX_FMT_RGB24, pCodecCtx->width,
pCodecCtx->height);
uint8_t *buffer = (uint8_t *)av_malloc(numBytes2*sizeof(uint8_t));

avpicture_fill((AVPicture *)pFrameYUV, buffer, PIX_FMT_RGB24,
pCodecCtx->width, pCodecCtx->height);


rgb_to_yuv_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height,
PIX_FMT_RGB24,
pCodecCtx->width,pCodecCtx->height,
PIX_FMT_RGB24,
SWS_BICUBIC, NULL,NULL,NULL);

sws_scale(rgb_to_yuv_ctx, pFrameRGB->data, pFrameRGB->linesize, 0,
pCodecCtx->height, pFrameYUV->data, pFrameYUV->linesize);

sws_freeContext(rgb_to_yuv_ctx);

SaveFrame(pFrameYUV, pCodecCtx->width, pCodecCtx->height, i);

av_free(buffer);
av_free(pFrameYUV);
}

original RGB24 frame

frame after RGB24->YUV420P conversion

最佳答案

那么对于初学者来说,我会假设你有:

rgb_to_yuv_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height,  
PIX_FMT_RGB24,
pCodecCtx->width,pCodecCtx->height,
PIX_FMT_RGB24,
SWS_BICUBIC, NULL,NULL,NULL);

你真的打算:
rgb_to_yuv_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height,  
PIX_FMT_RGB24,
pCodecCtx->width,pCodecCtx->height,
PIX_FMT_YUV420P,
SWS_BICUBIC, NULL,NULL,NULL);

我也不确定您为什么要两次调用 swscale !

YUV 是一种平面格式。这意味着所有三个 channel 都是独立存储的。 RGB 的存储方式如下:
RGBRGBRGB

YUV420P 是这样的商店:
YYYYYYYYYYYYYYYY..UUUUUUUUUU..VVVVVVVV

所以 swscale 需要你给它三个指针。

接下来,您希望您的线步长为 16 或 32 的倍数,以便可以使用处理器的向量单元。最后,Y 平面的尺寸需要被 2 整除(因为 U 和 V 平面是 Y 平面的四分之一大小)。

所以,让我们重写一下:
#define RNDTO2(X) ( ( (X) & 0xFFFFFFFE )
#define RNDTO32(X) ( ( (X) % 32 ) ? ( ( (X) + 32 ) & 0xFFFFFFE0 ) : (X) )




if(frameFinished)
{
static SwsContext *swsCtx = NULL;
int width = RNDTO2 ( pCodecCtx->width );
int height = RNDTO2 ( pCodecCtx->height );
int ystride = RNDTO32 ( width );
int uvstride = RNDTO32 ( width / 2 );
int ysize = ystride * height;
int vusize = uvstride * ( height / 2 );
int size = ysize + ( 2 * vusize )

void * pFrameYUV = malloc( size );
void *plane[] = { pFrameYUV, pFrameYUV + ysize, pFrameYUV + ysize + vusize, 0 };
int *stride[] = { ystride, vustride, vustride, 0 };

swsCtx = sws_getCachedContext ( swsCtx, pCodecCtx->width, pCodecCtx->height,
pCodecCtx->pixfmt, width, height, AV_PIX_FMT_YUV420P,
SWS_LANCZOS | SWS_ACCURATE_RND , NULL, NULL, NULL );
sws_scale ( swsCtx, pFrameRGB->data, pFrameRGB->linesize, 0,
pFrameRGB->height, plane, stride );
}

我还将您的算法切换为使用 SWS_LANCZOS | SWS_ACCURATE_RND。这将为您提供更好看的图像。如果它变慢,请将其更改回来。我还使用了源帧中的像素格式,而不是一直假设它是 RGB。

关于ffmpeg:RGB 到 YUV 的转换会丢失颜色和比例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21938674/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com