mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-04 13:07:52 +00:00
Bug 976172 - Part 1 Changes in MediaOmxDecoder to enable audio offloading r=roc
This adds support in MediaOmxDecoder to dynamically switch between MediaDecoderStateMachine and AudioOffloadPlayer
This commit is contained in:
parent
92bcfe6282
commit
0f755350a7
@ -232,7 +232,7 @@ if test -n "$gonkdir" ; then
|
||||
|
||||
case "$ANDROID_VERSION" in
|
||||
15)
|
||||
GONK_INCLUDES="-I$gonkdir/frameworks/base/opengl/include -I$gonkdir/frameworks/base/native/include -I$gonkdir/frameworks/base/include -I$gonkdir/frameworks/base/services/camera -I$gonkdir/frameworks/base/include/media/stagefright -I$gonkdir/frameworks/base/include/media/stagefright/openmax -I$gonkdir/frameworks/base/media/libstagefright/rtsp -I$gonkdir/frameworks/base/media/libstagefright/include -I$gonkdir/external/dbus -I$gonkdir/external/bluetooth/bluez/lib -I$gonkdir/dalvik/libnativehelper/include/nativehelper"
|
||||
GONK_INCLUDES="-I$gonkdir/frameworks/base/opengl/include -I$gonkdir/frameworks/base/native/include -I$gonkdir/frameworks/base/include -I$gonkdir/frameworks/base/services/camera -I$gonkdir/frameworks/base/include/media/ -I$gonkdir/frameworks/base/include/media/stagefright -I$gonkdir/frameworks/base/include/media/stagefright/openmax -I$gonkdir/frameworks/base/media/libstagefright/rtsp -I$gonkdir/frameworks/base/media/libstagefright/include -I$gonkdir/external/dbus -I$gonkdir/external/bluetooth/bluez/lib -I$gonkdir/dalvik/libnativehelper/include/nativehelper"
|
||||
MOZ_B2G_BT=1
|
||||
MOZ_B2G_BT_BLUEZ=1
|
||||
MOZ_NFC=1
|
||||
|
@ -50,6 +50,9 @@ class nsIRunnable;
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
// Number of milliseconds between timeupdate events as defined by spec
|
||||
#define TIMEUPDATE_MS 250
|
||||
|
||||
class MediaError;
|
||||
class MediaSource;
|
||||
class TextTrackList;
|
||||
|
@ -107,9 +107,6 @@ using mozilla::net::nsMediaFragmentURIParser;
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
// Number of milliseconds between timeupdate events as defined by spec
|
||||
#define TIMEUPDATE_MS 250
|
||||
|
||||
// Used by AudioChannel for suppresssing the volume to this ratio.
|
||||
#define FADED_VOLUME_RATIO 0.25
|
||||
|
||||
@ -3385,6 +3382,7 @@ void HTMLMediaElement::NotifyOwnerDocumentActivityChanged()
|
||||
nsIDocument* ownerDoc = OwnerDoc();
|
||||
|
||||
if (mDecoder) {
|
||||
mDecoder->SetElementVisibility(!ownerDoc->Hidden());
|
||||
mDecoder->SetDormantIfNecessary(ownerDoc->Hidden());
|
||||
}
|
||||
|
||||
|
@ -116,6 +116,12 @@ public:
|
||||
// required to begin playback have been acquired. Can be called on any thread.
|
||||
virtual void NotifyWaitingForResourcesStatusChanged() = 0;
|
||||
|
||||
// Called by Reader if the current audio track can be offloaded
|
||||
virtual void SetCanOffloadAudio(bool aCanOffloadAudio) {}
|
||||
|
||||
// Called from HTMLMediaElement when owner document activity changes
|
||||
virtual void SetElementVisibility(bool aIsVisible) {}
|
||||
|
||||
// Stack based class to assist in notifying the frame statistics of
|
||||
// parsed and decoded frames. Use inside video demux & decode functions
|
||||
// to ensure all parsed and decoded frames are reported on all return paths.
|
||||
|
12
content/media/MediaDecoder.h
Normal file → Executable file
12
content/media/MediaDecoder.h
Normal file → Executable file
@ -368,7 +368,7 @@ public:
|
||||
|
||||
virtual void NotifyWaitingForResourcesStatusChanged() MOZ_OVERRIDE;
|
||||
|
||||
void SetPlaybackRate(double aPlaybackRate);
|
||||
virtual void SetPlaybackRate(double aPlaybackRate);
|
||||
void SetPreservesPitch(bool aPreservesPitch);
|
||||
|
||||
// Directs the decoder to not preroll extra samples until the media is
|
||||
@ -760,7 +760,7 @@ public:
|
||||
// Change to a new play state. This updates the mState variable and
|
||||
// notifies any thread blocking on this object's monitor of the
|
||||
// change. Call on the main thread only.
|
||||
void ChangeState(PlayState aState);
|
||||
virtual void ChangeState(PlayState aState);
|
||||
|
||||
// Called by |ChangeState|, to update the state machine.
|
||||
// Call on the main thread only and the lock must be obtained.
|
||||
@ -772,7 +772,11 @@ public:
|
||||
|
||||
// Called when the metadata from the media file has been loaded by the
|
||||
// state machine. Call on the main thread only.
|
||||
void MetadataLoaded(int aChannels, int aRate, bool aHasAudio, bool aHasVideo, MetadataTags* aTags);
|
||||
virtual void MetadataLoaded(int aChannels,
|
||||
int aRate,
|
||||
bool aHasAudio,
|
||||
bool aHasVideo,
|
||||
MetadataTags* aTags);
|
||||
|
||||
// Called when the first frame has been loaded.
|
||||
// Call on the main thread only.
|
||||
@ -805,7 +809,7 @@ public:
|
||||
|
||||
// Calls mElement->UpdateReadyStateForData, telling it whether we have
|
||||
// data for the next frame and if we're buffering. Main thread only.
|
||||
void UpdateReadyStateForData();
|
||||
virtual void UpdateReadyStateForData();
|
||||
|
||||
// Find the end of the cached data starting at the current decoder
|
||||
// position.
|
||||
|
72
content/media/omx/AudioOffloadPlayerBase.h
Normal file
72
content/media/omx/AudioOffloadPlayerBase.h
Normal file
@ -0,0 +1,72 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/*
|
||||
* Copyright (c) 2014 The Linux Foundation. All rights reserved.
|
||||
* Copyright (C) 2009 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef AUDIO_OFFLOAD_PLAYER_BASE_H_
|
||||
#define AUDIO_OFFLOAD_PLAYER_BASE_H_
|
||||
|
||||
#include "MediaDecoderOwner.h"
|
||||
#include "MediaOmxDecoder.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class MediaOmxDecoder;
|
||||
|
||||
/**
|
||||
* AudioOffloadPlayer interface class which has funtions used by MediaOmxDecoder
|
||||
* This is to reduce the dependency of AudioOffloadPlayer in MediaOmxDecoder
|
||||
*/
|
||||
class AudioOffloadPlayerBase
|
||||
{
|
||||
typedef android::status_t status_t;
|
||||
typedef android::MediaSource MediaSource;
|
||||
|
||||
public:
|
||||
virtual ~AudioOffloadPlayerBase() {};
|
||||
|
||||
// Caller retains ownership of "aSource".
|
||||
virtual void SetSource(const android::sp<MediaSource> &aSource) {}
|
||||
|
||||
// Start the source if it's not already started and open the AudioSink to
|
||||
// create an offloaded audio track
|
||||
virtual status_t Start(bool aSourceAlreadyStarted = false)
|
||||
{
|
||||
return android::NO_INIT;
|
||||
}
|
||||
|
||||
virtual void ChangeState(MediaDecoder::PlayState aState) {}
|
||||
|
||||
virtual void SetVolume(double aVolume) {}
|
||||
|
||||
virtual double GetMediaTimeSecs() { return 0; }
|
||||
|
||||
// To update progress bar when the element is visible
|
||||
virtual void SetElementVisibility(bool aIsVisible) {}
|
||||
|
||||
// Update ready state based on current play state. Not checking data
|
||||
// availability since offloading is currently done only when whole compressed
|
||||
// data is available
|
||||
virtual MediaDecoderOwner::NextFrameStatus GetNextFrameStatus()
|
||||
{
|
||||
return MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // AUDIO_OFFLOAD_PLAYER_BASE_H_
|
223
content/media/omx/MediaOmxDecoder.cpp
Normal file → Executable file
223
content/media/omx/MediaOmxDecoder.cpp
Normal file → Executable file
@ -8,11 +8,33 @@
|
||||
#include "MediaOmxReader.h"
|
||||
#include "MediaDecoderStateMachine.h"
|
||||
|
||||
#include "OmxDecoder.h"
|
||||
|
||||
#ifdef MOZ_AUDIO_OFFLOAD
|
||||
#include "AudioOffloadPlayer.h"
|
||||
#endif
|
||||
|
||||
using namespace android;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
extern PRLogModuleInfo* gMediaDecoderLog;
|
||||
#define DECODER_LOG(type, msg) PR_LOG(gMediaDecoderLog, type, msg)
|
||||
#else
|
||||
#define DECODER_LOG(type, msg)
|
||||
#endif
|
||||
|
||||
MediaOmxDecoder::MediaOmxDecoder() :
|
||||
MediaDecoder()
|
||||
MediaDecoder(),
|
||||
mCanOffloadAudio(false),
|
||||
mFallbackToStateMachine(false)
|
||||
{
|
||||
#ifdef PR_LOGGING
|
||||
if (!gMediaDecoderLog) {
|
||||
gMediaDecoderLog = PR_NewLogModule("MediaDecoder");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
MediaDecoder* MediaOmxDecoder::Clone()
|
||||
@ -22,12 +44,205 @@ MediaDecoder* MediaOmxDecoder::Clone()
|
||||
|
||||
MediaDecoderStateMachine* MediaOmxDecoder::CreateStateMachine()
|
||||
{
|
||||
return new MediaDecoderStateMachine(this, new MediaOmxReader(this));
|
||||
mReader = new MediaOmxReader(this);
|
||||
mReader->SetAudioChannelType(GetAudioChannelType());
|
||||
return new MediaDecoderStateMachine(this, mReader);
|
||||
}
|
||||
|
||||
MediaOmxDecoder::~MediaOmxDecoder()
|
||||
void MediaOmxDecoder::SetCanOffloadAudio(bool aCanOffloadAudio)
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
|
||||
mCanOffloadAudio = aCanOffloadAudio;
|
||||
}
|
||||
|
||||
void MediaOmxDecoder::MetadataLoaded(int aChannels,
|
||||
int aRate,
|
||||
bool aHasAudio,
|
||||
bool aHasVideo,
|
||||
MetadataTags* aTags)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MediaDecoder::MetadataLoaded(aChannels, aRate, aHasAudio, aHasVideo, aTags);
|
||||
|
||||
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
|
||||
|
||||
if (!mCanOffloadAudio || mFallbackToStateMachine || mOutputStreams.Length() ||
|
||||
mInitialPlaybackRate != 1.0) {
|
||||
DECODER_LOG(PR_LOG_DEBUG, ("In %s Offload Audio check failed",
|
||||
__PRETTY_FUNCTION__));
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef MOZ_AUDIO_OFFLOAD
|
||||
mAudioOffloadPlayer = new AudioOffloadPlayer(this);
|
||||
#endif
|
||||
mAudioOffloadPlayer->SetSource(mReader->GetAudioOffloadTrack());
|
||||
status_t err = mAudioOffloadPlayer->Start(false);
|
||||
if (err == OK) {
|
||||
PauseStateMachine();
|
||||
// Call ChangeState() to run AudioOffloadPlayer since offload state enabled
|
||||
ChangeState(mPlayState);
|
||||
return;
|
||||
}
|
||||
|
||||
mAudioOffloadPlayer = nullptr;
|
||||
DECODER_LOG(PR_LOG_DEBUG, ("In %s Unable to start offload audio %d."
|
||||
"Switching to normal mode", __PRETTY_FUNCTION__, err));
|
||||
}
|
||||
|
||||
void MediaOmxDecoder::PauseStateMachine()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
GetReentrantMonitor().AssertCurrentThreadIn();
|
||||
DECODER_LOG(PR_LOG_DEBUG, ("%s", __PRETTY_FUNCTION__));
|
||||
|
||||
if (!mDecoderStateMachine) {
|
||||
return;
|
||||
}
|
||||
StopProgress();
|
||||
mDecoderStateMachine->SetDormant(true);
|
||||
}
|
||||
|
||||
void MediaOmxDecoder::ResumeStateMachine()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
GetReentrantMonitor().AssertCurrentThreadIn();
|
||||
DECODER_LOG(PR_LOG_DEBUG, ("%s current time %f", __PRETTY_FUNCTION__,
|
||||
mCurrentTime));
|
||||
|
||||
if (!mDecoderStateMachine) {
|
||||
return;
|
||||
}
|
||||
|
||||
mFallbackToStateMachine = true;
|
||||
mAudioOffloadPlayer = nullptr;
|
||||
mRequestedSeekTarget = SeekTarget(mCurrentTime, SeekTarget::Accurate);
|
||||
|
||||
mNextState = mPlayState;
|
||||
ChangeState(PLAY_STATE_LOADING);
|
||||
mDecoderStateMachine->SetDormant(false);
|
||||
}
|
||||
|
||||
void MediaOmxDecoder::AudioOffloadTearDown()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
PlaybackPositionChanged();
|
||||
DECODER_LOG(PR_LOG_DEBUG, ("%s", __PRETTY_FUNCTION__));
|
||||
{
|
||||
// Audio offload player sent tear down event. Fallback to state machine
|
||||
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
|
||||
ResumeStateMachine();
|
||||
}
|
||||
}
|
||||
|
||||
void MediaOmxDecoder::AddOutputStream(ProcessedMediaStream* aStream,
|
||||
bool aFinishWhenEnded)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
PlaybackPositionChanged();
|
||||
|
||||
if (mAudioOffloadPlayer) {
|
||||
// Offload player cannot handle MediaStream. Fallback
|
||||
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
|
||||
ResumeStateMachine();
|
||||
}
|
||||
|
||||
MediaDecoder::AddOutputStream(aStream, aFinishWhenEnded);
|
||||
}
|
||||
|
||||
void MediaOmxDecoder::SetPlaybackRate(double aPlaybackRate)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
PlaybackPositionChanged();
|
||||
|
||||
if (mAudioOffloadPlayer &&
|
||||
((aPlaybackRate != 0.0) || (aPlaybackRate != 1.0))) {
|
||||
// Offload player cannot handle playback rate other than 1/0. Fallback
|
||||
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
|
||||
ResumeStateMachine();
|
||||
}
|
||||
|
||||
MediaDecoder::SetPlaybackRate(aPlaybackRate);
|
||||
}
|
||||
|
||||
void MediaOmxDecoder::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) {
|
||||
mAudioOffloadPlayer->ChangeState(aState);
|
||||
}
|
||||
}
|
||||
|
||||
void MediaOmxDecoder::ApplyStateToStateMachine(PlayState aState)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
// During offload playback, state machine should be in dormant state.
|
||||
// ApplyStateToStateMachine() can change state machine state to
|
||||
// something else or reset the seek time. So don't call this when audio is
|
||||
// offloaded
|
||||
if (!mAudioOffloadPlayer) {
|
||||
MediaDecoder::ApplyStateToStateMachine(aState);
|
||||
}
|
||||
}
|
||||
|
||||
void MediaOmxDecoder::PlaybackPositionChanged()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (!mAudioOffloadPlayer) {
|
||||
MediaDecoder::PlaybackPositionChanged();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mOwner || mShuttingDown) {
|
||||
return;
|
||||
}
|
||||
|
||||
double lastTime = mCurrentTime;
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
|
||||
mCurrentTime = mAudioOffloadPlayer->GetMediaTimeSecs();
|
||||
}
|
||||
if (mOwner && lastTime != mCurrentTime) {
|
||||
FireTimeUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
void MediaOmxDecoder::SetElementVisibility(bool aIsVisible)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (mAudioOffloadPlayer) {
|
||||
mAudioOffloadPlayer->SetElementVisibility(aIsVisible);
|
||||
}
|
||||
}
|
||||
|
||||
void MediaOmxDecoder::UpdateReadyStateForData()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (!mAudioOffloadPlayer) {
|
||||
MediaDecoder::UpdateReadyStateForData();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mOwner || mShuttingDown)
|
||||
return;
|
||||
mOwner->UpdateReadyStateForData(mAudioOffloadPlayer->GetNextFrameStatus());
|
||||
}
|
||||
|
||||
void MediaOmxDecoder::SetVolume(double aVolume)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (!mAudioOffloadPlayer) {
|
||||
MediaDecoder::SetVolume(aVolume);
|
||||
return;
|
||||
}
|
||||
mAudioOffloadPlayer->SetVolume(aVolume);
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
|
43
content/media/omx/MediaOmxDecoder.h
Normal file → Executable file
43
content/media/omx/MediaOmxDecoder.h
Normal file → Executable file
@ -8,17 +8,56 @@
|
||||
|
||||
#include "base/basictypes.h"
|
||||
#include "MediaDecoder.h"
|
||||
#include "MediaOmxReader.h"
|
||||
#include "AudioOffloadPlayerBase.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class MediaOmxDecoder : public MediaDecoder
|
||||
{
|
||||
typedef android::MediaSource MediaSource;
|
||||
public:
|
||||
MediaOmxDecoder();
|
||||
~MediaOmxDecoder();
|
||||
|
||||
virtual MediaDecoder* Clone();
|
||||
virtual MediaDecoderStateMachine* CreateStateMachine();
|
||||
|
||||
virtual void MetadataLoaded(int aChannels,
|
||||
int aRate,
|
||||
bool aHasAudio,
|
||||
bool aHasVideo,
|
||||
MetadataTags* aTags);
|
||||
virtual void ChangeState(PlayState aState);
|
||||
virtual void ApplyStateToStateMachine(PlayState aState);
|
||||
virtual void SetVolume(double aVolume);
|
||||
virtual void PlaybackPositionChanged();
|
||||
virtual void UpdateReadyStateForData();
|
||||
virtual void SetElementVisibility(bool aIsVisible);
|
||||
virtual void SetCanOffloadAudio(bool aCanOffloadAudio);
|
||||
virtual void AddOutputStream(ProcessedMediaStream* aStream,
|
||||
bool aFinishWhenEnded);
|
||||
virtual void SetPlaybackRate(double aPlaybackRate);
|
||||
|
||||
void AudioOffloadTearDown();
|
||||
int64_t GetSeekTime() { return mRequestedSeekTarget.mTime; }
|
||||
void ResetSeekTime() { mRequestedSeekTarget.Reset(); }
|
||||
|
||||
private:
|
||||
void PauseStateMachine();
|
||||
void ResumeStateMachine();
|
||||
|
||||
MediaOmxReader* mReader;
|
||||
|
||||
// Offloaded audio track
|
||||
android::sp<MediaSource> mAudioTrack;
|
||||
|
||||
nsAutoPtr<AudioOffloadPlayerBase> mAudioOffloadPlayer;
|
||||
|
||||
// Set by MediaOmxReader to denote current track can be offloaded
|
||||
bool mCanOffloadAudio;
|
||||
|
||||
// Set when offload playback of current track fails in the middle and need to
|
||||
// fallback to state machine
|
||||
bool mFallbackToStateMachine;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -17,6 +17,12 @@
|
||||
#include "MPAPI.h"
|
||||
#include "gfx2DGlue.h"
|
||||
|
||||
#ifdef MOZ_AUDIO_OFFLOAD
|
||||
#include <stagefright/Utils.h>
|
||||
#include <cutils/properties.h>
|
||||
#include <stagefright/MetaData.h>
|
||||
#endif
|
||||
|
||||
#define MAX_DROPPED_FRAMES 25
|
||||
// Try not to spend more than this much time in a single call to DecodeVideoFrame.
|
||||
#define MAX_VIDEO_DECODE_SECONDS 3.0
|
||||
@ -26,14 +32,27 @@ using namespace android;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
extern PRLogModuleInfo* gMediaDecoderLog;
|
||||
#define DECODER_LOG(type, msg) PR_LOG(gMediaDecoderLog, type, msg)
|
||||
#else
|
||||
#define DECODER_LOG(type, msg)
|
||||
#endif
|
||||
|
||||
MediaOmxReader::MediaOmxReader(AbstractMediaDecoder *aDecoder) :
|
||||
MediaDecoderReader(aDecoder),
|
||||
mHasVideo(false),
|
||||
mHasAudio(false),
|
||||
mVideoSeekTimeUs(-1),
|
||||
mAudioSeekTimeUs(-1),
|
||||
mSkipCount(0)
|
||||
mSkipCount(0),
|
||||
mAudioChannelType(dom::AUDIO_CHANNEL_DEFAULT)
|
||||
{
|
||||
#ifdef PR_LOGGING
|
||||
if (!gMediaDecoderLog) {
|
||||
gMediaDecoderLog = PR_NewLogModule("MediaDecoder");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
MediaOmxReader::~MediaOmxReader()
|
||||
@ -124,6 +143,10 @@ nsresult MediaOmxReader::ReadMetadata(MediaInfo* aInfo,
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
#ifdef MOZ_AUDIO_OFFLOAD
|
||||
CheckAudioOffload();
|
||||
#endif
|
||||
|
||||
if (IsWaitingMediaResources()) {
|
||||
return NS_OK;
|
||||
}
|
||||
@ -391,5 +414,41 @@ void MediaOmxReader::SetActive() {
|
||||
NS_ASSERTION(result == NS_OK, "OmxDecoder should be in play state to continue decoding");
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
#ifdef MOZ_AUDIO_OFFLOAD
|
||||
void MediaOmxReader::CheckAudioOffload()
|
||||
{
|
||||
NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
|
||||
|
||||
char offloadProp[128];
|
||||
property_get("audio.offload.disable", offloadProp, "0");
|
||||
bool offloadDisable = atoi(offloadProp) != 0;
|
||||
if (offloadDisable) {
|
||||
return;
|
||||
}
|
||||
|
||||
mAudioOffloadTrack = mOmxDecoder->GetAudioOffloadTrack();
|
||||
sp<MetaData> meta = (mAudioOffloadTrack.get()) ?
|
||||
mAudioOffloadTrack->getFormat() : nullptr;
|
||||
|
||||
// Supporting audio offload only when there is no video, no streaming
|
||||
bool hasNoVideo = !mOmxDecoder->HasVideo();
|
||||
bool isNotStreaming
|
||||
= mDecoder->GetResource()->IsDataCachedToEndOfResource(0);
|
||||
|
||||
// Not much benefit in trying to offload other channel types. Most of them
|
||||
// aren't supported and also duration would be less than a minute
|
||||
bool isTypeMusic = mAudioChannelType == dom::AUDIO_CHANNEL_CONTENT;
|
||||
|
||||
DECODER_LOG(PR_LOG_DEBUG, ("%s meta %p, no video %d, no streaming %d,"
|
||||
" channel type %d", __FUNCTION__, meta.get(), hasNoVideo,
|
||||
isNotStreaming, mAudioChannelType));
|
||||
|
||||
if ((meta.get()) && hasNoVideo && isNotStreaming && isTypeMusic &&
|
||||
canOffloadStream(meta, false, false, AUDIO_STREAM_MUSIC)) {
|
||||
DECODER_LOG(PR_LOG_DEBUG, ("Can offload this audio stream"));
|
||||
mDecoder->SetCanOffloadAudio(true);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -9,7 +9,9 @@
|
||||
#include "MediaResource.h"
|
||||
#include "MediaDecoderReader.h"
|
||||
#include "nsRect.h"
|
||||
#include "AudioChannelCommon.h"
|
||||
#include <ui/GraphicBuffer.h>
|
||||
#include <stagefright/MediaSource.h>
|
||||
|
||||
namespace android {
|
||||
class OmxDecoder;
|
||||
@ -34,10 +36,11 @@ class MediaOmxReader : public MediaDecoderReader
|
||||
int64_t mVideoSeekTimeUs;
|
||||
int64_t mAudioSeekTimeUs;
|
||||
int32_t mSkipCount;
|
||||
dom::AudioChannelType mAudioChannelType;
|
||||
android::sp<android::MediaSource> mAudioOffloadTrack;
|
||||
|
||||
protected:
|
||||
android::sp<android::OmxDecoder> mOmxDecoder;
|
||||
|
||||
android::sp<android::MediaExtractor> mExtractor;
|
||||
|
||||
// Called by ReadMetadata() during MediaDecoderStateMachine::DecodeMetadata()
|
||||
@ -82,6 +85,21 @@ public:
|
||||
virtual void SetIdle() MOZ_OVERRIDE;
|
||||
virtual void SetActive() MOZ_OVERRIDE;
|
||||
|
||||
void SetAudioChannelType(dom::AudioChannelType aAudioChannelType) {
|
||||
mAudioChannelType = aAudioChannelType;
|
||||
}
|
||||
|
||||
android::sp<android::MediaSource> GetAudioOffloadTrack() {
|
||||
return mAudioOffloadTrack;
|
||||
}
|
||||
|
||||
#ifdef MOZ_AUDIO_OFFLOAD
|
||||
// Check whether it is possible to offload current audio track. This access
|
||||
// canOffloadStream() from libStageFright Utils.cpp, which is not there in
|
||||
// ANDROID_VERSION < 19
|
||||
void CheckAudioOffload();
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -362,6 +362,12 @@ bool OmxDecoder::Init(sp<MediaExtractor>& extractor) {
|
||||
|
||||
if (audioTrackIndex != -1) {
|
||||
mAudioTrack = extractor->getTrack(audioTrackIndex);
|
||||
|
||||
#ifdef MOZ_AUDIO_OFFLOAD
|
||||
// mAudioTrack is be used by OMXCodec. For offloaded audio track, using same
|
||||
// object gives undetermined behavior. So get a new track
|
||||
mAudioOffloadTrack = extractor->getTrack(audioTrackIndex);
|
||||
#endif
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -83,6 +83,7 @@ class OmxDecoder : public OMXCodecProxy::EventListener {
|
||||
sp<GonkNativeWindowClient> mNativeWindowClient;
|
||||
sp<MediaSource> mVideoTrack;
|
||||
sp<OMXCodecProxy> mVideoSource;
|
||||
sp<MediaSource> mAudioOffloadTrack;
|
||||
sp<MediaSource> mAudioTrack;
|
||||
sp<MediaSource> mAudioSource;
|
||||
int32_t mDisplayWidth;
|
||||
@ -244,6 +245,8 @@ public:
|
||||
|
||||
int64_t ProcessCachedData(int64_t aOffset, bool aWaitForCompletion);
|
||||
|
||||
sp<MediaSource> GetAudioOffloadTrack() { return mAudioOffloadTrack; }
|
||||
|
||||
static void RecycleCallback(TextureClient* aClient, void* aClosure);
|
||||
};
|
||||
|
||||
|
13
content/media/omx/moz.build
Normal file → Executable file
13
content/media/omx/moz.build
Normal file → Executable file
@ -5,6 +5,7 @@
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
EXPORTS += [
|
||||
'AudioOffloadPlayerBase.h',
|
||||
'MediaOmxDecoder.h',
|
||||
'MediaOmxReader.h',
|
||||
]
|
||||
@ -16,6 +17,17 @@ SOURCES += [
|
||||
'OmxDecoder.cpp',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_AUDIO_OFFLOAD']:
|
||||
EXPORTS += [
|
||||
'AudioOffloadPlayer.h',
|
||||
'AudioOutput.h',
|
||||
'AudioSink.h',
|
||||
]
|
||||
SOURCES += [
|
||||
'AudioOffloadPlayer.cpp',
|
||||
'AudioOutput.cpp',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_OMX_ENCODER']:
|
||||
EXPORTS += [
|
||||
'OMXCodecWrapper.h',
|
||||
@ -57,6 +69,7 @@ CXXFLAGS += [
|
||||
'frameworks/base/media/libstagefright/include',
|
||||
'frameworks/native/opengl/include',
|
||||
'frameworks/native/include',
|
||||
'hardware/libhardware/include/',
|
||||
]
|
||||
]
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user