Media Foundationを使用する場合、「unsigned char const *」から読み取る方法は?
私はそのような実装を持っています
void coAudioPlayerSampleGrabber::test(SoundDataType dataType,
unsigned char const * pData,
int64_t dataLen)
{
HeapSetInformation(NULL, HeapEnableTerminationOnCorruption, NULL, 0);
IMFSourceReader *pReader = NULL;
IMFByteStream * spByteStream = NULL;
HRESULT hr = S_OK;
// Initialize the COM library.
hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
// Initialize the Media Foundation platform.
if (SUCCEEDED(hr))
{
hr = MFStartup(MF_VERSION);
}
hr = MFCreateMFByteStreamOnStreamEx((IUnknown*)pData, &spByteStream);
if (FAILED(hr))
{
printf("Error MFCreateMFByteStreamOnStreamEx");
}
IMFAttributes * Atrr = NULL;
hr = MFCreateAttributes(&Atrr, 10);
if (FAILED(hr))
{
printf("Error MFCreateAttributes");
}
hr = Atrr->SetUINT32(MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS, true);
if (FAILED(hr))
{
printf("Error Atrr->SetUINT32(MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS, true)");
}
hr = MFCreateSourceReaderFromByteStream(spByteStream, Atrr, &pReader);
if (FAILED(hr))
{
printf("Error MFCreateSourceReaderFromByteStream");
}
if (FAILED(hr))
{
printf("Error opening input file");
}
IMFMediaType *pAudioType = NULL; // Represents the PCM audio format.
hr = ConfigureAudioStream(dataType, pReader, &pAudioType);
if (FAILED(hr))
{
printf("Error ConfigureAudioStream");
}
IMFSample *pSample = NULL;
IMFMediaBuffer *pBuffer = NULL;
BYTE *pAudioData = NULL;
DWORD cbBuffer = 0;
std::vector<SampleData> samples_vec;
while (true)
{
DWORD dwFlags = 0;
hr = pReader->ReadSample((DWORD)MF_SOURCE_READER_FIRST_AUDIO_STREAM, 0, NULL, &dwFlags, NULL, &pSample);
if (FAILED(hr)) { break; }
if (dwFlags & MF_SOURCE_READERF_CURRENTMEDIATYPECHANGED)
{
printf("Type change - not supported by WAVE file format.\n");
break;
}
if (dwFlags & MF_SOURCE_READERF_ENDOFSTREAM)
{
printf("End of input file.\n");
break;
}
hr = pSample->ConvertToContiguousBuffer(&pBuffer);
if (FAILED(hr)) { break; }
hr = pBuffer->Lock(&pAudioData, NULL, &cbBuffer);
if (FAILED(hr)) { break; }
//Do something with the pAudioData which is an array of unsigned chars of lenth cbBuffer
SampleData tmp;
tmp.pAudioData = new byte[cbBuffer];
memcpy(tmp.pAudioData, pAudioData, cbBuffer);
tmp.cbBuffer = cbBuffer;
samples_vec.push_back(tmp);
// Unlock the buffer.
hr = pBuffer->Unlock();
pAudioData = NULL;
if (FAILED(hr)) { break; }
}
SafeRelease(&pReader);
SafeRelease(&pSample);
SafeRelease(&pBuffer);
SafeRelease(&spByteStream);
SafeRelease(&Atrr);
// Shut down Media Foundation.
MFShutdown();
CoUninitialize();
}
ご覧のとおり、データとサイズへのポインタがあります。これは実際には、デコードする必要のあるデータです。問題はここにあることです
hr = MFCreateMFByteStreamOnStreamEx((IUnknown*)pData, &spByteStream);
エラーが発生しました。access violation
これは、に変換しようとしたためです。質問は-それを正しく変換する方法は?pData
IUnknown*
回答
このように角を切ることはできません:
unsigned char const * pData;
...
hr = MFCreateMFByteStreamOnStreamEx((IUnknown*)pData, &spByteStream);
IUnknown
バイトのもう1つの派手なエイリアスではありません。文書化されているように、ストリームを表すインターフェイスポインタを文字通り提供することになっています。
Media Foundationは、メモリバイトから読み取る手段を提供します。あなたは本当のストリームを作成し、作成する必要があるIStream
か、IRandomAccessStream
またはIMFByteStream
docuemntationごと。また、IMFAttributes
データ型を指定するための適切な属性(ファイルの場合は拡張子またはMIMEタイプから派生)を作成したものを提供すると、ソースリーダーAPIはメディアファイルデータのソースとしてメモリバイトを処理でき、適切なデコーダー(に似たPCMデータにオーディオデコードうこの)。
あなたが実際に素早く行うことができます何か:CreateStreamOnHGlobal作成するためのIStream
実装を、基礎となるバッファにあなたのバイトをコピー(ドキュメントを参照してください)。次にMFCreateMFByteStreamOnStream、IMFByteStream
その上にwrapprを作成し、このラッパーをMFCreateSourceReaderFromByteStream
引数として使用できます。
私はそのようなものにVectorStreamクラスを使用していました。一部の関数は実装されていませんが、基本的な考え方を理解する必要があります。
class VectorStream : public IStream
{
public:
bool ReadOnly = false;
ULONG r = 1;
std::vector<char> d;
size_t p = 0;
VectorStream()
{
}
void Clear()
{
d.clear();
p = 0;
}
// IUnknown
virtual HRESULT STDMETHODCALLTYPE QueryInterface(
/* [in] */ REFIID riid,
/* [iid_is][out] */ _COM_Outptr_ void __RPC_FAR* __RPC_FAR* ppvObject)
{
if (riid == __uuidof(IUnknown) || riid == __uuidof(IStream))
{
*ppvObject = (IStream*)this;
r++;
return S_OK;
}
return E_NOINTERFACE;
}
virtual ULONG STDMETHODCALLTYPE AddRef(void)
{
return ++r;
}
virtual ULONG STDMETHODCALLTYPE Release(void)
{
return --r;
}
HRESULT __stdcall Clone(
IStream** ppstm
)
{
return E_NOTIMPL;
}
HRESULT __stdcall Commit(
DWORD grfCommitFlags
)
{
return S_OK;
}
HRESULT __stdcall CopyTo(
IStream* pstm,
ULARGE_INTEGER cb,
ULARGE_INTEGER* pcbRead,
ULARGE_INTEGER* pcbWritten
)
{
return E_NOINTERFACE;
}
HRESULT __stdcall LockRegion(
ULARGE_INTEGER libOffset,
ULARGE_INTEGER cb,
DWORD dwLockType
)
{
return S_OK;
}
HRESULT __stdcall UnlockRegion(
ULARGE_INTEGER libOffset,
ULARGE_INTEGER cb,
DWORD dwLockType
)
{
return S_OK;
}
HRESULT __stdcall Revert()
{
return E_NOTIMPL;
}
HRESULT __stdcall Seek(
LARGE_INTEGER dlibMove,
DWORD dwOrigin,
ULARGE_INTEGER* plibNewPosition
)
{
LARGE_INTEGER lo = { 0 };
if (dwOrigin == STREAM_SEEK_SET)
{
p = dlibMove.QuadPart;
}
if (dwOrigin == STREAM_SEEK_CUR)
{
p += dlibMove.QuadPart;
}
if (dwOrigin == STREAM_SEEK_END)
{
p = d.size() - dlibMove.QuadPart;
}
if (p >= d.size())
p = d.size();
if (plibNewPosition)
plibNewPosition->QuadPart = p;
return S_OK;
}
HRESULT __stdcall SetSize(
ULARGE_INTEGER libNewSize
)
{
d.resize(libNewSize.QuadPart);
return S_OK;
}
int eb = 0;
HRESULT __stdcall Stat(
STATSTG* pstatstg,
DWORD grfStatFlag
)
{
pstatstg->type = STGTY_STREAM;
pstatstg->cbSize.QuadPart = d.size();
pstatstg->grfLocksSupported = true;
return S_OK;
}
unsigned long long readbytes = 0;
HRESULT __stdcall Read(
void* pv,
ULONG cb,
ULONG* pcbRead
)
{
auto av = d.size() - p;
if (cb < av)
av = cb;
memcpy(pv, d.data() + p, av);
p += av;
if (pcbRead)
*pcbRead = (ULONG)av;
// if (av < cb)
// return S_FALSE;
return S_OK;
}
HRESULT __stdcall Write(
const void* pv,
ULONG cb,
ULONG* pcbWritten
)
{
if (ReadOnly)
return STG_E_ACCESSDENIED;
if (d.size() < (p + cb))
{
auto exc = (p + cb) - d.size();
d.resize(d.size() + exc);
}
memcpy(d.data() + p, pv, cb);
p += cb;
if (pcbWritten)
*pcbWritten = cb;
return S_OK;
}
};
std :: vector <>をIStreamにカプセル化します。