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