【问题标题】:The byte stream type of the given URL is unsupported MediaFoundation给定 URL 的字节流类型不受支持 MediaFoundation
【发布时间】:2020-12-23 14:43:19
【问题描述】:

为了做到这一点,我需要从缓冲区(即 wav 字节)创建一个阅读器,我正在使用这种方法:

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 字节”?这是有效且可播放的 .WAV 文件的内容还是其他内容? .WAV 文件应该可以工作。
  • @RomanR。实际上在我的情况下,问题是 .wav 数据不包括标题。发布我的答案可能会有所帮助。无论如何谢谢,因为一开始我不确定我是否可以在 wav 上创建阅读器,但是在你批准这应该不是问题后,我开始检查 wav 格式

标签: c++ audio codec ms-media-foundation


【解决方案1】:

在我的情况下,问题在于我尝试在基于 wav 字节创建的流上调用此方法 MFCreateSourceReaderFromByteStream,但它不包含 .wav 标头。所以,我需要添加一个标题。我用了这个方法

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-02
    • 1970-01-01
    • 2022-07-14
    • 1970-01-01
    相关资源
    最近更新 更多