如何从缓冲区创建接收器编写器?

问题描述

我的编码器实现以输入 .wav 文件字节为输入,并将写入输出文件.mp3 字节作为输出

像这样

void co_AudioEncoderMF::start_encoding()
{
...
    IMFSinkWriter * sink_writer = nullptr;
    
    //Create sink writer
    HRESULT hr = MFCreateSinkWriterFromURL(
        L"D:\\buffer\\del\\out\\test_out.mp3",NULL,&sink_writer
    );
...

    // Add the stream
    hr = sink_writer->AddStream(
        ouput_media_type,&dwWriterStreamIndex
    );

    // Set input media type
    hr = sink_writer->SetInputMediaType(
        dwWriterStreamIndex,input_type,NULL
    );

    // Tell the sink writer to accept data
    hr = sink_writer->BeginWriting();

...

    hr = sink_writer->WriteSample(
            dwWriterStreamIndex,pSample
        );
...
}

因此,我创建了一个 IMFSinkWriter,然后将其添加到 straem + set mediatype,然后我可以将编码字节写入文件 L"D:\\buffer\\del\\out\\test_out.mp3"

这里的问题是我不想将编码数据写入输出文件,我需要将其作为缓冲区。

我发现还有另一种可能的方法

STDAPI MFCreateSinkWriterFromMediaSink(
    _In_ IMFMediaSink *pMediaSink,_In_opt_ IMFAttributes *pAttributes,_Out_ IMFSinkWriter **ppSinkWriter );

所以,据我所知,它需要在 IMFMediaSink 上和 IMFSinkWriter 上的指针,从这一点我知道我可以实现 IMFMediaSink 接口,它会创建 {{ 1}} 并在调用 IMFSinkWriter 方法时进行设置。 (但我不确定这是在缓冲区中写入编码数据的正确方法

所以,我实现了 MFCreateSinkWriterFromMediaSink

IMFMediaSink

用法::

#include "co_MediaSink.h"
#include <stdio.h>
#include "co_SinkWriter.h"

co_MediaSink::co_MediaSink()
{
}

co_MediaSink::~co_MediaSink()
{
}

HRESULT co_MediaSink::QueryInterface(REFIID riid,void ** ppvObject)
{
    printf("HERE");
    *ppvObject = new co_SinkWriter();
    return S_OK;
}

ULONG co_MediaSink::AddRef(void)
{
    printf("HERE");
    return 1;
}

ULONG co_MediaSink::Release(void)
{
    printf("HERE");
    return 1;
}

HRESULT co_MediaSink::Getcharacteristics(DWORD * pdwcharacteristics)
{
    printf("HERE");
    return S_OK;
}

HRESULT co_MediaSink::AddStreamSink(DWORD dwStreamSinkIdentifier,IMFMediaType * pMediaType,IMFStreamSink ** ppStreamSink)
{
    printf("HERE");
    return S_OK;
}

HRESULT co_MediaSink::RemoveStreamSink(DWORD dwStreamSinkIdentifier)
{
    printf("HERE");
    return S_OK;
}

HRESULT co_MediaSink::GetStreamSinkCount(DWORD * pcStreamSinkCount)
{
    printf("HERE");
    return S_OK;
}

HRESULT co_MediaSink::GetStreamSinkByIndex(DWORD dwIndex,IMFStreamSink ** ppStreamSink)
{
    printf("HERE");
    return S_OK;
}

HRESULT co_MediaSink::GetStreamSinkById(DWORD dwStreamSinkIdentifier,IMFStreamSink ** ppStreamSink)
{
    printf("HERE");
    return S_OK;
}

HRESULT co_MediaSink::SetPresentationClock(ImfpresentationClock * pPresentationClock)
{
    printf("HERE");
    return S_OK;
}

HRESULT co_MediaSink::GetPresentationClock(ImfpresentationClock ** ppPresentationClock)
{
    printf("HERE");
    return S_OK;
}

HRESULT co_MediaSink::Shutdown(void)
{
    printf("HERE");
    return S_OK;
}

所以,在这里通过调试,我看到在调用 IMFSinkWriter * sink_writer = nullptr; co_MediaSink media_sink; HRESULT hr = MFCreateSinkWriterFromMediaSink(&media_sink,nullptr,&sink_writer); 方法之后,下一个调试断点是一个 get in MFCreateSinkWriterFromMediaSink 方法,我需要在其中设置(我认为)我的 {{1} } 对这个输出指针 co_MediaSink::QueryInterface(REFIID riid,void ** ppvObject) 的实现就像这样 IMFSinkWriter,但是我得到一个错误

ppvObject

所以,实际上有两个问题,首先是选择了正确的方式来写入缓冲区,其次 - 如果是,*ppvObject = new co_SinkWriter(); 有什么问题?

解决方法

  1. 已实现字节流以接受数据(您在源端的开发中已经熟悉了 cypress run --headless 概念)
  2. MFCreateMP3MediaSink(这是上述任务的关键 API)为 MP3 流创建 IMFByteStream 的实现
  3. IMFMediaSink 将在此媒体接收器之上创建一个 MFCreateSinkWriterFromMediaSink,您已经知道如何使用接收器编写器

通过这种方式,您可以写入接收器写入器并在另一端接受部分 MP3 字节流。