From 9eddaeee3dae1380d661683b2f46cacbedd82e6a Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Fri, 11 Mar 2016 12:31:39 -0800 Subject: [PATCH] GUAC-236: Allocate and maintain frame data for encoding. --- src/guacenc/video.c | 49 +++++++++++++++++++++++++++++++++++++++++---- src/guacenc/video.h | 6 ++++++ 2 files changed, 51 insertions(+), 4 deletions(-) diff --git a/src/guacenc/video.c b/src/guacenc/video.c index f4fd1fcd..d0915af9 100644 --- a/src/guacenc/video.c +++ b/src/guacenc/video.c @@ -26,6 +26,8 @@ #include "video.h" #include +#include +#include #include #include @@ -64,19 +66,35 @@ guacenc_video* guacenc_video_alloc(const char* path, const char* codec_name, /* Open codec for use */ if (avcodec_open2(context, codec, NULL) < 0) { guacenc_log(GUAC_LOG_ERROR, "Failed to open codec \"%s\".", codec_name); - avcodec_free_context(&context); - return NULL; + goto fail_context; + } + + /* Allocate corresponding frame */ + AVFrame* frame = av_frame_alloc(); + if (frame == NULL) { + goto fail_context; + } + + /* Copy necessary data for frame from context */ + frame->format = context->pix_fmt; + frame->width = context->width; + frame->height = context->height; + + /* Allocate actual backing data for frame */ + if (av_image_alloc(frame->data, frame->linesize, frame->width, + frame->height, frame->format, 32) < 0) { + goto fail_frame; } /* Allocate video structure */ guacenc_video* video = malloc(sizeof(guacenc_video)); if (video == NULL) { - avcodec_free_context(&context); - return NULL; + goto fail_frame_data; } /* Init properties of video */ video->context = context; + video->frame = frame; video->width = width; video->height = height; video->frame_duration = 1000 / framerate; @@ -89,6 +107,17 @@ guacenc_video* guacenc_video_alloc(const char* path, const char* codec_name, return video; + /* Free all allocated data in case of failure */ +fail_frame_data: + av_freep(&frame->data[0]); + +fail_frame: + av_frame_free(&frame); + +fail_context: + avcodec_free_context(&context); + return NULL; + } /** @@ -109,6 +138,14 @@ static int guacenc_video_flush_frame(guacenc_video* video) { if (buffer == NULL) return 0; + /* Init video packet */ + AVPacket packet; + av_init_packet(&packet); + + /* Request that encoder allocate data for packet */ + packet.data = NULL; + packet.size = 0; + /* STUB: Write frame to video */ guacenc_log(GUAC_LOG_DEBUG, "Writing frame @ %" PRId64 "ms", video->current_time); @@ -160,6 +197,10 @@ int guacenc_video_free(guacenc_video* video) { /* Write final frame */ guacenc_video_flush_frame(video); + /* Free frame encoding data */ + av_freep(&video->frame->data[0]); + av_frame_free(&video->frame); + /* Clean up encoding context */ avcodec_close(video->context); avcodec_free_context(&(video->context)); diff --git a/src/guacenc/video.h b/src/guacenc/video.h index 21787bbc..23879186 100644 --- a/src/guacenc/video.h +++ b/src/guacenc/video.h @@ -42,6 +42,12 @@ typedef struct guacenc_video { */ AVCodecContext* context; + /** + * An image data area, containing YCbCr image data in the format required + * by avcodec_encode_video2(), for use and re-use as frames are rendered. + */ + AVFrame* frame; + /** * The width of the video, in pixels. */