ffenc: Make keyframe forcing thread-safe

Make the keyframe forcing thread-safe, also emit a downstream event
to allow muxers or payloaders to react appropriately.

https://bugzilla.gnome.org/show_bug.cgi?id=602556
This commit is contained in:
Olivier Crête 2009-11-20 21:46:33 -05:00
parent 08160ac0ef
commit b69fcc471e
2 changed files with 29 additions and 2 deletions

View file

@ -686,11 +686,20 @@ gst_ffmpegenc_chain_video (GstPad * pad, GstBuffer * inbuf)
GstFFMpegEnc *ffmpegenc = (GstFFMpegEnc *) (GST_PAD_PARENT (pad)); GstFFMpegEnc *ffmpegenc = (GstFFMpegEnc *) (GST_PAD_PARENT (pad));
GstBuffer *outbuf; GstBuffer *outbuf;
gint ret_size = 0, frame_size; gint ret_size = 0, frame_size;
gboolean force_keyframe;
GST_DEBUG_OBJECT (ffmpegenc, GST_DEBUG_OBJECT (ffmpegenc,
"Received buffer of time %" GST_TIME_FORMAT, "Received buffer of time %" GST_TIME_FORMAT,
GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (inbuf))); GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (inbuf)));
GST_OBJECT_LOCK (ffmpegenc);
force_keyframe = ffmpegenc->force_keyframe;
ffmpegenc->force_keyframe = FALSE;
GST_OBJECT_UNLOCK (ffmpegenc);
if (force_keyframe)
ffmpegenc->picture->pict_type = FF_I_TYPE;
frame_size = gst_ffmpeg_avpicture_fill ((AVPicture *) ffmpegenc->picture, frame_size = gst_ffmpeg_avpicture_fill ((AVPicture *) ffmpegenc->picture,
GST_BUFFER_DATA (inbuf), GST_BUFFER_DATA (inbuf),
ffmpegenc->context->pix_fmt, ffmpegenc->context->pix_fmt,
@ -751,6 +760,14 @@ gst_ffmpegenc_chain_video (GstPad * pad, GstBuffer * inbuf)
if (ffmpegenc->picture->pict_type) if (ffmpegenc->picture->pict_type)
ffmpegenc->picture->pict_type = 0; ffmpegenc->picture->pict_type = 0;
if (force_keyframe) {
gst_pad_push_event (ffmpegenc->srcpad,
gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM,
gst_structure_new ("GstForceKeyUnit",
"timestamp", G_TYPE_UINT64, GST_BUFFER_TIMESTAMP (outbuf),
NULL)));
}
return gst_pad_push (ffmpegenc->srcpad, outbuf); return gst_pad_push (ffmpegenc->srcpad, outbuf);
} }
@ -1028,13 +1045,18 @@ static gboolean
gst_ffmpegenc_event_src (GstPad * pad, GstEvent * event) gst_ffmpegenc_event_src (GstPad * pad, GstEvent * event)
{ {
GstFFMpegEnc *ffmpegenc = (GstFFMpegEnc *) (GST_PAD_PARENT (pad)); GstFFMpegEnc *ffmpegenc = (GstFFMpegEnc *) (GST_PAD_PARENT (pad));
gboolean forward = TRUE;
switch (GST_EVENT_TYPE (event)) { switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_CUSTOM_UPSTREAM:{ case GST_EVENT_CUSTOM_UPSTREAM:{
const GstStructure *s; const GstStructure *s;
s = gst_event_get_structure (event); s = gst_event_get_structure (event);
if (gst_structure_has_name (s, "GstForceKeyUnit")) { if (gst_structure_has_name (s, "GstForceKeyUnit")) {
ffmpegenc->picture->pict_type = FF_I_TYPE; GST_OBJECT_LOCK (ffmpegenc);
ffmpegenc->force_keyframe = TRUE;
GST_OBJECT_UNLOCK (ffmpegenc);
forward = FALSE;
gst_event_unref (event);
} }
break; break;
} }
@ -1043,7 +1065,10 @@ gst_ffmpegenc_event_src (GstPad * pad, GstEvent * event)
break; break;
} }
return gst_pad_push_event (ffmpegenc->sinkpad, event); if (forward)
return gst_pad_push_event (ffmpegenc->sinkpad, event);
else
return TRUE;
} }
static void static void

View file

@ -74,6 +74,8 @@ struct _GstFFMpegEnc
/* other settings are copied over straight, /* other settings are copied over straight,
* include a context here, rather than copy-and-past it from avcodec.h */ * include a context here, rather than copy-and-past it from avcodec.h */
AVCodecContext config; AVCodecContext config;
gboolean force_keyframe;
}; };
typedef struct _GstFFMpegEncClass GstFFMpegEncClass; typedef struct _GstFFMpegEncClass GstFFMpegEncClass;