123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209 |
- #include "MFTDecoder.h"
- #include "util.h"
- #include "../nsutil/pcm.h"
- #include <Mfapi.h>
- #include <Mferror.h>
- static // Release the events that an MFT might allocate in IMFTransform::ProcessOutput().
- void ReleaseEventCollection(MFT_OUTPUT_DATA_BUFFER* pBuffers)
- {
- if (pBuffers->pEvents)
- {
- pBuffers->pEvents->Release();
- pBuffers->pEvents = NULL;
- }
- }
- MFTDecoder::MFTDecoder()
- {
- decoder=0;
- output_buffer=0;
- output_sample=0;
- }
- MFTDecoder::~MFTDecoder()
- {
- if (decoder) {
- decoder->Release();
- }
- decoder = 0;
- if (output_buffer) {
- output_buffer->Release();
- }
- output_buffer = 0;
- if (output_sample) {
- output_sample->Release();
- }
- output_sample = 0;
- }
- HRESULT MFTDecoder::Open(const void *asc, size_t asc_bytes)
- {
- HRESULT hr = CreateAACDecoder(&decoder, asc, asc_bytes);
- if (SUCCEEDED(hr)) {
- decoder->ProcessMessage(MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, 0);
- }
- return hr;
- }
- HRESULT MFTDecoder::Open()
- {
- HRESULT hr = CreateADTSDecoder(&decoder);
- if (SUCCEEDED(hr)) {
- decoder->ProcessMessage(MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, 0);
- decoder->ProcessMessage(MFT_MESSAGE_NOTIFY_START_OF_STREAM, 0);
- }
- return hr;
- }
- void MFTDecoder::Flush()
- {
- if (decoder) {
- decoder->ProcessMessage(MFT_MESSAGE_COMMAND_FLUSH, 0);
- }
- }
- HRESULT MFTDecoder::GetOutputProperties(uint32_t *sampleRate, uint32_t *channels)
- {
- HRESULT hr;
- IMFMediaType *media_type;
- UINT32 local_sample_rate, local_channels;
- if (!decoder) {
- return E_FAIL;
- }
- hr = decoder->GetOutputCurrentType(0, &media_type);
- if (FAILED(hr)) {
- return hr;
- }
- if (FAILED(hr=media_type->GetUINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, &local_sample_rate))
- || FAILED(hr=media_type->GetUINT32(MF_MT_AUDIO_NUM_CHANNELS, &local_channels))) {
- media_type->Release();
- return hr;
- }
- *sampleRate = local_sample_rate;
- *channels = local_channels;
- return hr;
- }
- HRESULT MFTDecoder::Feed(const void *inputBuffer, size_t inputBufferBytes)
- {
- HRESULT hr;
- if (inputBuffer && inputBufferBytes) {
- IMFMediaBuffer *media_buffer=0;
- IMFSample *media_sample=0;
- MFCreateMemoryBuffer((DWORD)inputBufferBytes, &media_buffer);
- MFCreateSample(&media_sample);
- media_sample->AddBuffer(media_buffer);
- BYTE *buffer;
- DWORD max_length, current_length;
- media_buffer->Lock(&buffer, &max_length, ¤t_length);
- memcpy(buffer, inputBuffer, inputBufferBytes);
- media_buffer->Unlock();
- media_buffer->SetCurrentLength((DWORD)inputBufferBytes);
- hr = decoder->ProcessInput(0, media_sample, 0);
- media_sample->Release();
- media_buffer->Release();
- media_sample=0;
- media_buffer=0;
- } else {
- decoder->ProcessMessage(MFT_MESSAGE_NOTIFY_END_OF_STREAM, 0);
- decoder->ProcessMessage(MFT_MESSAGE_COMMAND_DRAIN, 0);
- }
- return S_OK;
- }
- HRESULT MFTDecoder::Decode(void *outputBuffer, size_t *outputBufferBytes, unsigned int bitsPerSample, bool isFloat, double gain)
- {
- HRESULT hr;
- if (!output_sample) {
- MFT_OUTPUT_STREAM_INFO output_stream_info;
- hr = decoder->GetOutputStreamInfo(0, &output_stream_info);
- if (FAILED(hr)) {
- return hr;
- }
- MFCreateMemoryBuffer(output_stream_info.cbSize, &output_buffer);
- MFCreateSample(&output_sample);
- output_sample->AddBuffer(output_buffer);
- }
- output_buffer->SetCurrentLength(0);
- MFT_OUTPUT_DATA_BUFFER output_data_buffer = {0, output_sample, 0, 0};
- DWORD status=0;
- hr = decoder->ProcessOutput(0, 1, &output_data_buffer, &status);
- if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) {
- *outputBufferBytes = 0;
- return S_OK;
- } else if (hr == MF_E_TRANSFORM_STREAM_CHANGE) {
- AssociateFloat(decoder);
- *outputBufferBytes = 0;
- return hr;
- }
- IMFMediaBuffer *decimation_buffer;
- hr = output_data_buffer.pSample->ConvertToContiguousBuffer(&decimation_buffer);
- float *pcm;
- DWORD max_length, current_length;
- decimation_buffer->Lock((BYTE **)&pcm, &max_length, ¤t_length);
- size_t num_samples = current_length / 4;
- *outputBufferBytes = num_samples*bitsPerSample/8;
- if (!isFloat)
- {
- nsutil_pcm_FloatToInt_Interleaved_Gain(outputBuffer, pcm, bitsPerSample, num_samples, (float)gain);
- }
- else
- {
- for (size_t i = 0;i != num_samples;i++)
- ((float *)outputBuffer)[i] = pcm[i] * (float)gain;
- }
- decimation_buffer->Unlock();
- decimation_buffer->Release();
- ReleaseEventCollection(&output_data_buffer);
- return S_OK;
- }
- HRESULT MFTDecoder::OutputBlockSizeSamples(size_t *frameSize)
- {
- HRESULT hr;
- MFT_OUTPUT_STREAM_INFO output_stream_info;
- if (!decoder) {
- return E_FAIL;
- }
- hr = decoder->GetOutputStreamInfo(0, &output_stream_info);
- if (FAILED(hr)) {
- return hr;
- }
- *frameSize = output_stream_info.cbSize;
- return hr;
- }
- bool MFTDecoder::AcceptingInput()
- {
- DWORD flags;
- if (decoder && SUCCEEDED(decoder->GetInputStatus(0, &flags))) {
- if (flags & MFT_INPUT_STATUS_ACCEPT_DATA) {
- return true;
- }
- }
- return false;
- }
|