• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.tv.tuner.exoplayer.ac3;
18 
19 import android.media.MediaFormat;
20 
21 import com.google.android.exoplayer.audio.AudioTrack;
22 
23 import java.nio.ByteBuffer;
24 
25 /**
26  * {@link AudioTrack} wrapper class for trickplay operations including FF/RW.
27  * FF/RW trickplay operations do not need framework {@link AudioTrack}.
28  * This wrapper class will do nothing in disabled status for those operations.
29  */
30 public class AudioTrackWrapper {
31     private final AudioTrack mAudioTrack = new AudioTrack();
32     private int mAudioSessionID;
33     private boolean mIsEnabled;
34 
AudioTrackWrapper()35     AudioTrackWrapper() {
36         mIsEnabled = true;
37     }
38 
resetSessionId()39     public void resetSessionId() {
40         mAudioSessionID = AudioTrack.SESSION_ID_NOT_SET;
41     }
42 
isInitialized()43     public boolean isInitialized() {
44         return mIsEnabled && mAudioTrack.isInitialized();
45     }
46 
restart()47     public void restart() {
48         if (mAudioTrack.isInitialized()) {
49             mAudioTrack.release();
50         }
51         mIsEnabled = true;
52         resetSessionId();
53     }
54 
release()55     public void release()  {
56         if (mAudioSessionID != AudioTrack.SESSION_ID_NOT_SET) {
57             mAudioTrack.release();
58         }
59     }
60 
initialize()61     public void initialize() throws AudioTrack.InitializationException {
62         if (!mIsEnabled) {
63             return;
64         }
65         if (mAudioSessionID != AudioTrack.SESSION_ID_NOT_SET) {
66             mAudioTrack.initialize(mAudioSessionID);
67         } else {
68             mAudioSessionID = mAudioTrack.initialize();
69         }
70     }
71 
reset()72     public void reset() {
73         if (!mIsEnabled) {
74             return;
75         }
76         mAudioTrack.reset();
77     }
78 
isEnded()79     public boolean isEnded() {
80         return !mIsEnabled || !mAudioTrack.hasPendingData();
81     }
82 
isReady()83     public boolean isReady() {
84         // In the case of not playing actual audio data, Audio track is always ready.
85         return !mIsEnabled || mAudioTrack.hasPendingData();
86     }
87 
play()88     public void play() {
89         if (!mIsEnabled) {
90             return;
91         }
92         mAudioTrack.play();
93     }
94 
pause()95     public void pause() {
96         if (!mIsEnabled) {
97             return;
98         }
99         mAudioTrack.pause();
100     }
101 
setVolume(float volume)102     public void setVolume(float volume) {
103         if (!mIsEnabled) {
104             return;
105         }
106         mAudioTrack.setVolume(volume);
107     }
108 
reconfigure(MediaFormat format)109     public void reconfigure(MediaFormat format) {
110         if (!mIsEnabled || format == null) {
111             return;
112         }
113         String mimeType = format.getString(MediaFormat.KEY_MIME);
114         int channelCount = format.getInteger(MediaFormat.KEY_CHANNEL_COUNT);
115         int sampleRate = format.getInteger(MediaFormat.KEY_SAMPLE_RATE);
116         int pcmEncoding;
117         try {
118             pcmEncoding = format.getInteger(MediaFormat.KEY_PCM_ENCODING);
119         } catch (Exception e) {
120             pcmEncoding = com.google.android.exoplayer.MediaFormat.NO_VALUE;
121         }
122         // TODO: Handle non-AC3 or non-passthrough audio.
123         if (MediaFormat.MIMETYPE_AUDIO_AC3.equalsIgnoreCase(mimeType) && channelCount != 2) {
124             // Workarounds b/25955476.
125             // Since all devices and platforms does not support passthrough for non-stereo AC3,
126             // It is safe to fake non-stereo AC3 as AC3 stereo which is default passthrough mode.
127             // In other words, the channel count should be always 2.
128             channelCount = 2;
129         }
130         mAudioTrack.configure(mimeType, channelCount, sampleRate, pcmEncoding);
131     }
132 
handleDiscontinuity()133     public void handleDiscontinuity() {
134         if (!mIsEnabled) {
135             return;
136         }
137         mAudioTrack.handleDiscontinuity();
138     }
139 
handleBuffer(ByteBuffer buffer, int offset, int size, long presentationTimeUs)140     public int handleBuffer(ByteBuffer buffer, int offset, int size, long presentationTimeUs)
141             throws AudioTrack.WriteException {
142         if (!mIsEnabled) {
143             return AudioTrack.RESULT_BUFFER_CONSUMED;
144         }
145         return mAudioTrack.handleBuffer(buffer, offset, size, presentationTimeUs);
146     }
147 
setStatus(boolean enable)148     public void setStatus(boolean enable) {
149         if (enable == mIsEnabled) {
150             return;
151         }
152         mAudioTrack.reset();
153         mIsEnabled = enable;
154     }
155 
isEnabled()156     public boolean isEnabled() {
157         return mIsEnabled;
158     }
159 
160     // This should be used only in case of being enabled.
getCurrentPositionUs(boolean isEnded)161     public long getCurrentPositionUs(boolean isEnded) {
162         return mAudioTrack.getCurrentPositionUs(isEnded);
163     }
164 }
165