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. И немного меняет цвет.

Можете ли вы сказать мне, где моя ошибка? Спасибо


person muocdich    schedule 12.12.2014    source источник
comment
вы можете добавить несколько операторов printf, чтобы проверить, используют ли они те же параметры, что и вы для SwsContext...   -  person rogerdpack    schedule 12.12.2014


Ответы (1)


Я не уверен в значениях по умолчанию для ffmpeg, но использование SWS_BILINEAR | SWS_ACCURATE_RND должно дать лучшие результаты.

person szatmary    schedule 12.12.2014