зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1168778 - Fix crash when seeking: 1. Replace FlushableMediaTaskQueue by MediaTaskQueue. 2. Refact the seek/DecodeAudioDataTask/DecodeVideoFrameTask functions. r=sotaro
--HG-- extra : rebase_source : be194c694dffd08c7b24789900cc4a6fa45acfeb
This commit is contained in:
Родитель
c384cc4424
Коммит
0378f2c94e
|
@ -396,9 +396,6 @@ MediaCodecReader::DecodeAudioDataSync()
|
|||
} else if (status == -EAGAIN) {
|
||||
if (TimeStamp::Now() > timeout) {
|
||||
// Don't let this loop run for too long. Try it again later.
|
||||
if (CheckAudioResources()) {
|
||||
DispatchAudioTask();
|
||||
}
|
||||
return;
|
||||
}
|
||||
continue; // Try it again now.
|
||||
|
@ -441,11 +438,22 @@ MediaCodecReader::DecodeAudioDataSync()
|
|||
void
|
||||
MediaCodecReader::DecodeAudioDataTask()
|
||||
{
|
||||
if (AudioQueue().GetSize() == 0 && !AudioQueue().IsFinished()) {
|
||||
DecodeAudioDataSync();
|
||||
}
|
||||
MOZ_ASSERT(mAudioTrack.mTaskQueue->IsCurrentThreadIn());
|
||||
MonitorAutoLock al(mAudioTrack.mTrackMonitor);
|
||||
if (mAudioTrack.mAudioPromise.IsEmpty()) {
|
||||
// Clear the data in queue because the promise might be canceled by
|
||||
// ResetDecode().
|
||||
AudioQueue().Reset();
|
||||
return;
|
||||
}
|
||||
if (AudioQueue().GetSize() == 0 && !AudioQueue().IsFinished()) {
|
||||
MonitorAutoUnlock ul(mAudioTrack.mTrackMonitor);
|
||||
DecodeAudioDataSync();
|
||||
}
|
||||
// Since we unlock the monitor above, we should check the promise again
|
||||
// because the promise might be canceled by ResetDecode().
|
||||
if (mAudioTrack.mAudioPromise.IsEmpty()) {
|
||||
AudioQueue().Reset();
|
||||
return;
|
||||
}
|
||||
if (AudioQueue().GetSize() > 0) {
|
||||
|
@ -467,9 +475,22 @@ MediaCodecReader::DecodeAudioDataTask()
|
|||
void
|
||||
MediaCodecReader::DecodeVideoFrameTask(int64_t aTimeThreshold)
|
||||
{
|
||||
DecodeVideoFrameSync(aTimeThreshold);
|
||||
MOZ_ASSERT(mVideoTrack.mTaskQueue->IsCurrentThreadIn());
|
||||
MonitorAutoLock al(mVideoTrack.mTrackMonitor);
|
||||
if (mVideoTrack.mVideoPromise.IsEmpty()) {
|
||||
// Clear the data in queue because the promise might be canceled by
|
||||
// ResetDecode().
|
||||
VideoQueue().Reset();
|
||||
return;
|
||||
}
|
||||
{
|
||||
MonitorAutoUnlock ul(mVideoTrack.mTrackMonitor);
|
||||
DecodeVideoFrameSync(aTimeThreshold);
|
||||
}
|
||||
// Since we unlock the monitor above, we should check the promise again
|
||||
// because the promise might be canceled by ResetDecode().
|
||||
if (mVideoTrack.mVideoPromise.IsEmpty()) {
|
||||
VideoQueue().Reset();
|
||||
return;
|
||||
}
|
||||
if (VideoQueue().GetSize() > 0) {
|
||||
|
@ -740,7 +761,6 @@ nsresult
|
|||
MediaCodecReader::ResetDecode()
|
||||
{
|
||||
if (CheckAudioResources()) {
|
||||
mAudioTrack.mTaskQueue->Flush();
|
||||
MonitorAutoLock al(mAudioTrack.mTrackMonitor);
|
||||
if (!mAudioTrack.mAudioPromise.IsEmpty()) {
|
||||
mAudioTrack.mAudioPromise.Reject(CANCELED, __func__);
|
||||
|
@ -749,7 +769,6 @@ MediaCodecReader::ResetDecode()
|
|||
mAudioTrack.mDiscontinuity = true;
|
||||
}
|
||||
if (CheckVideoResources()) {
|
||||
mVideoTrack.mTaskQueue->Flush();
|
||||
MonitorAutoLock al(mVideoTrack.mTrackMonitor);
|
||||
if (!mVideoTrack.mVideoPromise.IsEmpty()) {
|
||||
mVideoTrack.mVideoPromise.Reject(CANCELED, __func__);
|
||||
|
@ -893,9 +912,6 @@ MediaCodecReader::DecodeVideoFrameSync(int64_t aTimeThreshold)
|
|||
} else if (status == -EAGAIN) {
|
||||
if (TimeStamp::Now() > timeout) {
|
||||
// Don't let this loop run for too long. Try it again later.
|
||||
if (CheckVideoResources()) {
|
||||
DispatchVideoTask(aTimeThreshold);
|
||||
}
|
||||
return;
|
||||
}
|
||||
continue; // Try it again now.
|
||||
|
@ -1027,16 +1043,15 @@ MediaCodecReader::Seek(int64_t aTime, int64_t aEndTime)
|
|||
{
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
|
||||
mVideoTrack.mSeekTimeUs = aTime;
|
||||
mAudioTrack.mSeekTimeUs = aTime;
|
||||
mVideoTrack.mInputEndOfStream = false;
|
||||
mVideoTrack.mOutputEndOfStream = false;
|
||||
mAudioTrack.mInputEndOfStream = false;
|
||||
mAudioTrack.mOutputEndOfStream = false;
|
||||
mAudioTrack.mFlushed = false;
|
||||
mVideoTrack.mFlushed = false;
|
||||
int64_t timestamp = sInvalidTimestampUs;
|
||||
|
||||
if (CheckVideoResources()) {
|
||||
MonitorAutoLock al(mVideoTrack.mTrackMonitor);
|
||||
mVideoTrack.mSeekTimeUs = aTime;
|
||||
mVideoTrack.mInputEndOfStream = false;
|
||||
mVideoTrack.mOutputEndOfStream = false;
|
||||
mVideoTrack.mFlushed = false;
|
||||
|
||||
VideoFrameContainer* videoframe = mDecoder->GetVideoFrameContainer();
|
||||
if (videoframe) {
|
||||
layers::ImageContainer* image = videoframe->GetImageContainer();
|
||||
|
@ -1047,7 +1062,6 @@ MediaCodecReader::Seek(int64_t aTime, int64_t aEndTime)
|
|||
|
||||
MediaBuffer* source_buffer = nullptr;
|
||||
MediaSource::ReadOptions options;
|
||||
int64_t timestamp = sInvalidTimestampUs;
|
||||
options.setSeekTo(aTime, MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC);
|
||||
if (mVideoTrack.mSource->read(&source_buffer, &options) != OK ||
|
||||
source_buffer == nullptr) {
|
||||
|
@ -1058,12 +1072,25 @@ MediaCodecReader::Seek(int64_t aTime, int64_t aEndTime)
|
|||
if (format->findInt64(kKeyTime, ×tamp) &&
|
||||
IsValidTimestampUs(timestamp)) {
|
||||
mVideoTrack.mSeekTimeUs = timestamp;
|
||||
mAudioTrack.mSeekTimeUs = timestamp;
|
||||
}
|
||||
format = nullptr;
|
||||
}
|
||||
source_buffer->release();
|
||||
}
|
||||
|
||||
{
|
||||
MonitorAutoLock al(mAudioTrack.mTrackMonitor);
|
||||
mAudioTrack.mInputEndOfStream = false;
|
||||
mAudioTrack.mOutputEndOfStream = false;
|
||||
mAudioTrack.mFlushed = false;
|
||||
|
||||
if (IsValidTimestampUs(timestamp)) {
|
||||
mAudioTrack.mSeekTimeUs = timestamp;
|
||||
} else {
|
||||
mAudioTrack.mSeekTimeUs = aTime;
|
||||
}
|
||||
}
|
||||
|
||||
return SeekPromise::CreateAndResolve(aTime, __func__);
|
||||
}
|
||||
|
||||
|
@ -1284,11 +1311,11 @@ bool
|
|||
MediaCodecReader::CreateTaskQueues()
|
||||
{
|
||||
if (mAudioTrack.mSource != nullptr && !mAudioTrack.mTaskQueue) {
|
||||
mAudioTrack.mTaskQueue = CreateFlushableMediaDecodeTaskQueue();
|
||||
mAudioTrack.mTaskQueue = CreateMediaDecodeTaskQueue();
|
||||
NS_ENSURE_TRUE(mAudioTrack.mTaskQueue, false);
|
||||
}
|
||||
if (mVideoTrack.mSource != nullptr && !mVideoTrack.mTaskQueue) {
|
||||
mVideoTrack.mTaskQueue = CreateFlushableMediaDecodeTaskQueue();
|
||||
mVideoTrack.mTaskQueue = CreateMediaDecodeTaskQueue();
|
||||
NS_ENSURE_TRUE(mVideoTrack.mTaskQueue, false);
|
||||
mVideoTrack.mReleaseBufferTaskQueue = CreateMediaDecodeTaskQueue();
|
||||
NS_ENSURE_TRUE(mVideoTrack.mReleaseBufferTaskQueue, false);
|
||||
|
|
|
@ -148,15 +148,13 @@ protected:
|
|||
|
||||
// playback parameters
|
||||
CheckedUint32 mInputIndex;
|
||||
// mDiscontinuity, mFlushed, mInputEndOfStream, mInputEndOfStream,
|
||||
// mSeekTimeUs don't be protected by a lock because the
|
||||
// mTaskQueue->Flush() will flush all tasks.
|
||||
|
||||
bool mInputEndOfStream;
|
||||
bool mOutputEndOfStream;
|
||||
int64_t mSeekTimeUs;
|
||||
bool mFlushed; // meaningless when mSeekTimeUs is invalid.
|
||||
bool mDiscontinuity;
|
||||
nsRefPtr<FlushableMediaTaskQueue> mTaskQueue;
|
||||
nsRefPtr<MediaTaskQueue> mTaskQueue;
|
||||
Monitor mTrackMonitor;
|
||||
|
||||
private:
|
||||
|
|
Загрузка…
Ссылка в новой задаче