2 * Copyright (C) 2008 David Schleef <ds@schleef.org>
3 * Copyright (C) 2011 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>.
4 * Copyright (C) 2011 Nokia Corporation. All rights reserved.
5 * Contact: Stefan Kost <stefan.kost@nokia.com>
6 * Copyright (C) 2012 Collabora Ltd.
7 * Author : Edward Hervey <edward@collabora.com>
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Library General Public License for more details.
19 * You should have received a copy of the GNU Library General Public
20 * License along with this library; if not, write to the
21 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 * Boston, MA 02111-1307, USA.
26 * SECTION:gstvideoencoder
27 * @short_description: Base class for video encoders
30 * This base class is for video encoders turning raw video into
33 * GstVideoEncoder and subclass should cooperate as follows.
36 * <itemizedlist><title>Configuration</title>
38 * Initially, GstVideoEncoder calls @start when the encoder element
39 * is activated, which allows subclass to perform any global setup.
42 * GstVideoEncoder calls @set_format to inform subclass of the format
43 * of input video data that it is about to receive. Subclass should
44 * setup for encoding and configure base class as appropriate
45 * (e.g. latency). While unlikely, it might be called more than once,
46 * if changing input parameters require reconfiguration. Baseclass
47 * will ensure that processing of current configuration is finished.
50 * GstVideoEncoder calls @stop at end of all processing.
56 * <title>Data processing</title>
58 * Base class collects input data and metadata into a frame and hands
59 * this to subclass' @handle_frame.
62 * If codec processing results in encoded data, subclass should call
63 * @gst_video_encoder_finish_frame to have encoded data pushed
67 * If implemented, baseclass calls subclass @pre_push just prior to
68 * pushing to allow subclasses to modify some metadata on the buffer.
69 * If it returns GST_FLOW_OK, the buffer is pushed downstream.
72 * GstVideoEncoderClass will handle both srcpad and sinkpad events.
73 * Sink events will be passed to subclass if @event callback has been
79 * <itemizedlist><title>Shutdown phase</title>
81 * GstVideoEncoder class calls @stop to inform the subclass that data
82 * parsing will be stopped.
88 * Subclass is responsible for providing pad template caps for
89 * source and sink pads. The pads need to be named "sink" and "src". It should
90 * also be able to provide fixed src pad caps in @getcaps by the time it calls
91 * @gst_video_encoder_finish_frame.
93 * Things that subclass need to take care of:
95 * <listitem><para>Provide pad templates</para></listitem>
97 * Provide source pad caps before pushing the first buffer
100 * Accept data in @handle_frame and provide encoded results to
101 * @gst_video_encoder_finish_frame.
113 * * Change _set_output_format() to steal the reference of the provided caps
114 * * Calculate actual latency based on input/output timestamp/frame_number
115 * and if it exceeds the recorded one, save it and emit a GST_MESSAGE_LATENCY
118 /* FIXME 0.11: suppress warnings for deprecated API such as GStaticRecMutex
119 * with newer GLib versions (>= 2.31.0) */
120 #define GLIB_DISABLE_DEPRECATION_WARNINGS
122 #include "gstvideoencoder.h"
123 #include "gstvideoutils.h"
127 GST_DEBUG_CATEGORY (videoencoder_debug);
128 #define GST_CAT_DEFAULT videoencoder_debug
130 #define GST_VIDEO_ENCODER_GET_PRIVATE(obj) \
131 (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_VIDEO_ENCODER, \
132 GstVideoEncoderPrivate))
134 struct _GstVideoEncoderPrivate
136 guint64 presentation_frame_number;
137 int distance_from_sync;
139 /* FIXME : (and introduce a context ?) */
146 GList *current_frame_events;
149 gboolean new_headers; /* Whether new headers were just set */
151 GList *force_key_unit; /* List of pending forced keyunits */
153 guint64 system_frame_number;
155 GList *frames; /* Protected with OBJECT_LOCK */
156 GstVideoCodecState *input_state;
157 GstVideoCodecState *output_state;
158 gboolean output_state_changed;
164 typedef struct _ForcedKeyUnitEvent ForcedKeyUnitEvent;
165 struct _ForcedKeyUnitEvent
167 GstClockTime running_time;
168 gboolean pending; /* TRUE if this was requested already */
169 gboolean all_headers;
174 forced_key_unit_event_free (ForcedKeyUnitEvent * evt)
176 g_slice_free (ForcedKeyUnitEvent, evt);
179 static ForcedKeyUnitEvent *
180 forced_key_unit_event_new (GstClockTime running_time, gboolean all_headers,
183 ForcedKeyUnitEvent *evt = g_slice_new0 (ForcedKeyUnitEvent);
185 evt->running_time = running_time;
186 evt->all_headers = all_headers;
192 static GstElementClass *parent_class = NULL;
193 static void gst_video_encoder_class_init (GstVideoEncoderClass * klass);
194 static void gst_video_encoder_init (GstVideoEncoder * enc,
195 GstVideoEncoderClass * klass);
197 static void gst_video_encoder_finalize (GObject * object);
199 static gboolean gst_video_encoder_setcaps (GstVideoEncoder * enc,
201 static GstCaps *gst_video_encoder_sink_getcaps (GstVideoEncoder * encoder,
203 static gboolean gst_video_encoder_src_event (GstPad * pad, GstObject * parent,
205 static gboolean gst_video_encoder_sink_event (GstPad * pad, GstObject * parent,
207 static GstFlowReturn gst_video_encoder_chain (GstPad * pad, GstObject * parent,
209 static GstStateChangeReturn gst_video_encoder_change_state (GstElement *
210 element, GstStateChange transition);
211 static gboolean gst_video_encoder_sink_query (GstPad * pad, GstObject * parent,
213 static gboolean gst_video_encoder_src_query (GstPad * pad, GstObject * parent,
215 static GstVideoCodecFrame *gst_video_encoder_new_frame (GstVideoEncoder *
216 encoder, GstBuffer * buf, GstClockTime timestamp, GstClockTime duration);
218 /* we can't use G_DEFINE_ABSTRACT_TYPE because we need the klass in the _init
219 * method to get to the padtemplates */
221 gst_video_encoder_get_type (void)
223 static volatile gsize type = 0;
225 if (g_once_init_enter (&type)) {
227 static const GTypeInfo info = {
228 sizeof (GstVideoEncoderClass),
231 (GClassInitFunc) gst_video_encoder_class_init,
234 sizeof (GstVideoEncoder),
236 (GInstanceInitFunc) gst_video_encoder_init,
238 const GInterfaceInfo preset_interface_info = {
239 NULL, /* interface_init */
240 NULL, /* interface_finalize */
241 NULL /* interface_data */
244 _type = g_type_register_static (GST_TYPE_ELEMENT,
245 "GstVideoEncoder", &info, G_TYPE_FLAG_ABSTRACT);
246 g_type_add_interface_static (_type, GST_TYPE_PRESET,
247 &preset_interface_info);
248 g_once_init_leave (&type, _type);
254 gst_video_encoder_class_init (GstVideoEncoderClass * klass)
256 GObjectClass *gobject_class;
257 GstElementClass *gstelement_class;
259 gobject_class = G_OBJECT_CLASS (klass);
260 gstelement_class = GST_ELEMENT_CLASS (klass);
262 GST_DEBUG_CATEGORY_INIT (videoencoder_debug, "videoencoder", 0,
263 "Base Video Encoder");
265 parent_class = g_type_class_peek_parent (klass);
267 g_type_class_add_private (klass, sizeof (GstVideoEncoderPrivate));
269 gobject_class->finalize = gst_video_encoder_finalize;
271 gstelement_class->change_state =
272 GST_DEBUG_FUNCPTR (gst_video_encoder_change_state);
276 gst_video_encoder_reset (GstVideoEncoder * encoder)
278 GstVideoEncoderPrivate *priv = encoder->priv;
281 GST_VIDEO_ENCODER_STREAM_LOCK (encoder);
283 priv->presentation_frame_number = 0;
284 priv->distance_from_sync = 0;
286 g_list_foreach (priv->force_key_unit, (GFunc) forced_key_unit_event_free,
288 g_list_free (priv->force_key_unit);
289 priv->force_key_unit = NULL;
291 priv->drained = TRUE;
292 priv->min_latency = 0;
293 priv->max_latency = 0;
295 g_list_foreach (priv->headers, (GFunc) gst_event_unref, NULL);
296 g_list_free (priv->headers);
297 priv->headers = NULL;
298 priv->new_headers = FALSE;
300 g_list_foreach (priv->current_frame_events, (GFunc) gst_event_unref, NULL);
301 g_list_free (priv->current_frame_events);
302 priv->current_frame_events = NULL;
304 for (g = priv->frames; g; g = g->next) {
305 gst_video_codec_frame_unref ((GstVideoCodecFrame *) g->data);
307 g_list_free (priv->frames);
313 if (priv->input_state)
314 gst_video_codec_state_unref (priv->input_state);
315 priv->input_state = NULL;
316 if (priv->output_state)
317 gst_video_codec_state_unref (priv->output_state);
318 priv->output_state = NULL;
320 GST_VIDEO_ENCODER_STREAM_UNLOCK (encoder);
324 gst_video_encoder_init (GstVideoEncoder * encoder, GstVideoEncoderClass * klass)
326 GstVideoEncoderPrivate *priv;
327 GstPadTemplate *pad_template;
330 GST_DEBUG_OBJECT (encoder, "gst_video_encoder_init");
332 priv = encoder->priv = GST_VIDEO_ENCODER_GET_PRIVATE (encoder);
335 gst_element_class_get_pad_template (GST_ELEMENT_CLASS (klass), "sink");
336 g_return_if_fail (pad_template != NULL);
338 encoder->sinkpad = pad = gst_pad_new_from_template (pad_template, "sink");
340 gst_pad_set_chain_function (pad, GST_DEBUG_FUNCPTR (gst_video_encoder_chain));
341 gst_pad_set_event_function (pad,
342 GST_DEBUG_FUNCPTR (gst_video_encoder_sink_event));
343 gst_pad_set_query_function (pad,
344 GST_DEBUG_FUNCPTR (gst_video_encoder_sink_query));
345 gst_element_add_pad (GST_ELEMENT (encoder), encoder->sinkpad);
348 gst_element_class_get_pad_template (GST_ELEMENT_CLASS (klass), "src");
349 g_return_if_fail (pad_template != NULL);
351 encoder->srcpad = pad = gst_pad_new_from_template (pad_template, "src");
353 gst_pad_set_query_function (pad,
354 GST_DEBUG_FUNCPTR (gst_video_encoder_src_query));
355 gst_pad_set_event_function (pad,
356 GST_DEBUG_FUNCPTR (gst_video_encoder_src_event));
357 gst_element_add_pad (GST_ELEMENT (encoder), encoder->srcpad);
359 gst_segment_init (&encoder->input_segment, GST_FORMAT_TIME);
360 gst_segment_init (&encoder->output_segment, GST_FORMAT_TIME);
362 g_rec_mutex_init (&encoder->stream_lock);
364 priv->at_eos = FALSE;
365 priv->headers = NULL;
366 priv->new_headers = FALSE;
368 gst_video_encoder_reset (encoder);
372 gst_video_encoded_video_convert (gint64 bytes, gint64 time,
373 GstFormat src_format, gint64 src_value, GstFormat * dest_format,
376 gboolean res = FALSE;
378 g_return_val_if_fail (dest_format != NULL, FALSE);
379 g_return_val_if_fail (dest_value != NULL, FALSE);
381 if (G_UNLIKELY (src_format == *dest_format || src_value == 0 ||
384 *dest_value = src_value;
388 if (bytes <= 0 || time <= 0) {
389 GST_DEBUG ("not enough metadata yet to convert");
393 switch (src_format) {
394 case GST_FORMAT_BYTES:
395 switch (*dest_format) {
396 case GST_FORMAT_TIME:
397 *dest_value = gst_util_uint64_scale (src_value, time, bytes);
404 case GST_FORMAT_TIME:
405 switch (*dest_format) {
406 case GST_FORMAT_BYTES:
407 *dest_value = gst_util_uint64_scale (src_value, bytes, time);
415 GST_DEBUG ("unhandled conversion from %d to %d", src_format,
425 * gst_video_encoder_set_headers:
426 * @encoder: a #GstVideoEncoder
427 * @headers: (transfer full) (element-type GstBuffer): a list of #GstBuffer containing the codec header
429 * Set the codec headers to be sent downstream whenever requested.
434 gst_video_encoder_set_headers (GstVideoEncoder * video_encoder, GList * headers)
436 GST_VIDEO_ENCODER_STREAM_LOCK (video_encoder);
438 GST_DEBUG_OBJECT (video_encoder, "new headers %p", headers);
439 if (video_encoder->priv->headers) {
440 g_list_foreach (video_encoder->priv->headers, (GFunc) gst_buffer_unref,
442 g_list_free (video_encoder->priv->headers);
444 video_encoder->priv->headers = headers;
445 video_encoder->priv->new_headers = TRUE;
447 GST_VIDEO_ENCODER_STREAM_UNLOCK (video_encoder);
451 gst_video_encoder_drain (GstVideoEncoder * enc)
453 GstVideoEncoderPrivate *priv;
454 GstVideoEncoderClass *enc_class;
457 enc_class = GST_VIDEO_ENCODER_GET_CLASS (enc);
460 GST_DEBUG_OBJECT (enc, "draining");
463 GST_DEBUG_OBJECT (enc, "already drained");
467 if (enc_class->reset) {
468 GST_DEBUG_OBJECT (enc, "requesting subclass to finish");
469 ret = enc_class->reset (enc, TRUE);
471 /* everything should be away now */
473 /* not fatal/impossible though if subclass/enc eats stuff */
474 g_list_foreach (priv->frames, (GFunc) gst_video_codec_frame_unref, NULL);
475 g_list_free (priv->frames);
482 static GstVideoCodecState *
483 _new_output_state (GstCaps * caps, GstVideoCodecState * reference)
485 GstVideoCodecState *state;
487 state = g_slice_new0 (GstVideoCodecState);
488 state->ref_count = 1;
489 gst_video_info_init (&state->info);
490 gst_video_info_set_format (&state->info, GST_VIDEO_FORMAT_ENCODED, 0, 0);
495 GstVideoInfo *tgt, *ref;
498 ref = &reference->info;
500 /* Copy over extra fields from reference state */
501 tgt->interlace_mode = ref->interlace_mode;
502 tgt->flags = ref->flags;
503 tgt->width = ref->width;
504 tgt->height = ref->height;
505 tgt->chroma_site = ref->chroma_site;
506 tgt->colorimetry = ref->colorimetry;
507 tgt->par_n = ref->par_n;
508 tgt->par_d = ref->par_d;
509 tgt->fps_n = ref->fps_n;
510 tgt->fps_d = ref->fps_d;
516 static GstVideoCodecState *
517 _new_input_state (GstCaps * caps)
519 GstVideoCodecState *state;
521 state = g_slice_new0 (GstVideoCodecState);
522 state->ref_count = 1;
523 gst_video_info_init (&state->info);
524 if (G_UNLIKELY (!gst_video_info_from_caps (&state->info, caps)))
526 state->caps = gst_caps_ref (caps);
532 g_slice_free (GstVideoCodecState, state);
538 gst_video_encoder_setcaps (GstVideoEncoder * encoder, GstCaps * caps)
540 GstVideoEncoderClass *encoder_class;
541 GstVideoCodecState *state;
543 gboolean samecaps = FALSE;
545 encoder_class = GST_VIDEO_ENCODER_GET_CLASS (encoder);
547 /* subclass should do something here ... */
548 g_return_val_if_fail (encoder_class->set_format != NULL, FALSE);
550 GST_DEBUG_OBJECT (encoder, "setcaps %" GST_PTR_FORMAT, caps);
552 state = _new_input_state (caps);
553 if (G_UNLIKELY (!state))
556 GST_VIDEO_ENCODER_STREAM_LOCK (encoder);
558 if (encoder->priv->input_state)
560 gst_video_info_is_equal (&state->info,
561 &encoder->priv->input_state->info);
564 /* arrange draining pending frames */
565 gst_video_encoder_drain (encoder);
567 /* and subclass should be ready to configure format at any time around */
568 ret = encoder_class->set_format (encoder, state);
570 if (encoder->priv->input_state)
571 gst_video_codec_state_unref (encoder->priv->input_state);
572 encoder->priv->input_state = state;
574 gst_video_codec_state_unref (state);
576 /* no need to stir things up */
577 GST_DEBUG_OBJECT (encoder,
578 "new video format identical to configured format");
579 gst_video_codec_state_unref (state);
583 GST_VIDEO_ENCODER_STREAM_UNLOCK (encoder);
586 GST_WARNING_OBJECT (encoder, "rejected caps %" GST_PTR_FORMAT, caps);
588 gst_object_unref (encoder);
594 GST_WARNING_OBJECT (encoder, "Failed to parse caps");
595 gst_object_unref (encoder);
601 * gst_video_encoder_proxy_getcaps:
602 * @enc: a #GstVideoEncoder
603 * @caps: initial caps
605 * Returns caps that express @caps (or sink template caps if @caps == NULL)
606 * restricted to resolution/format/... combinations supported by downstream
607 * elements (e.g. muxers).
609 * Returns: a #GstCaps owned by caller
614 gst_video_encoder_proxy_getcaps (GstVideoEncoder * encoder, GstCaps * caps,
619 GstCaps *fcaps, *filter_caps;
622 /* Allow downstream to specify width/height/framerate/PAR constraints
623 * and forward them upstream for video converters to handle
625 templ_caps = caps ? caps : gst_pad_get_pad_template_caps (encoder->sinkpad);
626 allowed = gst_pad_get_allowed_caps (encoder->srcpad);
628 if (!allowed || gst_caps_is_empty (allowed) || gst_caps_is_any (allowed)) {
633 GST_LOG_OBJECT (encoder, "template caps %" GST_PTR_FORMAT, templ_caps);
634 GST_LOG_OBJECT (encoder, "allowed caps %" GST_PTR_FORMAT, allowed);
636 filter_caps = gst_caps_new_empty ();
638 for (i = 0; i < gst_caps_get_size (templ_caps); i++) {
640 gst_structure_get_name_id (gst_caps_get_structure (templ_caps, i));
642 for (j = 0; j < gst_caps_get_size (allowed); j++) {
643 const GstStructure *allowed_s = gst_caps_get_structure (allowed, j);
647 s = gst_structure_new_id_empty (q_name);
648 if ((val = gst_structure_get_value (allowed_s, "width")))
649 gst_structure_set_value (s, "width", val);
650 if ((val = gst_structure_get_value (allowed_s, "height")))
651 gst_structure_set_value (s, "height", val);
652 if ((val = gst_structure_get_value (allowed_s, "framerate")))
653 gst_structure_set_value (s, "framerate", val);
654 if ((val = gst_structure_get_value (allowed_s, "pixel-aspect-ratio")))
655 gst_structure_set_value (s, "pixel-aspect-ratio", val);
657 filter_caps = gst_caps_merge_structure (filter_caps, s);
661 fcaps = gst_caps_intersect (filter_caps, templ_caps);
662 gst_caps_unref (filter_caps);
663 gst_caps_unref (templ_caps);
666 GST_LOG_OBJECT (encoder, "intersecting with %" GST_PTR_FORMAT, filter);
667 filter_caps = gst_caps_intersect (fcaps, filter);
668 gst_caps_unref (fcaps);
673 gst_caps_replace (&allowed, NULL);
675 GST_LOG_OBJECT (encoder, "proxy caps %" GST_PTR_FORMAT, fcaps);
681 gst_video_encoder_sink_getcaps (GstVideoEncoder * encoder, GstCaps * filter)
683 GstVideoEncoderClass *klass;
686 klass = GST_VIDEO_ENCODER_GET_CLASS (encoder);
689 caps = klass->getcaps (encoder, filter);
691 caps = gst_video_encoder_proxy_getcaps (encoder, NULL, filter);
693 GST_LOG_OBJECT (encoder, "Returning caps %" GST_PTR_FORMAT, caps);
700 gst_video_encoder_sink_query (GstPad * pad, GstObject * parent,
703 GstVideoEncoder *encoder;
704 gboolean res = FALSE;
706 encoder = GST_VIDEO_ENCODER (parent);
708 switch (GST_QUERY_TYPE (query)) {
711 GstCaps *filter, *caps;
713 gst_query_parse_caps (query, &filter);
714 caps = gst_video_encoder_sink_getcaps (encoder, filter);
715 gst_query_set_caps_result (query, caps);
716 gst_caps_unref (caps);
721 res = gst_pad_query_default (pad, parent, query);
728 gst_video_encoder_finalize (GObject * object)
730 GstVideoEncoder *encoder;
732 GST_DEBUG_OBJECT (object, "finalize");
734 encoder = GST_VIDEO_ENCODER (object);
735 if (encoder->priv->headers) {
736 g_list_foreach (encoder->priv->headers, (GFunc) gst_buffer_unref, NULL);
737 g_list_free (encoder->priv->headers);
739 g_rec_mutex_clear (&encoder->stream_lock);
741 G_OBJECT_CLASS (parent_class)->finalize (object);
745 gst_video_encoder_push_event (GstVideoEncoder * encoder, GstEvent * event)
747 switch (GST_EVENT_TYPE (event)) {
748 case GST_EVENT_SEGMENT:
752 GST_VIDEO_ENCODER_STREAM_LOCK (encoder);
754 gst_event_copy_segment (event, &segment);
756 GST_DEBUG_OBJECT (encoder, "segment %" GST_SEGMENT_FORMAT, &segment);
758 if (segment.format != GST_FORMAT_TIME) {
759 GST_DEBUG_OBJECT (encoder, "received non TIME segment");
760 GST_VIDEO_ENCODER_STREAM_UNLOCK (encoder);
764 encoder->output_segment = segment;
765 GST_VIDEO_ENCODER_STREAM_UNLOCK (encoder);
772 return gst_pad_push_event (encoder->srcpad, event);
776 gst_video_encoder_sink_eventfunc (GstVideoEncoder * encoder, GstEvent * event)
778 GstVideoEncoderClass *encoder_class;
779 gboolean ret = FALSE;
781 encoder_class = GST_VIDEO_ENCODER_GET_CLASS (encoder);
783 switch (GST_EVENT_TYPE (event)) {
788 gst_event_parse_caps (event, &caps);
789 ret = gst_video_encoder_setcaps (encoder, caps);
790 gst_event_unref (event);
795 GstFlowReturn flow_ret;
797 GST_VIDEO_ENCODER_STREAM_LOCK (encoder);
798 encoder->priv->at_eos = TRUE;
800 if (encoder_class->finish) {
801 flow_ret = encoder_class->finish (encoder);
803 flow_ret = GST_FLOW_OK;
806 ret = (flow_ret == GST_VIDEO_ENCODER_FLOW_DROPPED);
807 GST_VIDEO_ENCODER_STREAM_UNLOCK (encoder);
810 case GST_EVENT_SEGMENT:
814 GST_VIDEO_ENCODER_STREAM_LOCK (encoder);
816 gst_event_copy_segment (event, &segment);
818 GST_DEBUG_OBJECT (encoder, "segment %" GST_SEGMENT_FORMAT, &segment);
820 if (segment.format != GST_FORMAT_TIME) {
821 GST_DEBUG_OBJECT (encoder, "received non TIME newsegment");
822 GST_VIDEO_ENCODER_STREAM_UNLOCK (encoder);
826 encoder->priv->at_eos = FALSE;
828 encoder->input_segment = segment;
829 GST_VIDEO_ENCODER_STREAM_UNLOCK (encoder);
832 case GST_EVENT_CUSTOM_DOWNSTREAM:
834 if (gst_video_event_is_force_key_unit (event)) {
835 GstClockTime running_time;
836 gboolean all_headers;
839 if (gst_video_event_parse_downstream_force_key_unit (event,
840 NULL, NULL, &running_time, &all_headers, &count)) {
841 ForcedKeyUnitEvent *fevt;
843 GST_OBJECT_LOCK (encoder);
844 fevt = forced_key_unit_event_new (running_time, all_headers, count);
845 encoder->priv->force_key_unit =
846 g_list_append (encoder->priv->force_key_unit, fevt);
847 GST_OBJECT_UNLOCK (encoder);
849 GST_DEBUG_OBJECT (encoder,
850 "force-key-unit event: running-time %" GST_TIME_FORMAT
851 ", all_headers %d, count %u",
852 GST_TIME_ARGS (running_time), all_headers, count);
854 gst_event_unref (event);
867 gst_video_encoder_sink_event (GstPad * pad, GstObject * parent,
870 GstVideoEncoder *enc;
871 GstVideoEncoderClass *klass;
872 gboolean handled = FALSE;
875 enc = GST_VIDEO_ENCODER (parent);
876 klass = GST_VIDEO_ENCODER_GET_CLASS (enc);
878 GST_DEBUG_OBJECT (enc, "received event %d, %s", GST_EVENT_TYPE (event),
879 GST_EVENT_TYPE_NAME (event));
881 if (klass->sink_event)
882 handled = klass->sink_event (enc, event);
885 handled = gst_video_encoder_sink_eventfunc (enc, event);
888 /* Forward non-serialized events and EOS/FLUSH_STOP immediately.
889 * For EOS this is required because no buffer or serialized event
890 * will come after EOS and nothing could trigger another
891 * _finish_frame() call. *
892 * If the subclass handles sending of EOS manually it can return
893 * _DROPPED from ::finish() and all other subclasses should have
894 * decoded/flushed all remaining data before this
896 * For FLUSH_STOP this is required because it is expected
897 * to be forwarded immediately and no buffers are queued anyway.
899 if (!GST_EVENT_IS_SERIALIZED (event)
900 || GST_EVENT_TYPE (event) == GST_EVENT_EOS
901 || GST_EVENT_TYPE (event) == GST_EVENT_FLUSH_STOP) {
902 ret = gst_video_encoder_push_event (enc, event);
904 GST_VIDEO_ENCODER_STREAM_LOCK (enc);
905 enc->priv->current_frame_events =
906 g_list_prepend (enc->priv->current_frame_events, event);
907 GST_VIDEO_ENCODER_STREAM_UNLOCK (enc);
911 GST_DEBUG_OBJECT (enc, "event handled");
917 gst_video_encoder_src_eventfunc (GstVideoEncoder * encoder, GstEvent * event)
919 gboolean handled = FALSE;
921 switch (GST_EVENT_TYPE (event)) {
922 case GST_EVENT_CUSTOM_UPSTREAM:
924 if (gst_video_event_is_force_key_unit (event)) {
925 GstClockTime running_time;
926 gboolean all_headers;
929 if (gst_video_event_parse_upstream_force_key_unit (event,
930 &running_time, &all_headers, &count)) {
931 ForcedKeyUnitEvent *fevt;
933 GST_OBJECT_LOCK (encoder);
934 fevt = forced_key_unit_event_new (running_time, all_headers, count);
935 encoder->priv->force_key_unit =
936 g_list_append (encoder->priv->force_key_unit, fevt);
937 GST_OBJECT_UNLOCK (encoder);
939 GST_DEBUG_OBJECT (encoder,
940 "force-key-unit event: running-time %" GST_TIME_FORMAT
941 ", all_headers %d, count %u",
942 GST_TIME_ARGS (running_time), all_headers, count);
944 gst_event_unref (event);
957 gst_video_encoder_src_event (GstPad * pad, GstObject * parent, GstEvent * event)
959 GstVideoEncoder *encoder;
960 GstVideoEncoderClass *klass;
961 gboolean ret = FALSE;
962 gboolean handled = FALSE;
964 encoder = GST_VIDEO_ENCODER (parent);
965 klass = GST_VIDEO_ENCODER_GET_CLASS (encoder);
967 GST_LOG_OBJECT (encoder, "handling event: %" GST_PTR_FORMAT, event);
969 if (klass->src_event)
970 handled = klass->src_event (encoder, event);
973 handled = gst_video_encoder_src_eventfunc (encoder, event);
976 ret = gst_pad_event_default (pad, parent, event);
982 gst_video_encoder_src_query (GstPad * pad, GstObject * parent, GstQuery * query)
984 GstVideoEncoderPrivate *priv;
985 GstVideoEncoder *enc;
988 enc = GST_VIDEO_ENCODER (parent);
991 GST_LOG_OBJECT (enc, "handling query: %" GST_PTR_FORMAT, query);
993 switch (GST_QUERY_TYPE (query)) {
994 case GST_QUERY_CONVERT:
996 GstFormat src_fmt, dest_fmt;
997 gint64 src_val, dest_val;
999 gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
1001 gst_video_encoded_video_convert (priv->bytes, priv->time, src_fmt,
1002 src_val, &dest_fmt, &dest_val);
1005 gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
1008 case GST_QUERY_LATENCY:
1011 GstClockTime min_latency, max_latency;
1013 res = gst_pad_peer_query (enc->sinkpad, query);
1015 gst_query_parse_latency (query, &live, &min_latency, &max_latency);
1016 GST_DEBUG_OBJECT (enc, "Peer latency: live %d, min %"
1017 GST_TIME_FORMAT " max %" GST_TIME_FORMAT, live,
1018 GST_TIME_ARGS (min_latency), GST_TIME_ARGS (max_latency));
1020 GST_OBJECT_LOCK (enc);
1021 min_latency += priv->min_latency;
1022 if (max_latency != GST_CLOCK_TIME_NONE) {
1023 max_latency += priv->max_latency;
1025 GST_OBJECT_UNLOCK (enc);
1027 gst_query_set_latency (query, live, min_latency, max_latency);
1032 res = gst_pad_query_default (pad, parent, query);
1037 GST_DEBUG_OBJECT (enc, "query failed");
1041 static GstVideoCodecFrame *
1042 gst_video_encoder_new_frame (GstVideoEncoder * encoder, GstBuffer * buf,
1043 GstClockTime timestamp, GstClockTime duration)
1045 GstVideoEncoderPrivate *priv = encoder->priv;
1046 GstVideoCodecFrame *frame;
1048 frame = g_slice_new0 (GstVideoCodecFrame);
1050 frame->ref_count = 1;
1052 GST_VIDEO_ENCODER_STREAM_LOCK (encoder);
1053 frame->system_frame_number = priv->system_frame_number;
1054 priv->system_frame_number++;
1056 frame->presentation_frame_number = priv->presentation_frame_number;
1057 priv->presentation_frame_number++;
1058 GST_VIDEO_ENCODER_STREAM_UNLOCK (encoder);
1060 frame->events = priv->current_frame_events;
1061 priv->current_frame_events = NULL;
1062 frame->input_buffer = buf;
1063 frame->pts = timestamp;
1064 frame->duration = duration;
1070 static GstFlowReturn
1071 gst_video_encoder_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
1073 GstVideoEncoder *encoder;
1074 GstVideoEncoderPrivate *priv;
1075 GstVideoEncoderClass *klass;
1076 GstVideoCodecFrame *frame;
1077 GstFlowReturn ret = GST_FLOW_OK;
1078 guint64 start, stop = GST_CLOCK_TIME_NONE, cstart, cstop;
1080 encoder = GST_VIDEO_ENCODER (parent);
1081 priv = encoder->priv;
1082 klass = GST_VIDEO_ENCODER_GET_CLASS (encoder);
1084 g_return_val_if_fail (klass->handle_frame != NULL, GST_FLOW_ERROR);
1086 GST_VIDEO_ENCODER_STREAM_LOCK (encoder);
1088 start = GST_BUFFER_TIMESTAMP (buf);
1089 if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_DURATION (buf)))
1090 stop = start + GST_BUFFER_DURATION (buf);
1092 GST_LOG_OBJECT (encoder,
1093 "received buffer of size %d with ts %" GST_TIME_FORMAT
1094 ", duration %" GST_TIME_FORMAT, gst_buffer_get_size (buf),
1095 GST_TIME_ARGS (start), GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));
1102 /* Drop buffers outside of segment */
1103 if (!gst_segment_clip (&encoder->output_segment,
1104 GST_FORMAT_TIME, start, stop, &cstart, &cstop)) {
1105 GST_DEBUG_OBJECT (encoder, "clipping to segment dropped frame");
1106 gst_buffer_unref (buf);
1110 frame = gst_video_encoder_new_frame (encoder, buf, cstart, cstop - cstart);
1112 GST_OBJECT_LOCK (encoder);
1113 if (priv->force_key_unit) {
1114 ForcedKeyUnitEvent *fevt = NULL;
1115 GstClockTime running_time;
1119 gst_segment_to_running_time (&encoder->output_segment, GST_FORMAT_TIME,
1120 GST_BUFFER_TIMESTAMP (buf));
1122 for (l = priv->force_key_unit; l; l = l->next) {
1123 ForcedKeyUnitEvent *tmp = l->data;
1125 /* Skip pending keyunits */
1129 /* Simple case, keyunit ASAP */
1130 if (tmp->running_time == GST_CLOCK_TIME_NONE) {
1135 /* Event for before this frame */
1136 if (tmp->running_time <= running_time) {
1143 GST_DEBUG_OBJECT (encoder,
1144 "Forcing a key unit at running time %" GST_TIME_FORMAT,
1145 GST_TIME_ARGS (running_time));
1146 GST_VIDEO_CODEC_FRAME_SET_FORCE_KEYFRAME (frame);
1147 if (fevt->all_headers)
1148 GST_VIDEO_CODEC_FRAME_SET_FORCE_KEYFRAME_HEADERS (frame);
1149 fevt->pending = TRUE;
1152 GST_OBJECT_UNLOCK (encoder);
1154 priv->frames = g_list_append (priv->frames, frame);
1156 /* new data, more finish needed */
1157 priv->drained = FALSE;
1159 GST_LOG_OBJECT (encoder, "passing frame pfn %d to subclass",
1160 frame->presentation_frame_number);
1162 ret = klass->handle_frame (encoder, frame);
1165 GST_VIDEO_ENCODER_STREAM_UNLOCK (encoder);
1170 static GstStateChangeReturn
1171 gst_video_encoder_change_state (GstElement * element, GstStateChange transition)
1173 GstVideoEncoder *encoder;
1174 GstVideoEncoderClass *encoder_class;
1175 GstStateChangeReturn ret;
1177 encoder = GST_VIDEO_ENCODER (element);
1178 encoder_class = GST_VIDEO_ENCODER_GET_CLASS (element);
1180 switch (transition) {
1181 case GST_STATE_CHANGE_NULL_TO_READY:
1182 /* open device/library if needed */
1183 if (encoder_class->open && !encoder_class->open (encoder))
1186 case GST_STATE_CHANGE_READY_TO_PAUSED:
1187 /* Initialize device/library if needed */
1188 if (encoder_class->start && !encoder_class->start (encoder))
1195 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1197 switch (transition) {
1198 case GST_STATE_CHANGE_PAUSED_TO_READY:
1199 gst_video_encoder_reset (encoder);
1200 if (encoder_class->stop && !encoder_class->stop (encoder))
1203 case GST_STATE_CHANGE_READY_TO_NULL:
1204 /* close device/library if needed */
1205 if (encoder_class->close && !encoder_class->close (encoder))
1218 GST_ELEMENT_ERROR (encoder, LIBRARY, INIT, (NULL),
1219 ("Failed to open encoder"));
1220 return GST_STATE_CHANGE_FAILURE;
1225 GST_ELEMENT_ERROR (encoder, LIBRARY, INIT, (NULL),
1226 ("Failed to start encoder"));
1227 return GST_STATE_CHANGE_FAILURE;
1232 GST_ELEMENT_ERROR (encoder, LIBRARY, INIT, (NULL),
1233 ("Failed to stop encoder"));
1234 return GST_STATE_CHANGE_FAILURE;
1239 GST_ELEMENT_ERROR (encoder, LIBRARY, INIT, (NULL),
1240 ("Failed to close encoder"));
1241 return GST_STATE_CHANGE_FAILURE;
1246 gst_video_encoder_set_src_caps (GstVideoEncoder * encoder)
1249 GstVideoCodecState *state = encoder->priv->output_state;
1250 GstVideoInfo *info = &state->info;
1252 g_return_val_if_fail (state->caps != NULL, FALSE);
1254 if (encoder->priv->output_state_changed) {
1255 state->caps = gst_caps_make_writable (state->caps);
1258 gst_caps_set_simple (state->caps, "width", G_TYPE_INT, info->width,
1259 "height", G_TYPE_INT, info->height,
1260 "pixel-aspect-ratio", GST_TYPE_FRACTION,
1261 info->par_n, info->par_d, NULL);
1262 if (info->flags & GST_VIDEO_FLAG_VARIABLE_FPS && info->fps_n != 0) {
1263 /* variable fps with a max-framerate */
1264 gst_caps_set_simple (state->caps, "framerate", GST_TYPE_FRACTION, 0, 1,
1265 "max-framerate", GST_TYPE_FRACTION, info->fps_n, info->fps_d, NULL);
1267 /* no variable fps or no max-framerate */
1268 gst_caps_set_simple (state->caps, "framerate", GST_TYPE_FRACTION,
1269 info->fps_n, info->fps_d, NULL);
1271 if (state->codec_data)
1272 gst_caps_set_simple (state->caps, "codec_data", GST_TYPE_BUFFER,
1273 state->codec_data, NULL);
1274 encoder->priv->output_state_changed = FALSE;
1277 ret = gst_pad_set_caps (encoder->srcpad, state->caps);
1283 * gst_video_encoder_finish_frame:
1284 * @encoder: a #GstVideoEncoder
1285 * @frame: (transfer full): an encoded #GstVideoCodecFrame
1287 * @frame must have a valid encoded data buffer, whose metadata fields
1288 * are then appropriately set according to frame data or no buffer at
1289 * all if the frame should be dropped.
1290 * It is subsequently pushed downstream or provided to @pre_push.
1291 * In any case, the frame is considered finished and released.
1293 * Returns: a #GstFlowReturn resulting from sending data downstream
1298 gst_video_encoder_finish_frame (GstVideoEncoder * encoder,
1299 GstVideoCodecFrame * frame)
1301 GstVideoEncoderPrivate *priv = encoder->priv;
1302 GstFlowReturn ret = GST_FLOW_OK;
1303 GstVideoEncoderClass *encoder_class;
1305 gboolean send_headers = FALSE;
1306 gboolean discont = (frame->presentation_frame_number == 0);
1308 encoder_class = GST_VIDEO_ENCODER_GET_CLASS (encoder);
1310 GST_LOG_OBJECT (encoder,
1311 "finish frame fpn %d", frame->presentation_frame_number);
1313 GST_VIDEO_ENCODER_STREAM_LOCK (encoder);
1315 if (G_UNLIKELY (priv->output_state_changed))
1316 gst_video_encoder_set_src_caps (encoder);
1318 if (G_UNLIKELY (priv->output_state == NULL))
1319 goto no_output_state;
1321 /* Push all pending events that arrived before this frame */
1322 for (l = priv->frames; l; l = l->next) {
1323 GstVideoCodecFrame *tmp = l->data;
1328 for (k = g_list_last (tmp->events); k; k = k->prev)
1329 gst_video_encoder_push_event (encoder, k->data);
1330 g_list_free (tmp->events);
1338 /* no buffer data means this frame is skipped/dropped */
1339 if (!frame->output_buffer) {
1340 GST_DEBUG_OBJECT (encoder, "skipping frame %" GST_TIME_FORMAT,
1341 GST_TIME_ARGS (frame->pts));
1345 if (GST_VIDEO_CODEC_FRAME_IS_SYNC_POINT (frame) && priv->force_key_unit) {
1346 GstClockTime stream_time, running_time;
1348 ForcedKeyUnitEvent *fevt = NULL;
1352 gst_segment_to_running_time (&encoder->output_segment, GST_FORMAT_TIME,
1355 GST_OBJECT_LOCK (encoder);
1356 for (l = priv->force_key_unit; l; l = l->next) {
1357 ForcedKeyUnitEvent *tmp = l->data;
1359 /* Skip non-pending keyunits */
1363 /* Simple case, keyunit ASAP */
1364 if (tmp->running_time == GST_CLOCK_TIME_NONE) {
1369 /* Event for before this frame */
1370 if (tmp->running_time <= running_time) {
1377 priv->force_key_unit = g_list_remove (priv->force_key_unit, fevt);
1379 GST_OBJECT_UNLOCK (encoder);
1383 gst_segment_to_stream_time (&encoder->output_segment, GST_FORMAT_TIME,
1386 ev = gst_video_event_new_downstream_force_key_unit
1387 (frame->pts, stream_time, running_time,
1388 fevt->all_headers, fevt->count);
1390 gst_video_encoder_push_event (encoder, ev);
1392 if (fevt->all_headers)
1393 send_headers = TRUE;
1395 GST_DEBUG_OBJECT (encoder,
1396 "Forced key unit: running-time %" GST_TIME_FORMAT
1397 ", all_headers %d, count %u",
1398 GST_TIME_ARGS (running_time), fevt->all_headers, fevt->count);
1399 forced_key_unit_event_free (fevt);
1403 if (GST_VIDEO_CODEC_FRAME_IS_SYNC_POINT (frame)) {
1404 priv->distance_from_sync = 0;
1405 GST_BUFFER_FLAG_UNSET (frame->output_buffer, GST_BUFFER_FLAG_DELTA_UNIT);
1406 /* For keyframes, DTS = PTS */
1407 frame->dts = frame->pts;
1409 GST_BUFFER_FLAG_SET (frame->output_buffer, GST_BUFFER_FLAG_DELTA_UNIT);
1412 frame->distance_from_sync = priv->distance_from_sync;
1413 priv->distance_from_sync++;
1415 GST_BUFFER_TIMESTAMP (frame->output_buffer) = frame->pts;
1416 GST_BUFFER_DURATION (frame->output_buffer) = frame->duration;
1418 /* update rate estimate */
1419 priv->bytes += gst_buffer_get_size (frame->output_buffer);
1420 if (GST_CLOCK_TIME_IS_VALID (frame->duration)) {
1421 priv->time += frame->duration;
1423 /* better none than nothing valid */
1424 priv->time = GST_CLOCK_TIME_NONE;
1427 if (G_UNLIKELY (send_headers || priv->new_headers)) {
1428 GList *tmp, *copy = NULL;
1430 GST_DEBUG_OBJECT (encoder, "Sending headers");
1432 /* First make all buffers metadata-writable */
1433 for (tmp = priv->headers; tmp; tmp = tmp->next) {
1434 GstBuffer *tmpbuf = GST_BUFFER (tmp->data);
1436 copy = g_list_append (copy, gst_buffer_make_writable (tmpbuf));
1438 g_list_free (priv->headers);
1439 priv->headers = copy;
1441 for (tmp = priv->headers; tmp; tmp = tmp->next) {
1442 GstBuffer *tmpbuf = GST_BUFFER (tmp->data);
1444 gst_buffer_ref (tmpbuf);
1445 priv->bytes += gst_buffer_get_size (tmpbuf);
1446 if (G_UNLIKELY (discont)) {
1447 GST_LOG_OBJECT (encoder, "marking discont");
1448 GST_BUFFER_FLAG_SET (tmpbuf, GST_BUFFER_FLAG_DISCONT);
1452 gst_pad_push (encoder->srcpad, tmpbuf);
1454 priv->new_headers = FALSE;
1457 if (G_UNLIKELY (discont)) {
1458 GST_LOG_OBJECT (encoder, "marking discont");
1459 GST_BUFFER_FLAG_SET (frame->output_buffer, GST_BUFFER_FLAG_DISCONT);
1462 if (encoder_class->pre_push)
1463 ret = encoder_class->pre_push (encoder, frame);
1465 if (ret == GST_FLOW_OK)
1466 ret = gst_pad_push (encoder->srcpad, frame->output_buffer);
1468 frame->output_buffer = NULL;
1472 priv->frames = g_list_remove (priv->frames, frame);
1474 gst_video_codec_frame_unref (frame);
1476 GST_VIDEO_ENCODER_STREAM_UNLOCK (encoder);
1483 GST_VIDEO_ENCODER_STREAM_UNLOCK (encoder);
1484 GST_ERROR_OBJECT (encoder, "Output state was not configured");
1485 return GST_FLOW_ERROR;
1490 * gst_video_encoder_get_output_state:
1491 * @encoder: a #GstVideoEncoder
1493 * Get the current #GstVideoCodecState
1495 * Returns: (transfer full): #GstVideoCodecState describing format of video data.
1499 GstVideoCodecState *
1500 gst_video_encoder_get_output_state (GstVideoEncoder * encoder)
1502 GstVideoCodecState *state;
1504 GST_VIDEO_ENCODER_STREAM_LOCK (encoder);
1505 state = gst_video_codec_state_ref (encoder->priv->output_state);
1506 GST_VIDEO_ENCODER_STREAM_UNLOCK (encoder);
1512 * gst_video_encoder_set_output_state:
1513 * @encoder: a #GstVideoEncoder
1514 * @caps: (transfer full): the #GstCaps to use for the output
1515 * @reference: (allow-none) (transfer none): An optional reference @GstVideoCodecState
1517 * Creates a new #GstVideoCodecState with the specified caps as the output state
1519 * Any previously set output state on @decoder will be replaced by the newly
1522 * The specified @caps should not contain any resolution, pixel-aspect-ratio,
1523 * framerate, codec-data, .... Those should be specified instead in the returned
1524 * #GstVideoCodecState.
1526 * If the subclass wishes to copy over existing fields (like pixel aspect ratio,
1527 * or framerate) from an existing #GstVideoCodecState, it can be provided as a
1530 * If the subclass wishes to override some fields from the output state (like
1531 * pixel-aspect-ratio or framerate) it can do so on the returned #GstVideoCodecState.
1533 * The new output state will only take effect (set on pads and buffers) starting
1534 * from the next call to #gst_video_encoder_finish_frame().
1536 * Returns: (transfer full): the newly configured output state.
1540 GstVideoCodecState *
1541 gst_video_encoder_set_output_state (GstVideoEncoder * encoder, GstCaps * caps,
1542 GstVideoCodecState * reference)
1544 GstVideoEncoderPrivate *priv = encoder->priv;
1545 GstVideoCodecState *state;
1547 g_return_val_if_fail (caps != NULL, NULL);
1549 state = _new_output_state (caps, reference);
1551 GST_VIDEO_ENCODER_STREAM_LOCK (encoder);
1552 if (priv->output_state)
1553 gst_video_codec_state_unref (priv->output_state);
1554 priv->output_state = gst_video_codec_state_ref (state);
1556 priv->output_state_changed = TRUE;
1557 GST_VIDEO_ENCODER_STREAM_UNLOCK (encoder);
1563 * gst_video_encoder_set_latency:
1564 * @encoder: a #GstVideoEncoder
1565 * @min_latency: minimum latency
1566 * @max_latency: maximum latency
1568 * Informs baseclass of encoding latency.
1573 gst_video_encoder_set_latency (GstVideoEncoder * encoder,
1574 GstClockTime min_latency, GstClockTime max_latency)
1576 g_return_if_fail (GST_CLOCK_TIME_IS_VALID (min_latency));
1577 g_return_if_fail (max_latency >= min_latency);
1579 GST_OBJECT_LOCK (encoder);
1580 encoder->priv->min_latency = min_latency;
1581 encoder->priv->max_latency = max_latency;
1582 GST_OBJECT_UNLOCK (encoder);
1584 gst_element_post_message (GST_ELEMENT_CAST (encoder),
1585 gst_message_new_latency (GST_OBJECT_CAST (encoder)));
1589 * gst_video_encoder_get_latency:
1590 * @encoder: a #GstVideoEncoder
1591 * @min_latency: (out) (allow-none): the configured minimum latency
1592 * @max_latency: (out) (allow-none): the configured maximum latency
1594 * Returns the configured encoding latency.
1599 gst_video_encoder_get_latency (GstVideoEncoder * encoder,
1600 GstClockTime * min_latency, GstClockTime * max_latency)
1602 GST_OBJECT_LOCK (encoder);
1604 *min_latency = encoder->priv->min_latency;
1606 *max_latency = encoder->priv->max_latency;
1607 GST_OBJECT_UNLOCK (encoder);
1611 * gst_video_encoder_get_oldest_frame:
1612 * @encoder: a #GstVideoEncoder
1614 * Get the oldest unfinished pending #GstVideoCodecFrame
1616 * Returns: oldest unfinished pending #GstVideoCodecFrame
1620 GstVideoCodecFrame *
1621 gst_video_encoder_get_oldest_frame (GstVideoEncoder * encoder)
1625 GST_VIDEO_ENCODER_STREAM_LOCK (encoder);
1626 g = encoder->priv->frames;
1627 GST_VIDEO_ENCODER_STREAM_UNLOCK (encoder);
1631 return (GstVideoCodecFrame *) (g->data);
1635 * gst_video_encoder_get_frame:
1636 * @encoder: a #GstVideoEnccoder
1637 * @frame_number: system_frame_number of a frame
1639 * Get a pending unfinished #GstVideoCodecFrame
1641 * Returns: (transfer none): pending unfinished #GstVideoCodecFrame identified by @frame_number.
1645 GstVideoCodecFrame *
1646 gst_video_encoder_get_frame (GstVideoEncoder * encoder, int frame_number)
1649 GstVideoCodecFrame *frame = NULL;
1651 GST_DEBUG_OBJECT (encoder, "frame_number : %d", frame_number);
1653 GST_VIDEO_ENCODER_STREAM_LOCK (encoder);
1654 for (g = encoder->priv->frames; g; g = g->next) {
1655 GstVideoCodecFrame *tmp = g->data;
1657 if (tmp->system_frame_number == frame_number) {
1662 GST_VIDEO_ENCODER_STREAM_UNLOCK (encoder);