GUAC-236: Allocate and maintain frame data for encoding.

This commit is contained in:
Michael Jumper 2016-03-11 12:31:39 -08:00
parent 9a5b503da5
commit 9eddaeee3d
2 changed files with 51 additions and 4 deletions

View File

@ -26,6 +26,8 @@
#include "video.h" #include "video.h"
#include <libavcodec/avcodec.h> #include <libavcodec/avcodec.h>
#include <libavutil/common.h>
#include <libavutil/imgutils.h>
#include <guacamole/client.h> #include <guacamole/client.h>
#include <guacamole/timestamp.h> #include <guacamole/timestamp.h>
@ -64,19 +66,35 @@ guacenc_video* guacenc_video_alloc(const char* path, const char* codec_name,
/* Open codec for use */ /* Open codec for use */
if (avcodec_open2(context, codec, NULL) < 0) { if (avcodec_open2(context, codec, NULL) < 0) {
guacenc_log(GUAC_LOG_ERROR, "Failed to open codec \"%s\".", codec_name); guacenc_log(GUAC_LOG_ERROR, "Failed to open codec \"%s\".", codec_name);
avcodec_free_context(&context); goto fail_context;
return NULL; }
/* 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 */ /* Allocate video structure */
guacenc_video* video = malloc(sizeof(guacenc_video)); guacenc_video* video = malloc(sizeof(guacenc_video));
if (video == NULL) { if (video == NULL) {
avcodec_free_context(&context); goto fail_frame_data;
return NULL;
} }
/* Init properties of video */ /* Init properties of video */
video->context = context; video->context = context;
video->frame = frame;
video->width = width; video->width = width;
video->height = height; video->height = height;
video->frame_duration = 1000 / framerate; video->frame_duration = 1000 / framerate;
@ -89,6 +107,17 @@ guacenc_video* guacenc_video_alloc(const char* path, const char* codec_name,
return video; 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) if (buffer == NULL)
return 0; 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 */ /* STUB: Write frame to video */
guacenc_log(GUAC_LOG_DEBUG, "Writing frame @ %" PRId64 "ms", guacenc_log(GUAC_LOG_DEBUG, "Writing frame @ %" PRId64 "ms",
video->current_time); video->current_time);
@ -160,6 +197,10 @@ int guacenc_video_free(guacenc_video* video) {
/* Write final frame */ /* Write final frame */
guacenc_video_flush_frame(video); guacenc_video_flush_frame(video);
/* Free frame encoding data */
av_freep(&video->frame->data[0]);
av_frame_free(&video->frame);
/* Clean up encoding context */ /* Clean up encoding context */
avcodec_close(video->context); avcodec_close(video->context);
avcodec_free_context(&(video->context)); avcodec_free_context(&(video->context));

View File

@ -42,6 +42,12 @@ typedef struct guacenc_video {
*/ */
AVCodecContext* context; 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. * The width of the video, in pixels.
*/ */