void TransformImage_RGB32( BYTE* pDest, LONG lDestStride, const BYTE* pSrc, LONG lSrcStride, DWORD dwWidthInPixels, DWORD dwHeightInPixels ) { MFCopyImage(pDest, lDestStride, pSrc, lSrcStride, dwWidthInPixels * 4, dwHeightInPixels); }
HRESULT VideoEncoder::WriteTransitionSample(UINT64 sampleDuration, TransitionBase* pTransition, DWORD streamIndex, LONGLONG* startTime) { HRESULT hr = S_OK; IMFMediaBuffer* pMediaBuffer = nullptr; BYTE* pFrameBuffer = nullptr; IMFSample* pSample = nullptr; BYTE* pOutputFrame = nullptr; for (DWORD i = 0; i < sampleDuration; i++) { CheckHR(MFCreateMemoryBuffer(this->m_frameBufferSize, &pMediaBuffer)); pMediaBuffer->Lock(&pFrameBuffer, nullptr, nullptr); float time = (float)i / (float)sampleDuration; pOutputFrame = pTransition->GetOutputFrame(time); CheckHR(MFCopyImage(pFrameBuffer, this->m_frameStride, pOutputFrame, this->m_frameStride, this->m_frameStride, this->m_frameHeight)); CheckHR(pMediaBuffer->Unlock()); CheckHR(pMediaBuffer->SetCurrentLength(this->m_frameBufferSize)); CheckHR(MFCreateSample(&pSample)); CheckHR(pSample->AddBuffer(pMediaBuffer)); CheckHR(pSample->SetSampleTime(*startTime)); CheckHR(pSample->SetSampleDuration(this->GetFrameDuration())); CheckHR(this->m_pSinkWriter->WriteSample(streamIndex, pSample)); (*startTime) += this->GetFrameDuration(); // 释放示例资源. SafeRelease(&pMediaBuffer); SafeRelease(&pSample); if (pOutputFrame != nullptr) { delete pOutputFrame; pOutputFrame = nullptr; } } cleanup: if (!SUCCEEDED(hr)) { DWORD error = GetLastError(); this->m_logFileStream << "意外错误: " << error << endl; } SafeRelease(&pMediaBuffer); SafeRelease(&pSample); if (pOutputFrame != nullptr) { delete pOutputFrame; pOutputFrame = nullptr; } return hr; }
// Create a new sample for mft input from segemtation image buffer and pass in the timestamp HRESULT EncodeTransform::AddSample(const LONGLONG& rtStart) { VTUNE_TASK(g_pDomain, "AddSample"); const LONG cYUY2WidthBytes = mStreamWidth * 2; // halfwidth * 4 const DWORD cbBuffer = cYUY2WidthBytes * mStreamHeight; BYTE *pData = NULL; // Lock the buffer and copy the video frame to the buffer. HRESULT hr = mpInputBuffer->Lock(&pData, NULL, NULL); if (SUCCEEDED(hr)) { hr = MFCopyImage( pData, // Destination buffer. cYUY2WidthBytes, // Destination stride. (BYTE*)mCompressedBuffer, // First row in source image. cYUY2WidthBytes, // Source stride. cYUY2WidthBytes, // Image width in bytes. mStreamHeight // Image height in pixels. ); hr = mpInputBuffer->Unlock(); } // Set the data length of the buffer. if (SUCCEEDED(hr)) { hr = mpInputBuffer->SetCurrentLength(cbBuffer); } // Set the time stamp and the duration. if (SUCCEEDED(hr)) { hr = pSampleProcIn->SetSampleTime(rtStart); } if (SUCCEEDED(hr)) { hr = pSampleProcIn->SetSampleDuration(VIDEO_FRAME_DURATION); } hr = mpEncoder->ProcessInput(mInputStreamID, pSampleProcIn, NULL); return hr; }
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; }