HRESULT WMFAACDecoder::CreateInputSample(const uint8_t* aData, uint32_t aDataSize, Microseconds aTimestamp, IMFSample** aOutSample) { HRESULT hr; CComPtr<IMFSample> sample = nullptr; hr = MFCreateSample(&sample); ENSURE(SUCCEEDED(hr), hr); CComPtr<IMFMediaBuffer> buffer = nullptr; int32_t bufferSize = std::max<uint32_t>(uint32_t(mInputStreamInfo.cbSize), aDataSize); UINT32 alignment = (mInputStreamInfo.cbAlignment > 1) ? mInputStreamInfo.cbAlignment - 1 : 0; hr = MFCreateAlignedMemoryBuffer(bufferSize, alignment, &buffer); ENSURE(SUCCEEDED(hr), hr); DWORD maxLength = 0; DWORD currentLength = 0; BYTE* dst = nullptr; hr = buffer->Lock(&dst, &maxLength, ¤tLength); ENSURE(SUCCEEDED(hr), hr); // Copy data into sample's buffer. memcpy(dst, aData, aDataSize); hr = buffer->Unlock(); ENSURE(SUCCEEDED(hr), hr); hr = buffer->SetCurrentLength(aDataSize); ENSURE(SUCCEEDED(hr), hr); hr = sample->AddBuffer(buffer); ENSURE(SUCCEEDED(hr), hr); hr = sample->SetSampleTime(UsecsToHNs(aTimestamp)); ENSURE(SUCCEEDED(hr), hr); *aOutSample = sample.Detach(); return S_OK; }
HRESULT WMFAACDecoder::CreateOutputSample(IMFSample** aOutSample) { HRESULT hr; CComPtr<IMFSample> sample = nullptr; hr = MFCreateSample(&sample); ENSURE(SUCCEEDED(hr), hr); CComPtr<IMFMediaBuffer> buffer = nullptr; int32_t bufferSize = mOutputStreamInfo.cbSize; UINT32 alignment = (mOutputStreamInfo.cbAlignment > 1) ? mOutputStreamInfo.cbAlignment - 1 : 0; hr = MFCreateAlignedMemoryBuffer(bufferSize, alignment, &buffer); ENSURE(SUCCEEDED(hr), hr); hr = sample->AddBuffer(buffer); ENSURE(SUCCEEDED(hr), hr); *aOutSample = sample.Detach(); return S_OK; }
void MfVideoEncoder::WriteFrame(uint8_t* data, int stride) { CComPtr<IMFSample> pSample; CComPtr<IMFMediaBuffer> pBuffer; const LONG cbWidth = 4 * mWidth; const DWORD cbBuffer = cbWidth * mHeight; BYTE *pData = NULL; // Create a new memory buffer. HRESULT hr = MFCreateMemoryBuffer(cbBuffer, &pBuffer); // Lock the buffer and copy the video frame to the buffer. if (SUCCEEDED(hr)) { hr = pBuffer->Lock(&pData, NULL, NULL); } if (SUCCEEDED(hr)) { hr = MFCopyImage( pData, // Destination buffer. cbWidth, // Destination stride. (BYTE*)data, // First row in source image. stride, // Source stride. cbWidth, // Image width in bytes. mHeight // Image height in pixels. ); } if (pBuffer) { pBuffer->Unlock(); } // Set the data length of the buffer. if (SUCCEEDED(hr)) { hr = pBuffer->SetCurrentLength(cbBuffer); } // Create a media sample and add the buffer to the sample. if (SUCCEEDED(hr)) { hr = MFCreateSample(&pSample); } if (SUCCEEDED(hr)) { hr = pSample->AddBuffer(pBuffer); } // Set the time stamp and the duration. if (SUCCEEDED(hr)) { hr = pSample->SetSampleTime(mCurrentTime); } if (SUCCEEDED(hr)) { hr = pSample->SetSampleDuration(mFrameTime); } // Send the sample to the Sink Writer. if (SUCCEEDED(hr)) { hr = mSinkWriter->WriteSample(mStreamIndex, pSample); } if (!SUCCEEDED(hr)) { throw TempleException("Unable to write video frame: {}", hr); } mCurrentTime += mFrameTime; }