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>
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:
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
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.
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
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.
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.
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.
50 #include "gstdshowaudiodec.h"
53 #include <wmcodecdsp.h>
55 GST_DEBUG_CATEGORY_STATIC (dshowaudiodec_debug);
56 #define GST_CAT_DEFAULT dshowaudiodec_debug
58 GST_BOILERPLATE (GstDshowAudioDec, gst_dshowaudiodec, GstElement,
61 static void gst_dshowaudiodec_dispose (GObject * object);
62 static GstStateChangeReturn gst_dshowaudiodec_change_state
63 (GstElement * element, GstStateChange transition);
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);
71 static gboolean gst_dshowaudiodec_create_graph_and_filters (GstDshowAudioDec *
73 static gboolean gst_dshowaudiodec_destroy_graph_and_filters (GstDshowAudioDec *
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);
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 }}
84 /* WMA we should always use the DMO */
85 static PreferredFilter preferred_wma_filters[] = {
86 {&CLSID_CWMADecMediaObject, &DMOCATEGORY_AUDIO_DECODER},
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},
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},
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},
115 {"dshowadec_wma2", "Windows Media Audio 8",
116 WAVE_FORMAT_WMAUDIO2,
117 "audio/x-wma, wmaversion = (int) 2",
118 preferred_wma_filters},
120 {"dshowadec_wma3", "Windows Media Audio 9 Professional",
121 WAVE_FORMAT_WMAUDIO3,
122 "audio/x-wma, wmaversion = (int) 3",
123 preferred_wma_filters},
125 {"dshowadec_wma4", "Windows Media Audio 9 Lossless",
126 WAVE_FORMAT_WMAUDIO_LOSSLESS,
127 "audio/x-wma, wmaversion = (int) 4",
128 preferred_wma_filters},
130 {"dshowadec_wms", "Windows Media Audio Voice v9",
131 WAVE_FORMAT_WMAVOICE9,
133 preferred_wma_filters},
135 {"dshowadec_mp3", "MPEG Layer 3 Audio",
136 WAVE_FORMAT_MPEGLAYER3,
138 "mpegversion = (int) 1, "
140 "rate = (int) [ 8000, 48000 ], "
141 "channels = (int) [ 1, 2 ], "
142 "parsed= (boolean) true",
143 preferred_mp3_filters},
145 {"dshowadec_mpeg_1_2", "MPEG Layer 1,2 Audio",
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},
156 HRESULT AudioFakeSink::DoRenderSample(IMediaSample *pMediaSample)
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;
167 BYTE *pBuffer = NULL;
168 LONGLONG lStart = 0, lStop = 0;
169 long size = pMediaSample->GetActualDataLength();
171 pMediaSample->GetPointer(&pBuffer);
172 pMediaSample->GetTime(&lStart, &lStop);
174 if (!GST_CLOCK_TIME_IS_VALID (mDec->timestamp)) {
175 // Convert REFERENCE_TIME to GST_CLOCK_TIME
176 mDec->timestamp = (GstClockTime)lStart * 100;
178 duration = (lStop - lStart) * 100;
180 buf_start = mDec->timestamp;
181 buf_stop = mDec->timestamp + duration;
183 /* save stop position to start next buffer with it */
184 mDec->timestamp = buf_stop;
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);
190 /* if the buffer is out of segment do not push it downstream */
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));
198 /* buffer is entirely or partially in-segment, so allocate a
199 * GstBuffer for output, and clip if required */
201 /* allocate a new buffer for raw audio */
202 mDec->last_ret = gst_pad_alloc_buffer (mDec->srcpad,
203 GST_BUFFER_OFFSET_NONE,
205 GST_PAD_CAPS (mDec->srcpad), &out_buf);
207 GST_WARNING_OBJECT (mDec, "cannot allocate a new GstBuffer");
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)));
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;
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;
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);
238 gst_buffer_set_caps (subbuf, GST_PAD_CAPS (mDec->srcpad));
239 gst_buffer_unref (out_buf);
244 GST_BUFFER_TIMESTAMP (out_buf) = clip_start;
245 GST_BUFFER_DURATION (out_buf) = clip_stop - clip_start;
247 /* replace the saved stop position by the clipped one */
248 mDec->timestamp = clip_stop;
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)));
258 mDec->last_ret = gst_pad_push (mDec->srcpad, out_buf);
265 HRESULT AudioFakeSink::CheckMediaType(const CMediaType *pmt)
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.
274 if (IsEqualGUID (pmt->majortype, m_MediaType.majortype) &&
275 IsEqualGUID (pmt->subtype, m_MediaType.subtype) &&
276 IsEqualGUID (pmt->formattype, m_MediaType.formattype))
278 /* Types are the same at the top-level. Now, we need to compare
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.
284 if (pmt->formattype == FORMAT_WaveFormatEx) {
285 if (pmt->cbFormat >= sizeof (WAVEFORMATEX) &&
286 m_MediaType.cbFormat >= sizeof (WAVEFORMATEX))
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)
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))
309 gst_dshowaudiodec_base_init (gpointer klass)
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;
319 qdata = g_type_get_qdata (G_OBJECT_CLASS_TYPE (klass), DSHOW_CODEC_QDATA);
321 /* element details */
322 tmp = audiodec_class->entry = (AudioCodecEntry *) qdata;
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);
335 sinkcaps = gst_caps_from_string (tmp->sinkcaps);
337 srccaps = gst_caps_from_string (
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));
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);
350 gst_element_class_add_pad_template (element_class, src);
351 gst_element_class_add_pad_template (element_class, sink);
353 gst_object_unref (src);
354 gst_object_unref (sink);
358 gst_dshowaudiodec_class_init (GstDshowAudioDecClass * klass)
360 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
361 GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
363 gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_dshowaudiodec_dispose);
365 gstelement_class->change_state =
366 GST_DEBUG_FUNCPTR (gst_dshowaudiodec_change_state);
368 parent_class = (GstElementClass *) g_type_class_peek_parent (klass);
372 gst_dshowaudiodec_com_thread (GstDshowAudioDec * adec)
376 g_mutex_lock (adec->com_init_lock);
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 */
382 res = CoInitializeEx (0, COINIT_MULTITHREADED);
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.");
388 GST_INFO_OBJECT (adec, "COM intialized succesfully");
390 adec->comInitialized = TRUE;
392 /* Signal other threads waiting on this condition that COM was initialized */
393 g_cond_signal (adec->com_initialized);
395 g_mutex_unlock (adec->com_init_lock);
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);
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);
409 gst_dshowaudiodec_init (GstDshowAudioDec * adec,
410 GstDshowAudioDecClass * adec_class)
412 GstElementClass *element_class = GST_ELEMENT_GET_CLASS (adec);
416 gst_pad_new_from_template (gst_element_class_get_pad_template
417 (element_class, "sink"), "sink");
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);
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);
429 adec->fakesrc = NULL;
430 adec->fakesink = NULL;
433 adec->filtergraph = 0;
434 adec->mediafilter = 0;
436 adec->timestamp = GST_CLOCK_TIME_NONE;
437 adec->segment = gst_segment_new ();
441 adec->block_align = 0;
445 adec->codec_data = NULL;
447 adec->last_ret = GST_FLOW_OK;
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();
455 g_mutex_lock (adec->com_init_lock);
457 /* create the COM initialization thread */
458 g_thread_create ((GThreadFunc)gst_dshowaudiodec_com_thread,
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);
467 gst_dshowaudiodec_dispose (GObject * object)
469 GstDshowAudioDec *adec = (GstDshowAudioDec *) (object);
472 gst_segment_free (adec->segment);
473 adec->segment = NULL;
476 if (adec->codec_data) {
477 gst_buffer_unref (adec->codec_data);
478 adec->codec_data = NULL;
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);
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);
495 G_OBJECT_CLASS (parent_class)->dispose (object);
499 static GstStateChangeReturn
500 gst_dshowaudiodec_change_state (GstElement * element, GstStateChange transition)
502 GstDshowAudioDec *adec = (GstDshowAudioDec *) (element);
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;
509 case GST_STATE_CHANGE_READY_TO_PAUSED:
511 case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
513 case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
515 case GST_STATE_CHANGE_PAUSED_TO_READY:
518 adec->block_align = 0;
522 if (adec->codec_data) {
523 gst_buffer_unref (adec->codec_data);
524 adec->codec_data = NULL;
527 case GST_STATE_CHANGE_READY_TO_NULL:
528 if (!gst_dshowaudiodec_destroy_graph_and_filters (adec))
529 return GST_STATE_CHANGE_FAILURE;
535 return GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
539 gst_dshowaudiodec_sink_setcaps (GstPad * pad, GstCaps * caps)
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;
546 adec->timestamp = GST_CLOCK_TIME_NONE;
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));
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);
561 if (adec->codec_data) {
562 gst_buffer_unref (adec->codec_data);
563 adec->codec_data = NULL;
566 if ((v = gst_structure_get_value (s, "codec_data")))
567 adec->codec_data = gst_buffer_ref (gst_value_get_buffer (v));
569 ret = gst_dshowaudiodec_setup_graph (adec, caps);
571 gst_object_unref (adec);
577 gst_dshowaudiodec_chain (GstPad * pad, GstBuffer * buffer)
579 GstDshowAudioDec *adec = (GstDshowAudioDec *) gst_pad_get_parent (pad);
580 bool discont = FALSE;
583 /* we are not set up */
584 GST_WARNING_OBJECT (adec, "Decoder not set up, failing");
585 adec->last_ret = GST_FLOW_WRONG_STATE;
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));
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)));
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);
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);
617 gst_buffer_unref (buffer);
618 gst_object_unref (adec);
619 return adec->last_ret;
623 gst_dshowaudiodec_sink_event (GstPad * pad, GstEvent * event)
626 GstDshowAudioDec *adec = (GstDshowAudioDec *) gst_pad_get_parent (pad);
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);
634 case GST_EVENT_NEWSEGMENT:
638 gint64 start, stop, time;
641 gst_event_parse_new_segment (event, &update, &rate, &format, &start,
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));
649 GST_CAT_DEBUG_OBJECT (dshowaudiodec_debug, adec,
650 "closing current segment flushing..");
651 gst_dshowaudiodec_flush (adec);
654 /* save the new segment in our local current segment */
655 gst_segment_set_newsegment (adec->segment, update, rate, format, start,
658 ret = gst_pad_event_default (pad, event);
662 ret = gst_pad_event_default (pad, event);
666 gst_object_unref (adec);
672 gst_dshowaudiodec_flush (GstDshowAudioDec * adec)
677 /* flush dshow decoder and reset timestamp */
678 adec->fakesrc->GetOutputPin()->Flush();
680 adec->timestamp = GST_CLOCK_TIME_NONE;
681 adec->last_ret = GST_FLOW_OK;
686 static AM_MEDIA_TYPE *
687 dshowaudiodec_set_input_format (GstDshowAudioDec *adec, GstCaps *caps)
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;
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;
706 mediatype->lSampleSize = 8192; /* need to evaluate it dynamically */
707 mediatype->formattype = FORMAT_WaveFormatEx;
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);
716 size = sizeof (MPEG1WAVEFORMAT);
717 format = (WAVEFORMATEX *)g_malloc0 (size);
718 format->cbSize = sizeof (MPEG1WAVEFORMAT) - sizeof (WAVEFORMATEX);
719 format->wFormatTag = WAVE_FORMAT_MPEG;
721 mpeg1_format = (MPEG1WAVEFORMAT *) format;
723 mpeg1_format->wfx.nChannels = adec->channels;
724 if (adec->channels == 2)
725 mpeg1_format->fwHeadMode = ACM_MPEG_STEREO;
727 mpeg1_format->fwHeadMode = ACM_MPEG_SINGLECHANNEL;
729 mpeg1_format->fwHeadModeExt = 0;
730 mpeg1_format->wHeadEmphasis = 0;
731 mpeg1_format->fwHeadFlags = 0;
733 switch (adec->layer) {
735 mpeg1_format->fwHeadLayer = ACM_MPEG_LAYER3;
738 mpeg1_format->fwHeadLayer = ACM_MPEG_LAYER2;
741 mpeg1_format->fwHeadLayer = ACM_MPEG_LAYER1;
745 gst_structure_get_int (structure, "mpegaudioversion", &version);
746 if (adec->layer == 1) {
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;
762 size = sizeof (WAVEFORMATEX) +
763 (adec->codec_data ? GST_BUFFER_SIZE (adec->codec_data) : 0);
765 if (adec->layer == 3) {
766 MPEGLAYER3WAVEFORMAT *mp3format;
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
772 size = sizeof (MPEGLAYER3WAVEFORMAT);
773 mp3format = (MPEGLAYER3WAVEFORMAT *)g_malloc0 (size);
774 format = (WAVEFORMATEX *)mp3format;
775 format->cbSize = MPEGLAYER3_WFX_EXTRA_BYTES;
777 mp3format->wID = MPEGLAYER3_ID_MPEG;
778 mp3format->fdwFlags = MPEGLAYER3_FLAG_PADDING_ISO; /* No idea what this means for a decoder */
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;
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);
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;
805 mediatype->cbFormat = size;
806 mediatype->pbFormat = (BYTE *) format;
811 static AM_MEDIA_TYPE *
812 dshowaudiodec_set_output_format (GstDshowAudioDec *adec)
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;
820 if (!gst_dshowaudiodec_get_filter_settings (adec)) {
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;
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;
847 dshowadec_free_mediatype (AM_MEDIA_TYPE *mediatype)
849 if (mediatype->pbFormat)
850 g_free (mediatype->pbFormat);
855 gst_dshowaudiodec_setup_graph (GstDshowAudioDec * adec, GstCaps *caps)
857 gboolean ret = FALSE;
858 GstDshowAudioDecClass *klass =
859 (GstDshowAudioDecClass *) G_OBJECT_GET_CLASS (adec);
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;
870 input_mediatype = dshowaudiodec_set_input_format (adec, caps);
872 adec->fakesrc->GetOutputPin()->SetMediaType (input_mediatype);
874 srcfilter = adec->fakesrc;
876 /* connect our fake source to decoder */
877 output_pin = gst_dshow_get_pin_from_filter (srcfilter, PINDIR_OUTPUT);
879 GST_ELEMENT_ERROR (adec, CORE, NEGOTIATION,
880 ("Can't get output pin from our directshow fakesrc filter"), (NULL));
883 input_pin = gst_dshow_get_pin_from_filter (adec->decfilter, PINDIR_INPUT);
885 GST_ELEMENT_ERROR (adec, CORE, NEGOTIATION,
886 ("Can't get input pin from decoder filter"), (NULL));
890 hres = adec->filtergraph->ConnectDirect (output_pin, input_pin,
893 GST_ELEMENT_ERROR (adec, CORE, NEGOTIATION,
894 ("Can't connect fakesrc with decoder (error=%x)", hres), (NULL));
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));
905 adec->fakesink->SetMediaType(output_mediatype);
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,
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));
922 gst_caps_unref (outcaps);
924 /* connect the decoder to our fake sink */
925 output_pin = gst_dshow_get_pin_from_filter (adec->decfilter, PINDIR_OUTPUT);
927 GST_ELEMENT_ERROR (adec, CORE, NEGOTIATION,
928 ("Can't get output pin from our decoder filter"), (NULL));
932 sinkfilter = adec->fakesink;
933 input_pin = gst_dshow_get_pin_from_filter (sinkfilter, PINDIR_INPUT);
935 GST_ELEMENT_ERROR (adec, CORE, NEGOTIATION,
936 ("Can't get input pin from our directshow fakesink filter"), (NULL));
940 hres = adec->filtergraph->ConnectDirect(output_pin, input_pin, NULL);
942 GST_ELEMENT_ERROR (adec, CORE, NEGOTIATION,
943 ("Can't connect decoder with fakesink (error=%x)", hres), (NULL));
947 hres = adec->mediafilter->Run (-1);
949 GST_ELEMENT_ERROR (adec, CORE, NEGOTIATION,
950 ("Can't run the directshow graph (error=%x)", hres), (NULL));
958 dshowadec_free_mediatype (input_mediatype);
959 if (output_mediatype)
960 dshowadec_free_mediatype (output_mediatype);
966 gst_dshowaudiodec_get_filter_settings (GstDshowAudioDec * adec)
968 CComPtr<IPin> output_pin;
969 CComPtr<IEnumMediaTypes> enum_mediatypes;
974 if (adec->decfilter == 0)
977 output_pin = gst_dshow_get_pin_from_filter (adec->decfilter, PINDIR_OUTPUT);
979 GST_ELEMENT_ERROR (adec, CORE, NEGOTIATION,
980 ("failed getting ouput pin from the decoder"), (NULL));
984 hres = output_pin->EnumMediaTypes (&enum_mediatypes);
985 if (hres == S_OK && enum_mediatypes) {
986 AM_MEDIA_TYPE *mediatype = NULL;
988 enum_mediatypes->Reset();
989 while (!ret && enum_mediatypes->Next(1, &mediatype, &fetched) == S_OK)
991 if (IsEqualGUID (mediatype->subtype, MEDIASUBTYPE_PCM) &&
992 IsEqualGUID (mediatype->formattype, FORMAT_WaveFormatEx))
994 WAVEFORMATEX *audio_info = (WAVEFORMATEX *) mediatype->pbFormat;
996 adec->channels = audio_info->nChannels;
997 adec->depth = audio_info->wBitsPerSample;
998 adec->rate = audio_info->nSamplesPerSec;
1001 DeleteMediaType (mediatype);
1009 gst_dshowaudiodec_create_graph_and_filters (GstDshowAudioDec * adec)
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);
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)",
1029 hres = adec->filtergraph->QueryInterface (&adec->mediafilter);
1030 if (FAILED (hres)) {
1031 GST_WARNING_OBJECT (adec, "Can't QI filtergraph to mediafilter");
1035 /* create fake src filter */
1036 adec->fakesrc = new FakeSrc();
1037 /* Created with a refcount of zero, so increment that */
1038 adec->fakesrc->AddRef();
1040 /* create decoder filter */
1041 adec->decfilter = gst_dshow_find_filter (MEDIATYPE_Audio,
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));
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();
1057 /* add filters to the graph */
1058 srcfilter = adec->fakesrc;
1059 hres = adec->filtergraph->AddFilter (srcfilter, L"src");
1061 GST_ELEMENT_ERROR (adec, STREAM, FAILED,
1062 ("Can't add fakesrc filter to the graph (error=%d)", hres), (NULL));
1066 hres = adec->filtergraph->AddFilter(adec->decfilter, L"decoder");
1068 GST_ELEMENT_ERROR (adec, STREAM, FAILED,
1069 ("Can't add decoder filter to the graph (error=%d)", hres), (NULL));
1073 sinkfilter = adec->fakesink;
1074 hres = adec->filtergraph->AddFilter(sinkfilter, L"sink");
1076 GST_ELEMENT_ERROR (adec, STREAM, FAILED,
1077 ("Can't add fakesink filter to the graph (error=%d)", hres), (NULL));
1084 if (adec->fakesrc) {
1085 adec->fakesrc->Release();
1086 adec->fakesrc = NULL;
1088 if (adec->fakesink) {
1089 adec->fakesink->Release();
1090 adec->fakesink = NULL;
1092 adec->decfilter = 0;
1093 adec->mediafilter = 0;
1094 adec->filtergraph = 0;
1100 gst_dshowaudiodec_destroy_graph_and_filters (GstDshowAudioDec * adec)
1102 if (adec->mediafilter) {
1103 adec->mediafilter->Stop();
1106 if (adec->fakesrc) {
1107 if (adec->filtergraph) {
1108 CComQIPtr<IBaseFilter> filter = adec->fakesrc;
1109 adec->filtergraph->RemoveFilter(filter);
1111 adec->fakesrc->Release();
1112 adec->fakesrc = NULL;
1114 if (adec->decfilter) {
1115 if (adec->filtergraph)
1116 adec->filtergraph->RemoveFilter(adec->decfilter);
1117 adec->decfilter = 0;
1119 if (adec->fakesink) {
1120 if (adec->filtergraph) {
1121 CComQIPtr<IBaseFilter> filter = adec->fakesink;
1122 adec->filtergraph->RemoveFilter(filter);
1125 adec->fakesink->Release();
1126 adec->fakesink = NULL;
1128 adec->mediafilter = 0;
1129 adec->filtergraph = 0;
1131 adec->setup = FALSE;
1137 dshow_adec_register (GstPlugin * plugin)
1140 sizeof (GstDshowAudioDecClass),
1141 (GBaseInitFunc) gst_dshowaudiodec_base_init,
1143 (GClassInitFunc) gst_dshowaudiodec_class_init,
1146 sizeof (GstDshowAudioDec),
1148 (GInstanceInitFunc) gst_dshowaudiodec_init,
1153 GST_DEBUG_CATEGORY_INIT (dshowaudiodec_debug, "dshowaudiodec", 0,
1154 "Directshow filter audio decoder");
1156 hr = CoInitialize(0);
1157 for (i = 0; i < sizeof (audio_dec_codecs) / sizeof (AudioCodecEntry); i++) {
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);
1163 filter = gst_dshow_find_filter (MEDIATYPE_Audio,
1167 audio_dec_codecs[i].preferred_filters);
1171 GST_DEBUG ("Registering %s", audio_dec_codecs[i].element_name);
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)) {
1180 GST_CAT_DEBUG (dshowaudiodec_debug, "Registered %s",
1181 audio_dec_codecs[i].element_name);
1184 GST_DEBUG ("Element %s not registered "
1185 "(the format is not supported by the system)",
1186 audio_dec_codecs[i].element_name);