summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOlivier CrĂȘte <olivier.crete@collabora.co.uk>2009-11-20 21:46:33 -0500
committerOlivier CrĂȘte <olivier.crete@collabora.co.uk>2009-11-20 22:14:51 -0500
commitb69fcc471ea268587a8796ddffc888f321933d0a (patch)
treeca7df7317e1279babce0c1122d74ac0dfa5ae68e
parent08160ac0ef7de24f0487e8865af1b26819fbc6d8 (diff)
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
-rw-r--r--ext/ffmpeg/gstffmpegenc.c29
-rw-r--r--ext/ffmpeg/gstffmpegenc.h2
2 files changed, 29 insertions, 2 deletions
diff --git a/ext/ffmpeg/gstffmpegenc.c b/ext/ffmpeg/gstffmpegenc.c
index d9ceb49..fd0f205 100644
--- a/ext/ffmpeg/gstffmpegenc.c
+++ b/ext/ffmpeg/gstffmpegenc.c
@@ -686,11 +686,20 @@ gst_ffmpegenc_chain_video (GstPad * pad, GstBuffer * inbuf)
GstFFMpegEnc *ffmpegenc = (GstFFMpegEnc *) (GST_PAD_PARENT (pad));
GstBuffer *outbuf;
gint ret_size = 0, frame_size;
+ gboolean force_keyframe;
GST_DEBUG_OBJECT (ffmpegenc,
"Received buffer of time %" GST_TIME_FORMAT,
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,
GST_BUFFER_DATA (inbuf),
ffmpegenc->context->pix_fmt,
@@ -751,6 +760,14 @@ gst_ffmpegenc_chain_video (GstPad * pad, GstBuffer * inbuf)
if (ffmpegenc->picture->pict_type)
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);
}
@@ -1028,13 +1045,18 @@ static gboolean
gst_ffmpegenc_event_src (GstPad * pad, GstEvent * event)
{
GstFFMpegEnc *ffmpegenc = (GstFFMpegEnc *) (GST_PAD_PARENT (pad));
+ gboolean forward = TRUE;
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")) {
- 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;
}
@@ -1043,7 +1065,10 @@ gst_ffmpegenc_event_src (GstPad * pad, GstEvent * event)
break;
}
- return gst_pad_push_event (ffmpegenc->sinkpad, event);
+ if (forward)
+ return gst_pad_push_event (ffmpegenc->sinkpad, event);
+ else
+ return TRUE;
}
static void
diff --git a/ext/ffmpeg/gstffmpegenc.h b/ext/ffmpeg/gstffmpegenc.h
index 3e4a6b1..c13a0d3 100644
--- a/ext/ffmpeg/gstffmpegenc.h
+++ b/ext/ffmpeg/gstffmpegenc.h
@@ -74,6 +74,8 @@ struct _GstFFMpegEnc
/* other settings are copied over straight,
* include a context here, rather than copy-and-past it from avcodec.h */
AVCodecContext config;
+
+ gboolean force_keyframe;
};
typedef struct _GstFFMpegEncClass GstFFMpegEncClass;