diff options
author | David Schleef <ds@schleef.org> | 2010-06-01 15:54:51 -0700 |
---|---|---|
committer | David Schleef <ds@schleef.org> | 2010-06-02 00:01:10 -0700 |
commit | bdb5926cda263f185f85a5fad2c7a1d42461dc26 (patch) | |
tree | 92393a17467733c2592349711acd0a58cdddce06 /gst-libs | |
parent | 937b8848a694baed40f4c6b9ecf9eb5f25e0727b (diff) | |
download | gstreamer-plugins-bad-bdb5926cda263f185f85a5fad2c7a1d42461dc26.tar.gz |
basevideo: Move base video from vp8 to gst-libs
Diffstat (limited to 'gst-libs')
-rw-r--r-- | gst-libs/gst/video/gstbasevideocodec.c | 13 | ||||
-rw-r--r-- | gst-libs/gst/video/gstbasevideocodec.h | 5 | ||||
-rw-r--r-- | gst-libs/gst/video/gstbasevideodecoder.c | 685 | ||||
-rw-r--r-- | gst-libs/gst/video/gstbasevideodecoder.h | 40 | ||||
-rw-r--r-- | gst-libs/gst/video/gstbasevideoencoder.c | 105 | ||||
-rw-r--r-- | gst-libs/gst/video/gstbasevideoencoder.h | 11 | ||||
-rw-r--r-- | gst-libs/gst/video/gstbasevideoparse.c | 26 | ||||
-rw-r--r-- | gst-libs/gst/video/gstbasevideoparse.h | 6 | ||||
-rw-r--r-- | gst-libs/gst/video/gstbasevideoutils.c | 138 | ||||
-rw-r--r-- | gst-libs/gst/video/gstbasevideoutils.h | 23 |
10 files changed, 705 insertions, 347 deletions
diff --git a/gst-libs/gst/video/gstbasevideocodec.c b/gst-libs/gst/video/gstbasevideocodec.c index 9cddc3bf4..75d0381e1 100644 --- a/gst-libs/gst/video/gstbasevideocodec.c +++ b/gst-libs/gst/video/gstbasevideocodec.c @@ -42,8 +42,15 @@ enum static void gst_base_video_codec_finalize (GObject * object); +//static const GstQueryType *gst_base_video_codec_get_query_types (GstPad *pad); +//static gboolean gst_base_video_codec_src_query (GstPad *pad, GstQuery *query); +//static gboolean gst_base_video_codec_sink_query (GstPad *pad, GstQuery *query); +//static gboolean gst_base_video_codec_src_event (GstPad *pad, GstEvent *event); +//static gboolean gst_base_video_codec_sink_event (GstPad *pad, GstEvent *event); static GstStateChangeReturn gst_base_video_codec_change_state (GstElement * element, GstStateChange transition); +//static GstFlowReturn gst_base_video_codec_push_all (GstBaseVideoCodec *base_video_codec, +// gboolean at_eos); GST_BOILERPLATE (GstBaseVideoCodec, gst_base_video_codec, GstElement, @@ -52,7 +59,7 @@ GST_BOILERPLATE (GstBaseVideoCodec, gst_base_video_codec, GstElement, static void gst_base_video_codec_base_init (gpointer g_class) { - GST_DEBUG_CATEGORY_INIT (basevideo_debug, "basevideo", 0, + GST_DEBUG_CATEGORY_INIT (basevideo_debug, "vp8basevideo", 0, "Base Video Classes"); } @@ -84,6 +91,8 @@ gst_base_video_codec_init (GstBaseVideoCodec * base_video_codec, g_return_if_fail (pad_template != NULL); base_video_codec->sinkpad = gst_pad_new_from_template (pad_template, "sink"); + //gst_pad_set_query_function (base_video_codec->sinkpad, + // gst_base_video_codec_sink_query); gst_element_add_pad (GST_ELEMENT (base_video_codec), base_video_codec->sinkpad); @@ -92,7 +101,6 @@ gst_base_video_codec_init (GstBaseVideoCodec * base_video_codec, g_return_if_fail (pad_template != NULL); base_video_codec->srcpad = gst_pad_new_from_template (pad_template, "src"); - gst_pad_use_fixed_caps (base_video_codec->srcpad); gst_element_add_pad (GST_ELEMENT (base_video_codec), base_video_codec->srcpad); @@ -108,6 +116,7 @@ gst_base_video_codec_reset (GstBaseVideoCodec * base_video_codec) base_video_codec->system_frame_number = 0; + //gst_segment_init (&base_video_codec->state.segment, GST_FORMAT_TIME); gst_adapter_clear (base_video_codec->input_adapter); gst_adapter_clear (base_video_codec->output_adapter); diff --git a/gst-libs/gst/video/gstbasevideocodec.h b/gst-libs/gst/video/gstbasevideocodec.h index b6acf62ee..f4a1cf95b 100644 --- a/gst-libs/gst/video/gstbasevideocodec.h +++ b/gst-libs/gst/video/gstbasevideocodec.h @@ -20,11 +20,6 @@ #ifndef _GST_BASE_VIDEO_CODEC_H_ #define _GST_BASE_VIDEO_CODEC_H_ -#ifndef GST_USE_UNSTABLE_API -#warning "GstBaseVideoCodec is unstable API and may change in future." -#warning "You can define GST_USE_UNSTABLE_API to avoid this warning." -#endif - #include <gst/gst.h> #include <gst/video/gstbasevideoutils.h> diff --git a/gst-libs/gst/video/gstbasevideodecoder.c b/gst-libs/gst/video/gstbasevideodecoder.c index 3d736dd06..b34820eb3 100644 --- a/gst-libs/gst/video/gstbasevideodecoder.c +++ b/gst-libs/gst/video/gstbasevideodecoder.c @@ -30,8 +30,6 @@ GST_DEBUG_CATEGORY_EXTERN (basevideo_debug); static void gst_base_video_decoder_finalize (GObject * object); -static gboolean gst_base_video_decoder_sink_activate_push (GstPad * pad, - gboolean active); static gboolean gst_base_video_decoder_sink_setcaps (GstPad * pad, GstCaps * caps); static gboolean gst_base_video_decoder_sink_event (GstPad * pad, @@ -42,6 +40,7 @@ static GstFlowReturn gst_base_video_decoder_chain (GstPad * pad, GstBuffer * buf); static gboolean gst_base_video_decoder_sink_query (GstPad * pad, GstQuery * query); +//static GstFlowReturn gst_base_video_decoder_process (GstBaseVideoDecoder *base_video_decoder); static GstStateChangeReturn gst_base_video_decoder_change_state (GstElement * element, GstStateChange transition); static const GstQueryType *gst_base_video_decoder_get_query_types (GstPad * @@ -54,12 +53,17 @@ static gboolean gst_base_video_decoder_src_convert (GstPad * pad, static void gst_base_video_decoder_reset (GstBaseVideoDecoder * base_video_decoder); +static GstFlowReturn +gst_base_video_decoder_have_frame_2 (GstBaseVideoDecoder * base_video_decoder); + static guint64 gst_base_video_decoder_get_timestamp (GstBaseVideoDecoder * base_video_decoder, int picture_number); static guint64 gst_base_video_decoder_get_field_timestamp (GstBaseVideoDecoder * base_video_decoder, int field_offset); +static guint64 gst_base_video_decoder_get_field_duration (GstBaseVideoDecoder * + base_video_decoder, int n_fields); static GstVideoFrame *gst_base_video_decoder_new_frame (GstBaseVideoDecoder * base_video_decoder); static void gst_base_video_decoder_free_frame (GstVideoFrame * frame); @@ -99,8 +103,6 @@ gst_base_video_decoder_init (GstBaseVideoDecoder * base_video_decoder, pad = GST_BASE_VIDEO_CODEC_SINK_PAD (base_video_decoder); - gst_pad_set_activatepush_function (pad, - gst_base_video_decoder_sink_activate_push); gst_pad_set_chain_function (pad, gst_base_video_decoder_chain); gst_pad_set_event_function (pad, gst_base_video_decoder_sink_event); gst_pad_set_setcaps_function (pad, gst_base_video_decoder_sink_setcaps); @@ -111,11 +113,12 @@ gst_base_video_decoder_init (GstBaseVideoDecoder * base_video_decoder, gst_pad_set_event_function (pad, gst_base_video_decoder_src_event); gst_pad_set_query_type_function (pad, gst_base_video_decoder_get_query_types); gst_pad_set_query_function (pad, gst_base_video_decoder_src_query); + gst_pad_use_fixed_caps (pad); base_video_decoder->input_adapter = gst_adapter_new (); base_video_decoder->output_adapter = gst_adapter_new (); - gst_segment_init (&base_video_decoder->state.segment, GST_FORMAT_TIME); + gst_segment_init (&base_video_decoder->segment, GST_FORMAT_TIME); gst_base_video_decoder_reset (base_video_decoder); base_video_decoder->current_frame = @@ -125,57 +128,14 @@ gst_base_video_decoder_init (GstBaseVideoDecoder * base_video_decoder, } static gboolean -gst_base_video_decoder_sink_activate (GstBaseVideoDecoder * decoder, - gboolean active) -{ - GstBaseVideoDecoderClass *klass; - gboolean result = FALSE; - - GST_DEBUG_OBJECT (decoder, "activate"); - - klass = GST_BASE_VIDEO_DECODER_GET_CLASS (decoder); - - if (active) { - if (klass->start) - result = klass->start (decoder); - } else { - /* We must make sure streaming has finished before resetting things - * and calling the ::stop vfunc */ - GST_PAD_STREAM_LOCK (GST_BASE_VIDEO_CODEC_SINK_PAD (decoder)); - GST_PAD_STREAM_UNLOCK (GST_BASE_VIDEO_CODEC_SINK_PAD (decoder)); - - if (klass->stop) - result = klass->stop (decoder); - } - - GST_DEBUG_OBJECT (decoder, "activate: %d", result); - - return result; -} - -static gboolean -gst_base_video_decoder_sink_activate_push (GstPad * pad, gboolean active) -{ - gboolean result = TRUE; - GstBaseVideoDecoder *base_video_decoder; - - base_video_decoder = GST_BASE_VIDEO_DECODER (gst_pad_get_parent (pad)); - - result = gst_base_video_decoder_sink_activate (base_video_decoder, active); - - gst_object_unref (base_video_decoder); - - return result; -} - -static gboolean gst_base_video_decoder_sink_setcaps (GstPad * pad, GstCaps * caps) { GstBaseVideoDecoder *base_video_decoder; GstBaseVideoDecoderClass *base_video_decoder_class; GstStructure *structure; const GValue *codec_data; - gboolean res = TRUE; + GstVideoState *state; + gboolean ret = TRUE; base_video_decoder = GST_BASE_VIDEO_DECODER (gst_pad_get_parent (pad)); base_video_decoder_class = @@ -183,24 +143,40 @@ gst_base_video_decoder_sink_setcaps (GstPad * pad, GstCaps * caps) GST_DEBUG ("setcaps %" GST_PTR_FORMAT, caps); - if (base_video_decoder->codec_data) { - gst_buffer_unref (base_video_decoder->codec_data); - base_video_decoder->codec_data = NULL; + state = &base_video_decoder->state; + + if (state->codec_data) { + gst_buffer_unref (state->codec_data); } + memset (state, 0, sizeof (GstVideoState)); structure = gst_caps_get_structure (caps, 0); + gst_video_format_parse_caps (caps, NULL, &state->width, &state->height); + gst_video_parse_caps_framerate (caps, &state->fps_n, &state->fps_d); + gst_video_parse_caps_pixel_aspect_ratio (caps, &state->par_n, &state->par_d); + +#if 0 + /* requires 0.10.23 */ + state->have_interlaced = + gst_video_format_parse_caps_interlaced (caps, &state->interlaced); +#else + state->have_interlaced = gst_structure_get_boolean (structure, + "interlaced", &state->interlaced); +#endif + codec_data = gst_structure_get_value (structure, "codec_data"); if (codec_data && G_VALUE_TYPE (codec_data) == GST_TYPE_BUFFER) { - base_video_decoder->codec_data = gst_value_get_buffer (codec_data); + state->codec_data = gst_value_get_buffer (codec_data); } - if (base_video_decoder_class->set_sink_caps) - res = base_video_decoder_class->set_sink_caps (base_video_decoder, caps); + if (base_video_decoder_class->start) { + ret = base_video_decoder_class->start (base_video_decoder); + } g_object_unref (base_video_decoder); - return res; + return ret; } static void @@ -215,6 +191,15 @@ gst_base_video_decoder_finalize (GObject * object) gst_base_video_decoder_reset (base_video_decoder); + if (base_video_decoder->input_adapter) { + g_object_unref (base_video_decoder->input_adapter); + base_video_decoder->input_adapter = NULL; + } + if (base_video_decoder->output_adapter) { + g_object_unref (base_video_decoder->output_adapter); + base_video_decoder->output_adapter = NULL; + } + GST_DEBUG_OBJECT (object, "finalize"); G_OBJECT_CLASS (parent_class)->finalize (object); @@ -234,18 +219,17 @@ gst_base_video_decoder_sink_event (GstPad * pad, GstEvent * event) switch (GST_EVENT_TYPE (event)) { case GST_EVENT_EOS: { - GstVideoFrame *frame; + if (!base_video_decoder->packetized) { + GstFlowReturn flow_ret; - frame = g_malloc0 (sizeof (GstVideoFrame)); - frame->presentation_frame_number = - base_video_decoder->presentation_frame_number; - frame->presentation_duration = 0; - base_video_decoder->presentation_frame_number++; + do { + flow_ret = + base_video_decoder_class->parse_data (base_video_decoder, TRUE); + } while (flow_ret == GST_FLOW_OK); + } - base_video_decoder->frames = - g_list_append (base_video_decoder->frames, frame); if (base_video_decoder_class->finish) { - base_video_decoder_class->finish (base_video_decoder, frame); + base_video_decoder_class->finish (base_video_decoder); } ret = @@ -262,6 +246,7 @@ gst_base_video_decoder_sink_event (GstPad * pad, GstEvent * event) gint64 start; gint64 stop; gint64 position; + GstSegment *segment = &base_video_decoder->segment; gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate, &format, &start, &stop, &position); @@ -269,16 +254,34 @@ gst_base_video_decoder_sink_event (GstPad * pad, GstEvent * event) if (format != GST_FORMAT_TIME) goto newseg_wrong_format; - gst_segment_set_newsegment_full (&base_video_decoder->state.segment, + if (!update) { + gst_base_video_decoder_reset (base_video_decoder); + } + + base_video_decoder->timestamp_offset = start; + + gst_segment_set_newsegment_full (segment, update, rate, applied_rate, format, start, stop, position); - GST_DEBUG ("new segment %" GST_SEGMENT_FORMAT, - &base_video_decoder->state.segment); + + GST_WARNING ("new segment: format %d rate %g start %" GST_TIME_FORMAT + " stop %" GST_TIME_FORMAT + " position %" GST_TIME_FORMAT + " update %d", + format, rate, + GST_TIME_ARGS (segment->start), + GST_TIME_ARGS (segment->stop), GST_TIME_ARGS (segment->time), update); ret = gst_pad_push_event (GST_BASE_VIDEO_CODEC_SRC_PAD (base_video_decoder), event); } break; + case GST_EVENT_FLUSH_STOP:{ + GST_OBJECT_LOCK (base_video_decoder); + base_video_decoder->earliest_time = GST_CLOCK_TIME_NONE; + base_video_decoder->proportion = 0.5; + GST_OBJECT_UNLOCK (base_video_decoder); + } default: /* FIXME this changes the order of events */ ret = @@ -318,6 +321,8 @@ gst_base_video_decoder_src_event (GstPad * pad, GstEvent * event) gint64 cur, stop; gint64 tcur, tstop; + GST_DEBUG ("seek event"); + gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur, &stop_type, &stop); gst_event_unref (event); @@ -348,12 +353,28 @@ gst_base_video_decoder_src_event (GstPad * pad, GstEvent * event) gdouble proportion; GstClockTimeDiff diff; GstClockTime timestamp; + GstClockTime duration; gst_event_parse_qos (event, &proportion, &diff, ×tamp); GST_OBJECT_LOCK (base_video_decoder); base_video_decoder->proportion = proportion; - base_video_decoder->earliest_time = timestamp + diff; + if (G_LIKELY (GST_CLOCK_TIME_IS_VALID (timestamp))) { + if (G_UNLIKELY (diff > 0)) { + if (base_video_decoder->state.fps_n > 0) + duration = + gst_util_uint64_scale (GST_SECOND, + base_video_decoder->state.fps_d, + base_video_decoder->state.fps_n); + else + duration = 0; + base_video_decoder->earliest_time = timestamp + 2 * diff + duration; + } else { + base_video_decoder->earliest_time = timestamp + diff; + } + } else { + base_video_decoder->earliest_time = GST_CLOCK_TIME_NONE; + } GST_OBJECT_UNLOCK (base_video_decoder); GST_DEBUG_OBJECT (base_video_decoder, @@ -495,6 +516,8 @@ static const GstQueryType * gst_base_video_decoder_get_query_types (GstPad * pad) { static const GstQueryType query_types[] = { + GST_QUERY_POSITION, + GST_QUERY_DURATION, GST_QUERY_CONVERT, 0 }; @@ -506,17 +529,45 @@ static gboolean gst_base_video_decoder_src_query (GstPad * pad, GstQuery * query) { GstBaseVideoDecoder *enc; - gboolean res; + gboolean res = TRUE; enc = GST_BASE_VIDEO_DECODER (gst_pad_get_parent (pad)); switch GST_QUERY_TYPE (query) { + case GST_QUERY_POSITION: + { + GstFormat format; + gint64 time; + + gst_query_parse_position (query, &format, NULL); + GST_DEBUG ("query in format %d", format); + + if (format != GST_FORMAT_TIME) { + goto error; + } + + time = enc->last_timestamp; + time = gst_segment_to_stream_time (&enc->segment, GST_FORMAT_TIME, time); + + gst_query_set_position (query, format, time); + + res = TRUE; + + break; + } + case GST_QUERY_DURATION: + { + res = gst_pad_peer_query (enc->base_video_codec.sinkpad, query); + break; + } case GST_QUERY_CONVERT: { GstFormat src_fmt, dest_fmt; gint64 src_val, dest_val; + GST_DEBUG ("convert query"); + gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val); res = gst_base_video_decoder_src_convert (pad, src_fmt, src_val, &dest_fmt, @@ -533,7 +584,7 @@ gst_base_video_decoder_src_query (GstPad * pad, GstQuery * query) return res; error: - GST_DEBUG_OBJECT (enc, "query failed"); + GST_ERROR_OBJECT (enc, "query failed"); gst_object_unref (enc); return res; } @@ -594,6 +645,64 @@ gst_pad_is_negotiated (GstPad * pad) } #endif +typedef struct _Timestamp Timestamp; +struct _Timestamp +{ + guint64 offset; + GstClockTime timestamp; + GstClockTime duration; +}; + +static void +gst_base_video_decoder_add_timestamp (GstBaseVideoDecoder * base_video_decoder, + GstBuffer * buffer) +{ + Timestamp *ts; + + ts = g_malloc (sizeof (Timestamp)); + + GST_DEBUG ("adding timestamp %lld %" GST_TIME_FORMAT, + base_video_decoder->input_offset, + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer))); + + ts->offset = base_video_decoder->input_offset; + ts->timestamp = GST_BUFFER_TIMESTAMP (buffer); + ts->duration = GST_BUFFER_DURATION (buffer); + + base_video_decoder->timestamps = + g_list_append (base_video_decoder->timestamps, ts); +} + +static void +gst_base_video_decoder_get_timestamp_at_offset (GstBaseVideoDecoder * + base_video_decoder, guint64 offset, GstClockTime * timestamp, + GstClockTime * duration) +{ + Timestamp *ts; + GList *g; + + *timestamp = GST_CLOCK_TIME_NONE; + *duration = GST_CLOCK_TIME_NONE; + + g = base_video_decoder->timestamps; + while (g) { + ts = g->data; + if (ts->offset <= offset) { + *timestamp = ts->timestamp; + *duration = ts->duration; + g_free (ts); + g = g_list_next (g); + base_video_decoder->timestamps = + g_list_remove (base_video_decoder->timestamps, ts); + } else { + break; + } + } + + GST_DEBUG ("got timestamp %lld %" GST_TIME_FORMAT, + offset, GST_TIME_ARGS (*timestamp)); +} + static void gst_base_video_decoder_reset (GstBaseVideoDecoder * base_video_decoder) { @@ -613,17 +722,25 @@ gst_base_video_decoder_reset (GstBaseVideoDecoder * base_video_decoder) base_video_decoder->timestamp_offset = GST_CLOCK_TIME_NONE; base_video_decoder->system_frame_number = 0; base_video_decoder->presentation_frame_number = 0; - base_video_decoder->last_sink_timestamp = GST_CLOCK_TIME_NONE; - base_video_decoder->last_sink_offset_end = GST_CLOCK_TIME_NONE; base_video_decoder->base_picture_number = 0; base_video_decoder->last_timestamp = GST_CLOCK_TIME_NONE; - base_video_decoder->offset = 0; + base_video_decoder->input_offset = 0; + base_video_decoder->frame_offset = 0; + + /* This function could be called from finalize() */ + if (base_video_decoder->input_adapter) { + gst_adapter_clear (base_video_decoder->input_adapter); + } + if (base_video_decoder->output_adapter) { + gst_adapter_clear (base_video_decoder->output_adapter); + } if (base_video_decoder->caps) { gst_caps_unref (base_video_decoder->caps); base_video_decoder->caps = NULL; } + //gst_segment_init (&base_video_decoder->segment, GST_FORMAT_TIME); if (base_video_decoder->current_frame) { gst_base_video_decoder_free_frame (base_video_decoder->current_frame); @@ -639,27 +756,26 @@ gst_base_video_decoder_reset (GstBaseVideoDecoder * base_video_decoder) g_list_free (base_video_decoder->frames); base_video_decoder->frames = NULL; + GST_OBJECT_LOCK (base_video_decoder); + base_video_decoder->earliest_time = GST_CLOCK_TIME_NONE; + base_video_decoder->proportion = 0.5; + GST_OBJECT_UNLOCK (base_video_decoder); + if (base_video_decoder_class->reset) { base_video_decoder_class->reset (base_video_decoder); } } -static GstBuffer * -gst_adapter_get_buffer (GstAdapter * adapter) -{ - return gst_buffer_ref (GST_BUFFER (adapter->buflist->data)); - -} - static GstFlowReturn gst_base_video_decoder_chain (GstPad * pad, GstBuffer * buf) { GstBaseVideoDecoder *base_video_decoder; GstBaseVideoDecoderClass *klass; - GstBuffer *buffer; GstFlowReturn ret; - GST_DEBUG ("chain %" G_GINT64_FORMAT, GST_BUFFER_TIMESTAMP (buf)); + GST_DEBUG ("chain %" GST_TIME_FORMAT " duration %" GST_TIME_FORMAT, + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)), + GST_TIME_ARGS (GST_BUFFER_DURATION (buf))); #if 0 /* requiring the pad to be negotiated makes it impossible to use @@ -677,9 +793,7 @@ gst_base_video_decoder_chain (GstPad * pad, GstBuffer * buf) if (G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DISCONT))) { GST_DEBUG_OBJECT (base_video_decoder, "received DISCONT buffer"); - if (base_video_decoder->started) { - gst_base_video_decoder_reset (base_video_decoder); - } + gst_base_video_decoder_reset (base_video_decoder); } if (!base_video_decoder->started) { @@ -687,16 +801,15 @@ gst_base_video_decoder_chain (GstPad * pad, GstBuffer * buf) base_video_decoder->started = TRUE; } - if (GST_BUFFER_TIMESTAMP (buf) != GST_CLOCK_TIME_NONE) { - GST_DEBUG ("timestamp %" G_GINT64_FORMAT " offset %" G_GINT64_FORMAT, - GST_BUFFER_TIMESTAMP (buf), base_video_decoder->offset); - base_video_decoder->last_sink_timestamp = GST_BUFFER_TIMESTAMP (buf); + if (base_video_decoder->current_frame == NULL) { + base_video_decoder->current_frame = + gst_base_video_decoder_new_frame (base_video_decoder); } - if (GST_BUFFER_OFFSET_END (buf) != -1) { - GST_DEBUG ("gp %" G_GINT64_FORMAT, GST_BUFFER_OFFSET_END (buf)); - base_video_decoder->last_sink_offset_end = GST_BUFFER_OFFSET_END (buf); + + if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) { + gst_base_video_decoder_add_timestamp (base_video_decoder, buf); } - base_video_decoder->offset += GST_BUFFER_SIZE (buf); + base_video_decoder->input_offset += GST_BUFFER_SIZE (buf); #if 0 if (base_video_decoder->timestamp_offset == GST_CLOCK_TIME_NONE && @@ -706,59 +819,55 @@ gst_base_video_decoder_chain (GstPad * pad, GstBuffer * buf) } #endif - if (base_video_decoder->current_frame == NULL) { - base_video_decoder->current_frame = - gst_base_video_decoder_new_frame (base_video_decoder); - } + if (base_video_decoder->packetized) { + base_video_decoder->current_frame->sink_buffer = buf; - gst_adapter_push (base_video_decoder->input_adapter, buf); + ret = gst_base_video_decoder_have_frame_2 (base_video_decoder); + } else { - if (!base_video_decoder->have_sync) { - int n, m; + gst_adapter_push (base_video_decoder->input_adapter, buf); - GST_DEBUG ("no sync, scanning"); + if (!base_video_decoder->have_sync) { + int n, m; - n = gst_adapter_available (base_video_decoder->input_adapter); - m = klass->scan_for_sync (base_video_decoder, FALSE, 0, n); + GST_DEBUG ("no sync, scanning"); - if (m < 0) { - g_warning ("subclass returned negative scan %d", m); - } + n = gst_adapter_available (base_video_decoder->input_adapter); + m = klass->scan_for_sync (base_video_decoder, FALSE, 0, n); + if (m == -1) { + gst_object_unref (base_video_decoder); + return GST_FLOW_OK; + } - if (m >= n) { - g_warning ("subclass scanned past end %d >= %d", m, n); - } + if (m >= n) { + GST_ERROR ("subclass scanned past end %d >= %d", m, n); + } + + gst_adapter_flush (base_video_decoder->input_adapter, m); - gst_adapter_flush (base_video_decoder->input_adapter, m); + if (m < n) { + GST_DEBUG ("found possible sync after %d bytes (of %d)", m, n); - if (m < n) { - GST_DEBUG ("found possible sync after %d bytes (of %d)", m, n); + /* this is only "maybe" sync */ + base_video_decoder->have_sync = TRUE; + } - /* this is only "maybe" sync */ - base_video_decoder->have_sync = TRUE; + if (!base_video_decoder->have_sync) { + gst_object_unref (base_video_decoder); + return GST_FLOW_OK; + } } - if (!base_video_decoder->have_sync) { + do { + ret = klass->parse_data (base_video_decoder, FALSE); + } while (ret == GST_FLOW_OK); + + if (ret == GST_BASE_VIDEO_DECODER_FLOW_NEED_DATA) { gst_object_unref (base_video_decoder); return GST_FLOW_OK; } } - /* FIXME: use gst_adapter_prev_timestamp() here instead? */ - buffer = gst_adapter_get_buffer (base_video_decoder->input_adapter); - - base_video_decoder->buffer_timestamp = GST_BUFFER_TIMESTAMP (buffer); - gst_buffer_unref (buffer); - - do { - ret = klass->parse_data (base_video_decoder, FALSE); - } while (ret == GST_FLOW_OK); - - if (ret == GST_BASE_VIDEO_DECODER_FLOW_NEED_DATA) { - gst_object_unref (base_video_decoder); - return GST_FLOW_OK; - } - gst_object_unref (base_video_decoder); return ret; } @@ -783,6 +892,9 @@ gst_base_video_decoder_change_state (GstElement * element, switch (transition) { case GST_STATE_CHANGE_PAUSED_TO_READY: + if (base_video_decoder_class->stop) { + base_video_decoder_class->stop (base_video_decoder); + } break; default: break; @@ -799,11 +911,9 @@ gst_base_video_decoder_free_frame (GstVideoFrame * frame) if (frame->sink_buffer) { gst_buffer_unref (frame->sink_buffer); } -#if 0 if (frame->src_buffer) { gst_buffer_unref (frame->src_buffer); } -#endif g_free (frame); } @@ -821,9 +931,9 @@ gst_base_video_decoder_new_frame (GstBaseVideoDecoder * base_video_decoder) frame->decode_frame_number = frame->system_frame_number - base_video_decoder->reorder_depth; - frame->decode_timestamp = -1; - frame->presentation_timestamp = -1; - frame->presentation_duration = -1; + frame->decode_timestamp = GST_CLOCK_TIME_NONE; + frame->presentation_timestamp = GST_CLOCK_TIME_NONE; + frame->presentation_duration = GST_CLOCK_TIME_NONE; frame->n_fields = 2; return frame; @@ -841,29 +951,30 @@ gst_base_video_decoder_finish_frame (GstBaseVideoDecoder * base_video_decoder, base_video_decoder_class = GST_BASE_VIDEO_DECODER_GET_CLASS (base_video_decoder); - GST_DEBUG ("finish frame sync=%d pts=%" G_GINT64_FORMAT, frame->is_sync_point, + GST_DEBUG ("finish frame sync=%d pts=%lld", frame->is_sync_point, frame->presentation_timestamp); - if (frame->is_sync_point) { - if (GST_CLOCK_TIME_IS_VALID (frame->presentation_timestamp)) { - if (frame->presentation_timestamp != base_video_decoder->timestamp_offset) { - GST_DEBUG ("sync timestamp %" G_GINT64_FORMAT " diff %" G_GINT64_FORMAT, - frame->presentation_timestamp, - frame->presentation_timestamp - - base_video_decoder->state.segment.start); - base_video_decoder->timestamp_offset = frame->presentation_timestamp; - base_video_decoder->field_index = 0; - } else { - /* This case is for one initial timestamp and no others, e.g., - * filesrc ! decoder ! xvimagesink */ - GST_WARNING ("sync timestamp didn't change, ignoring"); - frame->presentation_timestamp = GST_CLOCK_TIME_NONE; - } + if (GST_CLOCK_TIME_IS_VALID (frame->presentation_timestamp)) { + if (frame->presentation_timestamp != base_video_decoder->timestamp_offset) { + GST_DEBUG ("sync timestamp %lld diff %lld", + frame->presentation_timestamp, + frame->presentation_timestamp - base_video_decoder->segment.start); + base_video_decoder->timestamp_offset = frame->presentation_timestamp; + base_video_decoder->field_index = 0; } else { + /* This case is for one initial timestamp and no others, e.g., + * filesrc ! decoder ! xvimagesink */ + GST_WARNING ("sync timestamp didn't change, ignoring"); + frame->presentation_timestamp = GST_CLOCK_TIME_NONE; + } + } else { + if (frame->is_sync_point) { GST_WARNING ("sync point doesn't have timestamp"); - if (GST_CLOCK_TIME_IS_VALID (base_video_decoder->timestamp_offset)) { - GST_ERROR ("No base timestamp. Assuming frames start at 0"); - base_video_decoder->timestamp_offset = 0; + if (!GST_CLOCK_TIME_IS_VALID (base_video_decoder->timestamp_offset)) { + GST_WARNING + ("No base timestamp. Assuming frames start at segment start"); + base_video_decoder->timestamp_offset = + base_video_decoder->segment.start; base_video_decoder->field_index = 0; } } @@ -882,15 +993,14 @@ gst_base_video_decoder_finish_frame (GstBaseVideoDecoder * base_video_decoder, } if (frame->presentation_duration == GST_CLOCK_TIME_NONE) { frame->presentation_duration = - gst_base_video_decoder_get_field_timestamp (base_video_decoder, - frame->field_index + frame->n_fields) - frame->presentation_timestamp; + gst_base_video_decoder_get_field_duration (base_video_decoder, + frame->n_fields); } if (GST_CLOCK_TIME_IS_VALID (base_video_decoder->last_timestamp)) { if (frame->presentation_timestamp < base_video_decoder->last_timestamp) { - GST_WARNING ("decreasing timestamp (%" G_GINT64_FORMAT " < %" - G_GINT64_FORMAT ")", frame->presentation_timestamp, - base_video_decoder->last_timestamp); + GST_WARNING ("decreasing timestamp (%lld < %lld)", + frame->presentation_timestamp, base_video_decoder->last_timestamp); } } base_video_decoder->last_timestamp = frame->presentation_timestamp; @@ -927,10 +1037,11 @@ gst_base_video_decoder_finish_frame (GstBaseVideoDecoder * base_video_decoder, GST_BUFFER_TIMESTAMP (frame->src_buffer) = frame->presentation_timestamp; GST_BUFFER_DURATION (frame->src_buffer) = frame->presentation_duration; - GST_BUFFER_OFFSET (frame->src_buffer) = -1; - GST_BUFFER_OFFSET_END (frame->src_buffer) = -1; + GST_BUFFER_OFFSET (frame->src_buffer) = GST_BUFFER_OFFSET_NONE; + GST_BUFFER_OFFSET_END (frame->src_buffer) = GST_BUFFER_OFFSET_NONE; - GST_DEBUG ("pushing frame %" G_GINT64_FORMAT, frame->presentation_timestamp); + GST_DEBUG ("pushing frame %" GST_TIME_FORMAT, + GST_TIME_ARGS (frame->presentation_timestamp)); base_video_decoder->frames = g_list_remove (base_video_decoder->frames, frame); @@ -947,12 +1058,31 @@ gst_base_video_decoder_finish_frame (GstBaseVideoDecoder * base_video_decoder, gint64 stop = GST_BUFFER_TIMESTAMP (src_buffer) + GST_BUFFER_DURATION (src_buffer); - if (gst_segment_clip (&base_video_decoder->state.segment, GST_FORMAT_TIME, + if (gst_segment_clip (&base_video_decoder->segment, GST_FORMAT_TIME, start, stop, &start, &stop)) { GST_BUFFER_TIMESTAMP (src_buffer) = start; GST_BUFFER_DURATION (src_buffer) = stop - start; + GST_DEBUG ("accepting buffer inside segment: %" GST_TIME_FORMAT + " %" GST_TIME_FORMAT + " seg %" GST_TIME_FORMAT " to %" GST_TIME_FORMAT + " time %" GST_TIME_FORMAT, + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (src_buffer)), + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (src_buffer) + + GST_BUFFER_DURATION (src_buffer)), + GST_TIME_ARGS (base_video_decoder->segment.start), + GST_TIME_ARGS (base_video_decoder->segment.stop), + GST_TIME_ARGS (base_video_decoder->segment.time)); } else { - GST_DEBUG ("dropping buffer outside segment"); + GST_DEBUG ("dropping buffer outside segment: %" GST_TIME_FORMAT + " %" GST_TIME_FORMAT + " seg %" GST_TIME_FORMAT " to %" GST_TIME_FORMAT + " time %" GST_TIME_FORMAT, + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (src_buffer)), + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (src_buffer) + + GST_BUFFER_DURATION (src_buffer)), + GST_TIME_ARGS (base_video_decoder->segment.start), + GST_TIME_ARGS (base_video_decoder->segment.stop), + GST_TIME_ARGS (base_video_decoder->segment.time)); gst_buffer_unref (src_buffer); return GST_FLOW_OK; } @@ -962,6 +1092,76 @@ gst_base_video_decoder_finish_frame (GstBaseVideoDecoder * base_video_decoder, src_buffer); } +GstFlowReturn +gst_base_video_decoder_skip_frame (GstBaseVideoDecoder * base_video_decoder, + GstVideoFrame * frame) +{ + GstBaseVideoDecoderClass *base_video_decoder_class; + + GST_DEBUG ("finish frame"); + + base_video_decoder_class = + GST_BASE_VIDEO_DECODER_GET_CLASS (base_video_decoder); + + GST_DEBUG ("finish frame sync=%d pts=%lld", frame->is_sync_point, + frame->presentation_timestamp); + + if (GST_CLOCK_TIME_IS_VALID (frame->presentation_timestamp)) { + if (frame->presentation_timestamp != base_video_decoder->timestamp_offset) { + GST_DEBUG ("sync timestamp %lld diff %lld", + frame->presentation_timestamp, + frame->presentation_timestamp - base_video_decoder->segment.start); + base_video_decoder->timestamp_offset = frame->presentation_timestamp; + base_video_decoder->field_index = 0; + } else { + /* This case is for one initial timestamp and no others, e.g., + * filesrc ! decoder ! xvimagesink */ + GST_WARNING ("sync timestamp didn't change, ignoring"); + frame->presentation_timestamp = GST_CLOCK_TIME_NONE; + } + } else { + if (frame->is_sync_point) { + GST_WARNING ("sync point doesn't have timestamp"); + if (GST_CLOCK_TIME_IS_VALID (base_video_decoder->timestamp_offset)) { + GST_WARNING + ("No base timestamp. Assuming frames start at segment start"); + base_video_decoder->timestamp_offset = + base_video_decoder->segment.start; + base_video_decoder->field_index = 0; + } + } + } + frame->field_index = base_video_decoder->field_index; + base_video_decoder->field_index += frame->n_fields; + + if (frame->presentation_timestamp == GST_CLOCK_TIME_NONE) { + frame->presentation_timestamp = + gst_base_video_decoder_get_field_timestamp (base_video_decoder, + frame->field_index); + frame->presentation_duration = GST_CLOCK_TIME_NONE; + frame->decode_timestamp = + gst_base_video_decoder_get_timestamp (base_video_decoder, + frame->decode_frame_number); + } + if (frame->presentation_duration == GST_CLOCK_TIME_NONE) { + frame->presentation_duration = + gst_base_video_decoder_get_field_duration (base_video_decoder, + frame->n_fields); + } + + base_video_decoder->last_timestamp = frame->presentation_timestamp; + + GST_DEBUG ("skipping frame %" GST_TIME_FORMAT, + GST_TIME_ARGS (frame->presentation_timestamp)); + + base_video_decoder->frames = + g_list_remove (base_video_decoder->frames, frame); + + gst_base_video_decoder_free_frame (frame); + + return GST_FLOW_OK; +} + int gst_base_video_decoder_get_height (GstBaseVideoDecoder * base_video_decoder) { @@ -995,24 +1195,13 @@ gst_base_video_decoder_add_to_frame (GstBaseVideoDecoder * base_video_decoder, GST_DEBUG ("add to frame"); -#if 0 - if (gst_adapter_available (base_video_decoder->output_adapter) == 0) { - GstBuffer *buffer; - - buffer = - gst_adapter_get_orig_buffer_at_offset - (base_video_decoder->input_adapter, 0); - if (buffer) { - base_video_decoder->current_frame->presentation_timestamp = - GST_BUFFER_TIMESTAMP (buffer); - gst_buffer_unref (buffer); - } - } -#endif - if (n_bytes == 0) return; + if (gst_adapter_available (base_video_decoder->output_adapter) == 0) { + base_video_decoder->frame_offset = base_video_decoder->input_offset - + gst_adapter_available (base_video_decoder->input_adapter); + } buf = gst_adapter_take_buffer (base_video_decoder->input_adapter, n_bytes); gst_adapter_push (base_video_decoder->output_adapter, buf); @@ -1056,21 +1245,33 @@ gst_base_video_decoder_get_field_timestamp (GstBaseVideoDecoder * base_video_decoder->state.fps_n * 2); } +static guint64 +gst_base_video_decoder_get_field_duration (GstBaseVideoDecoder * + base_video_decoder, int n_fields) +{ + if (base_video_decoder->state.fps_d == 0) { + return GST_CLOCK_TIME_NONE; + } + if (n_fields < 0) { + GST_WARNING ("n_fields < 0"); + return GST_CLOCK_TIME_NONE; + } + return gst_util_uint64_scale (n_fields, + base_video_decoder->state.fps_d * GST_SECOND, + base_video_decoder->state.fps_n * 2); +} + GstFlowReturn gst_base_video_decoder_have_frame (GstBaseVideoDecoder * base_video_decoder) { - GstVideoFrame *frame = base_video_decoder->current_frame; GstBuffer *buffer; - GstBaseVideoDecoderClass *base_video_decoder_class; - GstFlowReturn ret = GST_FLOW_OK; int n_available; + GstClockTime timestamp; + GstClockTime duration; GST_DEBUG ("have_frame"); - base_video_decoder_class = - GST_BASE_VIDEO_DECODER_GET_CLASS (base_video_decoder); - n_available = gst_adapter_available (base_video_decoder->output_adapter); if (n_available) { buffer = gst_adapter_take_buffer (base_video_decoder->output_adapter, @@ -1079,56 +1280,54 @@ gst_base_video_decoder_have_frame (GstBaseVideoDecoder * base_video_decoder) buffer = gst_buffer_new_and_alloc (0); } + base_video_decoder->current_frame->sink_buffer = buffer; + + gst_base_video_decoder_get_timestamp_at_offset (base_video_decoder, + base_video_decoder->frame_offset, ×tamp, &duration); + + GST_BUFFER_TIMESTAMP (buffer) = timestamp; + GST_BUFFER_DURATION (buffer) = duration; + + return gst_base_video_decoder_have_frame_2 (base_video_decoder); +} + +static GstFlowReturn +gst_base_video_decoder_have_frame_2 (GstBaseVideoDecoder * base_video_decoder) +{ + GstVideoFrame *frame = base_video_decoder->current_frame; + GstBaseVideoDecoderClass *base_video_decoder_class; + GstFlowReturn ret = GST_FLOW_OK; + GstClockTime running_time; + GstClockTimeDiff deadline; + + base_video_decoder_class = + GST_BASE_VIDEO_DECODER_GET_CLASS (base_video_decoder); + frame->distance_from_sync = base_video_decoder->distance_from_sync; base_video_decoder->distance_from_sync++; -#if 0 - if (frame->presentation_timestamp == GST_CLOCK_TIME_NONE) { - frame->presentation_timestamp = - gst_base_video_decoder_get_timestamp (base_video_decoder, - frame->presentation_frame_number); - frame->presentation_duration = - gst_base_video_decoder_get_timestamp (base_video_decoder, - frame->presentation_frame_number + 1) - frame->presentation_timestamp; - frame->decode_timestamp = - gst_base_video_decoder_get_timestamp (base_video_decoder, - frame->decode_frame_number); - } -#endif - -#if 0 - GST_BUFFER_TIMESTAMP (buffer) = frame->presentation_timestamp; - GST_BUFFER_DURATION (buffer) = frame->presentation_duration; - if (frame->decode_frame_number < 0) { - GST_BUFFER_OFFSET (buffer) = 0; - } else { - GST_BUFFER_OFFSET (buffer) = frame->decode_timestamp; - } - GST_BUFFER_OFFSET_END (buffer) = GST_CLOCK_TIME_NONE; -#endif + frame->presentation_timestamp = GST_BUFFER_TIMESTAMP (frame->sink_buffer); + frame->presentation_duration = GST_BUFFER_DURATION (frame->sink_buffer); GST_DEBUG ("pts %" GST_TIME_FORMAT, GST_TIME_ARGS (frame->presentation_timestamp)); GST_DEBUG ("dts %" GST_TIME_FORMAT, GST_TIME_ARGS (frame->decode_timestamp)); GST_DEBUG ("dist %d", frame->distance_from_sync); - if (frame->is_sync_point) { - GST_BUFFER_FLAG_UNSET (buffer, GST_BUFFER_FLAG_DELTA_UNIT); - } else { - GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT); - } - if (base_video_decoder->discont) { - GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT); - base_video_decoder->discont = FALSE; - } - - frame->sink_buffer = buffer; - base_video_decoder->frames = g_list_append (base_video_decoder->frames, frame); + running_time = gst_segment_to_running_time (&base_video_decoder->segment, + GST_FORMAT_TIME, frame->presentation_timestamp); + + if (GST_CLOCK_TIME_IS_VALID (base_video_decoder->earliest_time)) + deadline = GST_CLOCK_DIFF (base_video_decoder->earliest_time, running_time); + else + deadline = G_MAXINT64; + /* do something with frame */ - ret = base_video_decoder_class->handle_frame (base_video_decoder, frame); + ret = base_video_decoder_class->handle_frame (base_video_decoder, frame, + deadline); if (!GST_FLOW_IS_SUCCESS (ret)) { GST_DEBUG ("flow error!"); } @@ -1176,11 +1375,19 @@ gst_base_video_decoder_set_sync_point (GstBaseVideoDecoder * base_video_decoder) base_video_decoder->current_frame->is_sync_point = TRUE; base_video_decoder->distance_from_sync = 0; +} - base_video_decoder->current_frame->presentation_timestamp = - base_video_decoder->last_sink_timestamp; +GstVideoFrame * +gst_base_video_decoder_get_oldest_frame (GstBaseVideoDecoder * + base_video_decoder) +{ + GList *g; + g = g_list_first (base_video_decoder->frames); + if (g == NULL) + return NULL; + return (GstVideoFrame *) (g->data); } GstVideoFrame * @@ -1220,4 +1427,30 @@ gst_base_video_decoder_set_src_caps (GstBaseVideoDecoder * base_video_decoder) gst_pad_set_caps (GST_BASE_VIDEO_CODEC_SRC_PAD (base_video_decoder), caps); base_video_decoder->have_src_caps = TRUE; + + gst_caps_unref (caps); +} + +GstFlowReturn +gst_base_video_decoder_alloc_src_frame (GstBaseVideoDecoder * + base_video_decoder, GstVideoFrame * frame) +{ + GstFlowReturn flow_ret; + int num_bytes; + + gst_base_video_decoder_set_src_caps (base_video_decoder); + + num_bytes = gst_video_format_get_size (base_video_decoder->state.format, + base_video_decoder->state.width, base_video_decoder->state.height); + flow_ret = + gst_pad_alloc_buffer_and_set_caps (GST_BASE_VIDEO_CODEC_SRC_PAD + (base_video_decoder), GST_BUFFER_OFFSET_NONE, num_bytes, + GST_PAD_CAPS (GST_BASE_VIDEO_CODEC_SRC_PAD (base_video_decoder)), + &frame->src_buffer); + + if (flow_ret != GST_FLOW_OK) { + GST_WARNING ("failed to get buffer"); + } + + return flow_ret; } diff --git a/gst-libs/gst/video/gstbasevideodecoder.h b/gst-libs/gst/video/gstbasevideodecoder.h index b6052f094..13b588605 100644 --- a/gst-libs/gst/video/gstbasevideodecoder.h +++ b/gst-libs/gst/video/gstbasevideodecoder.h @@ -20,11 +20,6 @@ #ifndef _GST_BASE_VIDEO_DECODER_H_ #define _GST_BASE_VIDEO_DECODER_H_ -#ifndef GST_USE_UNSTABLE_API -#warning "GstBaseVideoDecoder is unstable API and may change in future." -#warning "You can define GST_USE_UNSTABLE_API to avoid this warning." -#endif - #include <gst/video/gstbasevideocodec.h> G_BEGIN_DECLS @@ -56,10 +51,9 @@ G_BEGIN_DECLS #define GST_BASE_VIDEO_DECODER_SRC_NAME "src" /** - * GST_BASE_VIDEO_DECODER_FLOW_NEED_DATA: - * - * Custom GstFlowReturn value indicating that more data is needed. - */ + * * GST_BASE_VIDEO_DECODER_FLOW_NEED_DATA: + * * + * */ #define GST_BASE_VIDEO_DECODER_FLOW_NEED_DATA GST_FLOW_CUSTOM_SUCCESS @@ -81,6 +75,7 @@ struct _GstBaseVideoDecoder gboolean started; GstVideoState state; + GstSegment segment; gboolean sink_clipping; @@ -102,33 +97,41 @@ struct _GstBaseVideoDecoder gdouble proportion; GstClockTime earliest_time; - GstBuffer *codec_data; + //GstBuffer *codec_data; - guint64 offset; + guint64 input_offset; + guint64 frame_offset; GstClockTime last_timestamp; - GstClockTime last_sink_timestamp; - GstClockTime last_sink_offset_end; guint64 base_picture_number; int field_index; + + gboolean is_delta_unit; + gboolean packetized; + + GList *timestamps; }; struct _GstBaseVideoDecoderClass { GstBaseVideoCodecClass base_video_codec_class; - gboolean (*set_sink_caps) (GstBaseVideoDecoder *coder, GstCaps *caps); + gboolean (*set_format) (GstBaseVideoDecoder *coder, GstVideoFormat, + int width, int height, int fps_n, int fps_d, + int par_n, int par_d); gboolean (*start) (GstBaseVideoDecoder *coder); gboolean (*stop) (GstBaseVideoDecoder *coder); gboolean (*reset) (GstBaseVideoDecoder *coder); int (*scan_for_sync) (GstBaseVideoDecoder *decoder, gboolean at_eos, int offset, int n); GstFlowReturn (*parse_data) (GstBaseVideoDecoder *decoder, gboolean at_eos); - gboolean (*finish) (GstBaseVideoDecoder *coder, GstVideoFrame *frame); - GstFlowReturn (*handle_frame) (GstBaseVideoDecoder *coder, GstVideoFrame *frame); + GstFlowReturn (*finish) (GstBaseVideoDecoder *coder); + GstFlowReturn (*handle_frame) (GstBaseVideoDecoder *coder, GstVideoFrame *frame, + GstClockTimeDiff deadline); GstFlowReturn (*shape_output) (GstBaseVideoDecoder *coder, GstVideoFrame *frame); GstCaps *(*get_caps) (GstBaseVideoDecoder *coder); + }; GType gst_base_video_decoder_get_type (void); @@ -140,10 +143,13 @@ guint64 gst_base_video_decoder_get_timestamp_offset (GstBaseVideoDecoder *coder) GstVideoFrame *gst_base_video_decoder_get_frame (GstBaseVideoDecoder *coder, int frame_number); +GstVideoFrame *gst_base_video_decoder_get_oldest_frame (GstBaseVideoDecoder *coder); void gst_base_video_decoder_add_to_frame (GstBaseVideoDecoder *base_video_decoder, int n_bytes); GstFlowReturn gst_base_video_decoder_finish_frame (GstBaseVideoDecoder *base_video_decoder, GstVideoFrame *frame); +GstFlowReturn gst_base_video_decoder_skip_frame (GstBaseVideoDecoder * base_video_decoder, + GstVideoFrame * frame); GstFlowReturn gst_base_video_decoder_end_of_stream (GstBaseVideoDecoder *base_video_decoder, GstBuffer *buffer); GstFlowReturn @@ -156,6 +162,8 @@ void gst_base_video_decoder_set_sync_point (GstBaseVideoDecoder *base_video_deco void gst_base_video_decoder_set_src_caps (GstBaseVideoDecoder *base_video_decoder); +GstFlowReturn gst_base_video_decoder_alloc_src_frame (GstBaseVideoDecoder *base_video_decoder, + GstVideoFrame *frame); G_END_DECLS diff --git a/gst-libs/gst/video/gstbasevideoencoder.c b/gst-libs/gst/video/gstbasevideoencoder.c index 9daa6e7da..4d68c9ba4 100644 --- a/gst-libs/gst/video/gstbasevideoencoder.c +++ b/gst-libs/gst/video/gstbasevideoencoder.c @@ -35,6 +35,7 @@ static gboolean gst_base_video_encoder_sink_event (GstPad * pad, GstEvent * event); static GstFlowReturn gst_base_video_encoder_chain (GstPad * pad, GstBuffer * buf); +//static GstFlowReturn gst_base_video_encoder_process (GstBaseVideoEncoder *base_video_encoder); static GstStateChangeReturn gst_base_video_encoder_change_state (GstElement * element, GstStateChange transition); static const GstQueryType *gst_base_video_encoder_get_query_types (GstPad * @@ -42,21 +43,9 @@ static const GstQueryType *gst_base_video_encoder_get_query_types (GstPad * static gboolean gst_base_video_encoder_src_query (GstPad * pad, GstQuery * query); -static void -_do_init (GType object_type) -{ - const GInterfaceInfo preset_interface_info = { - NULL, /* interface_init */ - NULL, /* interface_finalize */ - NULL /* interface_data */ - }; - g_type_add_interface_static (object_type, GST_TYPE_PRESET, - &preset_interface_info); -} - -GST_BOILERPLATE_FULL (GstBaseVideoEncoder, gst_base_video_encoder, - GstBaseVideoCodec, GST_TYPE_BASE_VIDEO_CODEC, _do_init); +GST_BOILERPLATE (GstBaseVideoEncoder, gst_base_video_encoder, GstBaseVideoCodec, + GST_TYPE_BASE_VIDEO_CODEC); static void gst_base_video_encoder_base_init (gpointer g_class) @@ -93,6 +82,7 @@ gst_base_video_encoder_init (GstBaseVideoEncoder * base_video_encoder, gst_pad_set_chain_function (pad, gst_base_video_encoder_chain); gst_pad_set_event_function (pad, gst_base_video_encoder_sink_event); gst_pad_set_setcaps_function (pad, gst_base_video_encoder_sink_setcaps); + //gst_pad_set_query_function (pad, gst_base_video_encoder_sink_query); pad = GST_BASE_VIDEO_CODEC_SRC_PAD (base_video_encoder); @@ -105,7 +95,7 @@ gst_base_video_encoder_sink_setcaps (GstPad * pad, GstCaps * caps) { GstBaseVideoEncoder *base_video_encoder; GstBaseVideoEncoderClass *base_video_encoder_class; - gboolean res; + gboolean ret; base_video_encoder = GST_BASE_VIDEO_ENCODER (gst_pad_get_parent (pad)); base_video_encoder_class = @@ -115,14 +105,15 @@ gst_base_video_encoder_sink_setcaps (GstPad * pad, GstCaps * caps) gst_base_video_state_from_caps (&base_video_encoder->state, caps); - res = base_video_encoder_class->set_format (base_video_encoder, + ret = base_video_encoder_class->set_format (base_video_encoder, &base_video_encoder->state); - - base_video_encoder_class->start (base_video_encoder); + if (ret) { + ret = base_video_encoder_class->start (base_video_encoder); + } g_object_unref (base_video_encoder); - return res; + return ret; } static void @@ -130,6 +121,7 @@ gst_base_video_encoder_finalize (GObject * object) { GstBaseVideoEncoder *base_video_encoder; GstBaseVideoEncoderClass *base_video_encoder_class; + GList *g; g_return_if_fail (GST_IS_BASE_VIDEO_ENCODER (object)); base_video_encoder = GST_BASE_VIDEO_ENCODER (object); @@ -137,6 +129,16 @@ gst_base_video_encoder_finalize (GObject * object) GST_DEBUG ("finalize"); + for (g = base_video_encoder->frames; g; g = g_list_next (g)) { + gst_base_video_codec_free_frame ((GstVideoFrame *) g->data); + } + g_list_free (base_video_encoder->frames); + + if (base_video_encoder->caps) { + gst_caps_unref (base_video_encoder->caps); + base_video_encoder->caps = NULL; + } + G_OBJECT_CLASS (parent_class)->finalize (object); } @@ -154,18 +156,9 @@ gst_base_video_encoder_sink_event (GstPad * pad, GstEvent * event) switch (GST_EVENT_TYPE (event)) { case GST_EVENT_EOS: { - GstVideoFrame *frame; - - frame = g_malloc0 (sizeof (GstVideoFrame)); - frame->presentation_frame_number = - base_video_encoder->presentation_frame_number; - frame->presentation_duration = 0; - frame->is_eos = TRUE; - base_video_encoder->presentation_frame_number++; - - base_video_encoder->frames = - g_list_append (base_video_encoder->frames, frame); - base_video_encoder_class->finish (base_video_encoder, frame); + if (base_video_encoder_class->finish) { + base_video_encoder_class->finish (base_video_encoder); + } ret = gst_pad_push_event (GST_BASE_VIDEO_CODEC_SRC_PAD (base_video_encoder), @@ -188,10 +181,9 @@ gst_base_video_encoder_sink_event (GstPad * pad, GstEvent * event) if (format != GST_FORMAT_TIME) goto newseg_wrong_format; - GST_DEBUG ("new segment %" G_GINT64_FORMAT " %" G_GINT64_FORMAT, start, - position); + GST_DEBUG ("new segment %lld %lld", start, position); - gst_segment_set_newsegment_full (&base_video_encoder->state.segment, + gst_segment_set_newsegment_full (&base_video_encoder->segment, update, rate, applied_rate, format, start, stop, position); ret = @@ -223,6 +215,8 @@ static const GstQueryType * gst_base_video_encoder_get_query_types (GstPad * pad) { static const GstQueryType query_types[] = { + //GST_QUERY_POSITION, + //GST_QUERY_DURATION, GST_QUERY_CONVERT, GST_QUERY_LATENCY, 0 @@ -311,7 +305,6 @@ gst_base_video_encoder_chain (GstPad * pad, GstBuffer * buf) GstBaseVideoEncoder *base_video_encoder; GstBaseVideoEncoderClass *klass; GstVideoFrame *frame; - GstFlowReturn ret = GST_FLOW_OK; if (!gst_pad_is_negotiated (pad)) { return GST_FLOW_NOT_NEGOTIATED; @@ -326,14 +319,16 @@ gst_base_video_encoder_chain (GstPad * pad, GstBuffer * buf) gint64 clip_start; gint64 clip_stop; - if (!gst_segment_clip (&base_video_encoder->state.segment, + if (!gst_segment_clip (&base_video_encoder->segment, GST_FORMAT_TIME, start, stop, &clip_start, &clip_stop)) { GST_DEBUG ("clipping to segment dropped frame"); goto done; } } - frame = g_malloc0 (sizeof (GstVideoFrame)); + frame = + gst_base_video_codec_new_frame (GST_BASE_VIDEO_CODEC + (base_video_encoder)); frame->sink_buffer = buf; frame->presentation_timestamp = GST_BUFFER_TIMESTAMP (buf); frame->presentation_duration = GST_BUFFER_DURATION (buf); @@ -344,12 +339,12 @@ gst_base_video_encoder_chain (GstPad * pad, GstBuffer * buf) base_video_encoder->frames = g_list_append (base_video_encoder->frames, frame); - ret = klass->handle_frame (base_video_encoder, frame); + klass->handle_frame (base_video_encoder, frame); done: g_object_unref (base_video_encoder); - return ret; + return GST_FLOW_OK; } static GstStateChangeReturn @@ -423,18 +418,20 @@ gst_base_video_encoder_finish_frame (GstBaseVideoEncoder * base_video_encoder, g_list_remove (base_video_encoder->frames, frame); if (!base_video_encoder->set_output_caps) { - GstCaps *caps; - if (base_video_encoder_class->get_caps) { - caps = base_video_encoder_class->get_caps (base_video_encoder); + base_video_encoder->caps = + base_video_encoder_class->get_caps (base_video_encoder); } else { - caps = gst_caps_new_simple ("video/unknown", NULL); + base_video_encoder->caps = gst_caps_new_simple ("video/unknown", NULL); } - base_video_encoder->caps = gst_caps_ref (caps); - gst_pad_set_caps (GST_BASE_VIDEO_CODEC_SRC_PAD (base_video_encoder), caps); + gst_pad_set_caps (GST_BASE_VIDEO_CODEC_SRC_PAD (base_video_encoder), + base_video_encoder->caps); base_video_encoder->set_output_caps = TRUE; } + gst_buffer_set_caps (GST_BUFFER (frame->src_buffer), + base_video_encoder->caps); + if (base_video_encoder_class->shape_output) { ret = base_video_encoder_class->shape_output (base_video_encoder, frame); } else { @@ -488,6 +485,9 @@ gst_base_video_encoder_set_latency (GstBaseVideoEncoder * base_video_encoder, base_video_encoder->min_latency = min_latency; base_video_encoder->max_latency = max_latency; + + gst_element_post_message (GST_ELEMENT_CAST (base_video_encoder), + gst_message_new_latency (GST_OBJECT_CAST (base_video_encoder))); } void @@ -505,17 +505,14 @@ gst_base_video_encoder_set_latency_fields (GstBaseVideoEncoder * } GstVideoFrame * -gst_base_video_encoder_get_frame (GstBaseVideoEncoder * coder, int frame_number) +gst_base_video_encoder_get_oldest_frame (GstBaseVideoEncoder * + base_video_encoder) { GList *g; - for (g = coder->frames; g; g = g_list_next (g)) { - GstVideoFrame *frame = g->data; - - if (frame->system_frame_number == frame_number) { - return frame; - } - } + g = g_list_first (base_video_encoder->frames); - return NULL; + if (g == NULL) + return NULL; + return (GstVideoFrame *) (g->data); } diff --git a/gst-libs/gst/video/gstbasevideoencoder.h b/gst-libs/gst/video/gstbasevideoencoder.h index 7d60a64dd..761a9d707 100644 --- a/gst-libs/gst/video/gstbasevideoencoder.h +++ b/gst-libs/gst/video/gstbasevideoencoder.h @@ -20,11 +20,6 @@ #ifndef _GST_BASE_VIDEO_ENCODER_H_ #define _GST_BASE_VIDEO_ENCODER_H_ -#ifndef GST_USE_UNSTABLE_API -#warning "GstBaseVideoEncoder is unstable API and may change in future." -#warning "You can define GST_USE_UNSTABLE_API to avoid this warning." -#endif - #include <gst/video/gstbasevideocodec.h> #include <gst/video/gstbasevideoutils.h> @@ -68,6 +63,7 @@ struct _GstBaseVideoEncoder GList *frames; GstVideoState state; + GstSegment segment; gboolean sink_clipping; @@ -89,8 +85,8 @@ struct _GstBaseVideoEncoderClass gboolean (*set_format) (GstBaseVideoEncoder *coder, GstVideoState *state); gboolean (*start) (GstBaseVideoEncoder *coder); gboolean (*stop) (GstBaseVideoEncoder *coder); - gboolean (*finish) (GstBaseVideoEncoder *coder, GstVideoFrame *frame); - GstFlowReturn (*handle_frame) (GstBaseVideoEncoder *coder, GstVideoFrame *frame); + gboolean (*finish) (GstBaseVideoEncoder *coder); + gboolean (*handle_frame) (GstBaseVideoEncoder *coder, GstVideoFrame *frame); GstFlowReturn (*shape_output) (GstBaseVideoEncoder *coder, GstVideoFrame *frame); GstCaps *(*get_caps) (GstBaseVideoEncoder *coder); @@ -106,6 +102,7 @@ guint64 gst_base_video_encoder_get_timestamp_offset (GstBaseVideoEncoder *coder) GstVideoFrame *gst_base_video_encoder_get_frame (GstBaseVideoEncoder *coder, int frame_number); +GstVideoFrame *gst_base_video_encoder_get_oldest_frame (GstBaseVideoEncoder *coder); GstFlowReturn gst_base_video_encoder_finish_frame (GstBaseVideoEncoder *base_video_encoder, GstVideoFrame *frame); GstFlowReturn gst_base_video_encoder_end_of_stream (GstBaseVideoEncoder *base_video_encoder, diff --git a/gst-libs/gst/video/gstbasevideoparse.c b/gst-libs/gst/video/gstbasevideoparse.c index 78f34ab88..468ee6872 100644 --- a/gst-libs/gst/video/gstbasevideoparse.c +++ b/gst-libs/gst/video/gstbasevideoparse.c @@ -129,7 +129,7 @@ gst_base_video_parse_reset (GstBaseVideoParse * base_video_parse) base_video_parse->caps = NULL; } - gst_segment_init (&base_video_parse->state.segment, GST_FORMAT_TIME); + gst_segment_init (&base_video_parse->segment, GST_FORMAT_TIME); gst_adapter_clear (base_video_parse->input_adapter); gst_adapter_clear (base_video_parse->output_adapter); @@ -278,8 +278,8 @@ gst_base_video_parse_src_query (GstPad * pad, GstQuery * query) time = gst_util_uint64_scale (base_parse->presentation_frame_number, base_parse->state.fps_n, base_parse->state.fps_d); - time += base_parse->state.segment.time; - GST_DEBUG ("query position %" G_GINT64_FORMAT, time); + time += base_parse->segment.time; + GST_DEBUG ("query position %lld", time); res = gst_base_video_encoded_video_convert (&base_parse->state, GST_FORMAT_TIME, time, &format, &value); if (!res) @@ -484,9 +484,8 @@ gst_base_video_parse_sink_event (GstPad * pad, GstEvent * event) if (rate <= 0.0) goto newseg_wrong_rate; - GST_DEBUG ("newsegment %" G_GINT64_FORMAT " %" G_GINT64_FORMAT, start, - time); - gst_segment_set_newsegment (&base_video_parse->state.segment, update, + GST_DEBUG ("newsegment %lld %lld", start, time); + gst_segment_set_newsegment (&base_video_parse->segment, update, rate, format, start, stop, time); ret = @@ -580,13 +579,6 @@ gst_base_video_parse_push_all (GstBaseVideoParse * base_video_parse, return ret; } -static GstBuffer * -gst_adapter_get_buffer (GstAdapter * adapter) -{ - return gst_buffer_ref (GST_BUFFER (adapter->buflist->data)); - -} - static GstFlowReturn gst_base_video_parse_chain (GstPad * pad, GstBuffer * buf) { @@ -639,9 +631,9 @@ gst_base_video_parse_chain (GstPad * pad, GstBuffer * buf) } } - /* FIXME: use gst_adapter_prev_timestamp() here instead? */ buffer = gst_adapter_get_buffer (base_video_parse->input_adapter); + //base_video_parse->buffer_timestamp = GST_BUFFER_TIMESTAMP (buffer); gst_buffer_unref (buffer); /* FIXME check klass->parse_data */ @@ -855,9 +847,9 @@ gst_base_video_parse_push (GstBaseVideoParse * base_video_parse, } gst_buffer_set_caps (buffer, base_video_parse->caps); - GST_DEBUG ("pushing ts=%" G_GINT64_FORMAT " dur=%" G_GINT64_FORMAT " off=%" - G_GINT64_FORMAT " off_end=%" G_GINT64_FORMAT, - GST_BUFFER_TIMESTAMP (buffer), GST_BUFFER_DURATION (buffer), + GST_DEBUG ("pushing ts=%lld dur=%lld off=%lld off_end=%lld", + GST_BUFFER_TIMESTAMP (buffer), + GST_BUFFER_DURATION (buffer), GST_BUFFER_OFFSET (buffer), GST_BUFFER_OFFSET_END (buffer)); if (base_video_parse->discont) { diff --git a/gst-libs/gst/video/gstbasevideoparse.h b/gst-libs/gst/video/gstbasevideoparse.h index cdbcd27a4..5a1469f1f 100644 --- a/gst-libs/gst/video/gstbasevideoparse.h +++ b/gst-libs/gst/video/gstbasevideoparse.h @@ -20,11 +20,6 @@ #ifndef _GST_BASE_VIDEO_PARSE_H_ #define _GST_BASE_VIDEO_PARSE_H_ -#ifndef GST_USE_UNSTABLE_API -#warning "GstBaseVideoParse is unstable API and may change in future." -#warning "You can define GST_USE_UNSTABLE_API to avoid this warning." -#endif - #include <gst/video/gstbasevideocodec.h> #include <gst/video/gstbasevideoutils.h> @@ -81,6 +76,7 @@ struct _GstBaseVideoParse GstVideoFrame *current_frame; GstVideoState state; + GstSegment segment; int distance_from_sync; gboolean sink_clipping; diff --git a/gst-libs/gst/video/gstbasevideoutils.c b/gst-libs/gst/video/gstbasevideoutils.c index 83d72c956..69f614b28 100644 --- a/gst-libs/gst/video/gstbasevideoutils.c +++ b/gst-libs/gst/video/gstbasevideoutils.c @@ -29,6 +29,21 @@ GST_DEBUG_CATEGORY_EXTERN (basevideo_debug); #define GST_CAT_DEFAULT basevideo_debug +#if 0 +guint64 +gst_base_video_convert_bytes_to_frames (GstVideoState * state, guint64 bytes) +{ + return gst_util_uint64_scale_int (bytes, 1, state->bytes_per_picture); +} + +guint64 +gst_base_video_convert_frames_to_bytes (GstVideoState * state, guint64 frames) +{ + return frames * state->bytes_per_picture; +} +#endif + + gboolean gst_base_video_rawvideo_convert (GstVideoState * state, GstFormat src_format, gint64 src_value, @@ -113,8 +128,7 @@ gst_base_video_state_from_caps (GstVideoState * state, GstCaps * caps) gst_video_format_parse_caps (caps, &state->format, &state->width, &state->height); - if (!gst_video_parse_caps_framerate (caps, &state->fps_n, &state->fps_d)) - return FALSE; + gst_video_parse_caps_framerate (caps, &state->fps_n, &state->fps_d); state->par_n = 1; state->par_d = 1; @@ -136,15 +150,129 @@ gst_base_video_state_from_caps (GstVideoState * state, GstCaps * caps) } GstClockTime -gst_video_state_get_timestamp (const GstVideoState * state, int frame_number) +gst_video_state_get_timestamp (const GstVideoState * state, + GstSegment * segment, int frame_number) { if (frame_number < 0) { - return state->segment.start - + return segment->start - (gint64) gst_util_uint64_scale (-frame_number, state->fps_d * GST_SECOND, state->fps_n); } else { - return state->segment.start + + return segment->start + gst_util_uint64_scale (frame_number, state->fps_d * GST_SECOND, state->fps_n); } } + +/* gst adapter */ + +static GSList * +get_chunk (GstAdapter * adapter, int offset, int *skip) +{ + GSList *g; + +#if 1 + if (skip) + *skip = 0; +#endif + + g_return_val_if_fail (offset >= 0, NULL); + g_return_val_if_fail (offset < adapter->size, NULL); + + offset += adapter->skip; + g = adapter->buflist; + while (g) { + if (offset < GST_BUFFER_SIZE (GST_BUFFER_CAST (g->data))) { + if (skip) + *skip = offset; + return g; + } + offset -= GST_BUFFER_SIZE (GST_BUFFER_CAST (g->data)); + g = g->next; + } + + g_assert_not_reached (); +} + +static int +scan_fast (guint8 * data, guint32 pattern, guint32 mask, int n) +{ + int i; + + pattern &= mask; + for (i = 0; i < n; i++) { + if ((GST_READ_UINT32_BE (data + i) & mask) == pattern) { + return i; + } + } + return n; +} + +static gboolean +scan_slow (GstAdapter * adapter, GSList * g, int skip, guint32 pattern, + guint32 mask) +{ + guint8 tmp[4]; + int j; + + pattern &= mask; + for (j = 0; j < 4; j++) { + tmp[j] = ((guint8 *) GST_BUFFER_DATA (GST_BUFFER_CAST (g->data)))[skip]; + skip++; + if (skip >= GST_BUFFER_SIZE (GST_BUFFER_CAST (g->data))) { + g = g->next; + skip = 0; + } + } + + return ((GST_READ_UINT32_BE (tmp) & mask) == pattern); +} + +int +gst_adapter_masked_scan_uint32_compat (GstAdapter * adapter, guint32 mask, + guint32 pattern, guint offset, guint n) +{ + GSList *g; + int j; + int k; + int skip; + int m; + + g_return_val_if_fail (n >= 0, -1); + g_return_val_if_fail (offset >= 0, -1); + g_return_val_if_fail (offset + n + 4 <= adapter->size, -1); + + g = get_chunk (adapter, offset, &skip); + j = 0; + while (j < n) { + m = MIN (GST_BUFFER_SIZE (GST_BUFFER_CAST (g->data)) - skip - 4, 0); + if (m > 0) { + k = scan_fast (GST_BUFFER_DATA (GST_BUFFER_CAST (g->data)) + skip, + pattern, mask, m); + if (k < m) { + return offset + j + k; + } + j += m; + skip += m; + } else { + if (scan_slow (adapter, g, skip, pattern, mask)) { + return offset + j; + } + j++; + skip++; + } + if (skip >= GST_BUFFER_SIZE (GST_BUFFER_CAST (g->data))) { + g = g->next; + skip = 0; + } + } + + return -1; +} + +GstBuffer * +gst_adapter_get_buffer (GstAdapter * adapter) +{ + return gst_buffer_ref (GST_BUFFER_CAST (adapter->buflist->data)); + +} diff --git a/gst-libs/gst/video/gstbasevideoutils.h b/gst-libs/gst/video/gstbasevideoutils.h index e832fe76d..47871dcff 100644 --- a/gst-libs/gst/video/gstbasevideoutils.h +++ b/gst-libs/gst/video/gstbasevideoutils.h @@ -20,11 +20,6 @@ #ifndef _GST_BASE_VIDEO_UTILS_H_ #define _GST_BASE_VIDEO_UTILS_H_ -#ifndef GST_USE_UNSTABLE_API -#warning "The base video utils API is unstable and may change in future." -#warning "You can define GST_USE_UNSTABLE_API to avoid this warning." -#endif - #include <gst/gst.h> #include <gst/video/video.h> #include <gst/base/gstadapter.h> @@ -40,6 +35,8 @@ struct _GstVideoState int width, height; int fps_n, fps_d; int par_n, par_d; + + gboolean have_interlaced; gboolean interlaced; gboolean top_field_first; @@ -48,16 +45,18 @@ struct _GstVideoState int bytes_per_picture; - GstSegment segment; + //GstSegment segment; int picture_number; + GstBuffer *codec_data; + }; struct _GstVideoFrame { - guint64 decode_timestamp; - guint64 presentation_timestamp; - guint64 presentation_duration; + GstClockTime decode_timestamp; + GstClockTime presentation_timestamp; + GstClockTime presentation_duration; gint system_frame_number; gint decode_frame_number; @@ -87,7 +86,11 @@ gboolean gst_base_video_state_from_caps (GstVideoState *state, GstCaps *caps); GstClockTime gst_video_state_get_timestamp (const GstVideoState *state, - int frame_number); + GstSegment *segment, int frame_number); + +int gst_adapter_masked_scan_uint32_compat (GstAdapter *adapter, + guint32 pattern, guint32 mask, guint offset, guint n); +GstBuffer *gst_adapter_get_buffer (GstAdapter *adapter); G_END_DECLS |