给定 URL 的字节流类型不受 MediaFoundation 支持

The byte stream type of the given URL is unsupported MediaFoundation

我需要从缓冲区(即 wav 字节)创建一个 reader 才能做到这一点我正在使用这样的方法:

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;
}

我正在使用相同的方法,但使用 mp3 字节并且它有效,我认为它有区别,但我不知道如何批准它并解决它。

在我的案例中,问题在于我试图在基于 wav 字节创建的流上调用此方法 MFCreateSourceReaderFromByteStream,但它不包括 .wav header。所以,我需要添加一个header。我用了这个方法

/*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;
}