Exemple #1
0
DWORD StreamContext::Reset()
{
    AddRef();

    // Stop stream for now.
    Stop();

    m_lpWaveHdrCurrent  = NULL;
    m_lpCurrData       = NULL;
    m_lpCurrDataEnd    = NULL;
    m_dwByteCount      = 0;
    m_dwLoopCount      = 0;

    LPWAVEHDR lpHdr;
    while (m_lpWaveHdrHead)
    {
        lpHdr = m_lpWaveHdrHead;
        m_lpWaveHdrHead = lpHdr->lpNext;
        if (m_lpWaveHdrHead==NULL)
        {
            m_lpWaveHdrTail=NULL;
        }
        ReturnBuffer(lpHdr);
    }

    Release();

    return MMSYSERR_NOERROR;
}
Exemple #2
0
DWORD StreamContext::BreakLoop()
{
    AddRef();

    if (m_dwLoopCount>0)
    {
        m_dwLoopCount = 0;

        LPWAVEHDR lpHdr;
        while (m_lpWaveHdrHead!=m_lpWaveHdrCurrent)
        {
            lpHdr = m_lpWaveHdrHead;
            m_lpWaveHdrHead = lpHdr->lpNext;
            if (m_lpWaveHdrHead==NULL)
            {
                m_lpWaveHdrTail=NULL;
            }
            ReturnBuffer(lpHdr);
        }
    }

    Release();

    return MMSYSERR_NOERROR;
}
Exemple #3
0
// Read data from the audio Buffer.
// Called at interrupt time to get the good data from the audiobuffer object.
//
BOOL WAVESTREAM::_vReadAudioBuf(void)
{
   PSTREAMBUFFER pTemp = (PSTREAMBUFFER)qhInProcess.Head();
   ULONG pdataBuf;
   ULONG Buff_left, bytesread;

   if(!pTemp) return FALSE;

   // get the buffer pointer and amount of data remaining
   pdataBuf = (ULONG)pTemp->pBuffptr + pTemp->ulBuffpos;
   Buff_left = pTemp->ulBuffsz - pTemp->ulBuffpos;

   // write the audio buffer
   bytesread = OSS16_StreamAddBuffer(this, pdataBuf, Buff_left);
   if(bytesread == 0) {
	return FALSE; //no more data
   }

   dprintf4(("_vReadAudioBuf %lx size %d, bytes read %d", pdataBuf, Buff_left, bytesread));

   // update the buffer pos counter
   pTemp->ulBuffpos  += bytesread;
   _ulBytesProcessed += bytesread;

   if(pTemp->ulBuffpos == pTemp->ulBuffsz) {
      	qhDone.PushOnTail(qhInProcess.PopHead());
	ReturnBuffer();
   	dprintf4(("_vReadAudioBuf return buffer %lx size %ld, bytes read %ld", (ULONG)pTemp->pBuffptr, pTemp->ulBuffsz, bytesread));
   }

   return TRUE;
}
Exemple #4
0
void STREAM::ReturnBuffers(void)
{
   while (uHead != uTail) {
      ReturnBuffer(uHead);
      uHead = (uHead+1) & (MAX_BUFFERS-1);
   }

   uBufIdx=0;
}
Exemple #5
0
// called by the irq function in the hardware object when we get an interrupt
// first call _vUpdateProcessed() to update the dma amd audio buffer related
// stuff. Next if we have buffers on the primary queue try to read/write them
// to the audiobuffer. Look at the buffers on the done queue and see if they
// can be returned and finally process any events pending.
void WAVESTREAM::Process(void)
{
 PSTREAMBUFFER ptemp;
 ULONG         ulCurBytesProcessed = 0;
 ULONG         bytesinc;

   switch (ulStreamType & STREAM_WRITE) {
   case STREAM_WRITE:
   {
   	OSS16_StreamGetPos(this, &ulCurBytesProcessed);
   	if(ulCurBytesProcessed == 0) {
		//shouldn't happen
		DebugInt3();
		return;
	}
   	bytesinc           = ulCurBytesProcessed - _ulBytesProcessed;
	dprintf4(("Process: %lx %x", ulCurBytesProcessed, (USHORT)bytesinc));
	if(ulCurBytesProcessed < _ulBytesProcessed) {
       		dprintf(("WARNING: Process: Current pos %ld incr %d", ulCurBytesProcessed, (USHORT)bytesinc));
	}
   	_ulBytesProcessed  = ulCurBytesProcessed;

      	while(bytesinc) {
      	  if(qhDone.IsElements()) {  // if there are buffers that have been
                                  // completly written to the audio buffer
                                  // check the first one on the done queue
                                  // if it's data has been consumed by
                                  // the hardware return it
         	ptemp = (PSTREAMBUFFER)qhDone.Head();
		ptemp->ulDonepos += bytesinc;
		bytesinc          = 0;
		if(ptemp->ulDonepos >= ptemp->ulBuffsz) {
			//calc position in next buffer
			bytesinc = ptemp->ulDonepos - ptemp->ulBuffsz;
			dprintf3(("Process: Return buffer %lx size %d", ptemp->pBuffptr, ptemp->ulBuffsz));
		 	ReturnBuffer();
		}
      	  }
	  else	break; //shouldn't happen
      	}
	AddBuffers(FALSE);
	break;
   }
   case STREAM_READ:
	while(_vReadAudioBuf());
	break;
   default:
      break;
   } /* endswitch */

   ProcessEvents();
}
Exemple #6
0
void CMMALVideo::ReleaseBuffer(CMMALVideoBuffer *buffer)
{
  // remove from busy list
  pthread_mutex_lock(&m_output_mutex);
  assert(m_output_busy > 0);
  m_output_busy--;
  pthread_mutex_unlock(&m_output_mutex);
  ReturnBuffer(buffer);
  bool done = false;
  pthread_mutex_lock(&m_output_mutex);
  if (m_finished && !m_output_busy)
    done = true;
  pthread_mutex_unlock(&m_output_mutex);
  if (done)
    m_myself.reset();
  if (g_advancedSettings.CanLogComponent(LOGVIDEO))
    CLog::Log(LOGDEBUG, "%s::%s %p (%p) dts_queue(%d) ready_queue(%d) busy_queue(%d) done:%d", CLASSNAME, __func__, buffer, buffer->mmal_buffer, m_dts_queue.size(), m_output_ready.size(), m_output_busy, done);
  delete buffer;
}
Exemple #7
0
// Assumes lock is taken
PBYTE StreamContext::GetNextBuffer()
{
    LPWAVEHDR lpOldHdr;
    LPWAVEHDR lpNewHdr;
    LPSTR pNewBuf=NULL;

    // Get a pointer to the current buffer which is now done being processed
    lpOldHdr=m_lpWaveHdrCurrent;

    if (!lpOldHdr)
    {
        return NULL;
    }

    // Are we in a loop
    // Note: a loopcount of 1 means we're not really in a loop
    if (m_dwLoopCount>1)
    {
        // We're in a loop!
        if (lpOldHdr->dwFlags & WHDR_ENDLOOP)
        {
           // In loop, last buffer
            // If dwLoopCount was set to INFINITE, loop forever
            // (Note: this is not explicitly in the wave driver API spec)
            if (m_dwLoopCount!=INFINITE)
            {
           m_dwLoopCount--;                    // decrement loop count
            }
           lpNewHdr=m_lpWaveHdrHead;           // go back to start of loop
        }
        else
        {
           // In loop, intermediate buffer
           lpNewHdr=lpOldHdr->lpNext;          // just go to next buffer in loop block
        }

        lpOldHdr=NULL;
    }
    else
    {
        // Not in a loop; return old buffer and get new buffer
        lpNewHdr=lpOldHdr->lpNext;

        m_lpWaveHdrHead = lpNewHdr;           // reset list head
        if (!lpNewHdr)
        {
            m_lpWaveHdrTail=NULL;             // no new buffer, reset tail to NULL
        }
        else if (lpNewHdr->dwFlags & WHDR_BEGINLOOP)    // if new buffer is start of a loop block
        {
            m_dwLoopCount=lpNewHdr->dwLoops;  // save # of loops
        }
    }

    m_lpWaveHdrCurrent=lpNewHdr;              // save current buffer pointer

    if (lpNewHdr)
    {
        m_lpCurrData    = (PBYTE)lpNewHdr->lpData;  // reinitialize data pointer
        m_lpCurrDataEnd = m_lpCurrData + lpNewHdr->dwBufferLength;
    }
    else
    {
        m_lpCurrData  = NULL;
        m_lpCurrDataEnd = NULL;
    }

    // Return the old buffer
    // This may cause the stream to be destroyed, so make sure that any calls to this function
    // are within an AddRef/Release block
    if (lpOldHdr)
    {
        ReturnBuffer(lpOldHdr);
    }

    return m_lpCurrData;
}
Exemple #8
0
//
// _vRealignPausedBuffers(void)
// when a stream is paused we need to "realign" the data in the audio buffer
// with reality. On playback, not all the data in the audio buffer has been
// consumed. Likewise on a capture, not all the good data in the audio buffer
// has been copied out. After receiving the DDCMDCONTROL Pause we will call
// this function to line the MMPM buffers back up.
// there are 2 cases here: first one is the case of a capture stream.
// for a capture stream we simply read any data that is still in the audio
// buffer into a MMPM buffer.
// for a playback stream things are not so straight forward.
// first check the STREAMBUFFER on pHead to see if any of it's data is in the
// audio buffer and not consumed, if yes back up the ulBuffpos in the
// STREAMBUFFER. Next check any STREAMBUFFERS on pdone starting with the last
// one. (the one on the tail of the queue) If necessary back up the ulBuffpos
// and put the STREAMBUFFER on the Head queue.
//
void WAVESTREAM::_vRealignPausedBuffers(ULONG endpos)
{
   PSTREAMBUFFER ptempbuff;

   switch (ulStreamType & STREAM_WRITE) {
   case STREAM_READ:
	//SvL: Don't get the lastest recording data as a read command
        //     would now restart recording (as it's stopped)
        //     Just return what we've got or push the buffer on the inprocess queue
	ptempbuff = (PSTREAMBUFFER)qhDone.Head();
	if(ptempbuff) {
		if(ptempbuff->ulBuffpos) {//if we recorded anything into this buffer, then return it now
			ReturnBuffer();
			return;
		}
		ptempbuff->ulBuffpos = 0;
		ptempbuff->ulDonepos = 0;
		qhInProcess.PushOnHead(qhDone.PopHead());
	}
      	break;

   case STREAM_WRITE:
   {
        PQUEUEHEAD pTempHead = new QUEUEHEAD;
        ULONG bytesinc;
        USHORT usRC;

	bytesinc = endpos - _ulBytesProcessed;
      	bytesinc &= 0xFFFFFFFC; //keep it on a dword boundary

      	// if there are bufferes on the done queue, pop them off the head and
      	// push them on the head of qhTempHead.  This will reorder them so
      	// that the more recently used ones will be in the front of the queue.
      	// Pass them all to _vRealignBuffer. If the rc from _vRealignBuffer is
      	// 0 then there is no unprocessed data in the buffer (it is ready to
      	// be returned) so put it on the Tail of the done queue.
      	// If the rc is 1 then put it on the head of the InProcess queue.

      	while (qhDone.IsElements()) {
         	pTempHead->PushOnTail(qhDone.PopHead());
      	} /* endwhile */

      	while (qhInProcess.IsElements()) {
         	pTempHead->PushOnTail(qhInProcess.PopHead());
      	} /* endwhile */

      	while(pTempHead->IsElements()) {
         	usRC = _vRealignBuffer(&bytesinc, (PSTREAMBUFFER)pTempHead->Head());
         	if (usRC) {
           		qhInProcess.PushOnTail(pTempHead->PopHead());
		}
         	else {
		    	qhDone.PushOnTail(pTempHead->PopHead());
		}
      	} /* endwhile */
	if(qhDone.IsElements())
		ReturnBuffer();

   	delete pTempHead; // free the memory this ain't no Java here !!
      	break;
   }
   default:
      	break;
   } /* endswitch */
}