NS_IMETHODIMP MediaEngineDefaultAudioSource::Notify(nsITimer* aTimer) { TimeStamp now = TimeStamp::Now(); TimeDuration timeSinceLastNotify = now - mLastNotify; mLastNotify = now; TrackTicks samplesSinceLastNotify = RateConvertTicksRoundUp(AUDIO_RATE, 1000000, timeSinceLastNotify.ToMicroseconds()); // If it's been longer since the last Notify() than mBufferSize holds, we // have underrun and the MSG had to append silence while waiting for us // to push more data. In this case we reset to mBufferSize again. TrackTicks samplesToAppend = std::min(samplesSinceLastNotify, mBufferSize); AudioSegment segment; AppendToSegment(segment, samplesToAppend); mSource->AppendToTrack(mTrackID, &segment); // Generate null data for fake tracks. if (mHasFakeTracks) { for (int i = 0; i < kFakeAudioTrackCount; ++i) { AudioSegment nullSegment; nullSegment.AppendNullData(samplesToAppend); mSource->AppendToTrack(kTrackCount + kFakeVideoTrackCount+i, &nullSegment); } } return NS_OK; }
nsresult MediaEngineDefaultAudioSource::Start(SourceMediaStream* aStream, TrackID aID, const PrincipalHandle& aPrincipalHandle) { if (mState != kAllocated) { return NS_ERROR_FAILURE; } mTimer = do_CreateInstance(NS_TIMER_CONTRACTID); if (!mTimer) { return NS_ERROR_FAILURE; } mSource = aStream; // We try to keep the appended data at this size. // Make it two timer intervals to try to avoid underruns. mBufferSize = 2 * (AUDIO_RATE * DEFAULT_AUDIO_TIMER_MS) / 1000; // AddTrack will take ownership of segment AudioSegment* segment = new AudioSegment(); AppendToSegment(*segment, mBufferSize); mSource->AddAudioTrack(aID, AUDIO_RATE, 0, segment, SourceMediaStream::ADDTRACK_QUEUED); if (mHasFakeTracks) { for (int i = 0; i < kFakeAudioTrackCount; ++i) { segment = new AudioSegment(); segment->AppendNullData(mBufferSize); mSource->AddAudioTrack(kTrackCount + kFakeVideoTrackCount+i, AUDIO_RATE, 0, segment, SourceMediaStream::ADDTRACK_QUEUED); } } // Remember TrackID so we can finish later mTrackID = aID; // Remember PrincipalHandle since we don't append in NotifyPull. mPrincipalHandle = aPrincipalHandle; mLastNotify = TimeStamp::Now(); // 1 Audio frame per 10ms #if defined(MOZ_WIDGET_GONK) && defined(DEBUG) // B2G emulator debug is very, very slow and has problems dealing with realtime audio inputs mTimer->InitWithCallback(this, DEFAULT_AUDIO_TIMER_MS*10, nsITimer::TYPE_REPEATING_PRECISE_CAN_SKIP); #else mTimer->InitWithCallback(this, DEFAULT_AUDIO_TIMER_MS, nsITimer::TYPE_REPEATING_PRECISE_CAN_SKIP); #endif mState = kStarted; return NS_OK; }
void MediaEngineDefaultAudioSource::NotifyPull(MediaStreamGraph* aGraph, SourceMediaStream *aSource, TrackID aID, StreamTime aDesiredTime, const PrincipalHandle& aPrincipalHandle) { MOZ_ASSERT(aID == mTrackID); AudioSegment segment; // avoid accumulating rounding errors TrackTicks desired = aSource->TimeToTicksRoundUp(AUDIO_RATE, aDesiredTime); TrackTicks delta = desired - mLastNotify; mLastNotify += delta; AppendToSegment(segment, delta, aPrincipalHandle); aSource->AppendToTrack(mTrackID, &segment); }