Я работал с преобразованием RGB-> YUV420 некоторое время, используя библиотеку FFmpeg. Уже пробовал sws_scale
функциональность, но не работает хорошо. Теперь я решил преобразовать каждый пиксель индивидуально, используя формулы преобразования цветового пространства. Итак, следующий код дает мне несколько кадров и позволяет получить доступ к отдельным значениям R, G, B каждого пикселя:
// Read frames and save first five frames to disk
i=0;
while((av_read_frame(pFormatCtx, &packet)>=0) && (i<5))
{
// Is this a packet from the video stream?
if(packet.stream_index==videoStreamIdx)
{
/// Decode video frame
avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);
// 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);
int x, y, R, G, B;
uint8_t *p = pFrameRGB->data[0];
for(y = 0; y < h; y++)
{
for(x = 0; x < w; x++)
{
R = *p++;
G = *p++;
B = *p++;
printf(" %d-%d-%d ",R,G,B);
}
}
SaveFrame(pFrameRGB, pCodecCtx->width, pCodecCtx->height, i);
}
}
// Free the packet that was allocated by av_read_frame
av_free_packet(&packet);
}
Я читаю онлайн чтобы преобразовать RGB-> YUV420 или наоборот, сначала нужно преобразовать в формат YUV444. Итак, это как: RGB-> YUV444-> YUV420. Как мне реализовать это в C ++?
Кроме того, вот SaveFrame()
функция используется выше. Я думаю, это тоже должно немного измениться, так как YUV420 хранит данные по-другому. Как позаботиться об этом?
void SaveFrame(AVFrame *pFrame, int width, int height, int iFrame)
{
FILE *pFile;
char szFilename[32];
int y;
// Open file
sprintf(szFilename, "frame%d.ppm", iFrame);
pFile=fopen(szFilename, "wb");
if(pFile==NULL)
return;
// Write header
fprintf(pFile, "P6\n%d %d\n255\n", width, height);
// Write pixel data
for(y=0; y<height; y++)
fwrite(pFrame->data[0]+y*pFrame->linesize[0], 1, width*3, pFile);
// Close file
fclose(pFile);
}
Может кто-нибудь предложить, пожалуйста? Большое спасибо!!!
void SaveFrameYUV420P(AVFrame *pFrame, int width, int height, int iFrame)
{
FILE *pFile;
char szFilename[32];
int y;
// Open file
sprintf(szFilename, "frame%d.yuv", iFrame);
pFile=fopen(szFilename, "wb");
if(pFile==NULL)
return;
// Write pixel data
fwrite(pFrame->data[0], 1, width*height, pFile);
fwrite(pFrame->data[1], 1, width*height/4, pFile);
fwrite(pFrame->data[2], 1, width*height/4, pFile);
// Close file
fclose(pFile);
}
В Windows вы можете использовать IrfanView чтобы увидеть кадры, сохраненные таким образом. Вы открываете фрейм в формате RAW, 24bpp, задаете ширину и высоту и устанавливаете флажок «yuv420».
Других решений пока нет …