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.os.SystemClock; 20 import android.util.Log; 21 import android.util.Pair; 22 23 import java.util.ArrayList; 24 import java.util.HashSet; 25 import java.util.Set; 26 27 /** 28 * Monitors the rendering position of {@link AudioTrack}. 29 */ 30 public class AudioTrackMonitor { 31 private static final String TAG = "AudioTrackMonitor"; 32 private static final boolean DEBUG = false; 33 34 // For fetched audio samples 35 private final ArrayList<Pair<Long, Integer>> mPtsList = new ArrayList<>(); 36 private final Set<Integer> mSampleSize = new HashSet<>(); 37 private final Set<Integer> mCurSampleSize = new HashSet<>(); 38 private final Set<Integer> mAc3Header = new HashSet<>(); 39 40 private long mExpireMs; 41 private long mDuration; 42 private long mSampleCount; 43 private long mTotalCount; 44 private long mStartMs; 45 flush()46 private void flush() { 47 mExpireMs += mDuration; 48 mSampleCount = 0; 49 mCurSampleSize.clear(); 50 mPtsList.clear(); 51 } 52 53 /** 54 * Resets and initializes {@link AudioTrackMonitor}. 55 * 56 * @param duration the frequency of monitoring in milliseconds 57 */ reset(long duration)58 public void reset(long duration) { 59 mExpireMs = SystemClock.elapsedRealtime(); 60 mDuration = duration; 61 mTotalCount = 0; 62 mStartMs = 0; 63 mSampleSize.clear(); 64 mAc3Header.clear(); 65 flush(); 66 } 67 68 /** 69 * Adds an audio sample information for monitoring. 70 * 71 * @param pts the presentation timestamp of the sample 72 * @param sampleSize the size in bytes of the sample 73 * @param header the bitrate & sampling information header of the sample 74 */ addPts(long pts, int sampleSize, int header)75 public void addPts(long pts, int sampleSize, int header) { 76 mTotalCount++; 77 mSampleCount++; 78 mSampleSize.add(sampleSize); 79 mAc3Header.add(header); 80 mCurSampleSize.add(sampleSize); 81 if (mTotalCount == 1) { 82 mStartMs = SystemClock.elapsedRealtime(); 83 } 84 if (mPtsList.isEmpty() || mPtsList.get(mPtsList.size() - 1).first != pts) { 85 mPtsList.add(Pair.create(pts, 1)); 86 return; 87 } 88 Pair<Long, Integer> pair = mPtsList.get(mPtsList.size() - 1); 89 mPtsList.set(mPtsList.size() - 1, Pair.create(pair.first, pair.second + 1)); 90 } 91 92 /** 93 * Logs if interested events are present. 94 * <p> 95 * Periodic logging is not enabled in release mode in order to avoid verbose logging. 96 */ maybeLog()97 public void maybeLog() { 98 long now = SystemClock.elapsedRealtime(); 99 if (mExpireMs != 0 && now >= mExpireMs) { 100 if (DEBUG) { 101 long sampleDuration = (mTotalCount - 1) * 102 Ac3PassthroughTrackRenderer.AC3_SAMPLE_DURATION_US / 1000; 103 long totalDuration = now - mStartMs; 104 StringBuilder ptsBuilder = new StringBuilder(); 105 ptsBuilder.append("PTS received ").append(mSampleCount).append(", ") 106 .append(totalDuration - sampleDuration).append(' '); 107 108 for (Pair<Long, Integer> pair : mPtsList) { 109 ptsBuilder.append('[').append(pair.first).append(':').append(pair.second) 110 .append("], "); 111 } 112 Log.d(TAG, ptsBuilder.toString()); 113 } 114 if (DEBUG || mCurSampleSize.size() > 1) { 115 Log.d(TAG, "PTS received sample size: " 116 + String.valueOf(mSampleSize) + mCurSampleSize + mAc3Header); 117 } 118 flush(); 119 } 120 } 121 } 122