HRESULT GetSampleFromMFStreamer(/* out */ const vpx_codec_cx_pkt_t *& vpkt) { //printf("Get Sample...\n"); IMFSample *videoSample = NULL; // Initial read results in a null pSample?? CHECK_HR(videoReader->ReadSample( MF_SOURCE_READER_ANY_STREAM, // Stream index. 0, // Flags. &streamIndex, // Receives the actual stream index. &flags, // Receives status flags. &llVideoTimeStamp, // Receives the time stamp. &videoSample // Receives the sample or NULL. ), L"Error reading video sample."); if (!videoSample) { printf("Failed to get video sample from MF.\n"); } else { DWORD nCurrBufferCount = 0; CHECK_HR(videoSample->GetBufferCount(&nCurrBufferCount), L"Failed to get the buffer count from the video sample.\n"); IMFMediaBuffer * pMediaBuffer; CHECK_HR(videoSample->ConvertToContiguousBuffer(&pMediaBuffer), L"Failed to extract the video sample into a raw buffer.\n"); DWORD nCurrLen = 0; CHECK_HR(pMediaBuffer->GetCurrentLength(&nCurrLen), L"Failed to get the length of the raw buffer holding the video sample.\n"); byte *imgBuff; DWORD buffCurrLen = 0; DWORD buffMaxLen = 0; pMediaBuffer->Lock(&imgBuff, &buffMaxLen, &buffCurrLen); /*BYTE *i420 = new BYTE[4608000]; YUY2ToI420(WIDTH, HEIGHT, STRIDE, imgBuff, i420); vpx_image_t* img = vpx_img_wrap(&_rawImage, VIDEO_INPUT_FORMAT, _vpxConfig.g_w, _vpxConfig.g_h, 1, i420);*/ vpx_image_t* const img = vpx_img_wrap(&_rawImage, VIDEO_INPUT_FORMAT, _vpxConfig.g_w, _vpxConfig.g_h, 1, imgBuff); const vpx_codec_cx_pkt_t * pkt; vpx_enc_frame_flags_t flags = 0; if (vpx_codec_encode(&_vpxCodec, &_rawImage, _sampleCount, 1, flags, VPX_DL_REALTIME)) { printf("VPX codec failed to encode the frame.\n"); return -1; } else { vpx_codec_iter_t iter = NULL; while ((pkt = vpx_codec_get_cx_data(&_vpxCodec, &iter))) { switch (pkt->kind) { case VPX_CODEC_CX_FRAME_PKT: vpkt = pkt; // const_cast<vpx_codec_cx_pkt_t **>(&pkt); break; default: break; } printf("%s %i\n", pkt->kind == VPX_CODEC_CX_FRAME_PKT && (pkt->data.frame.flags & VPX_FRAME_IS_KEY) ? "K" : ".", pkt->data.frame.sz); } } _sampleCount++; vpx_img_free(img); pMediaBuffer->Unlock(); pMediaBuffer->Release(); //delete i420; videoSample->Release(); return S_OK; } }
SINT SoundSourceMediaFoundation::readSampleFrames( SINT numberOfFrames, CSAMPLE* sampleBuffer) { SINT numberOfFramesRemaining = numberOfFrames; CSAMPLE* pSampleBuffer = sampleBuffer; while (numberOfFramesRemaining > 0) { SampleBuffer::ReadableChunk readableChunk( m_sampleBuffer.readFromHead( frames2samples(numberOfFramesRemaining))); DEBUG_ASSERT(readableChunk.size() <= frames2samples(numberOfFramesRemaining)); if (readableChunk.size() > 0) { DEBUG_ASSERT(m_currentFrameIndex < getMaxFrameIndex()); if (sampleBuffer != nullptr) { SampleUtil::copy( pSampleBuffer, readableChunk.data(), readableChunk.size()); pSampleBuffer += readableChunk.size(); } m_currentFrameIndex += samples2frames(readableChunk.size()); numberOfFramesRemaining -= samples2frames(readableChunk.size()); } if (numberOfFramesRemaining == 0) { break; // finished reading } // No more decoded sample frames available DEBUG_ASSERT(m_sampleBuffer.isEmpty()); if (m_pSourceReader == nullptr) { break; // abort if reader is dead } DWORD dwFlags = 0; LONGLONG streamPos = 0; IMFSample* pSample = nullptr; HRESULT hrReadSample = m_pSourceReader->ReadSample( kStreamIndex, // [in] DWORD dwStreamIndex, 0, // [in] DWORD dwControlFlags, nullptr, // [out] DWORD *pdwActualStreamIndex, &dwFlags, // [out] DWORD *pdwStreamFlags, &streamPos, // [out] LONGLONG *pllTimestamp, &pSample); // [out] IMFSample **ppSample if (FAILED(hrReadSample)) { qWarning() << kLogPreamble << "IMFSourceReader::ReadSample() failed" << hrReadSample << "-> abort decoding"; DEBUG_ASSERT(pSample == nullptr); break; // abort } if (dwFlags & MF_SOURCE_READERF_ERROR) { qWarning() << kLogPreamble << "IMFSourceReader::ReadSample()" << "detected stream errors" << "(MF_SOURCE_READERF_ERROR)" << "-> abort and stop decoding"; DEBUG_ASSERT(pSample == nullptr); safeRelease(&m_pSourceReader); // kill the reader break; // abort } else if (dwFlags & MF_SOURCE_READERF_ENDOFSTREAM) { DEBUG_ASSERT(pSample == nullptr); break; // finished reading } else if (dwFlags & MF_SOURCE_READERF_CURRENTMEDIATYPECHANGED) { qWarning() << kLogPreamble << "IMFSourceReader::ReadSample()" << "detected that the media type has changed" << "(MF_SOURCE_READERF_CURRENTMEDIATYPECHANGED)" << "-> abort decoding"; DEBUG_ASSERT(pSample == nullptr); break; // abort } DEBUG_ASSERT(pSample != nullptr); SINT readerFrameIndex = m_streamUnitConverter.toFrameIndex(streamPos); DEBUG_ASSERT( (m_currentFrameIndex == getMaxFrameIndex()) || // unknown position after seeking (m_currentFrameIndex == readerFrameIndex)); m_currentFrameIndex = readerFrameIndex; DWORD dwSampleBufferCount = 0; HRESULT hrGetBufferCount = pSample->GetBufferCount(&dwSampleBufferCount); if (FAILED(hrGetBufferCount)) { qWarning() << kLogPreamble << "IMFSample::GetBufferCount() failed" << hrGetBufferCount << "-> abort decoding"; safeRelease(&pSample); break; // abort } DWORD dwSampleTotalLengthInBytes = 0; HRESULT hrGetTotalLength = pSample->GetTotalLength(&dwSampleTotalLengthInBytes); if (FAILED(hrGetTotalLength)) { qWarning() << kLogPreamble << "IMFSample::GetTotalLength() failed" << hrGetTotalLength << "-> abort decoding"; safeRelease(&pSample); break; // abort } // Enlarge temporary buffer (if necessary) DEBUG_ASSERT((dwSampleTotalLengthInBytes % kBytesPerSample) == 0); SINT numberOfSamplesToBuffer = dwSampleTotalLengthInBytes / kBytesPerSample; SINT sampleBufferCapacity = m_sampleBuffer.getCapacity(); DEBUG_ASSERT(sampleBufferCapacity > 0); while (sampleBufferCapacity < numberOfSamplesToBuffer) { sampleBufferCapacity *= 2; } if (m_sampleBuffer.getCapacity() < sampleBufferCapacity) { qDebug() << kLogPreamble << "Enlarging sample buffer capacity" << m_sampleBuffer.getCapacity() << "->" << sampleBufferCapacity; m_sampleBuffer.resetCapacity(sampleBufferCapacity); } DWORD dwSampleBufferIndex = 0; while (dwSampleBufferIndex < dwSampleBufferCount) { IMFMediaBuffer* pMediaBuffer = nullptr; HRESULT hrGetBufferByIndex = pSample->GetBufferByIndex(dwSampleBufferIndex, &pMediaBuffer); if (FAILED(hrGetBufferByIndex)) { qWarning() << kLogPreamble << "IMFSample::GetBufferByIndex() failed" << hrGetBufferByIndex << "-> abort decoding"; DEBUG_ASSERT(pMediaBuffer == nullptr); break; // prematurely exit buffer loop } CSAMPLE* pLockedSampleBuffer = nullptr; DWORD lockedSampleBufferLengthInBytes = 0; HRESULT hrLock = pMediaBuffer->Lock( reinterpret_cast<quint8**>(&pLockedSampleBuffer), nullptr, &lockedSampleBufferLengthInBytes); if (FAILED(hrLock)) { qWarning() << kLogPreamble << "IMFMediaBuffer::Lock() failed" << hrLock << "-> abort decoding"; safeRelease(&pMediaBuffer); break; // prematurely exit buffer loop } DEBUG_ASSERT((lockedSampleBufferLengthInBytes % sizeof(pLockedSampleBuffer[0])) == 0); SINT lockedSampleBufferCount = lockedSampleBufferLengthInBytes / sizeof(pLockedSampleBuffer[0]); SINT copySamplesCount = std::min( frames2samples(numberOfFramesRemaining), lockedSampleBufferCount); if (copySamplesCount > 0) { // Copy samples directly into output buffer if possible if (pSampleBuffer != nullptr) { SampleUtil::copy( pSampleBuffer, pLockedSampleBuffer, copySamplesCount); pSampleBuffer += copySamplesCount; } pLockedSampleBuffer += copySamplesCount; lockedSampleBufferCount -= copySamplesCount; m_currentFrameIndex += samples2frames(copySamplesCount); numberOfFramesRemaining -= samples2frames(copySamplesCount); } // Buffer the remaining samples SampleBuffer::WritableChunk writableChunk( m_sampleBuffer.writeToTail(lockedSampleBufferCount)); // The required capacity has been calculated in advance (see above) DEBUG_ASSERT(writableChunk.size() == lockedSampleBufferCount); SampleUtil::copy( writableChunk.data(), pLockedSampleBuffer, writableChunk.size()); HRESULT hrUnlock = pMediaBuffer->Unlock(); VERIFY_OR_DEBUG_ASSERT(SUCCEEDED(hrUnlock)) { qWarning() << kLogPreamble << "IMFMediaBuffer::Unlock() failed" << hrUnlock; // ignore and continue } safeRelease(&pMediaBuffer); ++dwSampleBufferIndex; } safeRelease(&pSample); if (dwSampleBufferIndex < dwSampleBufferCount) { // Failed to read data from all buffers -> kill the reader qWarning() << kLogPreamble << "Failed to read all buffered samples" << "-> abort and stop decoding"; safeRelease(&m_pSourceReader); break; // abort } } return numberOfFrames - numberOfFramesRemaining; }