lea*_*ner 1 ffmpeg video-encoding libavcodec libav libavformat
我试图在ffmpeg/libav中将RGB帧转换为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);
}
Run Code Online (Sandbox Code Playgroud)


sza*_*ary 10
对初学者来说,我会假设你拥有的地方:
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);
Run Code Online (Sandbox Code Playgroud)
你真的打算:
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);
Run Code Online (Sandbox Code Playgroud)
我也不确定你为什么两次打电话给swscale!
YUV是一种平面格式.这意味着所有三个通道都是独立存储的.RGB的存储方式如下:RGBRGBRGB
YUV420P是如下商店:YYYYYYYYYYYYYYYY..UUUUUUUUUUU ..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 );
}
Run Code Online (Sandbox Code Playgroud)
我还将您的算法切换为使用SWS_LANCZOS | SWS_ACCURATE_RND.这将为您提供更好看的图像.如果它要慢,请改回来.我还使用了源帧中的像素格式,而不是一直假设RGB.
| 归档时间: |
|
| 查看次数: |
8790 次 |
| 最近记录: |