/* Adds the video and audio stream to the H.264 writer sink. */ HRESULT ConfigureEncoder(IMFMediaType *pVideoType, DWORD *videoStreamIndex, DWORD *audioStreamIndex, IMFSinkWriter *pWriter) { IMFMediaType *pVideoOutType = NULL; IMFMediaType *pAudioOutType = NULL; // Configure the video stream. CHECK_HR(MFCreateMediaType(&pVideoOutType), L"Configure encoder failed to create media type for video output sink."); CHECK_HR(pVideoOutType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video), L"Failed to set video writer attribute, media type."); CHECK_HR(pVideoOutType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_H264), L"Failed to set video writer attribute, video format (H.264)."); CHECK_HR(pVideoOutType->SetUINT32(MF_MT_AVG_BITRATE, 240 * 1000), L"Failed to set video writer attribute, bit rate."); CHECK_HR(CopyAttribute(pVideoType, pVideoOutType, MF_MT_FRAME_SIZE), L"Failed to set video writer attribute, frame size."); CHECK_HR(CopyAttribute(pVideoType, pVideoOutType, MF_MT_FRAME_RATE), L"Failed to set video writer attribute, frame rate."); CHECK_HR(CopyAttribute(pVideoType, pVideoOutType, MF_MT_PIXEL_ASPECT_RATIO), L"Failed to set video writer attribute, aspect ratio."); CHECK_HR(CopyAttribute(pVideoType, pVideoOutType, MF_MT_INTERLACE_MODE), L"Failed to set video writer attribute, interlace mode.");; CHECK_HR(pWriter->AddStream(pVideoOutType, videoStreamIndex), L"Failed to add the video stream to the sink writer."); pVideoOutType->Release(); // Configure the audio stream. // See http://msdn.microsoft.com/en-us/library/windows/desktop/dd742785(v=vs.85).aspx for AAC encoder settings. // http://msdn.microsoft.com/en-us/library/ff819476%28VS.85%29.aspx CHECK_HR(MFCreateMediaType(&pAudioOutType), L"Configure encoder failed to create media type for audio output sink."); CHECK_HR(pAudioOutType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio), L"Failed to set audio writer attribute, media type."); CHECK_HR(pAudioOutType->SetGUID(MF_MT_SUBTYPE, MFAudioFormat_AAC), L"Failed to set audio writer attribute, audio format (AAC)."); CHECK_HR(pAudioOutType->SetUINT32(MF_MT_AUDIO_NUM_CHANNELS, 2), L"Failed to set audio writer attribute, number of channels."); CHECK_HR(pAudioOutType->SetUINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16), L"Failed to set audio writer attribute, bits per sample."); CHECK_HR(pAudioOutType->SetUINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100), L"Failed to set audio writer attribute, samples per second."); CHECK_HR(pAudioOutType->SetUINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 16000), L"Failed to set audio writer attribute, average bytes per second."); //CHECK_HR( pAudioOutType->SetUINT32( MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION, 0x29 ), L"Failed to set audio writer attribute, level indication."); CHECK_HR(pWriter->AddStream(pAudioOutType, audioStreamIndex), L"Failed to add the audio stream to the sink writer."); pAudioOutType->Release(); return S_OK; }
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(); }
// 创建sink writer. 返回流索引. HRESULT VideoEncoder::CreateSinkWriter(IMFSinkWriter** ppSinkWriter, DWORD* pStreamIndex) { HRESULT hr = S_OK; if (this->m_outputFile == L"") { return ERROR_FILE_INVALID; } // 创建sink writer. *ppSinkWriter = nullptr; IMFSinkWriter *pSinkWriter = nullptr; IMFMediaType* pOutputMediaType = nullptr; IMFMediaType *pInMediaType = nullptr; CheckHR(MFCreateSinkWriterFromURL(this->m_outputFile.c_str(), nullptr, nullptr, &pSinkWriter)); // 创建和配置输出媒体类型. CheckHR(MFCreateMediaType(&pOutputMediaType)); CheckHR(pOutputMediaType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video)); CheckHR(pOutputMediaType->SetGUID(MF_MT_SUBTYPE, this->m_outputVideoFormat)); CheckHR(pOutputMediaType->SetUINT32(MF_MT_AVG_BITRATE, this->m_videoBitRate)); CheckHR(pOutputMediaType->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive)); CheckHR(MFSetAttributeSize(pOutputMediaType, MF_MT_FRAME_SIZE, this->m_frameWidth, this->m_frameHeight)); CheckHR(MFSetAttributeRatio(pOutputMediaType, MF_MT_FRAME_RATE, (UINT32)this->m_fps, 1)); CheckHR(MFSetAttributeRatio(pOutputMediaType, MF_MT_PIXEL_ASPECT_RATIO, 1, 1)); DWORD streamIndex; CheckHR(pSinkWriter->AddStream(pOutputMediaType, &streamIndex)); // 设置输入的媒体类型. CheckHR(MFCreateMediaType(&pInMediaType)); CheckHR(pInMediaType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video)); CheckHR(pInMediaType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32)); CheckHR(pInMediaType->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive)); // 输入的步幅信息不为所有输出编码解码器需要.但某些编解码器需要它,如 H.264. // 如果步幅是去掉,或设置为负值,H.264 将从下到上处理图像. CheckHR(pInMediaType->SetUINT32(MF_MT_DEFAULT_STRIDE, this->m_frameStride)); CheckHR(MFSetAttributeSize(pInMediaType, MF_MT_FRAME_SIZE, this->m_frameWidth, this->m_frameHeight)); CheckHR(MFSetAttributeRatio(pInMediaType, MF_MT_FRAME_RATE, (UINT32)this->m_fps, 1)); CheckHR(MFSetAttributeRatio(pInMediaType, MF_MT_PIXEL_ASPECT_RATIO, 1, 1)); CheckHR(pSinkWriter->SetInputMediaType(streamIndex, pInMediaType, nullptr)); // 开始编写. CheckHR(pSinkWriter->BeginWriting()); *ppSinkWriter = pSinkWriter; (*ppSinkWriter)->AddRef(); *pStreamIndex = streamIndex; cleanup: if (!SUCCEEDED(hr)) { DWORD error = GetLastError(); this->m_logFileStream << "意外错误: " << error << endl; } SafeRelease(&pSinkWriter); SafeRelease(&pOutputMediaType); return hr; }
HRESULT EncodeTransform::SetOutputMediaType() { if (!mpEncoder) { return MF_E_NOT_INITIALIZED; } IMFMediaType* pMediaTypeOut = NULL; HRESULT hr = MFCreateMediaType(&pMediaTypeOut); // Set the output media type. if (SUCCEEDED(hr)) { hr = MFCreateMediaType(&pMediaTypeOut); } if (SUCCEEDED(hr)) { hr = pMediaTypeOut->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video); } if (SUCCEEDED(hr)) { hr = pMediaTypeOut->SetGUID(MF_MT_SUBTYPE, cVideoEncodingFormat); } if (SUCCEEDED(hr)) { hr = pMediaTypeOut->SetUINT32(MF_MT_AVG_BITRATE, VIDEO_BIT_RATE); } if (SUCCEEDED(hr)) { hr = MFSetAttributeRatio(pMediaTypeOut, MF_MT_FRAME_RATE, VIDEO_FPS, 1); } if (SUCCEEDED(hr)) { hr = MFSetAttributeSize(pMediaTypeOut, MF_MT_FRAME_SIZE, mStreamWidth, mStreamHeight); } if (SUCCEEDED(hr)) { hr = pMediaTypeOut->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive); } if (SUCCEEDED(hr)) { hr = pMediaTypeOut->SetUINT32(MF_MT_MPEG2_PROFILE, eAVEncH264VProfile_Base); } if (SUCCEEDED(hr)) { hr = MFSetAttributeRatio(pMediaTypeOut, MF_MT_PIXEL_ASPECT_RATIO, 1, 1); } if (SUCCEEDED(hr)) { hr = mpEncoder->SetOutputType(0, pMediaTypeOut, 0); } return hr; }
HRESULT CTedTestSink::InitVideoStream() { HRESULT hr = S_OK; InternalAddRef(); /*IMFMediaSink* pMediaSink; InternalQueryInterface(this, CTedTestSink::_GetEntries(), IID_IMFMediaSink, (void**) &pMediaSink);*/ CComPtr<IMFMediaType> spVideoType; IFC( MFCreateMediaType(&spVideoType) ); IFC( spVideoType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video) ); IFC( spVideoType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_RGB24) ); CComObject<CTedTestMediaTypeHandler>* pVideoTypeHandler = NULL; IFC( CComObject<CTedTestMediaTypeHandler>::CreateInstance(&pVideoTypeHandler) ); pVideoTypeHandler->AddRef(); pVideoTypeHandler->SetMajorType(MFMediaType_Video); pVideoTypeHandler->AddAvailableType(spVideoType); CComObject<CTedTestStreamSink>* pVideoStreamSink = NULL; IFC( CComObject<CTedTestStreamSink>::CreateInstance(&pVideoStreamSink) ); pVideoStreamSink->AddRef(); m_spVideoStreamSink = pVideoStreamSink; //IFC( pVideoStreamSink->Init(pMediaSink, pVideoTypeHandler, 1) ); IFC( pVideoStreamSink->Init(this, pVideoTypeHandler, 1) ); pVideoTypeHandler->Release(); pVideoStreamSink->Release(); //pMediaSink->Release(); Cleanup: return hr; }
static HRESULT CreateAudioMediaType(const WWMFPcmFormat &fmt, IMFMediaType** ppMediaType) { HRESULT hr; IMFMediaType *pMediaType = NULL; *ppMediaType = NULL; HRG(MFCreateMediaType(&pMediaType) ); HRG(pMediaType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio)); HRG(pMediaType->SetGUID(MF_MT_SUBTYPE, (fmt.sampleFormat == WWMFBitFormatInt) ? MFAudioFormat_PCM : MFAudioFormat_Float)); HRG(pMediaType->SetUINT32(MF_MT_AUDIO_NUM_CHANNELS, fmt.nChannels)); HRG(pMediaType->SetUINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, fmt.sampleRate)); HRG(pMediaType->SetUINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, fmt.FrameBytes())); HRG(pMediaType->SetUINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, fmt.BytesPerSec())); HRG(pMediaType->SetUINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, fmt.bits)); HRG(pMediaType->SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE)); if (0 != fmt.dwChannelMask) { HRG(pMediaType->SetUINT32(MF_MT_AUDIO_CHANNEL_MASK, fmt.dwChannelMask)); } if (fmt.bits != fmt.validBitsPerSample) { HRG(pMediaType->SetUINT32(MF_MT_AUDIO_VALID_BITS_PER_SAMPLE, fmt.validBitsPerSample)); } *ppMediaType = pMediaType; pMediaType = NULL; //< prevent release end: SafeRelease(&pMediaType); return hr; }
HRESULT FFmpegDecodeServices::SetInputMediaType(IMFMediaType* pMediaType) { std::lock_guard<decltype(_mutex)> lock(_mutex); if (pMediaType == NULL) { _inputMediaType.Reset(); _outputMediaType.Reset(); return S_OK; } HRESULT hr = CheckMediaType(pMediaType); if (FAILED(hr)) return hr; if (avcodec_find_decoder(ConvertGuidToCodecId(pMediaType)) == NULL) return E_ABORT; GUID majorType = GUID_NULL; pMediaType->GetGUID(MF_MT_MAJOR_TYPE, &majorType); if (majorType != MFMediaType_Video && majorType != MFMediaType_Audio) return MF_E_INVALID_CODEC_MERIT; hr = (majorType == MFMediaType_Video ? InitVideoDecoder(pMediaType) : InitAudioDecoder(pMediaType)); if (FAILED(hr)) return hr; MFCreateMediaType(&_inputMediaType); pMediaType->CopyAllItems(_inputMediaType.Get()); return S_OK; }
//------------------------------------------------------------------- // selectVideoStream: Finds the first video stream and sets the format to RGB32. // HRESULT VidReader::selectVideoStream() { HRESULT hr = S_OK; IMFMediaType *pType = NULL; // Configure the source reader to give us progressive RGB32 frames. // The source reader will load the decoder if needed. hr = MFCreateMediaType(&pType); if (FAILED(hr)) goto done; hr = pType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video); if (FAILED(hr)) goto done; hr = pType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32); if (FAILED(hr)) goto done; hr = m_pReader->SetCurrentMediaType((DWORD)MF_SOURCE_READER_FIRST_VIDEO_STREAM, NULL, pType); if (FAILED(hr)) goto done; // Ensure the stream is selected. hr = m_pReader->SetStreamSelection((DWORD)MF_SOURCE_READER_FIRST_VIDEO_STREAM, TRUE); if (FAILED(hr)) goto done; done: SafeRelease(&pType); return hr; }
HRESULT WMFAACDecoder::SetDecoderInputType(int32_t aChannelCount, int32_t aSampleRate, BYTE* aUserData, UINT32 aUserDataLength) { HRESULT hr; CComPtr<IMFMediaType> type; hr = MFCreateMediaType(&type); ENSURE(SUCCEEDED(hr), hr); hr = type->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio); ENSURE(SUCCEEDED(hr), hr); hr = type->SetGUID(MF_MT_SUBTYPE, MFAudioFormat_AAC); ENSURE(SUCCEEDED(hr), hr); mRate = aSampleRate; hr = type->SetUINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, mRate); ENSURE(SUCCEEDED(hr), hr); mChannels = aChannelCount; hr = type->SetUINT32(MF_MT_AUDIO_NUM_CHANNELS, mChannels); ENSURE(SUCCEEDED(hr), hr); hr = type->SetBlob(MF_MT_USER_DATA, aUserData, aUserDataLength); ENSURE(SUCCEEDED(hr), hr); hr = mDecoder->SetInputType(0, type, 0); ENSURE(SUCCEEDED(hr), hr); return S_OK; }
//------------------------------------------------------------------- // Open a file for writing and prepare the sink writer // HRESULT VidWriter::initSinkWriter(WCHAR *filename) { HRESULT hr = S_OK; IMFMediaType *pMediaTypeOut = NULL; IMFMediaType *pMediaTypeIn = NULL; // Create the sink writer SafeRelease(&m_pWriter); hr = MFCreateSinkWriterFromURL(filename, NULL, NULL, &m_pWriter); if (FAILED(hr)) goto done; // Create the output media type hr = MFCreateMediaType(&pMediaTypeOut); if (FAILED(hr)) goto done; // Configure it hr = configureOutput(pMediaTypeOut); if (FAILED(hr)) goto done; // Add it to the sink writer hr = m_pWriter->AddStream(pMediaTypeOut, &m_streamIndex); if (FAILED(hr)) goto done; // Create the input media type hr = MFCreateMediaType(&pMediaTypeIn); if (FAILED(hr)) goto done; // Configure it hr = configureInput(pMediaTypeIn); if (FAILED(hr)) goto done; // Add it to the sink writer hr = m_pWriter->SetInputMediaType(m_streamIndex, pMediaTypeIn, NULL); if (FAILED(hr)) goto done; // Tell the sink writer to start accepting data hr = m_pWriter->BeginWriting(); // Reset the frame timer m_rtStart = 0; done: SafeRelease(&pMediaTypeOut); SafeRelease(&pMediaTypeIn); return hr; }
HRESULT ConfigureEncoder( const EncodingParameters& params, IMFMediaType *pType, IMFSinkWriter *pWriter, DWORD *pdwStreamIndex ) { HRESULT hr = S_OK; IMFMediaType *pType2 = NULL; hr = MFCreateMediaType(&pType2); if (SUCCEEDED(hr)) { hr = pType2->SetGUID( MF_MT_MAJOR_TYPE, MFMediaType_Video ); } if (SUCCEEDED(hr)) { hr = pType2->SetGUID(MF_MT_SUBTYPE, params.subtype); } if (SUCCEEDED(hr)) { hr = pType2->SetUINT32(MF_MT_AVG_BITRATE, params.bitrate); } if (SUCCEEDED(hr)) { hr = CopyAttribute(pType, pType2, MF_MT_FRAME_SIZE); } if (SUCCEEDED(hr)) { hr = CopyAttribute(pType, pType2, MF_MT_FRAME_RATE); } if (SUCCEEDED(hr)) { hr = CopyAttribute(pType, pType2, MF_MT_PIXEL_ASPECT_RATIO); } if (SUCCEEDED(hr)) { hr = CopyAttribute(pType, pType2, MF_MT_INTERLACE_MODE); } if (SUCCEEDED(hr)) { hr = pWriter->AddStream(pType2, pdwStreamIndex); } SafeRelease(&pType2); return hr; }
HRESULT CloneVideoMediaType(IMFMediaType *pSrcMediaType, REFGUID guidSubType, IMFMediaType **ppNewMediaType) { IMFMediaType *pNewMediaType = NULL; HRESULT hr = MFCreateMediaType(&pNewMediaType); if (FAILED(hr)) { goto done; } hr = pNewMediaType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video); if (FAILED(hr)) { goto done; } hr = pNewMediaType->SetGUID(MF_MT_SUBTYPE, guidSubType); if (FAILED(hr)) { goto done; } hr = CopyAttribute(pSrcMediaType, pNewMediaType, MF_MT_FRAME_SIZE); if (FAILED(hr)) { goto done; } hr = CopyAttribute(pSrcMediaType, pNewMediaType, MF_MT_FRAME_RATE); if (FAILED(hr)) { goto done; } hr = CopyAttribute(pSrcMediaType, pNewMediaType, MF_MT_PIXEL_ASPECT_RATIO); if (FAILED(hr)) { goto done; } hr = CopyAttribute(pSrcMediaType, pNewMediaType, MF_MT_INTERLACE_MODE); if (FAILED(hr)) { goto done; } *ppNewMediaType = pNewMediaType; (*ppNewMediaType)->AddRef(); done: SafeRelease(&pNewMediaType); return hr; }
audio_reader::audio_reader(std::wstring& source) { { IMFByteStreamPtr stream; CHK(MFCreateFile(MF_FILE_ACCESSMODE::MF_ACCESSMODE_READ, MF_FILE_OPENMODE::MF_OPENMODE_FAIL_IF_NOT_EXIST, MF_FILE_FLAGS::MF_FILEFLAGS_NONE, source.c_str(), &stream)); IMFAttributesPtr attr; CHK(MFCreateAttributes(&attr, 10)); CHK(attr->SetUINT32(MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS, true)); IMFSourceReaderPtr reader; CHK(MFCreateSourceReaderFromByteStream(stream.Get(), attr.Get(), &reader)); // CHK(MFCreateSourceReaderFromURL(source.c_str(),attr.Get(), &reader)); CHK(reader.As(&reader_)); QWORD length; CHK(stream->GetLength(&length)); fileSize_ = length; } //CHK(reader_->GetServiceForStream(0, MF_WRAPPED_OBJECT, __uuidof(IMFByteStream), &stream)); CHK(reader_->GetNativeMediaType(0, 0, &native_media_type_)); CHK(MFCreateMediaType(¤t_media_type_)); CHK(current_media_type_->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio)); CHK(current_media_type_->SetGUID(MF_MT_SUBTYPE, MFAudioFormat_PCM)); CHK(current_media_type_->SetUINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, MFGetAttributeUINT32(native_media_type_.Get(), MF_MT_AUDIO_BITS_PER_SAMPLE, bits_per_sample) ) ); CHK(current_media_type_->SetUINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, MFGetAttributeUINT32(native_media_type_.Get(), MF_MT_AUDIO_SAMPLES_PER_SECOND, samples_per_second) )); CHK(current_media_type_->SetUINT32(MF_MT_AUDIO_NUM_CHANNELS, MFGetAttributeUINT32(native_media_type_.Get(), MF_MT_AUDIO_NUM_CHANNELS, channel_count) )); //DWORD blockAlign; //CHK(native_media_type_->GetUINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, &blockAlign)); //CHK(current_media_type_->SetUINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT,blockAlign )); CHK(reader_->SetCurrentMediaType(0, nullptr, current_media_type_.Get())); CHK(reader_->GetCurrentMediaType(0, current_media_type_.ReleaseAndGetAddressOf())); UINT32 blockAlign; CHK(current_media_type_->GetUINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, &blockAlign)); DOUT(boost::wformat(L"Block Align: %10d %10x") % blockAlign % blockAlign); }
IMFMediaType* MFDecoderSourceReader::setSource(IMFMediaSource *source, const QAudioFormat &audioFormat) { IMFMediaType *mediaType = NULL; if (m_source == source) return mediaType; if (m_source) { m_source->Release(); m_source = NULL; } if (m_sourceReader) { m_sourceReader->Release(); m_sourceReader = NULL; } if (!source) return mediaType; IMFAttributes *attr = NULL; MFCreateAttributes(&attr, 1); if (SUCCEEDED(attr->SetUnknown(MF_SOURCE_READER_ASYNC_CALLBACK, this))) { if (SUCCEEDED(MFCreateSourceReaderFromMediaSource(source, attr, &m_sourceReader))) { m_source = source; m_source->AddRef(); m_sourceReader->SetStreamSelection(DWORD(MF_SOURCE_READER_ALL_STREAMS), FALSE); m_sourceReader->SetStreamSelection(DWORD(MF_SOURCE_READER_FIRST_AUDIO_STREAM), TRUE); IMFMediaType *pPartialType = NULL; MFCreateMediaType(&pPartialType); pPartialType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio); if (audioFormat.sampleType() == QAudioFormat::Float) { pPartialType->SetGUID(MF_MT_SUBTYPE, MFAudioFormat_Float); } else { pPartialType->SetGUID(MF_MT_SUBTYPE, MFAudioFormat_PCM); } m_sourceReader->SetCurrentMediaType(DWORD(MF_SOURCE_READER_FIRST_AUDIO_STREAM), NULL, pPartialType); pPartialType->Release(); m_sourceReader->GetCurrentMediaType(DWORD(MF_SOURCE_READER_FIRST_AUDIO_STREAM), &mediaType); // Ensure the stream is selected. m_sourceReader->SetStreamSelection(DWORD(MF_SOURCE_READER_FIRST_AUDIO_STREAM), TRUE); } attr->Release(); } return mediaType; }
int select_input_mediatype(IMFTransform *transform, int in_stream_id, ADTSData adts, UINT8 *user_data, UINT32 user_data_len, GUID audio_format) { HRESULT hr = S_OK; IMFMediaType *t; // actually you can get rid of the whole block of searching and filtering mess // if you know the exact parameters of your media stream hr = MFCreateMediaType(&t); if (FAILED(hr)) { ReportError(L"Unable to create an empty MediaType", hr); return -1; } // basic definition t->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio); t->SetGUID(MF_MT_SUBTYPE, audio_format); // see https://docs.microsoft.com/en-us/windows/desktop/medfound/aac-decoder#example-media-types // and https://docs.microsoft.com/zh-cn/windows/desktop/api/mmreg/ns-mmreg-heaacwaveinfo_tag // for the meaning of the byte array below // for integrate into a larger project, it is recommended to wrap the parameters into a struct // and pass that struct into the function // const UINT8 aac_data[] = { 0x01, 0x00, 0xfe, 00, 00, 00, 00, 00, 00, 00, 00, 00, 0x11, 0x90 }; // 0: raw aac 1: adts 2: adif 3: latm/laos t->SetUINT32(MF_MT_AAC_PAYLOAD_TYPE, 1); t->SetUINT32(MF_MT_AUDIO_NUM_CHANNELS, adts.channels); t->SetUINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, adts.samplerate); // 0xfe = 254 = "unspecified" t->SetUINT32(MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION, 254); t->SetUINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 1); t->SetBlob(MF_MT_USER_DATA, user_data, user_data_len); hr = transform->SetInputType(in_stream_id, t, 0); if (FAILED(hr)) { ReportError(L"failed to select input types for MFT", hr); return -1; } return 0; }
HRESULT CreatePhotoMediaType(IMFMediaType *pSrcMediaType, IMFMediaType **ppPhotoMediaType) { *ppPhotoMediaType = NULL; const UINT32 uiFrameRateNumerator = 30; const UINT32 uiFrameRateDenominator = 1; IMFMediaType *pPhotoMediaType = NULL; HRESULT hr = MFCreateMediaType(&pPhotoMediaType); if (FAILED(hr)) { goto done; } hr = pPhotoMediaType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Image); if (FAILED(hr)) { goto done; } hr = pPhotoMediaType->SetGUID(MF_MT_SUBTYPE, GUID_ContainerFormatJpeg); if (FAILED(hr)) { goto done; } hr = CopyAttribute(pSrcMediaType, pPhotoMediaType, MF_MT_FRAME_SIZE); if (FAILED(hr)) { goto done; } *ppPhotoMediaType = pPhotoMediaType; (*ppPhotoMediaType)->AddRef(); done: SafeRelease(&pPhotoMediaType); return hr; }
// Called by the constructor only (for setting up the IMFTransform) // // Thread context: Dialog window thread bool DecoderMF::CreateInputMediaType(IMFMediaType** mediaType) { bool ret = false; HRESULT hr; IMFMediaType* newMediaType = NULL; if (mediaType == NULL) return false; hr = MFCreateMediaType(&newMediaType); if (FAILED(hr)) goto bail; hr = newMediaType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video); if (FAILED(hr)) goto bail; hr = newMediaType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_H264); if (FAILED(hr)) goto bail; ret = true; bail: if (ret == false) { if (newMediaType != NULL) { newMediaType->Release(); newMediaType = NULL; } } else { *mediaType = newMediaType; } return ret; }
/*static */HRESULT MFMovieSource::ConfigureDecoder( IMFSourceReader* reader, DWORD streamIndex ) { HRESULT hr; ComPtr_t<IMFMediaType> nativeType; ComPtr_t<IMFMediaType> mediaType; hr=reader->GetNativeMediaType( streamIndex, 0, &nativeType ); PKY_IF_ERR_RETURN( hr, "Cant Get NativeMediaType" ); GUID majorType, subType; hr=nativeType->GetGUID( MF_MT_MAJOR_TYPE, &majorType ); PKY_IF_ERR_RETURN( hr, "Get MajorType Failed" ); hr=nativeType->GetGUID( MF_MT_SUBTYPE, &subType ); hr=MFCreateMediaType( &mediaType ); PKY_IF_ERR_RETURN( hr, "Create MediaType Failed" ); hr=mediaType->SetGUID( MF_MT_MAJOR_TYPE, majorType ); PKY_IF_ERR_RETURN( hr, "Set MajorType Failed" ); if( majorType==MFMediaType_Video ) { subType=MFVideoFormat_RGB32; } else if( majorType==MFMediaType_Audio ) { subType=MFAudioFormat_PCM; } else { return S_FALSE; } hr=mediaType->SetGUID( MF_MT_SUBTYPE, subType ); PKY_IF_ERR_RETURN( hr, "Set SubType Failed" ); hr=reader->SetCurrentMediaType( streamIndex, 0, mediaType ); if( FAILED( hr ) ) { return hr; } return hr; }
HRESULT CMFCamCapture::init() { IMFMediaType *pType = NULL; HRESULT hr; CHECK_HR(hr = CoInitializeEx(NULL, COINIT_MULTITHREADED)); CHECK_HR(hr = MFStartup(MF_VERSION)); // Configure the media type that the Sample Grabber will receive. // Setting the major and subtype is usually enough for the topology loader // to resolve the topology. CHECK_HR(hr = MFCreateMediaType(&pType)); CHECK_HR(hr = pType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video)); CHECK_HR(hr = pType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_RGB24)); // Create the sample grabber sink. CHECK_HR(hr = SampleGrabberCB::CreateInstance(&m_spSampleGrabber)); CHECK_HR(hr = MFCreateSampleGrabberSinkActivate(pType, m_spSampleGrabber, &m_spSinkActivate)); // To run as fast as possible, set this attribute (requires Windows 7): CHECK_HR(hr = m_spSinkActivate->SetUINT32(MF_SAMPLEGRABBERSINK_IGNORE_CLOCK, TRUE)); // Create the Media Session. CHECK_HR(hr = MFCreateMediaSession(NULL, &m_spSession)); CHECK_HR(hr = enumVideoDevices()); CHECK_HR(hr = setupVideoDevice()); CHECK_HR(hr = setupMfSession()); done: SafeRelease(&pType); return hr; }
/** Cobbled together from: http://msdn.microsoft.com/en-us/library/dd757929(v=vs.85).aspx and http://msdn.microsoft.com/en-us/library/dd317928(VS.85).aspx -- Albert If anything in here fails, just bail. I'm not going to decode HRESULTS. -- Bill */ bool SoundSourceMediaFoundation::configureAudioStream(const Mixxx::AudioSourceConfig& audioSrcCfg) { HRESULT hr(S_OK); // deselect all streams, we only want the first hr = m_pReader->SetStreamSelection(MF_SOURCE_READER_ALL_STREAMS, false); if (FAILED(hr)) { qWarning() << "SSMF: failed to deselect all streams"; return false; } hr = m_pReader->SetStreamSelection(MF_SOURCE_READER_FIRST_AUDIO_STREAM, true); if (FAILED(hr)) { qWarning() << "SSMF: failed to select first audio stream"; return false; } hr = MFCreateMediaType(&m_pAudioType); if (FAILED(hr)) { qWarning() << "SSMF: failed to create media type"; return false; } hr = m_pAudioType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio); if (FAILED(hr)) { qWarning() << "SSMF: failed to set major type"; return false; } hr = m_pAudioType->SetGUID(MF_MT_SUBTYPE, MFAudioFormat_Float); if (FAILED(hr)) { qWarning() << "SSMF: failed to set subtype"; return false; } hr = m_pAudioType->SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, true); if (FAILED(hr)) { qWarning() << "SSMF: failed to set samples independent"; return false; } hr = m_pAudioType->SetUINT32(MF_MT_FIXED_SIZE_SAMPLES, true); if (FAILED(hr)) { qWarning() << "SSMF: failed to set fixed size samples"; return false; } hr = m_pAudioType->SetUINT32(MF_MT_SAMPLE_SIZE, kLeftoverSize); if (FAILED(hr)) { qWarning() << "SSMF: failed to set sample size"; return false; } hr = m_pAudioType->SetUINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, kSampleRate); if (FAILED(hr)) { qWarning() << "SSMF: failed to set sample rate"; return false; } // "Number of bits per audio sample in an audio media type." hr = m_pAudioType->SetUINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, kBitsPerSample); if (FAILED(hr)) { qWarning() << "SSMF: failed to set bits per sample"; return false; } if (isValidChannelCount(audioSrcCfg.channelCountHint)) { hr = m_pAudioType->SetUINT32(MF_MT_AUDIO_NUM_CHANNELS, audioSrcCfg.channelCountHint); if (FAILED(hr)) { qWarning() << "SSMF: failed to set number of channels"; return false; } setChannelCount(audioSrcCfg.channelCountHint); } else { UINT32 numChannels = 0; hr = m_pAudioType->GetUINT32(MF_MT_AUDIO_NUM_CHANNELS, &numChannels); if (FAILED(hr) || (0 >= numChannels)) { qWarning() << "SSMF: failed to get number of channels"; return false; } setChannelCount(numChannels); } // "...the block alignment is equal to the number of audio channels // multiplied by the number of bytes per audio sample." hr = m_pAudioType->SetUINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, frames2samples(sizeof(m_leftoverBuffer[0]))); if (FAILED(hr)) { qWarning() << "SSMF: failed to set block alignment"; return false; } // Set this type on the source reader. The source reader will // load the necessary decoder. hr = m_pReader->SetCurrentMediaType(MF_SOURCE_READER_FIRST_AUDIO_STREAM, NULL, m_pAudioType); // the reader has the media type now, free our reference so we can use our // pointer for other purposes. Do this before checking for failure so we // don't dangle. safeRelease(&m_pAudioType); if (FAILED(hr)) { qWarning() << "SSMF: failed to set media type"; return false; } // Get the complete uncompressed format. hr = m_pReader->GetCurrentMediaType(MF_SOURCE_READER_FIRST_AUDIO_STREAM, &m_pAudioType); if (FAILED(hr)) { qWarning() << "SSMF: failed to retrieve completed media type"; return false; } // Ensure the stream is selected. hr = m_pReader->SetStreamSelection(MF_SOURCE_READER_FIRST_AUDIO_STREAM, true); if (FAILED(hr)) { qWarning() << "SSMF: failed to select first audio stream (again)"; return false; } UINT32 leftoverBufferSize = 0; hr = m_pAudioType->GetUINT32(MF_MT_SAMPLE_SIZE, &leftoverBufferSize); if (FAILED(hr)) { qWarning() << "SSMF: failed to get buffer size"; return false; } m_leftoverBufferSize = leftoverBufferSize; m_leftoverBufferSize /= sizeof(CSAMPLE); // convert size in bytes to sizeof(CSAMPLE) m_leftoverBuffer = new CSAMPLE[m_leftoverBufferSize]; return true; }
/** Cobbled together from: http://msdn.microsoft.com/en-us/library/dd757929(v=vs.85).aspx and http://msdn.microsoft.com/en-us/library/dd317928(VS.85).aspx -- Albert If anything in here fails, just bail. I'm not going to decode HRESULTS. -- Bill */ bool SoundSourceMediaFoundation::configureAudioStream() { HRESULT hr(S_OK); // deselect all streams, we only want the first hr = m_pReader->SetStreamSelection(MF_SOURCE_READER_ALL_STREAMS, false); if (FAILED(hr)) { qWarning() << "SSMF: failed to deselect all streams"; return false; } hr = m_pReader->SetStreamSelection(MF_SOURCE_READER_FIRST_AUDIO_STREAM, true); if (FAILED(hr)) { qWarning() << "SSMF: failed to select first audio stream"; return false; } hr = MFCreateMediaType(&m_pAudioType); if (FAILED(hr)) { qWarning() << "SSMF: failed to create media type"; return false; } hr = m_pAudioType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio); if (FAILED(hr)) { qWarning() << "SSMF: failed to set major type"; return false; } hr = m_pAudioType->SetGUID(MF_MT_SUBTYPE, MFAudioFormat_PCM); if (FAILED(hr)) { qWarning() << "SSMF: failed to set subtype"; return false; } hr = m_pAudioType->SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, true); if (FAILED(hr)) { qWarning() << "SSMF: failed to set samples independent"; return false; } hr = m_pAudioType->SetUINT32(MF_MT_FIXED_SIZE_SAMPLES, true); if (FAILED(hr)) { qWarning() << "SSMF: failed to set fixed size samples"; return false; } hr = m_pAudioType->SetUINT32(MF_MT_SAMPLE_SIZE, kLeftoverSize); if (FAILED(hr)) { qWarning() << "SSMF: failed to set sample size"; return false; } // MSDN for this attribute says that if bps is 8, samples are unsigned. // Otherwise, they're signed (so they're signed for us as 16 bps). Why // chose to hide this rather useful tidbit here is beyond me -bkgood hr = m_pAudioType->SetUINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, kBitsPerSample); if (FAILED(hr)) { qWarning() << "SSMF: failed to set bits per sample"; return false; } hr = m_pAudioType->SetUINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, kNumChannels * (kBitsPerSample / 8)); if (FAILED(hr)) { qWarning() << "SSMF: failed to set block alignment"; return false; } hr = m_pAudioType->SetUINT32(MF_MT_AUDIO_NUM_CHANNELS, kNumChannels); if (FAILED(hr)) { qWarning() << "SSMF: failed to set number of channels"; return false; } hr = m_pAudioType->SetUINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, kSampleRate); if (FAILED(hr)) { qWarning() << "SSMF: failed to set sample rate"; return false; } // Set this type on the source reader. The source reader will // load the necessary decoder. hr = m_pReader->SetCurrentMediaType( MF_SOURCE_READER_FIRST_AUDIO_STREAM, NULL, m_pAudioType); // the reader has the media type now, free our reference so we can use our // pointer for other purposes. Do this before checking for failure so we // don't dangle. safeRelease(&m_pAudioType); if (FAILED(hr)) { qWarning() << "SSMF: failed to set media type"; return false; } // Get the complete uncompressed format. hr = m_pReader->GetCurrentMediaType( MF_SOURCE_READER_FIRST_AUDIO_STREAM, &m_pAudioType); if (FAILED(hr)) { qWarning() << "SSMF: failed to retrieve completed media type"; return false; } // Ensure the stream is selected. hr = m_pReader->SetStreamSelection( MF_SOURCE_READER_FIRST_AUDIO_STREAM, true); if (FAILED(hr)) { qWarning() << "SSMF: failed to select first audio stream (again)"; return false; } // this may not be safe on all platforms as m_leftoverBufferSize is a // size_t and this function is writing a uint32. However, on 32-bit // Windows 7, size_t is defined as uint which is 32-bits, so we're safe // for all supported platforms -bkgood UINT32 leftoverBufferSize = 0; hr = m_pAudioType->GetUINT32(MF_MT_SAMPLE_SIZE, &leftoverBufferSize); if (FAILED(hr)) { qWarning() << "SSMF: failed to get buffer size"; return false; } m_leftoverBufferSize = static_cast<size_t>(leftoverBufferSize); m_leftoverBufferSize /= 2; // convert size in bytes to size in int16s m_leftoverBuffer = new qint16[m_leftoverBufferSize]; return true; }
HRESULT WavSource::CreatePresentationDescriptor() { HRESULT hr = S_OK; MFTIME duration = 0; IMFMediaType *pMediaType = NULL; IMFStreamDescriptor *pStreamDescriptor = NULL; IMFMediaTypeHandler *pHandler = NULL; assert(WaveFormat() != NULL); // Create an empty media type. hr = MFCreateMediaType(&pMediaType); // Initialize the media type from the WAVEFORMATEX structure. if (SUCCEEDED(hr)) { hr = MFInitMediaTypeFromWaveFormatEx(pMediaType, WaveFormat(), WaveFormatSize()); } // Create the stream descriptor. if (SUCCEEDED(hr)) { hr = MFCreateStreamDescriptor( 0, // stream identifier 1, // Number of media types. &pMediaType, // Array of media types &pStreamDescriptor ); } // Set the default media type on the media type handler. if (SUCCEEDED(hr)) { hr = pStreamDescriptor->GetMediaTypeHandler(&pHandler); } if (SUCCEEDED(hr)) { hr = pHandler->SetCurrentMediaType(pMediaType); } // Create the presentation descriptor. if (SUCCEEDED(hr)) { hr = MFCreatePresentationDescriptor( 1, // Number of stream descriptors &pStreamDescriptor, // Array of stream descriptors &m_pPresentationDescriptor ); } // Select the first stream if (SUCCEEDED(hr)) { hr = m_pPresentationDescriptor->SelectStream(0); } // Set the file duration as an attribute on the presentation descriptor. if (SUCCEEDED(hr)) { duration = m_pRiff->FileDuration(); hr = m_pPresentationDescriptor->SetUINT64(MF_PD_DURATION, (UINT64)duration); } SafeRelease(&pMediaType); SafeRelease(&pStreamDescriptor); SafeRelease(&pHandler); return hr; }
HRESULT EncodeTransform::SetInputMediaType() { if (!mpEncoder) { return MF_E_NOT_INITIALIZED; } IMFMediaType* pMediaTypeIn = NULL; HRESULT hr = MFCreateMediaType(&pMediaTypeIn); // Set the input media type. if (SUCCEEDED(hr)) { hr = pMediaTypeIn->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video); } if (SUCCEEDED(hr)) { hr = pMediaTypeIn->SetGUID(MF_MT_SUBTYPE, cVideoInputFormat); } if (SUCCEEDED(hr)) { hr = pMediaTypeIn->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive); } if (SUCCEEDED(hr)) { hr = MFSetAttributeSize(pMediaTypeIn, MF_MT_FRAME_SIZE, mStreamWidth, mStreamHeight); } if (SUCCEEDED(hr)) { hr = MFSetAttributeRatio(pMediaTypeIn, MF_MT_FRAME_RATE, VIDEO_FPS, 1); } if (SUCCEEDED(hr)) { hr = MFSetAttributeRatio(pMediaTypeIn, MF_MT_PIXEL_ASPECT_RATIO, 1, 1); } if (SUCCEEDED(hr)) { hr = mpEncoder->SetInputType(0, pMediaTypeIn, 0); // if (hr == MF_E_TRANSFORM_TYPE_NOT_SET) { std::cout << "MF_E_TRANSFORM_TYPE_NOT_SET -> 0xC00D6D60L: You must set the output type first" << std::endl; } if (hr == MF_E_INVALIDMEDIATYPE) { std::cout << "MF_E_INVALIDMEDIATYPE -> 0xc00d36b4: the data specified for the media type is invalid, inconsistent, or not supported by this object" << std::endl; } #if defined(CODECAPI_AVLowLatencyMode) // Win8 only hr = mpEncoder->QueryInterface(IID_PPV_ARGS(&mpCodecAPI)); if (SUCCEEDED(hr)) { VARIANT var; var.vt = VT_UI4; var.ulVal = eAVEncCommonRateControlMode_Quality; hr = mpCodecAPI->SetValue(&CODECAPI_AVEncCommonRateControlMode, &var); if (FAILED(hr)){printf("Failed to set rate control mode.\n");} var.vt = VT_BOOL; var.boolVal = VARIANT_TRUE; hr = mpCodecAPI->SetValue(&CODECAPI_AVLowLatencyMode, &var); if (FAILED(hr)){ printf("Failed to enable low latency mode.\n"); } // This property controls the quality level when the encoder is not using a constrained bit rate. The AVEncCommonRateControlMode property determines whether the bit rate is constrained. VARIANT quality; InitVariantFromUInt32(50, &quality); hr = mpCodecAPI->SetValue(&CODECAPI_AVEncCommonQuality, &quality); if (FAILED(hr)){ printf("Failed to adjust quality mode.\n"); } } #endif } return hr; }
void MfVideoEncoder::Init(int width, int height, int fps) { mWidth = width; mHeight = height; mFps = fps; mFrameTime = 10 * 1000 * 1000 / fps; CComPtr<IMFMediaType> pMediaTypeOut; CComPtr<IMFMediaType> pMediaTypeIn; HRESULT hr = MFCreateSinkWriterFromURL(mFilename.c_str(), NULL, NULL, &mSinkWriter); // Set the output media type. if (SUCCEEDED(hr)) { hr = MFCreateMediaType(&pMediaTypeOut); } if (SUCCEEDED(hr)) { hr = pMediaTypeOut->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video); } if (SUCCEEDED(hr)) { hr = pMediaTypeOut->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_H264); } if (SUCCEEDED(hr)) { hr = pMediaTypeOut->SetUINT32(MF_MT_AVG_BITRATE, 8000000); } if (SUCCEEDED(hr)) { hr = pMediaTypeOut->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive); } if (SUCCEEDED(hr)) { hr = MFSetAttributeSize(pMediaTypeOut, MF_MT_FRAME_SIZE, width, height); } if (SUCCEEDED(hr)) { hr = MFSetAttributeRatio(pMediaTypeOut, MF_MT_FRAME_RATE, fps, 1); } if (SUCCEEDED(hr)) { hr = MFSetAttributeRatio(pMediaTypeOut, MF_MT_PIXEL_ASPECT_RATIO, 1, 1); } pMediaTypeOut->SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1); if (SUCCEEDED(hr)) { hr = mSinkWriter->AddStream(pMediaTypeOut, (DWORD*)&mStreamIndex); } // Set the input media type. if (SUCCEEDED(hr)) { hr = MFCreateMediaType(&pMediaTypeIn); } if (SUCCEEDED(hr)) { hr = pMediaTypeIn->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video); } if (SUCCEEDED(hr)) { hr = pMediaTypeIn->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32); } if (SUCCEEDED(hr)) { hr = pMediaTypeIn->SetUINT32(MF_MT_MPEG2_PROFILE, 77); } if (SUCCEEDED(hr)) { hr = pMediaTypeIn->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive); } if (SUCCEEDED(hr)) { hr = MFSetAttributeSize(pMediaTypeIn, MF_MT_FRAME_SIZE, width, height); } if (SUCCEEDED(hr)) { hr = MFSetAttributeRatio(pMediaTypeIn, MF_MT_FRAME_RATE, fps, 1); } if (SUCCEEDED(hr)) { hr = MFSetAttributeRatio(pMediaTypeIn, MF_MT_PIXEL_ASPECT_RATIO, 1, 1); } if (SUCCEEDED(hr)) { hr = mSinkWriter->SetInputMediaType(mStreamIndex, pMediaTypeIn, nullptr); } // Tell the sink writer to start accepting data. if (SUCCEEDED(hr)) { hr = mSinkWriter->BeginWriting(); } CComPtr<ICodecAPI> encoder; hr = mSinkWriter->GetServiceForStream(0, GUID_NULL, IID_PPV_ARGS(&encoder)); if (SUCCEEDED(hr)) { CComVariant quality((UINT32)eAVEncCommonRateControlMode_CBR, VT_UI4); hr = encoder->SetValue(&CODECAPI_AVEncCommonRateControlMode, &quality); } if (SUCCEEDED(hr)) { CComVariant quality((UINT32)80000000, VT_UI4); hr = encoder->SetValue(&CODECAPI_AVEncCommonMeanBitRate, &quality); } // Return the pointer to the caller. if (!SUCCEEDED(hr)) { mSinkWriter.Release(); throw TempleException("Unable to begin writing to the video stream"); } }
HRESULT CHWMFT::SetOutputType( DWORD dwOutputStreamID, IMFMediaType* pType, DWORD dwFlags) { /***************************************** ** See http://msdn.microsoft.com/en-us/library/ms702016(v=VS.85).aspx *****************************************/ HRESULT hr = S_OK; IMFMediaType* pMT = NULL; do { /************************************ ** Since this MFT is a decoder, it ** must not allow this function to be ** called until it is unlocked. If ** your MFT is an encoder, this function ** CAN be called before the MFT is ** unlocked ************************************/ if(IsLocked() != FALSE) { hr = MF_E_TRANSFORM_ASYNC_LOCKED; break; } if(pType == NULL) { hr = E_POINTER; break; } /***************************************** ** Todo: If your MFT supports more than one ** stream, make sure you modify ** MFT_MAX_STREAMS and adjust this function ** accordingly *****************************************/ if(dwOutputStreamID >= MFT_MAX_STREAMS) { hr = MF_E_INVALIDSTREAMNUMBER; break; } hr = CheckOutputType(pType); if(FAILED(hr)) { break; } /******************************************* ** Store a copy of the media type, not the ** one passed in by the caller. This way the ** caller is unable to modify the internal ** media type *******************************************/ hr = MFCreateMediaType(&pMT); if(FAILED(hr)) { break; } hr = DuplicateAttributes(pMT, pType); if(FAILED(hr)) { break; } { CAutoLock lock(&m_csLock); SAFERELEASE(m_pOutputMT); m_pOutputMT = pMT; m_pOutputMT->AddRef(); } IsMFTReady(); }while(false); SAFERELEASE(pMT); return hr; }
unsigned char *BBWin8Game::LoadAudioData( String path,int *length,int *channels,int *format,int *hertz ){ String url=PathToFilePath( path ); DXASS( MFStartup( MF_VERSION ) ); IMFAttributes *attrs; DXASS( MFCreateAttributes( &attrs,1 ) ); DXASS( attrs->SetUINT32( MF_LOW_LATENCY,TRUE ) ); IMFSourceReader *reader; DXASS( MFCreateSourceReaderFromURL( url.ToCString<wchar_t>(),attrs,&reader ) ); attrs->Release(); IMFMediaType *mediaType; DXASS( MFCreateMediaType( &mediaType ) ); DXASS( mediaType->SetGUID( MF_MT_MAJOR_TYPE,MFMediaType_Audio ) ); DXASS( mediaType->SetGUID( MF_MT_SUBTYPE,MFAudioFormat_PCM ) ); DXASS( reader->SetCurrentMediaType( MF_SOURCE_READER_FIRST_AUDIO_STREAM,0,mediaType ) ); mediaType->Release(); IMFMediaType *outputMediaType; DXASS( reader->GetCurrentMediaType( MF_SOURCE_READER_FIRST_AUDIO_STREAM,&outputMediaType ) ); WAVEFORMATEX *wformat; uint32 formatByteCount=0; DXASS( MFCreateWaveFormatExFromMFMediaType( outputMediaType,&wformat,&formatByteCount ) ); *channels=wformat->nChannels; *format=wformat->wBitsPerSample/8; *hertz=wformat->nSamplesPerSec; CoTaskMemFree( wformat ); outputMediaType->Release(); /* PROPVARIANT var; DXASS( reader->GetPresentationAttribute( MF_SOURCE_READER_MEDIASOURCE,MF_PD_DURATION,&var ) ); LONGLONG duration=var.uhVal.QuadPart; float64 durationInSeconds=(duration / (float64)(10000 * 1000)); m_maxStreamLengthInBytes=(uint32)( durationInSeconds * m_waveFormat.nAvgBytesPerSec ); */ std::vector<unsigned char*> bufs; std::vector<uint32> lens; uint32 len=0; for( ;; ){ uint32 flags=0; IMFSample *sample; DXASS( reader->ReadSample( MF_SOURCE_READER_FIRST_AUDIO_STREAM,0,0,reinterpret_cast<DWORD*>(&flags),0,&sample ) ); if( flags & MF_SOURCE_READERF_ENDOFSTREAM ){ break; } if( sample==0 ){ abort(); } IMFMediaBuffer *mediaBuffer; DXASS( sample->ConvertToContiguousBuffer( &mediaBuffer ) ); uint8 *audioData=0; uint32 sampleBufferLength=0; DXASS( mediaBuffer->Lock( &audioData,0,reinterpret_cast<DWORD*>( &sampleBufferLength ) ) ); unsigned char *buf=(unsigned char*)malloc( sampleBufferLength ); memcpy( buf,audioData,sampleBufferLength ); bufs.push_back( buf ); lens.push_back( sampleBufferLength ); len+=sampleBufferLength; DXASS( mediaBuffer->Unlock() ); mediaBuffer->Release(); sample->Release(); } reader->Release(); *length=len/(*channels * *format); unsigned char *data=(unsigned char*)malloc( len ); unsigned char *p=data; for( int i=0;i<bufs.size();++i ){ memcpy( p,bufs[i],lens[i] ); free( bufs[i] ); p+=lens[i]; } gc_force_sweep=true; return data; }
HRESULT CHWMFT::GetOutputAvailableType( DWORD dwOutputStreamID, DWORD dwTypeIndex, IMFMediaType** ppType) { /***************************************** ** Todo: This function will return a media ** type at a given index. The SDK ** implementation uses a static array of ** media types. Your MFT may want to use ** a dynamic array and modify the list ** order depending on the MFTs state ** See http://msdn.microsoft.com/en-us/library/ms703812(v=VS.85).aspx *****************************************/ HRESULT hr = S_OK; IMFMediaType* pMT = NULL; do { if(IsLocked() != FALSE) { hr = MF_E_TRANSFORM_ASYNC_LOCKED; break; } if(ppType == NULL) { hr = E_POINTER; break; } /***************************************** ** Todo: If your MFT supports more than one ** stream, make sure you modify ** MFT_MAX_STREAMS and adjust this function ** accordingly *****************************************/ if(dwOutputStreamID >= MFT_MAX_STREAMS) { hr = MF_E_INVALIDSTREAMNUMBER; break; } /***************************************** ** Todo: Modify the accepted output list ** g_ppguidOutputTypes or use your own ** implementation of this function *****************************************/ if(dwTypeIndex >= g_dwNumOutputTypes) { hr = MF_E_NO_MORE_TYPES; break; } { CAutoLock lock(&m_csLock); hr = MFCreateMediaType(&pMT); if(FAILED(hr)) { break; } hr = pMT->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video); if(FAILED(hr)) { break; } hr = pMT->SetGUID(MF_MT_SUBTYPE, *(g_ppguidOutputTypes[dwTypeIndex])); if(FAILED(hr)) { break; } /***************************************** ** Todo: The following implementation ** forces a standard output resolution ** and framerate. Your MFT should set these ** values properly and update the Media ** Type as necessary after decoding the ** stream *****************************************/ hr = MFSetAttributeSize(pMT, MF_MT_FRAME_SIZE, MFT_OUTPUT_WIDTH, MFT_OUTPUT_HEIGHT); if(FAILED(hr)) { break; } hr = MFSetAttributeRatio(pMT, MF_MT_FRAME_RATE, MFT_FRAMERATE_NUMERATOR, MFT_FRAMERATE_DENOMINATOR); if(FAILED(hr)) { break; } (*ppType) = pMT; (*ppType)->AddRef(); } }while(false); SAFERELEASE(pMT); return hr; }
static int MediaFoundation_open(Sound_Sample *sample, const char *ext) { MediaFoundationFileContainer* media_foundation_file_container; Sound_SampleInternal* internal = (Sound_SampleInternal*)sample->opaque; HRESULT hresult; IMFSourceReader* source_reader = NULL; // Since the byte stream stuff is so complicated, if you need to test without it, // you can hard code loading a file and use MFCreateSourceReaderFromURL. // const WCHAR* source_file = L"C:\\Users\\username\\Documents\\crystal.wav"; // const WCHAR* source_file = L"C:\\Users\\username\\Documents\\battle_hymn_of_the_republic.mp3"; // const WCHAR* source_file = L"C:\\Users\\username\\Documents\\TheDeclarationOfIndependencePreambleJFK.m4a"; IMFByteStreamRWops* byte_stream = new IMFByteStreamRWops(internal->rw, sample); // hresult = MFCreateSourceReaderFromURL(source_file, NULL, &source_reader); hresult = MFCreateSourceReaderFromByteStream(byte_stream, NULL, &source_reader); if (FAILED(hresult)) { SNDERR("Error opening input file"); return 0; } media_foundation_file_container = (MediaFoundationFileContainer*)calloc(1, sizeof(MediaFoundationFileContainer)); BAIL_IF_MACRO(media_foundation_file_container == NULL, ERR_OUT_OF_MEMORY, 0); internal->decoder_private = media_foundation_file_container; media_foundation_file_container->sourceReader = source_reader; media_foundation_file_container->byteStreamRWops = byte_stream; { HRESULT hr = hresult; IMFMediaType *pUncompressedAudioType = NULL; IMFMediaType* audio_type = NULL; // Select the first audio stream, and deselect all other streams. hr = source_reader->SetStreamSelection((DWORD)MF_SOURCE_READER_ALL_STREAMS, false); if (SUCCEEDED(hr)) { // select first stream hr = source_reader->SetStreamSelection((DWORD)MF_SOURCE_READER_FIRST_AUDIO_STREAM, true); } // Getting format data and debugging { // Not sure of the difference between GetNativeMediaType/GetNativeMediaType. // Search suggests GetCurrentMediaType gets the complete uncompressed format. // hr = source_reader->GetCurrentMediaType(MF_SOURCE_READER_FIRST_AUDIO_STREAM, &audio_type); // The method returns a copy of the media type, so it is safe to modify the object received in the ppMediaType parameter. hr = source_reader->GetNativeMediaType(MF_SOURCE_READER_FIRST_AUDIO_STREAM, 0, // Index of the media type to retreive (don't really know what that means) &audio_type ); if(FAILED(hr)) { SNDERR("GetNativeMediaType failed"); free(media_foundation_file_container); SafeRelease(&source_reader); return 0; } UINT32 all_samples_independent = 0; UINT32 fixed_size_samples = 0; UINT32 sample_size = 0; UINT32 bits_per_sample = 0; UINT32 block_alignment = 0; UINT32 num_channels = 0; UINT32 samples_per_second = 0; hr = audio_type->GetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, &all_samples_independent); hr = audio_type->GetUINT32(MF_MT_FIXED_SIZE_SAMPLES, &fixed_size_samples); hr = audio_type->GetUINT32(MF_MT_SAMPLE_SIZE, &sample_size); hr = audio_type->GetUINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, &bits_per_sample); hr = audio_type->GetUINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, &block_alignment); hr = audio_type->GetUINT32(MF_MT_AUDIO_NUM_CHANNELS, &num_channels); hr = audio_type->GetUINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, &samples_per_second); SNDDBG2("WindowsMediaFoundation: all_samples_independent == (%d).\n", all_samples_independent); SNDDBG2("WindowsMediaFoundation: fixed_size_samples == (%d).\n", fixed_size_samples); SNDDBG2("WindowsMediaFoundation: sample_size == (%d).\n", sample_size); SNDDBG2("WindowsMediaFoundation: bits_per_sample == (%d).\n", bits_per_sample); SNDDBG2("WindowsMediaFoundation: block_alignment == (%d).\n", block_alignment); SNDDBG2("WindowsMediaFoundation: num_channels == (%d).\n", num_channels); SNDDBG2("WindowsMediaFoundation: samples_per_second == (%d).\n", samples_per_second); // Get the total length of the stream PROPVARIANT prop_variant; double duration_in_milliseconds = -1.0; // get the duration, which is a 64-bit integer of 100-nanosecond units hr = source_reader->GetPresentationAttribute(MF_SOURCE_READER_MEDIASOURCE, MF_PD_DURATION, &prop_variant); if(FAILED(hr)) { SNDERR("WindowsMediaFoundation: Failed to get duration"); duration_in_milliseconds = -1.0; } else { LONGLONG file_duration = prop_variant.uhVal.QuadPart; //double durationInSeconds = (file_duration / static_cast<double>(10000 * 1000)); duration_in_milliseconds = (file_duration / static_cast<double>(10000)); } PropVariantClear(&prop_variant); sample->flags = SOUND_SAMPLEFLAG_CANSEEK; sample->actual.rate = samples_per_second; sample->actual.channels = (UINT8)num_channels; internal->total_time = (INT32)(duration_in_milliseconds + 0.5); /* * I want to use the native system to do conversion and decoding for performance reasons. * This is particularly important on mobile devices like iOS. * Taking from the Ogg Vorbis decode, I pretend the "actual" format is the same * as the desired format. */ if(0 == sample->desired.format) { sample->actual.format = AUDIO_S16SYS; } else { sample->actual.format = sample->desired.format; } SNDDBG2("WindowsMediaFoundation: total seconds of sample == (%d).\n", internal->total_time); // For compressed files, the bits per sample is undefined if(0 == bits_per_sample) { // hard code to 16 media_foundation_file_container->bitsPerSample = 16; } else { media_foundation_file_container->bitsPerSample = bits_per_sample; } SafeRelease(&audio_type); } { IMFMediaType* target_audio_type = NULL; // Create a partial media type that specifies uncompressed PCM audio. hr = MFCreateMediaType(&target_audio_type); if(FAILED(hr)) { SNDERR("WindowsMediaFoundation: Failed to create target MediaType\n"); SafeRelease(&source_reader); free(media_foundation_file_container); } hr = target_audio_type->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio); if(FAILED(hr)) { SNDERR("WindowsMediaFoundation: Failed to set MFMediaType_Audio\n"); SafeRelease(&target_audio_type); SafeRelease(&source_reader); free(media_foundation_file_container); return 0; } // We want to decode to raw PCM hr = target_audio_type->SetGUID(MF_MT_SUBTYPE, MFAudioFormat_PCM); if(FAILED(hr)) { SNDERR("WindowsMediaFoundation: Failed to set MFAudioFormat_PCM\n"); SafeRelease(&target_audio_type); SafeRelease(&source_reader); free(media_foundation_file_container); return 0; } // Set this type on the source reader. The source reader will // load the necessary decoder. hr = source_reader->SetCurrentMediaType((DWORD)MF_SOURCE_READER_FIRST_AUDIO_STREAM, NULL, target_audio_type); if(FAILED(hr)) { SNDERR("WindowsMediaFoundation: Failed to set SetCurrentMediaType\n"); SafeRelease(&target_audio_type); SafeRelease(&source_reader); free(media_foundation_file_container); return 0; } // Don't need this any more SafeRelease(&target_audio_type); } // specify the output type (pcm) { IMFMediaType* uncompressed_audio_type = NULL; // Get the complete uncompressed format. hr = source_reader->GetCurrentMediaType((DWORD)MF_SOURCE_READER_FIRST_AUDIO_STREAM, &uncompressed_audio_type); if(FAILED(hr)) { SNDERR("WindowsMediaFoundation: Failed to set SetCurrentMediaType\n"); SafeRelease(&source_reader); free(media_foundation_file_container); return 0; } hr = source_reader->SetStreamSelection((DWORD)MF_SOURCE_READER_FIRST_AUDIO_STREAM, true); // Ensure the stream is selected. if(FAILED(hr)) { SNDERR("WindowsMediaFoundation: Failed to set SetCurrentMediaType\n"); SafeRelease(&uncompressed_audio_type); SafeRelease(&source_reader); free(media_foundation_file_container); return 0; } // libaudiodecoder UINT32 leftover_buffer_size = 0; hr = uncompressed_audio_type->GetUINT32(MF_MT_SAMPLE_SIZE, &leftover_buffer_size); if(FAILED(hr)) { // EW: MS docs say this will fail for varible length samples (proably aac, etc?) // So this could happen a lot. // So far, haven't noticed adverse effects. SNDDBG2("WindowsMediaFoundation: Failed to get leftover_buffer_size\n"); leftover_buffer_size = 32; } media_foundation_file_container->leftoverBufferSize = leftover_buffer_size; media_foundation_file_container->leftoverBufferSize = leftover_buffer_size; media_foundation_file_container->leftoverBufferSize /= 2; // convert size in bytes to size in int16s media_foundation_file_container->leftoverBuffer = (short*)malloc(media_foundation_file_container->leftoverBufferSize * sizeof(short)); media_foundation_file_container->uncompressedAudioType = uncompressed_audio_type; media_foundation_file_container->uncompressedAudioType->AddRef(); SafeRelease(&uncompressed_audio_type); } } return(1); } /* MediaFoundation_open */
HRESULT CHWMFT::GetInputAvailableType( DWORD dwInputStreamID, DWORD dwTypeIndex, IMFMediaType** ppType) { /***************************************** ** Todo: This function will return a media ** type at a given index. The SDK ** implementation uses a static array of ** media types. Your MFT may want to use ** a dynamic array and modify the list ** order depending on the MFTs state ** See http://msdn.microsoft.com/en-us/library/ms704814(v=VS.85).aspx *****************************************/ HRESULT hr = S_OK; IMFMediaType* pMT = NULL; do { if(IsLocked() != FALSE) { hr = MF_E_TRANSFORM_ASYNC_LOCKED; break; } if(ppType == NULL) { hr = E_POINTER; break; } /***************************************** ** Todo: If your MFT supports more than one ** stream, make sure you modify ** MFT_MAX_STREAMS and adjust this function ** accordingly *****************************************/ if(dwInputStreamID >= MFT_MAX_STREAMS) { hr = MF_E_INVALIDSTREAMNUMBER; break; } /***************************************** ** Todo: Modify the accepted input list ** g_ppguidInputTypes or use your own ** implementation of this function *****************************************/ if(dwTypeIndex >= g_dwNumInputTypes) { hr = MF_E_NO_MORE_TYPES; break; } { CAutoLock lock(&m_csLock); hr = MFCreateMediaType(&pMT); if(FAILED(hr)) { break; } hr = pMT->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video); if(FAILED(hr)) { break; } hr = pMT->SetGUID(MF_MT_SUBTYPE, *(g_ppguidInputTypes[dwTypeIndex])); if(FAILED(hr)) { break; } (*ppType) = pMT; (*ppType)->AddRef(); } }while(false); SAFERELEASE(pMT); return hr; }
HRESULT CHWMFT::GetOutputCurrentType( DWORD dwOutputStreamID, IMFMediaType** ppType) { /***************************************** ** See http://msdn.microsoft.com/en-us/library/ms696985(v=VS.85).aspx *****************************************/ HRESULT hr = S_OK; IMFMediaType* pMT = NULL; do { /************************************ ** Since this MFT is a decoder, it ** must not allow this function to be ** called until it is unlocked. If ** your MFT is an encoder, this function ** CAN be called before the MFT is ** unlocked ************************************/ if(IsLocked() != FALSE) { hr = MF_E_TRANSFORM_ASYNC_LOCKED; break; } if(ppType == NULL) { hr = E_POINTER; break; } /***************************************** ** Todo: If your MFT supports more than one ** stream, make sure you modify ** MFT_MAX_STREAMS and adjust this function ** accordingly *****************************************/ if(dwOutputStreamID >= MFT_MAX_STREAMS) { hr = MF_E_INVALIDSTREAMNUMBER; break; } { CAutoLock lock(&m_csLock); if(m_pOutputMT == NULL) { hr = MF_E_TRANSFORM_TYPE_NOT_SET; break; } /******************************************* ** Return a copy of the media type, not the ** internal one. Returning the internal one ** will allow an external component to modify ** the internal media type *******************************************/ hr = MFCreateMediaType(&pMT); if(FAILED(hr)) { break; } hr = DuplicateAttributes(pMT, m_pOutputMT); if(FAILED(hr)) { break; } } (*ppType) = pMT; (*ppType)->AddRef(); }while(false); SAFERELEASE(pMT); return hr; }