1 /* 2 * Copyright (C) 2016 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.audio; 18 19 import android.os.Handler; 20 import com.google.android.exoplayer.ExoPlaybackException; 21 import com.google.android.exoplayer.MediaCodecAudioTrackRenderer; 22 import com.google.android.exoplayer.MediaCodecSelector; 23 import com.google.android.exoplayer.SampleSource; 24 25 /** 26 * MPEG-2 TS audio track renderer. 27 * 28 * <p>Since the audio output from {@link android.media.MediaExtractor} contains extra samples at the 29 * beginning, using original {@link MediaCodecAudioTrackRenderer} as audio renderer causes 30 * asynchronous Audio/Video outputs. This class calculates the offset of audio data and adjust the 31 * presentation times to avoid the asynchronous Audio/Video problem. 32 */ 33 public class MpegTsMediaCodecAudioTrackRenderer extends MediaCodecAudioTrackRenderer { 34 private final Ac3EventListener mListener; 35 36 public interface Ac3EventListener extends EventListener { 37 /** 38 * Invoked when a {@link android.media.PlaybackParams} set to an {@link 39 * android.media.AudioTrack} is not valid. 40 * 41 * @param e The corresponding exception. 42 */ onAudioTrackSetPlaybackParamsError(IllegalArgumentException e)43 void onAudioTrackSetPlaybackParamsError(IllegalArgumentException e); 44 } 45 MpegTsMediaCodecAudioTrackRenderer( SampleSource source, MediaCodecSelector mediaCodecSelector, Handler eventHandler, EventListener eventListener)46 public MpegTsMediaCodecAudioTrackRenderer( 47 SampleSource source, 48 MediaCodecSelector mediaCodecSelector, 49 Handler eventHandler, 50 EventListener eventListener) { 51 super(source, mediaCodecSelector, eventHandler, eventListener); 52 mListener = (Ac3EventListener) eventListener; 53 } 54 55 @Override handleMessage(int messageType, Object message)56 public void handleMessage(int messageType, Object message) throws ExoPlaybackException { 57 if (messageType == MSG_SET_PLAYBACK_PARAMS) { 58 try { 59 super.handleMessage(messageType, message); 60 } catch (IllegalArgumentException e) { 61 if (isAudioTrackSetPlaybackParamsError(e)) { 62 notifyAudioTrackSetPlaybackParamsError(e); 63 } 64 } 65 return; 66 } 67 super.handleMessage(messageType, message); 68 } 69 notifyAudioTrackSetPlaybackParamsError(final IllegalArgumentException e)70 private void notifyAudioTrackSetPlaybackParamsError(final IllegalArgumentException e) { 71 if (eventHandler != null && mListener != null) { 72 eventHandler.post(() -> mListener.onAudioTrackSetPlaybackParamsError(e)); 73 } 74 } 75 isAudioTrackSetPlaybackParamsError(IllegalArgumentException e)76 private static boolean isAudioTrackSetPlaybackParamsError(IllegalArgumentException e) { 77 if (e.getStackTrace() == null || e.getStackTrace().length < 1) { 78 return false; 79 } 80 for (StackTraceElement element : e.getStackTrace()) { 81 String elementString = element.toString(); 82 if (elementString.startsWith("android.media.AudioTrack.setPlaybackParams")) { 83 return true; 84 } 85 } 86 return false; 87 } 88 } 89