1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/content/media/omx/AudioOffloadPlayer.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,265 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* vim:set ts=2 sw=2 sts=2 et cindent: */ 1.6 +/* 1.7 + * Copyright (c) 2014 The Linux Foundation. All rights reserved. 1.8 + * Copyright (C) 2009 The Android Open Source Project 1.9 + * 1.10 + * Licensed under the Apache License, Version 2.0 (the "License"); 1.11 + * you may not use this file except in compliance with the License. 1.12 + * You may obtain a copy of the License at 1.13 + * 1.14 + * http://www.apache.org/licenses/LICENSE-2.0 1.15 + * 1.16 + * Unless required by applicable law or agreed to in writing, software 1.17 + * distributed under the License is distributed on an "AS IS" BASIS, 1.18 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1.19 + * See the License for the specific language governing permissions and 1.20 + * limitations under the License. 1.21 + */ 1.22 + 1.23 +#ifndef AUDIO_OFFLOAD_PLAYER_H_ 1.24 +#define AUDIO_OFFLOAD_PLAYER_H_ 1.25 + 1.26 +#include <stagefright/MediaBuffer.h> 1.27 +#include <stagefright/MediaSource.h> 1.28 +#include <stagefright/TimeSource.h> 1.29 +#include <utils/threads.h> 1.30 +#include <utils/RefBase.h> 1.31 + 1.32 +#include "AudioOutput.h" 1.33 + 1.34 +#include "MediaDecoderOwner.h" 1.35 +#include "MediaOmxDecoder.h" 1.36 + 1.37 +namespace mozilla { 1.38 + 1.39 +class MediaOmxDecoder; 1.40 + 1.41 +/** 1.42 + * AudioOffloadPlayer adds support for audio tunneling to a digital signal 1.43 + * processor (DSP) in the device chipset. With tunneling, audio decoding is 1.44 + * off-loaded to the DSP, waking the application processor less often and using 1.45 + * less battery 1.46 + * 1.47 + * This depends on offloading capability provided by Android KK AudioTrack class 1.48 + * 1.49 + * Audio playback is based on pull mechanism, whenever audio sink needs 1.50 + * data, FillBuffer() will read data from compressed audio source and provide 1.51 + * it to the sink 1.52 + * 1.53 + * Also this class passes state changes (play/pause/seek) from MediaOmxDecoder 1.54 + * to AudioSink as well as provide AudioSink status (position changed, 1.55 + * playback ended, seek complete, audio tear down) back to MediaOmxDecoder 1.56 + * 1.57 + * It acts as a bridge between MediaOmxDecoder and AudioSink during 1.58 + * offload playback 1.59 + */ 1.60 + 1.61 +class AudioOffloadPlayer : public AudioOffloadPlayerBase 1.62 +{ 1.63 + typedef android::Mutex Mutex; 1.64 + typedef android::MetaData MetaData; 1.65 + typedef android::status_t status_t; 1.66 + typedef android::AudioTrack AudioTrack; 1.67 + typedef android::MediaBuffer MediaBuffer; 1.68 + typedef android::MediaSource MediaSource; 1.69 + 1.70 +public: 1.71 + enum { 1.72 + REACHED_EOS, 1.73 + SEEK_COMPLETE 1.74 + }; 1.75 + 1.76 + AudioOffloadPlayer(MediaOmxDecoder* aDecoder = nullptr); 1.77 + 1.78 + ~AudioOffloadPlayer(); 1.79 + 1.80 + // Caller retains ownership of "aSource". 1.81 + void SetSource(const android::sp<MediaSource> &aSource); 1.82 + 1.83 + // Start the source if it's not already started and open the AudioSink to 1.84 + // create an offloaded audio track 1.85 + status_t Start(bool aSourceAlreadyStarted = false); 1.86 + 1.87 + double GetMediaTimeSecs(); 1.88 + 1.89 + // To update progress bar when the element is visible 1.90 + void SetElementVisibility(bool aIsVisible); 1.91 + 1.92 + status_t ChangeState(MediaDecoder::PlayState aState); 1.93 + 1.94 + void SetVolume(double aVolume); 1.95 + 1.96 + // Update ready state based on current play state. Not checking data 1.97 + // availability since offloading is currently done only when whole compressed 1.98 + // data is available 1.99 + MediaDecoderOwner::NextFrameStatus GetNextFrameStatus(); 1.100 + 1.101 + void TimeUpdate(); 1.102 + 1.103 + // Close the audio sink, stop time updates, frees the input buffers 1.104 + void Reset(); 1.105 + 1.106 +private: 1.107 + // Set when audio source is started and audioSink is initialized 1.108 + // Used only in main thread 1.109 + bool mStarted; 1.110 + 1.111 + // Set when audio sink is started. i.e. playback started 1.112 + // Used only in main thread 1.113 + bool mPlaying; 1.114 + 1.115 + // Set when playstate is seeking and reset when FillBUffer() acknowledged 1.116 + // seeking by seeking audio source. Used in main thread and offload 1.117 + // callback thread, protected by Mutex mLock 1.118 + bool mSeeking; 1.119 + 1.120 + // Once playback reached end of stream (last ~100ms), position provided by DSP 1.121 + // may be reset/corrupted. This bool is used to avoid that. 1.122 + // Used in main thread and offload callback thread, protected by Mutex 1.123 + // mLock 1.124 + bool mReachedEOS; 1.125 + 1.126 + // Set when there is a seek request during pause. 1.127 + // Used in main thread and offload callback thread, protected by Mutex 1.128 + // mLock 1.129 + bool mSeekDuringPause; 1.130 + 1.131 + // Seek can be triggered internally or by MediaDecoder. This bool is to 1.132 + // to track seek triggered by MediaDecoder so that we can send back 1.133 + // SeekingStarted and SeekingStopped events. 1.134 + // Used in main thread and offload callback thread, protected by Mutex mLock 1.135 + bool mDispatchSeekEvents; 1.136 + 1.137 + // Set when the HTML Audio Element is visible to the user. 1.138 + // Used only in main thread 1.139 + bool mIsElementVisible; 1.140 + 1.141 + // Session id given by Android::AudioSystem and used while creating audio sink 1.142 + // Used only in main thread 1.143 + int mSessionId; 1.144 + 1.145 + // Sample rate of current audio track. Used only in main thread 1.146 + int mSampleRate; 1.147 + 1.148 + // After seeking, positions returned by offlaoded tracks (DSP) will be 1.149 + // relative to the seeked position. And seeked position may be slightly 1.150 + // different than given mSeekTimeUs, if audio source cannot find a frame at 1.151 + // that position. Store seeked position in mStartPosUs and provide 1.152 + // mStartPosUs + GetPosition() (i.e. absolute position) to MediaOmxDecoder 1.153 + // Used in main thread and offload callback thread, protected by Mutex 1.154 + // mLock 1.155 + int64_t mStartPosUs; 1.156 + 1.157 + // Given seek time when there is a request to seek 1.158 + // Used in main thread and offload callback thread, protected by Mutex 1.159 + // mLock 1.160 + int64_t mSeekTimeUs; 1.161 + 1.162 + // Positions obtained from offlaoded tracks (DSP) 1.163 + // Used in main thread and offload callback thread, protected by Mutex 1.164 + // mLock 1.165 + int64_t mPositionTimeMediaUs; 1.166 + 1.167 + // State obtained from MediaOmxDecoder. Used only in main thread 1.168 + MediaDecoder::PlayState mPlayState; 1.169 + 1.170 + // Protect accessing audio position related variables between main thread and 1.171 + // offload callback thread 1.172 + Mutex mLock; 1.173 + 1.174 + // Compressed audio source. 1.175 + // Used in main thread first and later in offload callback thread 1.176 + android::sp<MediaSource> mSource; 1.177 + 1.178 + // Audio sink wrapper to access offloaded audio tracks 1.179 + // Used in main thread and offload callback thread 1.180 + // Race conditions are protected in underlying Android::AudioTrack class 1.181 + android::sp<AudioSink> mAudioSink; 1.182 + 1.183 + // Buffer used to get date from audio source. Used in offload callback thread 1.184 + MediaBuffer* mInputBuffer; 1.185 + 1.186 + // MediaOmxDecoder object used mainly to notify the audio sink status 1.187 + MediaOmxDecoder* mObserver; 1.188 + 1.189 + TimeStamp mLastFireUpdateTime; 1.190 + 1.191 + // Timer to trigger position changed events 1.192 + nsCOMPtr<nsITimer> mTimeUpdateTimer; 1.193 + 1.194 + // Timer to reset AudioSink when audio is paused for OFFLOAD_PAUSE_MAX_USECS. 1.195 + // It is triggered in Pause() and canceled when there is a Play() within 1.196 + // OFFLOAD_PAUSE_MAX_USECS. Used only from main thread so no lock is needed. 1.197 + nsCOMPtr<nsITimer> mResetTimer; 1.198 + 1.199 + int64_t GetMediaTimeUs(); 1.200 + 1.201 + // Provide the playback position in microseconds from total number of 1.202 + // frames played by audio track 1.203 + int64_t GetOutputPlayPositionUs_l() const; 1.204 + 1.205 + // Fill the buffer given by audio sink with data from compressed audio 1.206 + // source. Also handles the seek by seeking audio source and stop the sink in 1.207 + // case of error 1.208 + size_t FillBuffer(void *aData, size_t aSize); 1.209 + 1.210 + // Called by AudioSink when it needs data, to notify EOS or tear down event 1.211 + static size_t AudioSinkCallback(AudioSink *aAudioSink, 1.212 + void *aData, 1.213 + size_t aSize, 1.214 + void *aMe, 1.215 + AudioSink::cb_event_t aEvent); 1.216 + 1.217 + bool IsSeeking(); 1.218 + 1.219 + // Set mSeekTime to the given position and restart the sink. Actual seek 1.220 + // happens in FillBuffer(). If aDispatchSeekEvents is true, send 1.221 + // SeekingStarted event always and SeekingStopped event when the play state is 1.222 + // paused to MediaDecoder. 1.223 + // When decoding and playing happens separately, if there is a seek during 1.224 + // pause, we can decode and keep data ready. 1.225 + // In case of offload player, no way to seek during pause. So just fake that 1.226 + // seek is done. 1.227 + status_t SeekTo(int64_t aTimeUs, bool aDispatchSeekEvents = false); 1.228 + 1.229 + // Start/Resume the audio sink so that callback will start being called to get 1.230 + // compressed data 1.231 + status_t Play(); 1.232 + 1.233 + // Stop the audio sink if we need to play till we drain the current buffer. 1.234 + // or Pause the sink in case we should stop playing immediately 1.235 + void Pause(bool aPlayPendingSamples = false); 1.236 + 1.237 + // When audio is offloaded, application processor wakes up less frequently 1.238 + // (>1sec) But when Player UI is visible we need to update progress bar 1.239 + // atleast once in 250ms. Start a timer when player UI becomes visible or 1.240 + // audio starts playing to send PlaybackPositionChanged events once in 250ms. 1.241 + // Stop the timer when UI goes invisible or play state is not playing. 1.242 + // Also make sure timer functions are always called from main thread 1.243 + nsresult StartTimeUpdate(); 1.244 + nsresult StopTimeUpdate(); 1.245 + 1.246 + // Notify end of stream by sending PlaybackEnded event to observer 1.247 + // (i.e.MediaDecoder) 1.248 + void NotifyAudioEOS(); 1.249 + 1.250 + // Notify position changed event by sending PlaybackPositionChanged event to 1.251 + // observer 1.252 + void NotifyPositionChanged(); 1.253 + 1.254 + // Offloaded audio track is invalidated due to usecase change. Notify 1.255 + // MediaDecoder to re-evaluate offloading options 1.256 + void NotifyAudioTearDown(); 1.257 + 1.258 + // Send information from MetaData to the HAL via AudioSink 1.259 + void SendMetaDataToHal(android::sp<AudioSink>& aSink, 1.260 + const android::sp<MetaData>& aMeta); 1.261 + 1.262 + AudioOffloadPlayer(const AudioOffloadPlayer &); 1.263 + AudioOffloadPlayer &operator=(const AudioOffloadPlayer &); 1.264 +}; 1.265 + 1.266 +} // namespace mozilla 1.267 + 1.268 +#endif // AUDIO_OFFLOAD_PLAYER_H_