diff options
Diffstat (limited to 'ext/ffmpeg/gstffmpegviddec.c')
-rw-r--r-- | ext/ffmpeg/gstffmpegviddec.c | 779 |
1 files changed, 240 insertions, 539 deletions
diff --git a/ext/ffmpeg/gstffmpegviddec.c b/ext/ffmpeg/gstffmpegviddec.c index 918abf8..3184bac 100644 --- a/ext/ffmpeg/gstffmpegviddec.c +++ b/ext/ffmpeg/gstffmpegviddec.c @@ -40,7 +40,7 @@ /* define to enable alternative buffer refcounting algorithm */ #undef EXTRA_REF -typedef struct _GstFFMpegDec GstFFMpegDec; +typedef struct _GstFFMpegVidDec GstFFMpegVidDec; #define MAX_TS_MASK 0xff @@ -56,7 +56,7 @@ typedef struct gint64 offset; } GstTSInfo; -struct _GstFFMpegDec +struct _GstFFMpegVidDec { GstElement element; @@ -81,12 +81,6 @@ struct _GstFFMpegDec enum PixelFormat pix_fmt; } video; - struct - { - gint channels; - gint samplerate; - gint depth; - } audio; } format; gboolean waiting_for_key; gboolean discont; @@ -144,9 +138,9 @@ struct _GstFFMpegDec gboolean can_allocate_aligned; }; -typedef struct _GstFFMpegDecClass GstFFMpegDecClass; +typedef struct _GstFFMpegVidDecClass GstFFMpegVidDecClass; -struct _GstFFMpegDecClass +struct _GstFFMpegVidDecClass { GstElementClass parent_class; @@ -158,7 +152,7 @@ struct _GstFFMpegDecClass static const GstTSInfo ts_info_none = { -1, -1, -1, -1 }; static const GstTSInfo * -gst_ts_info_store (GstFFMpegDec * dec, GstClockTime timestamp, +gst_ts_info_store (GstFFMpegVidDec * dec, GstClockTime timestamp, GstClockTime duration, gint64 offset) { gint idx = dec->ts_idx; @@ -172,7 +166,7 @@ gst_ts_info_store (GstFFMpegDec * dec, GstClockTime timestamp, } static const GstTSInfo * -gst_ts_info_get (GstFFMpegDec * dec, gint idx) +gst_ts_info_get (GstFFMpegVidDec * dec, gint idx) { if (G_UNLIKELY (idx < 0 || idx > MAX_TS_MASK)) return GST_TS_INFO_NONE; @@ -181,14 +175,14 @@ gst_ts_info_get (GstFFMpegDec * dec, gint idx) } #define GST_TYPE_FFMPEGDEC \ - (gst_ffmpegdec_get_type()) + (gst_ffmpegviddec_get_type()) #define GST_FFMPEGDEC(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_FFMPEGDEC,GstFFMpegDec)) -#define GST_FFMPEGDEC_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_FFMPEGDEC,GstFFMpegDecClass)) + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_FFMPEGDEC,GstFFMpegVidDec)) +#define GST_FFMPEGVIDDEC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_FFMPEGDEC,GstFFMpegVidDecClass)) #define GST_IS_FFMPEGDEC(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_FFMPEGDEC)) -#define GST_IS_FFMPEGDEC_CLASS(klass) \ +#define GST_IS_FFMPEGVIDDEC_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_FFMPEGDEC)) #define DEFAULT_LOWRES 0 @@ -213,44 +207,44 @@ enum }; /* A number of function prototypes are given so we can refer to them later. */ -static void gst_ffmpegdec_base_init (GstFFMpegDecClass * klass); -static void gst_ffmpegdec_class_init (GstFFMpegDecClass * klass); -static void gst_ffmpegdec_init (GstFFMpegDec * ffmpegdec); -static void gst_ffmpegdec_finalize (GObject * object); +static void gst_ffmpegviddec_base_init (GstFFMpegVidDecClass * klass); +static void gst_ffmpegviddec_class_init (GstFFMpegVidDecClass * klass); +static void gst_ffmpegviddec_init (GstFFMpegVidDec * ffmpegdec); +static void gst_ffmpegviddec_finalize (GObject * object); -static gboolean gst_ffmpegdec_query (GstPad * pad, GstQuery * query); -static gboolean gst_ffmpegdec_src_event (GstPad * pad, GstEvent * event); +static gboolean gst_ffmpegviddec_query (GstPad * pad, GstQuery * query); +static gboolean gst_ffmpegviddec_src_event (GstPad * pad, GstEvent * event); -static gboolean gst_ffmpegdec_setcaps (GstPad * pad, GstCaps * caps); -static gboolean gst_ffmpegdec_sink_event (GstPad * pad, GstEvent * event); -static GstFlowReturn gst_ffmpegdec_chain (GstPad * pad, GstBuffer * buf); +static gboolean gst_ffmpegviddec_setcaps (GstPad * pad, GstCaps * caps); +static gboolean gst_ffmpegviddec_sink_event (GstPad * pad, GstEvent * event); +static GstFlowReturn gst_ffmpegviddec_chain (GstPad * pad, GstBuffer * buf); -static GstStateChangeReturn gst_ffmpegdec_change_state (GstElement * element, +static GstStateChangeReturn gst_ffmpegviddec_change_state (GstElement * element, GstStateChange transition); -static void gst_ffmpegdec_set_property (GObject * object, +static void gst_ffmpegviddec_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec); -static void gst_ffmpegdec_get_property (GObject * object, +static void gst_ffmpegviddec_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); -static gboolean gst_ffmpegdec_negotiate (GstFFMpegDec * ffmpegdec, +static gboolean gst_ffmpegviddec_negotiate (GstFFMpegVidDec * ffmpegdec, gboolean force); /* some sort of bufferpool handling, but different */ -static int gst_ffmpegdec_get_buffer (AVCodecContext * context, +static int gst_ffmpegviddec_get_buffer (AVCodecContext * context, AVFrame * picture); -static void gst_ffmpegdec_release_buffer (AVCodecContext * context, +static void gst_ffmpegviddec_release_buffer (AVCodecContext * context, AVFrame * picture); -static void gst_ffmpegdec_drain (GstFFMpegDec * ffmpegdec); +static void gst_ffmpegviddec_drain (GstFFMpegVidDec * ffmpegdec); #define GST_FFDEC_PARAMS_QDATA g_quark_from_static_string("ffdec-params") static GstElementClass *parent_class = NULL; -#define GST_FFMPEGDEC_TYPE_LOWRES (gst_ffmpegdec_lowres_get_type()) +#define GST_FFMPEGVIDDEC_TYPE_LOWRES (gst_ffmpegviddec_lowres_get_type()) static GType -gst_ffmpegdec_lowres_get_type (void) +gst_ffmpegviddec_lowres_get_type (void) { static GType ffmpegdec_lowres_type = 0; @@ -263,15 +257,15 @@ gst_ffmpegdec_lowres_get_type (void) }; ffmpegdec_lowres_type = - g_enum_register_static ("GstFFMpegDecLowres", ffmpegdec_lowres); + g_enum_register_static ("GstFFMpegVidDecLowres", ffmpegdec_lowres); } return ffmpegdec_lowres_type; } -#define GST_FFMPEGDEC_TYPE_SKIPFRAME (gst_ffmpegdec_skipframe_get_type()) +#define GST_FFMPEGVIDDEC_TYPE_SKIPFRAME (gst_ffmpegviddec_skipframe_get_type()) static GType -gst_ffmpegdec_skipframe_get_type (void) +gst_ffmpegviddec_skipframe_get_type (void) { static GType ffmpegdec_skipframe_type = 0; @@ -285,20 +279,21 @@ gst_ffmpegdec_skipframe_get_type (void) }; ffmpegdec_skipframe_type = - g_enum_register_static ("GstFFMpegDecSkipFrame", ffmpegdec_skipframe); + g_enum_register_static ("GstFFMpegVidDecSkipFrame", + ffmpegdec_skipframe); } return ffmpegdec_skipframe_type; } static void -gst_ffmpegdec_base_init (GstFFMpegDecClass * klass) +gst_ffmpegviddec_base_init (GstFFMpegVidDecClass * klass) { GstElementClass *element_class = GST_ELEMENT_CLASS (klass); GstPadTemplate *sinktempl, *srctempl; GstCaps *sinkcaps, *srccaps; AVCodec *in_plugin; - gchar *longname, *classification, *description; + gchar *longname, *description; in_plugin = (AVCodec *) g_type_get_qdata (G_OBJECT_CLASS_TYPE (klass), @@ -307,16 +302,13 @@ gst_ffmpegdec_base_init (GstFFMpegDecClass * klass) /* construct the element details struct */ longname = g_strdup_printf ("FFmpeg %s decoder", in_plugin->long_name); - classification = g_strdup_printf ("Codec/Decoder/%s", - (in_plugin->type == AVMEDIA_TYPE_VIDEO) ? "Video" : "Audio"); description = g_strdup_printf ("FFmpeg %s decoder", in_plugin->name); - gst_element_class_set_details_simple (element_class, longname, classification, - description, + gst_element_class_set_details_simple (element_class, longname, + "Codec/Decoder/Video", description, "Wim Taymans <wim.taymans@gmail.com>, " "Ronald Bultje <rbultje@ronald.bitfreak.net>, " "Edward Hervey <bilboed@bilboed.com>"); g_free (longname); - g_free (classification); g_free (description); /* get the caps */ @@ -325,16 +317,7 @@ gst_ffmpegdec_base_init (GstFFMpegDecClass * klass) GST_DEBUG ("Couldn't get sink caps for decoder '%s'", in_plugin->name); sinkcaps = gst_caps_from_string ("unknown/unknown"); } - if (in_plugin->type == AVMEDIA_TYPE_VIDEO) { - srccaps = gst_caps_from_string ("video/x-raw-rgb; video/x-raw-yuv"); - } else { - srccaps = gst_ffmpeg_codectype_to_audio_caps (NULL, - in_plugin->id, FALSE, in_plugin); - } - if (!srccaps) { - GST_DEBUG ("Couldn't get source caps for decoder '%s'", in_plugin->name); - srccaps = gst_caps_from_string ("unknown/unknown"); - } + srccaps = gst_caps_from_string ("video/x-raw-rgb; video/x-raw-yuv"); /* pad templates */ sinktempl = gst_pad_template_new ("sink", GST_PAD_SINK, @@ -350,17 +333,17 @@ gst_ffmpegdec_base_init (GstFFMpegDecClass * klass) } static void -gst_ffmpegdec_class_init (GstFFMpegDecClass * klass) +gst_ffmpegviddec_class_init (GstFFMpegVidDecClass * klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass); parent_class = g_type_class_peek_parent (klass); - gobject_class->finalize = gst_ffmpegdec_finalize; + gobject_class->finalize = gst_ffmpegviddec_finalize; - gobject_class->set_property = gst_ffmpegdec_set_property; - gobject_class->get_property = gst_ffmpegdec_get_property; + gobject_class->set_property = gst_ffmpegviddec_set_property; + gobject_class->get_property = gst_ffmpegviddec_get_property; if (klass->in_plugin->type == AVMEDIA_TYPE_VIDEO) { int caps; @@ -368,12 +351,13 @@ gst_ffmpegdec_class_init (GstFFMpegDecClass * klass) g_object_class_install_property (gobject_class, PROP_SKIPFRAME, g_param_spec_enum ("skip-frame", "Skip frames", "Which types of frames to skip during decoding", - GST_FFMPEGDEC_TYPE_SKIPFRAME, 0, + GST_FFMPEGVIDDEC_TYPE_SKIPFRAME, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (gobject_class, PROP_LOWRES, g_param_spec_enum ("lowres", "Low resolution", - "At which resolution to decode images", GST_FFMPEGDEC_TYPE_LOWRES, - 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + "At which resolution to decode images", + GST_FFMPEGVIDDEC_TYPE_LOWRES, 0, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (gobject_class, PROP_DIRECT_RENDERING, g_param_spec_boolean ("direct-rendering", "Direct Rendering", "Enable direct rendering", DEFAULT_DIRECT_RENDERING, @@ -403,32 +387,32 @@ gst_ffmpegdec_class_init (GstFFMpegDecClass * klass) } } - gstelement_class->change_state = gst_ffmpegdec_change_state; + gstelement_class->change_state = gst_ffmpegviddec_change_state; } static void -gst_ffmpegdec_init (GstFFMpegDec * ffmpegdec) +gst_ffmpegviddec_init (GstFFMpegVidDec * ffmpegdec) { - GstFFMpegDecClass *oclass; + GstFFMpegVidDecClass *oclass; - oclass = (GstFFMpegDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec)); + oclass = (GstFFMpegVidDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec)); /* setup pads */ ffmpegdec->sinkpad = gst_pad_new_from_template (oclass->sinktempl, "sink"); gst_pad_set_setcaps_function (ffmpegdec->sinkpad, - GST_DEBUG_FUNCPTR (gst_ffmpegdec_setcaps)); + GST_DEBUG_FUNCPTR (gst_ffmpegviddec_setcaps)); gst_pad_set_event_function (ffmpegdec->sinkpad, - GST_DEBUG_FUNCPTR (gst_ffmpegdec_sink_event)); + GST_DEBUG_FUNCPTR (gst_ffmpegviddec_sink_event)); gst_pad_set_chain_function (ffmpegdec->sinkpad, - GST_DEBUG_FUNCPTR (gst_ffmpegdec_chain)); + GST_DEBUG_FUNCPTR (gst_ffmpegviddec_chain)); gst_element_add_pad (GST_ELEMENT (ffmpegdec), ffmpegdec->sinkpad); ffmpegdec->srcpad = gst_pad_new_from_template (oclass->srctempl, "src"); gst_pad_use_fixed_caps (ffmpegdec->srcpad); gst_pad_set_event_function (ffmpegdec->srcpad, - GST_DEBUG_FUNCPTR (gst_ffmpegdec_src_event)); + GST_DEBUG_FUNCPTR (gst_ffmpegviddec_src_event)); gst_pad_set_query_function (ffmpegdec->srcpad, - GST_DEBUG_FUNCPTR (gst_ffmpegdec_query)); + GST_DEBUG_FUNCPTR (gst_ffmpegviddec_query)); gst_element_add_pad (GST_ELEMENT (ffmpegdec), ffmpegdec->srcpad); /* some ffmpeg data */ @@ -456,9 +440,9 @@ gst_ffmpegdec_init (GstFFMpegDec * ffmpegdec) } static void -gst_ffmpegdec_finalize (GObject * object) +gst_ffmpegviddec_finalize (GObject * object) { - GstFFMpegDec *ffmpegdec = (GstFFMpegDec *) object; + GstFFMpegVidDec *ffmpegdec = (GstFFMpegVidDec *) object; if (ffmpegdec->context != NULL) { av_free (ffmpegdec->context); @@ -474,12 +458,12 @@ gst_ffmpegdec_finalize (GObject * object) } static gboolean -gst_ffmpegdec_query (GstPad * pad, GstQuery * query) +gst_ffmpegviddec_query (GstPad * pad, GstQuery * query) { - GstFFMpegDec *ffmpegdec; + GstFFMpegVidDec *ffmpegdec; gboolean res = FALSE; - ffmpegdec = (GstFFMpegDec *) gst_pad_get_parent (pad); + ffmpegdec = (GstFFMpegVidDec *) gst_pad_get_parent (pad); switch (GST_QUERY_TYPE (query)) { case GST_QUERY_LATENCY: @@ -521,7 +505,7 @@ gst_ffmpegdec_query (GstPad * pad, GstQuery * query) } static void -gst_ffmpegdec_reset_ts (GstFFMpegDec * ffmpegdec) +gst_ffmpegviddec_reset_ts (GstFFMpegVidDec * ffmpegdec) { ffmpegdec->last_in = GST_CLOCK_TIME_NONE; ffmpegdec->last_diff = GST_CLOCK_TIME_NONE; @@ -533,7 +517,7 @@ gst_ffmpegdec_reset_ts (GstFFMpegDec * ffmpegdec) } static void -gst_ffmpegdec_update_qos (GstFFMpegDec * ffmpegdec, gdouble proportion, +gst_ffmpegviddec_update_qos (GstFFMpegVidDec * ffmpegdec, gdouble proportion, GstClockTime timestamp) { GST_LOG_OBJECT (ffmpegdec, "update QOS: %f, %" GST_TIME_FORMAT, @@ -546,15 +530,15 @@ gst_ffmpegdec_update_qos (GstFFMpegDec * ffmpegdec, gdouble proportion, } static void -gst_ffmpegdec_reset_qos (GstFFMpegDec * ffmpegdec) +gst_ffmpegviddec_reset_qos (GstFFMpegVidDec * ffmpegdec) { - gst_ffmpegdec_update_qos (ffmpegdec, 0.5, GST_CLOCK_TIME_NONE); + gst_ffmpegviddec_update_qos (ffmpegdec, 0.5, GST_CLOCK_TIME_NONE); ffmpegdec->processed = 0; ffmpegdec->dropped = 0; } static void -gst_ffmpegdec_read_qos (GstFFMpegDec * ffmpegdec, gdouble * proportion, +gst_ffmpegviddec_read_qos (GstFFMpegVidDec * ffmpegdec, gdouble * proportion, GstClockTime * timestamp) { GST_OBJECT_LOCK (ffmpegdec); @@ -564,12 +548,12 @@ gst_ffmpegdec_read_qos (GstFFMpegDec * ffmpegdec, gdouble * proportion, } static gboolean -gst_ffmpegdec_src_event (GstPad * pad, GstEvent * event) +gst_ffmpegviddec_src_event (GstPad * pad, GstEvent * event) { - GstFFMpegDec *ffmpegdec; + GstFFMpegVidDec *ffmpegdec; gboolean res; - ffmpegdec = (GstFFMpegDec *) gst_pad_get_parent (pad); + ffmpegdec = (GstFFMpegVidDec *) gst_pad_get_parent (pad); switch (GST_EVENT_TYPE (event)) { case GST_EVENT_QOS: @@ -581,7 +565,7 @@ gst_ffmpegdec_src_event (GstPad * pad, GstEvent * event) gst_event_parse_qos (event, &proportion, &diff, ×tamp); /* update our QoS values */ - gst_ffmpegdec_update_qos (ffmpegdec, proportion, timestamp + diff); + gst_ffmpegviddec_update_qos (ffmpegdec, proportion, timestamp + diff); /* forward upstream */ res = gst_pad_push_event (ffmpegdec->sinkpad, event); @@ -600,7 +584,7 @@ gst_ffmpegdec_src_event (GstPad * pad, GstEvent * event) /* with LOCK */ static void -gst_ffmpegdec_close (GstFFMpegDec * ffmpegdec) +gst_ffmpegviddec_close (GstFFMpegVidDec * ffmpegdec) { if (!ffmpegdec->opened) return; @@ -643,11 +627,11 @@ gst_ffmpegdec_close (GstFFMpegDec * ffmpegdec) /* with LOCK */ static gboolean -gst_ffmpegdec_open (GstFFMpegDec * ffmpegdec) +gst_ffmpegviddec_open (GstFFMpegVidDec * ffmpegdec) { - GstFFMpegDecClass *oclass; + GstFFMpegVidDecClass *oclass; - oclass = (GstFFMpegDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec)); + oclass = (GstFFMpegVidDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec)); if (gst_ffmpeg_avcodec_open (ffmpegdec->context, oclass->in_plugin) < 0) goto could_not_open; @@ -697,25 +681,14 @@ gst_ffmpegdec_open (GstFFMpegDec * ffmpegdec) break; } - switch (oclass->in_plugin->type) { - case AVMEDIA_TYPE_VIDEO: - ffmpegdec->format.video.width = 0; - ffmpegdec->format.video.height = 0; - ffmpegdec->format.video.clip_width = -1; - ffmpegdec->format.video.clip_height = -1; - ffmpegdec->format.video.pix_fmt = PIX_FMT_NB; - ffmpegdec->format.video.interlaced = FALSE; - break; - case AVMEDIA_TYPE_AUDIO: - ffmpegdec->format.audio.samplerate = 0; - ffmpegdec->format.audio.channels = 0; - ffmpegdec->format.audio.depth = 0; - break; - default: - break; - } + ffmpegdec->format.video.width = 0; + ffmpegdec->format.video.height = 0; + ffmpegdec->format.video.clip_width = -1; + ffmpegdec->format.video.clip_height = -1; + ffmpegdec->format.video.pix_fmt = PIX_FMT_NB; + ffmpegdec->format.video.interlaced = FALSE; - gst_ffmpegdec_reset_ts (ffmpegdec); + gst_ffmpegviddec_reset_ts (ffmpegdec); /* FIXME, reset_qos holds the LOCK */ ffmpegdec->proportion = 0.0; ffmpegdec->earliest_time = -1; @@ -725,7 +698,7 @@ gst_ffmpegdec_open (GstFFMpegDec * ffmpegdec) /* ERRORS */ could_not_open: { - gst_ffmpegdec_close (ffmpegdec); + gst_ffmpegviddec_close (ffmpegdec); GST_DEBUG_OBJECT (ffmpegdec, "ffdec_%s: Failed to open FFMPEG codec", oclass->in_plugin->name); return FALSE; @@ -733,17 +706,17 @@ could_not_open: } static gboolean -gst_ffmpegdec_setcaps (GstPad * pad, GstCaps * caps) +gst_ffmpegviddec_setcaps (GstPad * pad, GstCaps * caps) { - GstFFMpegDec *ffmpegdec; - GstFFMpegDecClass *oclass; + GstFFMpegVidDec *ffmpegdec; + GstFFMpegVidDecClass *oclass; GstStructure *structure; const GValue *par; const GValue *fps; gboolean ret = TRUE; - ffmpegdec = (GstFFMpegDec *) (gst_pad_get_parent (pad)); - oclass = (GstFFMpegDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec)); + ffmpegdec = (GstFFMpegVidDec *) (gst_pad_get_parent (pad)); + oclass = (GstFFMpegVidDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec)); GST_DEBUG_OBJECT (pad, "setcaps called"); @@ -757,9 +730,9 @@ gst_ffmpegdec_setcaps (GstPad * pad, GstCaps * caps) /* close old session */ if (ffmpegdec->opened) { GST_OBJECT_UNLOCK (ffmpegdec); - gst_ffmpegdec_drain (ffmpegdec); + gst_ffmpegviddec_drain (ffmpegdec); GST_OBJECT_LOCK (ffmpegdec); - gst_ffmpegdec_close (ffmpegdec); + gst_ffmpegviddec_close (ffmpegdec); /* and reset the defaults that were set when a context is created */ avcodec_get_context_defaults (ffmpegdec->context); @@ -767,8 +740,8 @@ gst_ffmpegdec_setcaps (GstPad * pad, GstCaps * caps) /* set buffer functions */ if (oclass->in_plugin->type == AVMEDIA_TYPE_VIDEO) { - ffmpegdec->context->get_buffer = gst_ffmpegdec_get_buffer; - ffmpegdec->context->release_buffer = gst_ffmpegdec_release_buffer; + ffmpegdec->context->get_buffer = gst_ffmpegviddec_get_buffer; + ffmpegdec->context->release_buffer = gst_ffmpegviddec_release_buffer; ffmpegdec->context->draw_horiz_band = NULL; } @@ -897,7 +870,7 @@ gst_ffmpegdec_setcaps (GstPad * pad, GstCaps * caps) /* open codec - we don't select an output pix_fmt yet, * simply because we don't know! We only get it * during playback... */ - if (!gst_ffmpegdec_open (ffmpegdec)) + if (!gst_ffmpegviddec_open (ffmpegdec)) goto open_failed; /* clipping region */ @@ -939,7 +912,7 @@ open_failed: } static GstFlowReturn -alloc_output_buffer (GstFFMpegDec * ffmpegdec, GstBuffer ** outbuf, +alloc_output_buffer (GstFFMpegVidDec * ffmpegdec, GstBuffer ** outbuf, gint width, gint height) { GstFlowReturn ret; @@ -951,7 +924,7 @@ alloc_output_buffer (GstFFMpegDec * ffmpegdec, GstBuffer ** outbuf, GST_LOG_OBJECT (ffmpegdec, "alloc output buffer"); /* see if we need renegotiation */ - if (G_UNLIKELY (!gst_ffmpegdec_negotiate (ffmpegdec, FALSE))) + if (G_UNLIKELY (!gst_ffmpegviddec_negotiate (ffmpegdec, FALSE))) goto negotiate_failed; /* get the size of the gstreamer output buffer given a @@ -1007,15 +980,18 @@ alloc_failed: } static int -gst_ffmpegdec_get_buffer (AVCodecContext * context, AVFrame * picture) +gst_ffmpegviddec_get_buffer (AVCodecContext * context, AVFrame * picture) { GstBuffer *buf = NULL; - GstFFMpegDec *ffmpegdec; + GstFFMpegVidDec *ffmpegdec; gint width, height; gint coded_width, coded_height; gint res; + GstFlowReturn ret; + gint clip_width, clip_height; - ffmpegdec = (GstFFMpegDec *) context->opaque; + + ffmpegdec = (GstFFMpegVidDec *) context->opaque; GST_DEBUG_OBJECT (ffmpegdec, "getting buffer"); @@ -1046,55 +1022,38 @@ gst_ffmpegdec_get_buffer (AVCodecContext * context, AVFrame * picture) return res; } - switch (context->codec_type) { - case AVMEDIA_TYPE_VIDEO: - /* some ffmpeg video plugins don't see the point in setting codec_type ... */ - case AVMEDIA_TYPE_UNKNOWN: - { - GstFlowReturn ret; - gint clip_width, clip_height; - - /* take final clipped output size */ - if ((clip_width = ffmpegdec->format.video.clip_width) == -1) - clip_width = width; - if ((clip_height = ffmpegdec->format.video.clip_height) == -1) - clip_height = height; - - GST_LOG_OBJECT (ffmpegdec, "raw outsize %d/%d", width, height); + /* take final clipped output size */ + if ((clip_width = ffmpegdec->format.video.clip_width) == -1) + clip_width = width; + if ((clip_height = ffmpegdec->format.video.clip_height) == -1) + clip_height = height; - /* this is the size ffmpeg needs for the buffer */ - avcodec_align_dimensions (context, &width, &height); + GST_LOG_OBJECT (ffmpegdec, "raw outsize %d/%d", width, height); - GST_LOG_OBJECT (ffmpegdec, "aligned outsize %d/%d, clip %d/%d", - width, height, clip_width, clip_height); + /* this is the size ffmpeg needs for the buffer */ + avcodec_align_dimensions (context, &width, &height); - if (width != clip_width || height != clip_height) { - /* We can't alloc if we need to clip the output buffer later */ - GST_LOG_OBJECT (ffmpegdec, "we need clipping, fallback alloc"); - return avcodec_default_get_buffer (context, picture); - } + GST_LOG_OBJECT (ffmpegdec, "aligned outsize %d/%d, clip %d/%d", + width, height, clip_width, clip_height); - /* alloc with aligned dimensions for ffmpeg */ - ret = alloc_output_buffer (ffmpegdec, &buf, width, height); - if (G_UNLIKELY (ret != GST_FLOW_OK)) { - /* alloc default buffer when we can't get one from downstream */ - GST_LOG_OBJECT (ffmpegdec, "alloc failed, fallback alloc"); - return avcodec_default_get_buffer (context, picture); - } + if (width != clip_width || height != clip_height) { + /* We can't alloc if we need to clip the output buffer later */ + GST_LOG_OBJECT (ffmpegdec, "we need clipping, fallback alloc"); + return avcodec_default_get_buffer (context, picture); + } - /* copy the right pointers and strides in the picture object */ - gst_ffmpeg_avpicture_fill ((AVPicture *) picture, - GST_BUFFER_DATA (buf), context->pix_fmt, width, height); - break; - } - case AVMEDIA_TYPE_AUDIO: - default: - GST_ERROR_OBJECT (ffmpegdec, - "_get_buffer() should never get called for non-video buffers !"); - g_assert_not_reached (); - break; + /* alloc with aligned dimensions for ffmpeg */ + ret = alloc_output_buffer (ffmpegdec, &buf, width, height); + if (G_UNLIKELY (ret != GST_FLOW_OK)) { + /* alloc default buffer when we can't get one from downstream */ + GST_LOG_OBJECT (ffmpegdec, "alloc failed, fallback alloc"); + return avcodec_default_get_buffer (context, picture); } + /* copy the right pointers and strides in the picture object */ + gst_ffmpeg_avpicture_fill ((AVPicture *) picture, + GST_BUFFER_DATA (buf), context->pix_fmt, width, height); + /* tell ffmpeg we own this buffer, tranfer the ref we have on the buffer to * the opaque data. */ picture->type = FF_BUFFER_TYPE_USER; @@ -1114,13 +1073,13 @@ gst_ffmpegdec_get_buffer (AVCodecContext * context, AVFrame * picture) } static void -gst_ffmpegdec_release_buffer (AVCodecContext * context, AVFrame * picture) +gst_ffmpegviddec_release_buffer (AVCodecContext * context, AVFrame * picture) { gint i; GstBuffer *buf; - GstFFMpegDec *ffmpegdec; + GstFFMpegVidDec *ffmpegdec; - ffmpegdec = (GstFFMpegDec *) context->opaque; + ffmpegdec = (GstFFMpegVidDec *) context->opaque; /* check if it was our buffer */ if (picture->opaque == NULL) { @@ -1151,7 +1110,7 @@ gst_ffmpegdec_release_buffer (AVCodecContext * context, AVFrame * picture) } static void -gst_ffmpegdec_add_pixel_aspect_ratio (GstFFMpegDec * ffmpegdec, +gst_ffmpegviddec_add_pixel_aspect_ratio (GstFFMpegVidDec * ffmpegdec, GstStructure * s) { gboolean demuxer_par_set = FALSE; @@ -1229,65 +1188,41 @@ no_par: } static gboolean -gst_ffmpegdec_negotiate (GstFFMpegDec * ffmpegdec, gboolean force) +gst_ffmpegviddec_negotiate (GstFFMpegVidDec * ffmpegdec, gboolean force) { - GstFFMpegDecClass *oclass; + GstFFMpegVidDecClass *oclass; GstCaps *caps; - - oclass = (GstFFMpegDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec)); - - switch (oclass->in_plugin->type) { - case AVMEDIA_TYPE_VIDEO: - if (!force && ffmpegdec->format.video.width == ffmpegdec->context->width - && ffmpegdec->format.video.height == ffmpegdec->context->height - && ffmpegdec->format.video.fps_n == ffmpegdec->format.video.old_fps_n - && ffmpegdec->format.video.fps_d == ffmpegdec->format.video.old_fps_d - && ffmpegdec->format.video.pix_fmt == ffmpegdec->context->pix_fmt - && ffmpegdec->format.video.par_n == - ffmpegdec->context->sample_aspect_ratio.num - && ffmpegdec->format.video.par_d == - ffmpegdec->context->sample_aspect_ratio.den) - return TRUE; - GST_DEBUG_OBJECT (ffmpegdec, - "Renegotiating video from %dx%d@ %d:%d PAR %d/%d fps to %dx%d@ %d:%d PAR %d/%d fps", - ffmpegdec->format.video.width, ffmpegdec->format.video.height, - ffmpegdec->format.video.par_n, ffmpegdec->format.video.par_d, - ffmpegdec->format.video.old_fps_n, ffmpegdec->format.video.old_fps_n, - ffmpegdec->context->width, ffmpegdec->context->height, - ffmpegdec->context->sample_aspect_ratio.num, - ffmpegdec->context->sample_aspect_ratio.den, - ffmpegdec->format.video.fps_n, ffmpegdec->format.video.fps_d); - ffmpegdec->format.video.width = ffmpegdec->context->width; - ffmpegdec->format.video.height = ffmpegdec->context->height; - ffmpegdec->format.video.old_fps_n = ffmpegdec->format.video.fps_n; - ffmpegdec->format.video.old_fps_d = ffmpegdec->format.video.fps_d; - ffmpegdec->format.video.pix_fmt = ffmpegdec->context->pix_fmt; - ffmpegdec->format.video.par_n = - ffmpegdec->context->sample_aspect_ratio.num; - ffmpegdec->format.video.par_d = - ffmpegdec->context->sample_aspect_ratio.den; - break; - case AVMEDIA_TYPE_AUDIO: - { - gint depth = av_smp_format_depth (ffmpegdec->context->sample_fmt); - if (!force && ffmpegdec->format.audio.samplerate == - ffmpegdec->context->sample_rate && - ffmpegdec->format.audio.channels == ffmpegdec->context->channels && - ffmpegdec->format.audio.depth == depth) - return TRUE; - GST_DEBUG_OBJECT (ffmpegdec, - "Renegotiating audio from %dHz@%dchannels (%d) to %dHz@%dchannels (%d)", - ffmpegdec->format.audio.samplerate, ffmpegdec->format.audio.channels, - ffmpegdec->format.audio.depth, - ffmpegdec->context->sample_rate, ffmpegdec->context->channels, depth); - ffmpegdec->format.audio.samplerate = ffmpegdec->context->sample_rate; - ffmpegdec->format.audio.channels = ffmpegdec->context->channels; - ffmpegdec->format.audio.depth = depth; - } - break; - default: - break; - } + gint width, height; + gboolean interlaced; + + oclass = (GstFFMpegVidDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec)); + + if (!force && ffmpegdec->format.video.width == ffmpegdec->context->width + && ffmpegdec->format.video.height == ffmpegdec->context->height + && ffmpegdec->format.video.fps_n == ffmpegdec->format.video.old_fps_n + && ffmpegdec->format.video.fps_d == ffmpegdec->format.video.old_fps_d + && ffmpegdec->format.video.pix_fmt == ffmpegdec->context->pix_fmt + && ffmpegdec->format.video.par_n == + ffmpegdec->context->sample_aspect_ratio.num + && ffmpegdec->format.video.par_d == + ffmpegdec->context->sample_aspect_ratio.den) + return TRUE; + GST_DEBUG_OBJECT (ffmpegdec, + "Renegotiating video from %dx%d@ %d:%d PAR %d/%d fps to %dx%d@ %d:%d PAR %d/%d fps", + ffmpegdec->format.video.width, ffmpegdec->format.video.height, + ffmpegdec->format.video.par_n, ffmpegdec->format.video.par_d, + ffmpegdec->format.video.old_fps_n, ffmpegdec->format.video.old_fps_n, + ffmpegdec->context->width, ffmpegdec->context->height, + ffmpegdec->context->sample_aspect_ratio.num, + ffmpegdec->context->sample_aspect_ratio.den, + ffmpegdec->format.video.fps_n, ffmpegdec->format.video.fps_d); + ffmpegdec->format.video.width = ffmpegdec->context->width; + ffmpegdec->format.video.height = ffmpegdec->context->height; + ffmpegdec->format.video.old_fps_n = ffmpegdec->format.video.fps_n; + ffmpegdec->format.video.old_fps_d = ffmpegdec->format.video.fps_d; + ffmpegdec->format.video.pix_fmt = ffmpegdec->context->pix_fmt; + ffmpegdec->format.video.par_n = ffmpegdec->context->sample_aspect_ratio.num; + ffmpegdec->format.video.par_d = ffmpegdec->context->sample_aspect_ratio.den; caps = gst_ffmpeg_codectype_to_caps (oclass->in_plugin->type, ffmpegdec->context, oclass->in_plugin->id, FALSE); @@ -1295,44 +1230,28 @@ gst_ffmpegdec_negotiate (GstFFMpegDec * ffmpegdec, gboolean force) if (caps == NULL) goto no_caps; - switch (oclass->in_plugin->type) { - case AVMEDIA_TYPE_VIDEO: - { - gint width, height; - gboolean interlaced; + width = ffmpegdec->format.video.clip_width; + height = ffmpegdec->format.video.clip_height; + interlaced = ffmpegdec->format.video.interlaced; - width = ffmpegdec->format.video.clip_width; - height = ffmpegdec->format.video.clip_height; - interlaced = ffmpegdec->format.video.interlaced; - - if (width != -1 && height != -1) { - /* overwrite the output size with the dimension of the - * clipping region but only if they are smaller. */ - if (width < ffmpegdec->context->width) - gst_caps_set_simple (caps, "width", G_TYPE_INT, width, NULL); - if (height < ffmpegdec->context->height) - gst_caps_set_simple (caps, "height", G_TYPE_INT, height, NULL); - } - gst_caps_set_simple (caps, "interlaced", G_TYPE_BOOLEAN, interlaced, - NULL); - - /* If a demuxer provided a framerate then use it (#313970) */ - if (ffmpegdec->format.video.fps_n != -1) { - gst_caps_set_simple (caps, "framerate", - GST_TYPE_FRACTION, ffmpegdec->format.video.fps_n, - ffmpegdec->format.video.fps_d, NULL); - } - gst_ffmpegdec_add_pixel_aspect_ratio (ffmpegdec, - gst_caps_get_structure (caps, 0)); - break; - } - case AVMEDIA_TYPE_AUDIO: - { - break; - } - default: - break; + if (width != -1 && height != -1) { + /* overwrite the output size with the dimension of the + * clipping region but only if they are smaller. */ + if (width < ffmpegdec->context->width) + gst_caps_set_simple (caps, "width", G_TYPE_INT, width, NULL); + if (height < ffmpegdec->context->height) + gst_caps_set_simple (caps, "height", G_TYPE_INT, height, NULL); } + gst_caps_set_simple (caps, "interlaced", G_TYPE_BOOLEAN, interlaced, NULL); + + /* If a demuxer provided a framerate then use it (#313970) */ + if (ffmpegdec->format.video.fps_n != -1) { + gst_caps_set_simple (caps, "framerate", + GST_TYPE_FRACTION, ffmpegdec->format.video.fps_n, + ffmpegdec->format.video.fps_d, NULL); + } + gst_ffmpegviddec_add_pixel_aspect_ratio (ffmpegdec, + gst_caps_get_structure (caps, 0)); if (!gst_pad_set_caps (ffmpegdec->srcpad, caps)) goto caps_failed; @@ -1382,7 +1301,7 @@ caps_failed: * entirely. */ static gboolean -gst_ffmpegdec_do_qos (GstFFMpegDec * ffmpegdec, GstClockTime timestamp, +gst_ffmpegviddec_do_qos (GstFFMpegVidDec * ffmpegdec, GstClockTime timestamp, gboolean * mode_switch) { GstClockTimeDiff diff; @@ -1397,7 +1316,7 @@ gst_ffmpegdec_do_qos (GstFFMpegDec * ffmpegdec, GstClockTime timestamp, goto no_qos; /* get latest QoS observation values */ - gst_ffmpegdec_read_qos (ffmpegdec, &proportion, &earliest_time); + gst_ffmpegviddec_read_qos (ffmpegdec, &proportion, &earliest_time); /* skip qos if we have no observation (yet) */ if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (earliest_time))) { @@ -1492,7 +1411,7 @@ drop_qos: /* returns TRUE if buffer is within segment, else FALSE. * if Buffer is on segment border, it's timestamp and duration will be clipped */ static gboolean -clip_video_buffer (GstFFMpegDec * dec, GstBuffer * buf, GstClockTime in_ts, +clip_video_buffer (GstFFMpegVidDec * dec, GstBuffer * buf, GstClockTime in_ts, GstClockTime in_dur) { gboolean res = TRUE; @@ -1546,15 +1465,15 @@ beach: /* figure out if the current picture is a keyframe, return TRUE if that is * the case. */ static gboolean -check_keyframe (GstFFMpegDec * ffmpegdec) +check_keyframe (GstFFMpegVidDec * ffmpegdec) { - GstFFMpegDecClass *oclass; + GstFFMpegVidDecClass *oclass; gboolean is_itype = FALSE; gboolean is_reference = FALSE; gboolean iskeyframe; /* figure out if we are dealing with a keyframe */ - oclass = (GstFFMpegDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec)); + oclass = (GstFFMpegVidDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec)); /* remember that we have B frames, we need this for the DTS -> PTS conversion * code */ @@ -1585,7 +1504,7 @@ check_keyframe (GstFFMpegDec * ffmpegdec) /* get an outbuf buffer with the current picture */ static GstFlowReturn -get_output_buffer (GstFFMpegDec * ffmpegdec, GstBuffer ** outbuf) +get_output_buffer (GstFFMpegVidDec * ffmpegdec, GstBuffer ** outbuf) { GstFlowReturn ret; @@ -1653,7 +1572,7 @@ alloc_failed: } static void -clear_queued (GstFFMpegDec * ffmpegdec) +clear_queued (GstFFMpegVidDec * ffmpegdec) { g_list_foreach (ffmpegdec->queued, (GFunc) gst_mini_object_unref, NULL); g_list_free (ffmpegdec->queued); @@ -1661,7 +1580,7 @@ clear_queued (GstFFMpegDec * ffmpegdec) } static GstFlowReturn -flush_queued (GstFFMpegDec * ffmpegdec) +flush_queued (GstFFMpegVidDec * ffmpegdec) { GstFlowReturn res = GST_FLOW_OK; @@ -1692,7 +1611,7 @@ gst_avpacket_init (AVPacket * packet, guint8 * data, guint size) packet->size = size; } -/* gst_ffmpegdec_[video|audio]_frame: +/* gst_ffmpegviddec_[video|audio]_frame: * ffmpegdec: * data: pointer to the data to decode * size: size of data in bytes @@ -1706,7 +1625,7 @@ gst_avpacket_init (AVPacket * packet, guint8 * data, guint size) * outbuf being non-NULL. */ static gint -gst_ffmpegdec_video_frame (GstFFMpegDec * ffmpegdec, +gst_ffmpegviddec_video_frame (GstFFMpegVidDec * ffmpegdec, guint8 * data, guint size, const GstTSInfo * dec_info, GstBuffer ** outbuf, GstFlowReturn * ret) { @@ -1731,7 +1650,8 @@ gst_ffmpegdec_video_frame (GstFFMpegDec * ffmpegdec, /* run QoS code, we don't stop decoding the frame when we are late because * else we might skip a reference frame */ - decode = gst_ffmpegdec_do_qos (ffmpegdec, dec_info->timestamp, &mode_switch); + decode = + gst_ffmpegviddec_do_qos (ffmpegdec, dec_info->timestamp, &mode_switch); if (ffmpegdec->is_realvideo && data != NULL) { gint slice_count; @@ -1824,7 +1744,7 @@ gst_ffmpegdec_video_frame (GstFFMpegDec * ffmpegdec, ffmpegdec->picture->interlaced_frame, ffmpegdec->format.video.interlaced); ffmpegdec->format.video.interlaced = ffmpegdec->picture->interlaced_frame; - gst_ffmpegdec_negotiate (ffmpegdec, TRUE); + gst_ffmpegviddec_negotiate (ffmpegdec, TRUE); } @@ -2062,192 +1982,8 @@ clipped: } } -/* returns TRUE if buffer is within segment, else FALSE. - * if Buffer is on segment border, it's timestamp and duration will be clipped */ -static gboolean -clip_audio_buffer (GstFFMpegDec * dec, GstBuffer * buf, GstClockTime in_ts, - GstClockTime in_dur) -{ - GstClockTime stop; - gint64 diff, ctime, cstop; - gboolean res = TRUE; - - GST_LOG_OBJECT (dec, - "timestamp:%" GST_TIME_FORMAT ", duration:%" GST_TIME_FORMAT - ", size %u", GST_TIME_ARGS (in_ts), GST_TIME_ARGS (in_dur), - GST_BUFFER_SIZE (buf)); - - /* can't clip without TIME segment */ - if (G_UNLIKELY (dec->segment.format != GST_FORMAT_TIME)) - goto beach; - - /* we need a start time */ - if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (in_ts))) - goto beach; - - /* trust duration */ - stop = in_ts + in_dur; - - res = gst_segment_clip (&dec->segment, GST_FORMAT_TIME, in_ts, stop, &ctime, - &cstop); - if (G_UNLIKELY (!res)) - goto out_of_segment; - - /* see if some clipping happened */ - if (G_UNLIKELY ((diff = ctime - in_ts) > 0)) { - /* bring clipped time to bytes */ - diff = - gst_util_uint64_scale_int (diff, dec->format.audio.samplerate, - GST_SECOND) * (dec->format.audio.depth * dec->format.audio.channels); - - GST_DEBUG_OBJECT (dec, "clipping start to %" GST_TIME_FORMAT " %" - G_GINT64_FORMAT " bytes", GST_TIME_ARGS (ctime), diff); - - GST_BUFFER_SIZE (buf) -= diff; - GST_BUFFER_DATA (buf) += diff; - } - if (G_UNLIKELY ((diff = stop - cstop) > 0)) { - /* bring clipped time to bytes */ - diff = - gst_util_uint64_scale_int (diff, dec->format.audio.samplerate, - GST_SECOND) * (dec->format.audio.depth * dec->format.audio.channels); - - GST_DEBUG_OBJECT (dec, "clipping stop to %" GST_TIME_FORMAT " %" - G_GINT64_FORMAT " bytes", GST_TIME_ARGS (cstop), diff); - - GST_BUFFER_SIZE (buf) -= diff; - } - GST_BUFFER_TIMESTAMP (buf) = ctime; - GST_BUFFER_DURATION (buf) = cstop - ctime; - -beach: - GST_LOG_OBJECT (dec, "%sdropping", (res ? "not " : "")); - return res; - - /* ERRORS */ -out_of_segment: - { - GST_LOG_OBJECT (dec, "out of segment"); - goto beach; - } -} - -static gint -gst_ffmpegdec_audio_frame (GstFFMpegDec * ffmpegdec, - AVCodec * in_plugin, guint8 * data, guint size, - const GstTSInfo * dec_info, GstBuffer ** outbuf, GstFlowReturn * ret) -{ - gint len = -1; - gint have_data = AVCODEC_MAX_AUDIO_FRAME_SIZE; - GstClockTime out_timestamp, out_duration; - gint64 out_offset; - AVPacket packet; - - GST_DEBUG_OBJECT (ffmpegdec, - "size:%d, offset:%" G_GINT64_FORMAT ", ts:%" GST_TIME_FORMAT ", dur:%" - GST_TIME_FORMAT ", ffmpegdec->next_out:%" GST_TIME_FORMAT, size, - dec_info->offset, GST_TIME_ARGS (dec_info->timestamp), - GST_TIME_ARGS (dec_info->duration), GST_TIME_ARGS (ffmpegdec->next_out)); - - *outbuf = - new_aligned_buffer (AVCODEC_MAX_AUDIO_FRAME_SIZE, - GST_PAD_CAPS (ffmpegdec->srcpad)); - - gst_avpacket_init (&packet, data, size); - len = avcodec_decode_audio3 (ffmpegdec->context, - (int16_t *) GST_BUFFER_DATA (*outbuf), &have_data, &packet); - GST_DEBUG_OBJECT (ffmpegdec, - "Decode audio: len=%d, have_data=%d", len, have_data); - - if (len >= 0 && have_data > 0) { - GST_DEBUG_OBJECT (ffmpegdec, "Creating output buffer"); - if (!gst_ffmpegdec_negotiate (ffmpegdec, FALSE)) { - gst_buffer_unref (*outbuf); - *outbuf = NULL; - len = -1; - goto beach; - } - - /* Buffer size */ - GST_BUFFER_SIZE (*outbuf) = have_data; - - /* - * Timestamps: - * - * 1) Copy input timestamp if valid - * 2) else interpolate from previous input timestamp - */ - /* always take timestamps from the input buffer if any */ - if (GST_CLOCK_TIME_IS_VALID (dec_info->timestamp)) { - out_timestamp = dec_info->timestamp; - } else { - out_timestamp = ffmpegdec->next_out; - } - - /* - * Duration: - * - * 1) calculate based on number of samples - */ - out_duration = gst_util_uint64_scale (have_data, GST_SECOND, - ffmpegdec->format.audio.depth * ffmpegdec->format.audio.channels * - ffmpegdec->format.audio.samplerate); - - /* offset: - * - * Just copy - */ - out_offset = dec_info->offset; - GST_DEBUG_OBJECT (ffmpegdec, - "Buffer created. Size:%d , timestamp:%" GST_TIME_FORMAT " , duration:%" - GST_TIME_FORMAT, have_data, - GST_TIME_ARGS (out_timestamp), GST_TIME_ARGS (out_duration)); - - GST_BUFFER_TIMESTAMP (*outbuf) = out_timestamp; - GST_BUFFER_DURATION (*outbuf) = out_duration; - GST_BUFFER_OFFSET (*outbuf) = out_offset; - gst_buffer_set_caps (*outbuf, GST_PAD_CAPS (ffmpegdec->srcpad)); - - /* the next timestamp we'll use when interpolating */ - if (GST_CLOCK_TIME_IS_VALID (out_timestamp)) - ffmpegdec->next_out = out_timestamp + out_duration; - - /* now see if we need to clip the buffer against the segment boundaries. */ - if (G_UNLIKELY (!clip_audio_buffer (ffmpegdec, *outbuf, out_timestamp, - out_duration))) - goto clipped; - - } else { - gst_buffer_unref (*outbuf); - *outbuf = NULL; - } - - /* If we don't error out after the first failed read with the AAC decoder, - * we must *not* carry on pushing data, else we'll cause segfaults... */ - if (len == -1 && (in_plugin->id == CODEC_ID_AAC - || in_plugin->id == CODEC_ID_AAC_LATM)) { - GST_ELEMENT_ERROR (ffmpegdec, STREAM, DECODE, (NULL), - ("Decoding of AAC stream by FFMPEG failed.")); - *ret = GST_FLOW_ERROR; - } - -beach: - GST_DEBUG_OBJECT (ffmpegdec, "return flow %d, out %p, len %d", - *ret, *outbuf, len); - return len; - - /* ERRORS */ -clipped: - { - GST_DEBUG_OBJECT (ffmpegdec, "buffer clipped"); - gst_buffer_unref (*outbuf); - *outbuf = NULL; - goto beach; - } -} - -/* gst_ffmpegdec_frame: +/* gst_ffmpegviddec_frame: * ffmpegdec: * data: pointer to the data to decode * size: size of data in bytes @@ -2262,11 +1998,11 @@ clipped: */ static gint -gst_ffmpegdec_frame (GstFFMpegDec * ffmpegdec, +gst_ffmpegviddec_frame (GstFFMpegVidDec * ffmpegdec, guint8 * data, guint size, gint * got_data, const GstTSInfo * dec_info, GstFlowReturn * ret) { - GstFFMpegDecClass *oclass; + GstFFMpegVidDecClass *oclass; GstBuffer *outbuf = NULL; gint have_data = 0, len = 0; @@ -2279,32 +2015,11 @@ gst_ffmpegdec_frame (GstFFMpegDec * ffmpegdec, *ret = GST_FLOW_OK; ffmpegdec->context->frame_number++; - oclass = (GstFFMpegDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec)); + oclass = (GstFFMpegVidDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec)); - switch (oclass->in_plugin->type) { - case AVMEDIA_TYPE_VIDEO: - len = - gst_ffmpegdec_video_frame (ffmpegdec, data, size, dec_info, &outbuf, - ret); - break; - case AVMEDIA_TYPE_AUDIO: - len = - gst_ffmpegdec_audio_frame (ffmpegdec, oclass->in_plugin, data, size, - dec_info, &outbuf, ret); - - /* if we did not get an output buffer and we have a pending discont, don't - * clear the input timestamps, we will put them on the next buffer because - * else we might create the first buffer with a very big timestamp gap. */ - if (outbuf == NULL && ffmpegdec->discont) { - GST_DEBUG_OBJECT (ffmpegdec, "no buffer but keeping timestamp"); - ffmpegdec->clear_ts = FALSE; - } - break; - default: - GST_ERROR_OBJECT (ffmpegdec, "Asked to decode non-audio/video frame !"); - g_assert_not_reached (); - break; - } + len = + gst_ffmpegviddec_video_frame (ffmpegdec, data, size, dec_info, + &outbuf, ret); if (outbuf) have_data = 1; @@ -2362,11 +2077,11 @@ no_codec: } static void -gst_ffmpegdec_drain (GstFFMpegDec * ffmpegdec) +gst_ffmpegviddec_drain (GstFFMpegVidDec * ffmpegdec) { - GstFFMpegDecClass *oclass; + GstFFMpegVidDecClass *oclass; - oclass = (GstFFMpegDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec)); + oclass = (GstFFMpegVidDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec)); if (oclass->in_plugin->capabilities & CODEC_CAP_DELAY) { gint have_data, len, try = 0; @@ -2378,7 +2093,7 @@ gst_ffmpegdec_drain (GstFFMpegDec * ffmpegdec) GstFlowReturn ret; len = - gst_ffmpegdec_frame (ffmpegdec, NULL, 0, &have_data, &ts_info_none, + gst_ffmpegviddec_frame (ffmpegdec, NULL, 0, &have_data, &ts_info_none, &ret); if (len < 0 || have_data == 0) break; @@ -2391,7 +2106,7 @@ gst_ffmpegdec_drain (GstFFMpegDec * ffmpegdec) } static void -gst_ffmpegdec_flush_pcache (GstFFMpegDec * ffmpegdec) +gst_ffmpegviddec_flush_pcache (GstFFMpegVidDec * ffmpegdec) { if (ffmpegdec->pctx) { gint size, bsize; @@ -2416,12 +2131,12 @@ gst_ffmpegdec_flush_pcache (GstFFMpegDec * ffmpegdec) } static gboolean -gst_ffmpegdec_sink_event (GstPad * pad, GstEvent * event) +gst_ffmpegviddec_sink_event (GstPad * pad, GstEvent * event) { - GstFFMpegDec *ffmpegdec; + GstFFMpegVidDec *ffmpegdec; gboolean ret = FALSE; - ffmpegdec = (GstFFMpegDec *) gst_pad_get_parent (pad); + ffmpegdec = (GstFFMpegVidDec *) gst_pad_get_parent (pad); GST_DEBUG_OBJECT (ffmpegdec, "Handling %s event", GST_EVENT_TYPE_NAME (event)); @@ -2429,7 +2144,7 @@ gst_ffmpegdec_sink_event (GstPad * pad, GstEvent * event) switch (GST_EVENT_TYPE (event)) { case GST_EVENT_EOS: { - gst_ffmpegdec_drain (ffmpegdec); + gst_ffmpegviddec_drain (ffmpegdec); break; } case GST_EVENT_FLUSH_STOP: @@ -2437,9 +2152,9 @@ gst_ffmpegdec_sink_event (GstPad * pad, GstEvent * event) if (ffmpegdec->opened) { avcodec_flush_buffers (ffmpegdec->context); } - gst_ffmpegdec_reset_ts (ffmpegdec); - gst_ffmpegdec_reset_qos (ffmpegdec); - gst_ffmpegdec_flush_pcache (ffmpegdec); + gst_ffmpegviddec_reset_ts (ffmpegdec); + gst_ffmpegviddec_reset_qos (ffmpegdec); + gst_ffmpegviddec_flush_pcache (ffmpegdec); ffmpegdec->waiting_for_key = TRUE; gst_segment_init (&ffmpegdec->segment, GST_FORMAT_TIME); clear_queued (ffmpegdec); @@ -2499,7 +2214,7 @@ gst_ffmpegdec_sink_event (GstPad * pad, GstEvent * event) /* drain pending frames before trying to use the new segment, queued * buffers belonged to the previous segment. */ if (ffmpegdec->context->codec) - gst_ffmpegdec_drain (ffmpegdec); + gst_ffmpegviddec_drain (ffmpegdec); GST_DEBUG_OBJECT (ffmpegdec, "NEWSEGMENT in time start %" GST_TIME_FORMAT " -- stop %" @@ -2538,10 +2253,10 @@ invalid_format: } static GstFlowReturn -gst_ffmpegdec_chain (GstPad * pad, GstBuffer * inbuf) +gst_ffmpegviddec_chain (GstPad * pad, GstBuffer * inbuf) { - GstFFMpegDec *ffmpegdec; - GstFFMpegDecClass *oclass; + GstFFMpegVidDec *ffmpegdec; + GstFFMpegVidDecClass *oclass; guint8 *data, *bdata; gint size, bsize, len, have_data; GstFlowReturn ret = GST_FLOW_OK; @@ -2552,7 +2267,7 @@ gst_ffmpegdec_chain (GstPad * pad, GstBuffer * inbuf) const GstTSInfo *in_info; const GstTSInfo *dec_info; - ffmpegdec = (GstFFMpegDec *) (GST_PAD_PARENT (pad)); + ffmpegdec = (GstFFMpegVidDec *) (GST_PAD_PARENT (pad)); if (G_UNLIKELY (!ffmpegdec->opened)) goto not_negotiated; @@ -2566,17 +2281,17 @@ gst_ffmpegdec_chain (GstPad * pad, GstBuffer * inbuf) if (G_UNLIKELY (discont)) { GST_DEBUG_OBJECT (ffmpegdec, "received DISCONT"); /* drain what we have queued */ - gst_ffmpegdec_drain (ffmpegdec); - gst_ffmpegdec_flush_pcache (ffmpegdec); + gst_ffmpegviddec_drain (ffmpegdec); + gst_ffmpegviddec_flush_pcache (ffmpegdec); avcodec_flush_buffers (ffmpegdec->context); ffmpegdec->discont = TRUE; - gst_ffmpegdec_reset_ts (ffmpegdec); + gst_ffmpegviddec_reset_ts (ffmpegdec); } /* by default we clear the input timestamp after decoding each frame so that * interpollation can work. */ ffmpegdec->clear_ts = TRUE; - oclass = (GstFFMpegDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec)); + oclass = (GstFFMpegVidDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec)); /* do early keyframe check pretty bad to rely on the keyframe flag in the * source for this as it might not even be parsed (UDP/file/..). */ @@ -2731,7 +2446,8 @@ gst_ffmpegdec_chain (GstPad * pad, GstBuffer * inbuf) /* decode a frame of audio/video now */ len = - gst_ffmpegdec_frame (ffmpegdec, data, size, &have_data, dec_info, &ret); + gst_ffmpegviddec_frame (ffmpegdec, data, size, &have_data, dec_info, + &ret); if (ffmpegdec->do_padding) { memcpy (data + size, tmp_padding, FF_INPUT_BUFFER_PADDING_SIZE); @@ -2816,7 +2532,7 @@ gst_ffmpegdec_chain (GstPad * pad, GstBuffer * inbuf) /* ERRORS */ not_negotiated: { - oclass = (GstFFMpegDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec)); + oclass = (GstFFMpegVidDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec)); GST_ELEMENT_ERROR (ffmpegdec, CORE, NEGOTIATION, (NULL), ("ffdec_%s: input format was not set before data start", oclass->in_plugin->name)); @@ -2832,9 +2548,9 @@ skip_keyframe: } static GstStateChangeReturn -gst_ffmpegdec_change_state (GstElement * element, GstStateChange transition) +gst_ffmpegviddec_change_state (GstElement * element, GstStateChange transition) { - GstFFMpegDec *ffmpegdec = (GstFFMpegDec *) element; + GstFFMpegVidDec *ffmpegdec = (GstFFMpegVidDec *) element; GstStateChangeReturn ret; ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); @@ -2842,7 +2558,7 @@ gst_ffmpegdec_change_state (GstElement * element, GstStateChange transition) switch (transition) { case GST_STATE_CHANGE_PAUSED_TO_READY: GST_OBJECT_LOCK (ffmpegdec); - gst_ffmpegdec_close (ffmpegdec); + gst_ffmpegviddec_close (ffmpegdec); GST_OBJECT_UNLOCK (ffmpegdec); clear_queued (ffmpegdec); g_free (ffmpegdec->padded); @@ -2858,10 +2574,10 @@ gst_ffmpegdec_change_state (GstElement * element, GstStateChange transition) } static void -gst_ffmpegdec_set_property (GObject * object, +gst_ffmpegviddec_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) { - GstFFMpegDec *ffmpegdec = (GstFFMpegDec *) object; + GstFFMpegVidDec *ffmpegdec = (GstFFMpegVidDec *) object; switch (prop_id) { case PROP_LOWRES: @@ -2894,10 +2610,10 @@ gst_ffmpegdec_set_property (GObject * object, } static void -gst_ffmpegdec_get_property (GObject * object, +gst_ffmpegviddec_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { - GstFFMpegDec *ffmpegdec = (GstFFMpegDec *) object; + GstFFMpegVidDec *ffmpegdec = (GstFFMpegVidDec *) object; switch (prop_id) { case PROP_LOWRES: @@ -2928,18 +2644,18 @@ gst_ffmpegdec_get_property (GObject * object, } gboolean -gst_ffmpegdec_register (GstPlugin * plugin) +gst_ffmpegviddec_register (GstPlugin * plugin) { GTypeInfo typeinfo = { - sizeof (GstFFMpegDecClass), - (GBaseInitFunc) gst_ffmpegdec_base_init, + sizeof (GstFFMpegVidDecClass), + (GBaseInitFunc) gst_ffmpegviddec_base_init, NULL, - (GClassInitFunc) gst_ffmpegdec_class_init, + (GClassInitFunc) gst_ffmpegviddec_class_init, NULL, NULL, - sizeof (GstFFMpegDec), + sizeof (GstFFMpegVidDec), 0, - (GInstanceInitFunc) gst_ffmpegdec_init, + (GInstanceInitFunc) gst_ffmpegviddec_init, }; GType type; AVCodec *in_plugin; @@ -3002,14 +2718,8 @@ gst_ffmpegdec_register (GstPlugin * plugin) /* MP2 : Use MP3 for decoding */ /* Theora: Use libtheora based theoradec */ if (!strcmp (in_plugin->name, "gif") || - !strcmp (in_plugin->name, "vorbis") || !strcmp (in_plugin->name, "theora") || !strcmp (in_plugin->name, "mpeg1video") || - !strcmp (in_plugin->name, "wavpack") || - !strcmp (in_plugin->name, "mp1") || - !strcmp (in_plugin->name, "mp2") || - !strcmp (in_plugin->name, "libfaad") || - !strcmp (in_plugin->name, "mpeg4aac") || !strcmp (in_plugin->name, "ass") || !strcmp (in_plugin->name, "srt") || !strcmp (in_plugin->name, "pgssub") || @@ -3041,28 +2751,19 @@ gst_ffmpegdec_register (GstPlugin * plugin) case CODEC_ID_MPEG4: case CODEC_ID_MSMPEG4V3: case CODEC_ID_H264: - case CODEC_ID_RA_144: - case CODEC_ID_RA_288: case CODEC_ID_RV10: case CODEC_ID_RV20: case CODEC_ID_RV30: case CODEC_ID_RV40: - case CODEC_ID_COOK: rank = GST_RANK_PRIMARY; break; /* DVVIDEO: we have a good dv decoder, fast on both ppc as well as x86. * They say libdv's quality is better though. leave as secondary. * note: if you change this, see the code in gstdv.c in good/ext/dv. - * - * SIPR: decoder should have a higher rank than realaudiodec. */ case CODEC_ID_DVVIDEO: - case CODEC_ID_SIPR: rank = GST_RANK_SECONDARY; break; - case CODEC_ID_MP3: - rank = GST_RANK_NONE; - break; default: rank = GST_RANK_MARGINAL; break; |