16ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko/* 26ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko * Copyright (C) 2017 The Android Open Source Project 36ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko * 46ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko * Licensed under the Apache License, Version 2.0 (the "License"); 56ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko * you may not use this file except in compliance with the License. 66ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko * You may obtain a copy of the License at 76ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko * 86ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko * http://www.apache.org/licenses/LICENSE-2.0 96ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko * 106ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko * Unless required by applicable law or agreed to in writing, software 116ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko * distributed under the License is distributed on an "AS IS" BASIS, 126ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko * See the License for the specific language governing permissions and 146ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko * limitations under the License. 156ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko */ 166ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko 176ebde20b03db4c0d57f67acaac11832b610b966bNick Chalkopackage com.android.tv.tuner.exoplayer.audio; 186ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko 196ebde20b03db4c0d57f67acaac11832b610b966bNick Chalkoimport android.media.MediaCodec; 206ebde20b03db4c0d57f67acaac11832b610b966bNick Chalkoimport android.util.Log; 216ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko 226ebde20b03db4c0d57f67acaac11832b610b966bNick Chalkoimport com.google.android.exoplayer.CodecCounters; 236ebde20b03db4c0d57f67acaac11832b610b966bNick Chalkoimport com.google.android.exoplayer.DecoderInfo; 246ebde20b03db4c0d57f67acaac11832b610b966bNick Chalkoimport com.google.android.exoplayer.ExoPlaybackException; 256ebde20b03db4c0d57f67acaac11832b610b966bNick Chalkoimport com.google.android.exoplayer.MediaCodecSelector; 266ebde20b03db4c0d57f67acaac11832b610b966bNick Chalkoimport com.google.android.exoplayer.MediaCodecUtil; 276ebde20b03db4c0d57f67acaac11832b610b966bNick Chalkoimport com.google.android.exoplayer.MediaFormat; 286ebde20b03db4c0d57f67acaac11832b610b966bNick Chalkoimport com.google.android.exoplayer.SampleHolder; 296ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko 306ebde20b03db4c0d57f67acaac11832b610b966bNick Chalkoimport java.nio.ByteBuffer; 316ebde20b03db4c0d57f67acaac11832b610b966bNick Chalkoimport java.util.ArrayList; 326ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko 336ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko/** A decoder to use MediaCodec for decoding audio stream. */ 346ebde20b03db4c0d57f67acaac11832b610b966bNick Chalkopublic class MediaCodecAudioDecoder extends AudioDecoder { 356ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko private static final String TAG = "MediaCodecAudioDecoder"; 366ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko 376ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko public static final int INDEX_INVALID = -1; 386ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko 396ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko private final CodecCounters mCodecCounters; 406ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko private final MediaCodecSelector mSelector; 416ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko 426ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko private MediaCodec mCodec; 436ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko private MediaCodec.BufferInfo mOutputBufferInfo; 446ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko private ByteBuffer mMediaCodecOutputBuffer; 456ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko private ArrayList<Long> mDecodeOnlyPresentationTimestamps; 466ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko private boolean mWaitingForFirstSyncFrame; 476ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko private boolean mIsNewIndex; 486ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko private int mInputIndex; 496ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko private int mOutputIndex; 506ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko 516ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko /** Creates a MediaCodec based audio decoder. */ 526ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko public MediaCodecAudioDecoder(MediaCodecSelector selector) { 536ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko mSelector = selector; 546ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko mOutputBufferInfo = new MediaCodec.BufferInfo(); 556ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko mCodecCounters = new CodecCounters(); 566ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko mDecodeOnlyPresentationTimestamps = new ArrayList<>(); 576ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 586ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko 596ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko /** Returns {@code true} if there is decoder for {@code mimeType}. */ 606ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko public static boolean supportMimeType(MediaCodecSelector selector, String mimeType) { 616ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko if (selector == null) { 626ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko return false; 636ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 646ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko return getDecoderInfo(selector, mimeType) != null; 656ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 666ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko 676ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko private static DecoderInfo getDecoderInfo(MediaCodecSelector selector, String mimeType) { 686ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko try { 696ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko return selector.getDecoderInfo(mimeType, false); 706ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } catch (MediaCodecUtil.DecoderQueryException e) { 716ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko Log.e(TAG, "Select decoder error:" + e); 726ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko return null; 736ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 746ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 756ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko 766ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko private boolean shouldInitCodec(MediaFormat format) { 776ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko return format != null && mCodec == null; 786ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 796ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko 806ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko @Override 816ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko public void maybeInitDecoder(MediaFormat format) throws ExoPlaybackException { 826ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko if (!shouldInitCodec(format)) { 836ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko return; 846ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 856ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko 866ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko String mimeType = format.mimeType; 876ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko DecoderInfo decoderInfo = getDecoderInfo(mSelector, mimeType); 886ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko if (decoderInfo == null) { 896ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko Log.i(TAG, "There is not decoder found for " + mimeType); 906ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko return; 916ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 926ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko 936ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko String codecName = decoderInfo.name; 946ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko try { 956ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko mCodec = MediaCodec.createByCodecName(codecName); 966ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko mCodec.configure(format.getFrameworkMediaFormatV16(), null, null, 0); 976ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko mCodec.start(); 986ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } catch (Exception e) { 996ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko Log.e(TAG, "Failed when configure or start codec:" + e); 1006ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko throw new ExoPlaybackException(e); 1016ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 1026ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko mInputIndex = INDEX_INVALID; 1036ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko mOutputIndex = INDEX_INVALID; 1046ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko mWaitingForFirstSyncFrame = true; 1056ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko mCodecCounters.codecInitCount++; 1066ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 1076ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko 1086ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko @Override 1096ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko public void resetDecoderState(String mimeType) { 1106ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko if (mCodec == null) { 1116ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko return; 1126ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 1136ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko mInputIndex = INDEX_INVALID; 1146ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko mOutputIndex = INDEX_INVALID; 1156ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko mDecodeOnlyPresentationTimestamps.clear(); 1166ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko mCodec.flush(); 1176ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko mWaitingForFirstSyncFrame = true; 1186ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 1196ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko 1206ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko @Override 1216ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko public void release() { 1226ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko if (mCodec != null) { 1236ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko mDecodeOnlyPresentationTimestamps.clear(); 1246ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko mInputIndex = INDEX_INVALID; 1256ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko mOutputIndex = INDEX_INVALID; 1266ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko mCodecCounters.codecReleaseCount++; 1276ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko try { 1286ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko mCodec.stop(); 1296ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } finally { 1306ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko try { 1316ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko mCodec.release(); 1326ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } finally { 1336ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko mCodec = null; 1346ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 1356ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 1366ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 1376ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 1386ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko 1396ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko /** Returns the index of input buffer which is ready for using. */ 1406ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko public int getInputIndex() { 1416ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko return mInputIndex; 1426ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 1436ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko 1446ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko @Override 1456ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko public ByteBuffer getInputBuffer() { 1466ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko if (mInputIndex < 0) { 1476ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko mInputIndex = mCodec.dequeueInputBuffer(0); 1486ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko if (mInputIndex < 0) { 1496ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko return null; 1506ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 1516ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko return mCodec.getInputBuffer(mInputIndex); 1526ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 1536ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko return mCodec.getInputBuffer(mInputIndex); 1546ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 1556ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko 1566ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko @Override 1576ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko public void decode(SampleHolder sampleHolder) { 1586ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko if (mWaitingForFirstSyncFrame) { 1596ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko if (!sampleHolder.isSyncFrame()) { 1606ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko sampleHolder.clearData(); 1616ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko return; 1626ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 1636ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko mWaitingForFirstSyncFrame = false; 1646ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 1656ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko long presentationTimeUs = sampleHolder.timeUs; 1666ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko if (sampleHolder.isDecodeOnly()) { 1676ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko mDecodeOnlyPresentationTimestamps.add(presentationTimeUs); 1686ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 1696ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko mCodec.queueInputBuffer(mInputIndex, 0, sampleHolder.data.limit(), presentationTimeUs, 0); 1706ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko mInputIndex = INDEX_INVALID; 1716ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko mCodecCounters.inputBufferCount++; 1726ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 1736ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko 1746ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko private int getDecodeOnlyIndex(long presentationTimeUs) { 1756ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko final int size = mDecodeOnlyPresentationTimestamps.size(); 1766ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko for (int i = 0; i < size; i++) { 1776ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko if (mDecodeOnlyPresentationTimestamps.get(i).longValue() == presentationTimeUs) { 1786ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko return i; 1796ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 1806ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 1816ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko return INDEX_INVALID; 1826ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 1836ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko 1846ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko /** Returns the index of output buffer which is ready for using. */ 1856ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko public int getOutputIndex() { 1866ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko if (mOutputIndex < 0) { 1876ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko mOutputIndex = mCodec.dequeueOutputBuffer(mOutputBufferInfo, 0); 1886ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko mIsNewIndex = true; 1896ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } else { 1906ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko mIsNewIndex = false; 1916ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 1926ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko return mOutputIndex; 1936ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 1946ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko 1956ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko @Override 1966ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko public android.media.MediaFormat getOutputFormat() { 1976ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko return mCodec.getOutputFormat(); 1986ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 1996ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko 2006ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko /** Returns {@code true} if the output is only for decoding but not for rendering. */ 2016ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko public boolean maybeDecodeOnlyIndex() { 2026ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko int decodeOnlyIndex = getDecodeOnlyIndex(mOutputBufferInfo.presentationTimeUs); 2036ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko if (decodeOnlyIndex != INDEX_INVALID) { 2046ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko mCodec.releaseOutputBuffer(mOutputIndex, false); 2056ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko mCodecCounters.skippedOutputBufferCount++; 2066ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko mDecodeOnlyPresentationTimestamps.remove(decodeOnlyIndex); 2076ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko mOutputIndex = INDEX_INVALID; 2086ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko return true; 2096ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 2106ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko return false; 2116ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 2126ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko 2136ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko @Override 2146ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko public ByteBuffer getDecodedSample() { 2156ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko if (maybeDecodeOnlyIndex() || mOutputIndex < 0) { 2166ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko return null; 2176ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 2186ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko if (mIsNewIndex) { 2196ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko mMediaCodecOutputBuffer = mCodec.getOutputBuffer(mOutputIndex); 2206ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 2216ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko return mMediaCodecOutputBuffer; 2226ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 2236ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko 2246ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko @Override 2256ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko public long getDecodedTimeUs() { 2266ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko return mOutputBufferInfo.presentationTimeUs; 2276ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 2286ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko 2296ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko /** Releases the output buffer after rendering. */ 2306ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko public void releaseOutputBuffer() { 2316ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko mCodecCounters.renderedOutputBufferCount++; 2326ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko mCodec.releaseOutputBuffer(mOutputIndex, false); 2336ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko mOutputIndex = INDEX_INVALID; 2346ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 2356ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko} 236