问题
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