Tizen 2.0 Release
[framework/multimedia/gst-plugins-bad0.10.git] / sys / dshowdecwrapper / gstdshowaudiodec.cpp
1 /*
2  * GStreamer DirectShow codecs wrapper
3  * Copyright <2006, 2007, 2008, 2009, 2010> Fluendo <support@fluendo.com>
4  * Copyright <2006, 2007, 2008> Pioneers of the Inevitable <songbird@songbirdnest.com>
5  * Copyright <2007,2008> Sebastien Moutte <sebastien@moutte.net>
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a
8  * copy of this software and associated documentation files (the "Software"),
9  * to deal in the Software without restriction, including without limitation
10  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11  * and/or sell copies of the Software, and to permit persons to whom the
12  * Software is furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in
15  * all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23  * DEALINGS IN THE SOFTWARE.
24  *
25  * Alternatively, the contents of this file may be used under the
26  * GNU Lesser General Public License Version 2.1 (the "LGPL"), in
27  * which case the following provisions apply instead of the ones
28  * mentioned above:
29  *
30  * This library is free software; you can redistribute it and/or
31  * modify it under the terms of the GNU Library General Public
32  * License as published by the Free Software Foundation; either
33  * version 2 of the License, or (at your option) any later version.
34  *
35  * This library is distributed in the hope that it will be useful,
36  * but WITHOUT ANY WARRANTY; without even the implied warranty of
37  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
38  * Library General Public License for more details.
39  *
40  * You should have received a copy of the GNU Library General Public
41  * License along with this library; if not, write to the
42  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
43  * Boston, MA 02111-1307, USA.
44  */
45
46 #ifdef HAVE_CONFIG_H
47 #include "config.h"
48 #endif
49
50 #include "gstdshowaudiodec.h"
51 #include <mmreg.h>
52 #include <dmoreg.h>
53 #include <wmcodecdsp.h>
54
55 GST_DEBUG_CATEGORY_STATIC (dshowaudiodec_debug);
56 #define GST_CAT_DEFAULT dshowaudiodec_debug
57
58 GST_BOILERPLATE (GstDshowAudioDec, gst_dshowaudiodec, GstElement,
59     GST_TYPE_ELEMENT);
60
61 static void gst_dshowaudiodec_dispose (GObject * object);
62 static GstStateChangeReturn gst_dshowaudiodec_change_state
63     (GstElement * element, GstStateChange transition);
64
65 /* sink pad overwrites */
66 static gboolean gst_dshowaudiodec_sink_setcaps (GstPad * pad, GstCaps * caps);
67 static GstFlowReturn gst_dshowaudiodec_chain (GstPad * pad, GstBuffer * buffer);
68 static gboolean gst_dshowaudiodec_sink_event (GstPad * pad, GstEvent * event);
69
70 /* utils */
71 static gboolean gst_dshowaudiodec_create_graph_and_filters (GstDshowAudioDec *
72     adec);
73 static gboolean gst_dshowaudiodec_destroy_graph_and_filters (GstDshowAudioDec *
74     adec);
75 static gboolean gst_dshowaudiodec_flush (GstDshowAudioDec * adec);
76 static gboolean gst_dshowaudiodec_get_filter_settings (GstDshowAudioDec * adec);
77 static gboolean gst_dshowaudiodec_setup_graph (GstDshowAudioDec * adec, GstCaps *caps);
78
79 /* All the GUIDs we want are generated from the FOURCC like this */
80 #define GUID_MEDIASUBTYPE_FROM_FOURCC(fourcc) \
81     { fourcc , 0x0000, 0x0010, \
82     { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }}
83
84 /* WMA we should always use the DMO */
85 static PreferredFilter preferred_wma_filters[] = {
86   {&CLSID_CWMADecMediaObject, &DMOCATEGORY_AUDIO_DECODER},
87   {0}
88 };
89
90 /* Prefer the Vista (DMO) decoder if present, otherwise the XP
91  * decoder (not a DMO), otherwise fallback to highest-merit */
92 static const GUID CLSID_XP_MP3_DECODER = {0x38BE3000, 0xDBF4, 0x11D0,
93    {0x86,0x0E,0x00,0xA0,0x24,0xCF,0xEF,0x6D}};
94 static PreferredFilter preferred_mp3_filters[] = {
95   {&CLSID_CMP3DecMediaObject, &DMOCATEGORY_AUDIO_DECODER},
96   {&CLSID_XP_MP3_DECODER},
97   {0}
98 };
99
100 /* MPEG 1/2: use the MPEG Audio Decoder filter */
101 static const GUID CLSID_WINDOWS_MPEG_AUDIO_DECODER = 
102   {0x4A2286E0, 0x7BEF, 0x11CE, 
103    {0x9B, 0xD9, 0x00, 0x00, 0xE2, 0x02, 0x59, 0x9C}};
104 static PreferredFilter preferred_mpegaudio_filters[] = {
105   {&CLSID_WINDOWS_MPEG_AUDIO_DECODER},
106   {0}
107 };
108
109 static const AudioCodecEntry audio_dec_codecs[] = {
110   {"dshowadec_wma1", "Windows Media Audio 7",
111    WAVE_FORMAT_MSAUDIO1,
112    "audio/x-wma, wmaversion = (int) 1",
113    preferred_wma_filters},
114
115   {"dshowadec_wma2", "Windows Media Audio 8",
116    WAVE_FORMAT_WMAUDIO2,
117    "audio/x-wma, wmaversion = (int) 2",
118    preferred_wma_filters},
119
120   {"dshowadec_wma3", "Windows Media Audio 9 Professional",
121    WAVE_FORMAT_WMAUDIO3,
122    "audio/x-wma, wmaversion = (int) 3",
123    preferred_wma_filters},
124
125   {"dshowadec_wma4", "Windows Media Audio 9 Lossless",
126    WAVE_FORMAT_WMAUDIO_LOSSLESS,
127    "audio/x-wma, wmaversion = (int) 4",
128    preferred_wma_filters},
129
130   {"dshowadec_wms", "Windows Media Audio Voice v9",
131    WAVE_FORMAT_WMAVOICE9,
132    "audio/x-wms",
133    preferred_wma_filters},
134
135   {"dshowadec_mp3", "MPEG Layer 3 Audio",
136    WAVE_FORMAT_MPEGLAYER3,
137    "audio/mpeg, "
138        "mpegversion = (int) 1, "
139        "layer = (int)3, "
140        "rate = (int) [ 8000, 48000 ], "
141        "channels = (int) [ 1, 2 ], "
142        "parsed= (boolean) true",
143    preferred_mp3_filters},
144
145   {"dshowadec_mpeg_1_2", "MPEG Layer 1,2 Audio",
146    WAVE_FORMAT_MPEG,
147    "audio/mpeg, "
148        "mpegversion = (int) 1, "
149        "layer = (int) [ 1, 2 ], "
150        "rate = (int) [ 8000, 48000 ], "
151        "channels = (int) [ 1, 2 ], "
152        "parsed= (boolean) true",
153    preferred_mpegaudio_filters},
154 };
155
156 HRESULT AudioFakeSink::DoRenderSample(IMediaSample *pMediaSample)
157 {
158   GstBuffer *out_buf = NULL;
159   gboolean in_seg = FALSE;
160   GstClockTime buf_start, buf_stop;
161   gint64 clip_start = 0, clip_stop = 0;
162   guint start_offset = 0, stop_offset;
163   GstClockTime duration;
164
165   if(pMediaSample)
166   {
167     BYTE *pBuffer = NULL;
168     LONGLONG lStart = 0, lStop = 0;
169     long size = pMediaSample->GetActualDataLength();
170
171     pMediaSample->GetPointer(&pBuffer);
172     pMediaSample->GetTime(&lStart, &lStop);
173     
174     if (!GST_CLOCK_TIME_IS_VALID (mDec->timestamp)) {
175       // Convert REFERENCE_TIME to GST_CLOCK_TIME
176       mDec->timestamp = (GstClockTime)lStart * 100;
177     }
178     duration = (lStop - lStart) * 100;
179
180     buf_start = mDec->timestamp;
181     buf_stop = mDec->timestamp + duration;
182
183     /* save stop position to start next buffer with it */
184     mDec->timestamp = buf_stop;
185
186     /* check if this buffer is in our current segment */
187     in_seg = gst_segment_clip (mDec->segment, GST_FORMAT_TIME,
188         buf_start, buf_stop, &clip_start, &clip_stop);
189
190     /* if the buffer is out of segment do not push it downstream */
191     if (!in_seg) {
192       GST_DEBUG_OBJECT (mDec,
193           "buffer is out of segment, start %" GST_TIME_FORMAT " stop %"
194           GST_TIME_FORMAT, GST_TIME_ARGS (buf_start), GST_TIME_ARGS (buf_stop));
195       goto done;
196     }
197
198     /* buffer is entirely or partially in-segment, so allocate a
199      * GstBuffer for output, and clip if required */
200
201     /* allocate a new buffer for raw audio */
202     mDec->last_ret = gst_pad_alloc_buffer (mDec->srcpad, 
203         GST_BUFFER_OFFSET_NONE,
204         size,
205         GST_PAD_CAPS (mDec->srcpad), &out_buf);
206     if (!out_buf) {
207       GST_WARNING_OBJECT (mDec, "cannot allocate a new GstBuffer");
208       goto done;
209     }
210
211     /* set buffer properties */
212     GST_BUFFER_TIMESTAMP (out_buf) = buf_start;
213     GST_BUFFER_DURATION (out_buf) = duration;
214     memcpy (GST_BUFFER_DATA (out_buf), pBuffer,
215         MIN ((unsigned int)size, GST_BUFFER_SIZE (out_buf)));
216
217     /* we have to remove some heading samples */
218     if ((GstClockTime) clip_start > buf_start) {
219       start_offset = (guint)gst_util_uint64_scale_int (clip_start - buf_start,
220           mDec->rate, GST_SECOND) * mDec->depth / 8 * mDec->channels;
221     }
222     else
223       start_offset = 0;
224     /* we have to remove some trailing samples */
225     if ((GstClockTime) clip_stop < buf_stop) {
226       stop_offset = (guint)gst_util_uint64_scale_int (buf_stop - clip_stop,
227           mDec->rate, GST_SECOND) * mDec->depth / 8 * mDec->channels;
228     }
229     else
230       stop_offset = size;
231
232     /* truncating */
233     if ((start_offset != 0) || (stop_offset != (size_t) size)) {
234       GstBuffer *subbuf = gst_buffer_create_sub (out_buf, start_offset,
235           stop_offset - start_offset);
236
237       if (subbuf) {
238         gst_buffer_set_caps (subbuf, GST_PAD_CAPS (mDec->srcpad));
239         gst_buffer_unref (out_buf);
240         out_buf = subbuf;
241       }
242     }
243
244     GST_BUFFER_TIMESTAMP (out_buf) = clip_start;
245     GST_BUFFER_DURATION (out_buf) = clip_stop - clip_start;
246
247     /* replace the saved stop position by the clipped one */
248     mDec->timestamp = clip_stop;
249
250     GST_DEBUG_OBJECT (mDec,
251         "push_buffer (size %d)=> pts %" GST_TIME_FORMAT " stop %" GST_TIME_FORMAT
252         " duration %" GST_TIME_FORMAT, size,
253         GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (out_buf)),
254         GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (out_buf) +
255             GST_BUFFER_DURATION (out_buf)),
256         GST_TIME_ARGS (GST_BUFFER_DURATION (out_buf)));
257
258     mDec->last_ret = gst_pad_push (mDec->srcpad, out_buf);
259   }
260
261 done:
262   return S_OK;
263 }
264
265 HRESULT AudioFakeSink::CheckMediaType(const CMediaType *pmt)
266 {
267   if(pmt != NULL)
268   {
269     /* The Vista MP3 decoder (and possibly others?) outputs an 
270      * AM_MEDIA_TYPE with the wrong cbFormat. So, rather than using
271      * CMediaType.operator==, we implement a sufficient check ourselves.
272      * I think this is a bug in the MP3 decoder.
273      */
274     if (IsEqualGUID (pmt->majortype, m_MediaType.majortype) &&
275         IsEqualGUID (pmt->subtype, m_MediaType.subtype) &&
276         IsEqualGUID (pmt->formattype, m_MediaType.formattype))
277     {
278       /* Types are the same at the top-level. Now, we need to compare
279        * the format blocks.
280        * We special case WAVEFORMATEX to not check that 
281        * pmt->cbFormat == m_MediaType.cbFormat, though the actual format
282        * blocks must still be the same.
283        */
284       if (pmt->formattype == FORMAT_WaveFormatEx) {
285         if (pmt->cbFormat >= sizeof (WAVEFORMATEX) &&
286             m_MediaType.cbFormat >= sizeof (WAVEFORMATEX))
287         {
288           WAVEFORMATEX *wf1 = (WAVEFORMATEX *)pmt->pbFormat;
289           WAVEFORMATEX *wf2 = (WAVEFORMATEX *)m_MediaType.pbFormat;
290           if (wf1->cbSize == wf2->cbSize &&
291               memcmp (wf1, wf2, sizeof(WAVEFORMATEX) + wf1->cbSize) == 0)
292             return S_OK;
293         }
294       }
295       else {
296         if (pmt->cbFormat == m_MediaType.cbFormat &&
297              pmt->cbFormat == 0 ||
298              (pmt->pbFormat != NULL && m_MediaType.pbFormat != NULL &&
299                  memcmp (pmt->pbFormat, m_MediaType.pbFormat, pmt->cbFormat) == 0))
300           return S_OK;
301       }
302     }
303   }
304
305   return S_FALSE;
306 }
307
308 static void
309 gst_dshowaudiodec_base_init (gpointer klass)
310 {
311   GstDshowAudioDecClass *audiodec_class = (GstDshowAudioDecClass *) klass;
312   GstPadTemplate *src, *sink;
313   GstCaps *srccaps, *sinkcaps;
314   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
315   GstElementDetails details;
316   const AudioCodecEntry *tmp;
317   gpointer qdata;
318
319   qdata = g_type_get_qdata (G_OBJECT_CLASS_TYPE (klass), DSHOW_CODEC_QDATA);
320
321   /* element details */
322   tmp = audiodec_class->entry = (AudioCodecEntry *) qdata;
323
324   details.longname = g_strdup_printf ("DirectShow %s Decoder Wrapper",
325       tmp->element_longname);
326   details.klass = g_strdup ("Codec/Decoder/Audio");
327   details.description = g_strdup_printf ("DirectShow %s Decoder Wrapper",
328       tmp->element_longname);
329   details.author = "Sebastien Moutte <sebastien@moutte.net>";
330   gst_element_class_set_details (element_class, &details);
331   g_free (details.longname);
332   g_free (details.klass);
333   g_free (details.description);
334
335   sinkcaps = gst_caps_from_string (tmp->sinkcaps);
336
337   srccaps = gst_caps_from_string (
338       "audio/x-raw-int,"
339       "width = (int)[1, 32],"
340       "depth = (int)[1, 32],"
341       "rate = (int)[1, MAX],"
342       "channels = (int)[1, MAX],"
343       "signed = (boolean)true,"
344       "endianness = (int)" G_STRINGIFY(G_LITTLE_ENDIAN));
345
346   sink = gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, sinkcaps);
347   src = gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS, srccaps);
348
349   /* register */
350   gst_element_class_add_pad_template (element_class, src);
351   gst_element_class_add_pad_template (element_class, sink);
352
353   gst_object_unref (src);
354   gst_object_unref (sink);
355 }
356
357 static void
358 gst_dshowaudiodec_class_init (GstDshowAudioDecClass * klass)
359 {
360   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
361   GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
362
363   gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_dshowaudiodec_dispose);
364
365   gstelement_class->change_state =
366       GST_DEBUG_FUNCPTR (gst_dshowaudiodec_change_state);
367
368   parent_class = (GstElementClass *) g_type_class_peek_parent (klass);
369 }
370
371 static void
372 gst_dshowaudiodec_com_thread (GstDshowAudioDec * adec)
373 {
374   HRESULT res;
375
376   g_mutex_lock (adec->com_init_lock);
377
378   /* Initialize COM with a MTA for this process. This thread will
379    * be the first one to enter the apartement and the last one to leave
380    * it, unitializing COM properly */
381
382   res = CoInitializeEx (0, COINIT_MULTITHREADED);
383   if (res == S_FALSE)
384     GST_WARNING_OBJECT (adec, "COM has been already initialized in the same process");
385   else if (res == RPC_E_CHANGED_MODE)
386     GST_WARNING_OBJECT (adec, "The concurrency model of COM has changed.");
387   else
388     GST_INFO_OBJECT (adec, "COM intialized succesfully");
389
390   adec->comInitialized = TRUE;
391
392   /* Signal other threads waiting on this condition that COM was initialized */
393   g_cond_signal (adec->com_initialized);
394
395   g_mutex_unlock (adec->com_init_lock);
396
397   /* Wait until the unitialize condition is met to leave the COM apartement */
398   g_mutex_lock (adec->com_deinit_lock);
399   g_cond_wait (adec->com_uninitialize, adec->com_deinit_lock);
400
401   CoUninitialize ();
402   GST_INFO_OBJECT (adec, "COM unintialized succesfully");
403   adec->comInitialized = FALSE;
404   g_cond_signal (adec->com_uninitialized);
405   g_mutex_unlock (adec->com_deinit_lock);
406 }
407
408 static void
409 gst_dshowaudiodec_init (GstDshowAudioDec * adec,
410     GstDshowAudioDecClass * adec_class)
411 {
412   GstElementClass *element_class = GST_ELEMENT_GET_CLASS (adec);
413
414   /* setup pads */
415   adec->sinkpad =
416       gst_pad_new_from_template (gst_element_class_get_pad_template
417       (element_class, "sink"), "sink");
418
419   gst_pad_set_setcaps_function (adec->sinkpad, gst_dshowaudiodec_sink_setcaps);
420   gst_pad_set_event_function (adec->sinkpad, gst_dshowaudiodec_sink_event);
421   gst_pad_set_chain_function (adec->sinkpad, gst_dshowaudiodec_chain);
422   gst_element_add_pad (GST_ELEMENT (adec), adec->sinkpad);
423
424   adec->srcpad =
425       gst_pad_new_from_template (gst_element_class_get_pad_template
426       (element_class, "src"), "src");
427   gst_element_add_pad (GST_ELEMENT (adec), adec->srcpad);
428
429   adec->fakesrc = NULL;
430   adec->fakesink = NULL;
431
432   adec->decfilter = 0;
433   adec->filtergraph = 0;
434   adec->mediafilter = 0;
435
436   adec->timestamp = GST_CLOCK_TIME_NONE;
437   adec->segment = gst_segment_new ();
438   adec->setup = FALSE;
439   adec->depth = 0;
440   adec->bitrate = 0;
441   adec->block_align = 0;
442   adec->channels = 0;
443   adec->rate = 0;
444   adec->layer = 0;
445   adec->codec_data = NULL;
446
447   adec->last_ret = GST_FLOW_OK;
448
449   adec->com_init_lock = g_mutex_new();
450   adec->com_deinit_lock = g_mutex_new();
451   adec->com_initialized = g_cond_new();
452   adec->com_uninitialize = g_cond_new();
453   adec->com_uninitialized = g_cond_new();
454
455   g_mutex_lock (adec->com_init_lock);
456
457   /* create the COM initialization thread */
458   g_thread_create ((GThreadFunc)gst_dshowaudiodec_com_thread,
459       adec, FALSE, NULL);
460
461   /* wait until the COM thread signals that COM has been initialized */
462   g_cond_wait (adec->com_initialized, adec->com_init_lock);
463   g_mutex_unlock (adec->com_init_lock);
464 }
465
466 static void
467 gst_dshowaudiodec_dispose (GObject * object)
468 {
469   GstDshowAudioDec *adec = (GstDshowAudioDec *) (object);
470
471   if (adec->segment) {
472     gst_segment_free (adec->segment);
473     adec->segment = NULL;
474   }
475
476   if (adec->codec_data) {
477     gst_buffer_unref (adec->codec_data);
478     adec->codec_data = NULL;
479   }
480
481   /* signal the COM thread that it sould uninitialize COM */
482   if (adec->comInitialized) {
483     g_mutex_lock (adec->com_deinit_lock);
484     g_cond_signal (adec->com_uninitialize);
485     g_cond_wait (adec->com_uninitialized, adec->com_deinit_lock);
486     g_mutex_unlock (adec->com_deinit_lock);
487   }
488
489   g_mutex_free (adec->com_init_lock);
490   g_mutex_free (adec->com_deinit_lock);
491   g_cond_free (adec->com_initialized);
492   g_cond_free (adec->com_uninitialize);
493   g_cond_free (adec->com_uninitialized);
494
495   G_OBJECT_CLASS (parent_class)->dispose (object);
496 }
497
498
499 static GstStateChangeReturn
500 gst_dshowaudiodec_change_state (GstElement * element, GstStateChange transition)
501 {
502   GstDshowAudioDec *adec = (GstDshowAudioDec *) (element);
503
504   switch (transition) {
505     case GST_STATE_CHANGE_NULL_TO_READY:
506       if (!gst_dshowaudiodec_create_graph_and_filters (adec))
507         return GST_STATE_CHANGE_FAILURE;
508       break;
509     case GST_STATE_CHANGE_READY_TO_PAUSED:
510       break;
511     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
512       break;
513     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
514       break;
515     case GST_STATE_CHANGE_PAUSED_TO_READY:
516       adec->depth = 0;
517       adec->bitrate = 0;
518       adec->block_align = 0;
519       adec->channels = 0;
520       adec->rate = 0;
521       adec->layer = 0;
522       if (adec->codec_data) {
523         gst_buffer_unref (adec->codec_data);
524         adec->codec_data = NULL;
525       }
526       break;
527     case GST_STATE_CHANGE_READY_TO_NULL:
528       if (!gst_dshowaudiodec_destroy_graph_and_filters (adec))
529         return GST_STATE_CHANGE_FAILURE;
530       break;
531     default:
532       break;
533   }
534
535   return GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
536 }
537
538 static gboolean
539 gst_dshowaudiodec_sink_setcaps (GstPad * pad, GstCaps * caps)
540 {
541   gboolean ret = FALSE;
542   GstDshowAudioDec *adec = (GstDshowAudioDec *) gst_pad_get_parent (pad);
543   GstStructure *s = gst_caps_get_structure (caps, 0);
544   const GValue *v = NULL;
545
546   adec->timestamp = GST_CLOCK_TIME_NONE;
547
548   /* read data, only rate and channels are needed */
549   if (!gst_structure_get_int (s, "rate", &adec->rate) ||
550       !gst_structure_get_int (s, "channels", &adec->channels)) {
551     GST_ELEMENT_ERROR (adec, CORE, NEGOTIATION,
552         ("error getting audio specs from caps"), (NULL));
553     goto end;
554   }
555
556   gst_structure_get_int (s, "depth", &adec->depth);
557   gst_structure_get_int (s, "bitrate", &adec->bitrate);
558   gst_structure_get_int (s, "block_align", &adec->block_align);
559   gst_structure_get_int (s, "layer", &adec->layer);
560
561   if (adec->codec_data) {
562     gst_buffer_unref (adec->codec_data);
563     adec->codec_data = NULL;
564   }
565
566   if ((v = gst_structure_get_value (s, "codec_data")))
567     adec->codec_data = gst_buffer_ref (gst_value_get_buffer (v));
568
569   ret = gst_dshowaudiodec_setup_graph (adec, caps);
570 end:
571   gst_object_unref (adec);
572
573   return ret;
574 }
575
576 static GstFlowReturn
577 gst_dshowaudiodec_chain (GstPad * pad, GstBuffer * buffer)
578 {
579   GstDshowAudioDec *adec = (GstDshowAudioDec *) gst_pad_get_parent (pad);
580   bool discont = FALSE;
581
582   if (!adec->setup) {
583     /* we are not set up */
584     GST_WARNING_OBJECT (adec, "Decoder not set up, failing");
585     adec->last_ret = GST_FLOW_WRONG_STATE;
586     goto beach;
587   }
588
589   if (adec->last_ret < GST_FLOW_UNEXPECTED) {
590     GST_DEBUG_OBJECT (adec, "last decoding iteration generated a fatal error "
591         "%s", gst_flow_get_name (adec->last_ret));
592     goto beach;
593   }
594
595   GST_CAT_DEBUG_OBJECT (dshowaudiodec_debug, adec, "chain (size %d)=> pts %"
596       GST_TIME_FORMAT " stop %" GST_TIME_FORMAT,
597       GST_BUFFER_SIZE (buffer), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)),
598       GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer) +
599           GST_BUFFER_DURATION (buffer)));
600
601   /* if the incoming buffer has discont flag set => flush decoder data */
602   if (buffer && GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT)) {
603     GST_CAT_DEBUG_OBJECT (dshowaudiodec_debug, adec,
604         "this buffer has a DISCONT flag (%" GST_TIME_FORMAT "), flushing",
605         GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)));
606     gst_dshowaudiodec_flush (adec);
607     discont = TRUE;
608   }
609
610   /* push the buffer to the directshow decoder */
611   adec->fakesrc->GetOutputPin()->PushBuffer (
612       GST_BUFFER_DATA (buffer), GST_BUFFER_TIMESTAMP (buffer),
613       GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer),
614       GST_BUFFER_SIZE (buffer), (bool)discont);
615
616 beach:
617   gst_buffer_unref (buffer);
618   gst_object_unref (adec);
619   return adec->last_ret;
620 }
621
622 static gboolean
623 gst_dshowaudiodec_sink_event (GstPad * pad, GstEvent * event)
624 {
625   gboolean ret = TRUE;
626   GstDshowAudioDec *adec = (GstDshowAudioDec *) gst_pad_get_parent (pad);
627
628   switch (GST_EVENT_TYPE (event)) {
629     case GST_EVENT_FLUSH_STOP:{
630       gst_dshowaudiodec_flush (adec);
631       ret = gst_pad_event_default (pad, event);
632       break;
633     }
634     case GST_EVENT_NEWSEGMENT:
635     {
636       GstFormat format;
637       gdouble rate;
638       gint64 start, stop, time;
639       gboolean update;
640
641       gst_event_parse_new_segment (event, &update, &rate, &format, &start,
642           &stop, &time);
643
644       GST_CAT_DEBUG_OBJECT (dshowaudiodec_debug, adec,
645           "received new segment from %" GST_TIME_FORMAT " to %" GST_TIME_FORMAT,
646           GST_TIME_ARGS (start), GST_TIME_ARGS (stop));
647
648       if (update) {
649         GST_CAT_DEBUG_OBJECT (dshowaudiodec_debug, adec,
650             "closing current segment flushing..");
651         gst_dshowaudiodec_flush (adec);
652       }
653
654       /* save the new segment in our local current segment */
655       gst_segment_set_newsegment (adec->segment, update, rate, format, start,
656           stop, time);
657
658       ret = gst_pad_event_default (pad, event);
659       break;
660     }
661     default:
662       ret = gst_pad_event_default (pad, event);
663       break;
664   }
665
666   gst_object_unref (adec);
667
668   return ret;
669 }
670
671 static gboolean
672 gst_dshowaudiodec_flush (GstDshowAudioDec * adec)
673 {
674   if (!adec->fakesrc)
675     return FALSE;
676
677   /* flush dshow decoder and reset timestamp */
678   adec->fakesrc->GetOutputPin()->Flush();
679
680   adec->timestamp = GST_CLOCK_TIME_NONE;
681   adec->last_ret = GST_FLOW_OK;
682
683   return TRUE;
684 }
685
686 static AM_MEDIA_TYPE *
687 dshowaudiodec_set_input_format (GstDshowAudioDec *adec, GstCaps *caps)
688 {
689   AM_MEDIA_TYPE *mediatype;
690   WAVEFORMATEX *format;
691   GstDshowAudioDecClass *klass =
692       (GstDshowAudioDecClass *) G_OBJECT_GET_CLASS (adec);
693   const AudioCodecEntry *codec_entry = klass->entry;
694   int size;
695
696   mediatype = (AM_MEDIA_TYPE *)g_malloc0 (sizeof(AM_MEDIA_TYPE));
697   mediatype->majortype = MEDIATYPE_Audio;
698   GUID subtype = GUID_MEDIASUBTYPE_FROM_FOURCC (0x00000000);
699   subtype.Data1 = codec_entry->format;
700   mediatype->subtype = subtype;
701   mediatype->bFixedSizeSamples = TRUE;
702   mediatype->bTemporalCompression = FALSE;
703   if (adec->block_align)
704     mediatype->lSampleSize = adec->block_align;
705   else
706     mediatype->lSampleSize = 8192; /* need to evaluate it dynamically */
707   mediatype->formattype = FORMAT_WaveFormatEx;
708
709   /* We need this special behaviour for layers 1 and 2 (layer 3 uses a different
710    * decoder which doesn't need this */
711   if (adec->layer == 1 || adec->layer == 2) {
712     MPEG1WAVEFORMAT *mpeg1_format;
713     int samples, version;
714     GstStructure *structure = gst_caps_get_structure (caps, 0);
715
716     size = sizeof (MPEG1WAVEFORMAT);
717     format = (WAVEFORMATEX *)g_malloc0 (size);
718     format->cbSize = sizeof (MPEG1WAVEFORMAT) - sizeof (WAVEFORMATEX);
719     format->wFormatTag = WAVE_FORMAT_MPEG;
720
721     mpeg1_format = (MPEG1WAVEFORMAT *) format;
722
723     mpeg1_format->wfx.nChannels = adec->channels;
724     if (adec->channels == 2)
725       mpeg1_format->fwHeadMode = ACM_MPEG_STEREO;
726     else
727       mpeg1_format->fwHeadMode = ACM_MPEG_SINGLECHANNEL;
728     
729     mpeg1_format->fwHeadModeExt = 0;
730     mpeg1_format->wHeadEmphasis = 0;
731     mpeg1_format->fwHeadFlags = 0;
732
733     switch (adec->layer) {
734       case 1:
735         mpeg1_format->fwHeadLayer = ACM_MPEG_LAYER3;
736         break;
737       case 2:
738         mpeg1_format->fwHeadLayer = ACM_MPEG_LAYER2;
739         break;
740       case 3:
741         mpeg1_format->fwHeadLayer = ACM_MPEG_LAYER1;
742         break;
743     };
744
745     gst_structure_get_int (structure, "mpegaudioversion", &version);
746     if (adec->layer == 1) {
747       samples = 384;
748     } else {
749       if (version == 1) {
750         samples = 576;
751       } else {
752         samples = 1152;
753       }
754     }
755     mpeg1_format->wfx.nBlockAlign = (WORD) samples;
756     mpeg1_format->wfx.nSamplesPerSec = adec->rate;
757     mpeg1_format->dwHeadBitrate = 128000; /* This doesn't seem to matter */
758     mpeg1_format->wfx.nAvgBytesPerSec = mpeg1_format->dwHeadBitrate / 8;
759   } 
760   else 
761   {
762     size = sizeof (WAVEFORMATEX) +
763         (adec->codec_data ? GST_BUFFER_SIZE (adec->codec_data) : 0);
764
765     if (adec->layer == 3) {
766       MPEGLAYER3WAVEFORMAT *mp3format;
767
768       /* The WinXP mp3 decoder doesn't actually check the size of this structure, 
769        * but requires that this be allocated and filled out (or we get obscure
770        * random crashes)
771        */
772       size = sizeof (MPEGLAYER3WAVEFORMAT);
773       mp3format = (MPEGLAYER3WAVEFORMAT *)g_malloc0 (size);
774       format = (WAVEFORMATEX *)mp3format;
775       format->cbSize = MPEGLAYER3_WFX_EXTRA_BYTES;
776
777       mp3format->wID = MPEGLAYER3_ID_MPEG;
778       mp3format->fdwFlags = MPEGLAYER3_FLAG_PADDING_ISO; /* No idea what this means for a decoder */
779
780       /* The XP decoder divides by nBlockSize, so we must set this to a
781          non-zero value, but it doesn't matter what - this is meaningless
782          for VBR mp3 anyway */
783       mp3format->nBlockSize = 1;
784       mp3format->nFramesPerBlock = 1;
785       mp3format->nCodecDelay = 0;
786     }
787     else {
788       format = (WAVEFORMATEX *)g_malloc0 (size);
789       if (adec->codec_data) {     /* Codec data is appended after our header */
790         memcpy (((guchar *) format) + sizeof (WAVEFORMATEX),
791             GST_BUFFER_DATA (adec->codec_data),
792             GST_BUFFER_SIZE (adec->codec_data));
793         format->cbSize = GST_BUFFER_SIZE (adec->codec_data);
794       }
795     }
796
797     format->wFormatTag = codec_entry->format;
798     format->nChannels = adec->channels;
799     format->nSamplesPerSec = adec->rate;
800     format->nAvgBytesPerSec = adec->bitrate / 8;
801     format->nBlockAlign = adec->block_align;
802     format->wBitsPerSample = adec->depth;
803   }
804
805   mediatype->cbFormat = size;
806   mediatype->pbFormat = (BYTE *) format;
807
808   return mediatype;
809 }
810
811 static AM_MEDIA_TYPE *
812 dshowaudiodec_set_output_format (GstDshowAudioDec *adec)
813 {
814   AM_MEDIA_TYPE *mediatype;
815   WAVEFORMATEX *format;
816   GstDshowAudioDecClass *klass =
817       (GstDshowAudioDecClass *) G_OBJECT_GET_CLASS (adec);
818   const AudioCodecEntry *codec_entry = klass->entry;
819
820   if (!gst_dshowaudiodec_get_filter_settings (adec)) {
821     return NULL;
822   }
823
824   format = (WAVEFORMATEX *)g_malloc0(sizeof (WAVEFORMATEX));
825   format->wFormatTag = WAVE_FORMAT_PCM;
826   format->wBitsPerSample = adec->depth;
827   format->nChannels = adec->channels;
828   format->nBlockAlign = adec->channels * (adec->depth / 8);
829   format->nSamplesPerSec = adec->rate;
830   format->nAvgBytesPerSec = format->nBlockAlign * adec->rate;
831
832   mediatype = (AM_MEDIA_TYPE *)g_malloc0(sizeof (AM_MEDIA_TYPE));
833   mediatype->majortype = MEDIATYPE_Audio;
834   GUID subtype = GUID_MEDIASUBTYPE_FROM_FOURCC (WAVE_FORMAT_PCM);
835   mediatype->subtype = subtype;
836   mediatype->bFixedSizeSamples = TRUE;
837   mediatype->bTemporalCompression = FALSE;
838   mediatype->lSampleSize = format->nBlockAlign;
839   mediatype->formattype = FORMAT_WaveFormatEx;
840   mediatype->cbFormat = sizeof (WAVEFORMATEX);
841   mediatype->pbFormat = (BYTE *)format;
842   
843   return mediatype;
844 }
845
846 static void
847 dshowadec_free_mediatype (AM_MEDIA_TYPE *mediatype)
848 {
849   if (mediatype->pbFormat)
850     g_free (mediatype->pbFormat);
851   g_free (mediatype);
852 }
853
854 static gboolean
855 gst_dshowaudiodec_setup_graph (GstDshowAudioDec * adec, GstCaps *caps)
856 {
857   gboolean ret = FALSE;
858   GstDshowAudioDecClass *klass =
859       (GstDshowAudioDecClass *) G_OBJECT_GET_CLASS (adec);
860   HRESULT hres;
861   GstCaps *outcaps;
862   AM_MEDIA_TYPE *output_mediatype = NULL;
863   AM_MEDIA_TYPE *input_mediatype = NULL;
864   CComPtr<IPin> output_pin;
865   CComPtr<IPin> input_pin;
866   const AudioCodecEntry *codec_entry = klass->entry;
867   CComQIPtr<IBaseFilter> srcfilter;
868   CComQIPtr<IBaseFilter> sinkfilter;
869
870   input_mediatype = dshowaudiodec_set_input_format (adec, caps);
871
872   adec->fakesrc->GetOutputPin()->SetMediaType (input_mediatype);
873
874   srcfilter = adec->fakesrc;
875
876   /* connect our fake source to decoder */
877   output_pin = gst_dshow_get_pin_from_filter (srcfilter, PINDIR_OUTPUT);
878   if (!output_pin) {
879     GST_ELEMENT_ERROR (adec, CORE, NEGOTIATION,
880         ("Can't get output pin from our directshow fakesrc filter"), (NULL));
881     goto end;
882   }
883   input_pin = gst_dshow_get_pin_from_filter (adec->decfilter, PINDIR_INPUT);
884   if (!input_pin) {
885     GST_ELEMENT_ERROR (adec, CORE, NEGOTIATION,
886         ("Can't get input pin from decoder filter"), (NULL));
887     goto end;
888   }
889
890   hres = adec->filtergraph->ConnectDirect (output_pin, input_pin,
891       NULL);
892   if (hres != S_OK) {
893     GST_ELEMENT_ERROR (adec, CORE, NEGOTIATION,
894         ("Can't connect fakesrc with decoder (error=%x)", hres), (NULL));
895     goto end;
896   }
897
898   output_mediatype = dshowaudiodec_set_output_format (adec);
899   if (!output_mediatype) {
900     GST_ELEMENT_ERROR (adec, CORE, NEGOTIATION,
901         ("Can't get audio output format from decoder"), (NULL));
902     goto end;
903   }
904
905   adec->fakesink->SetMediaType(output_mediatype);
906
907   outcaps = gst_caps_new_simple ("audio/x-raw-int",
908       "width", G_TYPE_INT, adec->depth,
909       "depth", G_TYPE_INT, adec->depth,
910       "rate", G_TYPE_INT, adec->rate,
911       "channels", G_TYPE_INT, adec->channels, 
912       "signed", G_TYPE_BOOLEAN, TRUE,
913       "endianness", G_TYPE_INT, G_LITTLE_ENDIAN,
914       NULL);
915
916   if (!gst_pad_set_caps (adec->srcpad, outcaps)) {
917     gst_caps_unref (outcaps);
918     GST_ELEMENT_ERROR (adec, CORE, NEGOTIATION,
919         ("Failed to negotiate output"), (NULL));
920     goto end;
921   }
922   gst_caps_unref (outcaps);
923
924   /* connect the decoder to our fake sink */
925   output_pin = gst_dshow_get_pin_from_filter (adec->decfilter, PINDIR_OUTPUT);
926   if (!output_pin) {
927     GST_ELEMENT_ERROR (adec, CORE, NEGOTIATION,
928         ("Can't get output pin from our decoder filter"), (NULL));
929     goto end;
930   }
931
932   sinkfilter = adec->fakesink;
933   input_pin = gst_dshow_get_pin_from_filter (sinkfilter, PINDIR_INPUT);
934   if (!input_pin) {
935     GST_ELEMENT_ERROR (adec, CORE, NEGOTIATION,
936         ("Can't get input pin from our directshow fakesink filter"), (NULL));
937     goto end;
938   }
939
940   hres = adec->filtergraph->ConnectDirect(output_pin, input_pin, NULL);
941   if (hres != S_OK) {
942     GST_ELEMENT_ERROR (adec, CORE, NEGOTIATION,
943         ("Can't connect decoder with fakesink (error=%x)", hres), (NULL));
944     goto end;
945   }
946
947   hres = adec->mediafilter->Run (-1);
948   if (hres != S_OK) {
949     GST_ELEMENT_ERROR (adec, CORE, NEGOTIATION,
950         ("Can't run the directshow graph (error=%x)", hres), (NULL));
951     goto end;
952   }
953
954   ret = TRUE;
955   adec->setup = TRUE;
956 end:
957   if (input_mediatype)
958     dshowadec_free_mediatype (input_mediatype);
959   if (output_mediatype)
960     dshowadec_free_mediatype (output_mediatype);
961
962   return ret;
963 }
964
965 static gboolean
966 gst_dshowaudiodec_get_filter_settings (GstDshowAudioDec * adec)
967 {
968   CComPtr<IPin> output_pin;
969   CComPtr<IEnumMediaTypes> enum_mediatypes;
970   HRESULT hres;
971   ULONG fetched;
972   BOOL ret = FALSE;
973
974   if (adec->decfilter == 0)
975     return FALSE;
976
977   output_pin = gst_dshow_get_pin_from_filter (adec->decfilter, PINDIR_OUTPUT);
978   if (!output_pin) {
979     GST_ELEMENT_ERROR (adec, CORE, NEGOTIATION,
980         ("failed getting ouput pin from the decoder"), (NULL));
981     return FALSE;
982   }
983
984   hres = output_pin->EnumMediaTypes (&enum_mediatypes);
985   if (hres == S_OK && enum_mediatypes) {
986     AM_MEDIA_TYPE *mediatype = NULL;
987
988     enum_mediatypes->Reset();
989     while (!ret && enum_mediatypes->Next(1, &mediatype, &fetched) == S_OK) 
990     {
991       if (IsEqualGUID (mediatype->subtype, MEDIASUBTYPE_PCM) &&
992           IsEqualGUID (mediatype->formattype, FORMAT_WaveFormatEx))
993       {
994         WAVEFORMATEX *audio_info = (WAVEFORMATEX *) mediatype->pbFormat;
995
996         adec->channels = audio_info->nChannels;
997         adec->depth = audio_info->wBitsPerSample;
998         adec->rate = audio_info->nSamplesPerSec;
999         ret = TRUE;
1000       }
1001       DeleteMediaType (mediatype);
1002     }
1003   }
1004
1005   return ret;
1006 }
1007
1008 static gboolean
1009 gst_dshowaudiodec_create_graph_and_filters (GstDshowAudioDec * adec)
1010 {
1011   HRESULT hres;
1012   GstDshowAudioDecClass *klass =
1013       (GstDshowAudioDecClass *) G_OBJECT_GET_CLASS (adec);
1014   CComQIPtr<IBaseFilter> srcfilter;
1015   CComQIPtr<IBaseFilter> sinkfilter;
1016   GUID insubtype = GUID_MEDIASUBTYPE_FROM_FOURCC (klass->entry->format);
1017   GUID outsubtype = GUID_MEDIASUBTYPE_FROM_FOURCC (WAVE_FORMAT_PCM);
1018
1019   /* create the filter graph manager object */
1020   hres = adec->filtergraph.CoCreateInstance (
1021       CLSID_FilterGraph, NULL, CLSCTX_INPROC);
1022   if (FAILED (hres)) {
1023     GST_ELEMENT_ERROR (adec, STREAM, FAILED,
1024         ("Can't create an instance of the directshow graph manager (error=%d)",
1025             hres), (NULL));
1026     goto error;
1027   }
1028
1029   hres = adec->filtergraph->QueryInterface (&adec->mediafilter);
1030   if (FAILED (hres)) {
1031     GST_WARNING_OBJECT (adec, "Can't QI filtergraph to mediafilter");
1032     goto error;
1033   }
1034
1035   /* create fake src filter */
1036   adec->fakesrc = new FakeSrc();
1037   /* Created with a refcount of zero, so increment that */
1038   adec->fakesrc->AddRef();
1039
1040   /* create decoder filter */
1041   adec->decfilter = gst_dshow_find_filter (MEDIATYPE_Audio,
1042           insubtype,
1043           MEDIATYPE_Audio,
1044           outsubtype,
1045           klass->entry->preferred_filters);
1046   if (adec->decfilter == NULL) {
1047     GST_ELEMENT_ERROR (adec, STREAM, FAILED,
1048         ("Can't create an instance of the decoder filter"), (NULL));
1049     goto error;
1050   }
1051
1052   /* create fake sink filter */
1053   adec->fakesink = new AudioFakeSink(adec);
1054   /* Created with a refcount of zero, so increment that */
1055   adec->fakesink->AddRef();
1056
1057   /* add filters to the graph */
1058   srcfilter = adec->fakesrc;
1059   hres = adec->filtergraph->AddFilter (srcfilter, L"src");
1060   if (hres != S_OK) {
1061     GST_ELEMENT_ERROR (adec, STREAM, FAILED,
1062         ("Can't add fakesrc filter to the graph (error=%d)", hres), (NULL));
1063     goto error;
1064   }
1065
1066   hres = adec->filtergraph->AddFilter(adec->decfilter, L"decoder");
1067   if (hres != S_OK) {
1068     GST_ELEMENT_ERROR (adec, STREAM, FAILED,
1069         ("Can't add decoder filter to the graph (error=%d)", hres), (NULL));
1070     goto error;
1071   }
1072
1073   sinkfilter = adec->fakesink;
1074   hres = adec->filtergraph->AddFilter(sinkfilter, L"sink");
1075   if (hres != S_OK) {
1076     GST_ELEMENT_ERROR (adec, STREAM, FAILED,
1077         ("Can't add fakesink filter to the graph (error=%d)", hres), (NULL));
1078     goto error;
1079   }
1080
1081   return TRUE;
1082
1083 error:
1084   if (adec->fakesrc) {
1085     adec->fakesrc->Release();
1086     adec->fakesrc = NULL;
1087   }
1088   if (adec->fakesink) {
1089     adec->fakesink->Release();
1090     adec->fakesink = NULL;
1091   }
1092   adec->decfilter = 0;
1093   adec->mediafilter = 0;
1094   adec->filtergraph = 0;
1095
1096   return FALSE;
1097 }
1098
1099 static gboolean
1100 gst_dshowaudiodec_destroy_graph_and_filters (GstDshowAudioDec * adec)
1101 {
1102   if (adec->mediafilter) {
1103     adec->mediafilter->Stop();
1104   }
1105
1106   if (adec->fakesrc) {
1107     if (adec->filtergraph) {
1108       CComQIPtr<IBaseFilter> filter = adec->fakesrc;
1109       adec->filtergraph->RemoveFilter(filter);
1110     }
1111     adec->fakesrc->Release();
1112     adec->fakesrc = NULL;
1113   }
1114   if (adec->decfilter) {
1115     if (adec->filtergraph)
1116       adec->filtergraph->RemoveFilter(adec->decfilter);
1117     adec->decfilter = 0;
1118   }
1119   if (adec->fakesink) {
1120     if (adec->filtergraph) {
1121       CComQIPtr<IBaseFilter> filter = adec->fakesink;
1122       adec->filtergraph->RemoveFilter(filter);
1123     }
1124
1125     adec->fakesink->Release();
1126     adec->fakesink = NULL;
1127   }
1128   adec->mediafilter = 0;
1129   adec->filtergraph = 0;
1130
1131   adec->setup = FALSE;
1132
1133   return TRUE;
1134 }
1135
1136 gboolean
1137 dshow_adec_register (GstPlugin * plugin)
1138 {
1139   GTypeInfo info = {
1140     sizeof (GstDshowAudioDecClass),
1141     (GBaseInitFunc) gst_dshowaudiodec_base_init,
1142     NULL,
1143     (GClassInitFunc) gst_dshowaudiodec_class_init,
1144     NULL,
1145     NULL,
1146     sizeof (GstDshowAudioDec),
1147     0,
1148     (GInstanceInitFunc) gst_dshowaudiodec_init,
1149   };
1150   gint i;
1151   HRESULT hr;
1152
1153   GST_DEBUG_CATEGORY_INIT (dshowaudiodec_debug, "dshowaudiodec", 0,
1154       "Directshow filter audio decoder");
1155
1156   hr = CoInitialize(0);
1157   for (i = 0; i < sizeof (audio_dec_codecs) / sizeof (AudioCodecEntry); i++) {
1158     GType type;
1159     CComPtr<IBaseFilter> filter;
1160     GUID insubtype = GUID_MEDIASUBTYPE_FROM_FOURCC (audio_dec_codecs[i].format);
1161     GUID outsubtype = GUID_MEDIASUBTYPE_FROM_FOURCC (WAVE_FORMAT_PCM);
1162
1163     filter = gst_dshow_find_filter (MEDIATYPE_Audio,
1164             insubtype,
1165             MEDIATYPE_Audio,
1166             outsubtype,
1167             audio_dec_codecs[i].preferred_filters);
1168
1169     if (filter) 
1170     {
1171       GST_DEBUG ("Registering %s", audio_dec_codecs[i].element_name);
1172
1173       type = g_type_register_static (GST_TYPE_ELEMENT,
1174           audio_dec_codecs[i].element_name, &info, (GTypeFlags)0);
1175       g_type_set_qdata (type, DSHOW_CODEC_QDATA, (gpointer) (audio_dec_codecs + i));
1176       if (!gst_element_register (plugin, audio_dec_codecs[i].element_name,
1177               GST_RANK_SECONDARY, type)) {
1178         return FALSE;
1179       }
1180       GST_CAT_DEBUG (dshowaudiodec_debug, "Registered %s",
1181           audio_dec_codecs[i].element_name);
1182     }
1183     else {
1184       GST_DEBUG ("Element %s not registered "
1185                  "(the format is not supported by the system)",
1186                  audio_dec_codecs[i].element_name);
1187     }
1188   }
1189
1190   if (SUCCEEDED(hr))
1191     CoUninitialize ();
1192
1193   return TRUE;
1194 }