How to make implementation of IStream correctly (MediaFoundation)?

你。 提交于 2021-01-07 02:34:25

问题


General idea is to get a IMFSinkWriter that will write a data to the buffer. There is such an implementation

bool co_AudioEncoderMF::start_encoding_to()
{
    bool result = false;
    co_Stream stream;
    IMFByteStream * byte_stream = nullptr;
    IMFMediaSink * media_sink = nullptr;
    IMFSinkWriter * sink_writer = nullptr;

    HRESULT hr = MFCreateMFByteStreamOnStream(&stream, &byte_stream);

    if (SUCCEEDED(hr) && byte_stream != nullptr)
    {
        hr = MFCreateMP3MediaSink(byte_stream, &media_sink);
    }
    
    if (SUCCEEDED(hr) && media_sink != nullptr)
    {
        hr = MFCreateSinkWriterFromMediaSink(media_sink, nullptr, &sink_writer);
    }

    if (SUCCEEDED(hr) && sink_writer != nullptr)
    {
        result = start_encoding_to(sink_writer, m_source_reader);
    }

    return result;
}

Here I created a class co_Stream that implement IStream (a minimal implementation, just for test)

co_Stream.h

#pragma once
#include <ObjIdlbase.h>
#include <vector>

class co_Stream: public IStream
{
    //Constructors
public:
    co_Stream();
    ~co_Stream();

    //Public Methods
public:
    virtual HRESULT STDMETHODCALLTYPE QueryInterface(
        /* [in] */ REFIID riid,
        /* [iid_is][out] */ _COM_Outptr_ void __RPC_FAR *__RPC_FAR *ppvObject) override;

    virtual ULONG STDMETHODCALLTYPE AddRef(void) override;

    virtual ULONG STDMETHODCALLTYPE Release(void) override;

    virtual /* [local] */ HRESULT STDMETHODCALLTYPE Read(
        /* [annotation] */
        _Out_writes_bytes_to_(cb, *pcbRead)  void *pv,
        /* [annotation][in] */
        _In_  ULONG cb,
        /* [annotation] */
        _Out_opt_  ULONG *pcbRead) override;

    virtual /* [local] */ HRESULT STDMETHODCALLTYPE Write(
        /* [annotation] */
        _In_reads_bytes_(cb)  const void *pv,
        /* [annotation][in] */
        _In_  ULONG cb,
        /* [annotation] */
        _Out_opt_  ULONG *pcbWritten) override;

    virtual /* [local] */ HRESULT STDMETHODCALLTYPE Seek(
        /* [in] */ LARGE_INTEGER dlibMove,
        /* [in] */ DWORD dwOrigin,
        /* [annotation] */
        _Out_opt_  ULARGE_INTEGER *plibNewPosition) override;

    virtual HRESULT STDMETHODCALLTYPE SetSize(
        /* [in] */ ULARGE_INTEGER libNewSize) override;

    virtual /* [local] */ HRESULT STDMETHODCALLTYPE CopyTo(
        /* [annotation][unique][in] */
        _In_  IStream *pstm,
        /* [in] */ ULARGE_INTEGER cb,
        /* [annotation] */
        _Out_opt_  ULARGE_INTEGER *pcbRead,
        /* [annotation] */
        _Out_opt_  ULARGE_INTEGER *pcbWritten) override;

    virtual HRESULT STDMETHODCALLTYPE Commit(
        /* [in] */ DWORD grfCommitFlags) override;

    virtual HRESULT STDMETHODCALLTYPE Revert(void) override;

    virtual HRESULT STDMETHODCALLTYPE LockRegion(
        /* [in] */ ULARGE_INTEGER libOffset,
        /* [in] */ ULARGE_INTEGER cb,
        /* [in] */ DWORD dwLockType) override;

    virtual HRESULT STDMETHODCALLTYPE UnlockRegion(
        /* [in] */ ULARGE_INTEGER libOffset,
        /* [in] */ ULARGE_INTEGER cb,
        /* [in] */ DWORD dwLockType) override;

    virtual HRESULT STDMETHODCALLTYPE Stat(
        /* [out] */ __RPC__out STATSTG *pstatstg,
        /* [in] */ DWORD grfStatFlag) override;

    virtual HRESULT STDMETHODCALLTYPE Clone(
        /* [out] */ __RPC__deref_out_opt IStream **ppstm) override;

    //Private Members
private:
    LONG m_cRef; // Reference count.
    std::vector<unsigned char> m_buffer;
    long m_buf_position = 0;
};

co_Stream.cpp

#include "co_Stream.h"
#include <iostream>
#include <mfplay.h>

co_Stream::co_Stream()
{
    m_cRef = 0;
}


co_Stream::~co_Stream()
{
}

HRESULT co_Stream::QueryInterface(REFIID riid, void ** ppvObject)
{
    if (riid == IID_IMFGetService)
    {
        *ppvObject = (LPVOID)this;
        AddRef();
        return NOERROR;
    }
    
    return E_NOINTERFACE;
}

ULONG co_Stream::AddRef(void)
{
    InterlockedIncrement(&m_cRef);
    return m_cRef;
}

ULONG co_Stream::Release(void)
{
    InterlockedDecrement(&m_cRef);
    return m_cRef;
}

HRESULT co_Stream::Read(void * pv, ULONG cb, ULONG * pcbRead)
{
    std::cout << "HERE" << std::endl;
    
    if (!m_buffer.empty() && m_buffer.size() < cb)
    {
        memcpy(pv, &m_buffer[0], cb);
        return NOERROR;
    }

    return ERROR;
}

HRESULT co_Stream::Write(const void * pv, ULONG cb, ULONG * pcbWritten)
{
    std::cout << "HERE" << std::endl;

    m_buffer.resize(cb);
    memcpy(&m_buffer[0], pv, cb);

    return NOERROR;
}

HRESULT co_Stream::Seek(LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER * plibNewPosition)
{
    std::cout << "HERE" << std::endl;
    return NOERROR;
}

HRESULT co_Stream::SetSize(ULARGE_INTEGER libNewSize)
{
    std::cout << "HERE" << std::endl;
    return NOERROR;
}

HRESULT co_Stream::CopyTo(IStream * pstm, ULARGE_INTEGER cb, ULARGE_INTEGER * pcbRead, ULARGE_INTEGER * pcbWritten)
{
    std::cout << "HERE" << std::endl;
    return NOERROR;
}

HRESULT co_Stream::Commit(DWORD grfCommitFlags)
{
    std::cout << "HERE" << std::endl;
    return NOERROR;
}

HRESULT co_Stream::Revert(void)
{
    std::cout << "HERE" << std::endl;
    return NOERROR;
}

HRESULT co_Stream::LockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
{
    std::cout << "HERE" << std::endl;
    return NOERROR;
}

HRESULT co_Stream::UnlockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
{
    std::cout << "HERE" << std::endl;
    return NOERROR;
}

HRESULT co_Stream::Stat(STATSTG * pstatstg, DWORD grfStatFlag)
{
    std::cout << "HERE" << std::endl;
    return NOERROR;
}

HRESULT co_Stream::Clone(IStream ** ppstm)
{
    std::cout << "HERE" << std::endl;
    return NOERROR;
}

The idea is that this method MFCreateMFByteStreamOnStream will take my implementation of IStream and return as out param IMFByteStream then I need to create a sink and finally sink writer. Then every time I'll call writer I get these bytes in my IStream implementation for further usage.

But instead after I call MFCreateMFByteStreamOnStream and pass my implementation of IStream as a param I get IMFByteStream - null as a out param.

In debug I see that in IStream implementation I get a call of QueryInterface -> AddRef -> Read() -> Release()

What am I doing wrong?

EDIT

There is my current implementation

#include "co_Stream.h"
#include <iostream>
#include <mfplay.h>

co_Stream::co_Stream()
{
    m_cRef = 0;
}


co_Stream::~co_Stream()
{
}

HRESULT co_Stream::QueryInterface(REFIID riid, void ** ppvObject)
{
    return E_NOINTERFACE;
}

ULONG co_Stream::AddRef(void)
{
    InterlockedIncrement(&m_cRef);
    return m_cRef;
}

ULONG co_Stream::Release(void)
{
    InterlockedDecrement(&m_cRef);
    return m_cRef;
}

HRESULT co_Stream::Read(void * pv, ULONG cb, ULONG * pcbRead)
{
    //This method is redundant in current implementation because it is needed only to write in buffer.
    return NOERROR;
}

HRESULT co_Stream::Write(const void * pv, ULONG cb, ULONG * pcbWritten)
{
    m_buffer.resize(cb);
    memcpy(&m_buffer[0], pv, cb);

    return NOERROR;
}

HRESULT co_Stream::Seek(LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER * plibNewPosition)
{
    std::cout << "HERE" << std::endl;
    return NOERROR;
}

HRESULT co_Stream::SetSize(ULARGE_INTEGER libNewSize)
{
    std::cout << "HERE" << std::endl;
    return NOERROR;
}

HRESULT co_Stream::CopyTo(IStream * pstm, ULARGE_INTEGER cb, ULARGE_INTEGER * pcbRead, ULARGE_INTEGER * pcbWritten)
{
    std::cout << "HERE" << std::endl;
    return NOERROR;
}

HRESULT co_Stream::Commit(DWORD grfCommitFlags)
{
    std::cout << "HERE" << std::endl;
    return NOERROR;
}

HRESULT co_Stream::Revert(void)
{
    std::cout << "HERE" << std::endl;
    return NOERROR;
}

HRESULT co_Stream::LockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
{
    std::cout << "HERE" << std::endl;
    return NOERROR;
}

HRESULT co_Stream::UnlockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
{
    std::cout << "HERE" << std::endl;
    return NOERROR;
}

HRESULT co_Stream::Stat(STATSTG * pstatstg, DWORD grfStatFlag)
{
    std::cout << "HERE" << std::endl;
    return NOERROR;
}

HRESULT co_Stream::Clone(IStream ** ppstm)
{
    std::cout << "HERE" << std::endl;
    return NOERROR;
}

When I get a call on my method co_AudioEncoderMF::start_encoding_to() (above in my question co_AudioEncoderMF::start_encoding_to) I get a call at seek and stat, but I don't get an idea how to implement in in case if I need to make a buffer implementation (std::vector<unsigned char> m_buffer).

But anyway currently I don't get any crash or errors, but also I am not getting call on my Write method.

Below in y code I have such a method

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

I see that pSample data exist as well as dwWriterStreamIndex has a value, but when this method invoke I don't get a Write call in my implementation of co_Stream

来源:https://stackoverflow.com/questions/65458867/how-to-make-implementation-of-istream-correctly-mediafoundation

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!