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 CPullPin::QueueSample( __inout REFERENCE_TIME& tCurrent, REFERENCE_TIME tAlignStop, BOOL bDiscontinuity ) { IMediaSample* pSample; HRESULT hr = m_pAlloc->GetBuffer(&pSample, NULL, NULL, 0); if (FAILED(hr)) { return hr; } LONGLONG tStopThis = tCurrent + (pSample->GetSize() * UNITS); if (tStopThis > tAlignStop) { tStopThis = tAlignStop; } pSample->SetTime(&tCurrent, &tStopThis); tCurrent = tStopThis; pSample->SetDiscontinuity(bDiscontinuity); hr = m_pReader->Request( pSample, 0); if (FAILED(hr)) { pSample->Release(); CleanupCancelled(); OnError(hr); } return hr; }
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; }
int StreamOutputPin::WritePackets(void * opaque, uint8_t * buf, int buf_size) { HRESULT hr = S_OK; BYTE * pBuffer = NULL; IMediaSample * pSample = NULL; StreamOutputPin * pThis = (StreamOutputPin *)opaque; REFERENCE_TIME newOffset = pThis->m_offset; hr = pThis->GetDeliveryBuffer(&pSample, NULL, NULL, 0); if (hr != S_OK) { //Pokusi sa zapisat buffer cez IStream - allocator je dealokovany if (pThis->m_stream) { ULONG written; LARGE_INTEGER move; move.QuadPart = pThis->m_offset; CHECK_HR(hr = pThis->m_stream->Seek(move, STREAM_SEEK_SET, NULL)); CHECK_HR(hr = pThis->m_stream->Write(buf, buf_size, &written)); pThis->m_offset += written; } goto done; } buf_size = min(pSample->GetSize(), buf_size); newOffset += buf_size; CHECK_HR(hr = pSample->GetPointer(&pBuffer)); //Pozor ak sa velkost nezhoduje memcpy(pBuffer, buf, buf_size); CHECK_HR(hr = pSample->SetActualDataLength(buf_size)); CHECK_HR(hr = pSample->SetTime(&pThis->m_offset, &newOffset)); pThis->m_offset = newOffset; CHECK_HR(hr = pThis->Deliver(pSample)); done: SAFE_RELEASE(pSample); return buf_size; }
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 TheoraEncodeInputPin::deliverData(LONGLONG inStart, LONGLONG inEnd, unsigned char* inBuf, unsigned long inNumBytes) { //debugLog <<" deliverData : "<<inStart<<" - "<<inEnd<<" :: size = "<<inNumBytes<<endl; //Get a pointer to a new sample stamped with our time IMediaSample* locSample; HRESULT locHR = mOutputPin->GetDeliveryBuffer(&locSample, &inStart, &inEnd, NULL); if (locHR != S_OK) { //We get here when the application goes into stop mode usually. return locHR; } BYTE* locBuffer = NULL; //Make our pointers set to point to the samples buffer locSample->GetPointer(&locBuffer); if (locSample->GetSize() >= inNumBytes) { memcpy((void*)locBuffer, (const void*)inBuf, inNumBytes); //Set the sample parameters. SetSampleParams(locSample, inNumBytes, &inStart, &inEnd); { CAutoLock locLock(m_pLock); HRESULT locHR = ((TheoraEncodeOutputPin*)mOutputPin)->mDataQueue->Receive(locSample); //->DownstreamFilter()->Receive(locSample); if (locHR != S_OK) { return locHR; } else { } } //debugLog<<"deliverData : SUCCESS"<<endl; return S_OK; } else { //debugLog<<"Buffer too small !!!! FATALITY !"<<endl; throw 0; } }
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);
// // Copy // // return a pointer to an identical copy of pSample IMediaSample * CTransInPlaceFilter::Copy(IMediaSample *pSource) { IMediaSample * pDest; HRESULT hr; REFERENCE_TIME tStart, tStop; const BOOL bTime = S_OK == pSource->GetTime( &tStart, &tStop); // this may block for an indeterminate amount of time hr = OutputPin()->PeekAllocator()->GetBuffer( &pDest , bTime ? &tStart : NULL , bTime ? &tStop : NULL , m_bSampleSkipped ? AM_GBF_PREVFRAMESKIPPED : 0 ); if (FAILED(hr)) { return NULL; } ASSERT(pDest); IMediaSample2 *pSample2; if (SUCCEEDED(pDest->QueryInterface(IID_IMediaSample2, (void **)&pSample2))) { HRESULT hr = pSample2->SetProperties( FIELD_OFFSET(AM_SAMPLE2_PROPERTIES, pbBuffer), (PBYTE)m_pInput->SampleProps()); pSample2->Release(); if (FAILED(hr)) { pDest->Release(); return NULL; } } else { if (bTime) { pDest->SetTime(&tStart, &tStop); } if (S_OK == pSource->IsSyncPoint()) { pDest->SetSyncPoint(TRUE); } if (S_OK == pSource->IsDiscontinuity() || m_bSampleSkipped) { pDest->SetDiscontinuity(TRUE); } if (S_OK == pSource->IsPreroll()) { pDest->SetPreroll(TRUE); } // Copy the media type AM_MEDIA_TYPE *pMediaType; if (S_OK == pSource->GetMediaType(&pMediaType)) { pDest->SetMediaType(pMediaType); DeleteMediaType( pMediaType ); } } m_bSampleSkipped = FALSE; // Copy the sample media times REFERENCE_TIME TimeStart, TimeEnd; if (pSource->GetMediaTime(&TimeStart,&TimeEnd) == NOERROR) { pDest->SetMediaTime(&TimeStart,&TimeEnd); } // Copy the actual data length and the actual data. { const long lDataLength = pSource->GetActualDataLength(); pDest->SetActualDataLength(lDataLength); // Copy the sample data { BYTE *pSourceBuffer, *pDestBuffer; long lSourceSize = pSource->GetSize(); long lDestSize = pDest->GetSize(); ASSERT(lDestSize >= lSourceSize && lDestSize >= lDataLength); pSource->GetPointer(&pSourceBuffer); pDest->GetPointer(&pDestBuffer); ASSERT(lDestSize == 0 || pSourceBuffer != NULL && pDestBuffer != NULL); CopyMemory( (PVOID) pDestBuffer, (PVOID) pSourceBuffer, lDataLength ); } } return pDest; } // Copy
void CPullPin::Process(void) { // is there anything to do? if (m_tStop <= m_tStart) { EndOfStream(); return; } BOOL bDiscontinuity = TRUE; // if there is more than one sample at the allocator, // then try to queue 2 at once in order to overlap. // -- get buffer count and required alignment ALLOCATOR_PROPERTIES Actual; HRESULT hr = m_pAlloc->GetProperties(&Actual); // align the start position downwards REFERENCE_TIME tStart = AlignDown(m_tStart / UNITS, Actual.cbAlign) * UNITS; REFERENCE_TIME tCurrent = tStart; REFERENCE_TIME tStop = m_tStop; if (tStop > m_tDuration) { tStop = m_tDuration; } // align the stop position - may be past stop, but that // doesn't matter REFERENCE_TIME tAlignStop = AlignUp(tStop / UNITS, Actual.cbAlign) * UNITS; DWORD dwRequest; if (!m_bSync) { // Break out of the loop either if we get to the end or we're asked // to do something else while (tCurrent < tAlignStop) { // Break out without calling EndOfStream if we're asked to // do something different if (CheckRequest(&dwRequest)) { return; } // queue a first sample if (Actual.cBuffers > 1) { hr = QueueSample(tCurrent, tAlignStop, TRUE); bDiscontinuity = FALSE; if (FAILED(hr)) { return; } } // loop queueing second and waiting for first.. while (tCurrent < tAlignStop) { hr = QueueSample(tCurrent, tAlignStop, bDiscontinuity); bDiscontinuity = FALSE; if (FAILED(hr)) { return; } hr = CollectAndDeliver(tStart, tStop); if (S_OK != hr) { // stop if error, or if downstream filter said // to stop. return; } } if (Actual.cBuffers > 1) { hr = CollectAndDeliver(tStart, tStop); if (FAILED(hr)) { return; } } } } else { // sync version of above loop while (tCurrent < tAlignStop) { // Break out without calling EndOfStream if we're asked to // do something different if (CheckRequest(&dwRequest)) { return; } IMediaSample* pSample; hr = m_pAlloc->GetBuffer(&pSample, NULL, NULL, 0); if (FAILED(hr)) { OnError(hr); return; } LONGLONG tStopThis = tCurrent + (pSample->GetSize() * UNITS); if (tStopThis > tAlignStop) { tStopThis = tAlignStop; } pSample->SetTime(&tCurrent, &tStopThis); tCurrent = tStopThis; if (bDiscontinuity) { pSample->SetDiscontinuity(TRUE); bDiscontinuity = FALSE; } hr = m_pReader->SyncReadAligned(pSample); if (FAILED(hr)) { pSample->Release(); OnError(hr); return; } hr = DeliverSample(pSample, tStart, tStop); if (hr != S_OK) { if (FAILED(hr)) { OnError(hr); } return; } } } EndOfStream(); }
DWORD WINAPI ReceiveThread(PVOID param) { HRESULT hr; ReceiveParam *receiveParam = (ReceiveParam*)param; HANDLE PushSemaphore = receiveParam->PushSemaphore; HANDLE PushDataMutex = receiveParam->PushDataMutex; std::map<REFERENCE_TIME,IMediaSample*>& SampleList = *receiveParam->SampleList; NetReceiveFilter* filter = receiveParam->filter; SOCKET socket ; delete receiveParam; LONG packSize; // CMediaSample *tmpSample = (CMediaSample*) malloc(sizeof(CMediaSample)); REFERENCE_TIME startTime = 0,endTime = 0; //马上播放 REFERENCE_TIME mediaStartTime = 0,mediaEndTime = 0; AM_SAMPLE2_PROPERTIES sample2Properties; NetReceiveOutputPin* outputPin = reinterpret_cast<NetReceiveOutputPin*>(filter->GetPin(0)); assert(outputPin != NULL); filter->waitForNewSocket(); while(true) { IMediaSample *sample = filter->GetFreeSample(); if (sample == NULL) { ErrorPrint("Get free sample error"); return 1; } PBYTE dataPointer = NULL; hr = sample->GetPointer(&dataPointer); if (FAILED(hr)) { ErrorPrint("Get data pointer error",hr); sample->Release(); return 1; } CAutoLock lock(filter->getSocketLock()); socket = filter->getSocket(); if (!receiveData(socket, (char*)&sample2Properties, sizeof(sample2Properties))) { ErrorPrint("Get pack Properties error"); sample->Release(); filter->waitForNewSocket(); continue; } packSize = sample2Properties.lActual; if (packSize > 100 * 1024) { std::cout<<"Exceed 100K:"<<packSize/1024<<std::endl; } AM_MEDIA_TYPE mediaType; filter->GetPin(0)->ConnectionMediaType(&mediaType); if (filter->getPlayMode() == 1) { // static const unsigned long offset = 10000000; //将延迟增加,尽量缓冲一些 // sample2Properties.tStart +=offset; // sample2Properties.tStop += offset; sample2Properties.cbData = sizeof(sample2Properties) - 9; sample2Properties.pbBuffer= dataPointer; IMediaSample2 *mediaSample2; hr = sample->QueryInterface(IID_IMediaSample2, (void**)&mediaSample2); if (FAILED(hr)) { ErrorPrint("Get media sample2 interface error",hr); sample->Release(); return 1; } ComReleaser mediaSample2Releaser(mediaSample2); hr = mediaSample2->SetProperties(sample2Properties.cbData, (BYTE*)&sample2Properties); if (FAILED(hr)) { ErrorPrint("Set sample properties error"); } sample->SetTime(&sample2Properties.tStart, &sample2Properties.tStop); sample->GetTime(&startTime,&endTime); } else { startTime = 0; endTime = 0; } ASSERT(packSize <= sample->GetSize()); sample->SetActualDataLength(packSize); sample->SetTime(&startTime, &endTime); if(!receiveData(socket, (char*)dataPointer, packSize)) { ErrorPrint("Receive pack errors"); sample->Release(); filter->waitForNewSocket(); continue; } //通知PUSH线程进行数据传送 WaitForSingleObject(PushDataMutex, INFINITE); SampleList.insert(std::make_pair(startTime, sample)); if(filter->getPlayMode() == 0) //如果尽快播放,则只要有一个sample就通知push线程 { if (SampleList.size() == 1) { ReleaseSemaphore(PushSemaphore, 1, NULL); } } else if (filter->getPlayMode() == 1)//如果考虑时间戳,我们则缓冲尽量多的sample,但也不能太多 { if (SampleList.size() >= 24 * 10) { ReleaseSemaphore(PushSemaphore, 1, NULL); } } ReleaseMutex(PushDataMutex); outputPin->newTransSample(sample2Properties, dataPointer); //通知进行sample的转发 } return 0; }
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; }
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; }
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 CWavPackDSDecoder::Receive(IMediaSample *pSample) { // Check for other streams and pass them on AM_SAMPLE2_PROPERTIES * const pProps = m_pInput->SampleProps(); if ((pProps->dwStreamId != AM_STREAM_MEDIA) && (pProps->dwStreamId != AM_STREAM_BLOCK_ADDITIONNAL)) { return m_pOutput->Deliver(pSample); } ASSERT(pSample); // If no output to deliver to then no point sending us data ASSERT(m_pOutput != NULL); HRESULT hr = S_OK; BYTE *pSrc, *pDst; DWORD SrcLength = pSample->GetActualDataLength(); hr = pSample->GetPointer(&pSrc); if(FAILED(hr)) return hr; // Check for minimal block size if(SrcLength < (3 * sizeof(uint32_t))) { return S_OK; } WAVEFORMATEX* pwfx = (WAVEFORMATEX*)m_pInput->CurrentMediaType().Format(); BOOL bSeveralBlocks = (pwfx->nChannels > 2); if(pProps->dwStreamId == AM_STREAM_MEDIA) { REFERENCE_TIME rtStop; if(pSample->IsSyncPoint() == S_OK) { pSample->GetTime(&m_rtFrameStart, &rtStop); m_TotalSamples = 0; } m_MainBlockDiscontinuity = (pSample->IsDiscontinuity() == S_OK); reconstruct_wavpack_frame( m_MainFrame, &m_CommonFrameData, (char*)pSrc, SrcLength, TRUE, bSeveralBlocks, m_PrivateData.version); if(m_HybridMode == TRUE) { // Stop here and wait for correction data return S_OK; } } if((m_HybridMode == TRUE) && (pProps->dwStreamId == AM_STREAM_BLOCK_ADDITIONNAL)) { // rebuild correction data block reconstruct_wavpack_frame( m_CorrectionFrame, &m_CommonFrameData, (char*)pSrc, SrcLength, FALSE, bSeveralBlocks, m_PrivateData.version); } if(wavpack_buffer_decoder_load_frame(m_Codec, m_MainFrame->data, m_MainFrame->len, m_HybridMode ? m_CorrectionFrame->data : NULL, m_CorrectionFrame->len) == 0) { // Something is wrong return S_FALSE; } // We can precise the decoding mode now if(m_HybridMode == FALSE) { if(m_CommonFrameData.array_flags[0] & WV_HYBRID_FLAG) { m_DecodingMode = DECODING_MODE_LOSSY; } else { m_DecodingMode = DECODING_MODE_LOSSLESS; } } uint32_t samplesLeft = m_CommonFrameData.block_samples; while(samplesLeft > 0) { // Set up the output sample IMediaSample *pOutSample; hr = InitializeOutputSample(pSample, &pOutSample); if(FAILED(hr)) { break; } DWORD DstLength = pOutSample->GetSize(); hr = pOutSample->GetPointer(&pDst); if(FAILED(hr)) { pOutSample->Release(); break; } DstLength &= 0xFFFFFFF8; long samples = wavpack_buffer_decoder_unpack(m_Codec,(int32_t *)pDst, m_SamplesPerBuffer); if(samples) { wavpack_buffer_format_samples(m_Codec, (uchar *) pDst, (long*) pDst, samples); DstLength = samples * WavpackGetBytesPerSample(m_Codec->wpc) * WavpackGetNumChannels (m_Codec->wpc); pOutSample->SetActualDataLength(DstLength); REFERENCE_TIME rtStart, rtStop; rtStart = m_rtFrameStart + (REFERENCE_TIME)(((double)m_TotalSamples / WavpackGetSampleRate(m_Codec->wpc)) * 10000000); m_TotalSamples += samples; rtStop = m_rtFrameStart + (REFERENCE_TIME)(((double)m_TotalSamples / WavpackGetSampleRate(m_Codec->wpc)) * 10000000); if(rtStart < 0 && rtStop < 0) { // No need to deliver this sample it will be skipped pOutSample->Release(); continue; } pOutSample->SetTime(&rtStart, &rtStop); pOutSample->SetSyncPoint(TRUE); pOutSample->SetDiscontinuity(m_MainBlockDiscontinuity); if(m_MainBlockDiscontinuity == TRUE) { m_MainBlockDiscontinuity = FALSE; } hr = m_pOutput->Deliver(pOutSample); if(FAILED(hr)) { pOutSample->Release(); break; } pOutSample->Release(); } else { pOutSample->Release(); break; } samplesLeft -= samples; } m_DecodedFrames++; m_CrcError = WavpackGetNumErrors(m_Codec->wpc); return S_OK; }