screenshot, vo_png: fix dependency on sizeof(AVFrame)

In order to stay binary compatible with libavcodec, applications should
not dependent on sizeof(AVFrame). This means allocating AVFrame on the
stack is not allowed, and the function avcodec_alloc_frame() must be
used to allocate an AVFrame instead.

Partially based on a patch by uau.
This commit is contained in:
wm4 2012-04-29 07:32:57 +02:00
parent 97ac824124
commit 4add4f708e
2 changed files with 22 additions and 11 deletions

View File

@ -50,6 +50,7 @@ static int z_compression;
static int framenum; static int framenum;
static int use_alpha; static int use_alpha;
static AVCodecContext *avctx; static AVCodecContext *avctx;
static AVFrame *pic;
static uint8_t *outbuffer; static uint8_t *outbuffer;
int outbuffer_size; int outbuffer_size;
@ -70,6 +71,9 @@ config(uint32_t width, uint32_t height, uint32_t d_width, uint32_t d_height, uin
avctx = avcodec_alloc_context3(png_codec); avctx = avcodec_alloc_context3(png_codec);
if (!avctx) if (!avctx)
goto error; goto error;
pic = avcodec_alloc_frame();
if (!pic)
goto error;
avctx->width = width; avctx->width = width;
avctx->height = height; avctx->height = height;
avctx->pix_fmt = imgfmt2pixfmt(format); avctx->pix_fmt = imgfmt2pixfmt(format);
@ -85,7 +89,6 @@ config(uint32_t width, uint32_t height, uint32_t d_width, uint32_t d_height, uin
static uint32_t draw_image(mp_image_t* mpi){ static uint32_t draw_image(mp_image_t* mpi){
AVFrame pic;
int buffersize; int buffersize;
int res; int res;
char buf[100]; char buf[100];
@ -101,15 +104,17 @@ static uint32_t draw_image(mp_image_t* mpi){
return 1; return 1;
} }
pic.data[0] = mpi->planes[0]; avcodec_get_frame_defaults(pic);
pic.linesize[0] = mpi->stride[0];
pic->data[0] = mpi->planes[0];
pic->linesize[0] = mpi->stride[0];
buffersize = mpi->w * mpi->h * 8; buffersize = mpi->w * mpi->h * 8;
if (outbuffer_size < buffersize) { if (outbuffer_size < buffersize) {
av_freep(&outbuffer); av_freep(&outbuffer);
outbuffer = av_malloc(buffersize); outbuffer = av_malloc(buffersize);
outbuffer_size = buffersize; outbuffer_size = buffersize;
} }
res = avcodec_encode_video(avctx, outbuffer, outbuffer_size, &pic); res = avcodec_encode_video(avctx, outbuffer, outbuffer_size, pic);
if(res < 0){ if(res < 0){
mp_msg(MSGT_VO,MSGL_WARN, "[VO_PNG] Error in create_png.\n"); mp_msg(MSGT_VO,MSGL_WARN, "[VO_PNG] Error in create_png.\n");
@ -156,6 +161,8 @@ static void uninit(void)
avcodec_close(avctx); avcodec_close(avctx);
av_freep(&avctx); av_freep(&avctx);
av_freep(&outbuffer); av_freep(&outbuffer);
av_free(pic);
pic = NULL;
outbuffer_size = 0; outbuffer_size = 0;
} }

View File

@ -23,8 +23,6 @@
#include <setjmp.h> #include <setjmp.h>
#include <time.h> #include <time.h>
#include "osdep/io.h"
#include <libswscale/swscale.h> #include <libswscale/swscale.h>
#include <libavcodec/avcodec.h> #include <libavcodec/avcodec.h>
@ -34,6 +32,8 @@
#include <jpeglib.h> #include <jpeglib.h>
#endif #endif
#include "osdep/io.h"
#include "talloc.h" #include "talloc.h"
#include "screenshot.h" #include "screenshot.h"
#include "mp_core.h" #include "mp_core.h"
@ -82,6 +82,7 @@ static int write_png(screenshot_ctx *ctx, struct mp_image *image, FILE *fp)
{ {
void *outbuffer = NULL; void *outbuffer = NULL;
int success = 0; int success = 0;
AVFrame *pic = NULL;
struct AVCodec *png_codec = avcodec_find_encoder(CODEC_ID_PNG); struct AVCodec *png_codec = avcodec_find_encoder(CODEC_ID_PNG);
AVCodecContext *avctx = NULL; AVCodecContext *avctx = NULL;
@ -109,13 +110,15 @@ static int write_png(screenshot_ctx *ctx, struct mp_image *image, FILE *fp)
if (!outbuffer) if (!outbuffer)
goto error_exit; goto error_exit;
AVFrame pic; pic = avcodec_alloc_frame();
avcodec_get_frame_defaults(&pic); if (!pic)
goto error_exit;
avcodec_get_frame_defaults(pic);
for (int n = 0; n < 4; n++) { for (int n = 0; n < 4; n++) {
pic.data[n] = image->planes[n]; pic->data[n] = image->planes[n];
pic.linesize[n] = image->stride[n]; pic->linesize[n] = image->stride[n];
} }
int size = avcodec_encode_video(avctx, outbuffer, outbuffer_size, &pic); int size = avcodec_encode_video(avctx, outbuffer, outbuffer_size, pic);
if (size < 1) if (size < 1)
goto error_exit; goto error_exit;
@ -126,6 +129,7 @@ error_exit:
if (avctx) if (avctx)
avcodec_close(avctx); avcodec_close(avctx);
av_free(avctx); av_free(avctx);
av_free(pic);
free(outbuffer); free(outbuffer);
return success; return success;
} }