STDMETHODIMP FakeOutputPin::PushBuffer(byte *buffer, __int64 start, __int64 stop, unsigned int size, bool discont) { IMediaSample *pSample = NULL; if (start != -1) { start /= 100; stop /= 100; } HRESULT hres = GetDeliveryBuffer(&pSample, NULL, NULL, 0); if (hres == S_OK && pSample) { BYTE *sample_buffer; pSample->GetPointer(&sample_buffer); if(sample_buffer) { memcpy (sample_buffer, buffer, size); pSample->SetActualDataLength(size); } pSample->SetDiscontinuity(discont); pSample->SetSyncPoint(TRUE); pSample->SetPreroll(FALSE); if (start != -1) pSample->SetTime(&start, &stop); hres = Deliver(pSample); pSample->Release(); } return S_OK; }
HRESULT CTSParserOutputPin::SendOut( DWORD nGroupFlag, const BYTE* pData, DWORD dwBytes, DWORD* dwUsedBytes ) { IMediaSample *pSample; BYTE *pSampleData; DWORD cbData; *dwUsedBytes = 0; HRESULT hr = GetDeliveryBuffer(&pSample,NULL,NULL,0); if (FAILED(hr)) return E_FAIL; pSample->GetPointer(&pSampleData); cbData = pSample->GetSize(); if ( cbData < dwBytes ) { dwBytes = cbData; ASSERT( 0 ); } memcpy( pSampleData, pData, dwBytes ); pSample->SetActualDataLength( dwBytes ); *dwUsedBytes = dwBytes; hr = Deliver(pSample); pSample->Release(); return S_OK; }
HRESULT CPushAudioPin::DoBufferProcessingLoop(void) { Command com; OnThreadStartPlay(); do { while (!CheckRequest(&com)) { HRESULT hr; CAutoLock lock(&m_cSharedState); if( WaitForSingleObject( this->buffLockEvent, 500 ) == WAIT_OBJECT_0 ){ if( this->buffData.size() != 0 ){ if( this->buffLockEvent != NULL ){ SetEvent(this->buffLockEvent); } IMediaSample *pSample; hr = GetDeliveryBuffer(&pSample,NULL,NULL,0); if (FAILED(hr)) { Sleep(1); continue; } hr = FillBuffer(pSample); if (hr == S_OK) { hr = Deliver(pSample); pSample->Release(); if(hr != S_OK) { return S_OK; } } else if (hr == S_FALSE) { pSample->Release(); DeliverEndOfStream(); return S_OK; } else { pSample->Release(); DeliverEndOfStream(); m_pFilter->NotifyEvent(EC_ERRORABORT, hr, 0); return hr; } }else{ if( this->buffLockEvent != NULL ){ SetEvent(this->buffLockEvent); } Sleep(10); } } } // For all commands sent to us there must be a Reply call! if (com == CMD_RUN || com == CMD_PAUSE) { Reply(NOERROR); } else if (com != CMD_STOP) { Reply((DWORD) E_UNEXPECTED); } } while (com != CMD_STOP); return S_FALSE; }
HRESULT OutputPin::Push(void *buf, long size) { HRESULT hr; IMediaSample *pSample; VIDEOINFOHEADER *vi; AM_MEDIA_TYPE *pmt; BYTE *dst_buf; /** * Hold the critical section here as the pin might get disconnected * during the Deliver() method call. */ m_pLock->Lock(); hr = GetDeliveryBuffer(&pSample, NULL, NULL, 0); if (FAILED(hr)) goto on_error; pSample->GetMediaType(&pmt); if (pmt) { mediaType.Set(*pmt); bufSize = pmt->lSampleSize; } pSample->GetPointer(&dst_buf); vi = (VIDEOINFOHEADER *)mediaType.pbFormat; if (vi->rcSource.right == vi->bmiHeader.biWidth) { assert(pSample->GetSize() >= size); memcpy(dst_buf, buf, size); } else { unsigned i, bpp; unsigned dststride, srcstride; BYTE *src_buf = (BYTE *)buf; bpp = size / abs(vi->bmiHeader.biHeight) / vi->rcSource.right; dststride = vi->bmiHeader.biWidth * bpp; srcstride = vi->rcSource.right * bpp; for (i = abs(vi->bmiHeader.biHeight); i > 0; i--) { memcpy(dst_buf, src_buf, srcstride); dst_buf += dststride; src_buf += srcstride; } } pSample->SetActualDataLength(size); hr = Deliver(pSample); pSample->Release(); on_error: m_pLock->Unlock(); return hr; }
HRESULT COutputPin::DeliverSample(GstBuffer *pBuffer) { HRESULT hr = S_OK; IMediaSample *pSample = NULL; REFERENCE_TIME start = -1; REFERENCE_TIME stop = -1; hr = m_pAlloc->SetGstBuffer(pBuffer); if (FAILED(hr)) return hr; hr = GetDeliveryBuffer(&pSample, NULL, NULL, 0); if (FAILED(hr)) return hr; // Set media time pSample->SetMediaTime(NULL, NULL); // Set time if (GST_BUFFER_TIMESTAMP_IS_VALID(pBuffer)) { start = GST_BUFFER_TIMESTAMP(pBuffer) / 100; if (GST_BUFFER_DURATION_IS_VALID(pBuffer)) { stop = (GST_BUFFER_TIMESTAMP(pBuffer) + GST_BUFFER_DURATION(pBuffer)) / 100; } else { stop = start + 1; } if (stop <= start) // Sometimes it may happen stop = start + 1; pSample->SetTime(&start, &stop); } else { pSample->SetTime(NULL, NULL); } if (GST_BUFFER_IS_DISCONT(pBuffer)) pSample->SetDiscontinuity(TRUE); hr = Deliver(pSample); pSample->Release(); if (FAILED(hr)) return hr; return S_OK; }
HRESULT CDXVADecoder::DisplayNextFrame() { HRESULT hr = S_FALSE; CComPtr<IMediaSample> pSampleToDeliver; int nPicIndex; nPicIndex = FindOldestFrame(); if (nPicIndex != -1) { if (m_pPictureStore[nPicIndex].rtStart >= 0) { switch (m_nEngine) { case ENGINE_DXVA1 : // For DXVA1, query a media sample at the last time (only one in the allocator) hr = GetDeliveryBuffer (m_pPictureStore[nPicIndex].rtStart, m_pPictureStore[nPicIndex].rtStop, &pSampleToDeliver); SetTypeSpecificFlags(&m_pPictureStore[nPicIndex], pSampleToDeliver); if (SUCCEEDED (hr)) { hr = m_pAMVideoAccelerator->DisplayFrame(nPicIndex, pSampleToDeliver); } break; case ENGINE_DXVA2 : // For DXVA2 media sample is in the picture store m_pPictureStore[nPicIndex].pSample->SetTime (&m_pPictureStore[nPicIndex].rtStart, &m_pPictureStore[nPicIndex].rtStop); SetTypeSpecificFlags(&m_pPictureStore[nPicIndex], m_pPictureStore[nPicIndex].pSample); hr = m_pFilter->GetOutputPin()->Deliver(m_pPictureStore[nPicIndex].pSample); break; } #if defined(_DEBUG) && 0 static REFERENCE_TIME rtLast = 0; TRACE ("Deliver : %10I64d - %10I64d (Dur = %10I64d) {Delta = %10I64d} Ind = %02d Codec=%d Ref=%d\n", m_pPictureStore[nPicIndex].rtStart, m_pPictureStore[nPicIndex].rtStop, m_pPictureStore[nPicIndex].rtStop - m_pPictureStore[nPicIndex].rtStart, m_pPictureStore[nPicIndex].rtStart - rtLast, nPicIndex, m_pPictureStore[nPicIndex].nCodecSpecific, m_pPictureStore[nPicIndex].bRefPicture); rtLast = m_pPictureStore[nPicIndex].rtStart; #endif } m_bNeedChangeAspect = false; m_pPictureStore[nPicIndex].bDisplayed = true; if (!m_pPictureStore[nPicIndex].bRefPicture) { FreePictureSlot (nPicIndex); } } return hr; }
HRESULT CDXVADecoder::GetFreeSurfaceIndex(int& nSurfaceIndex, IMediaSample** ppSampleToDeliver, REFERENCE_TIME rtStart, REFERENCE_TIME rtStop) { HRESULT hr = E_UNEXPECTED; int nPos = -1; DWORD dwMinDisplay = MAXDWORD; if (m_nFieldSurface != -1) { nSurfaceIndex = m_nFieldSurface; *ppSampleToDeliver = m_pFieldSample.Detach(); return S_FALSE; } switch (m_nEngine) { case ENGINE_DXVA1: for (int i = 0; i < m_nPicEntryNumber; i++) { if (!m_pPictureStore[i].bInUse && m_pPictureStore[i].dwDisplayCount < dwMinDisplay) { dwMinDisplay = m_pPictureStore[i].dwDisplayCount; nPos = i; } } if (nPos != -1) { nSurfaceIndex = nPos; return S_OK; } // Ho ho... ASSERT(FALSE); Flush(); break; case ENGINE_DXVA2: CComPtr<IMediaSample> pNewSample; CComQIPtr<IMPCDXVA2Sample> pMPCDXVA2Sample; // TODO : test IDirect3DDeviceManager9::TestDevice !!! if (SUCCEEDED(hr = GetDeliveryBuffer(rtStart, rtStop, &pNewSample))) { pMPCDXVA2Sample = pNewSample; nSurfaceIndex = pMPCDXVA2Sample ? pMPCDXVA2Sample->GetDXSurfaceId() : 0; *ppSampleToDeliver = pNewSample.Detach(); } break; } return hr; }
HRESULT CAMROutputPin::DeliverDataPacketAMR(DataPacketAMR &packet) { IMediaSample *sample; HRESULT hr = GetDeliveryBuffer(&sample, NULL, NULL, 0); if (FAILED(hr)) { return E_FAIL; } // we should have enough space in there long lsize = sample->GetSize(); ASSERT(lsize >= packet.size); BYTE *buf; sample->GetPointer(&buf); memcpy(buf, packet.buf, packet.size); sample->SetActualDataLength(packet.size); // sync point, discontinuity ? if (packet.sync_point) { sample->SetSyncPoint(TRUE); } else { sample->SetSyncPoint(FALSE); } if (packet.discontinuity) { sample->SetDiscontinuity(TRUE); } else { sample->SetDiscontinuity(FALSE); } // do we have a time stamp ? if (packet.has_time) { sample->SetTime(&packet.rtStart, &packet.rtStop); } // dorucime hr = Deliver(sample); sample->Release(); return hr; }
HRESULT CLAVOutputPin::DeliverPacket(Packet *pPacket) { HRESULT hr = S_OK; IMediaSample *pSample = nullptr; long nBytes = (long)pPacket->GetDataSize(); if(nBytes == 0) { goto done; } CHECK_HR(hr = GetDeliveryBuffer(&pSample, nullptr, nullptr, 0)); if (m_bPacketAllocator) { ILAVMediaSample *pLAVSample = nullptr; CHECK_HR(hr = pSample->QueryInterface(&pLAVSample)); CHECK_HR(hr = pLAVSample->SetPacket(pPacket)); SafeRelease(&pLAVSample); } else { // Resize buffer if it is too small // This can cause a playback hick-up, we should avoid this if possible by setting a big enough buffer size if(nBytes > pSample->GetSize()) { SafeRelease(&pSample); ALLOCATOR_PROPERTIES props, actual; CHECK_HR(hr = m_pAllocator->GetProperties(&props)); // Give us 2 times the requested size, so we don't resize every time props.cbBuffer = nBytes*2; if(props.cBuffers > 1) { CHECK_HR(hr = __super::DeliverBeginFlush()); CHECK_HR(hr = __super::DeliverEndFlush()); } CHECK_HR(hr = m_pAllocator->Decommit()); CHECK_HR(hr = m_pAllocator->SetProperties(&props, &actual)); CHECK_HR(hr = m_pAllocator->Commit()); CHECK_HR(hr = GetDeliveryBuffer(&pSample, nullptr, nullptr, 0)); } // Fill the sample BYTE* pData = nullptr; if(FAILED(hr = pSample->GetPointer(&pData)) || !pData) goto done; memcpy(pData, pPacket->GetData(), nBytes); } if(pPacket->pmt) { DbgLog((LOG_TRACE, 10, L"::DeliverPacket() - sending new media type to decoder")); pSample->SetMediaType(pPacket->pmt); pPacket->bDiscontinuity = true; CAutoLock cAutoLock(m_pLock); CMediaType pmt = *(pPacket->pmt); m_mts.clear(); m_mts.push_back(pmt); pPacket->pmt = nullptr; SetMediaType(&pmt); } bool fTimeValid = pPacket->rtStart != Packet::INVALID_TIME; // IBitRateInfo m_BitRate.nBytesSinceLastDeliverTime += nBytes; if (fTimeValid) { if (m_BitRate.rtLastDeliverTime == Packet::INVALID_TIME) { m_BitRate.rtLastDeliverTime = pPacket->rtStart; m_BitRate.nBytesSinceLastDeliverTime = 0; } if (m_BitRate.rtLastDeliverTime + 10000000 < pPacket->rtStart) { REFERENCE_TIME rtDiff = pPacket->rtStart - m_BitRate.rtLastDeliverTime; double dSecs, dBits; dSecs = rtDiff / 10000000.0; dBits = 8.0 * m_BitRate.nBytesSinceLastDeliverTime; m_BitRate.nCurrentBitRate = (DWORD)(dBits / dSecs); m_BitRate.rtTotalTimeDelivered += rtDiff; m_BitRate.nTotalBytesDelivered += m_BitRate.nBytesSinceLastDeliverTime; dSecs = m_BitRate.rtTotalTimeDelivered / 10000000.0; dBits = 8.0 * m_BitRate.nTotalBytesDelivered; m_BitRate.nAverageBitRate = (DWORD)(dBits / dSecs); m_BitRate.rtLastDeliverTime = pPacket->rtStart; m_BitRate.nBytesSinceLastDeliverTime = 0; } } CHECK_HR(hr = pSample->SetActualDataLength(nBytes)); CHECK_HR(hr = pSample->SetTime(fTimeValid ? &pPacket->rtStart : nullptr, fTimeValid ? &pPacket->rtStop : nullptr)); CHECK_HR(hr = pSample->SetMediaTime(nullptr, nullptr)); CHECK_HR(hr = pSample->SetDiscontinuity(pPacket->bDiscontinuity)); CHECK_HR(hr = pSample->SetSyncPoint(pPacket->bSyncPoint)); CHECK_HR(hr = pSample->SetPreroll(fTimeValid && pPacket->rtStart < 0)); // Deliver CHECK_HR(hr = Deliver(pSample)); done: if (!m_bPacketAllocator || !pSample) SAFE_DELETE(pPacket); SafeRelease(&pSample); return hr; }
// // DoBufferProcessingLoop // // Grabs a buffer and calls the users processing function. // Overridable, so that different delivery styles can be catered for. HRESULT CDynamicSourceStream::DoBufferProcessingLoop(void) { Command com; bool fOutputFormatChanged = false; OnThreadStartPlay(); do { while(!CheckRequest(&com)) { // CAutoUsingOutputPin::CAutoUsingOutputPin() only changes the value of hr // if an error occurs. HRESULT hr = S_OK; CAutoUsingOutputPin auopUsingOutputPin(this, &hr); if(FAILED(hr)) { FatalError(hr); return hr; } if(m_fReconnectOutputPin) { hr = DynamicReconnect(NULL); m_fReconnectOutputPin = false; if(FAILED(hr)) { FatalError(hr); return hr; } fOutputFormatChanged = true; } IMediaSample *pSample; hr = GetDeliveryBuffer(&pSample,NULL,NULL,0); if(FAILED(hr)) { Sleep(1); continue; // go round again. Perhaps the error will go away // or the allocator is decommited & we will be asked to // exit soon. } if(fOutputFormatChanged) { pSample->SetDiscontinuity(TRUE); fOutputFormatChanged = false; } // Virtual function user will override. hr = FillBuffer(pSample); if(hr == S_OK) { hr = Deliver(pSample); pSample->Release(); // downstream filter returns S_FALSE if it wants us to // stop or an error if it's reporting an error. if(hr != S_OK) { DbgLog((LOG_TRACE, 2, TEXT("Deliver() returned %08x; stopping"), hr)); return S_OK; } } else if(hr == S_FALSE) { // derived class wants us to stop pushing data pSample->Release(); DeliverEndOfStream(); return S_OK; } else { // derived class encountered an error pSample->Release(); DbgLog((LOG_ERROR, 1, TEXT("Error %08lX from FillBuffer!!!"), hr)); FatalError(hr); return hr; } // all paths release the sample } // For all commands sent to us there must be a Reply call! if(com == CMD_RUN || com == CMD_PAUSE) { Reply(NOERROR); } else if(com != CMD_STOP) { Reply((DWORD) E_UNEXPECTED); DbgLog((LOG_ERROR, 1, TEXT("Unexpected command!!!"))); } } while(com != CMD_STOP); return S_FALSE; }
HRESULT CMPVlcSourceStream::DoBufferProcessingLoop(void) { Command com; HRESULT result = S_OK; BOOL bStop = false; OnThreadStartPlay(); LogInfo("Starting grabber thread"); if (m_exec) { LogInfo("Executing external command: %s %s", m_exec, m_exec_opt); ::ShellExecuteA(0, NULL, m_exec, m_exec_opt, NULL, SW_HIDE); Sleep(m_exec_wait); } //libvlc_vlm_seek_media(m_vlc, "vlc_ds_stream", 0); if (libvlc_vlm_play_media (m_vlc, "vlc_ds_stream") != 0) { LogError("libvlc_vlm_play_media failed"); return S_FALSE; } OVERLAPPED o; o.hEvent = CreateEvent( NULL, FALSE, FALSE, NULL); o.Internal = o.InternalHigh = o.Offset = o.OffsetHigh = 0; ConnectNamedPipe(m_hPipe, &o); WaitForSingleObject(o.hEvent, 20000); BOOL fConnected = HasOverlappedIoCompleted(&o); SetThreadPriority(m_hThread, THREAD_PRIORITY_TIME_CRITICAL); if (!fConnected) { LogError("ConnectNamedPipe failed"); CancelIo(m_hPipe); CloseHandle(o.hEvent); return S_FALSE; } else do { BOOL requestAvail = FALSE; while ((requestAvail = CheckRequest(&com)) == FALSE) { //LogDebug ("Command: %d", com); IMediaSample *pSample; HRESULT hr = GetDeliveryBuffer(&pSample,NULL,NULL,0); if (FAILED(hr)) continue; // fill buffer // ------------------------------------------------------------------------------------ hr = S_OK; BYTE *pData; DWORD cbData; CheckPointer(pSample, E_POINTER); // Access the sample's data buffer pSample->GetPointer((BYTE **)&pData); cbData = pSample->GetSize(); DWORD startRecvTime = GetTickCount(); m_buffsize = 0; do { DWORD cbBytesRead = 0; ResetEvent(o.hEvent); o.Internal = o.InternalHigh = o.Offset = o.OffsetHigh = 0; BOOL fSuccess = ReadFile( m_hPipe, pData + m_buffsize, cbData - m_buffsize, &cbBytesRead, &o); if (GetLastError() == ERROR_IO_PENDING) { for (int n=0; n < 20; n++) { if ((requestAvail = CheckRequest(&com)) == TRUE) break; if (WaitForSingleObject(o.hEvent, 1000) == WAIT_OBJECT_0) break; } fSuccess = GetOverlappedResult(m_hPipe, &o, &cbBytesRead, false); } if (!fSuccess || cbBytesRead == 0) { CancelIo(m_hPipe); break; } m_buffsize += cbBytesRead; } while ( !requestAvail && m_buffsize < (cbData * 3 / 4) && abs((signed long)(GetTickCount() - startRecvTime)) < 100); // ------------------------------------------------------------------------------------ if (m_buffsize != 0 && !(requestAvail && com == CMD_STOP)) { LogDebug("Posting %d / %d bytes", m_buffsize, pSample->GetSize()); REFERENCE_TIME rtStart = startRecvTime; REFERENCE_TIME rtStop = GetTickCount(); pSample->SetTime(&rtStart, &rtStop); pSample->SetActualDataLength(m_buffsize); pSample->SetSyncPoint(TRUE); hr = Deliver(pSample); // downstream filter returns S_FALSE if it wants us to // stop or an error if it's reporting an error. if(hr != S_OK) { LogInfo("Deliver() returned %08x; stopping", hr); bStop = true; } } else { // FillBuffer returned false bStop = true; DeliverEndOfStream(); } pSample->Release(); if (bStop) break; } if (requestAvail) { LogInfo("Received command: %d", com); if (com == CMD_RUN || com == CMD_PAUSE) { Reply(NOERROR); } else if (com != CMD_STOP) { Reply((DWORD) E_UNEXPECTED); LogDebug("Unexpected command %d!!!", com); } } } while (com != CMD_STOP && bStop == false); //DeliverEndOfStream(); LogDebug("end loop"); HANDLE hSDThread = CreateThread(NULL, 0, &VlcStreamDiscardThread, LPVOID(m_hPipe), 0, 0); libvlc_vlm_stop_media(m_vlc, "vlc_ds_stream"); LogDebug("libvlc_vlm_stop_media"); if (WaitForSingleObject(hSDThread, 30000) == WAIT_TIMEOUT) { DWORD ec; LogError("Terminating StreamDiscardThread!"); GetExitCodeThread(hSDThread, &ec); TerminateThread(hSDThread, ec); } DisconnectNamedPipe(m_hPipe); LogDebug("DoBufferProcessingLoop end"); CloseHandle(o.hEvent); return result; }
HRESULT CMPIptvSourceStream::DoBufferProcessingLoop(void) { Command com; OnThreadStartPlay(); WSADATA wsaData; WSAStartup(MAKEWORD(2, 2), &wsaData); #ifdef logging LogDebug("Starting grabber thread"); #endif sockaddr_in addr; memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; if (localip) { addr.sin_addr.s_addr = inet_addr(localip); } else { addr.sin_addr.s_addr = htonl(INADDR_ANY); } addr.sin_port = htons((u_short)port); ip_mreq imr; imr.imr_multiaddr.s_addr = inet_addr(ip); if (localip) { imr.imr_interface.s_addr = inet_addr(localip); } else { imr.imr_interface.s_addr = INADDR_ANY; } unsigned long nonblocking = 1; if((m_socket = socket(AF_INET, SOCK_DGRAM, 0)) >= 0) { /* u_long argp = 1; ioctlsocket(m_socket, FIONBIO, &argp); */ DWORD dw = TRUE; int dwLen = sizeof(dw); if(setsockopt(m_socket, SOL_SOCKET, SO_REUSEADDR, (const char*)&dw, sizeof(dw)) < 0) { closesocket(m_socket); m_socket = -1; } if(setsockopt(m_socket, SOL_SOCKET, SO_BROADCAST, (const char*)&dw, sizeof(dw)) < 0) { closesocket(m_socket); m_socket = -1; } getsockopt(m_socket, SOL_SOCKET, SO_RCVBUF, (char *)&dw, &dwLen); #ifdef logging LogDebug("Socket receive buffer is: %d (%d)", dw, dwLen); LogDebug("Trying to set receive buffer to %d", IPTV_SOCKET_BUFFER_SIZE); #endif dw = IPTV_SOCKET_BUFFER_SIZE; if(setsockopt(m_socket, SOL_SOCKET, SO_RCVBUF, (const char*)&dw, sizeof(dw)) < 0) { closesocket(m_socket); m_socket = -1; } dwLen = sizeof(dw); getsockopt(m_socket, SOL_SOCKET, SO_RCVBUF, (char *)&dw, &dwLen); #ifdef logging LogDebug("New socket receive buffer is: %d (%d)", dw, dwLen); #endif if (ioctlsocket(m_socket, FIONBIO, &nonblocking) != 0) { closesocket(m_socket); m_socket = -1; } if(bind(m_socket, (struct sockaddr*)&addr, sizeof(addr)) < 0) { closesocket(m_socket); m_socket = -1; } if(IN_MULTICAST(htonl(imr.imr_multiaddr.s_addr))) { int ret = setsockopt(m_socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const char*)&imr, sizeof(imr)); if(ret < 0) ret = ::WSAGetLastError(); ret = ret; } } SetThreadPriority(m_hThread, THREAD_PRIORITY_TIME_CRITICAL); int fromlen = sizeof(addr); m_buffsize = 0; timeval tv; //Will be used for select() below tv.tv_sec = 0; tv.tv_usec = 100000; //100 msec do { BOOL requestAvail; while ((requestAvail = CheckRequest(&com)) == FALSE) { DWORD startRecvTime; startRecvTime = GetTickCount(); #ifdef FILL_DIRECTLY_INTO_BUFFER IMediaSample *pSample; char *pData; long cbData; HRESULT hr = GetDeliveryBuffer(&pSample,NULL,NULL,0); if (FAILED(hr)) continue; CheckPointer(pSample, E_POINTER); // Access the sample's data buffer pSample->GetPointer((BYTE **)&pData); cbData = pSample->GetSize(); #endif do { //Try to read the complete remaining buffer size //But stop reading after 100ms have passed (slow streams like internet radio) #ifdef FILL_DIRECTLY_INTO_BUFFER int len = recvfrom(m_socket, &pData[m_buffsize], cbData - m_buffsize, 0, (SOCKADDR*)&addr, &fromlen); #else int len = recvfrom(m_socket, &m_buffer[m_buffsize], IPTV_BUFFER_SIZE - m_buffsize, 0, (SOCKADDR*)&addr, &fromlen); #endif if(len <= 0) { //Wait until there's something in the receive buffer fd_set myFDsocket; myFDsocket.fd_count = 1; myFDsocket.fd_array[0] = m_socket; int selectRet = select(0, &myFDsocket, NULL, NULL, &tv); #ifdef logging LogDebug("select return code: %d", selectRet); #endif continue; //On error or nothing read just repeat the loop } #ifdef logging LogDebug("Read %d bytes at pos %d of %d", len, m_buffsize, IPTV_BUFFER_SIZE); #endif m_buffsize += len; #ifdef FILL_DIRECTLY_INTO_BUFFER } while ((requestAvail = CheckRequest(&com)) == FALSE && m_buffsize < (cbData * 3 / 4) && abs((signed long)(GetTickCount() - startRecvTime)) < 100); #else } while ((requestAvail = CheckRequest(&com)) == FALSE && m_buffsize < (IPTV_BUFFER_SIZE * 3 / 4) && abs((signed long)(GetTickCount() - startRecvTime)) < 100); #endif if (requestAvail) break; #ifndef FILL_DIRECTLY_INTO_BUFFER if (m_buffsize == 0) continue; //100ms passed but no buffer received IMediaSample *pSample; HRESULT hr = GetDeliveryBuffer(&pSample,NULL,NULL,0); if (FAILED(hr)) { continue; // go round again. Perhaps the error will go away // or the allocator is decommited & we will be asked to // exit soon. } #endif // fill buffer hr = FillBuffer(pSample); if (hr == S_OK) { hr = Deliver(pSample); pSample->Release(); // downstream filter returns S_FALSE if it wants us to // stop or an error if it's reporting an error. if(hr != S_OK) { #ifdef logging LogDebug("Deliver() returned %08x; stopping", hr); #endif if(m_socket >= 0) {closesocket(m_socket); m_socket = -1;} WSACleanup(); return S_OK; } } else if (hr == S_FALSE) { // derived class wants us to stop pushing data pSample->Release(); DeliverEndOfStream(); if(m_socket >= 0) {closesocket(m_socket); m_socket = -1;} WSACleanup(); return S_OK; } else { // derived class encountered an error pSample->Release(); #ifdef logging LogDebug("Error %08lX from FillBuffer!!!", hr); #endif DeliverEndOfStream(); m_pFilter->NotifyEvent(EC_ERRORABORT, hr, 0); if(m_socket >= 0) {closesocket(m_socket); m_socket = -1;} WSACleanup(); return hr; } // all paths release the sample } // For all commands sent to us there must be a Reply call! if (com == CMD_RUN || com == CMD_PAUSE) { Reply(NOERROR); } else if (com != CMD_STOP) { Reply((DWORD) E_UNEXPECTED); #ifdef logging LogDebug("Unexpected command %d!!!", com); #endif } } while (com != CMD_STOP);
HRESULT CLAVAudio::DeliverBitstream(AVCodecID codec, const BYTE *buffer, DWORD dwSize, DWORD dwFrameSize, REFERENCE_TIME rtStartInput, REFERENCE_TIME rtStopInput) { HRESULT hr = S_OK; CMediaType mt = CreateBitstreamMediaType(codec, m_bsParser.m_dwSampleRate); WAVEFORMATEX* wfe = (WAVEFORMATEX*)mt.Format(); if(FAILED(hr = ReconnectOutput(dwSize, mt))) { return hr; } IMediaSample *pOut; BYTE *pDataOut = NULL; if(FAILED(GetDeliveryBuffer(&pOut, &pDataOut))) { return E_FAIL; } REFERENCE_TIME rtStart = m_rtStart, rtStop = AV_NOPTS_VALUE; // TrueHD timings // Since the SPDIF muxer takes 24 frames and puts them into one IEC61937 frame, we use the cached timestamp from before. if (codec == AV_CODEC_ID_TRUEHD) { // long-term cache is valid if (m_rtBitstreamCache != AV_NOPTS_VALUE) rtStart = m_rtBitstreamCache; // Duration - stop time of the current frame is valid if (rtStopInput != AV_NOPTS_VALUE) rtStop = rtStopInput; else // no actual time of the current frame, use typical TrueHD frame size, 24 * 0.83333ms rtStop = rtStart + (REFERENCE_TIME)(200000 / m_dRate); m_rtStart = rtStop; } else { double dDuration = DBL_SECOND_MULT * (double)m_bsParser.m_dwSamples / m_bsParser.m_dwSampleRate / m_dRate; m_dStartOffset += fmod(dDuration, 1.0); // Add rounded duration to rtStop rtStop = rtStart + (REFERENCE_TIME)(dDuration + 0.5); // and unrounded to m_rtStart.. m_rtStart += (REFERENCE_TIME)dDuration; // and accumulate error.. if (m_dStartOffset > 0.5) { m_rtStart++; m_dStartOffset -= 1.0; } } REFERENCE_TIME rtJitter = rtStart - m_rtBitstreamCache; m_faJitter.Sample(rtJitter); REFERENCE_TIME rtJitterMin = m_faJitter.AbsMinimum(); if (m_settings.AutoAVSync && abs(rtJitterMin) > m_JitterLimit && m_bHasVideo) { DbgLog((LOG_TRACE, 10, L"::Deliver(): corrected A/V sync by %I64d", rtJitterMin)); m_rtStart -= rtJitterMin; m_faJitter.OffsetValues(-rtJitterMin); m_bDiscontinuity = TRUE; } #ifdef DEBUG DbgLog((LOG_CUSTOM5, 20, L"Bitstream Delivery, rtStart(calc): %I64d, rtStart(input): %I64d, duration: %I64d, diff: %I64d", rtStart, m_rtBitstreamCache, rtStop-rtStart, rtJitter)); if (m_faJitter.CurrentSample() == 0) { DbgLog((LOG_TRACE, 20, L"Jitter Stats: min: %I64d - max: %I64d - avg: %I64d", rtJitterMin, m_faJitter.AbsMaximum(), m_faJitter.Average())); } #endif m_rtBitstreamCache = AV_NOPTS_VALUE; if(m_settings.AudioDelayEnabled) { REFERENCE_TIME rtDelay = (REFERENCE_TIME)((m_settings.AudioDelay * 10000i64) / m_dRate); rtStart += rtDelay; rtStop += rtDelay; } pOut->SetTime(&rtStart, &rtStop); pOut->SetMediaTime(NULL, NULL); pOut->SetPreroll(FALSE); pOut->SetDiscontinuity(m_bDiscontinuity); m_bDiscontinuity = FALSE; pOut->SetSyncPoint(TRUE); pOut->SetActualDataLength(dwSize); memcpy(pDataOut, buffer, dwSize); if(hr == S_OK) { hr = m_pOutput->GetConnected()->QueryAccept(&mt); if (hr == S_FALSE && m_nCodecId == AV_CODEC_ID_DTS && m_bDTSHD) { DbgLog((LOG_TRACE, 1, L"DTS-HD Media Type failed with %0#.8x, trying fallback to DTS core", hr)); m_bForceDTSCore = TRUE; UpdateBitstreamContext(); goto done; } DbgLog((LOG_TRACE, 1, L"Sending new Media Type (QueryAccept: %0#.8x)", hr)); m_pOutput->SetMediaType(&mt); pOut->SetMediaType(&mt); } hr = m_pOutput->Deliver(pOut); if (FAILED(hr)) { DbgLog((LOG_ERROR, 10, L"::DeliverBitstream failed with code: %0#.8x", hr)); } done: SafeRelease(&pOut); return hr; }
HRESULT CBaseSplitterOutputPin::DeliverPacket(CAutoPtr<Packet> p) { HRESULT hr; long nBytes = (long)p->GetCount(); if (nBytes == 0) { return S_OK; } m_brs.nBytesSinceLastDeliverTime += nBytes; if (p->rtStart != Packet::INVALID_TIME) { if (m_brs.rtLastDeliverTime == Packet::INVALID_TIME) { m_brs.rtLastDeliverTime = p->rtStart; m_brs.nBytesSinceLastDeliverTime = 0; } if (m_brs.rtLastDeliverTime + 10000000 < p->rtStart) { REFERENCE_TIME rtDiff = p->rtStart - m_brs.rtLastDeliverTime; double secs, bits; secs = (double)rtDiff / 10000000; bits = 8.0 * m_brs.nBytesSinceLastDeliverTime; m_brs.nCurrentBitRate = (DWORD)(bits / secs); m_brs.rtTotalTimeDelivered += rtDiff; m_brs.nTotalBytesDelivered += m_brs.nBytesSinceLastDeliverTime; secs = (double)m_brs.rtTotalTimeDelivered / 10000000; bits = 8.0 * m_brs.nTotalBytesDelivered; m_brs.nAverageBitRate = (DWORD)(bits / secs); m_brs.rtLastDeliverTime = p->rtStart; m_brs.nBytesSinceLastDeliverTime = 0; /* TRACE(_T("[%d] c: %d kbps, a: %d kbps\n"), p->TrackNumber, (m_brs.nCurrentBitRate+500)/1000, (m_brs.nAverageBitRate+500)/1000); */ } double dRate = 1.0; if (SUCCEEDED((static_cast<CBaseSplitterFilter*>(m_pFilter))->GetRate(&dRate))) { p->rtStart = (REFERENCE_TIME)((double)p->rtStart / dRate); p->rtStop = (REFERENCE_TIME)((double)p->rtStop / dRate); } } do { CComPtr<IMediaSample> pSample; if (S_OK != (hr = GetDeliveryBuffer(&pSample, nullptr, nullptr, 0))) { break; } if (nBytes > pSample->GetSize()) { pSample.Release(); ALLOCATOR_PROPERTIES props, actual; if (S_OK != (hr = m_pAllocator->GetProperties(&props))) { break; } props.cbBuffer = nBytes * 3 / 2; if (props.cBuffers > 1) { if (S_OK != (hr = __super::DeliverBeginFlush())) { break; } if (S_OK != (hr = __super::DeliverEndFlush())) { break; } } if (S_OK != (hr = m_pAllocator->Decommit())) { break; } if (S_OK != (hr = m_pAllocator->SetProperties(&props, &actual))) { break; } if (S_OK != (hr = m_pAllocator->Commit())) { break; } if (S_OK != (hr = GetDeliveryBuffer(&pSample, nullptr, nullptr, 0))) { break; } } if (p->pmt) { pSample->SetMediaType(p->pmt); p->bDiscontinuity = true; CAutoLock cAutoLock(m_pLock); m_mts.RemoveAll(); m_mts.Add(*p->pmt); } bool fTimeValid = p->rtStart != Packet::INVALID_TIME; #if defined(_DEBUG) && 0 TRACE(_T("[%d]: d%d s%d p%d, b=%d, [%20I64d - %20I64d]\n"), p->TrackNumber, p->bDiscontinuity, p->bSyncPoint, fTimeValid && p->rtStart < 0, nBytes, p->rtStart, p->rtStop); #endif ASSERT(!p->bSyncPoint || fTimeValid); BYTE* pData = nullptr; if (S_OK != (hr = pSample->GetPointer(&pData)) || !pData) { break; } memcpy(pData, p->GetData(), nBytes); if (S_OK != (hr = pSample->SetActualDataLength(nBytes))) { break; } if (S_OK != (hr = pSample->SetTime(fTimeValid ? &p->rtStart : nullptr, fTimeValid ? &p->rtStop : nullptr))) { break; } if (S_OK != (hr = pSample->SetMediaTime(nullptr, nullptr))) { break; } if (S_OK != (hr = pSample->SetDiscontinuity(p->bDiscontinuity))) { break; } if (S_OK != (hr = pSample->SetSyncPoint(p->bSyncPoint))) { break; } if (S_OK != (hr = pSample->SetPreroll(fTimeValid && p->rtStart < 0))) { break; } if (S_OK != (hr = Deliver(pSample))) { break; } } while (false); return hr; }
// // DoBufferProcessingLoop // // Grabs a buffer and calls the users processing function. // Overridable, so that different delivery styles can be catered for. HRESULT CSourceStream::DoBufferProcessingLoop(void) { Command com; OnThreadStartPlay(); do { while (!CheckRequest(&com)) { IMediaSample *pSample; HRESULT hr = GetDeliveryBuffer(&pSample,NULL,NULL,0); if (FAILED(hr)) { Sleep(1); continue; // go round again. Perhaps the error will go away // or the allocator is decommited & we will be asked to // exit soon. } // Virtual function user will override. hr = FillBuffer(pSample); if (hr == S_OK) { hr = Deliver(pSample); pSample->Release(); // downstream filter returns S_FALSE if it wants us to // stop or an error if it's reporting an error. if(hr != S_OK) { DbgLog((LOG_TRACE, 2, TEXT("Deliver() returned %08x; stopping"), hr)); return S_OK; } } else if (hr == S_FALSE) { // derived class wants us to stop pushing data pSample->Release(); DeliverEndOfStream(); return S_OK; } else { // derived class encountered an error pSample->Release(); DbgLog((LOG_ERROR, 1, TEXT("Error %08lX from FillBuffer!!!"), hr)); DeliverEndOfStream(); m_pFilter->NotifyEvent(EC_ERRORABORT, hr, 0); return hr; } // all paths release the sample } // For all commands sent to us there must be a Reply call! if (com == CMD_RUN || com == CMD_PAUSE) { Reply(NOERROR); } else if (com != CMD_STOP) { Reply((DWORD) E_UNEXPECTED); DbgLog((LOG_ERROR, 1, TEXT("Unexpected command!!!"))); } } while (com != CMD_STOP); return S_FALSE; }
HRESULT CAudioPin::DoBufferProcessingLoop(void) { if (!m_bConnected) { return S_OK; m_bThreadRunning = false; } Command com; OnThreadStartPlay(); m_bThreadRunning = true; SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL); do { while (!CheckRequest(&com)) { IMediaSample *pSample; HRESULT hr = GetDeliveryBuffer(&pSample,NULL,NULL,0); if (FAILED(hr)) { Sleep(1); continue; // go round again. Perhaps the error will go away // or the allocator is decommited & we will be asked to // exit soon. } // Virtual function user will override. hr = FillBuffer(pSample); if (hr == S_OK) { // Some decoders seem to crash when we provide empty samples if ((pSample->GetActualDataLength() > 0) && !m_pTsReaderFilter->IsStopping() && m_bConnected) { hr = Deliver(pSample); m_sampleCount++ ; } else { m_bDiscontinuity = true; } pSample->Release(); // downstream filter returns S_FALSE if it wants us to // stop or an error if it's reporting an error. if(hr != S_OK) { DbgLog((LOG_TRACE, 2, TEXT("Deliver() returned %08x; stopping"), hr)); m_bThreadRunning = false; return S_OK; } } else if (hr == S_FALSE) { // derived class wants us to stop pushing data pSample->Release(); DeliverEndOfStream(); m_bThreadRunning = false; return S_OK; } else { // derived class encountered an error pSample->Release(); DbgLog((LOG_ERROR, 1, TEXT("Error %08lX from FillBuffer!!!"), hr)); DeliverEndOfStream(); m_pFilter->NotifyEvent(EC_ERRORABORT, hr, 0); m_bThreadRunning = false; return hr; } // all paths release the sample } // For all commands sent to us there must be a Reply call! if (com == CMD_RUN || com == CMD_PAUSE) { Reply(NOERROR); } else if (com != CMD_STOP) { Reply((DWORD) E_UNEXPECTED); DbgLog((LOG_ERROR, 1, TEXT("Unexpected command!!!"))); } } while (com != CMD_STOP); m_bThreadRunning = false; return S_FALSE; }
HRESULT CLAVOutputPin::DeliverPacket(Packet *pPacket) { HRESULT hr = S_OK; IMediaSample *pSample = NULL; long nBytes = (long)pPacket->GetDataSize(); if(nBytes == 0) { goto done; } CHECK_HR(hr = GetDeliveryBuffer(&pSample, NULL, NULL, 0)); if (m_bPacketAllocator) { ILAVMediaSample *pLAVSample = NULL; CHECK_HR(hr = pSample->QueryInterface(&pLAVSample)); CHECK_HR(hr = pLAVSample->SetPacket(pPacket)); SafeRelease(&pLAVSample); } else { // Resize buffer if it is too small // This can cause a playback hick-up, we should avoid this if possible by setting a big enough buffer size if(nBytes > pSample->GetSize()) { SafeRelease(&pSample); ALLOCATOR_PROPERTIES props, actual; CHECK_HR(hr = m_pAllocator->GetProperties(&props)); // Give us 2 times the requested size, so we don't resize every time props.cbBuffer = nBytes*2; if(props.cBuffers > 1) { CHECK_HR(hr = __super::DeliverBeginFlush()); CHECK_HR(hr = __super::DeliverEndFlush()); } CHECK_HR(hr = m_pAllocator->Decommit()); CHECK_HR(hr = m_pAllocator->SetProperties(&props, &actual)); CHECK_HR(hr = m_pAllocator->Commit()); CHECK_HR(hr = GetDeliveryBuffer(&pSample, NULL, NULL, 0)); } // Fill the sample BYTE* pData = NULL; if(FAILED(hr = pSample->GetPointer(&pData)) || !pData) goto done; memcpy(pData, pPacket->GetData(), nBytes); } if(pPacket->pmt) { DbgLog((LOG_TRACE, 10, L"::DeliverPacket() - sending new media type to decoder")); pSample->SetMediaType(pPacket->pmt); pPacket->bDiscontinuity = true; CAutoLock cAutoLock(m_pLock); CMediaType pmt = *(pPacket->pmt); m_mts.clear(); m_mts.push_back(pmt); pPacket->pmt = NULL; SetMediaType(&pmt); } bool fTimeValid = pPacket->rtStart != Packet::INVALID_TIME; CHECK_HR(hr = pSample->SetActualDataLength(nBytes)); CHECK_HR(hr = pSample->SetTime(fTimeValid ? &pPacket->rtStart : NULL, fTimeValid ? &pPacket->rtStop : NULL)); CHECK_HR(hr = pSample->SetMediaTime(NULL, NULL)); CHECK_HR(hr = pSample->SetDiscontinuity(pPacket->bDiscontinuity)); CHECK_HR(hr = pSample->SetSyncPoint(pPacket->bSyncPoint)); CHECK_HR(hr = pSample->SetPreroll(fTimeValid && pPacket->rtStart < 0)); // Deliver CHECK_HR(hr = Deliver(pSample)); done: if (!m_bPacketAllocator) SAFE_DELETE(pPacket); SafeRelease(&pSample); return hr; }
GstFlowReturn VideoFakeSrcPin::PushBuffer(GstBuffer *buffer) { IMediaSample *pSample = NULL; byte *data = GST_BUFFER_DATA (buffer); int attempts = 0; HRESULT hres; BYTE *sample_buffer; AM_MEDIA_TYPE *mediatype; StartUsingOutputPin(); while (attempts < MAX_ATTEMPTS) { hres = GetDeliveryBuffer(&pSample, NULL, NULL, 0); if (SUCCEEDED (hres)) break; attempts++; Sleep(100); } if (FAILED (hres)) { StopUsingOutputPin(); GST_WARNING ("Could not get sample for delivery to sink: %x", hres); return GST_FLOW_ERROR; } pSample->GetPointer(&sample_buffer); pSample->GetMediaType(&mediatype); if (mediatype) SetMediaType (mediatype); if(sample_buffer) { /* Copy to the destination stride. * This is not just a simple memcpy because of the different strides. * TODO: optimise for the same-stride case and avoid the copy entirely. */ CopyToDestinationBuffer (data, sample_buffer); } pSample->SetDiscontinuity(FALSE); /* Decoded frame; unimportant */ pSample->SetSyncPoint(TRUE); /* Decoded frame; always a valid syncpoint */ pSample->SetPreroll(FALSE); /* For non-displayed frames. Not used in GStreamer */ /* Disable synchronising on this sample. We instead let GStreamer handle * this at a higher level, inside BaseSink. */ pSample->SetTime(NULL, NULL); while (attempts < MAX_ATTEMPTS) { hres = Deliver(pSample); if (SUCCEEDED (hres)) break; attempts++; Sleep(100); } pSample->Release(); StopUsingOutputPin(); if (SUCCEEDED (hres)) return GST_FLOW_OK; else { GST_WARNING_OBJECT (this, "Failed to deliver sample: %x", hres); if (hres == VFW_E_NOT_CONNECTED) return GST_FLOW_NOT_LINKED; else return GST_FLOW_ERROR; } }
HRESULT CBaseSplitterOutputPin::DeliverPacket(CAutoPtr<Packet> p) { HRESULT hr; long nBytes = (long)p->GetCount(); if (nBytes == 0) { return S_OK; } DWORD nFlag = (static_cast<CBaseSplitterFilter*>(m_pFilter))->GetFlag(); if (p->rtStart != INVALID_TIME && (nFlag & PACKET_PTS_DISCONTINUITY)) { // Filter invalid PTS value (if too different from previous packet) if (!IsDiscontinuous() && !((nFlag & PACKET_PTS_VALIDATE_POSITIVE) && p->rtStart < 0)) { REFERENCE_TIME rt = p->rtStart + m_rtOffset; if (_abs64(rt - m_rtPrev) > MAX_PTS_SHIFT) { m_rtOffset += m_rtPrev - rt; DbgLog((LOG_TRACE, 3, L"CBaseSplitterOutputPin::DeliverPacket() : Packet discontinuity detected, adjusting offset to %I64d", m_rtOffset)); } } p->rtStart += m_rtOffset; p->rtStop += m_rtOffset; m_rtPrev = p->rtStart; } m_brs.nBytesSinceLastDeliverTime += nBytes; if (p->rtStart != INVALID_TIME) { if (m_brs.rtLastDeliverTime == INVALID_TIME) { m_brs.rtLastDeliverTime = p->rtStart; m_brs.nBytesSinceLastDeliverTime = 0; } if (m_brs.rtLastDeliverTime + 10000000 < p->rtStart) { REFERENCE_TIME rtDiff = p->rtStart - m_brs.rtLastDeliverTime; double secs, bits; secs = (double)rtDiff / 10000000; bits = 8.0 * m_brs.nBytesSinceLastDeliverTime; m_brs.nCurrentBitRate = (DWORD)(bits / secs); m_brs.rtTotalTimeDelivered += rtDiff; m_brs.nTotalBytesDelivered += m_brs.nBytesSinceLastDeliverTime; secs = (double)m_brs.rtTotalTimeDelivered / 10000000; bits = 8.0 * m_brs.nTotalBytesDelivered; m_brs.nAverageBitRate = (DWORD)(bits / secs); m_brs.rtLastDeliverTime = p->rtStart; m_brs.nBytesSinceLastDeliverTime = 0; /* TRACE(_T("[%d] c: %d kbps, a: %d kbps\n"), p->TrackNumber, (m_brs.nCurrentBitRate+500)/1000, (m_brs.nAverageBitRate+500)/1000); */ } double dRate = 1.0; if (SUCCEEDED((static_cast<CBaseSplitterFilter*>(m_pFilter))->GetRate(&dRate))) { p->rtStart = (REFERENCE_TIME)((double)p->rtStart / dRate); p->rtStop = (REFERENCE_TIME)((double)p->rtStop / dRate); } } do { CComPtr<IMediaSample> pSample; if (S_OK != (hr = GetDeliveryBuffer(&pSample, NULL, NULL, 0))) { break; } if (nBytes > pSample->GetSize()) { pSample.Release(); ALLOCATOR_PROPERTIES props, actual; if (S_OK != (hr = m_pAllocator->GetProperties(&props))) { break; } props.cbBuffer = nBytes*3/2; if (props.cBuffers > 1) { if (S_OK != (hr = __super::DeliverBeginFlush())) { break; } if (S_OK != (hr = __super::DeliverEndFlush())) { break; } } if (S_OK != (hr = m_pAllocator->Decommit())) { break; } if (S_OK != (hr = m_pAllocator->SetProperties(&props, &actual))) { break; } if (S_OK != (hr = m_pAllocator->Commit())) { break; } if (S_OK != (hr = GetDeliveryBuffer(&pSample, NULL, NULL, 0))) { break; } } if (p->pmt) { pSample->SetMediaType(p->pmt); p->bDiscontinuity = true; // CAutoLock cAutoLock(m_pLock); // this can cause the lock m_mts.RemoveAll(); m_mts.Add(*p->pmt); } bool fTimeValid = p->rtStart != INVALID_TIME; #if defined(_DEBUG) && 0 TRACE(_T("[%d]: d%d s%d p%d, b=%d, [%20I64d - %20I64d]\n"), p->TrackNumber, p->bDiscontinuity, p->bSyncPoint, fTimeValid && p->rtStart < 0, nBytes, p->rtStart, p->rtStop); #endif ASSERT(!p->bSyncPoint || fTimeValid); BYTE* pData = NULL; if (S_OK != (hr = pSample->GetPointer(&pData)) || !pData) { break; } memcpy(pData, p->GetData(), nBytes); if (S_OK != (hr = pSample->SetActualDataLength(nBytes))) { break; } if (S_OK != (hr = pSample->SetTime(fTimeValid ? &p->rtStart : NULL, fTimeValid ? &p->rtStop : NULL))) { break; } if (S_OK != (hr = pSample->SetMediaTime(NULL, NULL))) { break; } if (S_OK != (hr = pSample->SetDiscontinuity(p->bDiscontinuity))) { break; } if (S_OK != (hr = pSample->SetSyncPoint(p->bSyncPoint))) { break; } if (S_OK != (hr = pSample->SetPreroll(fTimeValid && p->rtStart < 0))) { break; } if (S_OK != (hr = Deliver(pSample))) { break; } } while (false); return hr; }
// the loop executed while running HRESULT FCapturePin::DoBufferProcessingLoop(void) { Command com; OnThreadStartPlay(); int32 LastFrame = -1; do { while (!CheckRequest(&com)) { // Wait for the next frame from the game thread if ( !GCaptureSyncEvent->Wait(1000) ) { FPlatformProcess::Sleep( 0.01f ); continue; // Reevaluate request } IMediaSample *pSample; int32 FrameNumber = FAVIWriter::GetInstance()->GetFrameNumber(); if (FrameNumber > LastFrame) { UE_LOG(LogMovieCapture, Log, TEXT(" FrameNumber > LastFrame = %d > %d"), FrameNumber, LastFrame); HRESULT hr = GetDeliveryBuffer(&pSample,NULL,NULL,0); if (FAILED(hr)) { if (pSample) { pSample->Release(); } } else { LastFrame = FrameNumber; hr = FillBuffer(pSample); if (hr == S_OK) { hr = Deliver(pSample); pSample->Release(); // downstream filter returns S_FALSE if it wants us to // stop or an error if it's reporting an error. if(hr != S_OK) { UE_LOG(LogMovieCapture, Log, TEXT("Deliver() returned %08x; stopping"), hr); return S_OK; } } } } // Allow the game thread read more data GCaptureSyncEvent->Trigger(); } // For all commands sent to us there must be a Reply call! if (com == CMD_RUN || com == CMD_PAUSE) { Reply(NOERROR); } else if (com != CMD_STOP) { Reply((uint32) E_UNEXPECTED); } } while (com != CMD_STOP); return S_FALSE; }