?? hxaudstr.cpp
字號:
{ m_Owner->UpdateStreamLastWriteTime(); UpdateStreamLastWriteTime(TRUE); } }//{FILE* f1 = ::fopen("c:\\temp\\audio.txt", "a+"); ::fprintf(f1, "%lu\tAddData\t%p\t%lu\n", HX_GET_BETTERTICKCOUNT(), this, pAudioData->ulAudioTime);::fclose(f1);}// ::fwrite(pAudioData->pData->GetBuffer(), pAudioData->pData->GetSize(), 1, fdin); UINT32 ulDataTime = CalcMs(pAudioData->pData->GetSize()); UINT32 ulEndTime = pAudioData->ulAudioTime + ulDataTime; if (m_pAvailableBuffers && !m_bDeterminedInitialCacheSize && ulDataTime > 0) { m_bDeterminedInitialCacheSize = TRUE; m_uCacheSize = (UINT16) (m_ulGranularity*2/ulDataTime) + 1; /* make sure it is atleast CACHE_INCREMENT_SIZE to begin with */ m_uCacheSize = m_uCacheSize < CACHE_INCREMENT_SIZE ? CACHE_INCREMENT_SIZE : m_uCacheSize; } if (m_ulLastInputStartTime > pAudioData->ulAudioTime && ((m_ulLastInputStartTime - pAudioData->ulAudioTime) > MAX_TIMESTAMP_GAP)) { bInTSRollOver = TRUE; m_ulTSRollOver++; } m_ulLastInputStartTime = pAudioData->ulAudioTime; m_ulLastInputEndTime = ulEndTime; /* even in STREAMING_AUDIO case, it might happen, that the packets * written are late. e.g. packets received late on the network */ INT64 llActualTimestamp = CAST_TO_INT64 (pAudioData->ulAudioTime) + CAST_TO_INT64 m_ulTSRollOver * CAST_TO_INT64 MAX_UINT32; INT64 llActualEndTime = CAST_TO_INT64 (pAudioData->ulAudioTime) + CAST_TO_INT64 (ulDataTime) + CAST_TO_INT64 m_ulTSRollOver * CAST_TO_INT64 MAX_UINT32; if ((pAudioData->uAudioStreamType == STREAMING_AUDIO || pAudioData->uAudioStreamType == TIMED_AUDIO) && !(llActualTimestamp >= m_llLastWriteTime || llActualEndTime > m_llLastWriteTime)) { /* Too late*/ m_bTobeTimed = TRUE;//{FILE* f1 = ::fopen("e:\\audio.txt", "a+"); ::fprintf(f1, "%lu\t%p\t%d\t%lu\t%lu\tLATE\n", HX_GET_BETTERTICKCOUNT(), this, m_pDataList->GetCount(), pAudioData->ulAudioTime, (INT32)m_llLastWriteTime);::fclose(f1);} return HXR_LATE_PACKET; } pAinfo = new HXAudioInfo; if(!pAinfo) { theErr = HXR_OUTOFMEMORY; goto exit; } pAudioData->pData->AddRef(); pAinfo->pBuffer = pAudioData->pData; pAinfo->ulStartTime = pAudioData->ulAudioTime; pAinfo->pOffset = pAudioData->pData->GetBuffer(); pAinfo->ulBytesLeft = pAudioData->pData->GetSize(); pAinfo->uAudioStreamType = pAudioData->uAudioStreamType; if (m_bTobeTimed && pAudioData->uAudioStreamType == STREAMING_AUDIO) { pAinfo->uAudioStreamType = TIMED_AUDIO; m_bTobeTimed = FALSE; } else if (m_bTobeTimed && pAudioData->uAudioStreamType == TIMED_AUDIO) { m_bTobeTimed = FALSE; }//{FILE* f1 = ::fopen("c:\\temp\\audio.txt", "a+"); ::fprintf(f1, "AddData ulAudioTime: %lu\n", pAudioData->ulAudioTime);::fclose(f1);} if (pAinfo->uAudioStreamType == INSTANTANEOUS_AUDIO) { CHXSimpleList* pList = new CHXSimpleList; if(!pList) { theErr = HXR_OUTOFMEMORY; goto exit; } pList->AddHead((void*) pAinfo); m_pInstantaneousList->AddTail((void*) pList); m_Owner->m_Owner->ToBeRewound(); } else if (pAinfo->uAudioStreamType == STREAMING_INSTANTANEOUS_AUDIO) { HX_ASSERT(m_pInstantaneousList && m_pInstantaneousList->GetCount() > 0); CHXSimpleList* pList = NULL; if (m_pInstantaneousList->GetCount() == 0) { pList = new CHXSimpleList; if(!pList) { theErr = HXR_OUTOFMEMORY; goto exit; } m_pInstantaneousList->AddTail((void*) pList); // fix for naive users! pAinfo->uAudioStreamType = INSTANTANEOUS_AUDIO; m_Owner->m_Owner->ToBeRewound(); } pList = (CHXSimpleList*) m_pInstantaneousList->GetTail(); pList->AddTail(pAinfo); } else if (m_pDataList->IsEmpty()) { m_pDataList->AddTail((void*) pAinfo); } else { HXAudioInfo* pInfo = (HXAudioInfo*) m_pDataList->GetTail(); UINT32 ulActualTSRollOver = m_ulTSRollOver; if (bInTSRollOver && ulActualTSRollOver) { ulActualTSRollOver--; } INT64 llActualLastEndTime = CAST_TO_INT64 (pInfo->ulStartTime) + CAST_TO_INT64 (CalcMs(pInfo->pBuffer->GetSize())) + CAST_TO_INT64 ulActualTSRollOver * CAST_TO_INT64 MAX_UINT32; INT64 llActualLastStartTime = CAST_TO_INT64 (pInfo->ulStartTime) + CAST_TO_INT64 ulActualTSRollOver * CAST_TO_INT64 MAX_UINT32; if (llActualTimestamp < llActualLastStartTime) { /* Not allowed */ theErr = HXR_OUTOFORDER_PACKET; /* something is fu*#$#up... figure out what?*/ HX_ASSERT(!("Packets written out of order")); goto exit; } if (pAinfo->uAudioStreamType == STREAMING_AUDIO) { /* is it a resonable packet to add to the list */ if ((llActualTimestamp <= llActualLastEndTime && llActualLastEndTime - llActualTimestamp <= m_ulFudge) || (llActualTimestamp >= llActualLastEndTime && llActualTimestamp - llActualLastEndTime <= m_ulFudge)) { m_pDataList->AddTail((void*) pAinfo); } else { theErr = HXR_NONCONTIGUOUS_PACKET; //HX_LATE_PACKET; /* something is fu*#$#up... figure out what?*/ HX_ASSERT(!("Streaming Audio: Non-Contigous Write")); m_bTobeTimed = TRUE; goto exit; } } else { /* see if there is any overlap.. we do not allow any overlap */ if (llActualTimestamp < llActualLastEndTime && llActualLastEndTime - llActualTimestamp > m_ulFudge) { /* hmmm an overlapped packet */ theErr = HXR_OVERLAPPED_PACKET; /* something is fu*#$#up... figure out what?*/ HX_ASSERT(!("Timed Audio: Overlapping write")); m_bTobeTimed = TRUE; goto exit; } else { m_pDataList->AddTail((void*) pAinfo); } } }exit: if (theErr != HXR_OK && pAinfo) { pAinfo->pBuffer->Release(); delete pAinfo; } /* Make sure to discard any data that is prior to cross-fade time */ if (!theErr && m_bCrossFadingToBeDone && m_bFadeToThisStream) { RemoveExcessCrossFadeData(); }//{FILE* f1 = ::fopen("e:\\audio.txt", "a+"); ::fprintf(f1, "%lu\t%p\t%d\t%lu\t%lu\n", HX_GET_BETTERTICKCOUNT(), this, m_pDataList->GetCount(), pAudioData->ulAudioTime, (UINT32)m_llLastWriteTime);::fclose(f1);} return theErr;}HX_RESULT CHXAudioStream::ProcessInfo(void){ HX_RESULT theErr = HXR_OK; // Calculate the number of bytes per granularity. m_ulInputBytesPerGran = (ULONG32) (((m_AudioFmt.uChannels * ((m_AudioFmt.uBitsPerSample==8)?1:2) * m_AudioFmt.ulSamplesPerSec) / 1000.0) * m_ulGranularity); m_ulOutputBytesPerGran = (ULONG32) (((m_DeviceFmt.uChannels * ((m_DeviceFmt.uBitsPerSample==8)?1:2) * m_DeviceFmt.ulSamplesPerSec) / 1000.0) * m_ulGranularity); /* Number of samples required at output should be a multiple of 8 if * sampling rate is 8K/16K/32K...or a multiple of 11 for 11K/22K... * This is needed since the resamplerequires works reliably ONLY if * this condition is true. Ken is working on this problem. This is * an interim fix */ ULONG32 ulExtraGranularity = 1; if (m_DeviceFmt.ulSamplesPerSec % 8 == 0) { ulExtraGranularity = 8; } else { ulExtraGranularity = 11; } // Make sure that number of bytes per granularity is an even number. if (m_ulInputBytesPerGran % (2*m_AudioFmt.uChannels*ulExtraGranularity) != 0) { m_ulInputBytesPerGran -= m_ulInputBytesPerGran % (2*m_AudioFmt.uChannels*ulExtraGranularity); } if (m_ulOutputBytesPerGran % (2*m_DeviceFmt.uChannels*ulExtraGranularity) != 0) { m_ulOutputBytesPerGran -= m_ulOutputBytesPerGran % (2*m_DeviceFmt.uChannels*ulExtraGranularity); } if (!theErr) { // Setup the resampler theErr = SetupResampler(); } if (!theErr) { m_bInited = TRUE; if (m_eState == E_STOPPED) { m_eState = E_INITIALIZED; } } if (!theErr && m_bInited && m_bCrossFadingToBeDone && m_bFadeToThisStream) { InitializeCrossFader(); } /* Get the current player time to set the last write audio time * If someone creates a stream mid presentation, we ask the player * object for the current write time. */ // set last write time to be the current playback time since // this is what other system components(i.e. renderers) based on // fixed b#69847 - loss of push-down-worth of data = // m_Owner->GetLastAudioWriteTime() - m_Owner->GetCurrentPlayBackTime()// m_llLastWriteTime = m_Owner->GetCurrentPlayBackTime(); // XXXRA: It is necessary to use last audio write time for any delayed // audio streams to work that do not involve any Pause/Rewind logic. // To cover the case where a source (and an audio stream) has been added // mid-playback by SMIL renderer which has a delay equivalent to the // current playback time, it should result in a player rewind which should // reset the lastaudiowrite time accordingly...so we should be able // to use m_Owner->GetLastAudioWriteTime() value in such a use case as well. // this change is required to fix PR 79161 and PR 69780. // Henry, PR 69847 (the reason for the earlier change) is still busted. // so I am reverting this code to the original code. you will have // to come up with a different fix for PR 69847 since this was clearly not // the correct fix. m_llLastWriteTime = m_Owner->GetLastAudioWriteTime(); if (!theErr && m_bInited) { m_Owner->StreamInitialized(this); } return theErr;}/************************************************************************ * Method: * IHXAudioStream::SetupResampler * Purpose: */HX_RESULT CHXAudioStream::SetupResampler(){ HX_RESULT theErr = HXR_OK;#if defined(HELIX_FEATURE_RESAMPLER) // Create a resampler for this stream if we need one. // Current resampler code resamples these sampling rates: // 8000,11025,16000,22050,32000,44100. The resample also // converts 8-bit to 16-bit. NOTE: We convert all 8-bit samples // to 16-bit before input into the resampler or mixer. /* Resampler does the following tasks: * 1. Conversion for sampling rates * 2. Conversion from 8->16 and will also do 16->8 (XXX TBD) * 3. Conversion from stereo to mono * We do not use resampler for conversion from mono to stereo. This * takes place in the Mixer. *//* fprintf(fdbeforetxt, "Samples: %lu, Channels: %lu, Bits/Sample: %lu\n", m_AudioFmt.ulSamplesPerSec, m_AudioFmt.uChannels, m_AudioFmt.uBitsPerSample); fprintf(fdaftertxt, "Samples: %lu, Channels: %lu, Bits/Sample: %lu\n", m_DeviceFmt.ulSamplesPerSec, m_DeviceFmt.uChannels, m_DeviceFmt.uBitsPerSample);*/ if ((m_AudioFmt.ulSamplesPerSec != m_DeviceFmt.ulSamplesPerSec) || (m_AudioFmt.uBitsPerSample != m_DeviceFmt.uBitsPerSample) || (m_AudioFmt.uChannels == 2 && m_DeviceFmt.uChannels == 1)) { m_AudioFmt.uMaxBlockSize = (UINT16) (m_ulInputBytesPerGran*1.5); if (HXR_OK == m_Owner->GetOwner()->CreateResampler(m_AudioFmt, m_DeviceFmt, m_pResampler)) { /* times 2 since resampler always returns data in 16 bit. * times 2 if i/p or o/p is stereo * May change in future when we do 16->8 conversion in resampler */ m_ulMaxBlockSize = (ULONG32) m_DeviceFmt.uMaxBlockSize * 2 * 2; /* This may be TRUE in downsampling */ if (m_ulMaxBlockSize < (ULONG32) (m_ulInputBytesPerGran*1.5)) { m_ulMaxBlockSize = (ULONG32) (m_ulInputBytesPerGran*1.5); } } else { HX_RELEASE(m_pResampler); theErr = HX_RESAMPLER_ERROR; } if ( !theErr ) { m_pResampleBuf = (UCHAR*) new char [ m_ulMaxBlockSize ]; m_pTmpResBuf = (UCHAR*) new char [ m_ulMaxBlockSize ]; if (!m_pResampleBuf || !m_pTmpResBuf) { theErr = HXR_OUTOFMEMORY; } } } else { m_ulMaxBlockSize = m_DeviceFmt.uMaxBlockSize; } /* Do not rely on max block size specified by the user */ if (!theErr) { m_AudioFmt.uMaxBlockSize = (UINT16) m_ulMaxBlockSize; } m_bChannelConvert = (m_AudioFmt.uChannels == 1 && m_DeviceFmt.uChannels == 2);#endif /* HELIX_FEATURE_RESAMPLER */ // Create the resampler output buffer. Size it to the largest needed. return theErr;}/************************************************************************ * Method: * IHXAudioStream::GetFormat * Purpose: * Return the stream's audio format. */HX_RESULT CHXAudioStream::GetFormat( HXAudioFormat* pAudioFormat){ if (!m_bAudioFormatKnown) { return HXR_NOT_INITIALIZED; } pAudioFormat->uChannels = m_AudioFmt.uChannels; pAudioFormat->uBitsPerSample = m_AudioFmt.uBitsPerSample; pAudioFormat->ulSamplesPerSec = m_AudioFmt.ulSamplesPerSec; pAudioFormat->uMaxBlockSize = m_AudioFmt.uMaxBlockSize; return HXR_OK;}/************************************************************************ * Method: * IHXAudioStream::Setup * Purpose: * This is called by the player's Setup method. At this * time the audio device format is set and we can now * set up the streams pre-mixing buffer. This buffer * contains data that has been resampled to match the * audio device format. */
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -