[FFmpeg-devel] PNG output horrible...
Peter Tap
ptrtap at yahoo.com
Mon Sep 10 03:25:35 CEST 2012
Comparing the original file to the generated file, here is what I see:
original.png : PNG image data, 128 x 128, 8-bit/color RGBA, non interlaced
new.png : PNG image data, 128 x 128, 8-bit/color RGB, non interlaced
The original file size is 13017 bytes. The new file size is 6840 bytes.
Perhaps this gives you some more ideas.
Regards,
Peter
----- Original Message -----
From: Peter Tap <ptrtap at yahoo.com>
To: "ffmpeg-devel at ffmpeg.org" <ffmpeg-devel at ffmpeg.org>
Cc:
Sent: Sunday, September 9, 2012 4:22 PM
Subject: PNG output horrible...
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