int LoadSamples (void) { FILE *f; int i; if (Verbose) printf (" Opening %s... ",szSoundFileName); f=fopen (szSoundFileName,"rb"); if (!f) { if (Verbose) puts("NOT FOUND");return 0; } if (Verbose) printf ("OK\n Loading samples... "); if (fread (sample_params,1,sizeof(sample_params),f)!=sizeof(sample_params)) { if (Verbose) puts ("READ ERROR"); return 0; } for (i=0;i<15;++i) { sample_ptr[i]=malloc (sample_params[i].len*2); if (!sample_ptr[i]) { if (Verbose) puts ("OUT OF MEMORY"); FreeSamples (); return 0; } if (fread (sample_ptr[i],1,sample_params[i].len*2,f)!=sample_params[i].len*2) { if (Verbose) puts ("READ ERROR"); FreeSamples (); return 0; } } fclose (f); if (Verbose) puts ("OK"); return 1; }
// // COutputQueuee Destructor : // // Free all resources - // // Thread, // Batched samples // COutputQueue::~COutputQueue() { DbgLog((LOG_TRACE, 3, TEXT("COutputQueue::~COutputQueue"))); /* Free our pointer */ if (m_pInputPin != NULL) { m_pInputPin->Release(); } if (m_hThread != NULL) { { CAutoLock lck(this); m_bTerminate = TRUE; m_hr = S_FALSE; NotifyThread(); } DbgWaitForSingleObject(m_hThread); EXECUTE_ASSERT(CloseHandle(m_hThread)); // The thread frees the samples when asked to terminate ASSERT(m_List->GetCount() == 0); delete m_List; } else { FreeSamples(); } if (m_hSem != NULL) { EXECUTE_ASSERT(CloseHandle(m_hSem)); } delete [] m_ppSamples; }
// // leave flush mode - pass this downstream void COutputQueue::EndFlush() { { CAutoLock lck(this); ASSERT(m_bFlushing); if(m_bFlushingOpt && m_bFlushed && IsQueued()) { m_bFlushing = FALSE; m_hr = S_OK; return; } } // sync with pushing thread -- done in BeginFlush // ensure no more data to go downstream -- done in BeginFlush // // Because we are synching here there is no need to hold the critical // section (in fact we'd deadlock if we did!) if(IsQueued()) { m_evFlushComplete.Wait(); } else { FreeSamples(); } // Be daring - the caller has guaranteed no samples will arrive // before EndFlush() returns m_bFlushing = FALSE; m_bFlushed = TRUE; // call EndFlush on downstream pins m_pPin->EndFlush(); m_hr = S_OK; }
// // Thread sending the samples downstream : // // When there is nothing to do the thread sets m_lWaiting (while // holding the critical section) and then waits for m_hSem to be // set (not holding the critical section) // DWORD COutputQueue::ThreadProc() { while (TRUE) { BOOL bWait = FALSE; IMediaSample *pSample; LONG lNumberToSend; // Local copy NewSegmentPacket* ppacket; // // Get a batch of samples and send it if possible // In any case exit the loop if there is a control action // requested // { CAutoLock lck(this); while (TRUE) { if (m_bTerminate) { FreeSamples(); return 0; } if (m_bFlushing) { FreeSamples(); SetEvent(m_evFlushComplete); } // Get a sample off the list pSample = m_List->RemoveHead(); // inform derived class we took something off the queue if (m_hEventPop) { //DbgLog((LOG_TRACE,3,TEXT("Queue: Delivered SET EVENT"))); SetEvent(m_hEventPop); } if (pSample != NULL && !IsSpecialSample(pSample)) { // If its just a regular sample just add it to the batch // and exit the loop if the batch is full m_ppSamples[m_nBatched++] = pSample; if (m_nBatched == m_lBatchSize) { break; } } else { // If there was nothing in the queue and there's nothing // to send (either because there's nothing or the batch // isn't full) then prepare to wait if (pSample == NULL && (m_bBatchExact || m_nBatched == 0)) { // Tell other thread to set the event when there's // something do to ASSERT(m_lWaiting == 0); m_lWaiting++; bWait = TRUE; } else { // We break out of the loop on SEND_PACKET unless // there's nothing to send if (pSample == SEND_PACKET && m_nBatched == 0) { continue; } if (pSample == NEW_SEGMENT) { // now we need the parameters - we are // guaranteed that the next packet contains them ppacket = (NewSegmentPacket *) m_List->RemoveHead(); // we took something off the queue if (m_hEventPop) { //DbgLog((LOG_TRACE,3,TEXT("Queue: Delivered SET EVENT"))); SetEvent(m_hEventPop); } ASSERT(ppacket); } // EOS_PACKET falls through here and we exit the loop // In this way it acts like SEND_PACKET } break; } } if (!bWait) { // We look at m_nBatched from the client side so keep // it up to date inside the critical section lNumberToSend = m_nBatched; // Local copy m_nBatched = 0; } } // Wait for some more data if (bWait) { DbgWaitForSingleObject(m_hSem); continue; } // OK - send it if there's anything to send // We DON'T check m_bBatchExact here because either we've got // a full batch or we dropped through because we got // SEND_PACKET or EOS_PACKET - both of which imply we should // flush our batch if (lNumberToSend != 0) { long nProcessed; if (m_hr == S_OK) { ASSERT(!m_bFlushed); HRESULT hr = m_pInputPin->ReceiveMultiple(m_ppSamples, lNumberToSend, &nProcessed); /* Don't overwrite a flushing state HRESULT */ CAutoLock lck(this); if (m_hr == S_OK) { m_hr = hr; } ASSERT(!m_bFlushed); } while (lNumberToSend != 0) { m_ppSamples[--lNumberToSend]->Release(); } if (m_hr != S_OK) { // In any case wait for more data - S_OK just // means there wasn't an error DbgLog((LOG_ERROR, 2, TEXT("ReceiveMultiple returned %8.8X"), m_hr)); } } // Check for end of stream if (pSample == EOS_PACKET) { // We don't send even end of stream on if we've previously // returned something other than S_OK // This is because in that case the pin which returned // something other than S_OK should have either sent // EndOfStream() or notified the filter graph if (m_hr == S_OK) { DbgLog((LOG_TRACE, 2, TEXT("COutputQueue sending EndOfStream()"))); HRESULT hr = m_pPin->EndOfStream(); if (FAILED(hr)) { DbgLog((LOG_ERROR, 2, TEXT("COutputQueue got code 0x%8.8X from EndOfStream()"))); } } } // Data from a new source if (pSample == RESET_PACKET) { m_hr = S_OK; SetEvent(m_evFlushComplete); } if (pSample == NEW_SEGMENT) { m_pPin->NewSegment(ppacket->tStart, ppacket->tStop, ppacket->dRate); delete ppacket; } } }