FFMPEG: преобразование RGB в YUV с помощью двоичного ffmpeg и кода C++ дает разные результаты
Я пытаюсь преобразовать кадры RGB (формат ppm) в формат YUV420P с помощью ffmpeg. Чтобы убедиться, что мой код C++ хорош, я сравнил вывод с созданным этой командой (тот же файл BILINEAR): ffmpeg -start_number 1 -i data/test512x512%d.ppm -sws_flags 'bilinear' -pix_fmt yuv420p data/test-yuv420p.yuv
Мой код:
static unsigned char *readPPM(int i)
{
FILE *pF;
unsigned char *imgRGB;
unsigned char *imgBGR;
int w,h;
int c;
int bit;
char buff[16];
char *filename;
asprintf(&filename,"test512x512%d.ppm",i);
pF = fopen(filename,"rb");
free(filename);
if (pF) {
if (!fgets(buff, sizeof(buff), pF)) {
return nullptr;
}
if (buff[0] != 'P' || buff[1] != '6') {
fprintf(stderr, "Invalid image format (must be 'P6')\n");
return nullptr;
}
c = getc(pF);
while (c == '#') {
while (getc(pF) != '\n') ;
c = getc(pF);
}
ungetc(c, pF);
// read size
if (fscanf(pF, "%d %d", &w, &h) != 2) {
fprintf(stderr, "Invalid image size (error loading '%s')\n", filename);
return nullptr;
}
//read bit
if (fscanf(pF, "%d", &bit) != 1) {
fprintf(stderr, "Invalid rgb component (error loading '%s')\n", filename);
exit(1);
}
imgRGB =(unsigned char*) malloc(3*h*w);
imgBGR =(unsigned char*) malloc(3*h*w);
//read pixel data from file
int length = fread(imgBGR, sizeof(unsigned char)*3, w*h, pF) ;
if (length != w*h) {
fprintf(stderr, "Error loading image '%s'\n", filename);
return nullptr;
}
int start=0;
for (i=0; i < HEIGHT*WIDTH;i++) {
imgRGB[start] = imgBGR[start];
imgRGB[start+2]= imgBGR[start+2];
imgRGB[start+1]= imgBGR[start+1];
start+=3;
}
fclose(pF);
free(imgBGR);
return imgRGB;
}
else {
return nullptr;
}
}
void Test_FFMPEG::FillFrame (uint8_t* pic, int index)
{
avpicture_fill((AVPicture*)RGBFrame, pic, AV_PIX_FMT_RGB24, encodeContext->width, encodeContext->height);
struct SwsContext* fooContext = sws_getContext(encodeContext->width, encodeContext->height,
PIX_FMT_RGB24,
encodeContext->width, encodeContext->height,
PIX_FMT_YUV420P,
SWS_BILINEAR , nullptr, nullptr, nullptr);
sws_scale(fooContext, RGBFrame->data, RGBFrame->linesize, 0, encodeContext->height, OrgFrame->data, OrgFrame->linesize);
OrgFrame->pts = index;
}
Результат сравнения не очень хороший. Есть небольшие различия в Y и V, но много в U. Я не могу опубликовать свои изображения, но есть часть Y в изображении U. И это немного меняет цвет.
Можете ли вы сказать мне, где моя ошибка? Спасибо вам
1 ответ
Я не уверен в значениях по умолчанию для ffmpeg, но использую SWS_BILINEAR | SWS_ACCURATE_RND
должен дать лучшие результаты.