зеркало из https://github.com/mozilla/gecko-dev.git
172 строки
5.6 KiB
C++
172 строки
5.6 KiB
C++
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#include "mozilla/MozPromise.h"
|
|
#include "MediaDecoderReaderWrapper.h"
|
|
|
|
namespace mozilla {
|
|
|
|
MediaDecoderReaderWrapper::MediaDecoderReaderWrapper(AbstractThread* aOwnerThread,
|
|
MediaDecoderReader* aReader)
|
|
: mOwnerThread(aOwnerThread)
|
|
, mReader(aReader)
|
|
{
|
|
// Must support either heuristic buffering or WaitForData().
|
|
MOZ_ASSERT(mReader->UseBufferingHeuristics() ||
|
|
mReader->IsWaitForDataSupported());
|
|
}
|
|
|
|
MediaDecoderReaderWrapper::~MediaDecoderReaderWrapper()
|
|
{}
|
|
|
|
media::TimeUnit
|
|
MediaDecoderReaderWrapper::StartTime() const
|
|
{
|
|
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
|
|
MOZ_ASSERT(!mShutdown);
|
|
return mStartTime.ref();
|
|
}
|
|
|
|
RefPtr<MediaDecoderReaderWrapper::MetadataPromise>
|
|
MediaDecoderReaderWrapper::ReadMetadata()
|
|
{
|
|
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
|
|
MOZ_ASSERT(!mShutdown);
|
|
return InvokeAsync(mReader->OwnerThread(), mReader.get(), __func__,
|
|
&MediaDecoderReader::AsyncReadMetadata)
|
|
->Then(mOwnerThread, __func__, this,
|
|
&MediaDecoderReaderWrapper::OnMetadataRead,
|
|
&MediaDecoderReaderWrapper::OnMetadataNotRead);
|
|
}
|
|
|
|
RefPtr<MediaDecoderReaderWrapper::AudioDataPromise>
|
|
MediaDecoderReaderWrapper::RequestAudioData()
|
|
{
|
|
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
|
|
MOZ_ASSERT(!mShutdown);
|
|
|
|
int64_t startTime = StartTime().ToMicroseconds();
|
|
return InvokeAsync(mReader->OwnerThread(), mReader.get(),
|
|
__func__, &MediaDecoderReader::RequestAudioData)
|
|
->Then(mOwnerThread, __func__,
|
|
[startTime] (RefPtr<AudioData> aAudio) {
|
|
aAudio->AdjustForStartTime(startTime);
|
|
return AudioDataPromise::CreateAndResolve(aAudio.forget(), __func__);
|
|
},
|
|
[] (const MediaResult& aError) {
|
|
return AudioDataPromise::CreateAndReject(aError, __func__);
|
|
});
|
|
}
|
|
|
|
RefPtr<MediaDecoderReaderWrapper::VideoDataPromise>
|
|
MediaDecoderReaderWrapper::RequestVideoData(bool aSkipToNextKeyframe,
|
|
media::TimeUnit aTimeThreshold)
|
|
{
|
|
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
|
|
MOZ_ASSERT(!mShutdown);
|
|
|
|
if (aTimeThreshold > media::TimeUnit::Zero()) {
|
|
aTimeThreshold += StartTime();
|
|
}
|
|
|
|
int64_t startTime = StartTime().ToMicroseconds();
|
|
return InvokeAsync(
|
|
mReader->OwnerThread(), mReader.get(), __func__,
|
|
&MediaDecoderReader::RequestVideoData,
|
|
aSkipToNextKeyframe, aTimeThreshold)
|
|
->Then(mOwnerThread, __func__,
|
|
[startTime] (RefPtr<VideoData> aVideo) {
|
|
aVideo->AdjustForStartTime(startTime);
|
|
return VideoDataPromise::CreateAndResolve(aVideo.forget(), __func__);
|
|
},
|
|
[] (const MediaResult& aError) {
|
|
return VideoDataPromise::CreateAndReject(aError, __func__);
|
|
});
|
|
}
|
|
|
|
RefPtr<MediaDecoderReader::SeekPromise>
|
|
MediaDecoderReaderWrapper::Seek(const SeekTarget& aTarget)
|
|
{
|
|
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
|
|
SeekTarget adjustedTarget = aTarget;
|
|
adjustedTarget.SetTime(adjustedTarget.GetTime() + StartTime());
|
|
return InvokeAsync(
|
|
mReader->OwnerThread(), mReader.get(), __func__,
|
|
&MediaDecoderReader::Seek,
|
|
Move(adjustedTarget));
|
|
}
|
|
|
|
RefPtr<MediaDecoderReaderWrapper::WaitForDataPromise>
|
|
MediaDecoderReaderWrapper::WaitForData(MediaData::Type aType)
|
|
{
|
|
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
|
|
MOZ_ASSERT(mReader->IsWaitForDataSupported());
|
|
return InvokeAsync(mReader->OwnerThread(), mReader.get(), __func__,
|
|
&MediaDecoderReader::WaitForData, aType);
|
|
}
|
|
|
|
void
|
|
MediaDecoderReaderWrapper::ReleaseResources()
|
|
{
|
|
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
|
|
nsCOMPtr<nsIRunnable> r =
|
|
NewRunnableMethod(mReader, &MediaDecoderReader::ReleaseResources);
|
|
mReader->OwnerThread()->Dispatch(r.forget());
|
|
}
|
|
|
|
void
|
|
MediaDecoderReaderWrapper::ResetDecode(TrackSet aTracks)
|
|
{
|
|
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
|
|
nsCOMPtr<nsIRunnable> r =
|
|
NewRunnableMethod<TrackSet>(mReader,
|
|
&MediaDecoderReader::ResetDecode,
|
|
aTracks);
|
|
mReader->OwnerThread()->Dispatch(r.forget());
|
|
}
|
|
|
|
RefPtr<ShutdownPromise>
|
|
MediaDecoderReaderWrapper::Shutdown()
|
|
{
|
|
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
|
|
mShutdown = true;
|
|
return InvokeAsync(mReader->OwnerThread(), mReader.get(), __func__,
|
|
&MediaDecoderReader::Shutdown);
|
|
}
|
|
|
|
RefPtr<MediaDecoderReaderWrapper::MetadataPromise>
|
|
MediaDecoderReaderWrapper::OnMetadataRead(MetadataHolder&& aMetadata)
|
|
{
|
|
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
|
|
if (mShutdown) {
|
|
return MetadataPromise::CreateAndReject(
|
|
NS_ERROR_DOM_MEDIA_ABORT_ERR, __func__);
|
|
}
|
|
|
|
if (mStartTime.isNothing()) {
|
|
mStartTime.emplace(aMetadata.mInfo->mStartTime);
|
|
}
|
|
return MetadataPromise::CreateAndResolve(Move(aMetadata), __func__);
|
|
}
|
|
|
|
RefPtr<MediaDecoderReaderWrapper::MetadataPromise>
|
|
MediaDecoderReaderWrapper::OnMetadataNotRead(const MediaResult& aError)
|
|
{
|
|
return MetadataPromise::CreateAndReject(aError, __func__);
|
|
}
|
|
|
|
void
|
|
MediaDecoderReaderWrapper::SetVideoBlankDecode(bool aIsBlankDecode)
|
|
{
|
|
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
|
|
nsCOMPtr<nsIRunnable> r =
|
|
NewRunnableMethod<bool>(mReader, &MediaDecoderReader::SetVideoNullDecode,
|
|
aIsBlankDecode);
|
|
mReader->OwnerThread()->Dispatch(r.forget());
|
|
}
|
|
|
|
} // namespace mozilla
|