📄 dmo.c
字号:
DMO_MEDIA_TYPE mt; int i_chroma = VLC_FOURCC('Y','U','Y','2'), i_planes = 1, i_bpp = 16; int i = 0; /* Find out which chroma to use */ while( !p_dmo->vt->GetOutputType( p_dmo, 0, i++, &mt ) ) { if( mt.subtype.Data1 == VLC_FOURCC('Y','V','1','2') ) { i_chroma = mt.subtype.Data1; i_planes = 3; i_bpp = 12; } DMOFreeMediaType( &mt ); } p_dec->fmt_out.i_codec = i_chroma == VLC_FOURCC('Y','V','1','2') ? VLC_FOURCC('I','4','2','0') : i_chroma; p_dec->fmt_out.video.i_width = p_dec->fmt_in.video.i_width; p_dec->fmt_out.video.i_height = p_dec->fmt_in.video.i_height; p_dec->fmt_out.video.i_bits_per_pixel = i_bpp; p_dec->fmt_out.video.i_aspect = VOUT_ASPECT_FACTOR * p_dec->fmt_out.video.i_width / p_dec->fmt_out.video.i_height; p_bih = &p_vih->bmiHeader; p_bih->biCompression = i_chroma; p_bih->biHeight *= -1; p_bih->biBitCount = p_dec->fmt_out.video.i_bits_per_pixel; p_bih->biSizeImage = p_dec->fmt_in.video.i_width * p_dec->fmt_in.video.i_height * (p_dec->fmt_in.video.i_bits_per_pixel + 7) / 8; p_bih->biPlanes = i_planes; p_bih->biSize = sizeof(BITMAPINFOHEADER); dmo_output_type.majortype = MEDIATYPE_Video; dmo_output_type.formattype = FORMAT_VideoInfo; dmo_output_type.subtype = dmo_output_type.majortype; dmo_output_type.subtype.Data1 = p_bih->biCompression; dmo_output_type.bFixedSizeSamples = VLC_TRUE; dmo_output_type.bTemporalCompression = 0; dmo_output_type.lSampleSize = p_bih->biSizeImage; dmo_output_type.cbFormat = sizeof(VIDEOINFOHEADER); dmo_output_type.pbFormat = (char *)p_vih; }#ifdef DMO_DEBUG /* Enumerate output types */ if( p_dec->fmt_in.i_cat == VIDEO_ES ) { int i = 0; DMO_MEDIA_TYPE mt; while( !p_dmo->vt->GetOutputType( p_dmo, 0, i++, &mt ) ) { msg_Dbg( p_dec, "available output chroma: %4.4s", (char *)&mt.subtype.Data1 ); DMOFreeMediaType( &mt ); } }#endif if( p_dmo->vt->SetOutputType( p_dmo, 0, &dmo_output_type, 0 ) ) { msg_Err( p_dec, "can't set DMO output type" ); goto error; } msg_Dbg( p_dec, "DMO output type set" ); /* Allocate the memory needed to store the decoder's structure */ if( ( p_dec->p_sys = p_sys = (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL ) { msg_Err( p_dec, "out of memory" ); goto error; } p_sys->hmsdmo_dll = hmsdmo_dll; p_sys->p_dmo = p_dmo;#ifdef LOADER p_sys->ldt_fs = ldt_fs;#endif /* Find out some properties of the output */ { uint32_t i_size, i_align; p_sys->i_min_output = 0; if( p_dmo->vt->GetOutputSizeInfo( p_dmo, 0, &i_size, &i_align ) ) { msg_Err( p_dec, "GetOutputSizeInfo() failed" ); goto error; } else { msg_Dbg( p_dec, "GetOutputSizeInfo(): bytes %i, align %i", i_size, i_align ); p_sys->i_min_output = i_size; p_sys->p_buffer = malloc( i_size ); if( !p_sys->p_buffer ) goto error; } } /* Set output properties */ p_dec->fmt_out.i_cat = p_dec->fmt_in.i_cat; if( p_dec->fmt_out.i_cat == AUDIO_ES ) date_Init( &p_sys->end_date, p_dec->fmt_in.audio.i_rate, 1 ); else date_Init( &p_sys->end_date, 25 /* FIXME */, 1 ); if( p_vih ) free( p_vih ); if( p_wf ) free( p_wf ); return VLC_SUCCESS; error: if( p_dmo ) p_dmo->vt->Release( (IUnknown *)p_dmo ); if( hmsdmo_dll ) FreeLibrary( hmsdmo_dll );#ifdef LOADER Restore_LDT_Keeper( ldt_fs );#else /* Uninitialize OLE/COM */ CoUninitialize();#endif /* LOADER */ if( p_vih ) free( p_vih ); if( p_wf ) free( p_wf ); if( p_sys ) free( p_sys ); return VLC_EGENERIC;}/***************************************************************************** * LoadDMO: Load the DMO object *****************************************************************************/static int LoadDMO( vlc_object_t *p_this, HINSTANCE *p_hmsdmo_dll, IMediaObject **pp_dmo, es_format_t *p_fmt, vlc_bool_t b_out ){ DMO_PARTIAL_MEDIATYPE dmo_partial_type; int i_err;#ifndef LOADER long (STDCALL *OurDMOEnum)( const GUID *, uint32_t, uint32_t, const DMO_PARTIAL_MEDIATYPE *, uint32_t, const DMO_PARTIAL_MEDIATYPE *, IEnumDMO ** ); IEnumDMO *p_enum_dmo = NULL; WCHAR *psz_dmo_name; GUID clsid_dmo; uint32_t i_dummy;#endif GETCLASS GetClass; IClassFactory *cFactory = NULL; IUnknown *cObject = NULL; codec_dll *codecs_table = b_out ? encoders_table : decoders_table; int i_codec; /* Look for a DMO which can handle the requested codec */ if( p_fmt->i_cat == AUDIO_ES ) { uint16_t i_tag; dmo_partial_type.type = MEDIATYPE_Audio; dmo_partial_type.subtype = dmo_partial_type.type; dmo_partial_type.subtype.Data1 = p_fmt->i_codec; fourcc_to_wf_tag( p_fmt->i_codec, &i_tag ); if( i_tag ) dmo_partial_type.subtype.Data1 = i_tag; } else { dmo_partial_type.type = MEDIATYPE_Video; dmo_partial_type.subtype = dmo_partial_type.type; dmo_partial_type.subtype.Data1 = p_fmt->i_codec; }#ifndef LOADER /* Load msdmo DLL */ *p_hmsdmo_dll = LoadLibrary( "msdmo.dll" ); if( *p_hmsdmo_dll == NULL ) { msg_Dbg( p_this, "failed loading msdmo.dll" ); return VLC_EGENERIC; } OurDMOEnum = (void *)GetProcAddress( *p_hmsdmo_dll, "DMOEnum" ); if( OurDMOEnum == NULL ) { msg_Dbg( p_this, "GetProcAddress failed to find DMOEnum()" ); FreeLibrary( *p_hmsdmo_dll ); return VLC_EGENERIC; } if( !b_out ) { i_err = OurDMOEnum( &GUID_NULL, 1 /*DMO_ENUMF_INCLUDE_KEYED*/, 1, &dmo_partial_type, 0, NULL, &p_enum_dmo ); } else { i_err = OurDMOEnum( &GUID_NULL, 1 /*DMO_ENUMF_INCLUDE_KEYED*/, 0, NULL, 1, &dmo_partial_type, &p_enum_dmo ); } if( i_err ) { FreeLibrary( *p_hmsdmo_dll ); /* return VLC_EGENERIC; */ /* Try loading the dll directly */ goto loader; } /* Pickup the first available codec */ *pp_dmo = 0; while( ( S_OK == p_enum_dmo->vt->Next( p_enum_dmo, 1, &clsid_dmo, &psz_dmo_name, &i_dummy /* NULL doesn't work */ ) ) ) { char psz_temp[MAX_PATH]; wcstombs( psz_temp, psz_dmo_name, MAX_PATH ); msg_Dbg( p_this, "found DMO: %s", psz_temp ); CoTaskMemFree( psz_dmo_name ); /* Create DMO */ if( CoCreateInstance( &clsid_dmo, NULL, CLSCTX_INPROC, &IID_IMediaObject, (void **)pp_dmo ) ) { msg_Warn( p_this, "can't create DMO: %s", psz_temp ); *pp_dmo = 0; } else break; } p_enum_dmo->vt->Release( (IUnknown *)p_enum_dmo ); if( !*pp_dmo ) { FreeLibrary( *p_hmsdmo_dll ); /* return VLC_EGENERIC; */ /* Try loading the dll directly */ goto loader; } return VLC_SUCCESS;#endif /* LOADER */ loader: for( i_codec = 0; codecs_table[i_codec].i_fourcc != 0; i_codec++ ) { if( codecs_table[i_codec].i_fourcc == p_fmt->i_codec ) break; } if( codecs_table[i_codec].i_fourcc == 0 ) return VLC_EGENERIC; /* Can't happen */ *p_hmsdmo_dll = LoadLibrary( codecs_table[i_codec].psz_dll ); if( *p_hmsdmo_dll == NULL ) { msg_Dbg( p_this, "failed loading '%s'", codecs_table[i_codec].psz_dll ); return VLC_EGENERIC; } GetClass = (GETCLASS)GetProcAddress( *p_hmsdmo_dll, "DllGetClassObject" ); if (!GetClass) { msg_Dbg( p_this, "GetProcAddress failed to find DllGetClassObject()" ); FreeLibrary( *p_hmsdmo_dll ); return VLC_EGENERIC; } i_err = GetClass( codecs_table[i_codec].p_guid, &IID_IClassFactory, (void**)&cFactory ); if( i_err || cFactory == NULL ) { msg_Dbg( p_this, "no such class object" ); FreeLibrary( *p_hmsdmo_dll ); return VLC_EGENERIC; } i_err = cFactory->vt->CreateInstance( cFactory, 0, &IID_IUnknown, (void**)&cObject ); cFactory->vt->Release( (IUnknown*)cFactory ); if( i_err || !cObject ) { msg_Dbg( p_this, "class factory failure" ); FreeLibrary( *p_hmsdmo_dll ); return VLC_EGENERIC; } i_err = cObject->vt->QueryInterface( cObject, &IID_IMediaObject, (void**)pp_dmo ); cObject->vt->Release( (IUnknown*)cObject ); if( i_err || !*pp_dmo ) { msg_Dbg( p_this, "QueryInterface failure" ); FreeLibrary( *p_hmsdmo_dll ); return VLC_EGENERIC; } return VLC_SUCCESS;}/***************************************************************************** * DecoderClose: close codec *****************************************************************************/void DecoderClose( vlc_object_t *p_this ){ decoder_t *p_dec = (decoder_t*)p_this; decoder_sys_t *p_sys = p_dec->p_sys; if( !p_sys ) return; if( p_sys->p_dmo ) p_sys->p_dmo->vt->Release( (IUnknown *)p_sys->p_dmo ); FreeLibrary( p_sys->hmsdmo_dll );#ifdef LOADER#if 0 Restore_LDT_Keeper( p_sys->ldt_fs );#endif#else /* Uninitialize OLE/COM */ CoUninitialize();#endif if( p_sys->p_buffer ) free( p_sys->p_buffer ); free( p_sys );}/**************************************************************************** * DecodeBlock: the whole thing **************************************************************************** * This function must be fed with ogg packets. ****************************************************************************/static void *DecodeBlock( decoder_t *p_dec, block_t **pp_block ){ decoder_sys_t *p_sys = p_dec->p_sys; block_t *p_block; int i_result; DMO_OUTPUT_DATA_BUFFER db; CMediaBuffer *p_out; block_t block_out; uint32_t i_status; if( p_sys == NULL ) { if( DecOpen( VLC_OBJECT(p_dec) ) ) { msg_Err( p_dec, "DecOpen failed" ); return NULL; } p_sys = p_dec->p_sys; } if( !pp_block ) return NULL; p_block = *pp_block; /* Won't work with streams with B-frames, but do we have any ? */ if( p_block && p_block->i_pts <= 0 ) p_block->i_pts = p_block->i_dts; /* Date management */ if( p_block && p_block->i_pts > 0 && p_block->i_pts != date_Get( &p_sys->end_date ) ) { date_Set( &p_sys->end_date, p_block->i_pts ); }#if 0 /* Breaks the video decoding */ if( !date_Get( &p_sys->end_date ) ) { /* We've just started the stream, wait for the first PTS. */ if( p_block ) block_Release( p_block ); return NULL; }#endif /* Feed input to the DMO */ if( p_block && p_block->i_buffer ) { CMediaBuffer *p_in; p_in = CMediaBufferCreate( p_block, p_block->i_buffer, VLC_TRUE ); i_result = p_sys->p_dmo->vt->ProcessInput( p_sys->p_dmo, 0, (IMediaBuffer *)p_in, DMO_INPUT_DATA_BUFFERF_SYNCPOINT, 0, 0 ); p_in->vt->Release( (IUnknown *)p_in ); if( i_result == S_FALSE ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -