xref: /aosp_15_r20/frameworks/av/media/libaudioclient/TrackPlayerBase.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
1*ec779b8eSAndroid Build Coastguard Worker /*
2*ec779b8eSAndroid Build Coastguard Worker  * Copyright (C) 2017 The Android Open Source Project
3*ec779b8eSAndroid Build Coastguard Worker  *
4*ec779b8eSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*ec779b8eSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*ec779b8eSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*ec779b8eSAndroid Build Coastguard Worker  *
8*ec779b8eSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*ec779b8eSAndroid Build Coastguard Worker  *
10*ec779b8eSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*ec779b8eSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*ec779b8eSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*ec779b8eSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*ec779b8eSAndroid Build Coastguard Worker  * limitations under the License.
15*ec779b8eSAndroid Build Coastguard Worker  */
16*ec779b8eSAndroid Build Coastguard Worker 
17*ec779b8eSAndroid Build Coastguard Worker #include <media/TrackPlayerBase.h>
18*ec779b8eSAndroid Build Coastguard Worker 
19*ec779b8eSAndroid Build Coastguard Worker namespace android {
20*ec779b8eSAndroid Build Coastguard Worker using aidl_utils::binderStatusFromStatusT;
21*ec779b8eSAndroid Build Coastguard Worker using media::VolumeShaper;
22*ec779b8eSAndroid Build Coastguard Worker 
23*ec779b8eSAndroid Build Coastguard Worker //--------------------------------------------------------------------------------------------------
TrackPlayerBase()24*ec779b8eSAndroid Build Coastguard Worker TrackPlayerBase::TrackPlayerBase() : PlayerBase(),
25*ec779b8eSAndroid Build Coastguard Worker         mPlayerVolumeL(1.0f), mPlayerVolumeR(1.0f)
26*ec779b8eSAndroid Build Coastguard Worker {
27*ec779b8eSAndroid Build Coastguard Worker     ALOGD("TrackPlayerBase::TrackPlayerBase()");
28*ec779b8eSAndroid Build Coastguard Worker }
29*ec779b8eSAndroid Build Coastguard Worker 
30*ec779b8eSAndroid Build Coastguard Worker 
~TrackPlayerBase()31*ec779b8eSAndroid Build Coastguard Worker TrackPlayerBase::~TrackPlayerBase() {
32*ec779b8eSAndroid Build Coastguard Worker     ALOGD("TrackPlayerBase::~TrackPlayerBase()");
33*ec779b8eSAndroid Build Coastguard Worker     doDestroy();
34*ec779b8eSAndroid Build Coastguard Worker }
35*ec779b8eSAndroid Build Coastguard Worker 
init(const sp<AudioTrack> & pat,const sp<AudioTrack::IAudioTrackCallback> & callback,player_type_t playerType,audio_usage_t usage,audio_session_t sessionId)36*ec779b8eSAndroid Build Coastguard Worker void TrackPlayerBase::init(const sp<AudioTrack>& pat,
37*ec779b8eSAndroid Build Coastguard Worker                            const sp<AudioTrack::IAudioTrackCallback>& callback,
38*ec779b8eSAndroid Build Coastguard Worker                            player_type_t playerType, audio_usage_t usage,
39*ec779b8eSAndroid Build Coastguard Worker                            audio_session_t sessionId) {
40*ec779b8eSAndroid Build Coastguard Worker     PlayerBase::init(playerType, usage, sessionId);
41*ec779b8eSAndroid Build Coastguard Worker     mAudioTrack.store(pat);
42*ec779b8eSAndroid Build Coastguard Worker     if (pat != 0) {
43*ec779b8eSAndroid Build Coastguard Worker         mCallbackHandle = callback;
44*ec779b8eSAndroid Build Coastguard Worker         mSelfAudioDeviceCallback = new SelfAudioDeviceCallback(*this);
45*ec779b8eSAndroid Build Coastguard Worker         pat->addAudioDeviceCallback(mSelfAudioDeviceCallback);
46*ec779b8eSAndroid Build Coastguard Worker         pat->setPlayerIId(mPIId);  // set in PlayerBase::init().
47*ec779b8eSAndroid Build Coastguard Worker     }
48*ec779b8eSAndroid Build Coastguard Worker }
49*ec779b8eSAndroid Build Coastguard Worker 
destroy()50*ec779b8eSAndroid Build Coastguard Worker void TrackPlayerBase::destroy() {
51*ec779b8eSAndroid Build Coastguard Worker     doDestroy();
52*ec779b8eSAndroid Build Coastguard Worker     baseDestroy();
53*ec779b8eSAndroid Build Coastguard Worker }
54*ec779b8eSAndroid Build Coastguard Worker 
SelfAudioDeviceCallback(PlayerBase & self)55*ec779b8eSAndroid Build Coastguard Worker TrackPlayerBase::SelfAudioDeviceCallback::SelfAudioDeviceCallback(PlayerBase& self) :
56*ec779b8eSAndroid Build Coastguard Worker     AudioSystem::AudioDeviceCallback(), mSelf(self) {
57*ec779b8eSAndroid Build Coastguard Worker }
58*ec779b8eSAndroid Build Coastguard Worker 
~SelfAudioDeviceCallback()59*ec779b8eSAndroid Build Coastguard Worker TrackPlayerBase::SelfAudioDeviceCallback::~SelfAudioDeviceCallback() {
60*ec779b8eSAndroid Build Coastguard Worker }
61*ec779b8eSAndroid Build Coastguard Worker 
onAudioDeviceUpdate(audio_io_handle_t __unused,const DeviceIdVector & deviceIds)62*ec779b8eSAndroid Build Coastguard Worker void TrackPlayerBase::SelfAudioDeviceCallback::onAudioDeviceUpdate(audio_io_handle_t __unused,
63*ec779b8eSAndroid Build Coastguard Worker         const DeviceIdVector& deviceIds) {
64*ec779b8eSAndroid Build Coastguard Worker     mSelf.baseUpdateDeviceIds(deviceIds);
65*ec779b8eSAndroid Build Coastguard Worker }
66*ec779b8eSAndroid Build Coastguard Worker 
doDestroy()67*ec779b8eSAndroid Build Coastguard Worker void TrackPlayerBase::doDestroy() {
68*ec779b8eSAndroid Build Coastguard Worker     sp<AudioTrack> audioTrack = getAudioTrack();
69*ec779b8eSAndroid Build Coastguard Worker 
70*ec779b8eSAndroid Build Coastguard Worker     // Note that there may still be another reference in post-unlock phase of SetPlayState
71*ec779b8eSAndroid Build Coastguard Worker     clearAudioTrack();
72*ec779b8eSAndroid Build Coastguard Worker 
73*ec779b8eSAndroid Build Coastguard Worker     if (audioTrack != 0) {
74*ec779b8eSAndroid Build Coastguard Worker         audioTrack->stop();
75*ec779b8eSAndroid Build Coastguard Worker         audioTrack->removeAudioDeviceCallback(mSelfAudioDeviceCallback);
76*ec779b8eSAndroid Build Coastguard Worker         mSelfAudioDeviceCallback.clear();
77*ec779b8eSAndroid Build Coastguard Worker     }
78*ec779b8eSAndroid Build Coastguard Worker }
79*ec779b8eSAndroid Build Coastguard Worker 
setPlayerVolume(float vl,float vr)80*ec779b8eSAndroid Build Coastguard Worker void TrackPlayerBase::setPlayerVolume(float vl, float vr) {
81*ec779b8eSAndroid Build Coastguard Worker     {
82*ec779b8eSAndroid Build Coastguard Worker         Mutex::Autolock _l(mSettingsLock);
83*ec779b8eSAndroid Build Coastguard Worker         mPlayerVolumeL = vl;
84*ec779b8eSAndroid Build Coastguard Worker         mPlayerVolumeR = vr;
85*ec779b8eSAndroid Build Coastguard Worker     }
86*ec779b8eSAndroid Build Coastguard Worker     doSetVolume();
87*ec779b8eSAndroid Build Coastguard Worker }
88*ec779b8eSAndroid Build Coastguard Worker 
89*ec779b8eSAndroid Build Coastguard Worker //------------------------------------------------------------------------------
90*ec779b8eSAndroid Build Coastguard Worker // Implementation of IPlayer
playerStart()91*ec779b8eSAndroid Build Coastguard Worker status_t TrackPlayerBase::playerStart() {
92*ec779b8eSAndroid Build Coastguard Worker     status_t status = NO_INIT;
93*ec779b8eSAndroid Build Coastguard Worker     if (sp<AudioTrack> audioTrack = getAudioTrack(); audioTrack != 0) {
94*ec779b8eSAndroid Build Coastguard Worker         status = audioTrack->start();
95*ec779b8eSAndroid Build Coastguard Worker     }
96*ec779b8eSAndroid Build Coastguard Worker     return status;
97*ec779b8eSAndroid Build Coastguard Worker }
98*ec779b8eSAndroid Build Coastguard Worker 
playerPause()99*ec779b8eSAndroid Build Coastguard Worker status_t TrackPlayerBase::playerPause() {
100*ec779b8eSAndroid Build Coastguard Worker     status_t status = NO_INIT;
101*ec779b8eSAndroid Build Coastguard Worker     if (sp<AudioTrack> audioTrack = getAudioTrack(); audioTrack != 0) {
102*ec779b8eSAndroid Build Coastguard Worker         audioTrack->pause();
103*ec779b8eSAndroid Build Coastguard Worker         status = NO_ERROR;
104*ec779b8eSAndroid Build Coastguard Worker     }
105*ec779b8eSAndroid Build Coastguard Worker     return status;
106*ec779b8eSAndroid Build Coastguard Worker }
107*ec779b8eSAndroid Build Coastguard Worker 
108*ec779b8eSAndroid Build Coastguard Worker 
playerStop()109*ec779b8eSAndroid Build Coastguard Worker status_t TrackPlayerBase::playerStop() {
110*ec779b8eSAndroid Build Coastguard Worker     status_t status = NO_INIT;
111*ec779b8eSAndroid Build Coastguard Worker     if (sp<AudioTrack> audioTrack = getAudioTrack(); audioTrack != 0) {
112*ec779b8eSAndroid Build Coastguard Worker         audioTrack->stop();
113*ec779b8eSAndroid Build Coastguard Worker         status = NO_ERROR;
114*ec779b8eSAndroid Build Coastguard Worker     }
115*ec779b8eSAndroid Build Coastguard Worker     return status;
116*ec779b8eSAndroid Build Coastguard Worker }
117*ec779b8eSAndroid Build Coastguard Worker 
playerSetVolume()118*ec779b8eSAndroid Build Coastguard Worker status_t TrackPlayerBase::playerSetVolume() {
119*ec779b8eSAndroid Build Coastguard Worker     return doSetVolume();
120*ec779b8eSAndroid Build Coastguard Worker }
121*ec779b8eSAndroid Build Coastguard Worker 
doSetVolume()122*ec779b8eSAndroid Build Coastguard Worker status_t TrackPlayerBase::doSetVolume() {
123*ec779b8eSAndroid Build Coastguard Worker     status_t status = NO_INIT;
124*ec779b8eSAndroid Build Coastguard Worker     if (sp<AudioTrack> audioTrack = getAudioTrack(); audioTrack != 0) {
125*ec779b8eSAndroid Build Coastguard Worker         float tl = mPlayerVolumeL * mPanMultiplierL * mVolumeMultiplierL;
126*ec779b8eSAndroid Build Coastguard Worker         float tr = mPlayerVolumeR * mPanMultiplierR * mVolumeMultiplierR;
127*ec779b8eSAndroid Build Coastguard Worker         audioTrack->setVolume(tl, tr);
128*ec779b8eSAndroid Build Coastguard Worker         status = NO_ERROR;
129*ec779b8eSAndroid Build Coastguard Worker     }
130*ec779b8eSAndroid Build Coastguard Worker     return status;
131*ec779b8eSAndroid Build Coastguard Worker }
132*ec779b8eSAndroid Build Coastguard Worker 
133*ec779b8eSAndroid Build Coastguard Worker 
applyVolumeShaper(const media::VolumeShaperConfiguration & configuration,const media::VolumeShaperOperation & operation)134*ec779b8eSAndroid Build Coastguard Worker binder::Status TrackPlayerBase::applyVolumeShaper(
135*ec779b8eSAndroid Build Coastguard Worker         const media::VolumeShaperConfiguration& configuration,
136*ec779b8eSAndroid Build Coastguard Worker         const media::VolumeShaperOperation& operation) {
137*ec779b8eSAndroid Build Coastguard Worker 
138*ec779b8eSAndroid Build Coastguard Worker     sp<VolumeShaper::Configuration> spConfiguration = new VolumeShaper::Configuration();
139*ec779b8eSAndroid Build Coastguard Worker     sp<VolumeShaper::Operation> spOperation = new VolumeShaper::Operation();
140*ec779b8eSAndroid Build Coastguard Worker 
141*ec779b8eSAndroid Build Coastguard Worker     status_t s = spConfiguration->readFromParcelable(configuration)
142*ec779b8eSAndroid Build Coastguard Worker             ?: spOperation->readFromParcelable(operation);
143*ec779b8eSAndroid Build Coastguard Worker     if (s != OK) {
144*ec779b8eSAndroid Build Coastguard Worker         return binderStatusFromStatusT(s);
145*ec779b8eSAndroid Build Coastguard Worker     }
146*ec779b8eSAndroid Build Coastguard Worker     if (sp<AudioTrack> audioTrack = getAudioTrack(); audioTrack != 0) {
147*ec779b8eSAndroid Build Coastguard Worker         ALOGD("TrackPlayerBase::applyVolumeShaper() from IPlayer");
148*ec779b8eSAndroid Build Coastguard Worker         VolumeShaper::Status status = audioTrack->applyVolumeShaper(spConfiguration, spOperation);
149*ec779b8eSAndroid Build Coastguard Worker         if (status < 0) { // a non-negative value is the volume shaper id.
150*ec779b8eSAndroid Build Coastguard Worker             ALOGE("TrackPlayerBase::applyVolumeShaper() failed with status %d", status);
151*ec779b8eSAndroid Build Coastguard Worker         }
152*ec779b8eSAndroid Build Coastguard Worker         return binderStatusFromStatusT(status);
153*ec779b8eSAndroid Build Coastguard Worker     } else {
154*ec779b8eSAndroid Build Coastguard Worker         ALOGD("TrackPlayerBase::applyVolumeShaper()"
155*ec779b8eSAndroid Build Coastguard Worker               " no AudioTrack for volume control from IPlayer");
156*ec779b8eSAndroid Build Coastguard Worker         return binder::Status::ok();
157*ec779b8eSAndroid Build Coastguard Worker     }
158*ec779b8eSAndroid Build Coastguard Worker }
159*ec779b8eSAndroid Build Coastguard Worker 
160*ec779b8eSAndroid Build Coastguard Worker } // namespace android
161