gecko-dev/dom/media/omx/MediaOmxCommonDecoder.cpp

298 строки
7.8 KiB
C++
Исходник Обычный вид История

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* 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 "MediaOmxCommonDecoder.h"
#include <stagefright/MediaSource.h>
#include "AudioOffloadPlayerBase.h"
#include "MediaDecoderStateMachine.h"
#include "MediaOmxCommonReader.h"
#ifdef MOZ_AUDIO_OFFLOAD
#include "AudioOffloadPlayer.h"
#endif
using namespace android;
namespace mozilla {
extern LazyLogModule gMediaDecoderLog;
#define DECODER_LOG(type, msg) MOZ_LOG(gMediaDecoderLog, type, msg)
MediaOmxCommonDecoder::MediaOmxCommonDecoder(MediaDecoderOwner* aOwner)
: MediaDecoder(aOwner)
, mReader(nullptr)
, mCanOffloadAudio(false)
, mFallbackToStateMachine(false)
, mIsCaptured(false)
{
mDormantSupported = true;
}
MediaOmxCommonDecoder::~MediaOmxCommonDecoder() {}
void
MediaOmxCommonDecoder::SetPlatformCanOffloadAudio(bool aCanOffloadAudio)
{
if (!aCanOffloadAudio) {
return;
}
// Stop MDSM from playing to avoid startup glitch (bug 1053186).
GetStateMachine()->DispatchAudioOffloading(true);
// Modify mCanOffloadAudio in the main thread.
Bug 1207245 - part 6 - rename nsRefPtr<T> to RefPtr<T>; r=ehsan; a=Tomcat The bulk of this commit was generated with a script, executed at the top level of a typical source code checkout. The only non-machine-generated part was modifying MFBT's moz.build to reflect the new naming. CLOSED TREE makes big refactorings like this a piece of cake. # The main substitution. find . -name '*.cpp' -o -name '*.cc' -o -name '*.h' -o -name '*.mm' -o -name '*.idl'| \ xargs perl -p -i -e ' s/nsRefPtr\.h/RefPtr\.h/g; # handle includes s/nsRefPtr ?</RefPtr</g; # handle declarations and variables ' # Handle a special friend declaration in gfx/layers/AtomicRefCountedWithFinalize.h. perl -p -i -e 's/::nsRefPtr;/::RefPtr;/' gfx/layers/AtomicRefCountedWithFinalize.h # Handle nsRefPtr.h itself, a couple places that define constructors # from nsRefPtr, and code generators specially. We do this here, rather # than indiscriminantly s/nsRefPtr/RefPtr/, because that would rename # things like nsRefPtrHashtable. perl -p -i -e 's/nsRefPtr/RefPtr/g' \ mfbt/nsRefPtr.h \ xpcom/glue/nsCOMPtr.h \ xpcom/base/OwningNonNull.h \ ipc/ipdl/ipdl/lower.py \ ipc/ipdl/ipdl/builtin.py \ dom/bindings/Codegen.py \ python/lldbutils/lldbutils/utils.py # In our indiscriminate substitution above, we renamed # nsRefPtrGetterAddRefs, the class behind getter_AddRefs. Fix that up. find . -name '*.cpp' -o -name '*.h' -o -name '*.idl' | \ xargs perl -p -i -e 's/nsRefPtrGetterAddRefs/RefPtrGetterAddRefs/g' if [ -d .git ]; then git mv mfbt/nsRefPtr.h mfbt/RefPtr.h else hg mv mfbt/nsRefPtr.h mfbt/RefPtr.h fi --HG-- rename : mfbt/nsRefPtr.h => mfbt/RefPtr.h
2015-10-18 08:24:48 +03:00
RefPtr<MediaOmxCommonDecoder> self = this;
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([=] () {
self->mCanOffloadAudio = true;
});
AbstractThread::MainThread()->Dispatch(r.forget());
}
void
MediaOmxCommonDecoder::DisableStateMachineAudioOffloading()
{
MOZ_ASSERT(NS_IsMainThread());
if (mCanOffloadAudio) {
// mCanOffloadAudio is true implies we've called
// |GetStateMachine()->DispatchAudioOffloading(true)| in
// SetPlatformCanOffloadAudio(). We need to turn off audio offloading
// for MDSM so it can start playback.
GetStateMachine()->DispatchAudioOffloading(false);
}
}
bool
MediaOmxCommonDecoder::CheckDecoderCanOffloadAudio()
{
MOZ_ASSERT(NS_IsMainThread());
return (mCanOffloadAudio && !mFallbackToStateMachine &&
!mIsCaptured && mPlaybackRate == 1.0);
}
void
MediaOmxCommonDecoder::FirstFrameLoaded(nsAutoPtr<MediaInfo> aInfo,
MediaDecoderEventVisibility aEventVisibility)
{
MOZ_ASSERT(NS_IsMainThread());
MediaDecoder::FirstFrameLoaded(aInfo, aEventVisibility);
if (!CheckDecoderCanOffloadAudio()) {
DECODER_LOG(LogLevel::Debug, ("In %s Offload Audio check failed",
__PRETTY_FUNCTION__));
DisableStateMachineAudioOffloading();
return;
}
#ifdef MOZ_AUDIO_OFFLOAD
mAudioOffloadPlayer = new AudioOffloadPlayer(this);
#endif
if (!mAudioOffloadPlayer) {
DisableStateMachineAudioOffloading();
return;
}
mAudioOffloadPlayer->SetSource(mReader->GetAudioOffloadTrack());
status_t err = mAudioOffloadPlayer->Start(false);
if (err != OK) {
mAudioOffloadPlayer = nullptr;
mFallbackToStateMachine = true;
DECODER_LOG(LogLevel::Debug, ("In %s Unable to start offload audio %d."
"Switching to normal mode", __PRETTY_FUNCTION__, err));
DisableStateMachineAudioOffloading();
return;
}
PauseStateMachine();
if (mLogicallySeeking) {
SeekTarget target = SeekTarget(mLogicalPosition,
SeekTarget::Accurate,
MediaDecoderEventVisibility::Observable);
mSeekRequest.DisconnectIfExists();
mSeekRequest.Begin(mAudioOffloadPlayer->Seek(target)
->Then(AbstractThread::MainThread(), __func__, static_cast<MediaDecoder*>(this),
&MediaDecoder::OnSeekResolved, &MediaDecoder::OnSeekRejected));
}
// Call ChangeState() to run AudioOffloadPlayer since offload state enabled
ChangeState(mPlayState);
}
void
MediaOmxCommonDecoder::PauseStateMachine()
{
MOZ_ASSERT(NS_IsMainThread());
DECODER_LOG(LogLevel::Debug, ("%s", __PRETTY_FUNCTION__));
MOZ_ASSERT(GetStateMachine());
// enter dormant state
GetStateMachine()->DispatchSetDormant(true);
}
void
MediaOmxCommonDecoder::ResumeStateMachine()
{
MOZ_ASSERT(NS_IsMainThread());
DECODER_LOG(LogLevel::Debug, ("%s current time %f", __PRETTY_FUNCTION__, mLogicalPosition));
if (IsShutdown()) {
return;
}
if (!GetStateMachine()) {
return;
}
GetStateMachine()->DispatchAudioOffloading(false);
mFallbackToStateMachine = true;
mAudioOffloadPlayer = nullptr;
SeekTarget target = SeekTarget(mLogicalPosition,
SeekTarget::Accurate,
MediaDecoderEventVisibility::Suppressed);
// Call Seek of MediaDecoderStateMachine to suppress seek events.
GetStateMachine()->InvokeSeek(target);
// exit dormant state
GetStateMachine()->DispatchSetDormant(false);
UpdateLogicalPosition();
}
void
MediaOmxCommonDecoder::AudioOffloadTearDown()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!IsShutdown());
DECODER_LOG(LogLevel::Debug, ("%s", __PRETTY_FUNCTION__));
// mAudioOffloadPlayer can be null here if ResumeStateMachine was called
// just before because of some other error.
if (mAudioOffloadPlayer) {
ResumeStateMachine();
}
}
void
MediaOmxCommonDecoder::AddOutputStream(ProcessedMediaStream* aStream,
bool aFinishWhenEnded)
{
MOZ_ASSERT(NS_IsMainThread());
mIsCaptured = true;
if (mAudioOffloadPlayer) {
ResumeStateMachine();
}
MediaDecoder::AddOutputStream(aStream, aFinishWhenEnded);
}
void
MediaOmxCommonDecoder::SetPlaybackRate(double aPlaybackRate)
{
MOZ_ASSERT(NS_IsMainThread());
if (mAudioOffloadPlayer &&
((aPlaybackRate != 0.0) || (aPlaybackRate != 1.0))) {
ResumeStateMachine();
}
MediaDecoder::SetPlaybackRate(aPlaybackRate);
}
void
MediaOmxCommonDecoder::ChangeState(PlayState aState)
{
MOZ_ASSERT(NS_IsMainThread());
// Keep MediaDecoder state in sync with MediaElement irrespective of offload
// playback so it will continue to work in normal mode when offloading fails
// in between
MediaDecoder::ChangeState(aState);
if (!mAudioOffloadPlayer) {
return;
}
status_t err = mAudioOffloadPlayer->ChangeState(aState);
if (err != OK) {
ResumeStateMachine();
return;
}
}
void
MediaOmxCommonDecoder::CallSeek(const SeekTarget& aTarget, dom::Promise* aPromise)
{
if (!mAudioOffloadPlayer) {
MediaDecoder::CallSeek(aTarget, aPromise);
return;
}
DiscardOngoingSeekIfExists();
mSeekDOMPromise = aPromise;
mSeekRequest.Begin(mAudioOffloadPlayer->Seek(aTarget)
->Then(AbstractThread::MainThread(), __func__, static_cast<MediaDecoder*>(this),
&MediaDecoder::OnSeekResolved, &MediaDecoder::OnSeekRejected));
}
int64_t
MediaOmxCommonDecoder::CurrentPosition()
{
MOZ_ASSERT(NS_IsMainThread());
if (!mAudioOffloadPlayer) {
return MediaDecoder::CurrentPosition();
}
return mAudioOffloadPlayer->GetMediaTimeUs();
}
void
MediaOmxCommonDecoder::SetElementVisibility(bool aIsVisible)
{
MOZ_ASSERT(NS_IsMainThread());
MediaDecoder::SetElementVisibility(aIsVisible);
if (mAudioOffloadPlayer) {
mAudioOffloadPlayer->SetElementVisibility(aIsVisible);
}
}
MediaDecoderOwner::NextFrameStatus
MediaOmxCommonDecoder::NextFrameStatus()
{
MOZ_ASSERT(NS_IsMainThread());
return mAudioOffloadPlayer ? mAudioOffloadPlayer->GetNextFrameStatus()
: MediaDecoder::NextFrameStatus();
}
void
MediaOmxCommonDecoder::SetVolume(double aVolume)
{
MOZ_ASSERT(NS_IsMainThread());
if (!mAudioOffloadPlayer) {
MediaDecoder::SetVolume(aVolume);
return;
}
mAudioOffloadPlayer->SetVolume(aVolume);
}
MediaDecoderStateMachine*
MediaOmxCommonDecoder::CreateStateMachine()
{
mReader = CreateReader();
if (mReader != nullptr) {
mReader->SetAudioChannel(GetAudioChannel());
}
return CreateStateMachineFromReader(mReader);
}
void
MediaOmxCommonDecoder::Shutdown()
{
mAudioOffloadPlayer = nullptr;
MediaDecoder::Shutdown();
}
} // namespace mozilla