gecko-dev/dom/media/omx/AudioOutput.cpp
Carsten "Tomcat" Book 5471309381 Backed out 14 changesets (bug 1165515) for linux x64 e10s m2 test failures
Backed out changeset d68dcf2ef372 (bug 1165515)
Backed out changeset 7c3b45a47811 (bug 1165515)
Backed out changeset b668b617bef2 (bug 1165515)
Backed out changeset d0916e1283a2 (bug 1165515)
Backed out changeset ac4dc7489942 (bug 1165515)
Backed out changeset e9632ce8bc65 (bug 1165515)
Backed out changeset c16d215cc7e4 (bug 1165515)
Backed out changeset e4d474f3c51a (bug 1165515)
Backed out changeset d87680bf9f7c (bug 1165515)
Backed out changeset b3c0a45ba99e (bug 1165515)
Backed out changeset 9370fa197674 (bug 1165515)
Backed out changeset 50970d668ca1 (bug 1165515)
Backed out changeset ffa4eb6d24b9 (bug 1165515)
Backed out changeset 5fcf1203cc1d (bug 1165515)

--HG--
extra : rebase_source : 6fb850d063cbabe738f97f0380302153e3eae97a
2015-06-02 13:05:56 +02:00

239 lines
5.9 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: */
/*
* Copyright (c) 2014 The Linux Foundation. All rights reserved.
* Copyright (C) 2008 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.
*/
#include <stagefright/foundation/ADebug.h>
#include "AudioOutput.h"
#include "mozilla/Logging.h"
namespace mozilla {
extern PRLogModuleInfo* gAudioOffloadPlayerLog;
#define AUDIO_OFFLOAD_LOG(type, msg) \
MOZ_LOG(gAudioOffloadPlayerLog, type, msg)
using namespace android;
AudioOutput::AudioOutput(int aSessionId, int aUid) :
mCallbackCookie(nullptr),
mCallback(nullptr),
mCallbackData(nullptr),
mUid(aUid),
mSessionId(aSessionId)
{
if (!gAudioOffloadPlayerLog) {
gAudioOffloadPlayerLog = PR_NewLogModule("AudioOffloadPlayer");
}
}
AudioOutput::~AudioOutput()
{
Close();
}
ssize_t AudioOutput::FrameSize() const
{
if (!mTrack.get()) {
return NO_INIT;
}
return mTrack->frameSize();
}
status_t AudioOutput::GetPosition(uint32_t *aPosition) const
{
if (!mTrack.get()) {
return NO_INIT;
}
return mTrack->getPosition(aPosition);
}
status_t AudioOutput::SetVolume(float aVolume) const
{
if (!mTrack.get()) {
return NO_INIT;
}
return mTrack->setVolume(aVolume);
}
status_t AudioOutput::SetParameters(const String8& aKeyValuePairs)
{
if (!mTrack.get()) {
return NO_INIT;
}
return mTrack->setParameters(aKeyValuePairs);
}
status_t AudioOutput::Open(uint32_t aSampleRate,
int aChannelCount,
audio_channel_mask_t aChannelMask,
audio_format_t aFormat,
AudioCallback aCb,
void* aCookie,
audio_output_flags_t aFlags,
const audio_offload_info_t *aOffloadInfo)
{
mCallback = aCb;
mCallbackCookie = aCookie;
if (((aFlags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) == 0) || !aCb ||
!aOffloadInfo) {
return BAD_VALUE;
}
AUDIO_OFFLOAD_LOG(PR_LOG_DEBUG, ("open(%u, %d, 0x%x, 0x%x, %d 0x%x)",
aSampleRate, aChannelCount, aChannelMask, aFormat, mSessionId, aFlags));
if (aChannelMask == CHANNEL_MASK_USE_CHANNEL_ORDER) {
aChannelMask = audio_channel_out_mask_from_count(aChannelCount);
if (0 == aChannelMask) {
AUDIO_OFFLOAD_LOG(PR_LOG_ERROR, ("open() error, can\'t derive mask for"
" %d audio channels", aChannelCount));
return NO_INIT;
}
}
sp<AudioTrack> t;
CallbackData* newcbd = new CallbackData(this);
t = new AudioTrack(
AUDIO_STREAM_MUSIC,
aSampleRate,
aFormat,
aChannelMask,
0, // Offloaded tracks will get frame count from AudioFlinger
aFlags,
CallbackWrapper,
newcbd,
0, // notification frames
mSessionId,
AudioTrack::TRANSFER_CALLBACK,
aOffloadInfo,
mUid);
if ((!t.get()) || (t->initCheck() != NO_ERROR)) {
AUDIO_OFFLOAD_LOG(PR_LOG_ERROR, ("Unable to create audio track"));
delete newcbd;
return NO_INIT;
}
mCallbackData = newcbd;
t->setVolume(1.0);
mTrack = t;
return NO_ERROR;
}
status_t AudioOutput::Start()
{
AUDIO_OFFLOAD_LOG(PR_LOG_DEBUG, ("%s", __PRETTY_FUNCTION__));
if (!mTrack.get()) {
return NO_INIT;
}
mTrack->setVolume(1.0);
return mTrack->start();
}
void AudioOutput::Stop()
{
AUDIO_OFFLOAD_LOG(PR_LOG_DEBUG, ("%s", __PRETTY_FUNCTION__));
if (mTrack.get()) {
mTrack->stop();
}
}
void AudioOutput::Flush()
{
if (mTrack.get()) {
mTrack->flush();
}
}
void AudioOutput::Pause()
{
if (mTrack.get()) {
mTrack->pause();
}
}
void AudioOutput::Close()
{
AUDIO_OFFLOAD_LOG(PR_LOG_DEBUG, ("%s", __PRETTY_FUNCTION__));
mTrack.clear();
delete mCallbackData;
mCallbackData = nullptr;
}
// static
void AudioOutput::CallbackWrapper(int aEvent, void* aCookie, void* aInfo)
{
CallbackData* data = (CallbackData*) aCookie;
data->Lock();
AudioOutput* me = data->GetOutput();
AudioTrack::Buffer* buffer = (AudioTrack::Buffer*) aInfo;
if (!me) {
// no output set, likely because the track was scheduled to be reused
// by another player, but the format turned out to be incompatible.
data->Unlock();
if (buffer) {
buffer->size = 0;
}
return;
}
switch(aEvent) {
case AudioTrack::EVENT_MORE_DATA: {
size_t actualSize = (*me->mCallback)(me, buffer->raw, buffer->size,
me->mCallbackCookie, CB_EVENT_FILL_BUFFER);
if (actualSize == 0 && buffer->size > 0) {
// We've reached EOS but the audio track is not stopped yet,
// keep playing silence.
memset(buffer->raw, 0, buffer->size);
actualSize = buffer->size;
}
buffer->size = actualSize;
} break;
case AudioTrack::EVENT_STREAM_END:
AUDIO_OFFLOAD_LOG(PR_LOG_DEBUG, ("Callback wrapper: EVENT_STREAM_END"));
(*me->mCallback)(me, nullptr /* buffer */, 0 /* size */,
me->mCallbackCookie, CB_EVENT_STREAM_END);
break;
case AudioTrack::EVENT_NEW_IAUDIOTRACK :
AUDIO_OFFLOAD_LOG(PR_LOG_DEBUG, ("Callback wrapper: EVENT_TEAR_DOWN"));
(*me->mCallback)(me, nullptr /* buffer */, 0 /* size */,
me->mCallbackCookie, CB_EVENT_TEAR_DOWN);
break;
default:
AUDIO_OFFLOAD_LOG(PR_LOG_DEBUG, ("received unknown event type: %d in"
" Callback wrapper!", aEvent));
break;
}
data->Unlock();
}
} // namespace mozilla