aboutsummaryrefslogtreecommitdiff
path: root/tuner/src/com/android/tv/tuner/exoplayer2/buffer/SampleChunkIoHelper.java
diff options
context:
space:
mode:
Diffstat (limited to 'tuner/src/com/android/tv/tuner/exoplayer2/buffer/SampleChunkIoHelper.java')
-rw-r--r--tuner/src/com/android/tv/tuner/exoplayer2/buffer/SampleChunkIoHelper.java198
1 files changed, 120 insertions, 78 deletions
diff --git a/tuner/src/com/android/tv/tuner/exoplayer2/buffer/SampleChunkIoHelper.java b/tuner/src/com/android/tv/tuner/exoplayer2/buffer/SampleChunkIoHelper.java
index da3dd725..5a3f6682 100644
--- a/tuner/src/com/android/tv/tuner/exoplayer2/buffer/SampleChunkIoHelper.java
+++ b/tuner/src/com/android/tv/tuner/exoplayer2/buffer/SampleChunkIoHelper.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,7 +16,7 @@
package com.android.tv.tuner.exoplayer2.buffer;
-import android.media.MediaCodec;
+import android.media.MediaFormat;
import android.os.ConditionVariable;
import android.os.Handler;
import android.os.HandlerThread;
@@ -26,11 +26,13 @@ import android.util.Log;
import android.util.Pair;
import com.android.tv.common.SoftPreconditions;
-import com.android.tv.tuner.exoplayer.buffer.RecordingSampleBuffer.BufferReason;
+import com.android.tv.tuner.exoplayer2.buffer.RecordingSampleBuffer.BufferReason;
-import com.google.android.exoplayer.MediaFormat;
-import com.google.android.exoplayer.SampleHolder;
-import com.google.android.exoplayer.util.MimeTypes;
+import com.google.android.exoplayer2.Format;
+import com.google.android.exoplayer2.decoder.DecoderInputBuffer;
+import com.google.android.exoplayer2.mediacodec.MediaFormatUtil;
+import com.google.android.exoplayer2.util.MimeTypes;
+import com.google.android.exoplayer2.util.Util;
import com.google.auto.factory.AutoFactory;
import java.io.IOException;
@@ -62,15 +64,15 @@ public class SampleChunkIoHelper implements Handler.Callback {
private final long mSampleChunkDurationUs;
private final int mTrackCount;
private final List<String> mIds;
- private final List<MediaFormat> mMediaFormats;
+ private final List<Format> mFormats;
private final @BufferReason int mBufferReason;
private final BufferManager mBufferManager;
- private final SamplePool mSamplePool;
+ private final InputBufferPool mInputBufferPool;
private final IoCallback mIoCallback;
private Handler mIoHandler;
- private final ConcurrentLinkedQueue<SampleHolder> mReadSampleBuffers[];
- private final ConcurrentLinkedQueue<SampleHolder> mHandlerReadSampleBuffers[];
+ private final ConcurrentLinkedQueue<DecoderInputBuffer>[] mReadSampleBuffers;
+ private final ConcurrentLinkedQueue<DecoderInputBuffer>[] mHandlerReadSampleBuffers;
private final long[] mWriteIndexEndPositionUs;
private final long[] mWriteChunkEndPositionUs;
private final SampleChunk.IoState[] mReadIoStates;
@@ -96,16 +98,16 @@ public class SampleChunkIoHelper implements Handler.Callback {
private static class IoParams {
private final int index;
private final long positionUs;
- private final SampleHolder sample;
+ private final DecoderInputBuffer sample;
private final ConditionVariable conditionVariable;
- private final ConcurrentLinkedQueue<SampleHolder> readSampleBuffer;
+ private final ConcurrentLinkedQueue<DecoderInputBuffer> readSampleBuffer;
private IoParams(
int index,
long positionUs,
- SampleHolder sample,
+ DecoderInputBuffer sample,
ConditionVariable conditionVariable,
- ConcurrentLinkedQueue<SampleHolder> readSampleBuffer) {
+ ConcurrentLinkedQueue<DecoderInputBuffer> readSampleBuffer) {
this.index = index;
this.positionUs = positionUs;
this.sample = sample;
@@ -121,12 +123,12 @@ public class SampleChunkIoHelper implements Handler.Callback {
* generated class.
*/
public interface Factory {
- public SampleChunkIoHelper create(
+ SampleChunkIoHelper create(
List<String> ids,
- List<MediaFormat> mediaFormats,
+ List<Format> formats,
@BufferReason int bufferReason,
BufferManager bufferManager,
- SamplePool samplePool,
+ InputBufferPool inputBufferPool,
IoCallback ioCallback);
}
@@ -134,26 +136,26 @@ public class SampleChunkIoHelper implements Handler.Callback {
* Creates {@link SampleChunk} I/O handler.
*
* @param ids track names
- * @param mediaFormats {@link android.media.MediaFormat} for each track
+ * @param formats {@link Format} for each track
* @param bufferReason reason to be buffered
* @param bufferManager manager of {@link SampleChunk} collections
- * @param samplePool allocator for a sample
+ * @param inputBufferPool allocator for a sample
* @param ioCallback listeners for I/O events
*/
@AutoFactory(implementing = Factory.class)
public SampleChunkIoHelper(
List<String> ids,
- List<MediaFormat> mediaFormats,
+ List<Format> formats,
@BufferReason int bufferReason,
BufferManager bufferManager,
- SamplePool samplePool,
+ InputBufferPool inputBufferPool,
IoCallback ioCallback) {
mTrackCount = ids.size();
mIds = ids;
- mMediaFormats = mediaFormats;
+ mFormats = formats;
mBufferReason = bufferReason;
mBufferManager = bufferManager;
- mSamplePool = samplePool;
+ mInputBufferPool = inputBufferPool;
mIoCallback = ioCallback;
mReadSampleBuffers = new ConcurrentLinkedQueue[mTrackCount];
@@ -182,7 +184,7 @@ public class SampleChunkIoHelper implements Handler.Callback {
/**
* Prepares and initializes for I/O operations.
*
- * @throws IOException
+ * @throws IOException if an I/O error occurs.
*/
public void init() throws IOException {
HandlerThread handlerThread = new HandlerThread(TAG);
@@ -190,7 +192,7 @@ public class SampleChunkIoHelper implements Handler.Callback {
mIoHandler = new Handler(handlerThread.getLooper(), this);
if (mBufferReason == RecordingSampleBuffer.BUFFER_REASON_RECORDED_PLAYBACK) {
for (int i = 0; i < mTrackCount; ++i) {
- mBufferManager.loadTrackFromStorage(mIds.get(i), mSamplePool);
+ mBufferManager.loadTrackFromStorage(mIds.get(i), mInputBufferPool);
}
mWriteEnded = true;
} else {
@@ -205,22 +207,23 @@ public class SampleChunkIoHelper implements Handler.Callback {
List<BufferManager.TrackFormat> audios = new ArrayList<>(mTrackCount);
List<BufferManager.TrackFormat> videos = new ArrayList<>(mTrackCount);
for (int i = 0; i < mTrackCount; ++i) {
- android.media.MediaFormat format =
- mMediaFormats.get(i).getFrameworkMediaFormatV16();
- format.setLong(android.media.MediaFormat.KEY_DURATION, mBufferDurationUs);
- if (mMediaFormats.get(i).pixelWidthHeightRatio > 0) {
- // MediaFormats doesn't store aspect ratio so updating the width
- // to maintain aspect ratio.
- format.setInteger(
- android.media.MediaFormat.KEY_WIDTH,
- (int)
- (mMediaFormats.get(i).width
- * mMediaFormats.get(i).pixelWidthHeightRatio));
- }
- if (MimeTypes.isAudio(mMediaFormats.get(i).mimeType)) {
- audios.add(new BufferManager.TrackFormat(mIds.get(i), format));
- } else if (MimeTypes.isVideo(mMediaFormats.get(i).mimeType)) {
- videos.add(new BufferManager.TrackFormat(mIds.get(i), format));
+ if (MimeTypes.isAudio(mFormats.get(i).sampleMimeType)) {
+ MediaFormat mediaFormat = getAudioMediaFormat(mFormats.get(i));
+ mediaFormat.setLong(MediaFormat.KEY_DURATION, mBufferDurationUs);
+ audios.add(new BufferManager.TrackFormat(mIds.get(i), mediaFormat));
+ } else if (MimeTypes.isVideo(mFormats.get(i).sampleMimeType)) {
+ MediaFormat mediaFormat = getVideoMediaFormat(mFormats.get(i));
+ mediaFormat.setLong(MediaFormat.KEY_DURATION, mBufferDurationUs);
+ if (mFormats.get(i).pixelWidthHeightRatio != Format.NO_VALUE) {
+ // MediaFormats doesn't store aspect ratio so updating the width
+ // to maintain aspect ratio.
+ mediaFormat.setInteger(
+ MediaFormat.KEY_WIDTH,
+ (int)
+ (mFormats.get(i).width
+ * mFormats.get(i).pixelWidthHeightRatio));
+ }
+ videos.add(new BufferManager.TrackFormat(mIds.get(i), mediaFormat));
}
}
mBufferManager.writeMetaFilesOnly(audios, videos);
@@ -230,14 +233,50 @@ public class SampleChunkIoHelper implements Handler.Callback {
}
}
+ private MediaFormat getVideoMediaFormat(Format format) {
+ MediaFormat mediaFormat = new MediaFormat();
+ // Set mediaFormat parameters that should always be set.
+ mediaFormat.setString(MediaFormat.KEY_MIME, format.sampleMimeType);
+ mediaFormat.setInteger(MediaFormat.KEY_WIDTH, format.width);
+ mediaFormat.setInteger(MediaFormat.KEY_HEIGHT, format.height);
+ MediaFormatUtil.setCsdBuffers(mediaFormat, format.initializationData);
+ // Set mediaFormat parameters that may be unset.
+ MediaFormatUtil.maybeSetFloat(mediaFormat, MediaFormat.KEY_FRAME_RATE, format.frameRate);
+ MediaFormatUtil.maybeSetInteger(
+ mediaFormat, MediaFormat.KEY_ROTATION, format.rotationDegrees);
+ MediaFormatUtil.maybeSetColorInfo(mediaFormat, format.colorInfo);
+ MediaFormatUtil.maybeSetInteger(
+ mediaFormat, MediaFormat.KEY_MAX_INPUT_SIZE, format.maxInputSize);
+ if (Util.SDK_INT >= 23) {
+ mediaFormat.setInteger(MediaFormat.KEY_PRIORITY, 0 /* realtime priority */);
+ }
+ return mediaFormat;
+ }
+
+ private MediaFormat getAudioMediaFormat(Format format) {
+ MediaFormat mediaFormat = new MediaFormat();
+ // Set mediaFormat parameters that should always be set.
+ mediaFormat.setString(MediaFormat.KEY_MIME, format.sampleMimeType);
+ mediaFormat.setInteger(MediaFormat.KEY_CHANNEL_COUNT, format.channelCount);
+ mediaFormat.setInteger(MediaFormat.KEY_SAMPLE_RATE, format.sampleRate);
+ // Set mediaFormat parameters that may be unset.
+ MediaFormatUtil.setCsdBuffers(mediaFormat, format.initializationData);
+ MediaFormatUtil.maybeSetInteger(
+ mediaFormat, MediaFormat.KEY_MAX_INPUT_SIZE, format.maxInputSize);
+ if (Util.SDK_INT >= 23) {
+ mediaFormat.setInteger(MediaFormat.KEY_PRIORITY, 0 /* realtime priority */);
+ }
+ return mediaFormat;
+ }
+
/**
* Reads a sample if it is available.
*
* @param index track index
* @return {@code null} if a sample is not available, otherwise returns a sample
*/
- public SampleHolder readSample(int index) {
- SampleHolder sample = mReadSampleBuffers[index].poll();
+ public DecoderInputBuffer readSample(int index) {
+ DecoderInputBuffer sample = mReadSampleBuffers[index].poll();
mIoHandler.sendMessage(mIoHandler.obtainMessage(MSG_READ, index));
return sample;
}
@@ -248,10 +287,12 @@ public class SampleChunkIoHelper implements Handler.Callback {
* @param index track index
* @param sample to write
* @param conditionVariable which will be wait until the write is finished
- * @throws IOException
+ * @throws IOException if an I/O error occurs.
*/
- public void writeSample(int index, SampleHolder sample, ConditionVariable conditionVariable)
- throws IOException {
+ public void writeSample(
+ int index,
+ DecoderInputBuffer sample,
+ ConditionVariable conditionVariable) throws IOException {
if (mErrorNotified) {
throw new IOException("Storage I/O error happened");
}
@@ -302,7 +343,7 @@ public class SampleChunkIoHelper implements Handler.Callback {
/**
* Finishes I/O operations and releases all the resources.
*
- * @throws IOException
+ * @throws IOException if an I/O error occurs.
*/
public void release() throws IOException {
if (mIoHandler == null) {
@@ -322,22 +363,23 @@ public class SampleChunkIoHelper implements Handler.Callback {
List<BufferManager.TrackFormat> audios = new LinkedList<>();
List<BufferManager.TrackFormat> videos = new LinkedList<>();
for (int i = 0; i < mTrackCount; ++i) {
- android.media.MediaFormat format =
- mMediaFormats.get(i).getFrameworkMediaFormatV16();
- format.setLong(android.media.MediaFormat.KEY_DURATION, mBufferDurationUs);
- if (mMediaFormats.get(i).pixelWidthHeightRatio > 0) {
- // MediaFormats doesn't store aspect ratio so updating the width
- // to maintain aspect ratio.
- format.setInteger(
- android.media.MediaFormat.KEY_WIDTH,
- (int)
- (mMediaFormats.get(i).width
- * mMediaFormats.get(i).pixelWidthHeightRatio));
- }
- if (MimeTypes.isAudio(mMediaFormats.get(i).mimeType)) {
- audios.add(new BufferManager.TrackFormat(mIds.get(i), format));
- } else if (MimeTypes.isVideo(mMediaFormats.get(i).mimeType)) {
- videos.add(new BufferManager.TrackFormat(mIds.get(i), format));
+ if (MimeTypes.isAudio(mFormats.get(i).sampleMimeType)) {
+ MediaFormat mediaFormat = getAudioMediaFormat(mFormats.get(i));
+ mediaFormat.setLong(MediaFormat.KEY_DURATION, mBufferDurationUs);
+ audios.add(new BufferManager.TrackFormat(mIds.get(i), mediaFormat));
+ } else if (MimeTypes.isVideo(mFormats.get(i).sampleMimeType)) {
+ MediaFormat mediaFormat = getVideoMediaFormat(mFormats.get(i));
+ mediaFormat.setLong(MediaFormat.KEY_DURATION, mBufferDurationUs);
+ if (mFormats.get(i).pixelWidthHeightRatio != Format.NO_VALUE) {
+ // MediaFormats doesn't store aspect ratio so updating the width
+ // to maintain aspect ratio.
+ mediaFormat.setInteger(
+ MediaFormat.KEY_WIDTH,
+ (int)
+ (mFormats.get(i).width
+ * mFormats.get(i).pixelWidthHeightRatio));
+ }
+ videos.add(new BufferManager.TrackFormat(mIds.get(i), mediaFormat));
}
}
mBufferManager.writeMetaFiles(audios, videos);
@@ -405,9 +447,9 @@ public class SampleChunkIoHelper implements Handler.Callback {
mSelectedTracks.add(index);
mReadIoStates[index].openRead(readPosition.first, (long) readPosition.second);
if (mHandlerReadSampleBuffers[index] != null) {
- SampleHolder sample;
+ DecoderInputBuffer sample;
while ((sample = mHandlerReadSampleBuffers[index].poll()) != null) {
- mSamplePool.releaseSample(sample);
+ mInputBufferPool.releaseSample(sample);
}
}
mHandlerReadSampleBuffers[index] = params.readSampleBuffer;
@@ -417,21 +459,21 @@ public class SampleChunkIoHelper implements Handler.Callback {
private void doOpenWrite(int index) throws IOException {
boolean updateIndexFile =
(mBufferReason == RecordingSampleBuffer.BUFFER_REASON_RECORDING)
- && (MimeTypes.isVideo(mMediaFormats.get(index).mimeType)
- || MimeTypes.isAudio(mMediaFormats.get(index).mimeType));
+ && (MimeTypes.isVideo(mFormats.get(index).sampleMimeType)
+ || MimeTypes.isAudio(mFormats.get(index).sampleMimeType));
SampleChunk chunk =
mBufferManager.createNewWriteFileIfNeeded(
- mIds.get(index), 0, mSamplePool, null, 0, updateIndexFile);
+ mIds.get(index), 0, mInputBufferPool, null, 0, updateIndexFile);
mWriteIoStates[index].openWrite(chunk);
}
private void doCloseRead(int index) {
mSelectedTracks.remove(index);
if (mHandlerReadSampleBuffers[index] != null) {
- SampleHolder sample;
+ DecoderInputBuffer sample;
while ((sample = mHandlerReadSampleBuffers[index].poll()) != null) {
- mSamplePool.releaseSample(sample);
+ mInputBufferPool.releaseSample(sample);
}
}
mIoHandler.removeMessages(MSG_READ, index);
@@ -454,7 +496,7 @@ public class SampleChunkIoHelper implements Handler.Callback {
mIoCallback.onIoReachedEos();
return;
}
- SampleHolder sample = mReadIoStates[index].read();
+ DecoderInputBuffer sample = mReadIoStates[index].read();
if (sample != null) {
mHandlerReadSampleBuffers[index].offer(sample);
mReadChunkOffset[index] = mReadIoStates[index].getOffset();
@@ -472,11 +514,11 @@ public class SampleChunkIoHelper implements Handler.Callback {
}
}
- public void doUpdateIndex(IoParams params) throws IOException {
+ private void doUpdateIndex(IoParams params) throws IOException {
int index = params.index;
mIoHandler.removeMessages(MSG_READ, index);
// Update Track from Storage to load new Samples
- mBufferManager.loadTrackFromStorage(mIds.get(index), mSamplePool);
+ mBufferManager.loadTrackFromStorage(mIds.get(index), mInputBufferPool);
Pair<SampleChunk, Integer> readPosition =
mBufferManager.getReadFile(mIds.get(index), mReadChunkPositionUs[index]);
if (readPosition == null) {
@@ -500,9 +542,9 @@ public class SampleChunkIoHelper implements Handler.Callback {
return;
}
int index = params.index;
- SampleHolder sample = params.sample;
+ DecoderInputBuffer sample = params.sample;
SampleChunk nextChunk = null;
- if ((sample.flags & MediaCodec.BUFFER_FLAG_KEY_FRAME) != 0) {
+ if (sample.isKeyFrame()) {
if (sample.timeUs > mBufferDurationUs) {
mBufferDurationUs = sample.timeUs;
}
@@ -514,15 +556,15 @@ public class SampleChunkIoHelper implements Handler.Callback {
int currentOffset = (int) mWriteIoStates[params.index].getOffset();
boolean updateIndexFile =
(mBufferReason == RecordingSampleBuffer.BUFFER_REASON_RECORDING)
- && (MimeTypes.isVideo(mMediaFormats.get(index).mimeType)
+ && (MimeTypes.isVideo(mFormats.get(index).sampleMimeType)
|| MimeTypes.isAudio(
- mMediaFormats.get(index).mimeType));
+ mFormats.get(index).sampleMimeType));
nextChunk =
mBufferManager.createNewWriteFileIfNeeded(
mIds.get(index),
mWriteIndexEndPositionUs[index],
- mSamplePool,
+ mInputBufferPool,
currentChunk,
currentOffset,
updateIndexFile);