diff options
author | Nirbheek Chauhan <nirbheek@centricular.com> | 2014-07-14 15:46:39 (GMT) |
---|---|---|
committer | Nirbheek Chauhan <nirbheek@centricular.com> | 2014-07-14 15:46:40 (GMT) |
commit | df0f28945f2c32f519457e838eb424401eb586e9 (patch) | |
tree | 0069fb922da82ac01f0fa3a0eea572da7f863d35 /src/encode.c | |
parent | feee319e6b6cb4774cce72d90d1a60f5ecc9bbda (diff) | |
download | soup-transcoding-proxy-df0f28945f2c32f519457e838eb424401eb586e9.zip soup-transcoding-proxy-df0f28945f2c32f519457e838eb424401eb586e9.tar.gz |
server: Always send data from the last keyframe
Store non-keyframe buffers sent to fakesink, and push them to all new clients
Diffstat (limited to 'src/encode.c')
-rw-r--r-- | src/encode.c | 65 |
1 files changed, 57 insertions, 8 deletions
diff --git a/src/encode.c b/src/encode.c index 00eb791..3862aa6 100644 --- a/src/encode.c +++ b/src/encode.c @@ -95,6 +95,27 @@ out: return; } +static void +update_keyframe_buffer_cb (GstElement *fakesink, + GstBuffer *buffer, + GstPad *pad, + TranscodeServerCtx *ctx) +{ + if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DECODE_ONLY) || + GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_CORRUPTED) || + GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_GAP) || + GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DROPPABLE)) + return; + + if (!GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT)) + gst_buffer_list_foreach (ctx->keyframe, + stp_unref_gst_buffer, NULL); + + gst_buffer_ref (buffer); + gst_buffer_list_add (ctx->keyframe, buffer); + return; +} + static GstEncodingProfile * create_webm_profile (void) { @@ -140,6 +161,9 @@ stp_encode_from_msg (TranscodeServerCtx *ctx) { #ifdef ENCODE_DEBUG char *tmp, *filename; + GstPad *srcpad, *sinkpad; + GstElement *filesink, *q2; + GstPadTemplate *template; #endif GstBus *bus; GstElement *src, *decodebin, *encodebin; @@ -166,23 +190,48 @@ stp_encode_from_msg (TranscodeServerCtx *ctx) g_object_set (encodebin, "profile", profile, "avoid-reencoding", TRUE, NULL); + tee = gst_element_factory_make ("tee", "tee"); q1 = gst_element_factory_make ("queue", "q1"); + fakesink = gst_element_factory_make ("fakesink", "fakesink"); + + /* Ensure that the stream is always realtime */ + g_object_set (fakesink, + "sync", TRUE, + "signal-handoffs", TRUE, NULL); + + gst_bin_add_many (GST_BIN (ctx->pipeline), encodebin, tee, q1, fakesink, NULL); + gst_element_link_many (encodebin, tee, q1, fakesink, NULL); + #ifdef ENCODE_DEBUG - fakesink = gst_element_factory_make ("filesink", "filesink"); + q2 = gst_element_factory_make ("queue", "q2"); + filesink = gst_element_factory_make ("filesink", "filesink"); + tmp = g_uri_escape_string (ctx->path, NULL, TRUE); filename = g_strdup_printf ("debug-encode-%s.webm", tmp); - g_object_set (fakesink, "location", filename, NULL); + g_object_set (filesink, "location", filename, NULL); + + gst_bin_add_many (GST_BIN (ctx->pipeline), q2, filesink, NULL); + gst_element_link (q2, filesink); + + /* Link pads */ + template = gst_pad_template_new ("teesrc", GST_PAD_SRC, + GST_PAD_REQUEST, GST_CAPS_ANY); + srcpad = gst_element_request_pad (tee, template, NULL, GST_CAPS_ANY); + sinkpad = gst_element_get_static_pad (q2, "sink"); + + gst_pad_link (srcpad, sinkpad); + + gst_object_unref (template); + gst_object_unref (srcpad); g_free (filename); g_free (tmp); -#else - fakesink = gst_element_factory_make ("fakesink", "fakesink"); #endif - /* Ensure that the stream is always realtime */ - g_object_set (fakesink, "sync", TRUE, NULL); - gst_bin_add_many (GST_BIN (ctx->pipeline), encodebin, tee, q1, fakesink, NULL); - gst_element_link_many (encodebin, tee, q1, fakesink, NULL); + ctx->keyframe = gst_buffer_list_new (); + + g_signal_connect (fakesink, "handoff", + G_CALLBACK (update_keyframe_buffer_cb), ctx); /* The pads of decodebin and encodebin are dynamic, * so those will be linked when streams/pads are added */ |