Bug 1309516 part 1 - retrieve start time before resolving the metadata promise; r=jya

MozReview-Commit-ID: FhnoFi1BSHM

--HG--
extra : rebase_source : 3c1a1efa936fa0f4decdfb12c90bcce607c5edba
This commit is contained in:
Kaku Kuo 2016-10-27 15:21:05 +08:00
parent 42a1f53991
commit 5bc83d3772
3 changed files with 119 additions and 14 deletions

View File

@ -732,10 +732,50 @@ MediaFormatReader::OnDemuxerInitDone(nsresult)
return;
}
mTags = Move(tags);
mInitDone = true;
// Try to get the start time.
// For MSE case, the start time of each track is assumed to be 0.
// For others, we must demux the first sample to know the start time for each
// track.
if (ForceZeroStartTime()) {
mAudio.mFirstDemuxedSampleTime.emplace(TimeUnit::FromMicroseconds(0));
mVideo.mFirstDemuxedSampleTime.emplace(TimeUnit::FromMicroseconds(0));
} else {
if (HasAudio()) {
RequestDemuxSamples(TrackInfo::kAudioTrack);
}
if (HasVideo()) {
RequestDemuxSamples(TrackInfo::kVideoTrack);
}
}
MaybeResolveMetadataPromise();
}
void
MediaFormatReader::MaybeResolveMetadataPromise()
{
MOZ_ASSERT(OnTaskQueue());
if ((HasAudio() && mAudio.mFirstDemuxedSampleTime.isNothing()) ||
(HasVideo() && mVideo.mFirstDemuxedSampleTime.isNothing())) {
return;
}
TimeUnit startTime =
std::min(mAudio.mFirstDemuxedSampleTime.refOr(TimeUnit::FromInfinity()),
mVideo.mFirstDemuxedSampleTime.refOr(TimeUnit::FromInfinity()));
if (!startTime.IsInfinite()) {
mInfo.mStartTime = startTime; // mInfo.mStartTime is initialized to 0.
}
RefPtr<MetadataHolder> metadata = new MetadataHolder();
metadata->mInfo = mInfo;
metadata->mTags = tags->Count() ? tags.release() : nullptr;
metadata->mTags = mTags->Count() ? mTags.release() : nullptr;
mMetadataPromise.Resolve(metadata, __func__);
}
@ -863,10 +903,22 @@ MediaFormatReader::OnDemuxFailed(TrackType aTrack, const MediaResult& aError)
void
MediaFormatReader::DoDemuxVideo()
{
mVideo.mDemuxRequest.Begin(mVideo.mTrackDemuxer->GetSamples(1)
->Then(OwnerThread(), __func__, this,
&MediaFormatReader::OnVideoDemuxCompleted,
&MediaFormatReader::OnVideoDemuxFailed));
auto p = mVideo.mTrackDemuxer->GetSamples(1);
if (mVideo.mFirstDemuxedSampleTime.isNothing()) {
RefPtr<MediaFormatReader> self = this;
p = p->Then(OwnerThread(), __func__,
[self] (RefPtr<MediaTrackDemuxer::SamplesHolder> aSamples) {
self->OnFirstDemuxCompleted(TrackInfo::kVideoTrack, aSamples);
},
[self] (const MediaResult& aError) {
self->OnFirstDemuxFailed(TrackInfo::kVideoTrack, aError);
})->CompletionPromise();
}
mVideo.mDemuxRequest.Begin(p->Then(OwnerThread(), __func__, this,
&MediaFormatReader::OnVideoDemuxCompleted,
&MediaFormatReader::OnVideoDemuxFailed));
}
void
@ -917,10 +969,22 @@ MediaFormatReader::RequestAudioData()
void
MediaFormatReader::DoDemuxAudio()
{
mAudio.mDemuxRequest.Begin(mAudio.mTrackDemuxer->GetSamples(1)
->Then(OwnerThread(), __func__, this,
&MediaFormatReader::OnAudioDemuxCompleted,
&MediaFormatReader::OnAudioDemuxFailed));
auto p = mAudio.mTrackDemuxer->GetSamples(1);
if (mAudio.mFirstDemuxedSampleTime.isNothing()) {
RefPtr<MediaFormatReader> self = this;
p = p->Then(OwnerThread(), __func__,
[self] (RefPtr<MediaTrackDemuxer::SamplesHolder> aSamples) {
self->OnFirstDemuxCompleted(TrackInfo::kAudioTrack, aSamples);
},
[self] (const MediaResult& aError) {
self->OnFirstDemuxFailed(TrackInfo::kAudioTrack, aError);
})->CompletionPromise();
}
mAudio.mDemuxRequest.Begin(p->Then(OwnerThread(), __func__, this,
&MediaFormatReader::OnAudioDemuxCompleted,
&MediaFormatReader::OnAudioDemuxFailed));
}
void
@ -1204,11 +1268,6 @@ MediaFormatReader::HandleDemuxedSamples(TrackType aTrack,
return;
}
if (!ForceZeroStartTime() && decoder.mFirstDemuxedSampleTime.isNothing()) {
decoder.mFirstDemuxedSampleTime.emplace(
media::TimeUnit::FromMicroseconds(decoder.mQueuedSamples[0]->mTime));
}
LOGV("Giving %s input to decoder", TrackTypeToStr(aTrack));
// Decode all our demuxed frames.
@ -2340,4 +2399,37 @@ MediaFormatReader::SetBlankDecode(TrackType aTrack, bool aIsBlankDecode)
return;
}
void
MediaFormatReader::OnFirstDemuxCompleted(TrackInfo::TrackType aType,
RefPtr<MediaTrackDemuxer::SamplesHolder> aSamples)
{
MOZ_ASSERT(OnTaskQueue());
if (mShutdown) {
return;
}
auto& decoder = GetDecoderData(aType);
MOZ_ASSERT(decoder.mFirstDemuxedSampleTime.isNothing());
decoder.mFirstDemuxedSampleTime.emplace(
TimeUnit::FromMicroseconds(aSamples->mSamples[0]->mTime));
MaybeResolveMetadataPromise();
}
void
MediaFormatReader::OnFirstDemuxFailed(TrackInfo::TrackType aType,
const MediaResult& aError)
{
MOZ_ASSERT(OnTaskQueue());
if (mShutdown) {
return;
}
auto& decoder = GetDecoderData(aType);
MOZ_ASSERT(decoder.mFirstDemuxedSampleTime.isNothing());
decoder.mFirstDemuxedSampleTime.emplace(TimeUnit::FromInfinity());
MaybeResolveMetadataPromise();
}
} // namespace mozilla

View File

@ -595,6 +595,15 @@ private:
UniquePtr<DecoderFactory> mDecoderFactory;
MediaEventListener mCompositorUpdatedListener;
void OnFirstDemuxCompleted(TrackInfo::TrackType aType,
RefPtr<MediaTrackDemuxer::SamplesHolder> aSamples);
void OnFirstDemuxFailed(TrackInfo::TrackType aType, const MediaResult& aError);
void MaybeResolveMetadataPromise();
UniquePtr<MetadataTags> mTags;
};
} // namespace mozilla

View File

@ -503,6 +503,10 @@ public:
bool mMediaSeekableOnlyInBufferedRanges = false;
EncryptionInfo mCrypto;
// The minimum of start times of audio and video tracks.
// Use to map the zero time on the media timeline to the first frame.
media::TimeUnit mStartTime;
};
class SharedTrackInfo {