00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include <stdlib.h>
00028 #include <stdio.h>
00029 #include <string.h>
00030
00031 #include <vlc/vlc.h>
00032 #include <vlc/decoder.h>
00033 #include <vlc/vout.h>
00034
00035 #ifndef WIN32
00036 # define LOADER
00037 #else
00038 # include <objbase.h>
00039 #endif
00040
00041 #ifdef LOADER
00042
00043 # include <wine/winerror.h>
00044 # include <ldt_keeper.h>
00045 # include <wine/windef.h>
00046 #endif
00047
00048 #include "codecs.h"
00049 #include "dmo.h"
00050
00051
00052
00053 #ifdef LOADER
00054
00055 long CoInitialize( void *pvReserved ) { return -1; }
00056 void CoUninitialize( void ) { }
00057
00058
00059 HMODULE WINAPI LoadLibraryA(LPCSTR);
00060 #define LoadLibrary LoadLibraryA
00061 FARPROC WINAPI GetProcAddress(HMODULE,LPCSTR);
00062 int WINAPI FreeLibrary(HMODULE);
00063 #endif
00064
00065 typedef long (STDCALL *GETCLASS) ( const GUID*, const GUID*, void** );
00066
00067 static int pi_channels_maps[7] =
00068 {
00069 0,
00070 AOUT_CHAN_CENTER,
00071 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
00072 AOUT_CHAN_CENTER | AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
00073 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT
00074 | AOUT_CHAN_REARRIGHT,
00075 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
00076 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT,
00077 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
00078 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE
00079 };
00080
00081
00082
00083
00084 static int DecoderOpen ( vlc_object_t * );
00085 static int DecOpen ( vlc_object_t * );
00086 static void DecoderClose ( vlc_object_t * );
00087 static void *DecodeBlock ( decoder_t *, block_t ** );
00088
00089 static int EncoderOpen ( vlc_object_t * );
00090 static int EncOpen ( vlc_object_t * );
00091 static void EncoderClose ( vlc_object_t * );
00092 static block_t *EncodeBlock( encoder_t *, void * );
00093
00094 static int LoadDMO( vlc_object_t *, HINSTANCE *, IMediaObject **,
00095 es_format_t *, vlc_bool_t );
00096 static void CopyPicture( decoder_t *, picture_t *, uint8_t * );
00097
00098 vlc_module_begin();
00099 set_description( _("DirectMedia Object decoder") );
00100 add_shortcut( "dmo" );
00101 set_capability( "decoder", 1 );
00102 set_callbacks( DecoderOpen, DecoderClose );
00103 set_category( CAT_INPUT );
00104 set_subcategory( SUBCAT_INPUT_SCODEC );
00105
00106 # define ENC_CFG_PREFIX "sout-dmo-"
00107 add_submodule();
00108 set_description( _("DirectMedia Object encoder") );
00109 set_capability( "encoder", 10 );
00110 set_callbacks( EncoderOpen, EncoderClose );
00111
00112 vlc_module_end();
00113
00114
00115
00116
00117
00118
00119
00120
00121 struct decoder_sys_t
00122 {
00123 HINSTANCE hmsdmo_dll;
00124 IMediaObject *p_dmo;
00125
00126 int i_min_output;
00127 uint8_t *p_buffer;
00128
00129 date_t end_date;
00130
00131 #ifdef LOADER
00132 ldt_fs_t *ldt_fs;
00133 #endif
00134 };
00135
00136 static const GUID guid_wmv9 = { 0x724bb6a4, 0xe526, 0x450f, { 0xaf, 0xfa, 0xab, 0x9b, 0x45, 0x12, 0x91, 0x11 } };
00137 static const GUID guid_wma9 = { 0x27ca0808, 0x01f5, 0x4e7a, { 0x8b, 0x05, 0x87, 0xf8, 0x07, 0xa2, 0x33, 0xd1 } };
00138
00139 static const GUID guid_wmv = { 0x82d353df, 0x90bd, 0x4382, { 0x8b, 0xc2, 0x3f, 0x61, 0x92, 0xb7, 0x6e, 0x34 } };
00140 static const GUID guid_wma = { 0x874131cb, 0x4ecc, 0x443b, { 0x89, 0x48, 0x74, 0x6b, 0x89, 0x59, 0x5d, 0x20 } };
00141
00142 static const GUID guid_wmv_enc = { 0x3181343b, 0x94a2, 0x4feb, { 0xad, 0xef, 0x30, 0xa1, 0xdd, 0xe6, 0x17, 0xb4 } };
00143 static const GUID guid_wma_enc = { 0x70f598e9, 0xf4ab, 0x495a, { 0x99, 0xe2, 0xa7, 0xc4, 0xd3, 0xd8, 0x9a, 0xbf } };
00144
00145 typedef struct
00146 {
00147 vlc_fourcc_t i_fourcc;
00148 const char *psz_dll;
00149 const GUID *p_guid;
00150
00151 } codec_dll;
00152
00153 static const codec_dll decoders_table[] =
00154 {
00155
00156 { VLC_FOURCC('W','M','V','3'), "wmv9dmod.dll", &guid_wmv9 },
00157 { VLC_FOURCC('w','m','v','3'), "wmv9dmod.dll", &guid_wmv9 },
00158
00159 { VLC_FOURCC('W','M','V','2'), "wmvdmod.dll", &guid_wmv },
00160 { VLC_FOURCC('w','m','v','2'), "wmvdmod.dll", &guid_wmv },
00161
00162 { VLC_FOURCC('W','M','V','1'), "wmvdmod.dll", &guid_wmv },
00163 { VLC_FOURCC('w','m','v','1'), "wmvdmod.dll", &guid_wmv },
00164
00165
00166 { VLC_FOURCC('W','M','A','3'), "wma9dmod.dll", &guid_wma9 },
00167 { VLC_FOURCC('w','m','a','3'), "wma9dmod.dll", &guid_wma9 },
00168 { VLC_FOURCC('w','m','a','p'), "wma9dmod.dll", &guid_wma9 },
00169
00170 { VLC_FOURCC('W','M','A','2'), "wma9dmod.dll", &guid_wma9 },
00171 { VLC_FOURCC('w','m','a','2'), "wma9dmod.dll", &guid_wma9 },
00172
00173
00174 { 0, NULL, NULL }
00175 };
00176
00177 static const codec_dll encoders_table[] =
00178 {
00179
00180 { VLC_FOURCC('W','M','V','2'), "wmvdmoe.dll", &guid_wmv_enc },
00181 { VLC_FOURCC('w','m','v','1'), "wmvdmoe.dll", &guid_wmv_enc },
00182
00183 { VLC_FOURCC('W','M','V','1'), "wmvdmoe.dll", &guid_wmv_enc },
00184 { VLC_FOURCC('w','m','v','1'), "wmvdmoe.dll", &guid_wmv_enc },
00185
00186
00187 { VLC_FOURCC('W','M','A','3'), "wmadmoe.dll", &guid_wma_enc },
00188 { VLC_FOURCC('w','m','a','3'), "wmadmoe.dll", &guid_wma_enc },
00189
00190 { VLC_FOURCC('W','M','A','2'), "wmadmoe.dll", &guid_wma_enc },
00191 { VLC_FOURCC('w','m','a','2'), "wmadmoe.dll", &guid_wma_enc },
00192
00193
00194 { 0, NULL, NULL }
00195 };
00196
00197 static void WINAPI DMOFreeMediaType( DMO_MEDIA_TYPE *mt )
00198 {
00199 if( mt->cbFormat != 0 ) CoTaskMemFree( (PVOID)mt->pbFormat );
00200 if( mt->pUnk != NULL ) mt->pUnk->vt->Release( (IUnknown *)mt->pUnk );
00201 mt->cbFormat = 0;
00202 mt->pbFormat = NULL;
00203 mt->pUnk = NULL;
00204 }
00205
00206
00207
00208
00209 static int DecoderOpen( vlc_object_t *p_this )
00210 {
00211 decoder_t *p_dec = (decoder_t*)p_this;
00212
00213 #ifndef LOADER
00214 int i_ret = DecOpen( p_this );
00215 if( i_ret != VLC_SUCCESS ) return i_ret;
00216
00217
00218 #else
00219
00220
00221 int i;
00222
00223 p_dec->p_sys = NULL;
00224
00225
00226 for( i = 0; decoders_table[i].i_fourcc != 0; i++ )
00227 {
00228 if( decoders_table[i].i_fourcc == p_dec->fmt_in.i_codec )
00229 {
00230 msg_Dbg( p_dec, "DMO codec for %4.4s may work with dll=%s",
00231 (char*)&p_dec->fmt_in.i_codec,
00232 decoders_table[i].psz_dll );
00233 break;
00234 }
00235 }
00236
00237 p_dec->p_sys = NULL;
00238 if( !decoders_table[i].i_fourcc ) return VLC_EGENERIC;
00239 #endif
00240
00241
00242 p_dec->pf_decode_video = (picture_t *(*)(decoder_t *, block_t **))
00243 DecodeBlock;
00244 p_dec->pf_decode_audio = (aout_buffer_t *(*)(decoder_t *, block_t **))
00245 DecodeBlock;
00246
00247 return VLC_SUCCESS;
00248 }
00249
00250
00251
00252
00253 static int DecOpen( vlc_object_t *p_this )
00254 {
00255 decoder_t *p_dec = (decoder_t*)p_this;
00256 decoder_sys_t *p_sys = NULL;
00257
00258 DMO_MEDIA_TYPE dmo_input_type, dmo_output_type;
00259 IMediaObject *p_dmo = NULL;
00260 HINSTANCE hmsdmo_dll = NULL;
00261
00262 VIDEOINFOHEADER *p_vih = NULL;
00263 WAVEFORMATEX *p_wf = NULL;
00264
00265 #ifdef LOADER
00266 ldt_fs_t *ldt_fs = Setup_LDT_Keeper();
00267 #else
00268
00269 CoInitialize( 0 );
00270 #endif
00271
00272 if( LoadDMO( p_this, &hmsdmo_dll, &p_dmo, &p_dec->fmt_in, VLC_FALSE )
00273 != VLC_SUCCESS )
00274 {
00275 hmsdmo_dll = 0;
00276 p_dmo = 0;
00277 goto error;
00278 }
00279
00280
00281 memset( &dmo_input_type, 0, sizeof(dmo_input_type) );
00282 dmo_input_type.pUnk = 0;
00283
00284 if( p_dec->fmt_in.i_cat == AUDIO_ES )
00285 {
00286 uint16_t i_tag;
00287 int i_size = sizeof(WAVEFORMATEX) + p_dec->fmt_in.i_extra;
00288 p_wf = malloc( i_size );
00289
00290 memset( p_wf, 0, sizeof(WAVEFORMATEX) );
00291 if( p_dec->fmt_in.i_extra )
00292 memcpy( &p_wf[1], p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra );
00293
00294 dmo_input_type.majortype = MEDIATYPE_Audio;
00295 dmo_input_type.subtype = dmo_input_type.majortype;
00296 dmo_input_type.subtype.Data1 = p_dec->fmt_in.i_codec;
00297 fourcc_to_wf_tag( p_dec->fmt_in.i_codec, &i_tag );
00298 if( i_tag ) dmo_input_type.subtype.Data1 = i_tag;
00299
00300 p_wf->wFormatTag = dmo_input_type.subtype.Data1;
00301 p_wf->nSamplesPerSec = p_dec->fmt_in.audio.i_rate;
00302 p_wf->nChannels = p_dec->fmt_in.audio.i_channels;
00303 p_wf->wBitsPerSample = p_dec->fmt_in.audio.i_bitspersample;
00304 p_wf->nBlockAlign = p_dec->fmt_in.audio.i_blockalign;
00305 p_wf->nAvgBytesPerSec = p_dec->fmt_in.i_bitrate / 8;
00306 p_wf->cbSize = p_dec->fmt_in.i_extra;
00307
00308 dmo_input_type.formattype = FORMAT_WaveFormatEx;
00309 dmo_input_type.cbFormat = i_size;
00310 dmo_input_type.pbFormat = (char *)p_wf;
00311 dmo_input_type.bFixedSizeSamples = 1;
00312 dmo_input_type.bTemporalCompression = 0;
00313 dmo_input_type.lSampleSize = p_wf->nBlockAlign;
00314 }
00315 else
00316 {
00317 BITMAPINFOHEADER *p_bih;
00318
00319 int i_size = sizeof(VIDEOINFOHEADER) + p_dec->fmt_in.i_extra;
00320 p_vih = malloc( i_size );
00321
00322 memset( p_vih, 0, sizeof(VIDEOINFOHEADER) );
00323 if( p_dec->fmt_in.i_extra )
00324 memcpy( &p_vih[1], p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra );
00325
00326 p_bih = &p_vih->bmiHeader;
00327 p_bih->biCompression = p_dec->fmt_in.i_codec;
00328 p_bih->biWidth = p_dec->fmt_in.video.i_width;
00329 p_bih->biHeight = p_dec->fmt_in.video.i_height;
00330 p_bih->biBitCount = p_dec->fmt_in.video.i_bits_per_pixel;
00331 p_bih->biPlanes = 1;
00332 p_bih->biSize = i_size - sizeof(VIDEOINFOHEADER) +
00333 sizeof(BITMAPINFOHEADER);
00334
00335 p_vih->rcSource.left = p_vih->rcSource.top = 0;
00336 p_vih->rcSource.right = p_dec->fmt_in.video.i_width;
00337 p_vih->rcSource.bottom = p_dec->fmt_in.video.i_height;
00338 p_vih->rcTarget = p_vih->rcSource;
00339
00340 dmo_input_type.majortype = MEDIATYPE_Video;
00341 dmo_input_type.subtype = dmo_input_type.majortype;
00342 dmo_input_type.subtype.Data1 = p_dec->fmt_in.i_codec;
00343 dmo_input_type.formattype = FORMAT_VideoInfo;
00344 dmo_input_type.bFixedSizeSamples = 0;
00345 dmo_input_type.bTemporalCompression = 1;
00346 dmo_input_type.cbFormat = i_size;
00347 dmo_input_type.pbFormat = (char *)p_vih;
00348 }
00349
00350 if( p_dmo->vt->SetInputType( p_dmo, 0, &dmo_input_type, 0 ) )
00351 {
00352 msg_Err( p_dec, "can't set DMO input type" );
00353 goto error;
00354 }
00355 msg_Dbg( p_dec, "DMO input type set" );
00356
00357
00358 memset( &dmo_output_type, 0, sizeof(dmo_output_type) );
00359 dmo_output_type.pUnk = 0;
00360
00361 if( p_dec->fmt_in.i_cat == AUDIO_ES )
00362 {
00363
00364 p_dec->fmt_out.i_codec = AOUT_FMT_S16_NE;
00365 p_dec->fmt_out.audio.i_rate = p_dec->fmt_in.audio.i_rate;
00366 p_dec->fmt_out.audio.i_channels = p_dec->fmt_in.audio.i_channels;
00367 p_dec->fmt_out.audio.i_bitspersample = 16;
00368 p_dec->fmt_out.audio.i_physical_channels =
00369 p_dec->fmt_out.audio.i_original_channels =
00370 pi_channels_maps[p_dec->fmt_out.audio.i_channels];
00371
00372 p_wf->wFormatTag = WAVE_FORMAT_PCM;
00373 p_wf->nSamplesPerSec = p_dec->fmt_out.audio.i_rate;
00374 p_wf->nChannels = p_dec->fmt_out.audio.i_channels;
00375 p_wf->wBitsPerSample = p_dec->fmt_out.audio.i_bitspersample;
00376 p_wf->nBlockAlign =
00377 p_wf->wBitsPerSample / 8 * p_wf->nChannels;
00378 p_wf->nAvgBytesPerSec =
00379 p_wf->nSamplesPerSec * p_wf->nBlockAlign;
00380 p_wf->cbSize = 0;
00381
00382 dmo_output_type.majortype = MEDIATYPE_Audio;
00383 dmo_output_type.formattype = FORMAT_WaveFormatEx;
00384 dmo_output_type.subtype = MEDIASUBTYPE_PCM;
00385 dmo_output_type.cbFormat = sizeof(WAVEFORMATEX);
00386 dmo_output_type.pbFormat = (char *)p_wf;
00387 dmo_output_type.bFixedSizeSamples = 1;
00388 dmo_output_type.bTemporalCompression = 0;
00389 dmo_output_type.lSampleSize = p_wf->nBlockAlign;
00390 }
00391 else
00392 {
00393 BITMAPINFOHEADER *p_bih;
00394 DMO_MEDIA_TYPE mt;
00395 unsigned i_chroma = VLC_FOURCC('Y','U','Y','2');
00396 int i_planes = 1, i_bpp = 16;
00397 int i = 0;
00398
00399
00400 while( !p_dmo->vt->GetOutputType( p_dmo, 0, i++, &mt ) )
00401 {
00402 if( mt.subtype.Data1 == VLC_FOURCC('Y','V','1','2') )
00403 {
00404 i_chroma = mt.subtype.Data1;
00405 i_planes = 3; i_bpp = 12;
00406 }
00407
00408 DMOFreeMediaType( &mt );
00409 }
00410
00411 p_dec->fmt_out.i_codec = i_chroma == VLC_FOURCC('Y','V','1','2') ?
00412 VLC_FOURCC('I','4','2','0') : i_chroma;
00413 p_dec->fmt_out.video.i_width = p_dec->fmt_in.video.i_width;
00414 p_dec->fmt_out.video.i_height = p_dec->fmt_in.video.i_height;
00415 p_dec->fmt_out.video.i_bits_per_pixel = i_bpp;
00416 p_dec->fmt_out.video.i_aspect = VOUT_ASPECT_FACTOR *
00417 p_dec->fmt_out.video.i_width / p_dec->fmt_out.video.i_height;
00418
00419 p_bih = &p_vih->bmiHeader;
00420 p_bih->biCompression = i_chroma;
00421 p_bih->biHeight *= -1;
00422 p_bih->biBitCount = p_dec->fmt_out.video.i_bits_per_pixel;
00423 p_bih->biSizeImage = p_dec->fmt_in.video.i_width *
00424 p_dec->fmt_in.video.i_height *
00425 (p_dec->fmt_in.video.i_bits_per_pixel + 7) / 8;
00426
00427 p_bih->biPlanes = i_planes;
00428 p_bih->biSize = sizeof(BITMAPINFOHEADER);
00429
00430 dmo_output_type.majortype = MEDIATYPE_Video;
00431 dmo_output_type.formattype = FORMAT_VideoInfo;
00432 dmo_output_type.subtype = dmo_output_type.majortype;
00433 dmo_output_type.subtype.Data1 = p_bih->biCompression;
00434 dmo_output_type.bFixedSizeSamples = VLC_TRUE;
00435 dmo_output_type.bTemporalCompression = 0;
00436 dmo_output_type.lSampleSize = p_bih->biSizeImage;
00437 dmo_output_type.cbFormat = sizeof(VIDEOINFOHEADER);
00438 dmo_output_type.pbFormat = (char *)p_vih;
00439 }
00440
00441 #ifdef DMO_DEBUG
00442
00443 if( p_dec->fmt_in.i_cat == VIDEO_ES )
00444 {
00445 int i = 0;
00446 DMO_MEDIA_TYPE mt;
00447
00448 while( !p_dmo->vt->GetOutputType( p_dmo, 0, i++, &mt ) )
00449 {
00450 msg_Dbg( p_dec, "available output chroma: %4.4s",
00451 (char *)&mt.subtype.Data1 );
00452 DMOFreeMediaType( &mt );
00453 }
00454 }
00455 #endif
00456
00457 if( p_dmo->vt->SetOutputType( p_dmo, 0, &dmo_output_type, 0 ) )
00458 {
00459 msg_Err( p_dec, "can't set DMO output type" );
00460 goto error;
00461 }
00462 msg_Dbg( p_dec, "DMO output type set" );
00463
00464
00465 if( ( p_dec->p_sys = p_sys =
00466 (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
00467 {
00468 msg_Err( p_dec, "out of memory" );
00469 goto error;
00470 }
00471
00472 p_sys->hmsdmo_dll = hmsdmo_dll;
00473 p_sys->p_dmo = p_dmo;
00474 #ifdef LOADER
00475 p_sys->ldt_fs = ldt_fs;
00476 #endif
00477
00478
00479 {
00480 uint32_t i_size, i_align;
00481
00482 p_sys->i_min_output = 0;
00483 if( p_dmo->vt->GetOutputSizeInfo( p_dmo, 0, &i_size, &i_align ) )
00484 {
00485 msg_Err( p_dec, "GetOutputSizeInfo() failed" );
00486 goto error;
00487 }
00488 else
00489 {
00490 msg_Dbg( p_dec, "GetOutputSizeInfo(): bytes %i, align %i",
00491 i_size, i_align );
00492 p_sys->i_min_output = i_size;
00493 p_sys->p_buffer = malloc( i_size );
00494 if( !p_sys->p_buffer ) goto error;
00495 }
00496 }
00497
00498
00499 p_dec->fmt_out.i_cat = p_dec->fmt_in.i_cat;
00500 if( p_dec->fmt_out.i_cat == AUDIO_ES )
00501 date_Init( &p_sys->end_date, p_dec->fmt_in.audio.i_rate, 1 );
00502 else
00503 date_Init( &p_sys->end_date, 25 , 1 );
00504
00505 if( p_vih ) free( p_vih );
00506 if( p_wf ) free( p_wf );
00507
00508 return VLC_SUCCESS;
00509
00510 error:
00511
00512 if( p_dmo ) p_dmo->vt->Release( (IUnknown *)p_dmo );
00513 if( hmsdmo_dll ) FreeLibrary( hmsdmo_dll );
00514
00515 #ifdef LOADER
00516 Restore_LDT_Keeper( ldt_fs );
00517 #else
00518
00519 CoUninitialize();
00520 #endif
00521
00522 if( p_vih ) free( p_vih );
00523 if( p_wf ) free( p_wf );
00524 if( p_sys ) free( p_sys );
00525
00526 return VLC_EGENERIC;
00527 }
00528
00529
00530
00531
00532 static int LoadDMO( vlc_object_t *p_this, HINSTANCE *p_hmsdmo_dll,
00533 IMediaObject **pp_dmo, es_format_t *p_fmt,
00534 vlc_bool_t b_out )
00535 {
00536 DMO_PARTIAL_MEDIATYPE dmo_partial_type;
00537 int i_err;
00538
00539 #ifndef LOADER
00540 long (STDCALL *OurDMOEnum)( const GUID *, uint32_t, uint32_t,
00541 const DMO_PARTIAL_MEDIATYPE *,
00542 uint32_t, const DMO_PARTIAL_MEDIATYPE *,
00543 IEnumDMO ** );
00544
00545 IEnumDMO *p_enum_dmo = NULL;
00546 WCHAR *psz_dmo_name;
00547 GUID clsid_dmo;
00548 uint32_t i_dummy;
00549 #endif
00550
00551 GETCLASS GetClass;
00552 IClassFactory *cFactory = NULL;
00553 IUnknown *cObject = NULL;
00554 const codec_dll *codecs_table = b_out ? encoders_table : decoders_table;
00555 int i_codec;
00556
00557
00558 if( p_fmt->i_cat == AUDIO_ES )
00559 {
00560 uint16_t i_tag;
00561 dmo_partial_type.type = MEDIATYPE_Audio;
00562 dmo_partial_type.subtype = dmo_partial_type.type;
00563 dmo_partial_type.subtype.Data1 = p_fmt->i_codec;
00564 fourcc_to_wf_tag( p_fmt->i_codec, &i_tag );
00565 if( i_tag ) dmo_partial_type.subtype.Data1 = i_tag;
00566 }
00567 else
00568 {
00569 dmo_partial_type.type = MEDIATYPE_Video;
00570 dmo_partial_type.subtype = dmo_partial_type.type;
00571 dmo_partial_type.subtype.Data1 = p_fmt->i_codec;
00572 }
00573
00574 #ifndef LOADER
00575
00576 *p_hmsdmo_dll = LoadLibrary( "msdmo.dll" );
00577 if( *p_hmsdmo_dll == NULL )
00578 {
00579 msg_Dbg( p_this, "failed loading msdmo.dll" );
00580 return VLC_EGENERIC;
00581 }
00582 OurDMOEnum = (void *)GetProcAddress( *p_hmsdmo_dll, "DMOEnum" );
00583 if( OurDMOEnum == NULL )
00584 {
00585 msg_Dbg( p_this, "GetProcAddress failed to find DMOEnum()" );
00586 FreeLibrary( *p_hmsdmo_dll );
00587 return VLC_EGENERIC;
00588 }
00589
00590 if( !b_out )
00591 {
00592 i_err = OurDMOEnum( &GUID_NULL, 1 ,
00593 1, &dmo_partial_type, 0, NULL, &p_enum_dmo );
00594 }
00595 else
00596 {
00597 i_err = OurDMOEnum( &GUID_NULL, 1 ,
00598 0, NULL, 1, &dmo_partial_type, &p_enum_dmo );
00599 }
00600 if( i_err )
00601 {
00602 FreeLibrary( *p_hmsdmo_dll );
00603
00604
00605 goto loader;
00606 }
00607
00608
00609 *pp_dmo = 0;
00610 while( ( S_OK == p_enum_dmo->vt->Next( p_enum_dmo, 1, &clsid_dmo,
00611 &psz_dmo_name, &i_dummy ) ) )
00612 {
00613 char psz_temp[MAX_PATH];
00614 wcstombs( psz_temp, psz_dmo_name, MAX_PATH );
00615 msg_Dbg( p_this, "found DMO: %s", psz_temp );
00616 CoTaskMemFree( psz_dmo_name );
00617
00618
00619 if( CoCreateInstance( &clsid_dmo, NULL, CLSCTX_INPROC,
00620 &IID_IMediaObject, (void **)pp_dmo ) )
00621 {
00622 msg_Warn( p_this, "can't create DMO: %s", psz_temp );
00623 *pp_dmo = 0;
00624 }
00625 else break;
00626 }
00627
00628 p_enum_dmo->vt->Release( (IUnknown *)p_enum_dmo );
00629
00630 if( !*pp_dmo )
00631 {
00632 FreeLibrary( *p_hmsdmo_dll );
00633
00634
00635 goto loader;
00636 }
00637
00638 return VLC_SUCCESS;
00639
00640 loader:
00641 #endif
00642
00643 for( i_codec = 0; codecs_table[i_codec].i_fourcc != 0; i_codec++ )
00644 {
00645 if( codecs_table[i_codec].i_fourcc == p_fmt->i_codec )
00646 break;
00647 }
00648 if( codecs_table[i_codec].i_fourcc == 0 )
00649 return VLC_EGENERIC;
00650
00651 *p_hmsdmo_dll = LoadLibrary( codecs_table[i_codec].psz_dll );
00652 if( *p_hmsdmo_dll == NULL )
00653 {
00654 msg_Dbg( p_this, "failed loading '%s'",
00655 codecs_table[i_codec].psz_dll );
00656 return VLC_EGENERIC;
00657 }
00658
00659 GetClass = (GETCLASS)GetProcAddress( *p_hmsdmo_dll, "DllGetClassObject" );
00660 if (!GetClass)
00661 {
00662 msg_Dbg( p_this, "GetProcAddress failed to find DllGetClassObject()" );
00663 FreeLibrary( *p_hmsdmo_dll );
00664 return VLC_EGENERIC;
00665 }
00666
00667 i_err = GetClass( codecs_table[i_codec].p_guid, &IID_IClassFactory,
00668 (void**)&cFactory );
00669 if( i_err || cFactory == NULL )
00670 {
00671 msg_Dbg( p_this, "no such class object" );
00672 FreeLibrary( *p_hmsdmo_dll );
00673 return VLC_EGENERIC;
00674 }
00675
00676 i_err = cFactory->vt->CreateInstance( cFactory, 0, &IID_IUnknown,
00677 (void**)&cObject );
00678 cFactory->vt->Release( (IUnknown*)cFactory );
00679 if( i_err || !cObject )
00680 {
00681 msg_Dbg( p_this, "class factory failure" );
00682 FreeLibrary( *p_hmsdmo_dll );
00683 return VLC_EGENERIC;
00684 }
00685 i_err = cObject->vt->QueryInterface( cObject, &IID_IMediaObject,
00686 (void**)pp_dmo );
00687 cObject->vt->Release( (IUnknown*)cObject );
00688 if( i_err || !*pp_dmo )
00689 {
00690 msg_Dbg( p_this, "QueryInterface failure" );
00691 FreeLibrary( *p_hmsdmo_dll );
00692 return VLC_EGENERIC;
00693 }
00694
00695 return VLC_SUCCESS;
00696 }
00697
00698
00699
00700
00701 void DecoderClose( vlc_object_t *p_this )
00702 {
00703 decoder_t *p_dec = (decoder_t*)p_this;
00704 decoder_sys_t *p_sys = p_dec->p_sys;
00705
00706 if( !p_sys ) return;
00707
00708 if( p_sys->p_dmo ) p_sys->p_dmo->vt->Release( (IUnknown *)p_sys->p_dmo );
00709 FreeLibrary( p_sys->hmsdmo_dll );
00710
00711 #ifdef LOADER
00712 #if 0
00713 Restore_LDT_Keeper( p_sys->ldt_fs );
00714 #endif
00715 #else
00716
00717 CoUninitialize();
00718 #endif
00719
00720 if( p_sys->p_buffer ) free( p_sys->p_buffer );
00721 free( p_sys );
00722 }
00723
00724
00725
00726
00727
00728
00729 static void *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
00730 {
00731 decoder_sys_t *p_sys = p_dec->p_sys;
00732 block_t *p_block;
00733 int i_result;
00734
00735 DMO_OUTPUT_DATA_BUFFER db;
00736 CMediaBuffer *p_out;
00737 block_t block_out;
00738 uint32_t i_status;
00739
00740 if( p_sys == NULL )
00741 {
00742 if( DecOpen( VLC_OBJECT(p_dec) ) )
00743 {
00744 msg_Err( p_dec, "DecOpen failed" );
00745 return NULL;
00746 }
00747 p_sys = p_dec->p_sys;
00748 }
00749
00750 if( !pp_block ) return NULL;
00751
00752 p_block = *pp_block;
00753
00754
00755 if( p_block && p_block->i_pts <= 0 ) p_block->i_pts = p_block->i_dts;
00756
00757
00758 if( p_block && p_block->i_pts > 0 &&
00759 p_block->i_pts != date_Get( &p_sys->end_date ) )
00760 {
00761 date_Set( &p_sys->end_date, p_block->i_pts );
00762 }
00763
00764 #if 0
00765 if( !date_Get( &p_sys->end_date ) )
00766 {
00767
00768 if( p_block ) block_Release( p_block );
00769 return NULL;
00770 }
00771 #endif
00772
00773
00774 if( p_block && p_block->i_buffer )
00775 {
00776 CMediaBuffer *p_in;
00777
00778 p_in = CMediaBufferCreate( p_block, p_block->i_buffer, VLC_TRUE );
00779
00780 i_result = p_sys->p_dmo->vt->ProcessInput( p_sys->p_dmo, 0,
00781 (IMediaBuffer *)p_in, DMO_INPUT_DATA_BUFFERF_SYNCPOINT,
00782 0, 0 );
00783
00784 p_in->vt->Release( (IUnknown *)p_in );
00785
00786 if( i_result == S_FALSE )
00787 {
00788
00789 #ifdef DMO_DEBUG
00790 msg_Dbg( p_dec, "ProcessInput(): no output generated" );
00791 #endif
00792 return NULL;
00793 }
00794 else if( i_result == (int)DMO_E_NOTACCEPTING )
00795 {
00796
00797 msg_Dbg( p_dec, "ProcessInput(): not accepting" );
00798 }
00799 else if( i_result != S_OK )
00800 {
00801 msg_Dbg( p_dec, "ProcessInput(): failed" );
00802 return NULL;
00803 }
00804 else
00805 {
00806
00807 *pp_block = 0;
00808 }
00809 }
00810 else if( p_block && !p_block->i_buffer )
00811 {
00812 block_Release( p_block );
00813 *pp_block = 0;
00814 }
00815
00816
00817 block_out.p_buffer = p_sys->p_buffer;
00818 block_out.i_buffer = 0;
00819
00820 p_out = CMediaBufferCreate( &block_out, p_sys->i_min_output, VLC_FALSE );
00821 memset( &db, 0, sizeof(db) );
00822 db.pBuffer = (IMediaBuffer *)p_out;
00823
00824 i_result = p_sys->p_dmo->vt->ProcessOutput( p_sys->p_dmo,
00825 DMO_PROCESS_OUTPUT_DISCARD_WHEN_NO_BUFFER,
00826 1, &db, &i_status );
00827
00828 if( i_result != S_OK )
00829 {
00830 if( i_result != S_FALSE )
00831 msg_Dbg( p_dec, "ProcessOutput(): failed" );
00832 #if DMO_DEBUG
00833 else
00834 msg_Dbg( p_dec, "ProcessOutput(): no output" );
00835 #endif
00836
00837 p_out->vt->Release( (IUnknown *)p_out );
00838 return NULL;
00839 }
00840
00841 #if DMO_DEBUG
00842 msg_Dbg( p_dec, "ProcessOutput(): success" );
00843 #endif
00844
00845 if( !block_out.i_buffer )
00846 {
00847 #if DMO_DEBUG
00848 msg_Dbg( p_dec, "ProcessOutput(): no output (i_buffer_out == 0)" );
00849 #endif
00850 p_out->vt->Release( (IUnknown *)p_out );
00851 return NULL;
00852 }
00853
00854 if( p_dec->fmt_out.i_cat == VIDEO_ES )
00855 {
00856
00857 picture_t *p_pic = p_dec->pf_vout_buffer_new( p_dec );
00858 if( !p_pic ) return NULL;
00859
00860 CopyPicture( p_dec, p_pic, block_out.p_buffer );
00861
00862
00863 p_pic->date = date_Get( &p_sys->end_date );
00864 date_Increment( &p_sys->end_date, 1 );
00865
00866 p_out->vt->Release( (IUnknown *)p_out );
00867
00868 return p_pic;
00869 }
00870 else
00871 {
00872 aout_buffer_t *p_aout_buffer;
00873 int i_samples = block_out.i_buffer /
00874 ( p_dec->fmt_out.audio.i_bitspersample *
00875 p_dec->fmt_out.audio.i_channels / 8 );
00876
00877 p_aout_buffer = p_dec->pf_aout_buffer_new( p_dec, i_samples );
00878 memcpy( p_aout_buffer->p_buffer,
00879 block_out.p_buffer, block_out.i_buffer );
00880
00881
00882 p_aout_buffer->start_date = date_Get( &p_sys->end_date );
00883 p_aout_buffer->end_date =
00884 date_Increment( &p_sys->end_date, i_samples );
00885
00886 p_out->vt->Release( (IUnknown *)p_out );
00887
00888 return p_aout_buffer;
00889 }
00890
00891 return NULL;
00892 }
00893
00894 static void CopyPicture( decoder_t *p_dec, picture_t *p_pic, uint8_t *p_in )
00895 {
00896 int i_plane, i_line, i_width, i_dst_stride;
00897 uint8_t *p_dst, *p_src = p_in;
00898
00899 p_dst = p_pic->p[1].p_pixels;
00900 p_pic->p[1].p_pixels = p_pic->p[2].p_pixels;
00901 p_pic->p[2].p_pixels = p_dst;
00902
00903 for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ )
00904 {
00905 p_dst = p_pic->p[i_plane].p_pixels;
00906 i_width = p_pic->p[i_plane].i_visible_pitch;
00907 i_dst_stride = p_pic->p[i_plane].i_pitch;
00908
00909 for( i_line = 0; i_line < p_pic->p[i_plane].i_visible_lines; i_line++ )
00910 {
00911 p_dec->p_vlc->pf_memcpy( p_dst, p_src, i_width );
00912 p_src += i_width;
00913 p_dst += i_dst_stride;
00914 }
00915 }
00916
00917 p_dst = p_pic->p[1].p_pixels;
00918 p_pic->p[1].p_pixels = p_pic->p[2].p_pixels;
00919 p_pic->p[2].p_pixels = p_dst;
00920 }
00921
00922
00923
00924
00925 struct encoder_sys_t
00926 {
00927 HINSTANCE hmsdmo_dll;
00928 IMediaObject *p_dmo;
00929
00930 int i_min_output;
00931
00932 date_t end_date;
00933
00934 #ifdef LOADER
00935 ldt_fs_t *ldt_fs;
00936 #endif
00937 };
00938
00939
00940
00941
00942 static int EncoderOpen( vlc_object_t *p_this )
00943 {
00944 encoder_t *p_enc = (encoder_t*)p_this;
00945
00946 #ifndef LOADER
00947 int i_ret = EncOpen( p_this );
00948 if( i_ret != VLC_SUCCESS ) return i_ret;
00949
00950 #else
00951
00952
00953 int i;
00954
00955
00956 for( i = 0; encoders_table[i].i_fourcc != 0; i++ )
00957 {
00958 if( encoders_table[i].i_fourcc == p_enc->fmt_out.i_codec )
00959 {
00960 msg_Dbg( p_enc, "DMO codec for %4.4s may work with dll=%s",
00961 (char*)&p_enc->fmt_out.i_codec,
00962 encoders_table[i].psz_dll );
00963 break;
00964 }
00965 }
00966
00967 p_enc->p_sys = NULL;
00968 if( !encoders_table[i].i_fourcc ) return VLC_EGENERIC;
00969 #endif
00970
00971
00972 p_enc->pf_encode_video = (block_t *(*)(encoder_t *, picture_t *))
00973 EncodeBlock;
00974 p_enc->pf_encode_audio = (block_t *(*)(encoder_t *, aout_buffer_t *))
00975 EncodeBlock;
00976
00977 return VLC_SUCCESS;
00978 }
00979
00980
00981
00982
00983 static int EncoderSetVideoType( encoder_t *p_enc, IMediaObject *p_dmo )
00984 {
00985 int i, i_selected, i_err;
00986 DMO_MEDIA_TYPE dmo_type;
00987 VIDEOINFOHEADER vih, *p_vih;
00988 BITMAPINFOHEADER *p_bih;
00989
00990
00991 p_enc->fmt_in.video.i_bits_per_pixel =
00992 p_enc->fmt_out.video.i_bits_per_pixel = 12;
00993
00994
00995 i = 0;
00996 while( !p_dmo->vt->GetInputType( p_dmo, 0, i++, &dmo_type ) )
00997 {
00998 p_vih = (VIDEOINFOHEADER *)dmo_type.pbFormat;
00999
01000 msg_Dbg( p_enc, "available input chroma: %4.4s",
01001 (char *)&dmo_type.subtype.Data1 );
01002 if( !memcmp( &dmo_type.subtype, &MEDIASUBTYPE_RGB565, 16 ) )
01003 msg_Dbg( p_enc, "-> MEDIASUBTYPE_RGB565" );
01004 if( !memcmp( &dmo_type.subtype, &MEDIASUBTYPE_RGB24, 16 ) )
01005 msg_Dbg( p_enc, "-> MEDIASUBTYPE_RGB24" );
01006
01007 DMOFreeMediaType( &dmo_type );
01008 }
01009
01010
01011 memset( &dmo_type, 0, sizeof(dmo_type) );
01012 dmo_type.pUnk = 0;
01013 memset( &vih, 0, sizeof(VIDEOINFOHEADER) );
01014
01015 p_bih = &vih.bmiHeader;
01016 p_bih->biCompression = VLC_FOURCC('I','4','2','0');
01017 p_bih->biWidth = p_enc->fmt_in.video.i_width;
01018 p_bih->biHeight = p_enc->fmt_in.video.i_height;
01019 p_bih->biBitCount = p_enc->fmt_in.video.i_bits_per_pixel;
01020 p_bih->biSizeImage = p_enc->fmt_in.video.i_width *
01021 p_enc->fmt_in.video.i_height * p_enc->fmt_in.video.i_bits_per_pixel /8;
01022 p_bih->biPlanes = 3;
01023 p_bih->biSize = sizeof(BITMAPINFOHEADER);
01024
01025 vih.rcSource.left = vih.rcSource.top = 0;
01026 vih.rcSource.right = p_enc->fmt_in.video.i_width;
01027 vih.rcSource.bottom = p_enc->fmt_in.video.i_height;
01028 vih.rcTarget = vih.rcSource;
01029
01030 vih.AvgTimePerFrame = I64C(10000000) / 25;
01031
01032 dmo_type.majortype = MEDIATYPE_Video;
01033
01034 dmo_type.subtype = MEDIASUBTYPE_I420;
01035
01036 dmo_type.formattype = FORMAT_VideoInfo;
01037 dmo_type.bFixedSizeSamples = TRUE;
01038 dmo_type.bTemporalCompression = FALSE;
01039 dmo_type.lSampleSize = p_bih->biSizeImage;
01040 dmo_type.cbFormat = sizeof(VIDEOINFOHEADER);
01041 dmo_type.pbFormat = (char *)&vih;
01042
01043 if( ( i_err = p_dmo->vt->SetInputType( p_dmo, 0, &dmo_type, 0 ) ) )
01044 {
01045 msg_Err( p_enc, "can't set DMO input type: %x", i_err );
01046 return VLC_EGENERIC;
01047 }
01048
01049 msg_Dbg( p_enc, "successfully set input type" );
01050
01051
01052 memset( &dmo_type, 0, sizeof(dmo_type) );
01053 dmo_type.pUnk = 0;
01054
01055
01056 i = 0, i_selected = -1;
01057 while( !p_dmo->vt->GetOutputType( p_dmo, 0, i++, &dmo_type ) )
01058 {
01059 p_vih = (VIDEOINFOHEADER *)dmo_type.pbFormat;
01060
01061 msg_Dbg( p_enc, "available output codec: %4.4s",
01062 (char *)&dmo_type.subtype.Data1 );
01063
01064 if( p_vih->bmiHeader.biCompression == p_enc->fmt_out.i_codec )
01065 i_selected = i - 1;
01066
01067 DMOFreeMediaType( &dmo_type );
01068 }
01069
01070 if( i_selected < 0 )
01071 {
01072 msg_Err( p_enc, "couldn't find codec: %4.4s",
01073 (char *)&p_enc->fmt_out.i_codec );
01074 return VLC_EGENERIC;
01075 }
01076
01077 p_dmo->vt->GetOutputType( p_dmo, 0, i_selected, &dmo_type );
01078 ((VIDEOINFOHEADER *)dmo_type.pbFormat)->dwBitRate =
01079 p_enc->fmt_out.i_bitrate;
01080
01081
01082 while( 1 )
01083 {
01084 IWMCodecPrivateData *p_privdata;
01085 VIDEOINFOHEADER *p_vih;
01086 uint8_t *p_data = 0;
01087 uint32_t i_data = 0, i_vih;
01088
01089 i_err = p_dmo->vt->QueryInterface( (IUnknown *)p_dmo,
01090 &IID_IWMCodecPrivateData,
01091 (void **)&p_privdata );
01092 if( i_err ) break;
01093
01094 i_err = p_privdata->vt->SetPartialOutputType( p_privdata, &dmo_type );
01095 if( i_err )
01096 {
01097 msg_Err( p_enc, "SetPartialOutputType() failed" );
01098 p_privdata->vt->Release( (IUnknown *)p_privdata );
01099 break;
01100 }
01101
01102 i_err = p_privdata->vt->GetPrivateData( p_privdata, NULL, &i_data );
01103 if( i_err )
01104 {
01105 msg_Err( p_enc, "GetPrivateData() failed" );
01106 p_privdata->vt->Release( (IUnknown *)p_privdata );
01107 break;
01108 }
01109
01110 p_data = malloc( i_data );
01111 i_err = p_privdata->vt->GetPrivateData( p_privdata, p_data, &i_data );
01112
01113
01114 i_vih = dmo_type.cbFormat + i_data;
01115 p_vih = CoTaskMemAlloc( i_vih );
01116 memcpy( p_vih, dmo_type.pbFormat, dmo_type.cbFormat );
01117 memcpy( ((uint8_t *)p_vih) + dmo_type.cbFormat, p_data, i_data );
01118 DMOFreeMediaType( &dmo_type );
01119 dmo_type.pbFormat = (char*)p_vih;
01120 dmo_type.cbFormat = i_vih;
01121
01122 msg_Dbg( p_enc, "found extra data: %i", i_data );
01123 p_enc->fmt_out.i_extra = i_data;
01124 p_enc->fmt_out.p_extra = p_data;
01125 break;
01126 }
01127
01128 i_err = p_dmo->vt->SetOutputType( p_dmo, 0, &dmo_type, 0 );
01129
01130 p_vih = (VIDEOINFOHEADER *)dmo_type.pbFormat;
01131 p_enc->fmt_in.i_codec = VLC_FOURCC('I','4','2','0');
01132
01133 DMOFreeMediaType( &dmo_type );
01134 if( i_err )
01135 {
01136 msg_Err( p_enc, "can't set DMO output type: %i", i_err );
01137 return VLC_EGENERIC;
01138 }
01139
01140 msg_Dbg( p_enc, "successfully set output type" );
01141 return VLC_SUCCESS;
01142 }
01143
01144
01145
01146
01147 static int EncoderSetAudioType( encoder_t *p_enc, IMediaObject *p_dmo )
01148 {
01149 int i, i_selected, i_err;
01150 unsigned int i_last_byterate;
01151 uint16_t i_tag;
01152 DMO_MEDIA_TYPE dmo_type;
01153 WAVEFORMATEX *p_wf;
01154
01155
01156 fourcc_to_wf_tag( p_enc->fmt_out.i_codec, &i_tag );
01157 if( i_tag == 0 ) return VLC_EGENERIC;
01158
01159 p_enc->fmt_in.i_codec = AOUT_FMT_S16_NE;
01160 p_enc->fmt_in.audio.i_bitspersample = 16;
01161
01162
01163
01164 i = 0; i_selected = -1; i_last_byterate = 0;
01165 while( !p_dmo->vt->GetOutputType( p_dmo, 0, i++, &dmo_type ) )
01166 {
01167 p_wf = (WAVEFORMATEX *)dmo_type.pbFormat;
01168 msg_Dbg( p_enc, "available format :%i, sample rate: %i, channels: %i, "
01169 "bits per sample: %i, bitrate: %i, blockalign: %i",
01170 (int) p_wf->wFormatTag, (int)p_wf->nSamplesPerSec,
01171 (int)p_wf->nChannels, (int)p_wf->wBitsPerSample,
01172 (int)p_wf->nAvgBytesPerSec * 8, (int)p_wf->nBlockAlign );
01173
01174 if( p_wf->wFormatTag == i_tag &&
01175 p_wf->nSamplesPerSec == p_enc->fmt_in.audio.i_rate &&
01176 p_wf->nChannels == p_enc->fmt_in.audio.i_channels &&
01177 p_wf->wBitsPerSample == p_enc->fmt_in.audio.i_bitspersample )
01178 {
01179 if( (int)p_wf->nAvgBytesPerSec <
01180 p_enc->fmt_out.i_bitrate * 110 / 800 &&
01181 p_wf->nAvgBytesPerSec > i_last_byterate )
01182 {
01183 i_selected = i - 1;
01184 i_last_byterate = p_wf->nAvgBytesPerSec;
01185 msg_Dbg( p_enc, "selected entry %i (bitrate: %i)",
01186 i_selected, p_wf->nAvgBytesPerSec * 8 );
01187 }
01188 }
01189
01190 DMOFreeMediaType( &dmo_type );
01191 }
01192
01193 if( i_selected < 0 )
01194 {
01195 msg_Err( p_enc, "couldn't find a matching ouput" );
01196 return VLC_EGENERIC;
01197 }
01198
01199 p_dmo->vt->GetOutputType( p_dmo, 0, i_selected, &dmo_type );
01200 p_wf = (WAVEFORMATEX *)dmo_type.pbFormat;
01201
01202 msg_Dbg( p_enc, "selected format: %i, sample rate:%i, "
01203 "channels: %i, bits per sample: %i, bitrate: %i, blockalign: %i",
01204 (int)p_wf->wFormatTag, (int)p_wf->nSamplesPerSec,
01205 (int)p_wf->nChannels, (int)p_wf->wBitsPerSample,
01206 (int)p_wf->nAvgBytesPerSec * 8, (int)p_wf->nBlockAlign );
01207
01208 p_enc->fmt_out.audio.i_rate = p_wf->nSamplesPerSec;
01209 p_enc->fmt_out.audio.i_channels = p_wf->nChannels;
01210 p_enc->fmt_out.audio.i_bitspersample = p_wf->wBitsPerSample;
01211 p_enc->fmt_out.audio.i_blockalign = p_wf->nBlockAlign;
01212 p_enc->fmt_out.i_bitrate = p_wf->nAvgBytesPerSec * 8;
01213
01214 if( p_wf->cbSize )
01215 {
01216 msg_Dbg( p_enc, "found cbSize: %i", p_wf->cbSize );
01217 p_enc->fmt_out.i_extra = p_wf->cbSize;
01218 p_enc->fmt_out.p_extra = malloc( p_enc->fmt_out.i_extra );
01219 memcpy( p_enc->fmt_out.p_extra, &p_wf[1], p_enc->fmt_out.i_extra );
01220 }
01221
01222 i_err = p_dmo->vt->SetOutputType( p_dmo, 0, &dmo_type, 0 );
01223 DMOFreeMediaType( &dmo_type );
01224
01225 if( i_err )
01226 {
01227 msg_Err( p_enc, "can't set DMO output type: %i", i_err );
01228 return VLC_EGENERIC;
01229 }
01230
01231 msg_Dbg( p_enc, "successfully set output type" );
01232
01233
01234 i = 0; i_selected = -1;
01235 while( !p_dmo->vt->GetInputType( p_dmo, 0, i++, &dmo_type ) )
01236 {
01237 p_wf = (WAVEFORMATEX *)dmo_type.pbFormat;
01238 msg_Dbg( p_enc, "available format :%i, sample rate: %i, channels: %i, "
01239 "bits per sample: %i, bitrate: %i, blockalign: %i",
01240 (int) p_wf->wFormatTag, (int)p_wf->nSamplesPerSec,
01241 (int)p_wf->nChannels, (int)p_wf->wBitsPerSample,
01242 (int)p_wf->nAvgBytesPerSec * 8, (int)p_wf->nBlockAlign );
01243
01244 if( p_wf->wFormatTag == WAVE_FORMAT_PCM &&
01245 p_wf->nSamplesPerSec == p_enc->fmt_in.audio.i_rate &&
01246 p_wf->nChannels == p_enc->fmt_in.audio.i_channels &&
01247 p_wf->wBitsPerSample == p_enc->fmt_in.audio.i_bitspersample )
01248 {
01249 i_selected = i - 1;
01250 }
01251
01252 DMOFreeMediaType( &dmo_type );
01253 }
01254
01255 if( i_selected < 0 )
01256 {
01257 msg_Err( p_enc, "couldn't find a matching input" );
01258 return VLC_EGENERIC;
01259 }
01260
01261 p_dmo->vt->GetInputType( p_dmo, 0, i_selected, &dmo_type );
01262 i_err = p_dmo->vt->SetInputType( p_dmo, 0, &dmo_type, 0 );
01263 DMOFreeMediaType( &dmo_type );
01264 if( i_err )
01265 {
01266 msg_Err( p_enc, "can't set DMO input type: %x", i_err );
01267 return VLC_EGENERIC;
01268 }
01269 msg_Dbg( p_enc, "successfully set input type" );
01270
01271 return VLC_SUCCESS;
01272 }
01273
01274
01275
01276
01277 static int EncOpen( vlc_object_t *p_this )
01278 {
01279 encoder_t *p_enc = (encoder_t*)p_this;
01280 encoder_sys_t *p_sys = NULL;
01281 IMediaObject *p_dmo = NULL;
01282 HINSTANCE hmsdmo_dll = NULL;
01283
01284 #ifdef LOADER
01285 ldt_fs_t *ldt_fs = Setup_LDT_Keeper();
01286 #else
01287
01288 CoInitialize( 0 );
01289 #endif
01290
01291 if( LoadDMO( p_this, &hmsdmo_dll, &p_dmo, &p_enc->fmt_out, VLC_TRUE )
01292 != VLC_SUCCESS )
01293 {
01294 hmsdmo_dll = 0;
01295 p_dmo = 0;
01296 goto error;
01297 }
01298
01299 if( p_enc->fmt_in.i_cat == VIDEO_ES )
01300 {
01301 if( EncoderSetVideoType( p_enc, p_dmo ) != VLC_SUCCESS ) goto error;
01302 }
01303 else
01304 {
01305 if( EncoderSetAudioType( p_enc, p_dmo ) != VLC_SUCCESS ) goto error;
01306 }
01307
01308
01309 if( ( p_enc->p_sys = p_sys =
01310 (encoder_sys_t *)malloc(sizeof(encoder_sys_t)) ) == NULL )
01311 {
01312 msg_Err( p_enc, "out of memory" );
01313 goto error;
01314 }
01315
01316 p_sys->hmsdmo_dll = hmsdmo_dll;
01317 p_sys->p_dmo = p_dmo;
01318 #ifdef LOADER
01319 p_sys->ldt_fs = ldt_fs;
01320 #endif
01321
01322
01323 {
01324 uint32_t i_size, i_align, dum;
01325
01326 if( p_dmo->vt->GetInputSizeInfo( p_dmo, 0, &i_size, &i_align, &dum ) )
01327 msg_Err( p_enc, "GetInputSizeInfo() failed" );
01328 else
01329 msg_Dbg( p_enc, "GetInputSizeInfo(): bytes %i, align %i, %i",
01330 i_size, i_align, dum );
01331 }
01332
01333
01334 {
01335 uint32_t i_size, i_align;
01336
01337 p_sys->i_min_output = 0;
01338 if( p_dmo->vt->GetOutputSizeInfo( p_dmo, 0, &i_size, &i_align ) )
01339 {
01340 msg_Err( p_enc, "GetOutputSizeInfo() failed" );
01341 goto error;
01342 }
01343 else
01344 {
01345 msg_Dbg( p_enc, "GetOutputSizeInfo(): bytes %i, align %i",
01346 i_size, i_align );
01347 p_sys->i_min_output = i_size;
01348 }
01349 }
01350
01351
01352 p_enc->fmt_out.i_cat = p_enc->fmt_out.i_cat;
01353 if( p_enc->fmt_out.i_cat == AUDIO_ES )
01354 date_Init( &p_sys->end_date, p_enc->fmt_out.audio.i_rate, 1 );
01355 else
01356 date_Init( &p_sys->end_date, 25 , 1 );
01357
01358 return VLC_SUCCESS;
01359
01360 error:
01361
01362 if( p_dmo ) p_dmo->vt->Release( (IUnknown *)p_dmo );
01363 if( hmsdmo_dll ) FreeLibrary( hmsdmo_dll );
01364
01365 #ifdef LOADER
01366 Restore_LDT_Keeper( ldt_fs );
01367 #else
01368
01369 CoUninitialize();
01370 #endif
01371
01372 if( p_sys ) free( p_sys );
01373
01374 return VLC_EGENERIC;
01375 }
01376
01377
01378
01379
01380 static block_t *EncodeBlock( encoder_t *p_enc, void *p_data )
01381 {
01382 encoder_sys_t *p_sys = p_enc->p_sys;
01383 CMediaBuffer *p_in;
01384 block_t *p_chain = NULL;
01385 block_t *p_block_in;
01386 uint32_t i_status;
01387 int i_result;
01388 mtime_t i_pts;
01389
01390 if( p_sys == NULL )
01391 {
01392 if( EncOpen( VLC_OBJECT(p_enc) ) )
01393 {
01394 msg_Err( p_enc, "EncOpen failed" );
01395 return NULL;
01396 }
01397 p_sys = p_enc->p_sys;
01398 }
01399
01400 if( !p_data ) return NULL;
01401
01402 if( p_enc->fmt_out.i_cat == VIDEO_ES )
01403 {
01404
01405 int i_plane, i_line, i_width, i_src_stride;
01406 picture_t *p_pic = (picture_t *)p_data;
01407 uint8_t *p_dst;
01408
01409 int i_buffer = p_enc->fmt_in.video.i_width *
01410 p_enc->fmt_in.video.i_height *
01411 p_enc->fmt_in.video.i_bits_per_pixel / 8;
01412
01413 p_block_in = block_New( p_enc, i_buffer );
01414
01415
01416 p_dst = p_block_in->p_buffer;
01417 for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ )
01418 {
01419 uint8_t *p_src = p_pic->p[i_plane].p_pixels;
01420 i_width = p_pic->p[i_plane].i_visible_pitch;
01421 i_src_stride = p_pic->p[i_plane].i_pitch;
01422
01423 for( i_line = 0; i_line < p_pic->p[i_plane].i_visible_lines;
01424 i_line++ )
01425 {
01426 p_enc->p_vlc->pf_memcpy( p_dst, p_src, i_width );
01427 p_dst += i_width;
01428 p_src += i_src_stride;
01429 }
01430 }
01431
01432 i_pts = p_pic->date;
01433 }
01434 else
01435 {
01436 aout_buffer_t *p_aout_buffer = (aout_buffer_t *)p_data;
01437 p_block_in = block_New( p_enc, p_aout_buffer->i_nb_bytes );
01438 memcpy( p_block_in->p_buffer, p_aout_buffer->p_buffer,
01439 p_block_in->i_buffer );
01440
01441 i_pts = p_aout_buffer->start_date;
01442 }
01443
01444
01445 p_in = CMediaBufferCreate( p_block_in, p_block_in->i_buffer, VLC_TRUE );
01446 i_result = p_sys->p_dmo->vt->ProcessInput( p_sys->p_dmo, 0,
01447 (IMediaBuffer *)p_in, DMO_INPUT_DATA_BUFFERF_TIME, i_pts * 10, 0 );
01448
01449 p_in->vt->Release( (IUnknown *)p_in );
01450 if( i_result == S_FALSE )
01451 {
01452
01453 #ifdef DMO_DEBUG
01454 msg_Dbg( p_enc, "ProcessInput(): no output generated "I64Fd, i_pts );
01455 #endif
01456 return NULL;
01457 }
01458 else if( i_result == (int)DMO_E_NOTACCEPTING )
01459 {
01460
01461 msg_Dbg( p_enc, "ProcessInput(): not accepting" );
01462 }
01463 else if( i_result != S_OK )
01464 {
01465 msg_Dbg( p_enc, "ProcessInput(): failed: %x", i_result );
01466 return NULL;
01467 }
01468
01469 #if DMO_DEBUG
01470 msg_Dbg( p_enc, "ProcessInput(): success" );
01471 #endif
01472
01473
01474 while( 1 )
01475 {
01476 DMO_OUTPUT_DATA_BUFFER db;
01477 block_t *p_block_out;
01478 CMediaBuffer *p_out;
01479
01480 p_block_out = block_New( p_enc, p_sys->i_min_output );
01481 p_block_out->i_buffer = 0;
01482 p_out = CMediaBufferCreate(p_block_out, p_sys->i_min_output, VLC_FALSE);
01483 memset( &db, 0, sizeof(db) );
01484 db.pBuffer = (IMediaBuffer *)p_out;
01485
01486 i_result = p_sys->p_dmo->vt->ProcessOutput( p_sys->p_dmo,
01487 0, 1, &db, &i_status );
01488
01489 if( i_result != S_OK )
01490 {
01491 if( i_result != S_FALSE )
01492 msg_Dbg( p_enc, "ProcessOutput(): failed: %x", i_result );
01493 #if DMO_DEBUG
01494 else
01495 msg_Dbg( p_enc, "ProcessOutput(): no output" );
01496 #endif
01497
01498 p_out->vt->Release( (IUnknown *)p_out );
01499 block_Release( p_block_out );
01500 return p_chain;
01501 }
01502
01503 if( !p_block_out->i_buffer )
01504 {
01505 #if DMO_DEBUG
01506 msg_Dbg( p_enc, "ProcessOutput(): no output (i_buffer_out == 0)" );
01507 #endif
01508 p_out->vt->Release( (IUnknown *)p_out );
01509 block_Release( p_block_out );
01510 return p_chain;
01511 }
01512
01513 if( db.dwStatus & DMO_OUTPUT_DATA_BUFFERF_TIME )
01514 {
01515 #if DMO_DEBUG
01516 msg_Dbg( p_enc, "ProcessOutput(): pts: "I64Fd", "I64Fd,
01517 i_pts, db.rtTimestamp / 10 );
01518 #endif
01519 i_pts = db.rtTimestamp / 10;
01520 }
01521
01522 if( db.dwStatus & DMO_OUTPUT_DATA_BUFFERF_TIMELENGTH )
01523 {
01524 p_block_out->i_length = db.rtTimelength / 10;
01525 #if DMO_DEBUG
01526 msg_Dbg( p_enc, "ProcessOutput(): length: "I64Fd,
01527 p_block_out->i_length );
01528 #endif
01529 }
01530
01531 if( p_enc->fmt_out.i_cat == VIDEO_ES )
01532 {
01533 if( db.dwStatus & DMO_OUTPUT_DATA_BUFFERF_SYNCPOINT )
01534 p_block_out->i_flags |= BLOCK_FLAG_TYPE_I;
01535 else
01536 p_block_out->i_flags |= BLOCK_FLAG_TYPE_P;
01537 }
01538
01539 p_block_out->i_dts = p_block_out->i_pts = i_pts;
01540 block_ChainAppend( &p_chain, p_block_out );
01541 }
01542 }
01543
01544
01545
01546
01547 void EncoderClose( vlc_object_t *p_this )
01548 {
01549 encoder_t *p_enc = (encoder_t*)p_this;
01550 encoder_sys_t *p_sys = p_enc->p_sys;
01551
01552 if( !p_sys ) return;
01553
01554 if( p_sys->p_dmo ) p_sys->p_dmo->vt->Release( (IUnknown *)p_sys->p_dmo );
01555 FreeLibrary( p_sys->hmsdmo_dll );
01556
01557 #ifdef LOADER
01558 #if 0
01559 Restore_LDT_Keeper( p_sys->ldt_fs );
01560 #endif
01561 #else
01562
01563 CoUninitialize();
01564 #endif
01565
01566 free( p_sys );
01567 }