summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/dshowdecwrapper/gstdshowaudiodec.c1189
-rw-r--r--sys/dshowdecwrapper/gstdshowdecwrapper.c79
-rw-r--r--sys/dshowdecwrapper/gstdshowvideodec.c1149
3 files changed, 0 insertions, 2417 deletions
diff --git a/sys/dshowdecwrapper/gstdshowaudiodec.c b/sys/dshowdecwrapper/gstdshowaudiodec.c
deleted file mode 100644
index 574ce1c6..00000000
--- a/sys/dshowdecwrapper/gstdshowaudiodec.c
+++ /dev/null
@@ -1,1189 +0,0 @@
-/*
- * GStreamer DirectShow codecs wrapper
- * Copyright <2006, 2007, 2008> Fluendo <gstreamer@fluendo.com>
- * Copyright <2006, 2007, 2008> Pioneers of the Inevitable <songbird@songbirdnest.com>
- * Copyright <2007,2008> Sebastien Moutte <sebastien@moutte.net>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Alternatively, the contents of this file may be used under the
- * GNU Lesser General Public License Version 2.1 (the "LGPL"), in
- * which case the following provisions apply instead of the ones
- * mentioned above:
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "gstdshowaudiodec.h"
-#include <mmreg.h>
-
-GST_DEBUG_CATEGORY_STATIC (dshowaudiodec_debug);
-#define GST_CAT_DEFAULT dshowaudiodec_debug
-
-GST_BOILERPLATE (GstDshowAudioDec, gst_dshowaudiodec, GstElement,
- GST_TYPE_ELEMENT);
-static const CodecEntry *tmp;
-
-static void gst_dshowaudiodec_dispose (GObject * object);
-static GstStateChangeReturn gst_dshowaudiodec_change_state
- (GstElement * element, GstStateChange transition);
-
-/* sink pad overwrites */
-static gboolean gst_dshowaudiodec_sink_setcaps (GstPad * pad, GstCaps * caps);
-static GstFlowReturn gst_dshowaudiodec_chain (GstPad * pad, GstBuffer * buffer);
-static gboolean gst_dshowaudiodec_sink_event (GstPad * pad, GstEvent * event);
-
-/* callback used by directshow to push buffers */
-static gboolean gst_dshowaudiodec_push_buffer (byte * buffer, long size,
- byte * src_object, UINT64 start, UINT64 stop);
-
-/* utils */
-static gboolean gst_dshowaudiodec_create_graph_and_filters (GstDshowAudioDec *
- adec);
-static gboolean gst_dshowaudiodec_destroy_graph_and_filters (GstDshowAudioDec *
- adec);
-static gboolean gst_dshowaudiodec_flush (GstDshowAudioDec * adec);
-static gboolean gst_dshowaudiodec_get_filter_settings (GstDshowAudioDec * adec);
-static gboolean gst_dshowaudiodec_setup_graph (GstDshowAudioDec * adec);
-
-static const long mpeg_bitrates[2][3][16] = {
- /* mpeg 1 */
- {
- /* one list per layer 1-3 */
- {0, 32000, 64000, 96000, 128000, 160000, 192000, 224000, 256000,
- 288000, 320000, 352000, 384000, 416000, 448000, 0},
- {0, 32000, 48000, 56000, 64000, 80000, 96000, 112000, 128000,
- 160000, 192000, 224000, 256000, 320000, 384000, 0},
- {0, 32000, 40000, 48000, 56000, 64000, 80000, 96000, 112000,
- 128000, 160000, 192000, 224000, 256000, 320000, 0},
- },
- /* mpeg 2 */
- {
- /* one list per layer 1-3 */
- {0, 32000, 48000, 56000, 64000, 80000, 96000, 112000, 128000, 144000,
- 160000, 176000, 192000, 224000, 256000, 0},
- {0, 8000, 16000, 24000, 32000, 40000, 48000, 56000, 64000, 80000, 96000,
- 112000, 128000, 144000, 160000, 0},
- {0, 8000, 16000, 24000, 32000, 40000, 48000, 56000, 64000, 80000, 96000,
- 112000, 128000, 144000, 160000, 0},
- }
-};
-
-#define GUID_MEDIATYPE_AUDIO {0x73647561, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }}
-#define GUID_MEDIASUBTYPE_PCM {0x00000001, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }}
-#define GUID_MEDIASUBTYPE_WMAV1 {0x00000160, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }}
-#define GUID_MEDIASUBTYPE_WMAV2 {0x00000161, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }}
-#define GUID_MEDIASUBTYPE_WMAV3 {0x00000162, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }}
-#define GUID_MEDIASUBTYPE_WMAV4 {0x00000163, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }}
-#define GUID_MEDIASUBTYPE_WMS {0x0000000a, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }}
-#define GUID_MEDIASUBTYPE_MP3 {0x00000055, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }}
-#define GUID_MEDIASUBTYPE_MPEG1AudioPayload {0x00000050, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9b, 0x71 }}
-
-static const CodecEntry audio_dec_codecs[] = {
- {"dshowadec_wma1",
- "Windows Media Audio 7",
- "DMO",
- 0x00000160,
- GUID_MEDIATYPE_AUDIO, GUID_MEDIASUBTYPE_WMAV1,
- "audio/x-wma, wmaversion = (int) 1",
- GUID_MEDIATYPE_AUDIO, GUID_MEDIASUBTYPE_PCM,
- "audio/x-raw-int, "
- "width = (int) { 1, 8, 16 }, depth = (int) { 1, 8, 16 }, "
- "signed = (boolean) true, endianness = (int) "
- G_STRINGIFY (G_LITTLE_ENDIAN)
- },
- {"dshowadec_wma2",
- "Windows Media Audio 8",
- "DMO",
- 0x00000161,
- GUID_MEDIATYPE_AUDIO, GUID_MEDIASUBTYPE_WMAV2,
- "audio/x-wma, wmaversion = (int) 2",
- GUID_MEDIATYPE_AUDIO, GUID_MEDIASUBTYPE_PCM,
- "audio/x-raw-int, "
- "width = (int) { 1, 8, 16 }, depth = (int) { 1, 8, 16 }, "
- "signed = (boolean) true, endianness = (int) "
- G_STRINGIFY (G_LITTLE_ENDIAN)
- },
- {"dshowadec_wma3",
- "Windows Media Audio 9 Professional",
- "DMO",
- 0x00000162,
- GUID_MEDIATYPE_AUDIO, GUID_MEDIASUBTYPE_WMAV3,
- "audio/x-wma, wmaversion = (int) 3",
- GUID_MEDIATYPE_AUDIO, GUID_MEDIASUBTYPE_PCM,
- "audio/x-raw-int, "
- "width = (int) { 1, 8, 16 }, depth = (int) { 1, 8, 16 }, "
- "signed = (boolean) true, endianness = (int) "
- G_STRINGIFY (G_LITTLE_ENDIAN)
- },
- {"dshowadec_wma4",
- "Windows Media Audio 9 Lossless",
- "DMO",
- 0x00000163,
- GUID_MEDIATYPE_AUDIO, GUID_MEDIASUBTYPE_WMAV4,
- "audio/x-wma, wmaversion = (int) 4",
- GUID_MEDIATYPE_AUDIO, GUID_MEDIASUBTYPE_PCM,
- "audio/x-raw-int, "
- "width = (int) { 1, 8, 16 }, depth = (int) { 1, 8, 16 }, "
- "signed = (boolean) true, endianness = (int) "
- G_STRINGIFY (G_LITTLE_ENDIAN)
- },
- {"dshowadec_wms",
- "Windows Media Audio Voice v9",
- "DMO",
- 0x0000000a,
- GUID_MEDIATYPE_AUDIO, GUID_MEDIASUBTYPE_WMS,
- "audio/x-wms",
- GUID_MEDIATYPE_AUDIO, GUID_MEDIASUBTYPE_PCM,
- "audio/x-raw-int, "
- "width = (int) { 1, 8, 16 }, depth = (int) { 1, 8, 16 }, "
- "signed = (boolean) true, endianness = (int) "
- G_STRINGIFY (G_LITTLE_ENDIAN)
- },
- {"dshowadec_mpeg1",
- "MPEG-1 Layer 1,2,3 Audio",
- "MPEG Layer-3 Decoder",
- 0x00000055,
- GUID_MEDIATYPE_AUDIO, GUID_MEDIASUBTYPE_MP3,
- "audio/mpeg, "
- "mpegversion = (int) 1, "
- "layer = (int) { 1 , 2, 3 }, "
- "rate = (int) [ 8000, 48000 ], "
- "channels = (int) [ 1, 2 ], " "parsed= (boolean) true",
- GUID_MEDIATYPE_AUDIO, GUID_MEDIASUBTYPE_PCM,
- "audio/x-raw-int, "
- "width = (int) { 1, 8, 16 }, depth = (int) { 1, 8, 16 }, "
- "signed = (boolean) true, endianness = (int) "
- G_STRINGIFY (G_LITTLE_ENDIAN)
- }
-};
-
-/* Private map used when dshowadec_mpeg is loaded with layer=1 or 2.
- * The problem is that gstreamer doesn't care about caps like layer when connecting pads.
- * So I've only one element handling mpeg audio in the public codecs map and
- * when it's loaded for mp3, I release the mpeg audio decoder and replace it by
- * the one described in this private map.
-*/
-static const CodecEntry audio_mpeg_1_2[] = { "dshowadec_mpeg_1_2",
- "MPEG-1 Layer 1,2 Audio",
- "MPEG Audio Decoder",
- 0x00000050,
- GUID_MEDIATYPE_AUDIO, GUID_MEDIASUBTYPE_MPEG1AudioPayload,
- "audio/mpeg, "
- "mpegversion = (int) 1, "
- "layer = (int) [ 1, 2 ], "
- "rate = (int) [ 8000, 48000 ], "
- "channels = (int) [ 1, 2 ], " "parsed= (boolean) true",
- GUID_MEDIATYPE_AUDIO, GUID_MEDIASUBTYPE_PCM,
- "audio/x-raw-int, "
- "width = (int) { 1, 8, 16 }, depth = (int) { 1, 8, 16 }, "
- "signed = (boolean) true, endianness = (int) "
- G_STRINGIFY (G_LITTLE_ENDIAN)
-};
-
-static void
-gst_dshowaudiodec_base_init (GstDshowAudioDecClass * klass)
-{
- GstPadTemplate *src, *sink;
- GstCaps *srccaps, *sinkcaps;
- GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
- GstElementDetails details;
-
- klass->entry = tmp;
- details.longname = g_strdup_printf ("DirectShow %s Decoder Wrapper",
- tmp->element_longname);
- details.klass = g_strdup ("Codec/Decoder/Audio");
- details.description = g_strdup_printf ("DirectShow %s Decoder Wrapper",
- tmp->element_longname);
- details.author = "Sebastien Moutte <sebastien@moutte.net>";
- gst_element_class_set_details (element_class, &details);
- g_free (details.longname);
- g_free (details.klass);
- g_free (details.description);
-
- sinkcaps = gst_caps_from_string (tmp->sinkcaps);
- gst_caps_set_simple (sinkcaps,
- "block_align", GST_TYPE_INT_RANGE, 0, G_MAXINT,
- "bitrate", GST_TYPE_INT_RANGE, 0, G_MAXINT, NULL);
-
- srccaps = gst_caps_from_string (tmp->srccaps);
-
- sink = gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, sinkcaps);
- src = gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS, srccaps);
-
- /* register */
- gst_element_class_add_pad_template (element_class, src);
- gst_element_class_add_pad_template (element_class, sink);
-}
-
-static void
-gst_dshowaudiodec_class_init (GstDshowAudioDecClass * klass)
-{
- GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
- GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
-
- gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_dshowaudiodec_dispose);
-
- gstelement_class->change_state =
- GST_DEBUG_FUNCPTR (gst_dshowaudiodec_change_state);
-
- if (!parent_class)
- parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
-
- if (!dshowaudiodec_debug) {
- GST_DEBUG_CATEGORY_INIT (dshowaudiodec_debug, "dshowaudiodec", 0,
- "Directshow filter audio decoder");
- }
-}
-
-static void
-gst_dshowaudiodec_init (GstDshowAudioDec * adec,
- GstDshowAudioDecClass * adec_class)
-{
- GstElementClass *element_class = GST_ELEMENT_GET_CLASS (adec);
- HRESULT hr;
-
- /* setup pads */
- adec->sinkpad =
- gst_pad_new_from_template (gst_element_class_get_pad_template
- (element_class, "sink"), "sink");
-
- gst_pad_set_setcaps_function (adec->sinkpad, gst_dshowaudiodec_sink_setcaps);
- gst_pad_set_event_function (adec->sinkpad, gst_dshowaudiodec_sink_event);
- gst_pad_set_chain_function (adec->sinkpad, gst_dshowaudiodec_chain);
- gst_element_add_pad (GST_ELEMENT (adec), adec->sinkpad);
-
- adec->srcpad =
- gst_pad_new_from_template (gst_element_class_get_pad_template
- (element_class, "src"), "src");
- gst_element_add_pad (GST_ELEMENT (adec), adec->srcpad);
-
- adec->srcfilter = NULL;
- adec->gstdshowsrcfilter = NULL;
- adec->decfilter = NULL;
- adec->sinkfilter = NULL;
- adec->filtergraph = NULL;
- adec->mediafilter = NULL;
- adec->timestamp = GST_CLOCK_TIME_NONE;
- adec->segment = gst_segment_new ();
- adec->setup = FALSE;
- adec->depth = 0;
- adec->bitrate = 0;
- adec->block_align = 0;
- adec->channels = 0;
- adec->rate = 0;
- adec->layer = 0;
- adec->codec_data = NULL;
-
- adec->last_ret = GST_FLOW_OK;
-
- hr = CoInitialize (0);
- if (SUCCEEDED (hr)) {
- adec->comInitialized = TRUE;
- }
-}
-
-static void
-gst_dshowaudiodec_dispose (GObject * object)
-{
- GstDshowAudioDec *adec = (GstDshowAudioDec *) (object);
-
- if (adec->segment) {
- gst_segment_free (adec->segment);
- adec->segment = NULL;
- }
-
- if (adec->codec_data) {
- gst_buffer_unref (adec->codec_data);
- adec->codec_data = NULL;
- }
-
- if (adec->comInitialized) {
- CoUninitialize ();
- adec->comInitialized = FALSE;
- }
-
- G_OBJECT_CLASS (parent_class)->dispose (object);
-}
-
-
-static GstStateChangeReturn
-gst_dshowaudiodec_change_state (GstElement * element, GstStateChange transition)
-{
- GstDshowAudioDec *adec = (GstDshowAudioDec *) (element);
-
- switch (transition) {
- case GST_STATE_CHANGE_NULL_TO_READY:
- if (!gst_dshowaudiodec_create_graph_and_filters (adec))
- return GST_STATE_CHANGE_FAILURE;
- break;
- case GST_STATE_CHANGE_READY_TO_PAUSED:
- break;
- case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
- break;
- case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
- break;
- case GST_STATE_CHANGE_PAUSED_TO_READY:
- adec->depth = 0;
- adec->bitrate = 0;
- adec->block_align = 0;
- adec->channels = 0;
- adec->rate = 0;
- adec->layer = 0;
- if (adec->codec_data) {
- gst_buffer_unref (adec->codec_data);
- adec->codec_data = NULL;
- }
- break;
- case GST_STATE_CHANGE_READY_TO_NULL:
- if (!gst_dshowaudiodec_destroy_graph_and_filters (adec))
- return GST_STATE_CHANGE_FAILURE;
- break;
- default:
- break;
- }
-
- return GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
-}
-
-static gboolean
-gst_dshowaudiodec_sink_setcaps (GstPad * pad, GstCaps * caps)
-{
- gboolean ret = FALSE;
- GstDshowAudioDec *adec = (GstDshowAudioDec *) gst_pad_get_parent (pad);
- GstStructure *s = gst_caps_get_structure (caps, 0);
- const GValue *v = NULL;
-
- adec->timestamp = GST_CLOCK_TIME_NONE;
-
- /* read data, only rate and channels are needed */
- if (!gst_structure_get_int (s, "rate", &adec->rate) ||
- !gst_structure_get_int (s, "channels", &adec->channels)) {
- GST_ELEMENT_ERROR (adec, CORE, NEGOTIATION,
- ("error getting audio specs from caps"), (NULL));
- goto end;
- }
-
- gst_structure_get_int (s, "depth", &adec->depth);
- gst_structure_get_int (s, "bitrate", &adec->bitrate);
- gst_structure_get_int (s, "block_align", &adec->block_align);
- gst_structure_get_int (s, "layer", &adec->layer);
-
- if (adec->codec_data) {
- gst_buffer_unref (adec->codec_data);
- adec->codec_data = NULL;
- }
-
- if ((v = gst_structure_get_value (s, "codec_data")))
- adec->codec_data = gst_buffer_ref (gst_value_get_buffer (v));
-
- if (adec->layer != 1 && adec->layer != 2) {
- /* setup dshow graph for all formats except for
- * MPEG-1 layer 1 and 2 for which we need negociate
- * in _chain function.
- */
- ret = gst_dshowaudiodec_setup_graph (adec);
- }
-
- ret = TRUE;
-end:
- gst_object_unref (adec);
-
- return ret;
-}
-
-static GstFlowReturn
-gst_dshowaudiodec_chain (GstPad * pad, GstBuffer * buffer)
-{
- GstDshowAudioDec *adec = (GstDshowAudioDec *) gst_pad_get_parent (pad);
- gboolean discount = FALSE;
-
- if (!adec->setup) {
- if (adec->layer != 0) {
- if (adec->codec_data) {
- gst_buffer_unref (adec->codec_data);
- adec->codec_data = NULL;
- }
- /* extract the 3 bytes of MPEG-1 audio frame header */
- adec->codec_data = gst_buffer_create_sub (buffer, 1, 3);
- }
-
- /* setup dshow graph */
- if (!gst_dshowaudiodec_setup_graph (adec)) {
- adec->last_ret = GST_FLOW_ERROR;
- goto beach;
- }
- }
-
- if (!adec->gstdshowsrcfilter) {
- /* we are not setup */
- adec->last_ret = GST_FLOW_WRONG_STATE;
- goto beach;
- }
-
- if (GST_FLOW_IS_FATAL (adec->last_ret)) {
- GST_DEBUG_OBJECT (adec, "last decoding iteration generated a fatal error "
- "%s", gst_flow_get_name (adec->last_ret));
- goto beach;
- }
-
- GST_CAT_DEBUG_OBJECT (dshowaudiodec_debug, adec, "chain (size %d)=> pts %"
- GST_TIME_FORMAT " stop %" GST_TIME_FORMAT,
- GST_BUFFER_SIZE (buffer), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)),
- GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer) +
- GST_BUFFER_DURATION (buffer)));
-
- /* if the incoming buffer has discont flag set => flush decoder data */
- if (buffer && GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT)) {
- GST_CAT_DEBUG_OBJECT (dshowaudiodec_debug, adec,
- "this buffer has a DISCONT flag (%" GST_TIME_FORMAT "), flushing",
- GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)));
- gst_dshowaudiodec_flush (adec);
- discount = TRUE;
- }
-
- /* push the buffer to the directshow decoder */
- IGstDshowInterface_gst_push_buffer (adec->gstdshowsrcfilter,
- GST_BUFFER_DATA (buffer), GST_BUFFER_TIMESTAMP (buffer),
- GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer),
- GST_BUFFER_SIZE (buffer), discount);
-
-beach:
- gst_buffer_unref (buffer);
- gst_object_unref (adec);
- return adec->last_ret;
-}
-
-static gboolean
-gst_dshowaudiodec_push_buffer (byte * buffer, long size, byte * src_object,
- UINT64 dshow_start, UINT64 dshow_stop)
-{
- GstDshowAudioDec *adec = (GstDshowAudioDec *) src_object;
- GstBuffer *out_buf = NULL;
- gboolean in_seg = FALSE;
- gint64 buf_start, buf_stop;
- gint64 clip_start = 0, clip_stop = 0;
- size_t start_offset = 0, stop_offset = size;
-
- if (!GST_CLOCK_TIME_IS_VALID (adec->timestamp)) {
- adec->timestamp = dshow_start;
- }
-
- buf_start = adec->timestamp;
- buf_stop = adec->timestamp + (dshow_stop - dshow_start);
-
- /* save stop position to start next buffer with it */
- adec->timestamp = buf_stop;
-
- /* check if this buffer is in our current segment */
- in_seg = gst_segment_clip (adec->segment, GST_FORMAT_TIME,
- buf_start, buf_stop, &clip_start, &clip_stop);
-
- /* if the buffer is out of segment do not push it downstream */
- if (!in_seg) {
- GST_CAT_DEBUG_OBJECT (dshowaudiodec_debug, adec,
- "buffer is out of segment, start %" GST_TIME_FORMAT " stop %"
- GST_TIME_FORMAT, GST_TIME_ARGS (buf_start), GST_TIME_ARGS (buf_stop));
- return FALSE;
- }
-
- /* buffer is in our segment allocate a new out buffer and clip it if needed */
-
- /* allocate a new buffer for raw audio */
- adec->last_ret = gst_pad_alloc_buffer (adec->srcpad, GST_BUFFER_OFFSET_NONE,
- size, GST_PAD_CAPS (adec->srcpad), &out_buf);
- if (!out_buf) {
- GST_CAT_ERROR_OBJECT (dshowaudiodec_debug, adec,
- "can't not allocate a new GstBuffer");
- return FALSE;
- }
-
- /* set buffer properties */
- GST_BUFFER_TIMESTAMP (out_buf) = buf_start;
- GST_BUFFER_DURATION (out_buf) = buf_stop - buf_start;
- memcpy (GST_BUFFER_DATA (out_buf), buffer,
- MIN (size, GST_BUFFER_SIZE (out_buf)));
-
- /* we have to remove some heading samples */
- if (clip_start > buf_start) {
- start_offset = (size_t) gst_util_uint64_scale_int (clip_start - buf_start,
- adec->rate, GST_SECOND) * adec->depth / 8 * adec->channels;
- }
- /* we have to remove some trailing samples */
- if (clip_stop < buf_stop) {
- stop_offset = (size_t) gst_util_uint64_scale_int (buf_stop - clip_stop,
- adec->rate, GST_SECOND) * adec->depth / 8 * adec->channels;
- }
-
- /* truncating */
- if ((start_offset != 0) || (stop_offset != (size_t) size)) {
- GstBuffer *subbuf = gst_buffer_create_sub (out_buf, start_offset,
- stop_offset - start_offset);
-
- if (subbuf) {
- gst_buffer_set_caps (subbuf, GST_PAD_CAPS (adec->srcpad));
- gst_buffer_unref (out_buf);
- out_buf = subbuf;
- }
- }
-
- GST_BUFFER_TIMESTAMP (out_buf) = clip_start;
- GST_BUFFER_DURATION (out_buf) = clip_stop - clip_start;
-
- /* replace the saved stop position by the clipped one */
- adec->timestamp = clip_stop;
-
- GST_CAT_DEBUG_OBJECT (dshowaudiodec_debug, adec,
- "push_buffer (size %d)=> pts %" GST_TIME_FORMAT " stop %" GST_TIME_FORMAT
- " duration %" GST_TIME_FORMAT, size,
- GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (out_buf)),
- GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (out_buf) +
- GST_BUFFER_DURATION (out_buf)),
- GST_TIME_ARGS (GST_BUFFER_DURATION (out_buf)));
-
- adec->last_ret = gst_pad_push (adec->srcpad, out_buf);
-
- return TRUE;
-}
-
-static gboolean
-gst_dshowaudiodec_sink_event (GstPad * pad, GstEvent * event)
-{
- gboolean ret = TRUE;
- GstDshowAudioDec *adec = (GstDshowAudioDec *) gst_pad_get_parent (pad);
-
- switch (GST_EVENT_TYPE (event)) {
- case GST_EVENT_FLUSH_STOP:{
- gst_dshowaudiodec_flush (adec);
- ret = gst_pad_event_default (pad, event);
- break;
- }
- case GST_EVENT_NEWSEGMENT:
- {
- GstFormat format;
- gdouble rate;
- gint64 start, stop, time;
- gboolean update;
-
- gst_event_parse_new_segment (event, &update, &rate, &format, &start,
- &stop, &time);
-
- GST_CAT_DEBUG_OBJECT (dshowaudiodec_debug, adec,
- "received new segment from %" GST_TIME_FORMAT " to %" GST_TIME_FORMAT,
- GST_TIME_ARGS (start), GST_TIME_ARGS (stop));
-
- if (update) {
- GST_CAT_DEBUG_OBJECT (dshowaudiodec_debug, adec,
- "closing current segment flushing..");
- gst_dshowaudiodec_flush (adec);
- }
-
- /* save the new segment in our local current segment */
- gst_segment_set_newsegment (adec->segment, update, rate, format, start,
- stop, time);
-
- ret = gst_pad_event_default (pad, event);
- break;
- }
- default:
- ret = gst_pad_event_default (pad, event);
- break;
- }
-
- gst_object_unref (adec);
-
- return ret;
-}
-
-static gboolean
-gst_dshowaudiodec_flush (GstDshowAudioDec * adec)
-{
- if (!adec->gstdshowsrcfilter)
- return FALSE;
-
- /* flush dshow decoder and reset timestamp */
- IGstDshowInterface_gst_flush (adec->gstdshowsrcfilter);
- adec->timestamp = GST_CLOCK_TIME_NONE;
-
- return TRUE;
-}
-
-
-static gboolean
-gst_dshowaudiodec_setup_graph (GstDshowAudioDec * adec)
-{
- gboolean ret = FALSE;
- GstDshowAudioDecClass *klass =
- (GstDshowAudioDecClass *) G_OBJECT_GET_CLASS (adec);
- HRESULT hres;
- gint size = 0;
- GstCaps *out;
- AM_MEDIA_TYPE output_mediatype, input_mediatype;
- WAVEFORMATEX *input_format = NULL, output_format;
- IPin *output_pin = NULL, *input_pin = NULL;
- IGstDshowInterface *gstdshowinterface = NULL;
- CodecEntry *codec_entry = klass->entry;
-
- if (adec->layer != 0) {
- if (adec->layer == 1 || adec->layer == 2) {
- /* for MPEG-1 layer 1 or 2 we have to release the current
- * MP3 decoder and create an instance of MPEG Audio Decoder
- */
- IBaseFilter_Release (adec->decfilter);
- adec->decfilter = NULL;
- codec_entry = audio_mpeg_1_2;
- gst_dshow_find_filter (codec_entry->input_majortype,
- codec_entry->input_subtype,
- codec_entry->output_majortype,
- codec_entry->output_subtype,
- codec_entry->preferred_filter_substring, &adec->decfilter);
- IFilterGraph_AddFilter (adec->filtergraph, adec->decfilter, L"decoder");
- } else {
- /* mp3 doesn't need to negotiate with MPEG1WAVEFORMAT */
- adec->layer = 0;
- }
- }
-
- /* set mediatype on fakesrc filter output pin */
- memset (&input_mediatype, 0, sizeof (AM_MEDIA_TYPE));
- input_mediatype.majortype = codec_entry->input_majortype;
- input_mediatype.subtype = codec_entry->input_subtype;
- input_mediatype.bFixedSizeSamples = TRUE;
- input_mediatype.bTemporalCompression = FALSE;
- if (adec->block_align)
- input_mediatype.lSampleSize = adec->block_align;
- else
- input_mediatype.lSampleSize = 8192; /* need to evaluate it dynamically */
- input_mediatype.formattype = FORMAT_WaveFormatEx;
-
- if (adec->layer != 0) {
- MPEG1WAVEFORMAT *mpeg1_format;
- BYTE b1, b2, b3;
- gint samples, version, layer;
-
- size = sizeof (MPEG1WAVEFORMAT);
- input_format = g_malloc0 (size);
- input_format->cbSize = sizeof (MPEG1WAVEFORMAT) - sizeof (WAVEFORMATEX);
- mpeg1_format = (MPEG1WAVEFORMAT *) input_format;
-
- /* initialize header bytes */
- b1 = *GST_BUFFER_DATA (adec->codec_data);
- b2 = *(GST_BUFFER_DATA (adec->codec_data) + 1);
- b3 = *(GST_BUFFER_DATA (adec->codec_data) + 2);
-
- /* fill MPEG1WAVEFORMAT using header */
- input_format->wFormatTag = WAVE_FORMAT_MPEG;
- mpeg1_format->wfx.nChannels = 2;
- switch (b3 >> 6) {
- case 0x00:
- mpeg1_format->fwHeadMode = ACM_MPEG_STEREO;
- break;
- case 0x01:
- mpeg1_format->fwHeadMode = ACM_MPEG_JOINTSTEREO;
- break;
- case 0x02:
- mpeg1_format->fwHeadMode = ACM_MPEG_DUALCHANNEL;
- break;
- case 0x03:
- mpeg1_format->fwHeadMode = ACM_MPEG_SINGLECHANNEL;
- mpeg1_format->wfx.nChannels = 1;
- break;
- }
-
- mpeg1_format->fwHeadModeExt = (WORD) (1 << (b3 >> 4));
- mpeg1_format->wHeadEmphasis = (WORD) ((b3 & 0x03) + 1);
- mpeg1_format->fwHeadFlags = (WORD) (((b2 & 1) ? ACM_MPEG_PRIVATEBIT : 0) +
- ((b3 & 8) ? ACM_MPEG_COPYRIGHT : 0) +
- ((b3 & 4) ? ACM_MPEG_ORIGINALHOME : 0) +
- ((b1 & 1) ? ACM_MPEG_PROTECTIONBIT : 0) + ACM_MPEG_ID_MPEG1);
-
- layer = (b1 >> 1) & 3;
- switch (layer) {
- case 1:
- mpeg1_format->fwHeadLayer = ACM_MPEG_LAYER3;
- layer = 3;
- break;
- case 2:
- mpeg1_format->fwHeadLayer = ACM_MPEG_LAYER2;
- break;
- case 3:
- mpeg1_format->fwHeadLayer = ACM_MPEG_LAYER1;
- layer = 1;
- break;
- };
-
- version = ((b1 >> 3) & 1) ? 0 : 1;
- if (layer == 1) {
- samples = 384;
- } else {
- if (version == 1) {
- samples = 576;
- } else {
- samples = 1152;
- }
- }
- mpeg1_format->wfx.nBlockAlign = (WORD) samples;
- mpeg1_format->wfx.nSamplesPerSec = adec->rate;
- mpeg1_format->dwHeadBitrate = mpeg_bitrates[version][layer - 1][b2 >> 4];
- mpeg1_format->wfx.nAvgBytesPerSec = mpeg1_format->dwHeadBitrate / 8;
- } else {
- size = sizeof (WAVEFORMATEX) +
- (adec->codec_data ? GST_BUFFER_SIZE (adec->codec_data) : 0);
- input_format = g_malloc0 (size);
- if (adec->codec_data) { /* Codec data is appended after our header */
- memcpy (((guchar *) input_format) + sizeof (WAVEFORMATEX),
- GST_BUFFER_DATA (adec->codec_data),
- GST_BUFFER_SIZE (adec->codec_data));
- input_format->cbSize = GST_BUFFER_SIZE (adec->codec_data);
- }
-
- input_format->wFormatTag = codec_entry->format;
- input_format->nChannels = adec->channels;
- input_format->nSamplesPerSec = adec->rate;
- input_format->nAvgBytesPerSec = adec->bitrate / 8;
- input_format->nBlockAlign = adec->block_align;
- input_format->wBitsPerSample = adec->depth;
- }
-
- input_mediatype.cbFormat = size;
- input_mediatype.pbFormat = (BYTE *) input_format;
-
- hres = IBaseFilter_QueryInterface (adec->srcfilter, &IID_IGstDshowInterface,
- (void **) &gstdshowinterface);
- if (hres != S_OK || !gstdshowinterface) {
- GST_ELEMENT_ERROR (adec, CORE, NEGOTIATION,
- ("Can't get IGstDshowInterface interface from dshow fakesrc filter (error=%d)",
- hres), (NULL));
- goto end;
- }
-
- /* save a reference to IGstDshowInterface to use it processing functions */
- if (!adec->gstdshowsrcfilter) {
- adec->gstdshowsrcfilter = gstdshowinterface;
- IBaseFilter_AddRef (adec->gstdshowsrcfilter);
- }
-
- IGstDshowInterface_gst_set_media_type (gstdshowinterface, &input_mediatype);
- IGstDshowInterface_Release (gstdshowinterface);
- gstdshowinterface = NULL;
-
- /* connect our fake source to decoder */
- gst_dshow_get_pin_from_filter (adec->srcfilter, PINDIR_OUTPUT, &output_pin);
- if (!output_pin) {
- GST_ELEMENT_ERROR (adec, CORE, NEGOTIATION,
- ("Can't get output pin from our directshow fakesrc filter"), (NULL));
- goto end;
- }
- gst_dshow_get_pin_from_filter (adec->decfilter, PINDIR_INPUT, &input_pin);
- if (!input_pin) {
- GST_ELEMENT_ERROR (adec, CORE, NEGOTIATION,
- ("Can't get input pin from decoder filter"), (NULL));
- goto end;
- }
-
- hres =
- IFilterGraph_ConnectDirect (adec->filtergraph, output_pin, input_pin,
- NULL);
- if (hres != S_OK) {
- GST_ELEMENT_ERROR (adec, CORE, NEGOTIATION,
- ("Can't connect fakesrc with decoder (error=%d)", hres), (NULL));
- goto end;
- }
-
- IPin_Release (input_pin);
- IPin_Release (output_pin);
- input_pin = NULL;
- output_pin = NULL;
-
- if (!gst_dshowaudiodec_get_filter_settings (adec)) {
- GST_ELEMENT_ERROR (adec, CORE, NEGOTIATION,
- ("Can't get audio depth from decoder"), (NULL));
- goto end;
- }
-
- /* set mediatype on fake sink input pin */
- memset (&output_format, 0, sizeof (WAVEFORMATEX));
- output_format.wFormatTag = WAVE_FORMAT_PCM;
- output_format.wBitsPerSample = adec->depth;
- output_format.nChannels = adec->channels;
- output_format.nBlockAlign = adec->channels * (adec->depth / 8);
- output_format.nSamplesPerSec = adec->rate;
- output_format.nAvgBytesPerSec = output_format.nBlockAlign * adec->rate;
-
- memset (&output_mediatype, 0, sizeof (AM_MEDIA_TYPE));
- output_mediatype.majortype = codec_entry->output_majortype;
- output_mediatype.subtype = codec_entry->output_subtype;
- output_mediatype.bFixedSizeSamples = TRUE;
- output_mediatype.bTemporalCompression = FALSE;
- output_mediatype.lSampleSize = output_format.nBlockAlign;
- output_mediatype.formattype = FORMAT_WaveFormatEx;
- output_mediatype.cbFormat = sizeof (WAVEFORMATEX);
- output_mediatype.pbFormat = (char *) &output_format;
-
- hres = IBaseFilter_QueryInterface (adec->sinkfilter, &IID_IGstDshowInterface,
- (void **) &gstdshowinterface);
- if (hres != S_OK || !gstdshowinterface) {
- GST_ELEMENT_ERROR (adec, CORE, NEGOTIATION,
- ("Can't get IGstDshowInterface interface from dshow fakesink filter (error=%d)",
- hres), (NULL));
- goto end;
- }
-
- IGstDshowInterface_gst_set_media_type (gstdshowinterface, &output_mediatype);
- IGstDshowInterface_gst_set_buffer_callback (gstdshowinterface,
- gst_dshowaudiodec_push_buffer, (byte *) adec);
- IGstDshowInterface_Release (gstdshowinterface);
- gstdshowinterface = NULL;
-
- /* negotiate output */
- out = gst_caps_from_string (codec_entry->srccaps);
- gst_caps_set_simple (out,
- "width", G_TYPE_INT, adec->depth,
- "depth", G_TYPE_INT, adec->depth,
- "rate", G_TYPE_INT, adec->rate,
- "channels", G_TYPE_INT, adec->channels, NULL);
- if (!gst_pad_set_caps (adec->srcpad, out)) {
- gst_caps_unref (out);
- GST_ELEMENT_ERROR (adec, CORE, NEGOTIATION,
- ("Failed to negotiate output"), (NULL));
- goto end;
- }
- gst_caps_unref (out);
-
- /* connect the decoder to our fake sink */
- gst_dshow_get_pin_from_filter (adec->decfilter, PINDIR_OUTPUT, &output_pin);
- if (!output_pin) {
- GST_ELEMENT_ERROR (adec, CORE, NEGOTIATION,
- ("Can't get output pin from our decoder filter"), (NULL));
- goto end;
- }
- gst_dshow_get_pin_from_filter (adec->sinkfilter, PINDIR_INPUT, &input_pin);
- if (!input_pin) {
- GST_ELEMENT_ERROR (adec, CORE, NEGOTIATION,
- ("Can't get input pin from our directshow fakesink filter"), (NULL));
- goto end;
- }
-
- hres =
- IFilterGraph_ConnectDirect (adec->filtergraph, output_pin, input_pin,
- NULL);
- if (hres != S_OK) {
- GST_ELEMENT_ERROR (adec, CORE, NEGOTIATION,
- ("Can't connect decoder with fakesink (error=%d)", hres), (NULL));
- goto end;
- }
-
- hres = IMediaFilter_Run (adec->mediafilter, -1);
- if (hres != S_OK) {
- GST_ELEMENT_ERROR (adec, CORE, NEGOTIATION,
- ("Can't run the directshow graph (error=%d)", hres), (NULL));
- goto end;
- }
-
- ret = TRUE;
- adec->setup = TRUE;
-end:
- if (input_format)
- g_free (input_format);
- if (gstdshowinterface)
- IGstDshowInterface_Release (gstdshowinterface);
- if (input_pin)
- IPin_Release (input_pin);
- if (output_pin)
- IPin_Release (output_pin);
-
- return ret;
-}
-
-static gboolean
-gst_dshowaudiodec_get_filter_settings (GstDshowAudioDec * adec)
-{
- IPin *output_pin = NULL;
- IEnumMediaTypes *enum_mediatypes = NULL;
- HRESULT hres;
- ULONG fetched;
- BOOL ret = FALSE;
-
- if (!adec->decfilter)
- return FALSE;
-
- if (!gst_dshow_get_pin_from_filter (adec->decfilter, PINDIR_OUTPUT,
- &output_pin)) {
- GST_ELEMENT_ERROR (adec, CORE, NEGOTIATION,
- ("failed getting ouput pin from the decoder"), (NULL));
- return FALSE;
- }
-
- hres = IPin_EnumMediaTypes (output_pin, &enum_mediatypes);
- if (hres == S_OK && enum_mediatypes) {
- AM_MEDIA_TYPE *mediatype = NULL;
-
- IEnumMediaTypes_Reset (enum_mediatypes);
- while (hres =
- IEnumMoniker_Next (enum_mediatypes, 1, &mediatype, &fetched),
- hres == S_OK) {
- RPC_STATUS rpcstatus;
-
- if ((UuidCompare (&mediatype->subtype, &MEDIASUBTYPE_PCM, &rpcstatus) == 0
- && rpcstatus == RPC_S_OK) &&
- (UuidCompare (&mediatype->formattype, &FORMAT_WaveFormatEx,
- &rpcstatus) == 0 && rpcstatus == RPC_S_OK)) {
- WAVEFORMATEX *audio_info = (WAVEFORMATEX *) mediatype->pbFormat;
-
- adec->channels = audio_info->nChannels;
- adec->depth = audio_info->wBitsPerSample;
- adec->rate = audio_info->nSamplesPerSec;
- ret = TRUE;
- }
- gst_dshow_free_mediatype (mediatype);
- if (ret)
- break;
- }
- IEnumMediaTypes_Release (enum_mediatypes);
- }
- if (output_pin) {
- IPin_Release (output_pin);
- }
-
- return ret;
-}
-
-static gboolean
-gst_dshowaudiodec_create_graph_and_filters (GstDshowAudioDec * adec)
-{
- BOOL ret = FALSE;
- HRESULT hres = S_FALSE;
- GstDshowAudioDecClass *klass =
- (GstDshowAudioDecClass *) G_OBJECT_GET_CLASS (adec);
-
- /* create the filter graph manager object */
- hres = CoCreateInstance (&CLSID_FilterGraph, NULL, CLSCTX_INPROC,
- &IID_IFilterGraph, (LPVOID *) & adec->filtergraph);
- if (hres != S_OK || !adec->filtergraph) {
- GST_ELEMENT_ERROR (adec, STREAM, FAILED,
- ("Can't create an instance of the directshow graph manager (error=%d)",
- hres), (NULL));
- goto error;
- }
-
- hres = IFilterGraph_QueryInterface (adec->filtergraph, &IID_IMediaFilter,
- (void **) &adec->mediafilter);
- if (hres != S_OK || !adec->mediafilter) {
- GST_ELEMENT_ERROR (adec, STREAM, FAILED,
- ("Can't get IMediacontrol interface from the graph manager (error=%d)",
- hres), (NULL));
- goto error;
- }
-
- /* create fake src filter */
- hres = CoCreateInstance (&CLSID_DshowFakeSrc, NULL, CLSCTX_INPROC,
- &IID_IBaseFilter, (LPVOID *) & adec->srcfilter);
- if (hres != S_OK || !adec->srcfilter) {
- GST_ELEMENT_ERROR (adec, STREAM, FAILED,
- ("Can't create an instance of the directshow fakesrc (error=%d)", hres),
- (NULL));
- goto error;
- }
-
- /* create decoder filter */
- if (!gst_dshow_find_filter (klass->entry->input_majortype,
- klass->entry->input_subtype,
- klass->entry->output_majortype,
- klass->entry->output_subtype,
- klass->entry->preferred_filter_substring, &adec->decfilter)) {
- GST_ELEMENT_ERROR (adec, STREAM, FAILED,
- ("Can't create an instance of the decoder filter"), (NULL));
- goto error;
- }
-
- /* create fake sink filter */
- hres = CoCreateInstance (&CLSID_DshowFakeSink, NULL, CLSCTX_INPROC,
- &IID_IBaseFilter, (LPVOID *) & adec->sinkfilter);
- if (hres != S_OK || !adec->sinkfilter) {
- GST_ELEMENT_ERROR (adec, STREAM, FAILED,
- ("Can't create an instance of the directshow fakesink (error=%d)",
- hres), (NULL));
- goto error;
- }
-
- /* add filters to the graph */
- hres = IFilterGraph_AddFilter (adec->filtergraph, adec->srcfilter, L"src");
- if (hres != S_OK) {
- GST_ELEMENT_ERROR (adec, STREAM, FAILED,
- ("Can't add fakesrc filter to the graph (error=%d)", hres), (NULL));
- goto error;
- }
-
- hres =
- IFilterGraph_AddFilter (adec->filtergraph, adec->decfilter, L"decoder");
- if (hres != S_OK) {
- GST_ELEMENT_ERROR (adec, STREAM, FAILED,
- ("Can't add decoder filter to the graph (error=%d)", hres), (NULL));
- goto error;
- }
-
- hres = IFilterGraph_AddFilter (adec->filtergraph, adec->sinkfilter, L"sink");
- if (hres != S_OK) {
- GST_ELEMENT_ERROR (adec, STREAM, FAILED,
- ("Can't add fakesink filter to the graph (error=%d)", hres), (NULL));
- goto error;
- }
-
- return TRUE;
-
-error:
- if (adec->srcfilter) {
- IBaseFilter_Release (adec->srcfilter);
- adec->srcfilter = NULL;
- }
- if (adec->decfilter) {
- IBaseFilter_Release (adec->decfilter);
- adec->decfilter = NULL;
- }
- if (adec->sinkfilter) {
- IBaseFilter_Release (adec->sinkfilter);
- adec->sinkfilter = NULL;
- }
- if (adec->mediafilter) {
- IMediaFilter_Release (adec->mediafilter);
- adec->mediafilter = NULL;
- }
- if (adec->filtergraph) {
- IFilterGraph_Release (adec->filtergraph);
- adec->filtergraph = NULL;
- }
-
- return FALSE;
-}
-
-static gboolean
-gst_dshowaudiodec_destroy_graph_and_filters (GstDshowAudioDec * adec)
-{
- if (adec->mediafilter) {
- IMediaFilter_Stop (adec->mediafilter);
- }
-
- if (adec->gstdshowsrcfilter) {
- IGstDshowInterface_Release (adec->gstdshowsrcfilter);
- adec->gstdshowsrcfilter = NULL;
- }
- if (adec->srcfilter) {
- if (adec->filtergraph)
- IFilterGraph_RemoveFilter (adec->filtergraph, adec->srcfilter);
- IBaseFilter_Release (adec->srcfilter);
- adec->srcfilter = NULL;
- }
- if (adec->decfilter) {
- if (adec->filtergraph)
- IFilterGraph_RemoveFilter (adec->filtergraph, adec->decfilter);
- IBaseFilter_Release (adec->decfilter);
- adec->decfilter = NULL;
- }
- if (adec->sinkfilter) {
- if (adec->filtergraph)
- IFilterGraph_RemoveFilter (adec->filtergraph, adec->sinkfilter);
- IBaseFilter_Release (adec->sinkfilter);
- adec->sinkfilter = NULL;
- }
- if (adec->mediafilter) {
- IMediaFilter_Release (adec->mediafilter);
- adec->mediafilter = NULL;
- }
- if (adec->filtergraph) {
- IFilterGraph_Release (adec->filtergraph);
- adec->filtergraph = NULL;
- }
-
- adec->setup = FALSE;
-
- return TRUE;
-}
-
-gboolean
-dshow_adec_register (GstPlugin * plugin)
-{
- GTypeInfo info = {
- sizeof (GstDshowAudioDecClass),
- (GBaseInitFunc) gst_dshowaudiodec_base_init,
- NULL,
- (GClassInitFunc) gst_dshowaudiodec_class_init,
- NULL,
- NULL,
- sizeof (GstDshowAudioDec),
- 0,
- (GInstanceInitFunc) gst_dshowaudiodec_init,
- };
- gint i;
- HRESULT hr;
-
- GST_DEBUG_CATEGORY_INIT (dshowaudiodec_debug, "dshowaudiodec", 0,
- "Directshow filter audio decoder");
-
- hr = CoInitialize (0);
- for (i = 0; i < sizeof (audio_dec_codecs) / sizeof (CodecEntry); i++) {
- GType type;
-
- if (gst_dshow_find_filter (audio_dec_codecs[i].input_majortype,
- audio_dec_codecs[i].input_subtype,
- audio_dec_codecs[i].output_majortype,
- audio_dec_codecs[i].output_subtype,
- audio_dec_codecs[i].preferred_filter_substring, NULL)) {
-
- GST_CAT_DEBUG (dshowaudiodec_debug, "Registering %s",
- audio_dec_codecs[i].element_name);
-
- tmp = &audio_dec_codecs[i];
- type =
- g_type_register_static (GST_TYPE_ELEMENT,
- audio_dec_codecs[i].element_name, &info, 0);
- if (!gst_element_register (plugin, audio_dec_codecs[i].element_name,
- GST_RANK_PRIMARY, type)) {
- return FALSE;
- }
- GST_CAT_DEBUG (dshowaudiodec_debug, "Registered %s",
- audio_dec_codecs[i].element_name);
- } else {
- GST_CAT_DEBUG (dshowaudiodec_debug,
- "Element %s not registered (the format is not supported by the system)",
- audio_dec_codecs[i].element_name);
- }
- }
-
- if (SUCCEEDED (hr))
- CoUninitialize ();
-
- return TRUE;
-}
diff --git a/sys/dshowdecwrapper/gstdshowdecwrapper.c b/sys/dshowdecwrapper/gstdshowdecwrapper.c
deleted file mode 100644
index 363fdbc8..00000000
--- a/sys/dshowdecwrapper/gstdshowdecwrapper.c
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * GStreamer DirectShow codecs wrapper
- * Copyright <2006, 2007, 2008> Fluendo <gstreamer@fluendo.com>
- * Copyright <2006, 2007, 2008> Pioneers of the Inevitable <songbird@songbirdnest.com>
- * Copyright <2007,2008> Sebastien Moutte <sebastien@moutte.net>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Alternatively, the contents of this file may be used under the
- * GNU Lesser General Public License Version 2.1 (the "LGPL"), in
- * which case the following provisions apply instead of the ones
- * mentioned above:
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "gstdshowaudiodec.h"
-#include "gstdshowvideodec.h"
-
-const GUID CLSID_GstreamerSrcFilter
- =
- { 0x6a780808, 0x9725, 0x4d0b, {0x86, 0x95, 0xa4, 0xdd, 0x8d, 0x21, 0x7,
- 0x73} };
-
-const GUID IID_IGstSrcInterface =
- { 0x542c0a24, 0x8bd1, 0x46cb, {0xaa, 0x57, 0x3e, 0x46, 0xd0, 0x6, 0xd2,
- 0xf3} };
-
-
-static gboolean
-plugin_init (GstPlugin * plugin)
-{
- /* register fake filters */
- gst_dshow_register_fakefilters ();
-
- if (!dshow_adec_register (plugin) || !dshow_vdec_register (plugin))
- return FALSE;
-
- return TRUE;
-}
-
-GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
- GST_VERSION_MINOR,
- "dshowdecwrapper",
- "Directshow decoder wrapper plugin",
- plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
diff --git a/sys/dshowdecwrapper/gstdshowvideodec.c b/sys/dshowdecwrapper/gstdshowvideodec.c
deleted file mode 100644
index 3c95771d..00000000
--- a/sys/dshowdecwrapper/gstdshowvideodec.c
+++ /dev/null
@@ -1,1149 +0,0 @@
-/*
- * GStreamer DirectShow codecs wrapper
- * Copyright <2006, 2007, 2008> Fluendo <gstreamer@fluendo.com>
- * Copyright <2006, 2007, 2008> Pioneers of the Inevitable <songbird@songbirdnest.com>
- * Copyright <2007,2008> Sebastien Moutte <sebastien@moutte.net>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Alternatively, the contents of this file may be used under the
- * GNU Lesser General Public License Version 2.1 (the "LGPL"), in
- * which case the following provisions apply instead of the ones
- * mentioned above:
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "gstdshowvideodec.h"
-
-GST_DEBUG_CATEGORY_STATIC (dshowvideodec_debug);
-#define GST_CAT_DEFAULT dshowvideodec_debug
-
-GST_BOILERPLATE (GstDshowVideoDec, gst_dshowvideodec, GstElement,
- GST_TYPE_ELEMENT);
-static const CodecEntry *tmp;
-
-static void gst_dshowvideodec_dispose (GObject * object);
-static GstStateChangeReturn gst_dshowvideodec_change_state
- (GstElement * element, GstStateChange transition);
-
-/* sink pad overwrites */
-static gboolean gst_dshowvideodec_sink_setcaps (GstPad * pad, GstCaps * caps);
-static gboolean gst_dshowvideodec_sink_event (GstPad * pad, GstEvent * event);
-static GstFlowReturn gst_dshowvideodec_chain (GstPad * pad, GstBuffer * buffer);
-
-/* src pad overwrites */
-static GstCaps *gst_dshowvideodec_src_getcaps (GstPad * pad);
-static gboolean gst_dshowvideodec_src_setcaps (GstPad * pad, GstCaps * caps);
-
-/* callback called by our directshow fake sink when it receives a buffer */
-static gboolean gst_dshowvideodec_push_buffer (byte * buffer, long size,
- byte * src_object, UINT64 start, UINT64 stop);
-
-/* utils */
-static gboolean gst_dshowvideodec_create_graph_and_filters (GstDshowVideoDec *
- vdec);
-static gboolean gst_dshowvideodec_destroy_graph_and_filters (GstDshowVideoDec *
- vdec);
-static gboolean gst_dshowvideodec_flush (GstDshowVideoDec * adec);
-static gboolean gst_dshowvideodec_get_filter_output_format (GstDshowVideoDec *
- vdec, GUID * subtype, VIDEOINFOHEADER ** format, guint * size);
-
-
-#define GUID_MEDIATYPE_VIDEO {0x73646976, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }}
-#define GUID_MEDIASUBTYPE_WMVV1 {0x31564d57, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }}
-#define GUID_MEDIASUBTYPE_WMVV2 {0x32564d57, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }}
-#define GUID_MEDIASUBTYPE_WMVV3 {0x33564d57, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }}
-#define GUID_MEDIASUBTYPE_WMVP {0x50564d57, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }}
-#define GUID_MEDIASUBTYPE_WMVA {0x41564d57, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }}
-#define GUID_MEDIASUBTYPE_CVID {0x64697663, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }}
-#define GUID_MEDIASUBTYPE_MP4S {0x5334504d, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }}
-#define GUID_MEDIASUBTYPE_MP42 {0x3234504d, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }}
-#define GUID_MEDIASUBTYPE_MP43 {0x3334504d, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }}
-#define GUID_MEDIASUBTYPE_M4S2 {0x3253344d, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }}
-#define GUID_MEDIASUBTYPE_XVID {0x44495658, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }}
-#define GUID_MEDIASUBTYPE_DX50 {0x30355844, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }}
-#define GUID_MEDIASUBTYPE_DIVX {0x58564944, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }}
-#define GUID_MEDIASUBTYPE_DIV3 {0x33564944, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }}
-
-#define GUID_MEDIASUBTYPE_MPG4 {0x3447504d, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }}
-#define GUID_MEDIASUBTYPE_MPEG1Payload {0xe436eb81, 0x524f, 0x11ce, {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}}
-
-
-/* output types */
-#define GUID_MEDIASUBTYPE_YUY2 {0x32595559, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }}
-#define GUID_MEDIASUBTYPE_YV12 {0x32315659, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }}
-#define GUID_MEDIASUBTYPE_RGB32 {0xe436eb7e, 0x524f, 0x11ce, { 0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70 }}
-#define GUID_MEDIASUBTYPE_RGB565 {0xe436eb7b, 0x524f, 0x11ce, { 0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70 }}
-
-/* video codecs array */
-static const CodecEntry video_dec_codecs[] = {
- {"dshowvdec_wmv1",
- "Windows Media Video 7",
- "DMO",
- GST_MAKE_FOURCC ('W', 'M', 'V', '1'),
- GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_WMVV1,
- "video/x-wmv, wmvversion = (int) 1",
- GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2,
- "video/x-raw-yuv, format=(fourcc)YUY2"},
- {"dshowvdec_wmv2",
- "Windows Media Video 8",
- "DMO",
- GST_MAKE_FOURCC ('W', 'M', 'V', '2'),
- GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_WMVV2,
- "video/x-wmv, wmvversion = (int) 2",
- GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2,
- "video/x-raw-yuv, format=(fourcc)YUY2"},
- {"dshowvdec_wmv3",
- "Windows Media Video 9",
- "DMO",
- GST_MAKE_FOURCC ('W', 'M', 'V', '3'),
- GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_WMVV3,
- "video/x-wmv, wmvversion = (int) 3, " "format = (fourcc) WMV3",
- GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2,
- "video/x-raw-yuv, format=(fourcc)YUY2"},
- {"dshowvdec_wmvp",
- "Windows Media Video 9 Image",
- "DMO",
- GST_MAKE_FOURCC ('W', 'M', 'V', 'P'),
- GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_WMVP,
- "video/x-wmv, wmvversion = (int) 3, " "format = (fourcc) WMVP",
- GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2,
- "video/x-raw-yuv, format=(fourcc)YUY2"},
- {"dshowvdec_wmva",
- "Windows Media Video 9 Advanced",
- "DMO",
- GST_MAKE_FOURCC ('W', 'M', 'V', 'A'),
- GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_WMVA,
- "video/x-wmv, wmvversion = (int) 3, " "format = (fourcc) WMVA",
- GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2,
- "video/x-raw-yuv, format=(fourcc)YUY2"},
- {"dshowvdec_cinepak",
- "Cinepack",
- "AVI Decompressor",
- 0x64697663,
- GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_CVID,
- "video/x-cinepak",
- GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_RGB32,
- "video/x-raw-rgb, bpp=(int)32, depth=(int)24, "
- "endianness=(int)4321, red_mask=(int)65280, "
- "green_mask=(int)16711680, blue_mask=(int)-16777216"},
- {"dshowvdec_msmpeg41",
- "Microsoft ISO MPEG-4 version 1",
- "DMO",
- GST_MAKE_FOURCC ('M', 'P', '4', 'S'),
- GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_MP4S,
- "video/x-msmpeg, msmpegversion=(int)41",
- GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2,
- "video/x-raw-yuv, format=(fourcc)YUY2"},
- {"dshowvdec_msmpeg42",
- "Microsoft ISO MPEG-4 version 2",
- "DMO",
- GST_MAKE_FOURCC ('M', 'P', '4', '2'),
- GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_MP42,
- "video/x-msmpeg, msmpegversion=(int)42",
- GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2,
- "video/x-raw-yuv, format=(fourcc)YUY2"},
- {"dshowvdec_msmpeg43",
- "Microsoft ISO MPEG-4 version 3",
- "DMO",
- GST_MAKE_FOURCC ('M', 'P', '4', '3'),
- GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_MP43,
- "video/x-msmpeg, msmpegversion=(int)43",
- GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2,
- "video/x-raw-yuv, format=(fourcc)YUY2"},
- {"dshowvdec_msmpeg4",
- "Microsoft ISO MPEG-4 version 1.1",
- "DMO",
- GST_MAKE_FOURCC ('M', '4', 'S', '2'),
- GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_M4S2,
- "video/x-msmpeg, msmpegversion=(int)4",
- GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2,
- "video/x-raw-yuv, format=(fourcc)YUY2"},
- {"dshowvdec_mpeg1",
- "MPEG-1 Video",
- "MPEG Video Decoder",
- GST_MAKE_FOURCC ('M', 'P', 'E', 'G'),
- GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_MPEG1Payload,
- "video/mpeg, mpegversion= (int) 1, "
- "parsed= (boolean) true, " "systemstream= (boolean) false",
- GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2,
- "video/x-raw-yuv, format=(fourcc)YUY2"},
- {"dshowvdec_xvid",
- "XVID Video",
- "ffdshow",
- GST_MAKE_FOURCC ('X', 'V', 'I', 'D'),
- GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_XVID,
- "video/x-xvid",
- GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2,
- "video/x-raw-yuv, format=(fourcc)YUY2"},
- {"dshowvdec_divx5",
- "DIVX 5.0 Video",
- "ffdshow",
- GST_MAKE_FOURCC ('D', 'X', '5', '0'),
- GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_DX50,
- "video/x-divx, divxversion=(int)5",
- GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2,
- "video/x-raw-yuv, format=(fourcc)YUY2"},
- {"dshowvdec_divx4",
- "DIVX 4.0 Video",
- "ffdshow",
- GST_MAKE_FOURCC ('D', 'I', 'V', 'X'),
- GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_DIVX,
- "video/x-divx, divxversion=(int)4",
- GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2,
- "video/x-raw-yuv, format=(fourcc)YUY2"},
- {"dshowvdec_divx3",
- "DIVX 3.0 Video",
- "ffdshow",
- GST_MAKE_FOURCC ('D', 'I', 'V', '3'),
- GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_DIV3,
- "video/x-divx, divxversion=(int)3",
- GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2,
- "video/x-raw-yuv, format=(fourcc)YUY2"}
- /*,
- { "dshowvdec_mpeg4",
- "DMO",
- GST_MAKE_FOURCC ('M', 'P', 'G', '4'),
- GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_MPG4,
- "video/mpeg, msmpegversion=(int)4",
- GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2,
- "video/x-raw-yuv, format=(fourcc)YUY2"
- } */
-};
-
-static void
-gst_dshowvideodec_base_init (GstDshowVideoDecClass * klass)
-{
- GstPadTemplate *src, *sink;
- GstCaps *srccaps, *sinkcaps;
- GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
- GstElementDetails details;
-
- klass->entry = tmp;
-
- details.longname = g_strdup_printf ("DirectShow %s Decoder Wrapper",
- tmp->element_longname);
- details.klass = g_strdup ("Codec/Decoder/Video");
- details.description = g_strdup_printf ("DirectShow %s Decoder Wrapper",
- tmp->element_longname);
- details.author = "Sebastien Moutte <sebastien@moutte.net>";
- gst_element_class_set_details (element_class, &details);
- g_free (details.longname);
- g_free (details.klass);
- g_free (details.description);
-
- sinkcaps = gst_caps_from_string (tmp->sinkcaps);
- gst_caps_set_simple (sinkcaps,
- "width", GST_TYPE_INT_RANGE, 16, 4096,
- "height", GST_TYPE_INT_RANGE, 16, 4096,
- "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
-
- srccaps = gst_caps_from_string (tmp->srccaps);
-
- sink = gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, sinkcaps);
- src = gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS, srccaps);
-
- gst_element_class_add_pad_template (element_class, src);
- gst_element_class_add_pad_template (element_class, sink);
-}
-
-static void
-gst_dshowvideodec_class_init (GstDshowVideoDecClass * klass)
-{
- GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
- GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
-
- gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_dshowvideodec_dispose);
-
- gstelement_class->change_state =
- GST_DEBUG_FUNCPTR (gst_dshowvideodec_change_state);
-
- if (!parent_class)
- parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
-
- if (!dshowvideodec_debug) {
- GST_DEBUG_CATEGORY_INIT (dshowvideodec_debug, "dshowvideodec", 0,
- "Directshow filter video decoder");
- }
-}
-
-static void
-gst_dshowvideodec_init (GstDshowVideoDec * vdec,
- GstDshowVideoDecClass * vdec_class)
-{
- GstElementClass *element_class = GST_ELEMENT_GET_CLASS (vdec);
- HRESULT hr;
-
- /* setup pads */
- vdec->sinkpad =
- gst_pad_new_from_template (gst_element_class_get_pad_template
- (element_class, "sink"), "sink");
-
- gst_pad_set_setcaps_function (vdec->sinkpad, gst_dshowvideodec_sink_setcaps);
- gst_pad_set_event_function (vdec->sinkpad, gst_dshowvideodec_sink_event);
- gst_pad_set_chain_function (vdec->sinkpad, gst_dshowvideodec_chain);
- gst_element_add_pad (GST_ELEMENT (vdec), vdec->sinkpad);
-
- vdec->srcpad =
- gst_pad_new_from_template (gst_element_class_get_pad_template
- (element_class, "src"), "src");
-/* needed to implement caps negociation on our src pad */
-/* gst_pad_set_getcaps_function (vdec->srcpad, gst_dshowvideodec_src_getcaps);
- gst_pad_set_setcaps_function (vdec->srcpad, gst_dshowvideodec_src_setcaps);*/
- gst_element_add_pad (GST_ELEMENT (vdec), vdec->srcpad);
-
- vdec->srcfilter = NULL;
- vdec->decfilter = NULL;
- vdec->sinkfilter = NULL;
-
- vdec->last_ret = GST_FLOW_OK;
-
- vdec->filtergraph = NULL;
- vdec->mediafilter = NULL;
- vdec->gstdshowsrcfilter = NULL;
- vdec->srccaps = NULL;
- vdec->segment = gst_segment_new ();
-
- hr = CoInitialize (0);
- if (SUCCEEDED (hr)) {
- vdec->comInitialized = TRUE;
- }
-}
-
-static void
-gst_dshowvideodec_dispose (GObject * object)
-{
- GstDshowVideoDec *vdec = (GstDshowVideoDec *) (object);
-
- if (vdec->segment) {
- gst_segment_free (vdec->segment);
- vdec->segment = NULL;
- }
-
- if (vdec->comInitialized) {
- CoUninitialize ();
- vdec->comInitialized = FALSE;
- }
-
- G_OBJECT_CLASS (parent_class)->dispose (object);
-}
-
-static GstStateChangeReturn
-gst_dshowvideodec_change_state (GstElement * element, GstStateChange transition)
-{
- GstDshowVideoDec *vdec = (GstDshowVideoDec *) (element);
-
- switch (transition) {
- case GST_STATE_CHANGE_NULL_TO_READY:
- if (!gst_dshowvideodec_create_graph_and_filters (vdec))
- return GST_STATE_CHANGE_FAILURE;
- break;
- case GST_STATE_CHANGE_READY_TO_PAUSED:
- break;
- case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
- break;
- case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
- break;
- case GST_STATE_CHANGE_PAUSED_TO_READY:
- break;
- case GST_STATE_CHANGE_READY_TO_NULL:
- if (!gst_dshowvideodec_destroy_graph_and_filters (vdec))
- return GST_STATE_CHANGE_FAILURE;
- break;
- default:
- break;
- }
-
- return GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
-}
-
-static gboolean
-gst_dshowvideodec_sink_setcaps (GstPad * pad, GstCaps * caps)
-{
- gboolean ret = FALSE;
- HRESULT hres;
- GstStructure *s = gst_caps_get_structure (caps, 0);
- GstDshowVideoDec *vdec = (GstDshowVideoDec *) gst_pad_get_parent (pad);
- GstDshowVideoDecClass *klass =
- (GstDshowVideoDecClass *) G_OBJECT_GET_CLASS (vdec);
- GstBuffer *extradata = NULL;
- const GValue *v = NULL;
- gint size = 0;
- GstCaps *caps_out;
- AM_MEDIA_TYPE output_mediatype, input_mediatype;
- VIDEOINFOHEADER *input_vheader = NULL, *output_vheader = NULL;
- IPin *output_pin = NULL, *input_pin = NULL;
- IGstDshowInterface *gstdshowinterface = NULL;
- const GValue *fps;
-
- /* read data */
- if (!gst_structure_get_int (s, "width", &vdec->width) ||
- !gst_structure_get_int (s, "height", &vdec->height)) {
- GST_ELEMENT_ERROR (vdec, CORE, NEGOTIATION,
- ("error getting video width or height from caps"), (NULL));
- goto end;
- }
- fps = gst_structure_get_value (s, "framerate");
- if (!fps) {
- GST_ELEMENT_ERROR (vdec, CORE, NEGOTIATION,
- ("error getting video framerate from caps"), (NULL));
- goto end;
- }
- vdec->fps_n = gst_value_get_fraction_numerator (fps);
- vdec->fps_d = gst_value_get_fraction_denominator (fps);
-
- if ((v = gst_structure_get_value (s, "codec_data")))
- extradata = gst_value_get_buffer (v);
-
- /* define the input type format */
- memset (&input_mediatype, 0, sizeof (AM_MEDIA_TYPE));
- input_mediatype.majortype = klass->entry->input_majortype;
- input_mediatype.subtype = klass->entry->input_subtype;
- input_mediatype.bFixedSizeSamples = FALSE;
- input_mediatype.bTemporalCompression = TRUE;
-
- if (strstr (klass->entry->sinkcaps, "video/mpeg, mpegversion= (int) 1")) {
- size =
- sizeof (MPEG1VIDEOINFO) + (extradata ? GST_BUFFER_SIZE (extradata) -
- 1 : 0);
- input_vheader = g_malloc0 (size);
-
- input_vheader->bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
- if (extradata) {
- MPEG1VIDEOINFO *mpeg_info = (MPEG1VIDEOINFO *) input_vheader;
-
- memcpy (mpeg_info->bSequenceHeader,
- GST_BUFFER_DATA (extradata), GST_BUFFER_SIZE (extradata));
- mpeg_info->cbSequenceHeader = GST_BUFFER_SIZE (extradata);
- }
- input_mediatype.formattype = FORMAT_MPEGVideo;
- } else {
- size =
- sizeof (VIDEOINFOHEADER) +
- (extradata ? GST_BUFFER_SIZE (extradata) : 0);
- input_vheader = g_malloc0 (size);
-
- input_vheader->bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
- if (extradata) { /* Codec data is appended after our header */
- memcpy (((guchar *) input_vheader) + sizeof (VIDEOINFOHEADER),
- GST_BUFFER_DATA (extradata), GST_BUFFER_SIZE (extradata));
- input_vheader->bmiHeader.biSize += GST_BUFFER_SIZE (extradata);
- }
- input_mediatype.formattype = FORMAT_VideoInfo;
- }
- input_vheader->rcSource.top = input_vheader->rcSource.left = 0;
- input_vheader->rcSource.right = vdec->width;
- input_vheader->rcSource.bottom = vdec->height;
- input_vheader->rcTarget = input_vheader->rcSource;
- input_vheader->bmiHeader.biWidth = vdec->width;
- input_vheader->bmiHeader.biHeight = vdec->height;
- input_vheader->bmiHeader.biPlanes = 1;
- input_vheader->bmiHeader.biBitCount = 16;
- input_vheader->bmiHeader.biCompression = klass->entry->format;
- input_vheader->bmiHeader.biSizeImage =
- (vdec->width * vdec->height) * (input_vheader->bmiHeader.biBitCount / 8);
-
- input_mediatype.cbFormat = size;
- input_mediatype.pbFormat = (BYTE *) input_vheader;
- input_mediatype.lSampleSize = input_vheader->bmiHeader.biSizeImage;
-
- hres = IBaseFilter_QueryInterface (vdec->srcfilter, &IID_IGstDshowInterface,
- (void **) &gstdshowinterface);
- if (hres != S_OK || !gstdshowinterface) {
- GST_ELEMENT_ERROR (vdec, CORE, NEGOTIATION,
- ("Can't get IGstDshowInterface interface from dshow fakesrc filter (error=%d)",
- hres), (NULL));
- goto end;
- }
-
- /* save a reference to IGstDshowInterface to use it processing functions */
- if (!vdec->gstdshowsrcfilter) {
- vdec->gstdshowsrcfilter = gstdshowinterface;
- IBaseFilter_AddRef (vdec->gstdshowsrcfilter);
- }
-
- IGstDshowInterface_gst_set_media_type (gstdshowinterface, &input_mediatype);
- IGstDshowInterface_Release (gstdshowinterface);
- gstdshowinterface = NULL;
-
- /* set the sample size for fakesrc filter to the output buffer size */
- IGstDshowInterface_gst_set_sample_size (vdec->gstdshowsrcfilter,
- input_mediatype.lSampleSize);
-
- /* connect our fake src to decoder */
- gst_dshow_get_pin_from_filter (vdec->srcfilter, PINDIR_OUTPUT, &output_pin);
- if (!output_pin) {
- GST_ELEMENT_ERROR (vdec, CORE, NEGOTIATION,
- ("Can't get output pin from our directshow fakesrc filter"), (NULL));
- goto end;
- }
- gst_dshow_get_pin_from_filter (vdec->decfilter, PINDIR_INPUT, &input_pin);
- if (!input_pin) {
- GST_ELEMENT_ERROR (vdec, CORE, NEGOTIATION,
- ("Can't get input pin from decoder filter"), (NULL));
- goto end;
- }
-
- hres =
- IFilterGraph_ConnectDirect (vdec->filtergraph, output_pin, input_pin,
- NULL);
- if (hres != S_OK) {
- GST_ELEMENT_ERROR (vdec, CORE, NEGOTIATION,
- ("Can't connect fakesrc with decoder (error=%d)", hres), (NULL));
- goto end;
- }
-
- IPin_Release (input_pin);
- IPin_Release (output_pin);
- input_pin = NULL;
- output_pin = NULL;
-
- /* get decoder output video format */
- if (!gst_dshowvideodec_get_filter_output_format (vdec,
- &klass->entry->output_subtype, &output_vheader, &size)) {
- GST_ELEMENT_ERROR (vdec, CORE, NEGOTIATION,
- ("Can't get decoder output video format"), (NULL));
- goto end;
- }
-
- memset (&output_mediatype, 0, sizeof (AM_MEDIA_TYPE));
- output_mediatype.majortype = klass->entry->output_majortype;
- output_mediatype.subtype = klass->entry->output_subtype;
- output_mediatype.bFixedSizeSamples = TRUE;
- output_mediatype.bTemporalCompression = FALSE;
- output_mediatype.lSampleSize = output_vheader->bmiHeader.biSizeImage;
- output_mediatype.formattype = FORMAT_VideoInfo;
- output_mediatype.cbFormat = size;
- output_mediatype.pbFormat = (char *) output_vheader;
-
- hres = IBaseFilter_QueryInterface (vdec->sinkfilter, &IID_IGstDshowInterface,
- (void **) &gstdshowinterface);
- if (hres != S_OK || !gstdshowinterface) {
- GST_ELEMENT_ERROR (vdec, CORE, NEGOTIATION,
- ("Can't get IGstDshowInterface interface from dshow fakesink filter (error=%d)",
- hres), (NULL));
- goto end;
- }
-
- IGstDshowInterface_gst_set_media_type (gstdshowinterface, &output_mediatype);
- IGstDshowInterface_gst_set_buffer_callback (gstdshowinterface,
- gst_dshowvideodec_push_buffer, (byte *) vdec);
- IGstDshowInterface_Release (gstdshowinterface);
- gstdshowinterface = NULL;
-
- /* connect decoder to our fake sink */
- gst_dshow_get_pin_from_filter (vdec->decfilter, PINDIR_OUTPUT, &output_pin);
- if (!output_pin) {
- GST_ELEMENT_ERROR (vdec, CORE, NEGOTIATION,
- ("Can't get output pin from our decoder filter"), (NULL));
- goto end;
- }
-
- gst_dshow_get_pin_from_filter (vdec->sinkfilter, PINDIR_INPUT, &input_pin);
- if (!input_pin) {
- GST_ELEMENT_ERROR (vdec, CORE, NEGOTIATION,
- ("Can't get input pin from our directshow fakesink filter"), (NULL));
- goto end;
- }
-
- hres =
- IFilterGraph_ConnectDirect (vdec->filtergraph, output_pin, input_pin,
- &output_mediatype);
- if (hres != S_OK) {
- GST_ELEMENT_ERROR (vdec, CORE, NEGOTIATION,
- ("Can't connect decoder with fakesink (error=%d)", hres), (NULL));
- goto end;
- }
-
- /* negotiate output */
- caps_out = gst_caps_from_string (klass->entry->srccaps);
- gst_caps_set_simple (caps_out,
- "width", G_TYPE_INT, vdec->width,
- "height", G_TYPE_INT, vdec->height,
- "framerate", GST_TYPE_FRACTION, vdec->fps_n, vdec->fps_d, NULL);
- if (!gst_pad_set_caps (vdec->srcpad, caps_out)) {
- gst_caps_unref (caps_out);
- GST_ELEMENT_ERROR (vdec, CORE, NEGOTIATION,
- ("Failed to negotiate output"), (NULL));
- goto end;
- }
- gst_caps_unref (caps_out);
-
- hres = IMediaFilter_Run (vdec->mediafilter, -1);
- if (hres != S_OK) {
- GST_ELEMENT_ERROR (vdec, CORE, NEGOTIATION,
- ("Can't run the directshow graph (error=%d)", hres), (NULL));
- goto end;
- }
-
- ret = TRUE;
-end:
- gst_object_unref (vdec);
- if (input_vheader)
- g_free (input_vheader);
- if (gstdshowinterface)
- IGstDshowInterface_Release (gstdshowinterface);
- if (input_pin)
- IPin_Release (input_pin);
- if (output_pin)
- IPin_Release (output_pin);
-
- return ret;
-}
-
-static gboolean
-gst_dshowvideodec_sink_event (GstPad * pad, GstEvent * event)
-{
- gboolean ret = TRUE;
- GstDshowVideoDec *vdec = (GstDshowVideoDec *) gst_pad_get_parent (pad);
-
- switch (GST_EVENT_TYPE (event)) {
- case GST_EVENT_FLUSH_STOP:
- gst_dshowvideodec_flush (vdec);
- ret = gst_pad_event_default (pad, event);
- break;
- case GST_EVENT_NEWSEGMENT:
- {
- GstFormat format;
- gdouble rate;
- gint64 start, stop, time;
- gboolean update;
-
- gst_event_parse_new_segment (event, &update, &rate, &format, &start,
- &stop, &time);
-
- /* save the new segment in our local current segment */
- gst_segment_set_newsegment (vdec->segment, update, rate, format, start,
- stop, time);
-
- GST_CAT_DEBUG_OBJECT (dshowvideodec_debug, vdec,
- "new segment received => start=%" GST_TIME_FORMAT " stop=%"
- GST_TIME_FORMAT, GST_TIME_ARGS (vdec->segment->start),
- GST_TIME_ARGS (vdec->segment->stop));
-
- if (update) {
- GST_CAT_DEBUG_OBJECT (dshowvideodec_debug, vdec,
- "closing current segment flushing..");
- gst_dshowvideodec_flush (vdec);
- }
-
- ret = gst_pad_event_default (pad, event);
- break;
- }
- default:
- ret = gst_pad_event_default (pad, event);
- break;
- }
-
- gst_object_unref (vdec);
-
- return ret;
-}
-
-static GstFlowReturn
-gst_dshowvideodec_chain (GstPad * pad, GstBuffer * buffer)
-{
- GstDshowVideoDec *vdec = (GstDshowVideoDec *) gst_pad_get_parent (pad);
- gboolean discount = FALSE;
- GstClockTime stop;
-
- if (!vdec->gstdshowsrcfilter) {
- /* we are not setup */
- vdec->last_ret = GST_FLOW_WRONG_STATE;
- goto beach;
- }
-
- if (GST_FLOW_IS_FATAL (vdec->last_ret)) {
- GST_DEBUG_OBJECT (vdec, "last decoding iteration generated a fatal error "
- "%s", gst_flow_get_name (vdec->last_ret));
- goto beach;
- }
-
- /* check if duration is valid and use duration only when it's valid
- /* because dshow is not decoding frames having stop smaller than start */
- if (GST_BUFFER_DURATION_IS_VALID (buffer)) {
- stop = GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer);
- } else {
- stop = GST_BUFFER_TIMESTAMP (buffer);
- }
-
- GST_CAT_LOG_OBJECT (dshowvideodec_debug, vdec,
- "chain (size %d)=> pts %" GST_TIME_FORMAT " stop %" GST_TIME_FORMAT,
- GST_BUFFER_SIZE (buffer), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)),
- GST_TIME_ARGS (stop));
-
- /* if the incoming buffer has discont flag set => flush decoder data */
- if (buffer && GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT)) {
- GST_CAT_DEBUG_OBJECT (dshowvideodec_debug, vdec,
- "this buffer has a DISCONT flag (%" GST_TIME_FORMAT "), flushing",
- GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)));
- gst_dshowvideodec_flush (vdec);
- discount = TRUE;
- }
-
- /* push the buffer to the directshow decoder */
- IGstDshowInterface_gst_push_buffer (vdec->gstdshowsrcfilter,
- GST_BUFFER_DATA (buffer), GST_BUFFER_TIMESTAMP (buffer), stop,
- GST_BUFFER_SIZE (buffer), discount);
-
-beach:
- gst_buffer_unref (buffer);
- gst_object_unref (vdec);
-
- return vdec->last_ret;
-}
-
-static gboolean
-gst_dshowvideodec_push_buffer (byte * buffer, long size, byte * src_object,
- UINT64 start, UINT64 stop)
-{
- GstDshowVideoDec *vdec = (GstDshowVideoDec *) src_object;
- GstDshowVideoDecClass *klass =
- (GstDshowVideoDecClass *) G_OBJECT_GET_CLASS (vdec);
- GstBuffer *buf = NULL;
- gboolean in_seg = FALSE;
- gint64 clip_start = 0, clip_stop = 0;
-
- /* check if this buffer is in our current segment */
- in_seg = gst_segment_clip (vdec->segment, GST_FORMAT_TIME,
- start, stop, &clip_start, &clip_stop);
-
- /* if the buffer is out of segment do not push it downstream */
- if (!in_seg) {
- GST_CAT_DEBUG_OBJECT (dshowvideodec_debug, vdec,
- "buffer is out of segment, start %" GST_TIME_FORMAT " stop %"
- GST_TIME_FORMAT, GST_TIME_ARGS (start), GST_TIME_ARGS (stop));
- return FALSE;
- }
-
- /* buffer is in our segment allocate a new out buffer and clip its
- * timestamps */
- vdec->last_ret = gst_pad_alloc_buffer (vdec->srcpad, GST_BUFFER_OFFSET_NONE,
- size, GST_PAD_CAPS (vdec->srcpad), &buf);
- if (!buf) {
- GST_CAT_WARNING_OBJECT (dshowvideodec_debug, vdec,
- "can't not allocate a new GstBuffer");
- return FALSE;
- }
-
- /* set buffer properties */
- GST_BUFFER_TIMESTAMP (buf) = clip_start;
- GST_BUFFER_DURATION (buf) = clip_stop - clip_start;
-
- if (strstr (klass->entry->srccaps, "rgb")) {
- /* FOR RGB directshow decoder will return bottom-up BITMAP
- * There is probably a way to get top-bottom video frames from
- * the decoder...
- */
- gint line = 0;
- guint stride = vdec->width * 4;
-
- for (; line < vdec->height; line++) {
- memcpy (GST_BUFFER_DATA (buf) + (line * stride),
- buffer + (size - ((line + 1) * (stride))), stride);
- }
- } else {
- memcpy (GST_BUFFER_DATA (buf), buffer, MIN (size, GST_BUFFER_SIZE (buf)));
- }
-
- GST_CAT_LOG_OBJECT (dshowvideodec_debug, vdec,
- "push_buffer (size %d)=> pts %" GST_TIME_FORMAT " stop %" GST_TIME_FORMAT
- " duration %" GST_TIME_FORMAT, size,
- GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
- GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf) + GST_BUFFER_DURATION (buf)),
- GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));
-
- /* push the buffer downstream */
- vdec->last_ret = gst_pad_push (vdec->srcpad, buf);
-
- return TRUE;
-}
-
-
-static GstCaps *
-gst_dshowvideodec_src_getcaps (GstPad * pad)
-{
- GstDshowVideoDec *vdec = (GstDshowVideoDec *) gst_pad_get_parent (pad);
- GstCaps *caps = NULL;
-
- if (!vdec->srccaps)
- vdec->srccaps = gst_caps_new_empty ();
-
- if (vdec->decfilter) {
- IPin *output_pin = NULL;
- IEnumMediaTypes *enum_mediatypes = NULL;
- HRESULT hres;
- ULONG fetched;
-
- if (!gst_dshow_get_pin_from_filter (vdec->decfilter, PINDIR_OUTPUT,
- &output_pin)) {
- GST_ELEMENT_ERROR (vdec, STREAM, FAILED,
- ("failed getting ouput pin from the decoder"), (NULL));
- goto beach;
- }
-
- hres = IPin_EnumMediaTypes (output_pin, &enum_mediatypes);
- if (hres == S_OK && enum_mediatypes) {
- AM_MEDIA_TYPE *mediatype = NULL;
-
- IEnumMediaTypes_Reset (enum_mediatypes);
- while (hres =
- IEnumMoniker_Next (enum_mediatypes, 1, &mediatype, &fetched),
- hres == S_OK) {
- RPC_STATUS rpcstatus;
- VIDEOINFOHEADER *video_info;
- GstCaps *mediacaps = NULL;
-
- /* RGB24 */
- if ((UuidCompare (&mediatype->subtype, &MEDIASUBTYPE_RGB24,
- &rpcstatus) == 0 && rpcstatus == RPC_S_OK)
- && (UuidCompare (&mediatype->formattype, &FORMAT_VideoInfo,
- &rpcstatus) == 0 && rpcstatus == RPC_S_OK)) {
- video_info = (VIDEOINFOHEADER *) mediatype->pbFormat;
-
- /* ffmpegcolorspace handles RGB24 in BIG_ENDIAN */
- mediacaps = gst_caps_new_simple ("video/x-raw-rgb",
- "bpp", G_TYPE_INT, 24,
- "depth", G_TYPE_INT, 24,
- "width", G_TYPE_INT, video_info->bmiHeader.biWidth,
- "height", G_TYPE_INT, video_info->bmiHeader.biHeight,
- "framerate", GST_TYPE_FRACTION,
- (int) (10000000 / video_info->AvgTimePerFrame), 1, "endianness",
- G_TYPE_INT, G_BIG_ENDIAN, "red_mask", G_TYPE_INT, 255,
- "green_mask", G_TYPE_INT, 65280, "blue_mask", G_TYPE_INT,
- 16711680, NULL);
-
- if (mediacaps) {
- vdec->mediatypes = g_list_append (vdec->mediatypes, mediatype);
- gst_caps_append (vdec->srccaps, mediacaps);
- } else {
- gst_dshow_free_mediatype (mediatype);
- }
- } else {
- gst_dshow_free_mediatype (mediatype);
- }
-
- }
- IEnumMediaTypes_Release (enum_mediatypes);
- }
- if (output_pin) {
- IPin_Release (output_pin);
- }
- }
-
- if (vdec->srccaps)
- caps = gst_caps_ref (vdec->srccaps);
-
-beach:
- gst_object_unref (vdec);
-
- return caps;
-}
-
-static gboolean
-gst_dshowvideodec_src_setcaps (GstPad * pad, GstCaps * caps)
-{
- gboolean ret = FALSE;
-
- return ret;
-}
-
-static gboolean
-gst_dshowvideodec_flush (GstDshowVideoDec * vdec)
-{
- if (!vdec->gstdshowsrcfilter)
- return FALSE;
-
- /* flush dshow decoder and reset timestamp */
- IGstDshowInterface_gst_flush (vdec->gstdshowsrcfilter);
-
- return TRUE;
-}
-
-static gboolean
-gst_dshowvideodec_get_filter_output_format (GstDshowVideoDec * vdec,
- GUID * subtype, VIDEOINFOHEADER ** format, guint * size)
-{
- IPin *output_pin = NULL;
- IEnumMediaTypes *enum_mediatypes = NULL;
- HRESULT hres;
- ULONG fetched;
- BOOL ret = FALSE;
-
- if (!vdec->decfilter)
- return FALSE;
-
- if (!gst_dshow_get_pin_from_filter (vdec->decfilter, PINDIR_OUTPUT,
- &output_pin)) {
- GST_ELEMENT_ERROR (vdec, CORE, NEGOTIATION,
- ("failed getting ouput pin from the decoder"), (NULL));
- return FALSE;
- }
-
- hres = IPin_EnumMediaTypes (output_pin, &enum_mediatypes);
- if (hres == S_OK && enum_mediatypes) {
- AM_MEDIA_TYPE *mediatype = NULL;
-
- IEnumMediaTypes_Reset (enum_mediatypes);
- while (hres =
- IEnumMoniker_Next (enum_mediatypes, 1, &mediatype, &fetched),
- hres == S_OK) {
- RPC_STATUS rpcstatus;
-
- if ((UuidCompare (&mediatype->subtype, subtype, &rpcstatus) == 0
- && rpcstatus == RPC_S_OK) &&
- (UuidCompare (&mediatype->formattype, &FORMAT_VideoInfo,
- &rpcstatus) == 0 && rpcstatus == RPC_S_OK)) {
- *size = mediatype->cbFormat;
- *format = g_malloc0 (*size);
- memcpy (*format, mediatype->pbFormat, *size);
- ret = TRUE;
- }
- gst_dshow_free_mediatype (mediatype);
- if (ret)
- break;
- }
- IEnumMediaTypes_Release (enum_mediatypes);
- }
- if (output_pin) {
- IPin_Release (output_pin);
- }
-
- return ret;
-}
-
-static gboolean
-gst_dshowvideodec_create_graph_and_filters (GstDshowVideoDec * vdec)
-{
- HRESULT hres = S_FALSE;
- GstDshowVideoDecClass *klass =
- (GstDshowVideoDecClass *) G_OBJECT_GET_CLASS (vdec);
-
- /* create the filter graph manager object */
- hres = CoCreateInstance (&CLSID_FilterGraph, NULL, CLSCTX_INPROC,
- &IID_IFilterGraph, (LPVOID *) & vdec->filtergraph);
- if (hres != S_OK || !vdec->filtergraph) {
- GST_ELEMENT_ERROR (vdec, STREAM, FAILED, ("Can't create an instance "
- "of the directshow graph manager (error=%d)", hres), (NULL));
- goto error;
- }
-
- hres = IFilterGraph_QueryInterface (vdec->filtergraph, &IID_IMediaFilter,
- (void **) &vdec->mediafilter);
- if (hres != S_OK || !vdec->mediafilter) {
- GST_ELEMENT_ERROR (vdec, STREAM, FAILED,
- ("Can't get IMediacontrol interface "
- "from the graph manager (error=%d)", hres), (NULL));
- goto error;
- }
-
- /* create fake src filter */
- hres = CoCreateInstance (&CLSID_DshowFakeSrc, NULL, CLSCTX_INPROC,
- &IID_IBaseFilter, (LPVOID *) & vdec->srcfilter);
- if (hres != S_OK || !vdec->srcfilter) {
- GST_ELEMENT_ERROR (vdec, STREAM, FAILED, ("Can't create an instance "
- "of the directshow fakesrc (error=%d)", hres), (NULL));
- goto error;
- }
-
- /* search a decoder filter and create it */
- if (!gst_dshow_find_filter (klass->entry->input_majortype,
- klass->entry->input_subtype,
- klass->entry->output_majortype,
- klass->entry->output_subtype,
- klass->entry->preferred_filter_substring, &vdec->decfilter)) {
- GST_ELEMENT_ERROR (vdec, STREAM, FAILED, ("Can't create an instance "
- "of the decoder filter"), (NULL));
- goto error;
- }
-
- /* create fake sink filter */
- hres = CoCreateInstance (&CLSID_DshowFakeSink, NULL, CLSCTX_INPROC,
- &IID_IBaseFilter, (LPVOID *) & vdec->sinkfilter);
- if (hres != S_OK || !vdec->sinkfilter) {
- GST_ELEMENT_ERROR (vdec, STREAM, FAILED, ("Can't create an instance "
- "of the directshow fakesink (error=%d)", hres), (NULL));
- goto error;
- }
-
- /* add filters to the graph */
- hres = IFilterGraph_AddFilter (vdec->filtergraph, vdec->srcfilter, L"src");
- if (hres != S_OK) {
- GST_ELEMENT_ERROR (vdec, STREAM, FAILED, ("Can't add fakesrc filter "
- "to the graph (error=%d)", hres), (NULL));
- goto error;
- }
-
- hres =
- IFilterGraph_AddFilter (vdec->filtergraph, vdec->decfilter, L"decoder");
- if (hres != S_OK) {
- GST_ELEMENT_ERROR (vdec, STREAM, FAILED, ("Can't add decoder filter "
- "to the graph (error=%d)", hres), (NULL));
- goto error;
- }
-
- hres = IFilterGraph_AddFilter (vdec->filtergraph, vdec->sinkfilter, L"sink");
- if (hres != S_OK) {
- GST_ELEMENT_ERROR (vdec, STREAM, FAILED, ("Can't add fakesink filter "
- "to the graph (error=%d)", hres), (NULL));
- goto error;
- }
-
- return TRUE;
-
-error:
- if (vdec->srcfilter) {
- IBaseFilter_Release (vdec->srcfilter);
- vdec->srcfilter = NULL;
- }
- if (vdec->decfilter) {
- IBaseFilter_Release (vdec->decfilter);
- vdec->decfilter = NULL;
- }
- if (vdec->sinkfilter) {
- IBaseFilter_Release (vdec->sinkfilter);
- vdec->sinkfilter = NULL;
- }
- if (vdec->mediafilter) {
- IMediaFilter_Release (vdec->mediafilter);
- vdec->mediafilter = NULL;
- }
- if (vdec->filtergraph) {
- IFilterGraph_Release (vdec->filtergraph);
- vdec->filtergraph = NULL;
- }
-
- return FALSE;
-}
-
-static gboolean
-gst_dshowvideodec_destroy_graph_and_filters (GstDshowVideoDec * vdec)
-{
- if (vdec->mediafilter) {
- IMediaFilter_Stop (vdec->mediafilter);
- }
-
- if (vdec->gstdshowsrcfilter) {
- IGstDshowInterface_Release (vdec->gstdshowsrcfilter);
- vdec->gstdshowsrcfilter = NULL;
- }
- if (vdec->srcfilter) {
- if (vdec->filtergraph)
- IFilterGraph_RemoveFilter (vdec->filtergraph, vdec->srcfilter);
- IBaseFilter_Release (vdec->srcfilter);
- vdec->srcfilter = NULL;
- }
- if (vdec->decfilter) {
- if (vdec->filtergraph)
- IFilterGraph_RemoveFilter (vdec->filtergraph, vdec->decfilter);
- IBaseFilter_Release (vdec->decfilter);
- vdec->decfilter = NULL;
- }
- if (vdec->sinkfilter) {
- if (vdec->filtergraph)
- IFilterGraph_RemoveFilter (vdec->filtergraph, vdec->sinkfilter);
- IBaseFilter_Release (vdec->sinkfilter);
- vdec->sinkfilter = NULL;
- }
- if (vdec->mediafilter) {
- IMediaFilter_Release (vdec->mediafilter);
- vdec->mediafilter = NULL;
- }
- if (vdec->filtergraph) {
- IFilterGraph_Release (vdec->filtergraph);
- vdec->filtergraph = NULL;
- }
-
- return TRUE;
-}
-
-gboolean
-dshow_vdec_register (GstPlugin * plugin)
-{
- GTypeInfo info = {
- sizeof (GstDshowVideoDecClass),
- (GBaseInitFunc) gst_dshowvideodec_base_init,
- NULL,
- (GClassInitFunc) gst_dshowvideodec_class_init,
- NULL,
- NULL,
- sizeof (GstDshowVideoDec),
- 0,
- (GInstanceInitFunc) gst_dshowvideodec_init,
- };
- gint i;
- HRESULT hr;
-
- GST_DEBUG_CATEGORY_INIT (dshowvideodec_debug, "dshowvideodec", 0,
- "Directshow filter video decoder");
-
- hr = CoInitialize (0);
-
- for (i = 0; i < sizeof (video_dec_codecs) / sizeof (CodecEntry); i++) {
- GType type;
-
- if (gst_dshow_find_filter (video_dec_codecs[i].input_majortype,
- video_dec_codecs[i].input_subtype,
- video_dec_codecs[i].output_majortype,
- video_dec_codecs[i].output_subtype,
- video_dec_codecs[i].preferred_filter_substring, NULL)) {
-
- GST_CAT_DEBUG (dshowvideodec_debug, "Registering %s",
- video_dec_codecs[i].element_name);
-
- tmp = &video_dec_codecs[i];
- type =
- g_type_register_static (GST_TYPE_ELEMENT,
- video_dec_codecs[i].element_name, &info, 0);
- if (!gst_element_register (plugin, video_dec_codecs[i].element_name,
- GST_RANK_PRIMARY, type)) {
- return FALSE;
- }
- GST_CAT_DEBUG (dshowvideodec_debug, "Registered %s",
- video_dec_codecs[i].element_name);
- } else {
- GST_CAT_DEBUG (dshowvideodec_debug,
- "Element %s not registered (the format is not supported by the system)",
- video_dec_codecs[i].element_name);
- }
- }
-
- if (SUCCEEDED (hr))
- CoUninitialize ();
-
- return TRUE;
-}