/***************************************************************************** * Open: probe the packetizer and return score ***************************************************************************** * Tries to launch a decoder and return score so that the interface is able * to choose. *****************************************************************************/ static int Open( vlc_object_t *p_this ) { decoder_t *p_dec = (decoder_t*)p_this; decoder_sys_t *p_sys; if( p_dec->fmt_in.i_cat != AUDIO_ES && p_dec->fmt_in.i_cat != VIDEO_ES && p_dec->fmt_in.i_cat != SPU_ES ) { msg_Err( p_dec, "invalid ES type" ); return VLC_EGENERIC; } if( p_dec->fmt_in.i_cat == SPU_ES ) p_dec->pf_packetize = PacketizeSub; else p_dec->pf_packetize = Packetize; /* Create the output format */ es_format_Copy( &p_dec->fmt_out, &p_dec->fmt_in ); /* Fix the value of the fourcc for audio */ if( p_dec->fmt_in.i_cat == AUDIO_ES ) { p_dec->fmt_out.i_codec = vlc_fourcc_GetCodecAudio( p_dec->fmt_in.i_codec, p_dec->fmt_in.audio.i_bitspersample ); if( !p_dec->fmt_out.i_codec ) { msg_Err( p_dec, "unknown raw audio sample size" ); return VLC_EGENERIC; } } p_dec->p_sys = p_sys = malloc( sizeof(*p_sys) ); p_sys->p_block = NULL; switch( p_dec->fmt_in.i_codec ) { case VLC_CODEC_WMV3: p_sys->pf_parse = ParseWMV3; break; default: p_sys->pf_parse = NULL; break; } return VLC_SUCCESS; }
static int SetOutputType(decoder_t *p_dec, DWORD stream_id, IMFMediaType **result) { decoder_sys_t *p_sys = p_dec->p_sys; HRESULT hr; *result = NULL; IMFMediaType *output_media_type = NULL; /* * Enumerate available output types. The list is ordered by * preference thus we will use the first one unless YV12/I420 is * available for video or float32 for audio. */ int output_type_index = 0; bool found = false; for (int i = 0; !found; ++i) { hr = IMFTransform_GetOutputAvailableType(p_sys->mft, stream_id, i, &output_media_type); if (hr == MF_E_NO_MORE_TYPES) break; else if (hr == MF_E_TRANSFORM_TYPE_NOT_SET) { /* The input type must be set before setting the output type for this MFT. */ return VLC_SUCCESS; } else if (FAILED(hr)) goto error; GUID subtype; hr = IMFMediaType_GetGUID(output_media_type, &MF_MT_SUBTYPE, &subtype); if (FAILED(hr)) goto error; if (p_dec->fmt_in.i_cat == VIDEO_ES) { if (IsEqualGUID(&subtype, &MFVideoFormat_YV12) || IsEqualGUID(&subtype, &MFVideoFormat_I420)) found = true; } else { UINT32 bits_per_sample; hr = IMFMediaType_GetUINT32(output_media_type, &MF_MT_AUDIO_BITS_PER_SAMPLE, &bits_per_sample); if (FAILED(hr)) continue; if (bits_per_sample == 32 && IsEqualGUID(&subtype, &MFAudioFormat_Float)) found = true; } if (found) output_type_index = i; IMFMediaType_Release(output_media_type); output_media_type = NULL; } /* * It's not an error if we don't find the output type we were * looking for, in this case we use the first available type which * is the "preferred" output type for this MFT. */ hr = IMFTransform_GetOutputAvailableType(p_sys->mft, stream_id, output_type_index, &output_media_type); if (FAILED(hr)) goto error; hr = IMFTransform_SetOutputType(p_sys->mft, stream_id, output_media_type, 0); if (FAILED(hr)) goto error; GUID subtype; hr = IMFMediaType_GetGUID(output_media_type, &MF_MT_SUBTYPE, &subtype); if (FAILED(hr)) goto error; if (p_dec->fmt_in.i_cat == VIDEO_ES) { video_format_Copy( &p_dec->fmt_out.video, &p_dec->fmt_in.video ); p_dec->fmt_out.i_codec = vlc_fourcc_GetCodec(p_dec->fmt_in.i_cat, subtype.Data1); } else { p_dec->fmt_out.audio = p_dec->fmt_in.audio; UINT32 bitspersample = 0; hr = IMFMediaType_GetUINT32(output_media_type, &MF_MT_AUDIO_BITS_PER_SAMPLE, &bitspersample); if (SUCCEEDED(hr) && bitspersample) p_dec->fmt_out.audio.i_bitspersample = bitspersample; UINT32 channels = 0; hr = IMFMediaType_GetUINT32(output_media_type, &MF_MT_AUDIO_NUM_CHANNELS, &channels); if (SUCCEEDED(hr) && channels) p_dec->fmt_out.audio.i_channels = channels; UINT32 rate = 0; hr = IMFMediaType_GetUINT32(output_media_type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &rate); if (SUCCEEDED(hr) && rate) p_dec->fmt_out.audio.i_rate = rate; vlc_fourcc_t fourcc; wf_tag_to_fourcc(subtype.Data1, &fourcc, NULL); p_dec->fmt_out.i_codec = vlc_fourcc_GetCodecAudio(fourcc, p_dec->fmt_out.audio.i_bitspersample); p_dec->fmt_out.audio.i_physical_channels = pi_channels_maps[p_dec->fmt_out.audio.i_channels]; } *result = output_media_type; return VLC_SUCCESS; error: msg_Err(p_dec, "Error in SetOutputType()"); if (output_media_type) IMFMediaType_Release(output_media_type); return VLC_EGENERIC; }
/***************************************************************************** * DecoderOpen: probe the decoder and return score *****************************************************************************/ static int DecoderOpen( vlc_object_t *p_this ) { decoder_t *p_dec = (decoder_t*)p_this; vlc_fourcc_t format = p_dec->fmt_in.i_codec; switch( p_dec->fmt_in.i_codec ) { case VLC_FOURCC('a','r','a','w'): case VLC_FOURCC('a','f','l','t'): /* _signed_ big endian samples (mov) */ case VLC_FOURCC('t','w','o','s'): /* _signed_ little endian samples (mov) */ case VLC_FOURCC('s','o','w','t'): format = vlc_fourcc_GetCodecAudio( p_dec->fmt_in.i_codec, p_dec->fmt_in.audio.i_bitspersample ); if( !format ) { msg_Err( p_dec, "bad parameters(bits/sample)" ); return VLC_EGENERIC; } break; } void (*decode) (void *, const uint8_t *, unsigned) = NULL; uint_fast8_t bits; switch( format ) { #ifdef WORDS_BIGENDIAN case VLC_CODEC_F64L: #else case VLC_CODEC_F64B: #endif format = VLC_CODEC_FL64; decode = F64IDecode; bits = 64; break; case VLC_CODEC_FL64: decode = F64NDecode; bits = 64; break; #ifdef WORDS_BIGENDIAN case VLC_CODEC_F32L: #else case VLC_CODEC_F32B: #endif format = VLC_CODEC_FL32; decode = F32IDecode; bits = 32; break; case VLC_CODEC_FL32: decode = F32NDecode; bits = 32; break; case VLC_CODEC_U32B: format = VLC_CODEC_S32N; decode = U32BDecode; bits = 32; break; case VLC_CODEC_U32L: format = VLC_CODEC_S32N; decode = U32LDecode; bits = 32; break; case VLC_CODEC_S32I: format = VLC_CODEC_S32N; decode = S32IDecode; /* fall through */ case VLC_CODEC_S32N: bits = 32; break; case VLC_CODEC_S24B32: format = VLC_CODEC_S32N; decode = S24B32Decode; bits = 32; break; case VLC_CODEC_S24L32: format = VLC_CODEC_S32N; decode = S24L32Decode; bits = 32; break; case VLC_CODEC_U24B: format = VLC_CODEC_S32N; decode = U24BDecode; bits = 24; break; case VLC_CODEC_U24L: format = VLC_CODEC_S32N; decode = U24LDecode; bits = 24; break; case VLC_CODEC_S24B: format = VLC_CODEC_S32N; decode = S24BDecode; bits = 24; break; case VLC_CODEC_S24L: format = VLC_CODEC_S32N; decode = S24LDecode; bits = 24; break; case VLC_CODEC_S20B: format = VLC_CODEC_S32N; decode = S20BDecode; bits = 20; break; case VLC_CODEC_U16B: format = VLC_CODEC_S16N; decode = U16BDecode; bits = 16; break; case VLC_CODEC_U16L: format = VLC_CODEC_S16N; decode = U16LDecode; bits = 16; break; case VLC_CODEC_S16I: format = VLC_CODEC_S16N; decode = S16IDecode; /* fall through */ case VLC_CODEC_S16N: bits = 16; break; case VLC_CODEC_DAT12: format = VLC_CODEC_S16N; decode = DAT12Decode; bits = 12; break; case VLC_CODEC_S8: decode = S8Decode; format = VLC_CODEC_U8; /* fall through */ case VLC_CODEC_U8: bits = 8; break; default: return VLC_EGENERIC; } if( p_dec->fmt_in.audio.i_channels == 0 || p_dec->fmt_in.audio.i_channels > INPUT_CHAN_MAX ) { msg_Err( p_dec, "bad channels count (1-%i): %i", AOUT_CHAN_MAX, p_dec->fmt_in.audio.i_channels ); return VLC_EGENERIC; } if( p_dec->fmt_in.audio.i_rate == 0 || p_dec->fmt_in.audio.i_rate > 384000 ) { msg_Err( p_dec, "bad samplerate: %d Hz", p_dec->fmt_in.audio.i_rate ); return VLC_EGENERIC; } msg_Dbg( p_dec, "samplerate:%dHz channels:%d bits/sample:%d", p_dec->fmt_in.audio.i_rate, p_dec->fmt_in.audio.i_channels, p_dec->fmt_in.audio.i_bitspersample ); /* Allocate the memory needed to store the decoder's structure */ decoder_sys_t *p_sys = malloc(sizeof(*p_sys)); if( unlikely(p_sys == NULL) ) return VLC_ENOMEM; /* Set output properties */ p_dec->fmt_out.i_codec = format; p_dec->fmt_out.audio.channel_type = p_dec->fmt_in.audio.channel_type; p_dec->fmt_out.audio.i_format = format; p_dec->fmt_out.audio.i_rate = p_dec->fmt_in.audio.i_rate; if( p_dec->fmt_in.audio.i_channels <= ARRAY_SIZE( pi_channels_maps ) - 1 ) { if( p_dec->fmt_in.audio.i_physical_channels ) p_dec->fmt_out.audio.i_physical_channels = p_dec->fmt_in.audio.i_physical_channels; else p_dec->fmt_out.audio.i_physical_channels = pi_channels_maps[p_dec->fmt_in.audio.i_channels]; } else { /* Unknown channel map, let the aout/filters decide what to do */ p_dec->fmt_out.audio.i_channels = p_dec->fmt_in.audio.i_channels; p_dec->fmt_out.audio.i_physical_channels = 0; } aout_FormatPrepare( &p_dec->fmt_out.audio ); p_sys->decode = decode; p_sys->framebits = bits * p_dec->fmt_out.audio.i_channels; assert( p_sys->framebits ); date_Init( &p_sys->end_date, p_dec->fmt_out.audio.i_rate, 1 ); date_Set( &p_sys->end_date, 0 ); p_dec->pf_decode = DecodeBlock; p_dec->pf_flush = Flush; p_dec->p_sys = p_sys; return VLC_SUCCESS; }