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