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.usbtuner.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 if (!mIsEnabled) { 45 return false; 46 } 47 return mAudioTrack.isInitialized(); 48 } 49 restart()50 public void restart() { 51 if (mAudioTrack.isInitialized()) { 52 mAudioTrack.release(); 53 } 54 mIsEnabled = true; 55 resetSessionId(); 56 } 57 release()58 public void release() { 59 if (mAudioSessionID != AudioTrack.SESSION_ID_NOT_SET) { 60 mAudioTrack.release(); 61 } 62 } 63 initialize()64 public void initialize() throws AudioTrack.InitializationException { 65 if (!mIsEnabled) { 66 return; 67 } 68 if (mAudioSessionID != AudioTrack.SESSION_ID_NOT_SET) { 69 mAudioTrack.initialize(mAudioSessionID); 70 } else { 71 mAudioSessionID = mAudioTrack.initialize(); 72 } 73 } 74 reset()75 public void reset() { 76 if (!mIsEnabled) { 77 return; 78 } 79 mAudioTrack.reset(); 80 } 81 isEnded()82 public boolean isEnded() { 83 if (!mIsEnabled) { 84 return true; 85 } 86 return !mAudioTrack.hasPendingData(); 87 } 88 isReady()89 public boolean isReady() { 90 // In the case of not playing actual audio data, Audio track is always ready. 91 return !mIsEnabled || mAudioTrack.hasPendingData(); 92 } 93 play()94 public void play() { 95 if (!mIsEnabled) { 96 return; 97 } 98 mAudioTrack.play(); 99 } 100 pause()101 public void pause() { 102 if (!mIsEnabled) { 103 return; 104 } 105 mAudioTrack.pause(); 106 } 107 setVolume(float volume)108 public void setVolume(float volume) { 109 if (!mIsEnabled) { 110 return; 111 } 112 mAudioTrack.setVolume(volume); 113 } 114 reconfigure(MediaFormat format)115 public void reconfigure(MediaFormat format) { 116 if (!mIsEnabled) { 117 return; 118 } 119 // TODO: Handle non-AC3 or non-passthrough audio. 120 if (MediaFormat.MIMETYPE_AUDIO_AC3.equalsIgnoreCase(format.getString(MediaFormat.KEY_MIME)) 121 && format.getInteger(MediaFormat.KEY_CHANNEL_COUNT) == 1) { 122 // Workarounds b/25955476 . 123 // Since all devices and platforms does not support AC3 mono passthrough, 124 // It is safe to fake AC3 mono as AC3 stereo which is default passthrough mode. 125 format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 2); 126 } 127 mAudioTrack.configure(format, true); 128 } 129 handleDiscontinuity()130 public void handleDiscontinuity() { 131 if (!mIsEnabled) { 132 return; 133 } 134 mAudioTrack.handleDiscontinuity(); 135 } 136 handleBuffer(ByteBuffer buffer, int offset, int size, long presentationTimeUs)137 public int handleBuffer(ByteBuffer buffer, int offset, int size, long presentationTimeUs) 138 throws AudioTrack.WriteException { 139 if (!mIsEnabled) { 140 return AudioTrack.RESULT_BUFFER_CONSUMED; 141 } 142 return mAudioTrack.handleBuffer(buffer, offset, size, presentationTimeUs); 143 } 144 setStatus(boolean enable)145 public void setStatus(boolean enable) { 146 if (enable == mIsEnabled) { 147 return; 148 } 149 mAudioTrack.reset(); 150 mIsEnabled = enable; 151 } 152 isEnabled()153 public boolean isEnabled() { 154 return mIsEnabled; 155 } 156 157 // This should be used only in case of being enabled. getCurrentPositionUs(boolean isEnded)158 public long getCurrentPositionUs(boolean isEnded) { 159 return mAudioTrack.getCurrentPositionUs(isEnded); 160 } 161 } 162