From da673880eb8f9bca9c84f63ef722720b3a3fc49f Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Mon, 25 Feb 2013 10:49:19 +0000 Subject: [PATCH] theoraenc: do not reset the encoder when we need a keyframe Instead, remember we need a keyframe, and we will force the encoder to emit one next time we submit a new frame. Since libtheora does not have an API to request a keyframe, we reset the max keyframe interval to 1 temporarily. This has the advantage that the rate control keeps its history, and that the encoder won't choose different quant tables or somesuch, thus requiring new streamheaders (although this is probably only a theoretical possibility). Should also be a bit faster than resetting the encoder. https://bugzilla.gnome.org/show_bug.cgi?id=663350 --- ext/theora/gsttheoraenc.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/ext/theora/gsttheoraenc.c b/ext/theora/gsttheoraenc.c index d431deb08f..0823e22bc7 100644 --- a/ext/theora/gsttheoraenc.c +++ b/ext/theora/gsttheoraenc.c @@ -940,12 +940,16 @@ theora_enc_handle_frame (GstVideoEncoder * benc, GstVideoCodecFrame * frame) { th_ycbcr_buffer ycbcr; - gint res; + gint res, keyframe_interval; GstVideoFrame vframe; if (force_keyframe) { - theora_enc_reset (enc); - theora_enc_reset_ts (enc, running_time, frame->presentation_frame_number); + /* if we want a keyframe, temporarily reset the max keyframe interval + * to 1, which will cause libtheora to emit one. There is no API to + * request a keyframe at the moment. */ + keyframe_interval = 1; + th_encode_ctl (enc->encoder, TH_ENCCTL_SET_KEYFRAME_FREQUENCY_FORCE, + &keyframe_interval, sizeof (keyframe_interval)); } if (enc->multipass_cache_fd @@ -976,6 +980,16 @@ theora_enc_handle_frame (GstVideoEncoder * benc, GstVideoCodecFrame * frame) ret = GST_FLOW_OK; while (th_encode_packetout (enc->encoder, 0, &op)) { + /* Reset the max keyframe interval to its original state, and reset + * the flag so we don't create more keyframes if we loop */ + if (force_keyframe) { + keyframe_interval = + enc->keyframe_auto ? enc->keyframe_force : enc->keyframe_freq; + th_encode_ctl (enc->encoder, TH_ENCCTL_SET_KEYFRAME_FREQUENCY_FORCE, + &keyframe_interval, sizeof (keyframe_interval)); + force_keyframe = FALSE; + } + ret = theora_push_packet (enc, &op); if (ret != GST_FLOW_OK) goto beach;