summaryrefslogtreecommitdiff
path: root/src/encode.c
diff options
context:
space:
mode:
authorNirbheek Chauhan <nirbheek@centricular.com>2014-07-14 15:46:39 (GMT)
committerNirbheek Chauhan <nirbheek@centricular.com>2014-07-14 15:46:40 (GMT)
commitdf0f28945f2c32f519457e838eb424401eb586e9 (patch)
tree0069fb922da82ac01f0fa3a0eea572da7f863d35 /src/encode.c
parentfeee319e6b6cb4774cce72d90d1a60f5ecc9bbda (diff)
downloadsoup-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.c65
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 */