mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 973408 - Set MediaDecoderReaders idle when they're not decoding. r=kinetik
This commit is contained in:
parent
fbe154216d
commit
5e594c8460
@ -78,16 +78,16 @@ public:
|
|||||||
int64_t aEndTime,
|
int64_t aEndTime,
|
||||||
int64_t aCurrentTime) = 0;
|
int64_t aCurrentTime) = 0;
|
||||||
|
|
||||||
// Called when the decode thread is started, before calling any other
|
// Called to move the reader into idle/active state. When the reader is
|
||||||
// decode, read metadata, or seek functions. Do any thread local setup
|
// created it is assumed to be active (i.e. not idle). When the media
|
||||||
// in this function.
|
// element is paused and we don't need to decode any more data, the state
|
||||||
virtual void OnDecodeThreadStart() {}
|
// machine calls SetIdle() to inform the reader that its decoder won't be
|
||||||
|
// needed for a while. When we need to decode data again, the state machine
|
||||||
// Called when the decode thread is about to finish, after all calls to
|
// calls SetActive() to activate the decoder. The reader can use these
|
||||||
// any other decode, read metadata, or seek functions. Any backend specific
|
// notifications to enter/exit a low power state when the decoder isn't
|
||||||
// thread local tear down must be done in this function. Note that another
|
// needed, if desired. This is most useful on mobile.
|
||||||
// decode thread could start up and run in future.
|
virtual void SetIdle() { }
|
||||||
virtual void OnDecodeThreadFinish() {}
|
virtual void SetActive() { }
|
||||||
|
|
||||||
// Tell the reader that the data decoded are not for direct playback, so it
|
// Tell the reader that the data decoded are not for direct playback, so it
|
||||||
// can accept more files, in particular those which have more channels than
|
// can accept more files, in particular those which have more channels than
|
||||||
|
@ -175,6 +175,7 @@ MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder,
|
|||||||
mAmpleAudioThresholdUsecs(AMPLE_AUDIO_USECS),
|
mAmpleAudioThresholdUsecs(AMPLE_AUDIO_USECS),
|
||||||
mDispatchedAudioDecodeTask(false),
|
mDispatchedAudioDecodeTask(false),
|
||||||
mDispatchedVideoDecodeTask(false),
|
mDispatchedVideoDecodeTask(false),
|
||||||
|
mIsReaderIdle(false),
|
||||||
mAudioCaptured(false),
|
mAudioCaptured(false),
|
||||||
mTransportSeekable(true),
|
mTransportSeekable(true),
|
||||||
mMediaSeekable(true),
|
mMediaSeekable(true),
|
||||||
@ -559,6 +560,7 @@ MediaDecoderStateMachine::DecodeVideo()
|
|||||||
mDispatchedVideoDecodeTask = false;
|
mDispatchedVideoDecodeTask = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
EnsureActive();
|
||||||
|
|
||||||
// We don't want to consider skipping to the next keyframe if we've
|
// We don't want to consider skipping to the next keyframe if we've
|
||||||
// only just started up the decode loop, so wait until we've decoded
|
// only just started up the decode loop, so wait until we've decoded
|
||||||
@ -628,6 +630,8 @@ MediaDecoderStateMachine::DecodeVideo()
|
|||||||
mDispatchedVideoDecodeTask = false;
|
mDispatchedVideoDecodeTask = false;
|
||||||
if (NeedToDecodeVideo()) {
|
if (NeedToDecodeVideo()) {
|
||||||
EnsureVideoDecodeTaskQueued();
|
EnsureVideoDecodeTaskQueued();
|
||||||
|
} else {
|
||||||
|
UpdateIdleState();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -651,6 +655,7 @@ MediaDecoderStateMachine::DecodeAudio()
|
|||||||
mDispatchedAudioDecodeTask = false;
|
mDispatchedAudioDecodeTask = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
EnsureActive();
|
||||||
|
|
||||||
// We don't want to consider skipping to the next keyframe if we've
|
// We don't want to consider skipping to the next keyframe if we've
|
||||||
// only just started up the decode loop, so wait until we've decoded
|
// only just started up the decode loop, so wait until we've decoded
|
||||||
@ -683,6 +688,8 @@ MediaDecoderStateMachine::DecodeAudio()
|
|||||||
mDispatchedAudioDecodeTask = false;
|
mDispatchedAudioDecodeTask = false;
|
||||||
if (NeedToDecodeAudio()) {
|
if (NeedToDecodeAudio()) {
|
||||||
EnsureAudioDecodeTaskQueued();
|
EnsureAudioDecodeTaskQueued();
|
||||||
|
} else {
|
||||||
|
UpdateIdleState();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -702,6 +709,7 @@ MediaDecoderStateMachine::CheckIfDecodeComplete()
|
|||||||
// We've finished decoding all active streams,
|
// We've finished decoding all active streams,
|
||||||
// so move to COMPLETED state.
|
// so move to COMPLETED state.
|
||||||
mState = DECODER_STATE_COMPLETED;
|
mState = DECODER_STATE_COMPLETED;
|
||||||
|
UpdateIdleState();
|
||||||
ScheduleStateMachine();
|
ScheduleStateMachine();
|
||||||
}
|
}
|
||||||
DECODER_LOG(PR_LOG_DEBUG,
|
DECODER_LOG(PR_LOG_DEBUG,
|
||||||
@ -1053,6 +1061,8 @@ void MediaDecoderStateMachine::StopPlayback()
|
|||||||
mDecoder->GetReentrantMonitor().NotifyAll();
|
mDecoder->GetReentrantMonitor().NotifyAll();
|
||||||
NS_ASSERTION(!IsPlaying(), "Should report not playing at end of StopPlayback()");
|
NS_ASSERTION(!IsPlaying(), "Should report not playing at end of StopPlayback()");
|
||||||
mDecoder->UpdateStreamBlockingForStateMachinePlaying();
|
mDecoder->UpdateStreamBlockingForStateMachinePlaying();
|
||||||
|
|
||||||
|
UpdateIdleState();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MediaDecoderStateMachine::SetSyncPointForMediaStream()
|
void MediaDecoderStateMachine::SetSyncPointForMediaStream()
|
||||||
@ -1317,6 +1327,11 @@ void MediaDecoderStateMachine::StartDecoding()
|
|||||||
mIsVideoDecoding = HasVideo() && !mReader->VideoQueue().IsFinished();
|
mIsVideoDecoding = HasVideo() && !mReader->VideoQueue().IsFinished();
|
||||||
mIsAudioDecoding = HasAudio() && !mReader->AudioQueue().IsFinished();
|
mIsAudioDecoding = HasAudio() && !mReader->AudioQueue().IsFinished();
|
||||||
|
|
||||||
|
CheckIfDecodeComplete();
|
||||||
|
if (mState == DECODER_STATE_COMPLETED) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Reset other state to pristine values before starting decode.
|
// Reset other state to pristine values before starting decode.
|
||||||
mSkipToNextKeyFrame = false;
|
mSkipToNextKeyFrame = false;
|
||||||
mIsAudioPrerolling = true;
|
mIsAudioPrerolling = true;
|
||||||
@ -1482,6 +1497,64 @@ MediaDecoderStateMachine::EnqueueDecodeMetadataTask()
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MediaDecoderStateMachine::EnsureActive()
|
||||||
|
{
|
||||||
|
AssertCurrentThreadInMonitor();
|
||||||
|
MOZ_ASSERT(OnDecodeThread());
|
||||||
|
if (!mIsReaderIdle) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mIsReaderIdle = false;
|
||||||
|
SetReaderActive();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MediaDecoderStateMachine::SetReaderIdle()
|
||||||
|
{
|
||||||
|
DECODER_LOG(PR_LOG_DEBUG, ("%p SetReaderIdle()", mDecoder.get()));
|
||||||
|
MOZ_ASSERT(OnDecodeThread());
|
||||||
|
mReader->SetIdle();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MediaDecoderStateMachine::SetReaderActive()
|
||||||
|
{
|
||||||
|
DECODER_LOG(PR_LOG_DEBUG, ("%p SetReaderActive()", mDecoder.get()));
|
||||||
|
MOZ_ASSERT(OnDecodeThread());
|
||||||
|
mReader->SetActive();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MediaDecoderStateMachine::UpdateIdleState()
|
||||||
|
{
|
||||||
|
AssertCurrentThreadInMonitor();
|
||||||
|
|
||||||
|
// If we're in completed state, we should not need to decode anything else.
|
||||||
|
MOZ_ASSERT(mState != DECODER_STATE_COMPLETED ||
|
||||||
|
(!NeedToDecodeAudio() && !NeedToDecodeVideo()));
|
||||||
|
|
||||||
|
bool needIdle = mDecoder->GetState() == MediaDecoder::PLAY_STATE_PAUSED &&
|
||||||
|
!NeedToDecodeAudio() &&
|
||||||
|
!NeedToDecodeVideo() &&
|
||||||
|
!IsPlaying();
|
||||||
|
|
||||||
|
if (mIsReaderIdle == needIdle) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mIsReaderIdle = needIdle;
|
||||||
|
nsRefPtr<nsIRunnable> event;
|
||||||
|
if (mIsReaderIdle) {
|
||||||
|
event = NS_NewRunnableMethod(this, &MediaDecoderStateMachine::SetReaderIdle);
|
||||||
|
} else {
|
||||||
|
event = NS_NewRunnableMethod(this, &MediaDecoderStateMachine::SetReaderActive);
|
||||||
|
}
|
||||||
|
if (NS_FAILED(mDecodeTaskQueue->Dispatch(event)) &&
|
||||||
|
mState != DECODER_STATE_SHUTDOWN) {
|
||||||
|
NS_WARNING("Failed to dispatch event to set decoder idle state");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
MediaDecoderStateMachine::EnqueueDecodeSeekTask()
|
MediaDecoderStateMachine::EnqueueDecodeSeekTask()
|
||||||
{
|
{
|
||||||
@ -1698,6 +1771,7 @@ nsresult MediaDecoderStateMachine::DecodeMetadata()
|
|||||||
if (mState != DECODER_STATE_DECODING_METADATA) {
|
if (mState != DECODER_STATE_DECODING_METADATA) {
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
EnsureActive();
|
||||||
|
|
||||||
nsresult res;
|
nsresult res;
|
||||||
MediaInfo info;
|
MediaInfo info;
|
||||||
@ -1803,6 +1877,7 @@ void MediaDecoderStateMachine::DecodeSeek()
|
|||||||
if (mState != DECODER_STATE_SEEKING) {
|
if (mState != DECODER_STATE_SEEKING) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
EnsureActive();
|
||||||
|
|
||||||
// During the seek, don't have a lock on the decoder state,
|
// During the seek, don't have a lock on the decoder state,
|
||||||
// otherwise long seek operations can block the main thread.
|
// otherwise long seek operations can block the main thread.
|
||||||
@ -1905,7 +1980,12 @@ void MediaDecoderStateMachine::DecodeSeek()
|
|||||||
DECODER_LOG(PR_LOG_DEBUG, ("%p Changed state from SEEKING (to %lld) to COMPLETED",
|
DECODER_LOG(PR_LOG_DEBUG, ("%p Changed state from SEEKING (to %lld) to COMPLETED",
|
||||||
mDecoder.get(), seekTime));
|
mDecoder.get(), seekTime));
|
||||||
stopEvent = NS_NewRunnableMethod(mDecoder, &MediaDecoder::SeekingStoppedAtEnd);
|
stopEvent = NS_NewRunnableMethod(mDecoder, &MediaDecoder::SeekingStoppedAtEnd);
|
||||||
|
// Explicitly set our state so we don't decode further, and so
|
||||||
|
// we report playback ended to the media element.
|
||||||
mState = DECODER_STATE_COMPLETED;
|
mState = DECODER_STATE_COMPLETED;
|
||||||
|
mIsAudioDecoding = false;
|
||||||
|
mIsVideoDecoding = false;
|
||||||
|
UpdateIdleState();
|
||||||
} else {
|
} else {
|
||||||
DECODER_LOG(PR_LOG_DEBUG, ("%p Changed state from SEEKING (to %lld) to DECODING",
|
DECODER_LOG(PR_LOG_DEBUG, ("%p Changed state from SEEKING (to %lld) to DECODING",
|
||||||
mDecoder.get(), seekTime));
|
mDecoder.get(), seekTime));
|
||||||
@ -2508,11 +2588,11 @@ void MediaDecoderStateMachine::StartBuffering()
|
|||||||
mDecoder.get(), decodeDuration.ToSeconds()));
|
mDecoder.get(), decodeDuration.ToSeconds()));
|
||||||
#ifdef PR_LOGGING
|
#ifdef PR_LOGGING
|
||||||
MediaDecoder::Statistics stats = mDecoder->GetStatistics();
|
MediaDecoder::Statistics stats = mDecoder->GetStatistics();
|
||||||
#endif
|
|
||||||
DECODER_LOG(PR_LOG_DEBUG, ("%p Playback rate: %.1lfKB/s%s download rate: %.1lfKB/s%s",
|
DECODER_LOG(PR_LOG_DEBUG, ("%p Playback rate: %.1lfKB/s%s download rate: %.1lfKB/s%s",
|
||||||
mDecoder.get(),
|
mDecoder.get(),
|
||||||
stats.mPlaybackRate/1024, stats.mPlaybackRateReliable ? "" : " (unreliable)",
|
stats.mPlaybackRate/1024, stats.mPlaybackRateReliable ? "" : " (unreliable)",
|
||||||
stats.mDownloadRate/1024, stats.mDownloadRateReliable ? "" : " (unreliable)"));
|
stats.mDownloadRate/1024, stats.mDownloadRateReliable ? "" : " (unreliable)"));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult MediaDecoderStateMachine::GetBuffered(dom::TimeRanges* aBuffered) {
|
nsresult MediaDecoderStateMachine::GetBuffered(dom::TimeRanges* aBuffered) {
|
||||||
|
@ -564,6 +564,22 @@ private:
|
|||||||
// The decoder monitor must be held.
|
// The decoder monitor must be held.
|
||||||
nsresult EnqueueDecodeSeekTask();
|
nsresult EnqueueDecodeSeekTask();
|
||||||
|
|
||||||
|
// Calls the reader's SetIdle(), with aIsIdle as parameter. This is only
|
||||||
|
// called in a task dispatched to the decode task queue, don't call it
|
||||||
|
// directly.
|
||||||
|
void SetReaderIdle();
|
||||||
|
void SetReaderActive();
|
||||||
|
|
||||||
|
// Re-evaluates the state and determines whether we should set the reader
|
||||||
|
// to idle mode. This is threadsafe, and can be called from any thread.
|
||||||
|
// The decoder monitor must be held.
|
||||||
|
void UpdateIdleState();
|
||||||
|
|
||||||
|
// Called before we do anything on the decode task queue to set the reader
|
||||||
|
// as not idle if it was idle. This is called before we decode, seek, or
|
||||||
|
// decode metadata (in case we were dormant or awaiting resources).
|
||||||
|
void EnsureActive();
|
||||||
|
|
||||||
// Queries our state to see whether the decode has finished for all streams.
|
// Queries our state to see whether the decode has finished for all streams.
|
||||||
// If so, we move into DECODER_STATE_COMPLETED and schedule the state machine
|
// If so, we move into DECODER_STATE_COMPLETED and schedule the state machine
|
||||||
// to run.
|
// to run.
|
||||||
@ -831,6 +847,12 @@ private:
|
|||||||
// the video decode.
|
// the video decode.
|
||||||
bool mDispatchedVideoDecodeTask;
|
bool mDispatchedVideoDecodeTask;
|
||||||
|
|
||||||
|
// True when the reader is initialized, but has been ordered "idle" by the
|
||||||
|
// state machine. This happens when the MediaQueue's of decoded data are
|
||||||
|
// "full" and playback is paused. The reader may choose to use the idle
|
||||||
|
// notification to enter a low power state.
|
||||||
|
bool mIsReaderIdle;
|
||||||
|
|
||||||
// If the video decode is falling behind the audio, we'll start dropping the
|
// If the video decode is falling behind the audio, we'll start dropping the
|
||||||
// inter-frames up until the next keyframe which is at or before the current
|
// inter-frames up until the next keyframe which is at or before the current
|
||||||
// playback position. skipToNextKeyframe is true if we're currently
|
// playback position. skipToNextKeyframe is true if we're currently
|
||||||
|
@ -393,21 +393,6 @@ DirectShowReader::Seek(int64_t aTargetUs,
|
|||||||
return DecodeToTarget(aTargetUs);
|
return DecodeToTarget(aTargetUs);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
DirectShowReader::OnDecodeThreadStart()
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(mDecoder->OnDecodeThread(), "Should be on decode thread.");
|
|
||||||
HRESULT hr = CoInitializeEx(0, COINIT_MULTITHREADED);
|
|
||||||
NS_ENSURE_TRUE_VOID(SUCCEEDED(hr));
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
DirectShowReader::OnDecodeThreadFinish()
|
|
||||||
{
|
|
||||||
NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
|
|
||||||
CoUninitialize();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
DirectShowReader::NotifyDataArrived(const char* aBuffer, uint32_t aLength, int64_t aOffset)
|
DirectShowReader::NotifyDataArrived(const char* aBuffer, uint32_t aLength, int64_t aOffset)
|
||||||
{
|
{
|
||||||
|
@ -65,9 +65,6 @@ public:
|
|||||||
int64_t aEndTime,
|
int64_t aEndTime,
|
||||||
int64_t aCurrentTime) MOZ_OVERRIDE;
|
int64_t aCurrentTime) MOZ_OVERRIDE;
|
||||||
|
|
||||||
void OnDecodeThreadStart() MOZ_OVERRIDE;
|
|
||||||
void OnDecodeThreadFinish() MOZ_OVERRIDE;
|
|
||||||
|
|
||||||
void NotifyDataArrived(const char* aBuffer,
|
void NotifyDataArrived(const char* aBuffer,
|
||||||
uint32_t aLength,
|
uint32_t aLength,
|
||||||
int64_t aOffset) MOZ_OVERRIDE;
|
int64_t aOffset) MOZ_OVERRIDE;
|
||||||
|
@ -361,17 +361,19 @@ static uint64_t BytesToTime(int64_t offset, uint64_t length, uint64_t durationUs
|
|||||||
return uint64_t(double(durationUs) * perc);
|
return uint64_t(double(durationUs) * perc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MediaOmxReader::OnDecodeThreadFinish() {
|
void MediaOmxReader::SetIdle() {
|
||||||
if (mOmxDecoder.get()) {
|
if (!mOmxDecoder.get()) {
|
||||||
mOmxDecoder->Pause();
|
return;
|
||||||
}
|
}
|
||||||
|
mOmxDecoder->Pause();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MediaOmxReader::OnDecodeThreadStart() {
|
void MediaOmxReader::SetActive() {
|
||||||
if (mOmxDecoder.get()) {
|
if (!mOmxDecoder.get()) {
|
||||||
DebugOnly<nsresult> result = mOmxDecoder->Play();
|
return;
|
||||||
NS_ASSERTION(result == NS_OK, "OmxDecoder should be in play state to continue decoding");
|
|
||||||
}
|
}
|
||||||
|
DebugOnly<nsresult> result = mOmxDecoder->Play();
|
||||||
|
NS_ASSERTION(result == NS_OK, "OmxDecoder should be in play state to continue decoding");
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
@ -79,9 +79,9 @@ public:
|
|||||||
MetadataTags** aTags);
|
MetadataTags** aTags);
|
||||||
virtual nsresult Seek(int64_t aTime, int64_t aStartTime, int64_t aEndTime, int64_t aCurrentTime);
|
virtual nsresult Seek(int64_t aTime, int64_t aStartTime, int64_t aEndTime, int64_t aCurrentTime);
|
||||||
|
|
||||||
virtual void OnDecodeThreadStart() MOZ_OVERRIDE;
|
virtual void SetIdle() MOZ_OVERRIDE;
|
||||||
|
virtual void SetActive() MOZ_OVERRIDE;
|
||||||
|
|
||||||
virtual void OnDecodeThreadFinish() MOZ_OVERRIDE;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
@ -299,37 +299,8 @@ nsresult RtspOmxReader::Seek(int64_t aTime, int64_t aStartTime,
|
|||||||
return MediaOmxReader::Seek(aTime, aStartTime, aEndTime, aCurrentTime);
|
return MediaOmxReader::Seek(aTime, aStartTime, aEndTime, aCurrentTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RtspOmxReader::OnDecodeThreadStart() {
|
void RtspOmxReader::SetIdle() {
|
||||||
// Start RTSP streaming right after starting the decoding thread in
|
// Need to pause RTSP streaming OMXCodec decoding.
|
||||||
// MediaDecoderStateMachine and before starting OMXCodec decoding.
|
|
||||||
if (mRtspResource) {
|
|
||||||
nsIStreamingProtocolController* controller =
|
|
||||||
mRtspResource->GetMediaStreamController();
|
|
||||||
if (controller) {
|
|
||||||
controller->Play();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Call parent class to start OMXCodec decoding.
|
|
||||||
MediaOmxReader::OnDecodeThreadStart();
|
|
||||||
}
|
|
||||||
|
|
||||||
void RtspOmxReader::OnDecodeThreadFinish() {
|
|
||||||
// Call parent class to pause OMXCodec decoding.
|
|
||||||
MediaOmxReader::OnDecodeThreadFinish();
|
|
||||||
|
|
||||||
// Stop RTSP streaming right before destroying the decoding thread in
|
|
||||||
// MediaDecoderStateMachine and after pausing OMXCodec decoding.
|
|
||||||
// RTSP streaming should not be paused until OMXCodec has been paused and
|
|
||||||
// until the decoding thread in MediaDecoderStateMachine is about to be
|
|
||||||
// destroyed. Otherwise, RtspMediaSource::read() would block the binder
|
|
||||||
// thread of OMXCodecObserver::onMessage() --> OMXCodec::on_message() -->
|
|
||||||
// OMXCodec::drainInputBuffer() due to network data starvation. Because
|
|
||||||
// OMXCodec::mLock is held by the binder thread in this case, all other
|
|
||||||
// threads would be blocked when they try to lock this mutex. As a result, the
|
|
||||||
// decoding thread in MediaDecoderStateMachine would be blocked forever in
|
|
||||||
// OMXCodec::read() if there is no enough data for RtspMediaSource::read() to
|
|
||||||
// return.
|
|
||||||
if (mRtspResource) {
|
if (mRtspResource) {
|
||||||
nsIStreamingProtocolController* controller =
|
nsIStreamingProtocolController* controller =
|
||||||
mRtspResource->GetMediaStreamController();
|
mRtspResource->GetMediaStreamController();
|
||||||
@ -337,6 +308,23 @@ void RtspOmxReader::OnDecodeThreadFinish() {
|
|||||||
controller->Pause();
|
controller->Pause();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Call parent class to set OMXCodec idle.
|
||||||
|
MediaOmxReader::SetIdle();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RtspOmxReader::SetActive() {
|
||||||
|
// Need to start RTSP streaming OMXCodec decoding.
|
||||||
|
if (mRtspResource) {
|
||||||
|
nsIStreamingProtocolController* controller =
|
||||||
|
mRtspResource->GetMediaStreamController();
|
||||||
|
if (controller) {
|
||||||
|
controller->Play();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call parent class to set OMXCodec active.
|
||||||
|
MediaOmxReader::SetActive();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
@ -71,9 +71,8 @@ public:
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void OnDecodeThreadStart() MOZ_OVERRIDE;
|
virtual void SetIdle() MOZ_OVERRIDE;
|
||||||
|
virtual void SetActive() MOZ_OVERRIDE;
|
||||||
virtual void OnDecodeThreadFinish() MOZ_OVERRIDE;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// A pointer to RtspMediaResource for calling the Rtsp specific function.
|
// A pointer to RtspMediaResource for calling the Rtsp specific function.
|
||||||
|
@ -269,8 +269,6 @@ MediaDecodeTask::Decode()
|
|||||||
// bakend support.
|
// bakend support.
|
||||||
mDecoderReader->SetIgnoreAudioOutputFormat();
|
mDecoderReader->SetIgnoreAudioOutputFormat();
|
||||||
|
|
||||||
mDecoderReader->OnDecodeThreadStart();
|
|
||||||
|
|
||||||
MediaInfo mediaInfo;
|
MediaInfo mediaInfo;
|
||||||
nsAutoPtr<MetadataTags> tags;
|
nsAutoPtr<MetadataTags> tags;
|
||||||
nsresult rv = mDecoderReader->ReadMetadata(&mediaInfo, getter_Transfers(tags));
|
nsresult rv = mDecoderReader->ReadMetadata(&mediaInfo, getter_Transfers(tags));
|
||||||
@ -289,8 +287,6 @@ MediaDecodeTask::Decode()
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
mDecoderReader->OnDecodeThreadFinish();
|
|
||||||
|
|
||||||
MediaQueue<AudioData>& audioQueue = mDecoderReader->AudioQueue();
|
MediaQueue<AudioData>& audioQueue = mDecoderReader->AudioQueue();
|
||||||
uint32_t frameCount = audioQueue.FrameCount();
|
uint32_t frameCount = audioQueue.FrameCount();
|
||||||
uint32_t channelCount = mediaInfo.mAudio.mChannels;
|
uint32_t channelCount = mediaInfo.mAudio.mChannels;
|
||||||
|
@ -80,28 +80,6 @@ WMFReader::~WMFReader()
|
|||||||
MOZ_COUNT_DTOR(WMFReader);
|
MOZ_COUNT_DTOR(WMFReader);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
WMFReader::OnDecodeThreadStart()
|
|
||||||
{
|
|
||||||
NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
|
|
||||||
|
|
||||||
// XXX WebAudio will call this on the main thread so CoInit will definitely
|
|
||||||
// fail. You cannot change the concurrency model once already set.
|
|
||||||
// The main thread will continue to be STA, which seems to work, but MSDN
|
|
||||||
// recommends that MTA be used.
|
|
||||||
mCOMInitialized = SUCCEEDED(CoInitializeEx(0, COINIT_MULTITHREADED));
|
|
||||||
NS_ENSURE_TRUE_VOID(mCOMInitialized);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
WMFReader::OnDecodeThreadFinish()
|
|
||||||
{
|
|
||||||
NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
|
|
||||||
if (mCOMInitialized) {
|
|
||||||
CoUninitialize();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
WMFReader::InitializeDXVA()
|
WMFReader::InitializeDXVA()
|
||||||
{
|
{
|
||||||
|
@ -47,10 +47,6 @@ public:
|
|||||||
int64_t aStartTime,
|
int64_t aStartTime,
|
||||||
int64_t aEndTime,
|
int64_t aEndTime,
|
||||||
int64_t aCurrentTime) MOZ_OVERRIDE;
|
int64_t aCurrentTime) MOZ_OVERRIDE;
|
||||||
|
|
||||||
void OnDecodeThreadStart() MOZ_OVERRIDE;
|
|
||||||
void OnDecodeThreadFinish() MOZ_OVERRIDE;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
HRESULT ConfigureAudioDecoder();
|
HRESULT ConfigureAudioDecoder();
|
||||||
|
Loading…
Reference in New Issue
Block a user