1 /* GStreamer Smart Video Encoder element
2 * Copyright (C) <2010> Edward Hervey <bilboed@gmail.com>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
21 * * Implement get_caps/set_caps (store/forward caps)
22 * * Adjust template caps to the formats we can support
30 #include "gstsmartencoder.h"
32 GST_DEBUG_CATEGORY_STATIC (smart_encoder_debug);
33 #define GST_CAT_DEFAULT smart_encoder_debug
35 /* FIXME : Update this with new caps */
36 /* WARNING : We can only allow formats with closed-GOP */
37 #define ALLOWED_CAPS "video/x-h263;video/x-intel-h263;"\
38 "video/mpeg,mpegversion=(int)1,systemstream=(boolean)false;"\
39 "video/mpeg,mpegversion=(int)2,systemstream=(boolean)false;"
41 static GstStaticPadTemplate src_template =
42 GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC,
44 GST_STATIC_CAPS (ALLOWED_CAPS)
47 static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
50 GST_STATIC_CAPS (ALLOWED_CAPS)
53 static GQuark INTERNAL_ELEMENT;
55 /* GstSmartEncoder signals and args */
71 INTERNAL_ELEMENT = g_quark_from_string ("internal-element");
74 G_DEFINE_TYPE_EXTENDED (GstSmartEncoder, gst_smart_encoder, GST_TYPE_ELEMENT, 0,
77 static void gst_smart_encoder_dispose (GObject * object);
79 static gboolean setup_recoder_pipeline (GstSmartEncoder * smart_encoder);
81 static GstFlowReturn gst_smart_encoder_chain (GstPad * pad, GstBuffer * buf);
82 static gboolean smart_encoder_sink_event (GstPad * pad, GstEvent * event);
83 static GstCaps *smart_encoder_sink_getcaps (GstPad * pad);
84 static GstStateChangeReturn
85 gst_smart_encoder_change_state (GstElement * element,
86 GstStateChange transition);
89 gst_smart_encoder_class_init (GstSmartEncoderClass * klass)
91 GObjectClass *gobject_class;
92 GstElementClass *element_class;
94 element_class = (GstElementClass *) klass;
95 gobject_class = G_OBJECT_CLASS (klass);
97 gst_smart_encoder_parent_class = g_type_class_peek_parent (klass);
99 gst_element_class_add_static_pad_template (element_class, &src_template);
100 gst_element_class_add_static_pad_template (element_class,
103 gst_element_class_set_details_simple (element_class, "Smart Video Encoder",
104 "Codec/Recoder/Video",
105 "Re-encodes portions of Video that lay on segment boundaries",
106 "Edward Hervey <bilboed@gmail.com>");
108 gobject_class->dispose = (GObjectFinalizeFunc) (gst_smart_encoder_dispose);
109 element_class->change_state = gst_smart_encoder_change_state;
111 GST_DEBUG_CATEGORY_INIT (smart_encoder_debug, "smartencoder", 0,
116 smart_encoder_reset (GstSmartEncoder * smart_encoder)
118 gst_segment_init (smart_encoder->segment, GST_FORMAT_UNDEFINED);
120 if (smart_encoder->encoder) {
121 /* Clean up/remove elements */
122 gst_element_set_state (smart_encoder->encoder, GST_STATE_NULL);
123 gst_element_set_state (smart_encoder->decoder, GST_STATE_NULL);
124 gst_element_set_bus (smart_encoder->encoder, NULL);
125 gst_element_set_bus (smart_encoder->decoder, NULL);
126 gst_pad_set_active (smart_encoder->internal_srcpad, FALSE);
127 gst_pad_set_active (smart_encoder->internal_sinkpad, FALSE);
128 gst_object_unref (smart_encoder->encoder);
129 gst_object_unref (smart_encoder->decoder);
130 gst_object_unref (smart_encoder->internal_srcpad);
131 gst_object_unref (smart_encoder->internal_sinkpad);
133 smart_encoder->encoder = NULL;
134 smart_encoder->decoder = NULL;
135 smart_encoder->internal_sinkpad = NULL;
136 smart_encoder->internal_srcpad = NULL;
139 if (smart_encoder->newsegment) {
140 gst_event_unref (smart_encoder->newsegment);
141 smart_encoder->newsegment = NULL;
147 gst_smart_encoder_init (GstSmartEncoder * smart_encoder)
149 smart_encoder->sinkpad =
150 gst_pad_new_from_static_template (&sink_template, "sink");
151 gst_pad_set_chain_function (smart_encoder->sinkpad, gst_smart_encoder_chain);
152 gst_pad_set_event_function (smart_encoder->sinkpad, smart_encoder_sink_event);
153 gst_pad_set_getcaps_function (smart_encoder->sinkpad,
154 smart_encoder_sink_getcaps);
155 gst_element_add_pad (GST_ELEMENT (smart_encoder), smart_encoder->sinkpad);
157 smart_encoder->srcpad =
158 gst_pad_new_from_static_template (&src_template, "src");
159 gst_pad_use_fixed_caps (smart_encoder->srcpad);
160 gst_element_add_pad (GST_ELEMENT (smart_encoder), smart_encoder->srcpad);
162 smart_encoder->segment = gst_segment_new ();
164 smart_encoder_reset (smart_encoder);
168 gst_smart_encoder_dispose (GObject * object)
170 GstSmartEncoder *smart_encoder = (GstSmartEncoder *) object;
172 if (smart_encoder->segment)
173 gst_segment_free (smart_encoder->segment);
174 smart_encoder->segment = NULL;
175 if (smart_encoder->available_caps)
176 gst_caps_unref (smart_encoder->available_caps);
177 smart_encoder->available_caps = NULL;
178 G_OBJECT_CLASS (gst_smart_encoder_parent_class)->dispose (object);
182 gst_smart_encoder_reencode_gop (GstSmartEncoder * smart_encoder)
184 GstFlowReturn res = GST_FLOW_OK;
187 if (smart_encoder->encoder == NULL) {
188 if (!setup_recoder_pipeline (smart_encoder))
189 return GST_FLOW_ERROR;
192 /* Activate elements */
193 /* Set elements to PAUSED */
194 gst_element_set_state (smart_encoder->encoder, GST_STATE_PAUSED);
195 gst_element_set_state (smart_encoder->decoder, GST_STATE_PAUSED);
197 GST_INFO ("Pushing Flush start/stop to clean decoder/encoder");
198 gst_pad_push_event (smart_encoder->internal_srcpad,
199 gst_event_new_flush_start ());
200 gst_pad_push_event (smart_encoder->internal_srcpad,
201 gst_event_new_flush_stop ());
203 /* push newsegment */
204 GST_INFO ("Pushing newsegment %" GST_PTR_FORMAT, smart_encoder->newsegment);
205 gst_pad_push_event (smart_encoder->internal_srcpad,
206 gst_event_ref (smart_encoder->newsegment));
208 /* Push buffers through our pads */
209 GST_DEBUG ("Pushing pending buffers");
211 for (tmp = smart_encoder->pending_gop; tmp; tmp = tmp->next) {
212 GstBuffer *buf = (GstBuffer *) tmp->data;
214 res = gst_pad_push (smart_encoder->internal_srcpad, buf);
215 if (G_UNLIKELY (res != GST_FLOW_OK))
219 if (G_UNLIKELY (res != GST_FLOW_OK)) {
220 GST_WARNING ("Error pushing pending buffers : %s", gst_flow_get_name (res));
221 /* Remove pending bfufers */
222 for (tmp = smart_encoder->pending_gop; tmp; tmp = tmp->next) {
223 gst_buffer_unref ((GstBuffer *) tmp->data);
226 GST_INFO ("Pushing out EOS to flush out decoder/encoder");
227 gst_pad_push_event (smart_encoder->internal_srcpad, gst_event_new_eos ());
230 /* Activate elements */
231 /* Set elements to PAUSED */
232 gst_element_set_state (smart_encoder->encoder, GST_STATE_NULL);
233 gst_element_set_state (smart_encoder->decoder, GST_STATE_NULL);
235 g_list_free (smart_encoder->pending_gop);
236 smart_encoder->pending_gop = NULL;
242 gst_smart_encoder_push_pending_gop (GstSmartEncoder * smart_encoder)
244 gint64 cstart, cstop;
246 GstFlowReturn res = GST_FLOW_OK;
248 GST_DEBUG ("Pushing pending GOP (%" GST_TIME_FORMAT " -- %" GST_TIME_FORMAT
249 ")", GST_TIME_ARGS (smart_encoder->gop_start),
250 GST_TIME_ARGS (smart_encoder->gop_stop));
252 /* If GOP is entirely within segment, just push downstream */
253 if (gst_segment_clip (smart_encoder->segment, GST_FORMAT_TIME,
254 smart_encoder->gop_start, smart_encoder->gop_stop, &cstart, &cstop)) {
255 if ((cstart != smart_encoder->gop_start)
256 || (cstop != smart_encoder->gop_stop)) {
257 GST_DEBUG ("GOP needs to be re-encoded from %" GST_TIME_FORMAT " to %"
258 GST_TIME_FORMAT, GST_TIME_ARGS (cstart), GST_TIME_ARGS (cstop));
259 res = gst_smart_encoder_reencode_gop (smart_encoder);
261 /* The whole GOP is within the segment, push all pending buffers downstream */
262 GST_DEBUG ("GOP doesn't need to be modified, pushing downstream");
263 for (tmp = smart_encoder->pending_gop; tmp; tmp = tmp->next) {
264 GstBuffer *buf = (GstBuffer *) tmp->data;
265 res = gst_pad_push (smart_encoder->srcpad, buf);
266 if (G_UNLIKELY (res != GST_FLOW_OK))
271 /* The whole GOP is outside the segment, there's most likely
272 * a bug somewhere. */
274 ("GOP is entirely outside of the segment, upstream gave us too much data");
275 for (tmp = smart_encoder->pending_gop; tmp; tmp = tmp->next) {
276 gst_buffer_unref ((GstBuffer *) tmp->data);
280 if (smart_encoder->pending_gop) {
281 g_list_free (smart_encoder->pending_gop);
282 smart_encoder->pending_gop = NULL;
284 smart_encoder->gop_start = GST_CLOCK_TIME_NONE;
285 smart_encoder->gop_stop = GST_CLOCK_TIME_NONE;
291 gst_smart_encoder_chain (GstPad * pad, GstBuffer * buf)
293 GstSmartEncoder *smart_encoder;
294 GstFlowReturn res = GST_FLOW_OK;
295 gboolean discont, keyframe;
297 smart_encoder = GST_SMART_ENCODER (gst_object_get_parent (GST_OBJECT (pad)));
299 discont = GST_BUFFER_IS_DISCONT (buf);
300 keyframe = !GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
302 GST_DEBUG ("New buffer %s %s %" GST_TIME_FORMAT,
303 discont ? "discont" : "",
304 keyframe ? "keyframe" : "", GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));
307 GST_DEBUG ("Got a keyframe");
309 /* If there's a pending GOP, flush it out */
310 if (smart_encoder->pending_gop) {
312 smart_encoder->gop_stop = GST_BUFFER_TIMESTAMP (buf);
315 res = gst_smart_encoder_push_pending_gop (smart_encoder);
316 if (G_UNLIKELY (res != GST_FLOW_OK))
320 /* Mark gop_start for new gop */
321 smart_encoder->gop_start = GST_BUFFER_TIMESTAMP (buf);
325 smart_encoder->pending_gop = g_list_append (smart_encoder->pending_gop, buf);
326 /* Update GOP stop position */
327 if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
328 smart_encoder->gop_stop = GST_BUFFER_TIMESTAMP (buf);
329 if (GST_BUFFER_DURATION_IS_VALID (buf))
330 smart_encoder->gop_stop += GST_BUFFER_DURATION (buf);
333 GST_DEBUG ("Buffer stored , Current GOP : %" GST_TIME_FORMAT " -- %"
334 GST_TIME_FORMAT, GST_TIME_ARGS (smart_encoder->gop_start),
335 GST_TIME_ARGS (smart_encoder->gop_stop));
338 gst_object_unref (smart_encoder);
343 smart_encoder_sink_event (GstPad * pad, GstEvent * event)
346 GstSmartEncoder *smart_encoder = GST_SMART_ENCODER (gst_pad_get_parent (pad));
348 switch (GST_EVENT_TYPE (event)) {
349 case GST_EVENT_FLUSH_STOP:
350 smart_encoder_reset (smart_encoder);
352 case GST_EVENT_NEWSEGMENT:
356 gint64 start, stop, time;
359 gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format,
360 &start, &stop, &time);
361 GST_DEBUG_OBJECT (smart_encoder,
362 "newsegment: update %d, rate %g, arate %g, start %" GST_TIME_FORMAT
363 ", stop %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT,
364 update, rate, arate, GST_TIME_ARGS (start), GST_TIME_ARGS (stop),
365 GST_TIME_ARGS (time));
366 if (format != GST_FORMAT_TIME)
368 ("smart_encoder can not handle streams not specified in GST_FORMAT_TIME");
370 /* now configure the values */
371 gst_segment_set_newsegment_full (smart_encoder->segment, update,
372 rate, arate, format, start, stop, time);
374 /* And keep a copy for further usage */
375 if (smart_encoder->newsegment)
376 gst_event_unref (smart_encoder->newsegment);
377 smart_encoder->newsegment = gst_event_ref (event);
381 GST_DEBUG ("Eos, flushing remaining data");
382 gst_smart_encoder_push_pending_gop (smart_encoder);
388 res = gst_pad_push_event (smart_encoder->srcpad, event);
390 gst_object_unref (smart_encoder);
395 smart_encoder_sink_getcaps (GstPad * pad)
397 GstCaps *peer, *tmpl, *res;
398 GstSmartEncoder *smart_encoder = GST_SMART_ENCODER (gst_pad_get_parent (pad));
400 /* Try getting it from downstream */
401 peer = gst_pad_peer_get_caps_reffed (smart_encoder->srcpad);
403 /* Use computed caps */
404 if (smart_encoder->available_caps)
405 tmpl = gst_caps_ref (smart_encoder->available_caps);
407 tmpl = gst_static_pad_template_get_caps (&src_template);
412 res = gst_caps_intersect (peer, tmpl);
413 gst_caps_unref (peer);
414 gst_caps_unref (tmpl);
417 gst_object_unref (smart_encoder);
421 /*****************************************
422 * Internal encoder/decoder pipeline *
423 ******************************************/
425 static GstElementFactory *
426 get_decoder_factory (GstCaps * caps)
428 GstElementFactory *fact = NULL;
429 GList *decoders, *tmp;
432 gst_element_factory_list_get_elements (GST_ELEMENT_FACTORY_TYPE_DECODER,
434 decoders = gst_element_factory_list_filter (tmp, caps, GST_PAD_SINK, FALSE);
435 gst_plugin_feature_list_free (tmp);
437 for (tmp = decoders; tmp; tmp = tmp->next) {
438 /* We just pick the first one */
439 fact = (GstElementFactory *) tmp->data;
440 gst_object_ref (fact);
444 gst_plugin_feature_list_free (decoders);
449 static GstElementFactory *
450 get_encoder_factory (GstCaps * caps)
452 GstElementFactory *fact = NULL;
453 GList *encoders, *tmp;
456 gst_element_factory_list_get_elements (GST_ELEMENT_FACTORY_TYPE_ENCODER,
458 encoders = gst_element_factory_list_filter (tmp, caps, GST_PAD_SRC, FALSE);
459 gst_plugin_feature_list_free (tmp);
461 for (tmp = encoders; tmp; tmp = tmp->next) {
462 /* We just pick the first one */
463 fact = (GstElementFactory *) tmp->data;
464 gst_object_ref (fact);
468 gst_plugin_feature_list_free (encoders);
474 get_decoder (GstCaps * caps)
476 GstElementFactory *fact = get_decoder_factory (caps);
477 GstElement *res = NULL;
480 res = gst_element_factory_create (fact, "internal-decoder");
481 gst_object_unref (fact);
487 get_encoder (GstCaps * caps)
489 GstElementFactory *fact = get_encoder_factory (caps);
490 GstElement *res = NULL;
493 res = gst_element_factory_create (fact, "internal-encoder");
494 gst_object_unref (fact);
500 internal_chain (GstPad * pad, GstBuffer * buf)
502 GstSmartEncoder *smart_encoder =
503 g_object_get_qdata ((GObject *) pad, INTERNAL_ELEMENT);
505 return gst_pad_push (smart_encoder->srcpad, buf);
509 setup_recoder_pipeline (GstSmartEncoder * smart_encoder)
514 if (G_UNLIKELY (smart_encoder->encoder))
517 GST_DEBUG ("Creating internal decoder and encoder");
519 /* Create decoder/encoder */
520 smart_encoder->decoder = get_decoder (GST_PAD_CAPS (smart_encoder->sinkpad));
521 if (G_UNLIKELY (smart_encoder->decoder == NULL))
523 gst_element_set_bus (smart_encoder->decoder, GST_ELEMENT_BUS (smart_encoder));
525 smart_encoder->encoder = get_encoder (GST_PAD_CAPS (smart_encoder->sinkpad));
526 if (G_UNLIKELY (smart_encoder->encoder == NULL))
528 gst_element_set_bus (smart_encoder->encoder, GST_ELEMENT_BUS (smart_encoder));
530 GST_DEBUG ("Creating internal pads");
532 /* Create internal pads */
534 /* Source pad which we'll use to feed data to decoders */
535 smart_encoder->internal_srcpad = gst_pad_new ("internal_src", GST_PAD_SRC);
536 g_object_set_qdata ((GObject *) smart_encoder->internal_srcpad,
537 INTERNAL_ELEMENT, smart_encoder);
538 gst_pad_set_caps (smart_encoder->internal_srcpad,
539 GST_PAD_CAPS (smart_encoder->sinkpad));
540 gst_pad_set_active (smart_encoder->internal_srcpad, TRUE);
542 /* Sink pad which will get the buffers from the encoder.
543 * Note: We don't need an event function since we'll be discarding all
545 smart_encoder->internal_sinkpad = gst_pad_new ("internal_sink", GST_PAD_SINK);
546 g_object_set_qdata ((GObject *) smart_encoder->internal_sinkpad,
547 INTERNAL_ELEMENT, smart_encoder);
548 gst_pad_set_caps (smart_encoder->internal_sinkpad,
549 GST_PAD_CAPS (smart_encoder->sinkpad));
550 gst_pad_set_chain_function (smart_encoder->internal_sinkpad, internal_chain);
551 gst_pad_set_active (smart_encoder->internal_sinkpad, TRUE);
553 GST_DEBUG ("Linking pads to elements");
555 /* Link everything */
556 tmppad = gst_element_get_static_pad (smart_encoder->encoder, "src");
557 if (GST_PAD_LINK_FAILED (gst_pad_link (tmppad,
558 smart_encoder->internal_sinkpad)))
559 goto sinkpad_link_fail;
560 gst_object_unref (tmppad);
562 if (!gst_element_link (smart_encoder->decoder, smart_encoder->encoder))
563 goto encoder_decoder_link_fail;
565 tmppad = gst_element_get_static_pad (smart_encoder->decoder, "sink");
566 if (GST_PAD_LINK_FAILED (gst_pad_link (smart_encoder->internal_srcpad,
568 goto srcpad_link_fail;
569 gst_object_unref (tmppad);
571 GST_DEBUG ("Done creating internal elements/pads");
577 GST_WARNING ("Couldn't find a decoder for %" GST_PTR_FORMAT,
578 GST_PAD_CAPS (smart_encoder->sinkpad));
584 GST_WARNING ("Couldn't find an encoder for %" GST_PTR_FORMAT,
585 GST_PAD_CAPS (smart_encoder->sinkpad));
591 gst_object_unref (tmppad);
592 GST_WARNING ("Couldn't link internal srcpad to decoder");
598 gst_object_unref (tmppad);
599 GST_WARNING ("Couldn't link encoder to internal sinkpad");
603 encoder_decoder_link_fail:
605 GST_WARNING ("Couldn't link decoder to encoder");
610 static GstStateChangeReturn
611 gst_smart_encoder_find_elements (GstSmartEncoder * smart_encoder)
614 GstCaps *tmpl, *st, *res;
615 GstElementFactory *dec, *enc;
616 GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
618 if (G_UNLIKELY (smart_encoder->available_caps))
621 /* Iterate over all pad template caps and see if we have both an
622 * encoder and a decoder for those media types */
623 tmpl = gst_static_pad_template_get_caps (&src_template);
624 res = gst_caps_new_empty ();
625 n = gst_caps_get_size (tmpl);
627 for (i = 0; i < n; i++) {
628 st = gst_caps_copy_nth (tmpl, i);
629 GST_DEBUG_OBJECT (smart_encoder,
630 "Checking for available decoder and encoder for %" GST_PTR_FORMAT, st);
631 if (!(dec = get_decoder_factory (st))) {
635 gst_object_unref (dec);
636 if (!(enc = get_encoder_factory (st))) {
640 gst_object_unref (enc);
641 GST_DEBUG_OBJECT (smart_encoder, "OK");
642 gst_caps_append (res, st);
645 gst_caps_unref (tmpl);
647 if (gst_caps_is_empty (res)) {
648 gst_caps_unref (res);
649 ret = GST_STATE_CHANGE_FAILURE;
651 smart_encoder->available_caps = res;
653 GST_DEBUG_OBJECT (smart_encoder, "Done, available_caps:%" GST_PTR_FORMAT,
654 smart_encoder->available_caps);
660 /******************************************
661 * GstElement vmethod implementations *
662 ******************************************/
664 static GstStateChangeReturn
665 gst_smart_encoder_change_state (GstElement * element, GstStateChange transition)
667 GstSmartEncoder *smart_encoder;
668 GstStateChangeReturn ret;
670 g_return_val_if_fail (GST_IS_SMART_ENCODER (element),
671 GST_STATE_CHANGE_FAILURE);
673 smart_encoder = GST_SMART_ENCODER (element);
675 switch (transition) {
676 case GST_STATE_CHANGE_NULL_TO_READY:
677 /* Figure out which elements are available */
679 gst_smart_encoder_find_elements (smart_encoder)) ==
680 GST_STATE_CHANGE_FAILURE)
688 GST_ELEMENT_CLASS (gst_smart_encoder_parent_class)->change_state (element,
691 switch (transition) {
692 case GST_STATE_CHANGE_PAUSED_TO_READY:
693 smart_encoder_reset (smart_encoder);