问题
I need to create a reader from buffer(that is wav bytes) in order to do it I am using such approach:
void co_AudioEncoderMF::load_from_memory(unsigned char const * data, long data_size)
{
unsigned char * buf = new unsigned char[data_size]; //JUST FOR TEST IN ORDER TO BE SURE THAT I HAVE THIS DATA
memcpy(buf, data, data_size);
IMFMediaType *input_type = nullptr;
IMFSourceReader *source_reader = nullptr;
IMFMediaType *ouput_media_type = nullptr;
IMFSinkWriter *sink_writer = nullptr;
IStream * stream = nullptr;
IMFByteStream * byte_stream = nullptr;
HRESULT hr = InitAndStartCOMLib();
if (SUCCEEDED(hr))
{
hr = create_stream(buf, data_size, &stream); <---- HERE I CREATE A STREAM
}
if (SUCCEEDED(hr))
{
hr = MFCreateMFByteStreamOnStream(stream, &byte_stream);
}
HGLOBAL hGlobal = nullptr;
//IMFSourceReader *pReader = nullptr;
if (SUCCEEDED(hr))
{
GetHGlobalFromStream(stream, &hGlobal);
hr = create_source_reader(byte_stream, &source_reader); <----- HERE I CREATE A READER
}
...
}
HRESULT co_AudioEncoderMF::InitAndStartCOMLib()
{
HRESULT hr = S_OK;
HeapSetInformation(nullptr, HeapEnableTerminationOnCorruption, nullptr, 0);
// Initialize the COM library.
hr = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
// Initialize the Media Foundation platform.
if (SUCCEEDED(hr))
{
hr = MFStartup(MF_VERSION);
}
return hr;
}
HRESULT co_AudioEncoderMF::create_stream(unsigned char const * pData, long dataLen, IStream ** out_stream)
{
HGLOBAL m_phMem = ::GlobalAlloc(GMEM_MOVEABLE, dataLen);
if (!m_phMem)
{
printf("Error AfxThrowMemoryException");
}
LPVOID dest = ::GlobalLock(m_phMem);
memcpy(dest, pData, dataLen);
::GlobalUnlock(m_phMem);
return CreateStreamOnHGlobal(m_phMem, FALSE /*fDeleteOnRelease*/, out_stream);// NOTE :: in order to get more flexablity need to consider such an approach https://gist.github.com/alekseytimoshchenko/e8f52604fdeb50c8ad7873aeb8281bfa
}
HRESULT co_AudioEncoderMF::create_source_reader(IMFByteStream * in_byte_stream, IMFSourceReader **source_reader)
{
HRESULT hr = S_OK;
IMFAttributes * attr = nullptr;
hr = MFCreateAttributes(&attr, 10);
if (SUCCEEDED(hr))
{
hr = attr->SetUINT32(MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS, true);
}
else
{
printf("Error MFCreateAttributes");
}
if (SUCCEEDED(hr))
{
hr = MFCreateSourceReaderFromByteStream(in_byte_stream, attr, source_reader); <----- AND HERE I GOT MY ERROR ABOUT UNSUPPORTED FORMAT
}
else
{
printf("Error Atrr->SetUINT32(MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS, true)");
}
if (FAILED(hr))
{
printf("Error MFCreateSourceReaderFromByteStream");
}
return hr;
}
I am using the same approach but with mp3 bytes and it is works, I assume that it has a difference, but I don't know how to approve it and solve.
回答1:
In my case problem was in that I tried to call this method MFCreateSourceReaderFromByteStream
on stream that was created on wav bytes, but it didn't includes .wav
header. So, I was needed to add a header. I used this method
/*static*/ void Utils::append_data_to_wav_header(unsigned char * buff, int buff_size, int num_of_channels, int sample_rate, std::vector<unsigned char> & out_buf)
{
//*** START OF HEADER
long idx = 0;
uint32_t uint_32_buf = buff_size + 44 /*header size*/;
out_buf.resize(uint_32_buf);
std::string str_buf = "RIFF";
memcpy(&out_buf[idx], str_buf.c_str(), strlen(str_buf.c_str()));
idx += (long)strlen(str_buf.c_str());
memcpy(&out_buf[idx], &uint_32_buf, sizeof(uint_32_buf));
idx += sizeof(uint_32_buf);
str_buf = "WAVE";
memcpy(&out_buf[idx], str_buf.c_str(), strlen(str_buf.c_str()));
idx += (long)strlen(str_buf.c_str());
str_buf = "fmt ";
memcpy(&out_buf[idx], str_buf.c_str(), strlen(str_buf.c_str()));
idx += (long)strlen(str_buf.c_str());
uint_32_buf = 16;
memcpy(&out_buf[idx], &uint_32_buf, 1);
idx += sizeof(uint_32_buf);
uint16_t uint_16_buff = 1;
memcpy(&out_buf[idx], &uint_16_buff, 1);
idx += sizeof(uint_16_buff);
uint_16_buff = num_of_channels;
memcpy(&out_buf[idx], &uint_16_buff, 1);
idx += sizeof(uint_16_buff);
uint_32_buf = sample_rate;
memcpy(&out_buf[idx], &uint_32_buf, 1);
idx += sizeof(uint_32_buf);
uint_32_buf = (sample_rate * 16 * num_of_channels) / 8;
memcpy(&out_buf[idx], &uint_32_buf, 1);
idx += sizeof(uint_32_buf);
uint_16_buff = 16 * num_of_channels / 8;
memcpy(&out_buf[idx], &uint_16_buff, 1);
idx += sizeof(uint_16_buff);
uint_16_buff = 16;
memcpy(&out_buf[idx], &uint_16_buff, 1);
idx += sizeof(uint_16_buff);
str_buf = "data";
memcpy(&out_buf[idx], str_buf.c_str(), strlen(str_buf.c_str()));
idx += (long)strlen(str_buf.c_str());
uint_32_buf = buff_size;
memcpy(&out_buf[idx], &uint_32_buf, 1);
idx += sizeof(uint_32_buf);
//*** END OF HEADER
memcpy(&out_buf[idx], buff, buff_size);
idx += buff_size;
}
来源:https://stackoverflow.com/questions/65426136/the-byte-stream-type-of-the-given-url-is-unsupported-mediafoundation