From b0aa56c7960dfb529502fb39fbddf599d4a387b7 Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Fri, 22 Jun 2007 12:13:18 +0000 Subject: [PATCH] ext/ffmpeg/gstffmpegenc.*: Instead of allocating 512KB buffers and then setting BUFFER_SIZE to what ffmpeg produced, ... Original commit message from CVS: * ext/ffmpeg/gstffmpegenc.c: (ffmpegenc_setup_working_buf), (gst_ffmpegenc_chain_video), (gst_ffmpegenc_flush_buffers), (gst_ffmpegenc_change_state): * ext/ffmpeg/gstffmpegenc.h: Instead of allocating 512KB buffers and then setting BUFFER_SIZE to what ffmpeg produced, we're better off by far to use a single working buffer and copy data out into neat little buffers. This prevents exhorbitant virtual memory wastage in the form of allocated but untouched buffers. --- ChangeLog | 13 +++++++++++++ common | 2 +- ext/ffmpeg/gstffmpegenc.c | 33 ++++++++++++++++++++++++++------- ext/ffmpeg/gstffmpegenc.h | 3 +++ 4 files changed, 43 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index 70e5d11f16..e37f40498e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2007-06-22 Jan Schmidt + + * ext/ffmpeg/gstffmpegenc.c: (ffmpegenc_setup_working_buf), + (gst_ffmpegenc_chain_video), (gst_ffmpegenc_flush_buffers), + (gst_ffmpegenc_change_state): + * ext/ffmpeg/gstffmpegenc.h: + Instead of allocating 512KB buffers and then setting BUFFER_SIZE + to what ffmpeg produced, we're better off by far to use a single + working buffer and copy data out into neat little buffers. + + This prevents exhorbitant virtual memory wastage in the form + of allocated but untouched buffers. + 2007-06-20 Stefan Kost * ext/ffmpeg/gstffmpegcodecmap.c: diff --git a/common b/common index 6cb0000a5a..14c5a68981 160000 --- a/common +++ b/common @@ -1 +1 @@ -Subproject commit 6cb0000a5a30d4fc580a06489106a637fca024c4 +Subproject commit 14c5a68981278f642e4ca5fd5ca08554fc78b348 diff --git a/ext/ffmpeg/gstffmpegenc.c b/ext/ffmpeg/gstffmpegenc.c index 6e6d6f5298..fefd4a96ab 100644 --- a/ext/ffmpeg/gstffmpegenc.c +++ b/ext/ffmpeg/gstffmpegenc.c @@ -567,6 +567,18 @@ gst_ffmpegenc_setcaps (GstPad * pad, GstCaps * caps) return TRUE; } +static void +ffmpegenc_setup_working_buf (GstFFMpegEnc *ffmpegenc) +{ + if (ffmpegenc->working_buf == NULL || + ffmpegenc->working_buf_size != ffmpegenc->buffer_size) { + if (ffmpegenc->working_buf) + g_free (ffmpegenc->working_buf); + ffmpegenc->working_buf_size = ffmpegenc->buffer_size; + ffmpegenc->working_buf = g_malloc (ffmpegenc->working_buf_size); + } +} + static GstFlowReturn gst_ffmpegenc_chain_video (GstPad * pad, GstBuffer * inbuf) { @@ -588,9 +600,11 @@ gst_ffmpegenc_chain_video (GstPad * pad, GstBuffer * inbuf) gst_ffmpeg_time_gst_to_ff (GST_BUFFER_TIMESTAMP (inbuf), ffmpegenc->context->time_base); - outbuf = gst_buffer_new_and_alloc (ffmpegenc->buffer_size); + ffmpegenc_setup_working_buf (ffmpegenc); + ret_size = avcodec_encode_video (ffmpegenc->context, - GST_BUFFER_DATA (outbuf), GST_BUFFER_SIZE (outbuf), ffmpegenc->picture); + ffmpegenc->working_buf, ffmpegenc->working_buf_size, + ffmpegenc->picture); if (ret_size < 0) { #ifndef GST_DISABLE_GST_DEBUG @@ -600,7 +614,6 @@ gst_ffmpegenc_chain_video (GstPad * pad, GstBuffer * inbuf) "ffenc_%s: failed to encode buffer", oclass->in_plugin->name); #endif /* GST_DISABLE_GST_DEBUG */ gst_buffer_unref (inbuf); - gst_buffer_unref (outbuf); return GST_FLOW_OK; } @@ -620,7 +633,7 @@ gst_ffmpegenc_chain_video (GstPad * pad, GstBuffer * inbuf) (("Could not write to file \"%s\"."), ffmpegenc->filename), GST_ERROR_SYSTEM); - GST_BUFFER_SIZE (outbuf) = ret_size; + outbuf = gst_buffer_new_and_alloc (ret_size); GST_BUFFER_TIMESTAMP (outbuf) = GST_BUFFER_TIMESTAMP (inbuf); GST_BUFFER_DURATION (outbuf) = GST_BUFFER_DURATION (inbuf); if (!ffmpegenc->context->coded_frame->key_frame) @@ -739,9 +752,10 @@ gst_ffmpegenc_flush_buffers (GstFFMpegEnc * ffmpegenc, gboolean send) while (!g_queue_is_empty (ffmpegenc->delay)) { - outbuf = gst_buffer_new_and_alloc (ffmpegenc->buffer_size); + ffmpegenc_setup_working_buf (ffmpegenc); + ret_size = avcodec_encode_video (ffmpegenc->context, - GST_BUFFER_DATA (outbuf), GST_BUFFER_SIZE (outbuf), NULL); + ffmpegenc->working_buf, ffmpegenc->working_buf_size, NULL); if (ret_size < 0) { /* there should be something, notify and give up */ #ifndef GST_DISABLE_GST_DEBUG @@ -763,9 +777,10 @@ gst_ffmpegenc_flush_buffers (GstFFMpegEnc * ffmpegenc, gboolean send) /* handle b-frame delay when no output, so we don't output empty frames */ inbuf = g_queue_pop_head (ffmpegenc->delay); - GST_BUFFER_SIZE (outbuf) = ret_size; + outbuf = gst_buffer_new_and_alloc (ret_size); GST_BUFFER_TIMESTAMP (outbuf) = GST_BUFFER_TIMESTAMP (inbuf); GST_BUFFER_DURATION (outbuf) = GST_BUFFER_DURATION (inbuf); + if (!ffmpegenc->context->coded_frame->key_frame) GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT); gst_buffer_set_caps (outbuf, GST_PAD_CAPS (ffmpegenc->srcpad)); @@ -898,6 +913,10 @@ gst_ffmpegenc_change_state (GstElement * element, GstStateChange transition) fclose (ffmpegenc->file); ffmpegenc->file = NULL; } + if (ffmpegenc->working_buf) { + g_free (ffmpegenc->working_buf); + ffmpegenc->working_buf = NULL; + } break; default: break; diff --git a/ext/ffmpeg/gstffmpegenc.h b/ext/ffmpeg/gstffmpegenc.h index 4c3c10ea98..ac9768abb5 100644 --- a/ext/ffmpeg/gstffmpegenc.h +++ b/ext/ffmpeg/gstffmpegenc.h @@ -48,6 +48,9 @@ struct _GstFFMpegEnc gulong buffer_size; gulong rtp_payload_size; + guint8 *working_buf; + gulong working_buf_size; + /* settings with some special handling */ guint pass; gfloat quantizer;