问题描述
总体思路是获取一个 IMFSinkWriter
将数据写入缓冲区。有这样一个实现
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;
}
在这里我创建了一个实现 co_Stream
的类 IStream
(一个最小的实现,仅用于测试)
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] */
_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] */ DWORD dwLockType) override;
virtual HRESULT STDMETHODCALLTYPE UnlockRegion(
/* [in] */ ULARGE_INTEGER libOffset,/* [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 * 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,DWORD dwLockType)
{
std::cout << "HERE" << std::endl;
return NOERROR;
}
HRESULT co_Stream::UnlockRegion(ULARGE_INTEGER libOffset,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;
}
这个想法是,这个方法 MFCreateMFByteStreamOnStream
将采用我的 IStream
实现并作为 out param IMFByteStream
返回,然后我需要创建一个接收器,最后创建接收器编写器。然后,每次我调用 writer 时,我都会在 IStream
实现中获取这些字节以供进一步使用。
但是在我调用 MFCreateMFByteStreamOnStream
并将 IStream
的实现作为参数传递后,我得到 IMFByteStream
- null 作为输出参数。
在调试中,我看到在 IStream
实现中,我收到了 QueryInterface
-> AddRef
-> Read()
-> Release()
我做错了什么?
编辑
这是我目前的实现
#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 * 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 * pcbWritten)
{
m_buffer.resize(cb);
memcpy(&m_buffer[0],DWORD grfStatFlag)
{
std::cout << "HERE" << std::endl;
return NOERROR;
}
HRESULT co_Stream::Clone(IStream ** ppstm)
{
std::cout << "HERE" << std::endl;
return NOERROR;
}
当我的方法 co_AudioEncoderMF::start_encoding_to()
(在我的问题 co_AudioEncoderMF::start_encoding_to 上)接到电话时,我在 seek
和 stat
收到电话,但我没有收到如果我需要进行缓冲区实现 (std::vector<unsigned char> m_buffer
),请了解如何实现。
但无论如何,目前我没有遇到任何崩溃或错误,而且我的 Write
方法也没有被调用。
在y代码下面我有这样的方法
...
hr = sink_writer->WriteSample(
dwWriterStreamIndex,pSample
);
...
我看到 pSample
数据存在并且 dwWriterStreamIndex
具有值,但是当调用此方法时,我在 {{1} 的实现中没有收到 Write
调用}
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)