[FFmpeg-devel] PNG output horrible...

Peter Tap ptrtap at yahoo.com
Mon Sep 10 01:22:31 CEST 2012


Folks,

In my application, I open and read a png file and create a new png file as output. However, I am not getting the same quality of output. I would appreciate it if someone can point the mistake in my code. I will walk you through the code. For clarity, I have removed all the error checking.


void
SaveFrameToFile(AVFrame* pFrame, int width, int height, const char* format) {
    AVCodec* encoderCodec = avcodec_find_encoder_by_name(format);
    AVCodecContext* encoderCtx = avcodec_alloc_context();
    avcodec_open2(encoderCtx, encoderCodec, NULL);


    encoderCtx->width = width;
    encoderCtx->height = height;
    encoderCtx->pix_fmt = PIX_FMT_RGB24; // Is this line really needed? 

    int bufferSize = avpicture_get_size(encoderCtx->pix_fmt, width, height);
    uint8_t* buffer = (uint8_t*) av_malloc(bufferSize);
    int newSize = avcodec_encode_video(encoderCtx, buffer, bufferSize, pFrame);


    FILE* pFile = fopen(...);
    fwrite(buffer, 1, newSize, pFile);
    fclose(pFile);

    // Do the necessary cleanup
}


This method is straight-forward. It encodes the frame in the given format and writes to a file.
AVFrame*
AllocAVFrame(PixelFormat fmt, int width, int height) {
   AVFrame* retVal = avcodec_alloc_frame();
   int size = avpicture_get_size(fmt, width, height);
   uint8_t* frameBuf = (uint8_t*) av_malloc(size);
   avpicture_fill((AVPicture*) retVal, frameBuf, fmt, width, height);
   return retVal;
}


This method is also straight-forward. It just creates a new frame of given format, width, and height.

Now, here is main program loop:


  AVFrame* pFrame = avcodec_alloc_frame();

  AVPacket packet;
  while(av_read_frame(pFormatCtx, &packet) >= 0) {
      int  frameFinished;
      int len = avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);
      if(frameFinished) {
         PixelFormat fmt = PIX_FMT_RGB24;
         AVFrame* outputFrame = AllocAVFrame(fmt, w, h);
        SwsContext* imgConvertCtx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt,
                SWS_BICUBIC,  NULL, NULL, NULL);
        sws_scale(imgConvertCtx,
          (const uint8_t* const*)pFrame->data,
          pFrame->linesize,
          0,
          pCodecCtx->height,
          outputFrame->data,
          outputFrame->linesize);
        SaveFrameToFile(outputFrame, pCodecCtx->width, pCodecCtx->height, "png");
 
     // Clean up
   }

Here, we decode the input, convert to PIX_FMT_RGB24, and save the frame to a file.

This code works in the sense that when I view the generated file, I do see the original image. However, the quality of the output is very bad. 

I am wondering if anyone can correct my mistake. Is it some bitrate I need to consider?

A higher bitrate would imply a longer buffer size. However, av_picture_get_size does not take bitrate as a parameter. In this case, how would you obtain proper buffer size?


Another related question while we are looking at the code. I have the original frame obtained out of avcodec_decode_video2. If I just try to save this frame to the file, it works partially. The output file contains only a grayscale image and the shape is also a bit crooked. Why?


Thank you in advance for your help.


Regards,
Peter


More information about the ffmpeg-devel mailing list