basevideoencoder: Add initial support for the all-headers field of the force-keyframe event

See bug #607742.
This commit is contained in:
Jonas Larsson 2011-11-25 11:48:08 +01:00 committed by Sebastian Dröge
parent 135239605f
commit 54cb226009
2 changed files with 52 additions and 2 deletions

View file

@ -188,6 +188,7 @@ gst_base_video_encoder_reset (GstBaseVideoEncoder * base_video_encoder)
gst_event_unref (base_video_encoder->force_keyunit_event);
base_video_encoder->force_keyunit_event = NULL;
}
gst_buffer_replace (&base_video_encoder->headers, NULL);
g_list_foreach (base_video_encoder->current_frame_events,
(GFunc) gst_event_unref, NULL);
@ -226,11 +227,20 @@ gst_base_video_encoder_init (GstBaseVideoEncoder * base_video_encoder,
GST_DEBUG_FUNCPTR (gst_base_video_encoder_src_event));
base_video_encoder->a.at_eos = FALSE;
base_video_encoder->headers = NULL;
/* encoder is expected to do so */
base_video_encoder->sink_clipping = TRUE;
}
void
gst_base_video_encoder_set_headers (GstBaseVideoEncoder * base_video_encoder,
GstBuffer * headers)
{
GST_DEBUG_OBJECT (base_video_encoder, "new headers %p", headers);
gst_buffer_replace (&base_video_encoder->headers, headers);
}
static gboolean
gst_base_video_encoder_drain (GstBaseVideoEncoder * enc)
{
@ -439,8 +449,13 @@ done:
static void
gst_base_video_encoder_finalize (GObject * object)
{
GstBaseVideoEncoder *base_video_encoder;
GST_DEBUG_OBJECT (object, "finalize");
base_video_encoder = GST_BASE_VIDEO_ENCODER (object);
gst_buffer_replace (&base_video_encoder->headers, NULL);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
@ -515,9 +530,15 @@ gst_base_video_encoder_sink_eventfunc (GstBaseVideoEncoder * base_video_encoder,
if (gst_structure_has_name (s, "GstForceKeyUnit")) {
GST_OBJECT_LOCK (base_video_encoder);
base_video_encoder->force_keyframe = TRUE;
if (!gst_structure_get_boolean (s, "all-headers",
&base_video_encoder->force_keyframe_headers))
base_video_encoder->force_keyframe_headers = FALSE;
if (base_video_encoder->force_keyunit_event)
gst_event_unref (base_video_encoder->force_keyunit_event);
base_video_encoder->force_keyunit_event = gst_event_copy (event);
GST_DEBUG_OBJECT (base_video_encoder, "GstForceKeyUnit, all-headers %d",
base_video_encoder->force_keyframe_headers);
GST_OBJECT_UNLOCK (base_video_encoder);
gst_event_unref (event);
ret = TRUE;
@ -602,9 +623,14 @@ gst_base_video_encoder_src_event (GstPad * pad, GstEvent * event)
if (gst_structure_has_name (s, "GstForceKeyUnit")) {
GST_OBJECT_LOCK (base_video_encoder);
base_video_encoder->force_keyframe = TRUE;
if (!gst_structure_get_boolean (s, "all-headers",
&base_video_encoder->force_keyframe_headers))
base_video_encoder->force_keyframe_headers = FALSE;
GST_OBJECT_UNLOCK (base_video_encoder);
gst_event_unref (event);
GST_DEBUG_OBJECT (base_video_encoder, "GstForceKeyUnit, all-headers %d",
base_video_encoder->force_keyframe_headers);
ret = TRUE;
} else {
ret =
@ -851,6 +877,7 @@ gst_base_video_encoder_finish_frame (GstBaseVideoEncoder * base_video_encoder,
GstFlowReturn ret = GST_FLOW_OK;
GstBaseVideoEncoderClass *base_video_encoder_class;
GList *l;
GstBuffer *headers = NULL;
base_video_encoder_class =
GST_BASE_VIDEO_ENCODER_GET_CLASS (base_video_encoder);
@ -920,7 +947,15 @@ gst_base_video_encoder_finish_frame (GstBaseVideoEncoder * base_video_encoder,
}
if (frame->is_sync_point) {
GST_LOG_OBJECT (base_video_encoder, "key frame");
if (base_video_encoder->force_keyframe_headers) {
GST_DEBUG_OBJECT (base_video_encoder, "force_keyframe_headers");
if (base_video_encoder->headers) {
gst_buffer_ref (base_video_encoder->headers);
headers = base_video_encoder->headers;
}
base_video_encoder->force_keyframe_headers = FALSE;
}
GST_LOG_OBJECT (base_video_encoder, "key frame, headers %p", headers);
base_video_encoder->distance_from_sync = 0;
GST_BUFFER_FLAG_UNSET (frame->src_buffer, GST_BUFFER_FLAG_DELTA_UNIT);
} else {
@ -943,6 +978,12 @@ gst_base_video_encoder_finish_frame (GstBaseVideoEncoder * base_video_encoder,
GST_BUFFER_DURATION (frame->src_buffer) = frame->presentation_duration;
GST_BUFFER_OFFSET (frame->src_buffer) = frame->decode_timestamp;
if (G_UNLIKELY (headers)) {
GST_BUFFER_TIMESTAMP (headers) = frame->presentation_timestamp;
GST_BUFFER_DURATION (headers) = 0;
GST_BUFFER_OFFSET (headers) = frame->decode_timestamp;
}
/* update rate estimate */
GST_BASE_VIDEO_CODEC (base_video_encoder)->bytes +=
GST_BUFFER_SIZE (frame->src_buffer);
@ -963,6 +1004,12 @@ gst_base_video_encoder_finish_frame (GstBaseVideoEncoder * base_video_encoder,
gst_buffer_set_caps (GST_BUFFER (frame->src_buffer),
GST_PAD_CAPS (GST_BASE_VIDEO_CODEC_SRC_PAD (base_video_encoder)));
if (G_UNLIKELY (headers)) {
gst_buffer_set_caps (headers,
GST_PAD_CAPS (GST_BASE_VIDEO_CODEC_SRC_PAD (base_video_encoder)));
gst_pad_push (GST_BASE_VIDEO_CODEC_SRC_PAD (base_video_encoder), headers);
}
if (base_video_encoder_class->shape_output) {
ret = base_video_encoder_class->shape_output (base_video_encoder, frame);
} else {

View file

@ -85,6 +85,7 @@ struct _GstBaseVideoEncoder
int distance_from_sync;
gboolean force_keyframe;
gboolean force_keyframe_headers;
/*< private >*/
/* FIXME move to real private part ?
@ -96,6 +97,7 @@ struct _GstBaseVideoEncoder
GstEvent *force_keyunit_event;
GList *current_frame_events;
GstBuffer *headers;
union {
void *padding;
@ -178,7 +180,8 @@ void gst_base_video_encoder_set_latency (GstBaseVideoEncoder *
GstClockTime min_latency, GstClockTime max_latency);
void gst_base_video_encoder_set_latency_fields (GstBaseVideoEncoder *base_video_encoder,
int n_fields);
void gst_base_video_encoder_set_headers (GstBaseVideoEncoder *base_video_encoder,
GstBuffer *headers);
G_END_DECLS
#endif