2016-03-31 11:32:03 +03:00
|
|
|
/* -*- 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"
|
2017-07-19 12:01:32 +03:00
|
|
|
#include "MediaFormatReader.h"
|
2017-07-27 09:49:57 +03:00
|
|
|
#include "ReaderProxy.h"
|
|
|
|
#include "TimeUnits.h"
|
2016-03-31 11:32:03 +03:00
|
|
|
|
|
|
|
namespace mozilla {
|
|
|
|
|
2017-07-27 09:49:57 +03:00
|
|
|
ReaderProxy::ReaderProxy(AbstractThread* aOwnerThread,
|
|
|
|
MediaFormatReader* aReader)
|
2016-11-23 12:34:12 +03:00
|
|
|
: mOwnerThread(aOwnerThread)
|
2016-03-31 11:32:03 +03:00
|
|
|
, mReader(aReader)
|
2017-07-06 06:45:02 +03:00
|
|
|
, mWatchManager(this, aReader->OwnerThread())
|
|
|
|
, mDuration(aReader->OwnerThread(),
|
2017-07-27 09:49:57 +03:00
|
|
|
media::NullableTimeUnit(),
|
|
|
|
"ReaderProxy::mDuration (Mirror)")
|
2017-11-10 07:06:12 +03:00
|
|
|
, mSeamlessLoopingEnabled(false)
|
2016-12-21 12:37:56 +03:00
|
|
|
{
|
|
|
|
// Must support either heuristic buffering or WaitForData().
|
|
|
|
MOZ_ASSERT(mReader->UseBufferingHeuristics() ||
|
|
|
|
mReader->IsWaitForDataSupported());
|
|
|
|
}
|
2016-03-31 11:32:03 +03:00
|
|
|
|
2017-07-27 09:49:57 +03:00
|
|
|
ReaderProxy::~ReaderProxy()
|
2016-03-31 11:32:03 +03:00
|
|
|
{}
|
|
|
|
|
|
|
|
media::TimeUnit
|
2017-07-27 09:49:57 +03:00
|
|
|
ReaderProxy::StartTime() const
|
2016-03-31 11:32:03 +03:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
|
|
|
|
MOZ_ASSERT(!mShutdown);
|
2016-10-14 14:10:24 +03:00
|
|
|
return mStartTime.ref();
|
2016-03-31 11:32:03 +03:00
|
|
|
}
|
|
|
|
|
2017-07-27 09:49:57 +03:00
|
|
|
RefPtr<ReaderProxy::MetadataPromise>
|
|
|
|
ReaderProxy::ReadMetadata()
|
2016-03-31 11:32:03 +03:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
|
|
|
|
MOZ_ASSERT(!mShutdown);
|
2017-07-19 12:01:32 +03:00
|
|
|
return InvokeAsync(mReader->OwnerThread(),
|
|
|
|
mReader.get(),
|
|
|
|
__func__,
|
|
|
|
&MediaFormatReader::AsyncReadMetadata)
|
|
|
|
->Then(mOwnerThread,
|
|
|
|
__func__,
|
|
|
|
this,
|
2017-07-27 09:49:57 +03:00
|
|
|
&ReaderProxy::OnMetadataRead,
|
|
|
|
&ReaderProxy::OnMetadataNotRead);
|
2016-03-31 11:32:03 +03:00
|
|
|
}
|
|
|
|
|
2017-07-27 09:49:57 +03:00
|
|
|
RefPtr<ReaderProxy::AudioDataPromise>
|
|
|
|
ReaderProxy::RequestAudioData()
|
2016-03-31 11:32:03 +03:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
|
|
|
|
MOZ_ASSERT(!mShutdown);
|
|
|
|
|
2016-12-20 07:54:23 +03:00
|
|
|
int64_t startTime = StartTime().ToMicroseconds();
|
2017-07-19 12:01:32 +03:00
|
|
|
return InvokeAsync(mReader->OwnerThread(),
|
|
|
|
mReader.get(),
|
|
|
|
__func__,
|
|
|
|
&MediaFormatReader::RequestAudioData)
|
|
|
|
->Then(mOwnerThread,
|
|
|
|
__func__,
|
|
|
|
[startTime](RefPtr<AudioData> aAudio) {
|
2016-12-20 07:54:23 +03:00
|
|
|
aAudio->AdjustForStartTime(startTime);
|
2017-05-11 03:30:39 +03:00
|
|
|
return AudioDataPromise::CreateAndResolve(aAudio.forget(), __func__);
|
2016-12-20 07:54:23 +03:00
|
|
|
},
|
2017-07-19 12:01:32 +03:00
|
|
|
[](const MediaResult& aError) {
|
2017-05-09 18:31:32 +03:00
|
|
|
return AudioDataPromise::CreateAndReject(aError, __func__);
|
|
|
|
});
|
2016-03-31 11:32:03 +03:00
|
|
|
}
|
|
|
|
|
2017-07-27 09:49:57 +03:00
|
|
|
RefPtr<ReaderProxy::VideoDataPromise>
|
|
|
|
ReaderProxy::RequestVideoData(const media::TimeUnit& aTimeThreshold)
|
2016-03-31 11:32:03 +03:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
|
|
|
|
MOZ_ASSERT(!mShutdown);
|
2016-04-27 09:50:23 +03:00
|
|
|
|
2017-06-19 05:45:55 +03:00
|
|
|
const auto threshold = aTimeThreshold > media::TimeUnit::Zero()
|
|
|
|
? aTimeThreshold + StartTime()
|
|
|
|
: aTimeThreshold;
|
2016-03-31 11:32:03 +03:00
|
|
|
|
2016-12-20 08:17:05 +03:00
|
|
|
int64_t startTime = StartTime().ToMicroseconds();
|
2017-07-19 12:01:32 +03:00
|
|
|
return InvokeAsync(mReader->OwnerThread(),
|
|
|
|
mReader.get(),
|
|
|
|
__func__,
|
|
|
|
&MediaFormatReader::RequestVideoData,
|
|
|
|
threshold)
|
|
|
|
->Then(mOwnerThread,
|
|
|
|
__func__,
|
|
|
|
[startTime](RefPtr<VideoData> aVideo) {
|
|
|
|
aVideo->AdjustForStartTime(startTime);
|
|
|
|
return VideoDataPromise::CreateAndResolve(aVideo.forget(),
|
|
|
|
__func__);
|
|
|
|
},
|
|
|
|
[](const MediaResult& aError) {
|
|
|
|
return VideoDataPromise::CreateAndReject(aError, __func__);
|
|
|
|
});
|
2016-03-31 11:32:03 +03:00
|
|
|
}
|
|
|
|
|
2017-07-27 09:49:57 +03:00
|
|
|
RefPtr<ReaderProxy::SeekPromise>
|
|
|
|
ReaderProxy::Seek(const SeekTarget& aTarget)
|
2016-03-31 11:32:03 +03:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
|
2016-11-13 09:42:19 +03:00
|
|
|
SeekTarget adjustedTarget = aTarget;
|
|
|
|
adjustedTarget.SetTime(adjustedTarget.GetTime() + StartTime());
|
2017-07-19 12:01:32 +03:00
|
|
|
return InvokeAsync(mReader->OwnerThread(),
|
|
|
|
mReader.get(),
|
|
|
|
__func__,
|
|
|
|
&MediaFormatReader::Seek,
|
|
|
|
Move(adjustedTarget));
|
2016-03-31 11:32:03 +03:00
|
|
|
}
|
|
|
|
|
2017-07-27 09:49:57 +03:00
|
|
|
RefPtr<ReaderProxy::WaitForDataPromise>
|
|
|
|
ReaderProxy::WaitForData(MediaData::Type aType)
|
2016-04-19 11:14:30 +03:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
|
2016-12-21 12:37:56 +03:00
|
|
|
MOZ_ASSERT(mReader->IsWaitForDataSupported());
|
2017-07-19 12:01:32 +03:00
|
|
|
return InvokeAsync(mReader->OwnerThread(),
|
|
|
|
mReader.get(),
|
|
|
|
__func__,
|
|
|
|
&MediaFormatReader::WaitForData,
|
|
|
|
aType);
|
2016-04-19 11:14:30 +03:00
|
|
|
}
|
|
|
|
|
2016-03-31 11:32:03 +03:00
|
|
|
void
|
2017-07-27 09:49:57 +03:00
|
|
|
ReaderProxy::ReleaseResources()
|
2016-04-19 11:14:30 +03:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
|
|
|
|
nsCOMPtr<nsIRunnable> r =
|
2017-07-19 12:01:32 +03:00
|
|
|
NewRunnableMethod("MediaFormatReader::ReleaseResources",
|
2017-06-12 22:34:10 +03:00
|
|
|
mReader,
|
2017-07-19 12:01:32 +03:00
|
|
|
&MediaFormatReader::ReleaseResources);
|
2017-11-15 09:58:03 +03:00
|
|
|
nsresult rv = mReader->OwnerThread()->Dispatch(r.forget());
|
|
|
|
MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
|
2016-04-19 11:14:30 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-07-27 09:49:57 +03:00
|
|
|
ReaderProxy::ResetDecode(TrackSet aTracks)
|
2016-04-19 11:14:30 +03:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
|
|
|
|
nsCOMPtr<nsIRunnable> r =
|
2017-07-19 12:01:32 +03:00
|
|
|
NewRunnableMethod<TrackSet>("MediaFormatReader::ResetDecode",
|
2017-06-12 22:34:10 +03:00
|
|
|
mReader,
|
2017-07-19 12:01:32 +03:00
|
|
|
&MediaFormatReader::ResetDecode,
|
2016-05-31 07:32:37 +03:00
|
|
|
aTracks);
|
2017-11-15 09:58:03 +03:00
|
|
|
nsresult rv = mReader->OwnerThread()->Dispatch(r.forget());
|
|
|
|
MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
|
2016-04-19 11:14:30 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
RefPtr<ShutdownPromise>
|
2017-07-27 09:49:57 +03:00
|
|
|
ReaderProxy::Shutdown()
|
2016-03-31 11:32:03 +03:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
|
|
|
|
mShutdown = true;
|
2017-07-27 09:49:57 +03:00
|
|
|
RefPtr<ReaderProxy> self = this;
|
2017-07-06 06:45:02 +03:00
|
|
|
return InvokeAsync(mReader->OwnerThread(), __func__, [self]() {
|
|
|
|
self->mDuration.DisconnectIfConnected();
|
|
|
|
self->mWatchManager.Shutdown();
|
|
|
|
return self->mReader->Shutdown();
|
|
|
|
});
|
2016-03-31 11:32:03 +03:00
|
|
|
}
|
|
|
|
|
2017-07-27 09:49:57 +03:00
|
|
|
RefPtr<ReaderProxy::MetadataPromise>
|
|
|
|
ReaderProxy::OnMetadataRead(MetadataHolder&& aMetadata)
|
2016-03-31 11:32:03 +03:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
|
|
|
|
if (mShutdown) {
|
2017-05-09 18:31:32 +03:00
|
|
|
return MetadataPromise::CreateAndReject(
|
|
|
|
NS_ERROR_DOM_MEDIA_ABORT_ERR, __func__);
|
2016-03-31 11:32:03 +03:00
|
|
|
}
|
2016-10-14 14:10:24 +03:00
|
|
|
|
|
|
|
if (mStartTime.isNothing()) {
|
2017-05-18 05:20:44 +03:00
|
|
|
mStartTime.emplace(aMetadata.mInfo->mStartTime);
|
2016-03-31 11:32:03 +03:00
|
|
|
}
|
2017-05-18 05:20:44 +03:00
|
|
|
return MetadataPromise::CreateAndResolve(Move(aMetadata), __func__);
|
2017-05-09 18:31:32 +03:00
|
|
|
}
|
|
|
|
|
2017-07-27 09:49:57 +03:00
|
|
|
RefPtr<ReaderProxy::MetadataPromise>
|
|
|
|
ReaderProxy::OnMetadataNotRead(const MediaResult& aError)
|
2017-05-09 18:31:32 +03:00
|
|
|
{
|
|
|
|
return MetadataPromise::CreateAndReject(aError, __func__);
|
2016-03-31 11:32:03 +03:00
|
|
|
}
|
|
|
|
|
2016-07-29 09:51:18 +03:00
|
|
|
void
|
2017-07-27 09:49:57 +03:00
|
|
|
ReaderProxy::SetVideoBlankDecode(bool aIsBlankDecode)
|
2016-07-29 09:51:18 +03:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
|
|
|
|
nsCOMPtr<nsIRunnable> r =
|
2017-07-19 12:01:32 +03:00
|
|
|
NewRunnableMethod<bool>("MediaFormatReader::SetVideoNullDecode",
|
2017-06-12 22:34:10 +03:00
|
|
|
mReader,
|
2017-07-19 12:01:32 +03:00
|
|
|
&MediaFormatReader::SetVideoNullDecode,
|
2016-07-29 09:51:18 +03:00
|
|
|
aIsBlankDecode);
|
2017-11-15 09:58:03 +03:00
|
|
|
nsresult rv = mReader->OwnerThread()->Dispatch(r.forget());
|
|
|
|
MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
|
2016-07-29 09:51:18 +03:00
|
|
|
}
|
|
|
|
|
2017-07-06 06:45:02 +03:00
|
|
|
void
|
2017-07-27 09:49:57 +03:00
|
|
|
ReaderProxy::UpdateDuration()
|
2017-07-06 06:45:02 +03:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(mReader->OwnerThread()->IsCurrentThreadIn());
|
|
|
|
mReader->UpdateDuration(mDuration.Ref().ref());
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-07-27 09:49:57 +03:00
|
|
|
ReaderProxy::SetCanonicalDuration(
|
2017-07-06 06:45:02 +03:00
|
|
|
AbstractCanonical<media::NullableTimeUnit>* aCanonical)
|
|
|
|
{
|
|
|
|
using DurationT = AbstractCanonical<media::NullableTimeUnit>;
|
2017-07-27 09:49:57 +03:00
|
|
|
RefPtr<ReaderProxy> self = this;
|
2017-07-06 06:45:02 +03:00
|
|
|
RefPtr<DurationT> canonical = aCanonical;
|
|
|
|
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction(
|
2017-07-27 09:49:57 +03:00
|
|
|
"ReaderProxy::SetCanonicalDuration", [this, self, canonical]() {
|
2017-07-06 06:45:02 +03:00
|
|
|
mDuration.Connect(canonical);
|
2017-07-27 09:49:57 +03:00
|
|
|
mWatchManager.Watch(mDuration, &ReaderProxy::UpdateDuration);
|
2017-07-06 06:45:02 +03:00
|
|
|
});
|
2017-11-15 09:58:03 +03:00
|
|
|
nsresult rv = mReader->OwnerThread()->Dispatch(r.forget());
|
|
|
|
MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
|
2017-07-06 06:45:02 +03:00
|
|
|
}
|
|
|
|
|
2017-11-10 07:06:12 +03:00
|
|
|
void
|
|
|
|
ReaderProxy::SetSeamlessLoopingEnabled(bool aEnabled)
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
|
|
|
|
mSeamlessLoopingEnabled = aEnabled;
|
|
|
|
}
|
|
|
|
|
2016-03-31 11:32:03 +03:00
|
|
|
} // namespace mozilla
|