diff --git a/gst-libs/gst/video/gstbasevideodecoder.c b/gst-libs/gst/video/gstbasevideodecoder.c index 1ca7d7292c..299b9746d9 100644 --- a/gst-libs/gst/video/gstbasevideodecoder.c +++ b/gst-libs/gst/video/gstbasevideodecoder.c @@ -1,5 +1,8 @@ /* GStreamer * Copyright (C) 2008 David Schleef + * Copyright (C) 2011 Mark Nauwelaerts . + * Copyright (C) 2011 Nokia Corporation. All rights reserved. + * Contact: Stefan Kost * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -17,6 +20,101 @@ * Boston, MA 02111-1307, USA. */ +/** + * SECTION:gstbasevideodecoder + * @short_description: Base class for video decoders + * @see_also: #GstBaseTransform + * + * This base class is for video decoders turning encoded data into raw video + * frames. + * + * GstBaseVideoDecoder and subclass should cooperate as follows. + * + * + * Configuration + * + * Initially, GstBaseVideoDecoder calls @start when the decoder element + * is activated, which allows subclass to perform any global setup. + * + * + * GstBaseVideoDecoder calls @set_format to inform subclass of caps + * describing input video data that it is about to receive, including + * possibly configuration data. + * While unlikely, it might be called more than once, if changing input + * parameters require reconfiguration. + * + * + * GstBaseVideoDecoder calls @stop at end of all processing. + * + * + * + * + * + * Data processing + * + * Base class gathers input data, and optionally allows subclass + * to parse this into subsequently manageable chunks, typically + * corresponding to and referred to as 'frames'. + * + * + * Input frame is provided to subclass' @handle_frame. + * + * + * If codec processing results in decoded data, subclass should call + * @gst_base_video_decoder_finish_frame to have decoded data pushed + * downstream. + * + * + * + * + * Shutdown phase + * + * GstBaseVideoDecoder class calls @stop to inform the subclass that data + * parsing will be stopped. + * + * + * + * + * + * Subclass is responsible for providing pad template caps for + * source and sink pads. The pads need to be named "sink" and "src". It also + * needs to set the fixed caps on srcpad, when the format is ensured. This + * is typically when base class calls subclass' @set_format function, though + * it might be delayed until calling @gst_base_video_decoder_finish_frame. + * + * Subclass is also responsible for providing (presentation) timestamps + * (likely based on corresponding input ones). If that is not applicable + * or possible, baseclass provides limited framerate based interpolation. + * + * Similarly, the baseclass provides some limited (legacy) seeking support + * (upon explicit subclass request), as full-fledged support + * should rather be left to upstream demuxer, parser or alike. This simple + * approach caters for seeking and duration reporting using estimated input + * bitrates. + * + * Things that subclass need to take care of: + * + * Provide pad templates + * + * Set source pad caps when appropriate + * + * + * Configure some baseclass behaviour parameters. + * + * + * Optionally parse input data, if it is not considered packetized. + * Parse sync is obtained either by providing baseclass with a + * mask and pattern or a custom @scan_for_sync. When sync is established, + * @parse_data should invoke @gst_base_video_decoder_add_to_frame and + * @gst_base_video_decoder_have_frame as appropriate. + * + * + * Accept data in @handle_frame and provide decoded results to + * @gst_base_video_decoder_finish_frame. + * + * + */ + #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -1006,6 +1104,18 @@ gst_base_video_decoder_new_frame (GstBaseVideoDecoder * base_video_decoder) return frame; } +/** + * gst_base_video_decoder_finish_frame: + * @base_video_decoder: a #GstBaseVideoDecoder + * @frame: a decoded #GstVideoFrame + * + * @frame should have a valid decoded data buffer, whose metadata fields + * are then appropriately set according to frame data and pushed downstream. + * If no output data is provided, @frame is considered skipped. + * In any case, the frame is considered finished and released. + * + * Returns: a #GstFlowReturn resulting from sending data downstream + */ GstFlowReturn gst_base_video_decoder_finish_frame (GstBaseVideoDecoder * base_video_decoder, GstVideoFrame * frame) @@ -1187,6 +1297,13 @@ done: return ret; } +/** + * gst_base_video_decoder_finish_frame: + * @base_video_decoder: a #GstBaseVideoDecoder + * @n_bytes: an encoded #GstVideoFrame + * + * Removes next @n_bytes of input data and adds it to currently parsed frame. + */ void gst_base_video_decoder_add_to_frame (GstBaseVideoDecoder * base_video_decoder, int n_bytes) @@ -1263,7 +1380,15 @@ gst_base_video_decoder_get_field_duration (GstBaseVideoDecoder * state->fps_n * 2); } - +/** + * gst_base_video_decoder_have_frame: + * @base_video_decoder: a #GstBaseVideoDecoder + * + * Gathers all data collected for currently parsed frame, gathers corresponding + * metadata and passes it along for further processing, i.e. @handle_frame. + * + * Returns: a #GstFlowReturn + */ GstFlowReturn gst_base_video_decoder_have_frame (GstBaseVideoDecoder * base_video_decoder) { @@ -1341,20 +1466,24 @@ gst_base_video_decoder_have_frame_2 (GstBaseVideoDecoder * base_video_decoder) return ret; } +/** + * gst_base_video_decoder_get_state: + * @base_video_decoder: a #GstBaseVideoDecoder + * + * Returns: #GstVideoState describing format of video data. + */ GstVideoState * gst_base_video_decoder_get_state (GstBaseVideoDecoder * base_video_decoder) { return &GST_BASE_VIDEO_CODEC (base_video_decoder)->state; } -void -gst_base_video_decoder_set_state (GstBaseVideoDecoder * base_video_decoder, - GstVideoState * state) -{ - memcpy (&GST_BASE_VIDEO_CODEC (base_video_decoder)->state, - state, sizeof (*state)); -} - +/** + * gst_base_video_decoder_lost_sync: + * @base_video_decoder: a #GstBaseVideoDecoder + * + * Advances out-of-sync input data by 1 byte and marks it accordingly. + */ void gst_base_video_decoder_lost_sync (GstBaseVideoDecoder * base_video_decoder) { @@ -1369,6 +1498,13 @@ gst_base_video_decoder_lost_sync (GstBaseVideoDecoder * base_video_decoder) base_video_decoder->have_sync = FALSE; } +/* FIXME not quite exciting; get rid of this ? */ +/** + * gst_base_video_decoder_set_sync_point: + * @base_video_decoder: a #GstBaseVideoDecoder + * + * Marks current frame as a sync point, i.e. keyframe. + */ void gst_base_video_decoder_set_sync_point (GstBaseVideoDecoder * base_video_decoder) { @@ -1378,6 +1514,12 @@ gst_base_video_decoder_set_sync_point (GstBaseVideoDecoder * base_video_decoder) base_video_decoder->distance_from_sync = 0; } +/** + * gst_base_video_decoder_get_oldest_frame: + * @base_video_decoder: a #GstBaseVideoDecoder + * + * Returns: oldest pending unfinished #GstVideoFrame. + */ GstVideoFrame * gst_base_video_decoder_get_oldest_frame (GstBaseVideoDecoder * base_video_decoder) @@ -1391,6 +1533,13 @@ gst_base_video_decoder_get_oldest_frame (GstBaseVideoDecoder * return (GstVideoFrame *) (g->data); } +/** + * gst_base_video_decoder_get_frame: + * @base_video_decoder: a #GstBaseVideoDecoder + * @frame_number: system_frame_number of a frame + * + * Returns: pending unfinished #GstVideoFrame identified by @frame_number. + */ GstVideoFrame * gst_base_video_decoder_get_frame (GstBaseVideoDecoder * base_video_decoder, int frame_number) @@ -1409,6 +1558,13 @@ gst_base_video_decoder_get_frame (GstBaseVideoDecoder * base_video_decoder, return NULL; } +/** + * gst_base_video_decoder_set_src_caps: + * @base_video_decoder: a #GstBaseVideoDecoder + * + * Sets src pad caps according to currently configured #GstVideoState. + * + */ void gst_base_video_decoder_set_src_caps (GstBaseVideoDecoder * base_video_decoder) { @@ -1434,6 +1590,16 @@ gst_base_video_decoder_set_src_caps (GstBaseVideoDecoder * base_video_decoder) gst_caps_unref (caps); } +/** + * gst_base_video_decoder_alloc_src_buffer: + * @base_video_decoder: a #GstBaseVideoDecoder + * + * Helper function that uses gst_pad_alloc_buffer_and_set_caps + * to allocate a buffer to hold a video frame for @base_video_decoder's + * current #GstVideoState. + * + * Returns: allocated buffer + */ GstBuffer * gst_base_video_decoder_alloc_src_buffer (GstBaseVideoDecoder * base_video_decoder) @@ -1464,6 +1630,17 @@ gst_base_video_decoder_alloc_src_buffer (GstBaseVideoDecoder * return buffer; } +/** + * gst_base_video_decoder_alloc_src_frame: + * @base_video_decoder: a #GstBaseVideoDecoder + * @frame: a #GstVideoFrame + * + * Helper function that uses gst_pad_alloc_buffer_and_set_caps + * to allocate a buffer to hold a video frame for @base_video_decoder's + * current #GstVideoState. + * + * Returns: result from pad alloc call + */ GstFlowReturn gst_base_video_decoder_alloc_src_frame (GstBaseVideoDecoder * base_video_decoder, GstVideoFrame * frame) @@ -1490,6 +1667,18 @@ gst_base_video_decoder_alloc_src_frame (GstBaseVideoDecoder * return flow_ret; } +/** + * gst_base_video_decoder_get_max_decode_time: + * @base_video_decoder: a #GstBaseVideoDecoder + * @frame: a #GstVideoFrame + * + * Determines maximum possible decoding time for @frame that will + * allow it to decode and arrive in time (as determined by QoS messages). + * In particular, a negative result means decoding in time is no longer possible + * and should therefore occur as soon/skippy as possible. + * + * Returns: max decoding time. + */ GstClockTimeDiff gst_base_video_decoder_get_max_decode_time (GstBaseVideoDecoder * base_video_decoder, GstVideoFrame * frame) @@ -1511,6 +1700,14 @@ gst_base_video_decoder_get_max_decode_time (GstBaseVideoDecoder * return deadline; } +/** + * gst_base_video_decoder_get_oldest_frame: + * @base_video_decoder_class: a #GstBaseVideoDecoderClass + * + * Sets the mask and pattern that will be scanned for to obtain parse sync. + * Note that a non-zero @mask implies that @scan_for_sync will be ignored. + * + */ void gst_base_video_decoder_class_set_capture_pattern (GstBaseVideoDecoderClass * base_video_decoder_class, guint32 mask, guint32 pattern) diff --git a/gst-libs/gst/video/gstbasevideodecoder.h b/gst-libs/gst/video/gstbasevideodecoder.h index 3c6ca76189..59829f050b 100644 --- a/gst-libs/gst/video/gstbasevideodecoder.h +++ b/gst-libs/gst/video/gstbasevideodecoder.h @@ -1,5 +1,8 @@ /* GStreamer * Copyright (C) 2008 David Schleef + * Copyright (C) 2011 Mark Nauwelaerts . + * Copyright (C) 2011 Nokia Corporation. All rights reserved. + * Contact: Stefan Kost * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -66,6 +69,11 @@ G_BEGIN_DECLS typedef struct _GstBaseVideoDecoder GstBaseVideoDecoder; typedef struct _GstBaseVideoDecoderClass GstBaseVideoDecoderClass; +/** + * GstBaseVideoDecoder: + * + * The opaque #GstBaseVideoDecoder data structure. + */ struct _GstBaseVideoDecoder { GstBaseVideoCodec base_video_codec; @@ -120,58 +128,89 @@ struct _GstBaseVideoDecoder void *padding[GST_PADDING_LARGE]; }; +/** + * GstBaseAudioDecoderClass: + * @start: Optional. + * Called when the element starts processing. + * Allows opening external resources. + * @stop: Optional. + * Called when the element stops processing. + * Allows closing external resources. + * @set_format: Notifies subclass of incoming data format (caps). + * @scan_for_sync: Optional. + * Allows subclass to obtain sync for subsequent parsing + * by custom means (above an beyond scanning for specific + * marker and mask). + * @parse_data: Required for non-packetized input. + * Allows chopping incoming data into manageable units (frames) + * for subsequent decoding. + * @reset: Optional. + * Allows subclass (codec) to perform post-seek semantics reset. + * @handle_frame: Provides input data frame to subclass. + * @finish: Optional. + * Called to request subclass to dispatch any pending remaining + * data (e.g. at EOS). + * + * Subclasses can override any of the available virtual methods or not, as + * needed. At minimum @handle_frame needs to be overridden, and @set_format + * and likely as well. If non-packetized input is supported or expected, + * @parse needs to be overridden as well. + */ struct _GstBaseVideoDecoderClass { GstBaseVideoCodecClass base_video_codec_class; - gboolean (*set_format) (GstBaseVideoDecoder *coder, GstVideoState * state); - 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); - GstFlowReturn (*finish) (GstBaseVideoDecoder *coder); - GstFlowReturn (*handle_frame) (GstBaseVideoDecoder *coder, GstVideoFrame *frame); - GstFlowReturn (*shape_output) (GstBaseVideoDecoder *coder, GstVideoFrame *frame); - GstCaps *(*get_caps) (GstBaseVideoDecoder *coder); + gboolean (*start) (GstBaseVideoDecoder *coder); - guint32 capture_mask; - guint32 capture_pattern; + gboolean (*stop) (GstBaseVideoDecoder *coder); + + int (*scan_for_sync) (GstBaseVideoDecoder *decoder, gboolean at_eos, + int offset, int n); + + GstFlowReturn (*parse_data) (GstBaseVideoDecoder *decoder, gboolean at_eos); + + gboolean (*set_format) (GstBaseVideoDecoder *coder, GstVideoState * state); + + gboolean (*reset) (GstBaseVideoDecoder *coder); + + GstFlowReturn (*finish) (GstBaseVideoDecoder *coder); + + GstFlowReturn (*handle_frame) (GstBaseVideoDecoder *coder, GstVideoFrame *frame); + + + /*< private >*/ + guint32 capture_mask; + guint32 capture_pattern; /* FIXME before moving to base */ - void *padding[GST_PADDING_LARGE]; + void *padding[GST_PADDING_LARGE]; }; -GType gst_base_video_decoder_get_type (void); +void gst_base_video_decoder_class_set_capture_pattern (GstBaseVideoDecoderClass *klass, + guint32 mask, guint32 pattern); -void gst_base_video_decoder_class_set_capture_pattern (GstBaseVideoDecoderClass *klass, - guint32 mask, guint32 pattern); +GstVideoFrame *gst_base_video_decoder_get_frame (GstBaseVideoDecoder *coder, + int frame_number); +GstVideoFrame *gst_base_video_decoder_get_oldest_frame (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_have_frame (GstBaseVideoDecoder *base_video_decoder); -GstVideoState * gst_base_video_decoder_get_state (GstBaseVideoDecoder *base_video_decoder); -void gst_base_video_decoder_set_state (GstBaseVideoDecoder *base_video_decoder, - GstVideoState *state); -void gst_base_video_decoder_lost_sync (GstBaseVideoDecoder *base_video_decoder); -void gst_base_video_decoder_set_sync_point (GstBaseVideoDecoder *base_video_decoder); - -void gst_base_video_decoder_set_src_caps (GstBaseVideoDecoder *base_video_decoder); - -GstBuffer * gst_base_video_decoder_alloc_src_buffer (GstBaseVideoDecoder * - base_video_decoder); -GstFlowReturn gst_base_video_decoder_alloc_src_frame (GstBaseVideoDecoder *base_video_decoder, - GstVideoFrame *frame); +void gst_base_video_decoder_add_to_frame (GstBaseVideoDecoder *base_video_decoder, + int n_bytes); +void gst_base_video_decoder_lost_sync (GstBaseVideoDecoder *base_video_decoder); +GstFlowReturn gst_base_video_decoder_have_frame (GstBaseVideoDecoder *base_video_decoder); +void gst_base_video_decoder_set_sync_point (GstBaseVideoDecoder *base_video_decoder); +void gst_base_video_decoder_set_src_caps (GstBaseVideoDecoder *base_video_decoder); +GstBuffer *gst_base_video_decoder_alloc_src_buffer (GstBaseVideoDecoder * base_video_decoder); +GstFlowReturn gst_base_video_decoder_alloc_src_frame (GstBaseVideoDecoder *base_video_decoder, + GstVideoFrame *frame); +GstVideoState *gst_base_video_decoder_get_state (GstBaseVideoDecoder *base_video_decoder); GstClockTimeDiff gst_base_video_decoder_get_max_decode_time ( - GstBaseVideoDecoder *base_video_decoder, GstVideoFrame *frame); + GstBaseVideoDecoder *base_video_decoder, + GstVideoFrame *frame); +GstFlowReturn gst_base_video_decoder_finish_frame (GstBaseVideoDecoder *base_video_decoder, + GstVideoFrame *frame); + +GType gst_base_video_decoder_get_type (void); G_END_DECLS