x264enc: add force keyframe event handling

Use the GstForceKeyUnit event to force a keyframe.
Fixes #578112.
This commit is contained in:
Janin Kolenc 2009-04-09 23:53:39 +02:00 committed by Wim Taymans
parent cacadf3f4d
commit dde471ab49
2 changed files with 48 additions and 2 deletions

View file

@ -217,6 +217,7 @@ static void gst_x264_enc_close_encoder (GstX264Enc * encoder);
static gboolean gst_x264_enc_sink_set_caps (GstPad * pad, GstCaps * caps); static gboolean gst_x264_enc_sink_set_caps (GstPad * pad, GstCaps * caps);
static gboolean gst_x264_enc_sink_event (GstPad * pad, GstEvent * event); static gboolean gst_x264_enc_sink_event (GstPad * pad, GstEvent * event);
static gboolean gst_x264_enc_src_event (GstPad * pad, GstEvent * event);
static GstFlowReturn gst_x264_enc_chain (GstPad * pad, GstBuffer * buf); static GstFlowReturn gst_x264_enc_chain (GstPad * pad, GstBuffer * buf);
static void gst_x264_enc_flush_frames (GstX264Enc * encoder, gboolean send); static void gst_x264_enc_flush_frames (GstX264Enc * encoder, gboolean send);
static GstFlowReturn gst_x264_enc_encode_frame (GstX264Enc * encoder, static GstFlowReturn gst_x264_enc_encode_frame (GstX264Enc * encoder,
@ -418,6 +419,9 @@ gst_x264_enc_init (GstX264Enc * encoder, GstX264EncClass * klass)
gst_pad_use_fixed_caps (encoder->srcpad); gst_pad_use_fixed_caps (encoder->srcpad);
gst_element_add_pad (GST_ELEMENT (encoder), encoder->srcpad); gst_element_add_pad (GST_ELEMENT (encoder), encoder->srcpad);
gst_pad_set_event_function (encoder->srcpad,
GST_DEBUG_FUNCPTR (gst_x264_enc_src_event));
/* properties */ /* properties */
encoder->threads = ARG_THREADS_DEFAULT; encoder->threads = ARG_THREADS_DEFAULT;
encoder->pass = ARG_PASS_DEFAULT; encoder->pass = ARG_PASS_DEFAULT;
@ -452,6 +456,7 @@ gst_x264_enc_init (GstX264Enc * encoder, GstX264EncClass * klass)
encoder->buffer_size = 100000; encoder->buffer_size = 100000;
encoder->buffer = g_malloc (encoder->buffer_size); encoder->buffer = g_malloc (encoder->buffer_size);
encoder->i_type = X264_TYPE_AUTO;
x264_param_default (&encoder->x264param); x264_param_default (&encoder->x264param);
/* log callback setup; part of parameters */ /* log callback setup; part of parameters */
@ -803,6 +808,34 @@ gst_x264_enc_sink_set_caps (GstPad * pad, GstCaps * caps)
return TRUE; return TRUE;
} }
static gboolean
gst_x264_enc_src_event (GstPad * pad, GstEvent * event)
{
gboolean ret;
GstX264Enc *encoder;
encoder = GST_X264_ENC (gst_pad_get_parent (pad));
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_CUSTOM_UPSTREAM:{
const GstStructure *s;
s = gst_event_get_structure (event);
if (gst_structure_has_name (s, "GstForceKeyUnit")) {
/* Set I frame request */
encoder->i_type = X264_TYPE_I;
}
break;
}
default:
break;
}
ret = gst_pad_push_event (encoder->sinkpad, event);
gst_object_unref (encoder);
return ret;
}
static gboolean static gboolean
gst_x264_enc_sink_event (GstPad * pad, GstEvent * event) gst_x264_enc_sink_event (GstPad * pad, GstEvent * event)
{ {
@ -817,6 +850,14 @@ gst_x264_enc_sink_event (GstPad * pad, GstEvent * event)
break; break;
/* no flushing if flush received, /* no flushing if flush received,
* buffers in encoder are considered (in the) past */ * buffers in encoder are considered (in the) past */
case GST_EVENT_CUSTOM_DOWNSTREAM:{
const GstStructure *s;
s = gst_event_get_structure (event);
if (gst_structure_has_name (s, "GstForceKeyUnit")) {
encoder->i_type = X264_TYPE_I;
}
break;
}
default: default:
break; break;
} }
@ -837,7 +878,6 @@ gst_x264_enc_chain (GstPad * pad, GstBuffer * buf)
GstFlowReturn ret; GstFlowReturn ret;
x264_picture_t pic_in; x264_picture_t pic_in;
gint i_nal, i; gint i_nal, i;
if (G_UNLIKELY (encoder->x264enc == NULL)) if (G_UNLIKELY (encoder->x264enc == NULL))
goto not_inited; goto not_inited;
@ -859,7 +899,11 @@ gst_x264_enc_chain (GstPad * pad, GstBuffer * buf)
pic_in.img.i_stride[i] = encoder->stride[i]; pic_in.img.i_stride[i] = encoder->stride[i];
} }
pic_in.i_type = X264_TYPE_AUTO; pic_in.i_type = encoder->i_type;
/* Reset encoder forced picture type */
encoder->i_type = X264_TYPE_AUTO;
pic_in.i_pts = GST_BUFFER_TIMESTAMP (buf); pic_in.i_pts = GST_BUFFER_TIMESTAMP (buf);
ret = gst_x264_enc_encode_frame (encoder, &pic_in, &i_nal, TRUE); ret = gst_x264_enc_encode_frame (encoder, &pic_in, &i_nal, TRUE);

View file

@ -96,6 +96,8 @@ struct _GstX264Enc
guint8 *buffer; guint8 *buffer;
gulong buffer_size; gulong buffer_size;
gint i_type;
}; };
struct _GstX264EncClass struct _GstX264EncClass