Bug 1336367 - Move AudioTrackEncoder Segment init logic into new method. r?pehrsons
The AudioTrackEncoder has logic to attempt to init when given an AudioSegment.
This logic has previously been part of NotifyQueuedTrackChanges. This
changeset moves the logic to its own method. This allows for finer testing of
the init attempt behaviour.
MozReview-Commit-ID: Der1iM9J8fr
--- a/dom/media/encoder/TrackEncoder.cpp
+++ b/dom/media/encoder/TrackEncoder.cpp
@@ -40,74 +40,89 @@ TrackEncoder::TrackEncoder()
void TrackEncoder::NotifyEvent(MediaStreamGraph* aGraph,
MediaStreamGraphEvent event)
{
if (event == MediaStreamGraphEvent::EVENT_REMOVED) {
NotifyEndOfStream();
}
}
+nsresult
+AudioTrackEncoder::TryInit(const AudioSegment& aSegment, int aSamplingRate)
+{
+ ReentrantMonitorAutoEnter mon(mReentrantMonitor);
+
+ if (mInitialized) {
+ return NS_OK;
+ }
+
+ mInitCounter++;
+ TRACK_LOG(LogLevel::Debug, ("Init the audio encoder %d times", mInitCounter));
+ AudioSegment::ConstChunkIterator iter(aSegment);
+ while (!iter.IsEnded()) {
+ AudioChunk chunk = *iter;
+
+ // The number of channels is determined by the first non-null chunk, and
+ // thus the audio encoder is initialized at this time.
+ if (!chunk.IsNull()) {
+ nsresult rv = Init(chunk.mChannelData.Length(), aSamplingRate);
+ if (NS_FAILED(rv)) {
+ TRACK_LOG(LogLevel::Error,
+ ("[AudioTrackEncoder]: Fail to initialize the encoder!"));
+ NotifyCancel();
+ return rv;
+ }
+ break;
+ }
+
+ iter.Next();
+ }
+
+ mNotInitDuration += aSegment.GetDuration();
+ if (!mInitialized &&
+ (mNotInitDuration / aSamplingRate >= AUDIO_INIT_FAILED_DURATION) &&
+ mInitCounter > 1) {
+ // Perform a best effort initialization since we haven't gotten any
+ // data yet. Motivated by issues like Bug 1336367
+ TRACK_LOG(LogLevel::Warning,
+ ("[AudioTrackEncoder]: Initialize failed "
+ "for %ds. Attempting to init with %d "
+ "(default) channels!",
+ AUDIO_INIT_FAILED_DURATION,
+ DEFAULT_CHANNELS));
+ nsresult rv = Init(DEFAULT_CHANNELS, aSamplingRate);
+ if (NS_FAILED(rv)) {
+ TRACK_LOG(LogLevel::Error,
+ ("[AudioTrackEncoder]: Fail to initialize the encoder!"));
+ NotifyCancel();
+ return rv;
+ }
+ }
+
+ return NS_OK;
+}
+
void
AudioTrackEncoder::NotifyQueuedTrackChanges(MediaStreamGraph* aGraph,
TrackID aID,
StreamTime aTrackOffset,
uint32_t aTrackEvents,
const MediaSegment& aQueuedMedia)
{
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
if (mCanceled) {
return;
}
const AudioSegment& audio = static_cast<const AudioSegment&>(aQueuedMedia);
- // Check and initialize parameters for codec encoder.
- if (!mInitialized) {
- mInitCounter++;
- TRACK_LOG(LogLevel::Debug, ("Init the audio encoder %d times", mInitCounter));
- AudioSegment::ChunkIterator iter(const_cast<AudioSegment&>(audio));
- while (!iter.IsEnded()) {
- AudioChunk chunk = *iter;
-
- // The number of channels is determined by the first non-null chunk, and
- // thus the audio encoder is initialized at this time.
- if (!chunk.IsNull()) {
- nsresult rv = Init(chunk.mChannelData.Length(), aGraph->GraphRate());
- if (NS_FAILED(rv)) {
- TRACK_LOG(LogLevel::Error, ("[AudioTrackEncoder]: Fail to initialize the encoder!"));
- NotifyCancel();
- }
- break;
- }
-
- iter.Next();
- }
-
- mNotInitDuration += aQueuedMedia.GetDuration();
- if (!mInitialized &&
- (mNotInitDuration / aGraph->GraphRate() >=
- AUDIO_INIT_FAILED_DURATION) &&
- mInitCounter > 1) {
- // Perform a best effort initialization since we haven't gotten any
- // data yet. Motivated by issues like Bug 1336367
- TRACK_LOG(LogLevel::Warning,
- ("[AudioTrackEncoder]: Initialize failed "
- "for %ds. Attempting to init with %d "
- "(default) channels!",
- AUDIO_INIT_FAILED_DURATION,
- DEFAULT_CHANNELS));
- nsresult rv = Init(DEFAULT_CHANNELS, aGraph->GraphRate());
- if (NS_FAILED(rv)) {
- TRACK_LOG(LogLevel::Error,
- ("[AudioTrackEncoder]: Fail to initialize the encoder!"));
- NotifyCancel();
- return;
- }
- }
+ nsresult rv = TryInit(audio, aGraph->GraphRate());
+ if (NS_FAILED(rv)) {
+ return;
}
// Append and consume this raw segment.
AppendAudioSegment(audio);
// The stream has stopped and reached the end of track.
if (aTrackEvents == TrackEventCommand::TRACK_EVENT_ENDED) {
--- a/dom/media/encoder/TrackEncoder.h
+++ b/dom/media/encoder/TrackEncoder.h
@@ -197,16 +197,31 @@ protected:
/**
* Number of samples per channel in a pcm buffer. This is also the value of
* frame size required by audio encoder, and mReentrantMonitor will be
* notified when at least this much data has been added to mRawSegment.
*/
virtual int GetPacketDuration() { return 0; }
/**
+ * Attempt to initialize the audio encoder. The call of this method is
+ * delayed until we have received the first valid track from
+ * MediaStreamGraph, and the mReentrantMonitor will be notified if other
+ * methods is waiting for encoder to be completely initialized. This method
+ * is called on the MediaStreamGraph thread. This method will attempt to
+ * initialize with best effort if all the following are met:
+ * - it has been called multiple times
+ * - reached a threshold duration of audio data
+ * - the encoder has not yet initialized.
+ * Returns NS_OK on init, as well as when deferring for more data, so check
+ * mInitialized after calling as necessary.
+ */
+ virtual nsresult TryInit(const AudioSegment& aSegment, int aSamplingRate);
+
+ /**
* Initializes the audio encoder. The call of this method is delayed until we
* have received the first valid track from MediaStreamGraph, and the
* mReentrantMonitor will be notified if other methods is waiting for encoder
* to be completely initialized. This method is called on the MediaStreamGraph
* thread.
*/
virtual nsresult Init(int aChannels, int aSamplingRate) = 0;