1 /*****************************************************************************
2 * dmo.c : DirectMedia Object decoder module for vlc
3 *****************************************************************************
4 * Copyright (C) 2002, 2003 VLC authors and VideoLAN
6 * Author: Gildas Bazin <gbazin@videolan.org>
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation; either version 2.1 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21 *****************************************************************************/
23 /*****************************************************************************
25 *****************************************************************************/
33 #include <vlc_common.h>
34 #include <vlc_plugin.h>
35 #include <vlc_codec.h>
36 #include <vlc_codecs.h>
42 #include <vlc_codecs.h>
44 #include "../../video_chroma/copy.h"
50 typedef long (STDCALL
*GETCLASS
) ( const GUID
*, const GUID
*, void** );
52 /*****************************************************************************
54 *****************************************************************************/
55 static int DecoderOpen ( vlc_object_t
* );
56 static void DecoderClose ( vlc_object_t
* );
57 static int DecodeBlock ( decoder_t
*, block_t
* );
58 static void *DecoderThread( void * );
59 static int EncoderOpen ( vlc_object_t
* );
60 static void EncoderClose ( vlc_object_t
* );
61 static block_t
*EncodeBlock( encoder_t
*, void * );
63 static int EncOpen ( vlc_object_t
* );
65 static int LoadDMO( vlc_object_t
*, HINSTANCE
*, IMediaObject
**,
66 es_format_t
*, bool );
67 static void CopyPicture( picture_t
*, uint8_t * );
70 set_description( N_("DirectMedia Object decoder") )
72 set_capability( "video decoder", 1 )
73 set_callbacks( DecoderOpen
, DecoderClose
)
74 set_category( CAT_INPUT
)
75 set_subcategory( SUBCAT_INPUT_VCODEC
)
79 set_capability( "audio decoder", 1 )
80 set_callbacks(DecoderOpen
, DecoderClose
)
83 set_description( N_("DirectMedia Object encoder") )
85 set_capability( "encoder", 10 )
86 set_callbacks( EncoderOpen
, EncoderClose
)
90 /*****************************************************************************
92 *****************************************************************************/
94 /****************************************************************************
95 * Decoder descriptor declaration
96 ****************************************************************************/
109 vlc_cond_t wait_input
, wait_output
;
110 bool b_ready
, b_works
;
114 const GUID IID_IWMCodecPrivateData
= {0x73f0be8e, 0x57f7, 0x4f01, {0xaa, 0x66, 0x9f, 0x57, 0x34, 0xc, 0xfe, 0xe}};
115 const GUID IID_IMediaObject
= {0xd8ad0f58, 0x5494, 0x4102, {0x97, 0xc5, 0xec, 0x79, 0x8e, 0x59, 0xbc, 0xf4}};
116 const GUID IID_IMediaBuffer
= {0x59eff8b9, 0x938c, 0x4a26, {0x82, 0xf2, 0x95, 0xcb, 0x84, 0xcd, 0xc8, 0x37}};
117 const GUID MEDIATYPE_Video
= {0x73646976, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
118 const GUID MEDIATYPE_Audio
= {0x73647561, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
119 const GUID MEDIASUBTYPE_PCM
= {0x00000001, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
120 const GUID MEDIASUBTYPE_IEEE_FLOAT
= {0x00000003, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
121 const GUID FORMAT_VideoInfo
= {0x05589f80, 0xc356, 0x11ce, {0xbf, 0x01, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a}};
122 const GUID FORMAT_WaveFormatEx
= {0x05589f81, 0xc356, 0x11ce, {0xbf, 0x01, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a}};
123 const GUID GUID_NULL
= {0x0000, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
124 const GUID MEDIASUBTYPE_I420
= {0x30323449, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
125 const GUID MEDIASUBTYPE_YV12
= {0x32315659, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
126 const GUID MEDIASUBTYPE_RGB24
= {0xe436eb7d, 0x524f, 0x11ce, {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}};
127 const GUID MEDIASUBTYPE_RGB565
= {0xe436eb7b, 0x524f, 0x11ce, {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}};
130 static const GUID guid_wvc1
= { 0xc9bfbccf, 0xe60e, 0x4588, { 0xa3, 0xdf, 0x5a, 0x03, 0xb1, 0xfd, 0x95, 0x85 } };
131 static const GUID guid_wmv9
= { 0x724bb6a4, 0xe526, 0x450f, { 0xaf, 0xfa, 0xab, 0x9b, 0x45, 0x12, 0x91, 0x11 } };
133 static const GUID guid_wmv
= { 0x82d353df, 0x90bd, 0x4382, { 0x8b, 0xc2, 0x3f, 0x61, 0x92, 0xb7, 0x6e, 0x34 } };
134 static const GUID guid_wms
= { 0x7bafb3b1, 0xd8f4, 0x4279, { 0x92, 0x53, 0x27, 0xda, 0x42, 0x31, 0x08, 0xde } };
135 static const GUID guid_wmva
={ 0x03be3ac4, 0x84b7, 0x4e0e, { 0xa7, 0x8d, 0xd3, 0x52, 0x4e, 0x60, 0x39, 0x5a } };
137 static const GUID guid_wma
= { 0x874131cb, 0x4ecc, 0x443b, { 0x89, 0x48, 0x74, 0x6b, 0x89, 0x59, 0x5d, 0x20 } };
138 static const GUID guid_wma9
= { 0x27ca0808, 0x01f5, 0x4e7a, { 0x8b, 0x05, 0x87, 0xf8, 0x07, 0xa2, 0x33, 0xd1 } };
140 static const GUID guid_wmv_enc2
= { 0x96b57cdd, 0x8966, 0x410c,{ 0xbb, 0x1f, 0xc9, 0x7e, 0xea, 0x76, 0x5c, 0x04 } };
141 static const GUID guid_wma_enc
= { 0x70f598e9, 0xf4ab, 0x495a, { 0x99, 0xe2, 0xa7, 0xc4, 0xd3, 0xd8, 0x9a, 0xbf } };
142 static const GUID guid_wmv8_enc
= { 0x7e320092, 0x596a, 0x41b2,{ 0xbb, 0xeb, 0x17, 0x5d, 0x10, 0x50, 0x4e, 0xb6 } };
143 static const GUID guid_wmv9_enc
= { 0xd23b90d0, 0x144f, 0x46bd,{ 0x84, 0x1d, 0x59, 0xe4, 0xeb, 0x19, 0xdc, 0x59 } };
151 vlc_fourcc_t i_fourcc
;
152 const WCHAR
*psz_dll
;
157 static const codec_dll decoders_table
[] =
160 { VLC_CODEC_VC1
, TEXT("wvc1dmod.dll"), &guid_wvc1
},
162 { VLC_CODEC_WMV3
, TEXT("wmv9dmod.dll"), &guid_wmv9
},
164 { VLC_CODEC_WMV2
, TEXT("wmvdmod.dll"), &guid_wmv
},
166 { VLC_CODEC_WMV1
, TEXT("wmvdmod.dll"), &guid_wmv
},
168 { VLC_CODEC_MSS2
, TEXT("WMVSDECD.DLL"), &guid_wms
},
169 { VLC_CODEC_MSS2
, TEXT("wmsdmod.dll"), &guid_wms
},
170 { VLC_CODEC_MSS1
, TEXT("WMVSDECD.DLL"), &guid_wms
},
171 { VLC_CODEC_MSS1
, TEXT("wmsdmod.dll"), &guid_wms
},
172 /* Windows Media Video Adv */
173 { VLC_CODEC_WMVA
, TEXT("wmvadvd.dll"), &guid_wmva
},
176 { VLC_CODEC_WMAP
, TEXT("wma9dmod.dll"), &guid_wma9
},
177 { VLC_CODEC_WMAL
, TEXT("wma9dmod.dll"), &guid_wma9
},
180 { VLC_CODEC_WMA2
, TEXT("wma9dmod.dll"), &guid_wma9
},
183 { VLC_CODEC_WMAS
, TEXT("wmspdmod.dll"), &guid_wma
},
189 static const codec_dll encoders_table
[] =
192 { VLC_CODEC_WMV3
, TEXT("wmvdmoe2.dll"), &guid_wmv_enc2
},
194 { VLC_CODEC_WMV2
, TEXT("wmvdmoe2.dll"), &guid_wmv_enc2
},
196 { VLC_CODEC_WMV1
, TEXT("wmvdmoe2.dll"), &guid_wmv_enc2
},
199 { VLC_CODEC_WMAP
, TEXT("wmadmoe.dll"), &guid_wma_enc
},
201 { VLC_CODEC_WMA2
, TEXT("wmadmoe.dll"), &guid_wma_enc
},
204 { VLC_CODEC_WMV3
, TEXT("wmvencod.dll"), &guid_wmv9_enc
},
206 { VLC_CODEC_WMV2
, TEXT("wmvxencd.dll"), &guid_wmv8_enc
},
208 { VLC_CODEC_WMV1
, TEXT("wmvxencd.dll"), &guid_wmv8_enc
},
214 static void WINAPI
DMOFreeMediaType( DMO_MEDIA_TYPE
*mt
)
216 if( mt
->cbFormat
!= 0 ) CoTaskMemFree( (PVOID
)mt
->pbFormat
);
217 if( mt
->pUnk
!= NULL
) mt
->pUnk
->vt
->Release( (IUnknown
*)mt
->pUnk
);
223 /*****************************************************************************
224 * DecoderOpen: open dmo codec
225 *****************************************************************************/
226 static int DecoderOpen( vlc_object_t
*p_this
)
228 decoder_t
*p_dec
= (decoder_t
*)p_this
;
229 decoder_sys_t
*p_sys
;
231 /* We can't open it now, because of ldt_keeper or something
232 * Open/Decode/Close has to be done in the same thread */
234 /* Probe if we support it */
235 for( unsigned i
= 0; decoders_table
[i
].i_fourcc
!= 0; i
++ )
237 if( decoders_table
[i
].i_fourcc
== p_dec
->fmt_in
.i_codec
)
239 msg_Dbg( p_dec
, "DMO codec for %4.4s may work with dll=%ls",
240 (char*)&p_dec
->fmt_in
.i_codec
, decoders_table
[i
].psz_dll
);
247 p_sys
= p_dec
->p_sys
= malloc(sizeof(*p_sys
));
252 p_dec
->pf_decode
= DecodeBlock
;
254 vlc_mutex_init( &p_sys
->lock
);
255 vlc_cond_init( &p_sys
->wait_input
);
256 vlc_cond_init( &p_sys
->wait_output
);
258 p_sys
->b_ready
= false;
259 p_sys
->p_input
= NULL
;
261 if( vlc_clone( &p_sys
->thread
, DecoderThread
, p_dec
,
262 VLC_THREAD_PRIORITY_INPUT
) )
265 vlc_mutex_lock( &p_sys
->lock
);
266 while( !p_sys
->b_ready
)
267 vlc_cond_wait( &p_sys
->wait_output
, &p_sys
->lock
);
268 vlc_mutex_unlock( &p_sys
->lock
);
273 vlc_join( p_sys
->thread
, NULL
);
279 /*****************************************************************************
280 * DecoderClose: close codec
281 *****************************************************************************/
282 static void DecoderClose( vlc_object_t
*p_this
)
284 decoder_t
*p_dec
= (decoder_t
*)p_this
;
285 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
287 vlc_mutex_lock( &p_sys
->lock
);
288 p_sys
->b_ready
= false;
289 vlc_cond_signal( &p_sys
->wait_input
);
290 vlc_mutex_unlock( &p_sys
->lock
);
292 vlc_join( p_sys
->thread
, NULL
);
296 static int DecodeBlock( decoder_t
*p_dec
, block_t
*p_block
)
298 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
300 if( p_block
== NULL
) /* No Drain */
301 return VLCDEC_SUCCESS
;
303 vlc_mutex_lock( &p_sys
->lock
);
304 while( p_sys
->p_input
)
305 vlc_cond_wait( &p_sys
->wait_output
, &p_sys
->lock
);
306 p_sys
->p_input
= p_block
;
307 vlc_cond_signal( &p_sys
->wait_input
);
308 vlc_mutex_unlock( &p_sys
->lock
);
310 return VLCDEC_SUCCESS
;
313 /*****************************************************************************
314 * DecOpen: open dmo codec
315 *****************************************************************************/
316 static int DecOpen( decoder_t
*p_dec
)
318 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
320 DMO_MEDIA_TYPE dmo_input_type
, dmo_output_type
;
321 IMediaObject
*p_dmo
= NULL
;
322 HINSTANCE hmsdmo_dll
= NULL
;
324 VIDEOINFOHEADER
*p_vih
= NULL
;
325 WAVEFORMATEX
*p_wf
= NULL
;
327 /* Initialize OLE/COM */
328 if( FAILED(CoInitializeEx( NULL
, COINIT_MULTITHREADED
)) )
329 vlc_assert_unreachable();
331 if( LoadDMO( VLC_OBJECT(p_dec
), &hmsdmo_dll
, &p_dmo
, &p_dec
->fmt_in
, false )
339 /* Setup input format */
340 memset( &dmo_input_type
, 0, sizeof(dmo_input_type
) );
341 dmo_input_type
.pUnk
= 0;
343 if( p_dec
->fmt_in
.i_cat
== AUDIO_ES
)
346 int i_size
= sizeof(WAVEFORMATEX
) + p_dec
->fmt_in
.i_extra
;
347 p_wf
= malloc( i_size
);
349 memset( p_wf
, 0, sizeof(WAVEFORMATEX
) );
350 if( p_dec
->fmt_in
.i_extra
)
351 memcpy( &p_wf
[1], p_dec
->fmt_in
.p_extra
, p_dec
->fmt_in
.i_extra
);
353 dmo_input_type
.majortype
= MEDIATYPE_Audio
;
354 dmo_input_type
.subtype
= dmo_input_type
.majortype
;
355 dmo_input_type
.subtype
.Data1
= p_dec
->fmt_in
.i_original_fourcc
?
356 p_dec
->fmt_in
.i_original_fourcc
: p_dec
->fmt_in
.i_codec
;
357 fourcc_to_wf_tag( p_dec
->fmt_in
.i_codec
, &i_tag
);
358 if( i_tag
) dmo_input_type
.subtype
.Data1
= i_tag
;
360 p_wf
->wFormatTag
= dmo_input_type
.subtype
.Data1
;
361 p_wf
->nSamplesPerSec
= p_dec
->fmt_in
.audio
.i_rate
;
362 p_wf
->nChannels
= p_dec
->fmt_in
.audio
.i_channels
;
363 p_wf
->wBitsPerSample
= p_dec
->fmt_in
.audio
.i_bitspersample
;
364 p_wf
->nBlockAlign
= p_dec
->fmt_in
.audio
.i_blockalign
;
365 p_wf
->nAvgBytesPerSec
= p_dec
->fmt_in
.i_bitrate
/ 8;
366 p_wf
->cbSize
= p_dec
->fmt_in
.i_extra
;
368 dmo_input_type
.formattype
= FORMAT_WaveFormatEx
;
369 dmo_input_type
.cbFormat
= i_size
;
370 dmo_input_type
.pbFormat
= (char *)p_wf
;
371 dmo_input_type
.bFixedSizeSamples
= 1;
372 dmo_input_type
.bTemporalCompression
= 0;
373 dmo_input_type
.lSampleSize
= p_wf
->nBlockAlign
;
377 VLC_BITMAPINFOHEADER
*p_bih
;
379 int i_size
= sizeof(VIDEOINFOHEADER
) + p_dec
->fmt_in
.i_extra
;
380 p_vih
= malloc( i_size
);
382 memset( p_vih
, 0, sizeof(VIDEOINFOHEADER
) );
383 if( p_dec
->fmt_in
.i_extra
)
384 memcpy( &p_vih
[1], p_dec
->fmt_in
.p_extra
, p_dec
->fmt_in
.i_extra
);
386 p_bih
= &p_vih
->bmiHeader
;
387 p_bih
->biCompression
= p_dec
->fmt_in
.i_original_fourcc
?
388 p_dec
->fmt_in
.i_original_fourcc
: p_dec
->fmt_in
.i_codec
;
389 p_bih
->biWidth
= p_dec
->fmt_in
.video
.i_width
;
390 p_bih
->biHeight
= p_dec
->fmt_in
.video
.i_height
;
391 p_bih
->biBitCount
= p_dec
->fmt_in
.video
.i_bits_per_pixel
;
393 p_bih
->biSize
= i_size
- sizeof(VIDEOINFOHEADER
) +
394 sizeof(VLC_BITMAPINFOHEADER
);
396 p_vih
->rcSource
.left
= p_vih
->rcSource
.top
= 0;
397 p_vih
->rcSource
.right
= p_dec
->fmt_in
.video
.i_width
;
398 p_vih
->rcSource
.bottom
= p_dec
->fmt_in
.video
.i_height
;
399 p_vih
->rcTarget
= p_vih
->rcSource
;
401 dmo_input_type
.majortype
= MEDIATYPE_Video
;
402 dmo_input_type
.subtype
= dmo_input_type
.majortype
;
403 dmo_input_type
.subtype
.Data1
= p_dec
->fmt_in
.i_original_fourcc
?
404 p_dec
->fmt_in
.i_original_fourcc
: p_dec
->fmt_in
.i_codec
;
405 dmo_input_type
.formattype
= FORMAT_VideoInfo
;
406 dmo_input_type
.bFixedSizeSamples
= 0;
407 dmo_input_type
.bTemporalCompression
= 1;
408 dmo_input_type
.cbFormat
= i_size
;
409 dmo_input_type
.pbFormat
= (char *)p_vih
;
412 if( p_dmo
->vt
->SetInputType( p_dmo
, 0, &dmo_input_type
, 0 ) )
414 msg_Err( p_dec
, "can't set DMO input type" );
417 msg_Dbg( p_dec
, "DMO input type set" );
419 /* Setup output format */
420 memset( &dmo_output_type
, 0, sizeof(dmo_output_type
) );
421 dmo_output_type
.pUnk
= 0;
423 if( p_dec
->fmt_in
.i_cat
== AUDIO_ES
)
425 /* Setup the format */
426 p_dec
->fmt_out
.i_codec
= VLC_CODEC_S16N
;
427 p_dec
->fmt_out
.audio
.i_rate
= p_dec
->fmt_in
.audio
.i_rate
;
428 p_dec
->fmt_out
.audio
.i_channels
= p_dec
->fmt_in
.audio
.i_channels
;
429 p_dec
->fmt_out
.audio
.i_bitspersample
= 16;//p_dec->fmt_in.audio.i_bitspersample; We request 16
430 if( p_dec
->fmt_in
.audio
.i_channels
> 8 )
432 p_dec
->fmt_out
.audio
.i_physical_channels
=
433 vlc_chan_maps
[p_dec
->fmt_out
.audio
.i_channels
];
435 p_wf
->wFormatTag
= WAVE_FORMAT_PCM
;
436 p_wf
->nSamplesPerSec
= p_dec
->fmt_out
.audio
.i_rate
;
437 p_wf
->nChannels
= p_dec
->fmt_out
.audio
.i_channels
;
438 p_wf
->wBitsPerSample
= p_dec
->fmt_out
.audio
.i_bitspersample
;
440 p_wf
->wBitsPerSample
/ 8 * p_wf
->nChannels
;
441 p_wf
->nAvgBytesPerSec
=
442 p_wf
->nSamplesPerSec
* p_wf
->nBlockAlign
;
445 dmo_output_type
.majortype
= MEDIATYPE_Audio
;
446 dmo_output_type
.formattype
= FORMAT_WaveFormatEx
;
447 dmo_output_type
.subtype
= MEDIASUBTYPE_PCM
;
448 dmo_output_type
.cbFormat
= sizeof(WAVEFORMATEX
);
449 dmo_output_type
.pbFormat
= (char *)p_wf
;
450 dmo_output_type
.bFixedSizeSamples
= 1;
451 dmo_output_type
.bTemporalCompression
= 0;
452 dmo_output_type
.lSampleSize
= p_wf
->nBlockAlign
;
456 VLC_BITMAPINFOHEADER
*p_bih
;
458 unsigned i_chroma
= VLC_CODEC_YUYV
;
462 /* Find out which chroma to use */
463 while( !p_dmo
->vt
->GetOutputType( p_dmo
, 0, i
++, &mt
) )
465 if( mt
.subtype
.Data1
== VLC_CODEC_YV12
)
467 i_chroma
= mt
.subtype
.Data1
;
469 DMOFreeMediaType( &mt
);
472 else if( (p_dec
->fmt_in
.i_codec
== VLC_CODEC_MSS1
||
473 p_dec
->fmt_in
.i_codec
== VLC_CODEC_MSS2
) &&
474 guidcmp( &mt
.subtype
, &MEDIASUBTYPE_RGB24
) )
476 i_chroma
= VLC_CODEC_RGB24
;
480 DMOFreeMediaType( &mt
);
483 p_dec
->fmt_out
.i_codec
= i_chroma
== VLC_CODEC_YV12
? VLC_CODEC_I420
: i_chroma
;
484 p_dec
->fmt_out
.video
.i_width
= p_dec
->fmt_in
.video
.i_width
;
485 p_dec
->fmt_out
.video
.i_height
= p_dec
->fmt_in
.video
.i_height
;
486 p_dec
->fmt_out
.video
.i_bits_per_pixel
= i_bpp
;
488 /* If an aspect-ratio was specified in the input format then force it */
489 if( p_dec
->fmt_in
.video
.i_sar_num
> 0 &&
490 p_dec
->fmt_in
.video
.i_sar_den
> 0 )
492 p_dec
->fmt_out
.video
.i_sar_num
= p_dec
->fmt_in
.video
.i_sar_num
;
493 p_dec
->fmt_out
.video
.i_sar_den
= p_dec
->fmt_in
.video
.i_sar_den
;
497 p_dec
->fmt_out
.video
.i_sar_num
= 1;
498 p_dec
->fmt_out
.video
.i_sar_den
= 1;
501 p_bih
= &p_vih
->bmiHeader
;
502 p_bih
->biCompression
= i_chroma
== VLC_CODEC_RGB24
? BI_RGB
: i_chroma
;
503 p_bih
->biHeight
*= -1;
504 p_bih
->biBitCount
= p_dec
->fmt_out
.video
.i_bits_per_pixel
;
505 p_bih
->biSizeImage
= p_dec
->fmt_in
.video
.i_width
*
506 p_dec
->fmt_in
.video
.i_height
*
507 (p_dec
->fmt_in
.video
.i_bits_per_pixel
+ 7) / 8;
509 p_bih
->biPlanes
= 1; /* http://msdn.microsoft.com/en-us/library/dd183376%28v=vs.85%29.aspx */
510 p_bih
->biSize
= sizeof(VLC_BITMAPINFOHEADER
);
512 dmo_output_type
.majortype
= MEDIATYPE_Video
;
513 dmo_output_type
.formattype
= FORMAT_VideoInfo
;
514 if( i_chroma
== VLC_CODEC_RGB24
)
516 dmo_output_type
.subtype
= MEDIASUBTYPE_RGB24
;
520 dmo_output_type
.subtype
= dmo_output_type
.majortype
;
521 dmo_output_type
.subtype
.Data1
= p_bih
->biCompression
;
523 dmo_output_type
.bFixedSizeSamples
= true;
524 dmo_output_type
.bTemporalCompression
= 0;
525 dmo_output_type
.lSampleSize
= p_bih
->biSizeImage
;
526 dmo_output_type
.cbFormat
= sizeof(VIDEOINFOHEADER
);
527 dmo_output_type
.pbFormat
= (char *)p_vih
;
531 /* Enumerate output types */
532 if( p_dec
->fmt_in
.i_cat
== VIDEO_ES
)
537 while( !p_dmo
->vt
->GetOutputType( p_dmo
, 0, i
++, &mt
) )
539 msg_Dbg( p_dec
, "available output chroma: %4.4s", (char *)&mt
.subtype
.Data1
);
540 DMOFreeMediaType( &mt
);
545 unsigned i_err
= p_dmo
->vt
->SetOutputType( p_dmo
, 0, &dmo_output_type
, 0 );
548 msg_Err( p_dec
, "can't set DMO output type for decoder: 0x%x", i_err
);
551 msg_Dbg( p_dec
, "DMO output type set for decoder" );
553 /* Allocate the memory needed to store the decoder's structure */
554 p_sys
->hmsdmo_dll
= hmsdmo_dll
;
555 p_sys
->p_dmo
= p_dmo
;
557 /* Find out some properties of the output */
559 uint32_t i_size
, i_align
;
561 p_sys
->i_min_output
= 0;
562 if( p_dmo
->vt
->GetOutputSizeInfo( p_dmo
, 0, &i_size
, &i_align
) )
564 msg_Err( p_dec
, "GetOutputSizeInfo() failed" );
569 msg_Dbg( p_dec
, "GetOutputSizeInfo(): bytes %i, align %i",
571 p_sys
->i_min_output
= i_size
;
572 p_sys
->p_buffer
= malloc( i_size
);
573 if( !p_sys
->p_buffer
) goto error
;
577 /* Set output properties */
578 p_dec
->fmt_out
.i_cat
= p_dec
->fmt_in
.i_cat
;
579 if( p_dec
->fmt_out
.i_cat
== AUDIO_ES
)
580 date_Init( &p_sys
->end_date
, p_dec
->fmt_in
.audio
.i_rate
, 1 );
582 date_Init( &p_sys
->end_date
, 25 /* FIXME */, 1 );
583 date_Set( &p_sys
->end_date
, VLC_TICK_0
);
588 vlc_mutex_lock( &p_sys
->lock
);
590 p_sys
->b_works
= true;
591 vlc_cond_signal( &p_sys
->wait_output
);
592 vlc_mutex_unlock( &p_sys
->lock
);
598 if( p_dmo
) p_dmo
->vt
->Release( (IUnknown
*)p_dmo
);
599 if( hmsdmo_dll
) FreeLibrary( hmsdmo_dll
);
601 /* Uninitialize OLE/COM */
607 vlc_mutex_lock( &p_sys
->lock
);
608 p_sys
->b_ready
= true;
609 vlc_cond_signal( &p_sys
->wait_output
);
610 vlc_mutex_unlock( &p_sys
->lock
);
614 /*****************************************************************************
615 * LoadDMO: Load the DMO object
616 *****************************************************************************/
617 static int LoadDMO( vlc_object_t
*p_this
, HINSTANCE
*p_hmsdmo_dll
,
618 IMediaObject
**pp_dmo
, es_format_t
*p_fmt
,
621 DMO_PARTIAL_MEDIATYPE dmo_partial_type
;
624 long (STDCALL
*OurDMOEnum
)( const GUID
*, uint32_t, uint32_t,
625 const DMO_PARTIAL_MEDIATYPE
*,
626 uint32_t, const DMO_PARTIAL_MEDIATYPE
*,
629 IEnumDMO
*p_enum_dmo
= NULL
;
635 IClassFactory
*cFactory
= NULL
;
636 IUnknown
*cObject
= NULL
;
637 const codec_dll
*codecs_table
= b_out
? encoders_table
: decoders_table
;
640 /* Look for a DMO which can handle the requested codec */
641 if( p_fmt
->i_cat
== AUDIO_ES
)
644 dmo_partial_type
.type
= MEDIATYPE_Audio
;
645 dmo_partial_type
.subtype
= dmo_partial_type
.type
;
646 dmo_partial_type
.subtype
.Data1
= p_fmt
->i_original_fourcc
?
647 p_fmt
->i_original_fourcc
: p_fmt
->i_codec
;
648 fourcc_to_wf_tag( p_fmt
->i_codec
, &i_tag
);
649 if( i_tag
) dmo_partial_type
.subtype
.Data1
= i_tag
;
653 dmo_partial_type
.type
= MEDIATYPE_Video
;
654 dmo_partial_type
.subtype
= dmo_partial_type
.type
;
655 dmo_partial_type
.subtype
.Data1
= p_fmt
->i_original_fourcc
?
656 p_fmt
->i_original_fourcc
: p_fmt
->i_codec
;
660 *p_hmsdmo_dll
= LoadLibrary( TEXT( "msdmo.dll" ) );
661 if( *p_hmsdmo_dll
== NULL
)
663 msg_Dbg( p_this
, "failed loading msdmo.dll" );
666 OurDMOEnum
= (void *)GetProcAddress( *p_hmsdmo_dll
, "DMOEnum" );
667 if( OurDMOEnum
== NULL
)
669 msg_Dbg( p_this
, "GetProcAddress failed to find DMOEnum()" );
670 FreeLibrary( *p_hmsdmo_dll
);
676 i_err
= OurDMOEnum( &GUID_NULL
, 1 /*DMO_ENUMF_INCLUDE_KEYED*/,
677 1, &dmo_partial_type
, 0, NULL
, &p_enum_dmo
);
681 i_err
= OurDMOEnum( &GUID_NULL
, 1 /*DMO_ENUMF_INCLUDE_KEYED*/,
682 0, NULL
, 1, &dmo_partial_type
, &p_enum_dmo
);
686 FreeLibrary( *p_hmsdmo_dll
);
687 /* return VLC_EGENERIC; */
688 /* Try loading the dll directly */
692 /* Pickup the first available codec */
694 while( ( S_OK
== p_enum_dmo
->vt
->Next( p_enum_dmo
, 1, &clsid_dmo
,
695 &psz_dmo_name
, &i_dummy
/* NULL doesn't work */ ) ) )
697 msg_Dbg( p_this
, "found DMO: %ls", psz_dmo_name
);
698 CoTaskMemFree( psz_dmo_name
);
701 if( CoCreateInstance( &clsid_dmo
, NULL
, CLSCTX_INPROC
,
702 &IID_IMediaObject
, (void **)pp_dmo
) )
704 msg_Warn( p_this
, "can't create DMO" );
711 p_enum_dmo
->vt
->Release( (IUnknown
*)p_enum_dmo
);
715 FreeLibrary( *p_hmsdmo_dll
);
716 /* return VLC_EGENERIC; */
717 /* Try loading the dll directly */
725 for( i_codec
= 0; codecs_table
[i_codec
].i_fourcc
!= 0; i_codec
++ )
727 if( codecs_table
[i_codec
].i_fourcc
== p_fmt
->i_codec
)
730 if( codecs_table
[i_codec
].i_fourcc
== 0 )
731 return VLC_EGENERIC
; /* Can't happen */
733 *p_hmsdmo_dll
= LoadLibrary( codecs_table
[i_codec
].psz_dll
);
734 if( *p_hmsdmo_dll
== NULL
)
736 msg_Dbg( p_this
, "failed loading '%ls'", codecs_table
[i_codec
].psz_dll
);
740 GetClass
= (GETCLASS
)GetProcAddress( *p_hmsdmo_dll
, "DllGetClassObject" );
743 msg_Dbg( p_this
, "GetProcAddress failed to find DllGetClassObject()" );
744 FreeLibrary( *p_hmsdmo_dll
);
748 i_err
= GetClass( codecs_table
[i_codec
].p_guid
, &IID_IClassFactory
,
751 if( i_err
|| cFactory
== NULL
)
753 msg_Dbg( p_this
, "no such class object" );
754 FreeLibrary( *p_hmsdmo_dll
);
758 i_err
= cFactory
->vt
->CreateInstance( cFactory
, 0, &IID_IUnknown
,
760 cFactory
->vt
->Release( (IUnknown
*)cFactory
);
761 if( i_err
|| !cObject
)
763 msg_Dbg( p_this
, "class factory failure" );
764 FreeLibrary( *p_hmsdmo_dll
);
767 i_err
= cObject
->vt
->QueryInterface( cObject
, &IID_IMediaObject
,
769 cObject
->vt
->Release( (IUnknown
*)cObject
);
770 if( i_err
|| !*pp_dmo
)
772 msg_Dbg( p_this
, "QueryInterface failure" );
773 FreeLibrary( *p_hmsdmo_dll
);
780 static void DecClose( decoder_t
*p_dec
)
782 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
784 if( p_sys
->p_dmo
) p_sys
->p_dmo
->vt
->Release( (IUnknown
*)p_sys
->p_dmo
);
785 FreeLibrary( p_sys
->hmsdmo_dll
);
789 free( p_sys
->p_buffer
);
792 /****************************************************************************
793 * DecodeBlock: the whole thing
794 ****************************************************************************
795 * This function must be fed with packets.
796 ****************************************************************************/
797 static int DecBlock( decoder_t
*p_dec
, block_t
**pp_block
)
799 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
803 DMO_OUTPUT_DATA_BUFFER db
;
810 /* Won't work with streams with B-frames, but do we have any ? */
811 if( p_block
&& p_block
->i_pts
== VLC_TICK_INVALID
)
812 p_block
->i_pts
= p_block
->i_dts
;
814 /* Date management */
815 if( p_block
&& p_block
->i_pts
!= VLC_TICK_INVALID
&&
816 p_block
->i_pts
!= date_Get( &p_sys
->end_date
) )
818 date_Set( &p_sys
->end_date
, p_block
->i_pts
);
821 #if 0 /* Breaks the video decoding */
822 if( date_Get( &p_sys
->end_date
) == VLC_TICK_INVALID
)
824 /* We've just started the stream, wait for the first PTS. */
825 if( p_block
) block_Release( p_block
);
830 /* Feed input to the DMO */
831 if( p_block
&& p_block
->i_buffer
)
835 p_in
= CMediaBufferCreate( p_block
, p_block
->i_buffer
, true );
837 i_result
= p_sys
->p_dmo
->vt
->ProcessInput( p_sys
->p_dmo
, 0,
838 (IMediaBuffer
*)p_in
, DMO_INPUT_DATA_BUFFERF_SYNCPOINT
,
842 p_in
->vt
->Release( (IUnknown
*)p_in
);
844 if( i_result
== S_FALSE
)
846 /* No output generated */
848 msg_Dbg( p_dec
, "ProcessInput(): no output generated" );
852 else if( i_result
== (int)DMO_E_NOTACCEPTING
)
854 /* Need to call ProcessOutput */
855 msg_Dbg( p_dec
, "ProcessInput(): not accepting" );
857 else if( i_result
!= S_OK
)
859 msg_Dbg( p_dec
, "ProcessInput(): failed" );
865 msg_Dbg( p_dec
, "ProcessInput(): successful" );
870 /* Get output from the DMO */
871 block_out
.p_buffer
= p_sys
->p_buffer
;
872 block_out
.i_buffer
= 0;
874 p_out
= CMediaBufferCreate( &block_out
, p_sys
->i_min_output
, false );
875 memset( &db
, 0, sizeof(db
) );
876 db
.pBuffer
= (IMediaBuffer
*)p_out
;
878 i_result
= p_sys
->p_dmo
->vt
->ProcessOutput( p_sys
->p_dmo
,
879 DMO_PROCESS_OUTPUT_DISCARD_WHEN_NO_BUFFER
,
882 if( i_result
!= S_OK
)
884 if( i_result
!= S_FALSE
)
885 msg_Dbg( p_dec
, "ProcessOutput(): failed" );
888 msg_Dbg( p_dec
, "ProcessOutput(): no output" );
891 p_out
->vt
->Release( (IUnknown
*)p_out
);
896 msg_Dbg( p_dec
, "ProcessOutput(): success" );
899 if( !block_out
.i_buffer
)
902 msg_Dbg( p_dec
, "ProcessOutput(): no output (i_buffer_out == 0)" );
904 p_out
->vt
->Release( (IUnknown
*)p_out
);
908 if( p_dec
->fmt_out
.i_cat
== VIDEO_ES
)
910 /* Get a new picture */
911 if( decoder_UpdateVideoFormat( p_dec
) )
913 picture_t
*p_pic
= decoder_NewPicture( p_dec
);
914 if( !p_pic
) return -1;
916 CopyPicture( p_pic
, block_out
.p_buffer
);
918 /* Date management */
919 p_pic
->date
= date_Get( &p_sys
->end_date
);
920 date_Increment( &p_sys
->end_date
, 1 );
922 p_out
->vt
->Release( (IUnknown
*)p_out
);
924 decoder_QueueVideo( p_dec
, p_pic
);
929 if( decoder_UpdateAudioFormat( p_dec
) )
931 p_out
->vt
->Release( (IUnknown
*)p_out
);
935 block_t
*p_aout_buffer
;
936 int i_samples
= block_out
.i_buffer
/
937 ( p_dec
->fmt_out
.audio
.i_bitspersample
*
938 p_dec
->fmt_out
.audio
.i_channels
/ 8 );
940 p_aout_buffer
= decoder_NewAudioBuffer( p_dec
, i_samples
);
943 memcpy( p_aout_buffer
->p_buffer
,
944 block_out
.p_buffer
, block_out
.i_buffer
);
945 /* Date management */
946 p_aout_buffer
->i_pts
= date_Get( &p_sys
->end_date
);
947 p_aout_buffer
->i_length
=
948 date_Increment( &p_sys
->end_date
, i_samples
)
949 - p_aout_buffer
->i_pts
;
951 p_out
->vt
->Release( (IUnknown
*)p_out
);
953 decoder_QueueAudio( p_dec
, p_aout_buffer
);
958 static void CopyPicture( picture_t
*p_pic
, uint8_t *p_in
)
960 int i_plane
, i_line
, i_width
, i_dst_stride
;
961 uint8_t *p_dst
, *p_src
= p_in
;
963 picture_SwapUV( p_pic
);
965 for( i_plane
= 0; i_plane
< p_pic
->i_planes
; i_plane
++ )
967 p_dst
= p_pic
->p
[i_plane
].p_pixels
;
968 i_width
= p_pic
->p
[i_plane
].i_visible_pitch
;
969 i_dst_stride
= p_pic
->p
[i_plane
].i_pitch
;
971 for( i_line
= 0; i_line
< p_pic
->p
[i_plane
].i_visible_lines
; i_line
++ )
973 memcpy( p_dst
, p_src
, i_width
);
975 p_dst
+= i_dst_stride
;
979 picture_SwapUV( p_pic
);
982 static void *DecoderThread( void *data
)
984 decoder_t
*p_dec
= data
;
985 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
987 if( DecOpen( p_dec
) )
988 return NULL
; /* failed */
990 vlc_mutex_lock( &p_sys
->lock
);
993 while( p_sys
->b_ready
&& !p_sys
->p_input
)
994 vlc_cond_wait( &p_sys
->wait_input
, &p_sys
->lock
);
995 if( !p_sys
->b_ready
)
998 while( DecBlock( p_dec
, &p_sys
->p_input
) == 0 );
1000 if( p_sys
->p_input
!= NULL
)
1001 block_Release( p_sys
->p_input
);
1002 p_sys
->p_input
= NULL
;
1004 vlc_cond_signal( &p_sys
->wait_output
);
1006 vlc_mutex_unlock( &p_sys
->lock
);
1013 /****************************************************************************
1014 * Encoder descriptor declaration
1015 ****************************************************************************/
1018 HINSTANCE hmsdmo_dll
;
1019 IMediaObject
*p_dmo
;
1027 /*****************************************************************************
1028 * EncoderOpen: open dmo codec
1029 *****************************************************************************/
1030 static int EncoderOpen( vlc_object_t
*p_this
)
1032 encoder_t
*p_enc
= (encoder_t
*)p_this
;
1034 int i_ret
= EncOpen( p_this
);
1035 if( i_ret
!= VLC_SUCCESS
) return i_ret
;
1038 p_enc
->pf_encode_video
= (block_t
*(*)(encoder_t
*, picture_t
*))
1040 p_enc
->pf_encode_audio
= (block_t
*(*)(encoder_t
*, block_t
*))
1046 /*****************************************************************************
1047 * EncoderSetVideoType: configures the input and output types of the dmo
1048 *****************************************************************************/
1049 static int EncoderSetVideoType( encoder_t
*p_enc
, IMediaObject
*p_dmo
)
1051 int i
, i_selected
, i_err
;
1052 DMO_MEDIA_TYPE dmo_type
;
1053 VIDEOINFOHEADER vih
, *p_vih
;
1054 VLC_BITMAPINFOHEADER
*p_bih
;
1057 p_enc
->fmt_in
.video
.i_bits_per_pixel
=
1058 p_enc
->fmt_out
.video
.i_bits_per_pixel
= 12;
1060 /* Enumerate input format (for debug output) */
1062 while( !p_dmo
->vt
->GetInputType( p_dmo
, 0, i
++, &dmo_type
) )
1064 p_vih
= (VIDEOINFOHEADER
*)dmo_type
.pbFormat
;
1066 msg_Dbg( p_enc
, "available input chroma: %4.4s",
1067 (char *)&dmo_type
.subtype
.Data1
);
1068 if( !memcmp( &dmo_type
.subtype
, &MEDIASUBTYPE_RGB565
, 16 ) )
1069 msg_Dbg( p_enc
, "-> MEDIASUBTYPE_RGB565" );
1070 if( !memcmp( &dmo_type
.subtype
, &MEDIASUBTYPE_RGB24
, 16 ) )
1071 msg_Dbg( p_enc
, "-> MEDIASUBTYPE_RGB24" );
1073 DMOFreeMediaType( &dmo_type
);
1076 /* Setup input format */
1077 memset( &dmo_type
, 0, sizeof(dmo_type
) );
1078 memset( &vih
, 0, sizeof(VIDEOINFOHEADER
) );
1080 p_bih
= &vih
.bmiHeader
;
1081 p_bih
->biCompression
= VLC_CODEC_I420
;
1082 p_bih
->biWidth
= p_enc
->fmt_in
.video
.i_visible_width
;
1083 p_bih
->biHeight
= p_enc
->fmt_in
.video
.i_visible_height
;
1084 p_bih
->biBitCount
= p_enc
->fmt_in
.video
.i_bits_per_pixel
;
1085 p_bih
->biSizeImage
= p_enc
->fmt_in
.video
.i_visible_width
*
1086 p_enc
->fmt_in
.video
.i_visible_height
* p_enc
->fmt_in
.video
.i_bits_per_pixel
/8;
1087 p_bih
->biPlanes
= 3;
1088 p_bih
->biSize
= sizeof(VLC_BITMAPINFOHEADER
);
1090 vih
.rcSource
.left
= vih
.rcSource
.top
= 0;
1091 vih
.rcSource
.right
= p_enc
->fmt_in
.video
.i_visible_width
;
1092 vih
.rcSource
.bottom
= p_enc
->fmt_in
.video
.i_visible_height
;
1093 vih
.rcTarget
= vih
.rcSource
;
1095 vih
.AvgTimePerFrame
= INT64_C(10000000) / 25; //FIXME
1097 dmo_type
.majortype
= MEDIATYPE_Video
;
1098 //dmo_type.subtype = MEDIASUBTYPE_RGB24;
1099 dmo_type
.subtype
= MEDIASUBTYPE_I420
;
1100 //dmo_type.subtype.Data1 = p_bih->biCompression;
1101 dmo_type
.formattype
= FORMAT_VideoInfo
;
1102 dmo_type
.bFixedSizeSamples
= TRUE
;
1103 dmo_type
.bTemporalCompression
= FALSE
;
1104 dmo_type
.lSampleSize
= p_bih
->biSizeImage
;
1105 dmo_type
.cbFormat
= sizeof(VIDEOINFOHEADER
);
1106 dmo_type
.pbFormat
= (char *)&vih
;
1108 if( ( i_err
= p_dmo
->vt
->SetInputType( p_dmo
, 0, &dmo_type
, 0 ) ) )
1110 msg_Err( p_enc
, "can't set DMO input type: %x", i_err
);
1111 return VLC_EGENERIC
;
1114 msg_Dbg( p_enc
, "successfully set input type" );
1116 /* Setup output format */
1117 memset( &dmo_type
, 0, sizeof(dmo_type
) );
1120 /* Enumerate output types */
1121 i
= 0, i_selected
= -1;
1122 while( !p_dmo
->vt
->GetOutputType( p_dmo
, 0, i
++, &dmo_type
) )
1124 p_vih
= (VIDEOINFOHEADER
*)dmo_type
.pbFormat
;
1126 msg_Dbg( p_enc
, "available output codec: %4.4s",
1127 (char *)&dmo_type
.subtype
.Data1
);
1129 if( p_vih
->bmiHeader
.biCompression
== p_enc
->fmt_out
.i_codec
)
1132 DMOFreeMediaType( &dmo_type
);
1135 if( i_selected
< 0 )
1137 msg_Err( p_enc
, "couldn't find codec: %4.4s",
1138 (char *)&p_enc
->fmt_out
.i_codec
);
1139 return VLC_EGENERIC
;
1142 p_dmo
->vt
->GetOutputType( p_dmo
, 0, i_selected
, &dmo_type
);
1143 ((VIDEOINFOHEADER
*)dmo_type
.pbFormat
)->dwBitRate
=
1144 p_enc
->fmt_out
.i_bitrate
;
1146 /* Get the private data for the codec */
1149 IWMCodecPrivateData
*p_privdata
;
1150 VIDEOINFOHEADER
*p_vih
;
1151 uint8_t *p_data
= 0;
1152 uint32_t i_data
= 0, i_vih
;
1154 i_err
= p_dmo
->vt
->QueryInterface( (IUnknown
*)p_dmo
,
1155 &IID_IWMCodecPrivateData
,
1156 (void**)&p_privdata
);
1159 i_err
= p_privdata
->vt
->SetPartialOutputType( p_privdata
, &dmo_type
);
1162 msg_Err( p_enc
, "SetPartialOutputType() failed" );
1163 p_privdata
->vt
->Release( (IUnknown
*)p_privdata
);
1167 i_err
= p_privdata
->vt
->GetPrivateData( p_privdata
, NULL
, &i_data
);
1170 msg_Err( p_enc
, "GetPrivateData() failed" );
1171 p_privdata
->vt
->Release( (IUnknown
*)p_privdata
);
1175 p_data
= malloc( i_data
);
1176 i_err
= p_privdata
->vt
->GetPrivateData( p_privdata
, p_data
, &i_data
);
1178 /* Update the media type with the private data */
1179 i_vih
= dmo_type
.cbFormat
+ i_data
;
1180 p_vih
= CoTaskMemAlloc( i_vih
);
1181 memcpy( p_vih
, dmo_type
.pbFormat
, dmo_type
.cbFormat
);
1182 memcpy( ((uint8_t *)p_vih
) + dmo_type
.cbFormat
, p_data
, i_data
);
1183 DMOFreeMediaType( &dmo_type
);
1184 dmo_type
.pbFormat
= (char*)p_vih
;
1185 dmo_type
.cbFormat
= i_vih
;
1187 msg_Dbg( p_enc
, "found extra data: %i", i_data
);
1188 p_enc
->fmt_out
.i_extra
= i_data
;
1189 p_enc
->fmt_out
.p_extra
= p_data
;
1193 i_err
= p_dmo
->vt
->SetOutputType( p_dmo
, 0, &dmo_type
, 0 );
1195 p_vih
= (VIDEOINFOHEADER
*)dmo_type
.pbFormat
;
1196 p_enc
->fmt_in
.i_codec
= VLC_CODEC_I420
;
1198 DMOFreeMediaType( &dmo_type
);
1201 msg_Err( p_enc
, "can't set DMO output type for encoder: 0x%x", i_err
);
1202 return VLC_EGENERIC
;
1205 msg_Dbg( p_enc
, "successfully set output type for encoder" );
1209 /*****************************************************************************
1210 * EncoderSetAudioType: configures the input and output types of the dmo
1211 *****************************************************************************/
1212 static int EncoderSetAudioType( encoder_t
*p_enc
, IMediaObject
*p_dmo
)
1214 int i
, i_selected
, i_err
;
1215 unsigned int i_last_byterate
;
1217 DMO_MEDIA_TYPE dmo_type
;
1220 /* Setup the format structure */
1221 fourcc_to_wf_tag( p_enc
->fmt_out
.i_codec
, &i_tag
);
1222 if( i_tag
== 0 ) return VLC_EGENERIC
;
1224 p_enc
->fmt_in
.i_codec
= VLC_CODEC_S16N
;
1225 p_enc
->fmt_in
.audio
.i_bitspersample
= 16;
1227 /* We first need to choose an output type from the predefined
1228 * list of choices (we cycle through the list to select the best match) */
1229 i
= 0; i_selected
= -1; i_last_byterate
= 0;
1230 while( !p_dmo
->vt
->GetOutputType( p_dmo
, 0, i
++, &dmo_type
) )
1232 p_wf
= (WAVEFORMATEX
*)dmo_type
.pbFormat
;
1233 msg_Dbg( p_enc
, "available format :%i, sample rate: %i, channels: %i, "
1234 "bits per sample: %i, bitrate: %i, blockalign: %i",
1235 (int) p_wf
->wFormatTag
, (int)p_wf
->nSamplesPerSec
,
1236 (int)p_wf
->nChannels
, (int)p_wf
->wBitsPerSample
,
1237 (int)p_wf
->nAvgBytesPerSec
* 8, (int)p_wf
->nBlockAlign
);
1239 if( p_wf
->wFormatTag
== i_tag
&&
1240 p_wf
->nSamplesPerSec
== p_enc
->fmt_in
.audio
.i_rate
&&
1241 p_wf
->nChannels
== p_enc
->fmt_in
.audio
.i_channels
&&
1242 p_wf
->wBitsPerSample
== p_enc
->fmt_in
.audio
.i_bitspersample
)
1244 if( p_wf
->nAvgBytesPerSec
<
1245 p_enc
->fmt_out
.i_bitrate
* 110 / 800 /* + 10% */ &&
1246 p_wf
->nAvgBytesPerSec
> i_last_byterate
)
1249 i_last_byterate
= p_wf
->nAvgBytesPerSec
;
1250 msg_Dbg( p_enc
, "selected entry %i (bitrate: %i)",
1251 i_selected
, p_wf
->nAvgBytesPerSec
* 8 );
1255 DMOFreeMediaType( &dmo_type
);
1258 if( i_selected
< 0 )
1260 msg_Err( p_enc
, "couldn't find a matching output" );
1261 return VLC_EGENERIC
;
1264 p_dmo
->vt
->GetOutputType( p_dmo
, 0, i_selected
, &dmo_type
);
1265 p_wf
= (WAVEFORMATEX
*)dmo_type
.pbFormat
;
1267 msg_Dbg( p_enc
, "selected format: %i, sample rate:%i, "
1268 "channels: %i, bits per sample: %i, bitrate: %i, blockalign: %i",
1269 (int)p_wf
->wFormatTag
, (int)p_wf
->nSamplesPerSec
,
1270 (int)p_wf
->nChannels
, (int)p_wf
->wBitsPerSample
,
1271 (int)p_wf
->nAvgBytesPerSec
* 8, (int)p_wf
->nBlockAlign
);
1273 p_enc
->fmt_out
.audio
.i_rate
= p_wf
->nSamplesPerSec
;
1274 p_enc
->fmt_out
.audio
.i_channels
= p_wf
->nChannels
;
1275 p_enc
->fmt_out
.audio
.i_bitspersample
= p_wf
->wBitsPerSample
;
1276 p_enc
->fmt_out
.audio
.i_blockalign
= p_wf
->nBlockAlign
;
1277 p_enc
->fmt_out
.i_bitrate
= p_wf
->nAvgBytesPerSec
* 8;
1281 msg_Dbg( p_enc
, "found cbSize: %i", p_wf
->cbSize
);
1282 p_enc
->fmt_out
.i_extra
= p_wf
->cbSize
;
1283 p_enc
->fmt_out
.p_extra
= malloc( p_enc
->fmt_out
.i_extra
);
1284 if( p_enc
->fmt_out
.p_extra
== NULL
)
1285 return VLC_EGENERIC
;
1287 memcpy( p_enc
->fmt_out
.p_extra
, &p_wf
[1], p_enc
->fmt_out
.i_extra
);
1290 i_err
= p_dmo
->vt
->SetOutputType( p_dmo
, 0, &dmo_type
, 0 );
1291 DMOFreeMediaType( &dmo_type
);
1295 msg_Err( p_enc
, "can't set DMO output type: %i", i_err
);
1296 return VLC_EGENERIC
;
1299 msg_Dbg( p_enc
, "successfully set output type" );
1301 /* Setup the input type */
1302 i
= 0; i_selected
= -1;
1303 while( !p_dmo
->vt
->GetInputType( p_dmo
, 0, i
++, &dmo_type
) )
1305 p_wf
= (WAVEFORMATEX
*)dmo_type
.pbFormat
;
1306 msg_Dbg( p_enc
, "available format :%i, sample rate: %i, channels: %i, "
1307 "bits per sample: %i, bitrate: %i, blockalign: %i",
1308 (int) p_wf
->wFormatTag
, (int)p_wf
->nSamplesPerSec
,
1309 (int)p_wf
->nChannels
, (int)p_wf
->wBitsPerSample
,
1310 (int)p_wf
->nAvgBytesPerSec
* 8, (int)p_wf
->nBlockAlign
);
1312 if( p_wf
->wFormatTag
== WAVE_FORMAT_PCM
&&
1313 p_wf
->nSamplesPerSec
== p_enc
->fmt_in
.audio
.i_rate
&&
1314 p_wf
->nChannels
== p_enc
->fmt_in
.audio
.i_channels
&&
1315 p_wf
->wBitsPerSample
== p_enc
->fmt_in
.audio
.i_bitspersample
)
1320 DMOFreeMediaType( &dmo_type
);
1323 if( i_selected
< 0 )
1325 msg_Err( p_enc
, "couldn't find a matching input" );
1326 return VLC_EGENERIC
;
1329 p_dmo
->vt
->GetInputType( p_dmo
, 0, i_selected
, &dmo_type
);
1330 i_err
= p_dmo
->vt
->SetInputType( p_dmo
, 0, &dmo_type
, 0 );
1331 DMOFreeMediaType( &dmo_type
);
1334 msg_Err( p_enc
, "can't set DMO input type: 0x%x", i_err
);
1335 return VLC_EGENERIC
;
1337 msg_Dbg( p_enc
, "successfully set input type" );
1342 /*****************************************************************************
1343 * EncOpen: open dmo codec
1344 *****************************************************************************/
1345 static int EncOpen( vlc_object_t
*p_this
)
1347 encoder_t
*p_enc
= (encoder_t
*)p_this
;
1348 encoder_sys_t
*p_sys
= NULL
;
1349 IMediaObject
*p_dmo
= NULL
;
1350 HINSTANCE hmsdmo_dll
= NULL
;
1352 /* Initialize OLE/COM */
1353 if( FAILED(CoInitializeEx( NULL
, COINIT_MULTITHREADED
)) )
1354 vlc_assert_unreachable();
1356 if( LoadDMO( p_this
, &hmsdmo_dll
, &p_dmo
, &p_enc
->fmt_out
, true )
1364 if( p_enc
->fmt_in
.i_cat
== VIDEO_ES
)
1366 if( EncoderSetVideoType( p_enc
, p_dmo
) != VLC_SUCCESS
) goto error
;
1370 if( EncoderSetAudioType( p_enc
, p_dmo
) != VLC_SUCCESS
) goto error
;
1373 /* Allocate the memory needed to store the decoder's structure */
1374 if( ( p_enc
->p_sys
= p_sys
= malloc(sizeof(*p_sys
)) ) == NULL
)
1379 p_sys
->hmsdmo_dll
= hmsdmo_dll
;
1380 p_sys
->p_dmo
= p_dmo
;
1382 /* Find out some properties of the inputput */
1384 uint32_t i_size
, i_align
, dum
;
1386 if( p_dmo
->vt
->GetInputSizeInfo( p_dmo
, 0, &i_size
, &i_align
, &dum
) )
1387 msg_Err( p_enc
, "GetInputSizeInfo() failed" );
1389 msg_Dbg( p_enc
, "GetInputSizeInfo(): bytes %i, align %i, %i",
1390 i_size
, i_align
, dum
);
1393 /* Find out some properties of the output */
1395 uint32_t i_size
, i_align
;
1397 p_sys
->i_min_output
= 0;
1398 if( p_dmo
->vt
->GetOutputSizeInfo( p_dmo
, 0, &i_size
, &i_align
) )
1400 msg_Err( p_enc
, "GetOutputSizeInfo() failed" );
1405 msg_Dbg( p_enc
, "GetOutputSizeInfo(): bytes %i, align %i",
1407 p_sys
->i_min_output
= i_size
;
1411 /* Set output properties */
1412 p_enc
->fmt_out
.i_cat
= p_enc
->fmt_in
.i_cat
;
1413 if( p_enc
->fmt_out
.i_cat
== AUDIO_ES
)
1414 date_Init( &p_sys
->end_date
, p_enc
->fmt_out
.audio
.i_rate
, 1 );
1416 date_Init( &p_sys
->end_date
, 25 /* FIXME */, 1 );
1422 if( p_dmo
) p_dmo
->vt
->Release( (IUnknown
*)p_dmo
);
1423 if( hmsdmo_dll
) FreeLibrary( hmsdmo_dll
);
1425 /* Uninitialize OLE/COM */
1430 return VLC_EGENERIC
;
1433 /****************************************************************************
1434 * Encode: the whole thing
1435 ****************************************************************************/
1436 static block_t
*EncodeBlock( encoder_t
*p_enc
, void *p_data
)
1438 encoder_sys_t
*p_sys
= p_enc
->p_sys
;
1440 block_t
*p_chain
= NULL
;
1441 block_t
*p_block_in
;
1446 if( !p_data
) return NULL
;
1448 if( p_enc
->fmt_out
.i_cat
== VIDEO_ES
)
1450 /* Get picture data */
1451 int i_plane
, i_line
, i_width
, i_src_stride
;
1452 picture_t
*p_pic
= (picture_t
*)p_data
;
1455 int i_buffer
= p_enc
->fmt_in
.video
.i_visible_width
*
1456 p_enc
->fmt_in
.video
.i_visible_height
*
1457 p_enc
->fmt_in
.video
.i_bits_per_pixel
/ 8;
1459 p_block_in
= block_Alloc( i_buffer
);
1461 /* Copy picture stride by stride */
1462 p_dst
= p_block_in
->p_buffer
;
1463 for( i_plane
= 0; i_plane
< p_pic
->i_planes
; i_plane
++ )
1465 uint8_t *p_src
= p_pic
->p
[i_plane
].p_pixels
;
1466 i_width
= p_pic
->p
[i_plane
].i_visible_pitch
;
1467 i_src_stride
= p_pic
->p
[i_plane
].i_pitch
;
1469 for( i_line
= 0; i_line
< p_pic
->p
[i_plane
].i_visible_lines
;
1472 memcpy( p_dst
, p_src
, i_width
);
1474 p_src
+= i_src_stride
;
1478 i_pts
= p_pic
->date
;
1482 block_t
*p_aout_buffer
= (block_t
*)p_data
;
1483 p_block_in
= block_Alloc( p_aout_buffer
->i_buffer
);
1484 memcpy( p_block_in
->p_buffer
, p_aout_buffer
->p_buffer
,
1485 p_block_in
->i_buffer
);
1487 i_pts
= p_aout_buffer
->i_pts
;
1490 /* Feed input to the DMO */
1491 p_in
= CMediaBufferCreate( p_block_in
, p_block_in
->i_buffer
, true );
1492 i_result
= p_sys
->p_dmo
->vt
->ProcessInput( p_sys
->p_dmo
, 0,
1493 (IMediaBuffer
*)p_in
, DMO_INPUT_DATA_BUFFERF_TIME
, MSFTIME_FROM_VLC_TICK(i_pts
), 0 );
1495 p_in
->vt
->Release( (IUnknown
*)p_in
);
1496 if( i_result
== S_FALSE
)
1498 /* No output generated */
1500 msg_Dbg( p_enc
, "ProcessInput(): no output generated %"PRId64
, i_pts
);
1504 else if( i_result
== (int)DMO_E_NOTACCEPTING
)
1506 /* Need to call ProcessOutput */
1507 msg_Dbg( p_enc
, "ProcessInput(): not accepting" );
1509 else if( i_result
!= S_OK
)
1511 msg_Dbg( p_enc
, "ProcessInput(): failed: %x", i_result
);
1516 msg_Dbg( p_enc
, "ProcessInput(): success" );
1519 /* Get output from the DMO */
1522 DMO_OUTPUT_DATA_BUFFER db
;
1523 block_t
*p_block_out
;
1524 CMediaBuffer
*p_out
;
1526 p_block_out
= block_Alloc( p_sys
->i_min_output
);
1527 p_block_out
->i_buffer
= 0;
1528 p_out
= CMediaBufferCreate(p_block_out
, p_sys
->i_min_output
, false);
1529 memset( &db
, 0, sizeof(db
) );
1530 db
.pBuffer
= (IMediaBuffer
*)p_out
;
1532 i_result
= p_sys
->p_dmo
->vt
->ProcessOutput( p_sys
->p_dmo
,
1533 0, 1, &db
, &i_status
);
1535 if( i_result
!= S_OK
)
1537 if( i_result
!= S_FALSE
)
1538 msg_Dbg( p_enc
, "ProcessOutput(): failed: %x", i_result
);
1541 msg_Dbg( p_enc
, "ProcessOutput(): no output" );
1544 p_out
->vt
->Release( (IUnknown
*)p_out
);
1545 block_Release( p_block_out
);
1549 if( !p_block_out
->i_buffer
)
1552 msg_Dbg( p_enc
, "ProcessOutput(): no output (i_buffer_out == 0)" );
1554 p_out
->vt
->Release( (IUnknown
*)p_out
);
1555 block_Release( p_block_out
);
1559 if( db
.dwStatus
& DMO_OUTPUT_DATA_BUFFERF_TIME
)
1562 msg_Dbg( p_enc
, "ProcessOutput(): pts: %"PRId64
", %"PRId64
,
1563 i_pts
, VLC_TICK_FROM_MSFTIME(db
.rtTimestamp
) );
1565 i_pts
= VLC_TICK_FROM_MSFTIME(db
.rtTimestamp
);
1568 if( db
.dwStatus
& DMO_OUTPUT_DATA_BUFFERF_TIMELENGTH
)
1570 p_block_out
->i_length
= VLC_TICK_FROM_MSFTIME(db
.rtTimelength
);
1572 msg_Dbg( p_enc
, "ProcessOutput(): length: %"PRId64
,
1573 p_block_out
->i_length
);
1577 if( p_enc
->fmt_out
.i_cat
== VIDEO_ES
)
1579 if( db
.dwStatus
& DMO_OUTPUT_DATA_BUFFERF_SYNCPOINT
)
1580 p_block_out
->i_flags
|= BLOCK_FLAG_TYPE_I
;
1582 p_block_out
->i_flags
|= BLOCK_FLAG_TYPE_P
;
1585 p_block_out
->i_dts
= p_block_out
->i_pts
= i_pts
;
1586 block_ChainAppend( &p_chain
, p_block_out
);
1590 /*****************************************************************************
1591 * EncoderClose: close codec
1592 *****************************************************************************/
1593 void EncoderClose( vlc_object_t
*p_this
)
1595 encoder_t
*p_enc
= (encoder_t
*)p_this
;
1596 encoder_sys_t
*p_sys
= p_enc
->p_sys
;
1598 if( !p_sys
) return;
1600 if( p_sys
->p_dmo
) p_sys
->p_dmo
->vt
->Release( (IUnknown
*)p_sys
->p_dmo
);
1601 FreeLibrary( p_sys
->hmsdmo_dll
);
1603 /* Uninitialize OLE/COM */