static void DestroyMFT(decoder_t *p_dec) { decoder_sys_t *p_sys = p_dec->p_sys; if (p_sys->event_generator) IMFMediaEventGenerator_Release(p_sys->event_generator); if (p_sys->input_type) IMFMediaType_Release(p_sys->input_type); if (p_sys->output_sample) { IMFMediaBuffer *output_media_buffer = NULL; HRESULT hr = IMFSample_GetBufferByIndex(p_sys->output_sample, 0, &output_media_buffer); if (SUCCEEDED(hr)) IMFSample_Release(output_media_buffer); IMFSample_Release(p_sys->output_sample); } if (p_sys->output_type) IMFMediaType_Release(p_sys->output_type); if (p_sys->mft) IMFTransform_Release(p_sys->mft); p_sys->event_generator = NULL; p_sys->input_type = NULL; p_sys->output_sample = NULL; p_sys->output_type = NULL; p_sys->mft = NULL; }
static void test_MFCreateMediaType(void) { HRESULT hr; IMFMediaType *mediatype; hr = MFStartup(MAKELONG( MF_API_VERSION, 0xdead ), MFSTARTUP_FULL); ok(hr == MF_E_BAD_STARTUP_VERSION, "got 0x%08x\n", hr); hr = MFStartup(MF_VERSION, MFSTARTUP_FULL); ok(hr == S_OK, "got 0x%08x\n", hr); if(0) { /* Crash on Windows Vista/7 */ hr = MFCreateMediaType(NULL); ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); } hr = MFCreateMediaType(&mediatype); ok(hr == S_OK, "got 0x%08x\n", hr); hr = IMFMediaType_SetGUID(mediatype, &MF_MT_MAJOR_TYPE, &MFMediaType_Video); todo_wine ok(hr == S_OK, "got 0x%08x\n", hr); IMFMediaType_Release(mediatype); MFShutdown(); }
static int ProcessOutputStream(decoder_t *p_dec, DWORD stream_id) { decoder_sys_t *p_sys = p_dec->p_sys; HRESULT hr; picture_t *picture = NULL; block_t *aout_buffer = NULL; DWORD output_status = 0; MFT_OUTPUT_DATA_BUFFER output_buffer = { stream_id, p_sys->output_sample, 0, NULL }; hr = IMFTransform_ProcessOutput(p_sys->mft, 0, 1, &output_buffer, &output_status); if (output_buffer.pEvents) IMFCollection_Release(output_buffer.pEvents); /* Use the returned sample since it can be provided by the MFT. */ IMFSample *output_sample = output_buffer.pSample; if (hr == S_OK) { if (!output_sample) return VLC_SUCCESS; LONGLONG sample_time; hr = IMFSample_GetSampleTime(output_sample, &sample_time); if (FAILED(hr)) goto error; /* Convert from 100 nanoseconds unit to microseconds. */ sample_time /= 10; DWORD total_length = 0; hr = IMFSample_GetTotalLength(output_sample, &total_length); if (FAILED(hr)) goto error; if (p_dec->fmt_in.i_cat == VIDEO_ES) { if (decoder_UpdateVideoFormat(p_dec)) return VLC_SUCCESS; picture = decoder_NewPicture(p_dec); if (!picture) return VLC_SUCCESS; UINT32 interlaced = false; hr = IMFSample_GetUINT32(output_sample, &MFSampleExtension_Interlaced, &interlaced); picture->b_progressive = !interlaced; picture->date = sample_time; } else { if (decoder_UpdateAudioFormat(p_dec)) goto error; if (p_dec->fmt_out.audio.i_bitspersample == 0 || p_dec->fmt_out.audio.i_channels == 0) goto error; int samples = total_length / (p_dec->fmt_out.audio.i_bitspersample * p_dec->fmt_out.audio.i_channels / 8); aout_buffer = decoder_NewAudioBuffer(p_dec, samples); if (!aout_buffer) return VLC_SUCCESS; if (aout_buffer->i_buffer < total_length) goto error; aout_buffer->i_pts = sample_time; } IMFMediaBuffer *output_media_buffer = NULL; hr = IMFSample_GetBufferByIndex(output_sample, 0, &output_media_buffer); BYTE *buffer_start; hr = IMFMediaBuffer_Lock(output_media_buffer, &buffer_start, NULL, NULL); if (FAILED(hr)) goto error; if (p_dec->fmt_in.i_cat == VIDEO_ES) CopyPackedBufferToPicture(picture, buffer_start); else memcpy(aout_buffer->p_buffer, buffer_start, total_length); hr = IMFMediaBuffer_Unlock(output_media_buffer); IMFSample_Release(output_media_buffer); if (FAILED(hr)) goto error; if (p_sys->output_sample) { /* Sample is not provided by the MFT: clear its content. */ hr = IMFMediaBuffer_SetCurrentLength(output_media_buffer, 0); if (FAILED(hr)) goto error; } else { /* Sample is provided by the MFT: decrease refcount. */ IMFSample_Release(output_sample); } } else if (hr == MF_E_TRANSFORM_STREAM_CHANGE || hr == MF_E_TRANSFORM_TYPE_NOT_SET) { if (p_sys->output_type) IMFMediaType_Release(p_sys->output_type); if (SetOutputType(p_dec, p_sys->output_stream_id, &p_sys->output_type)) goto error; /* Reallocate output sample. */ if (p_sys->output_sample) IMFSample_Release(p_sys->output_sample); p_sys->output_sample = NULL; if (AllocateOutputSample(p_dec, 0, &p_sys->output_sample)) goto error; return VLC_SUCCESS; } else if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) { return VLC_SUCCESS; } else /* An error not listed above occurred */ { msg_Err(p_dec, "Unexpected error in IMFTransform::ProcessOutput: %#lx", hr); goto error; } if (p_dec->fmt_in.i_cat == VIDEO_ES) decoder_QueueVideo(p_dec, picture); else decoder_QueueAudio(p_dec, aout_buffer); return VLC_SUCCESS; error: msg_Err(p_dec, "Error in ProcessOutputStream()"); if (picture) picture_Release(picture); if (aout_buffer) block_Release(aout_buffer); return VLC_EGENERIC; }
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; }
static int SetInputType(decoder_t *p_dec, DWORD stream_id, IMFMediaType **result) { decoder_sys_t *p_sys = p_dec->p_sys; HRESULT hr; *result = NULL; IMFMediaType *input_media_type = NULL; /* Search a suitable input type for the MFT. */ int input_type_index = 0; bool found = false; for (int i = 0; !found; ++i) { hr = IMFTransform_GetInputAvailableType(p_sys->mft, stream_id, i, &input_media_type); if (hr == MF_E_NO_MORE_TYPES) break; else if (hr == MF_E_TRANSFORM_TYPE_NOT_SET) { /* The output type must be set before setting the input type for this MFT. */ return VLC_SUCCESS; } else if (FAILED(hr)) goto error; GUID subtype; hr = IMFMediaType_GetGUID(input_media_type, &MF_MT_SUBTYPE, &subtype); if (FAILED(hr)) goto error; if (IsEqualGUID(&subtype, p_sys->subtype)) found = true; if (found) input_type_index = i; IMFMediaType_Release(input_media_type); input_media_type = NULL; } if (!found) goto error; hr = IMFTransform_GetInputAvailableType(p_sys->mft, stream_id, input_type_index, &input_media_type); if (FAILED(hr)) goto error; if (p_dec->fmt_in.i_cat == VIDEO_ES) { UINT64 width = p_dec->fmt_in.video.i_width; UINT64 height = p_dec->fmt_in.video.i_height; UINT64 frame_size = (width << 32) | height; hr = IMFMediaType_SetUINT64(input_media_type, &MF_MT_FRAME_SIZE, frame_size); if (FAILED(hr)) goto error; } else { hr = IMFMediaType_SetUINT32(input_media_type, &MF_MT_ORIGINAL_WAVE_FORMAT_TAG, p_sys->subtype->Data1); if (FAILED(hr)) goto error; if (p_dec->fmt_in.audio.i_rate) { hr = IMFMediaType_SetUINT32(input_media_type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, p_dec->fmt_in.audio.i_rate); if (FAILED(hr)) goto error; } if (p_dec->fmt_in.audio.i_channels) { hr = IMFMediaType_SetUINT32(input_media_type, &MF_MT_AUDIO_NUM_CHANNELS, p_dec->fmt_in.audio.i_channels); if (FAILED(hr)) goto error; } if (p_dec->fmt_in.audio.i_bitspersample) { hr = IMFMediaType_SetUINT32(input_media_type, &MF_MT_AUDIO_BITS_PER_SAMPLE, p_dec->fmt_in.audio.i_bitspersample); if (FAILED(hr)) goto error; } if (p_dec->fmt_in.audio.i_blockalign) { hr = IMFMediaType_SetUINT32(input_media_type, &MF_MT_AUDIO_BLOCK_ALIGNMENT, p_dec->fmt_in.audio.i_blockalign); if (FAILED(hr)) goto error; } if (p_dec->fmt_in.i_bitrate) { hr = IMFMediaType_SetUINT32(input_media_type, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, p_dec->fmt_in.i_bitrate / 8); if (FAILED(hr)) goto error; } } if (p_dec->fmt_in.i_extra > 0) { UINT32 blob_size = 0; hr = IMFMediaType_GetBlobSize(input_media_type, &MF_MT_USER_DATA, &blob_size); /* * Do not overwrite existing user data in the input type, this * can cause the MFT to reject the type. */ if (hr == MF_E_ATTRIBUTENOTFOUND) { hr = IMFMediaType_SetBlob(input_media_type, &MF_MT_USER_DATA, (const UINT8*)p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra); if (FAILED(hr)) goto error; } } hr = IMFTransform_SetInputType(p_sys->mft, stream_id, input_media_type, 0); if (FAILED(hr)) goto error; *result = input_media_type; return VLC_SUCCESS; error: msg_Err(p_dec, "Error in SetInputType()"); if (input_media_type) IMFMediaType_Release(input_media_type); return VLC_EGENERIC; }