use of androidx.media3.decoder.DecoderInputBuffer in project ExoPlayer by google.
the class MergingMediaPeriodTest method selectTracks_withPeriodOffsets_selectTracksWithOffset_andCreatesSampleStreamsCorrectingOffset.
@Test
public void selectTracks_withPeriodOffsets_selectTracksWithOffset_andCreatesSampleStreamsCorrectingOffset() throws Exception {
MergingMediaPeriod mergingMediaPeriod = prepareMergingPeriod(new MergingPeriodDefinition(/* timeOffsetUs= */
0, /* singleSampleTimeUs= */
123_000, childFormat11, childFormat12), new MergingPeriodDefinition(/* timeOffsetUs= */
-3000, /* singleSampleTimeUs= */
456_000, childFormat21, childFormat22));
ExoTrackSelection selectionForChild1 = new FixedTrackSelection(mergingMediaPeriod.getTrackGroups().get(0), /* track= */
0);
ExoTrackSelection selectionForChild2 = new FixedTrackSelection(mergingMediaPeriod.getTrackGroups().get(2), /* track= */
0);
SampleStream[] streams = new SampleStream[2];
mergingMediaPeriod.selectTracks(/* selections= */
new ExoTrackSelection[] { selectionForChild1, selectionForChild2 }, /* mayRetainStreamFlags= */
new boolean[] { false, false }, streams, /* streamResetFlags= */
new boolean[] { false, false }, /* positionUs= */
0);
mergingMediaPeriod.continueLoading(/* positionUs= */
0);
FormatHolder formatHolder = new FormatHolder();
DecoderInputBuffer inputBuffer = new DecoderInputBuffer(DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_NORMAL);
streams[0].readData(formatHolder, inputBuffer, FLAG_REQUIRE_FORMAT);
streams[1].readData(formatHolder, inputBuffer, FLAG_REQUIRE_FORMAT);
FakeMediaPeriodWithSelectTracksPosition childMediaPeriod1 = (FakeMediaPeriodWithSelectTracksPosition) mergingMediaPeriod.getChildPeriod(0);
assertThat(childMediaPeriod1.selectTracksPositionUs).isEqualTo(0);
assertThat(streams[0].readData(formatHolder, inputBuffer, /* readFlags= */
0)).isEqualTo(C.RESULT_BUFFER_READ);
assertThat(inputBuffer.timeUs).isEqualTo(123_000L);
FakeMediaPeriodWithSelectTracksPosition childMediaPeriod2 = (FakeMediaPeriodWithSelectTracksPosition) mergingMediaPeriod.getChildPeriod(1);
assertThat(childMediaPeriod2.selectTracksPositionUs).isEqualTo(3000L);
assertThat(streams[1].readData(formatHolder, inputBuffer, /* readFlags= */
0)).isEqualTo(C.RESULT_BUFFER_READ);
assertThat(inputBuffer.timeUs).isEqualTo(456_000 - 3000);
}
use of androidx.media3.decoder.DecoderInputBuffer in project ExoPlayer by google.
the class SampleQueueTest method assertReadSample.
/**
* Asserts {@link SampleQueue#read} returns {@link C#RESULT_BUFFER_READ} and that the buffer is
* filled with the specified sample data.
*
* @param timeUs The expected buffer timestamp.
* @param isKeyFrame The expected keyframe flag.
* @param isDecodeOnly The expected decodeOnly flag.
* @param isEncrypted The expected encrypted flag.
* @param sampleData An array containing the expected sample data.
* @param offset The offset in {@code sampleData} of the expected sample data.
* @param length The length of the expected sample data.
*/
private void assertReadSample(long timeUs, boolean isKeyFrame, boolean isDecodeOnly, boolean isEncrypted, byte[] sampleData, int offset, int length) {
// Check that peek whilst omitting data yields the expected values.
formatHolder.format = null;
DecoderInputBuffer flagsOnlyBuffer = DecoderInputBuffer.newNoDataInstance();
int result = sampleQueue.read(formatHolder, flagsOnlyBuffer, FLAG_OMIT_SAMPLE_DATA | FLAG_PEEK, /* loadingFinished= */
false);
assertSampleBufferReadResult(flagsOnlyBuffer, result, timeUs, isKeyFrame, isDecodeOnly, isEncrypted);
// Check that peek yields the expected values.
clearFormatHolderAndInputBuffer();
result = sampleQueue.read(formatHolder, inputBuffer, FLAG_PEEK, /* loadingFinished= */
false);
assertSampleBufferReadResult(result, timeUs, isKeyFrame, isDecodeOnly, isEncrypted, sampleData, offset, length);
// Check that read yields the expected values.
clearFormatHolderAndInputBuffer();
result = sampleQueue.read(formatHolder, inputBuffer, /* readFlags= */
0, /* loadingFinished= */
false);
assertSampleBufferReadResult(result, timeUs, isKeyFrame, isDecodeOnly, isEncrypted, sampleData, offset, length);
}
use of androidx.media3.decoder.DecoderInputBuffer in project ExoPlayer by google.
the class SampleQueueTest method setUp.
@Before
public void setUp() {
allocator = new DefaultAllocator(false, ALLOCATION_SIZE);
mockDrmSession = Mockito.mock(DrmSession.class);
mockDrmSessionManager = new MockDrmSessionManager(mockDrmSession);
eventDispatcher = new DrmSessionEventListener.EventDispatcher();
sampleQueue = new SampleQueue(allocator, mockDrmSessionManager, eventDispatcher);
formatHolder = new FormatHolder();
inputBuffer = new DecoderInputBuffer(DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_NORMAL);
}
use of androidx.media3.decoder.DecoderInputBuffer in project ExoPlayer by google.
the class TransformerBaseRenderer method feedPipelineFromInput.
/**
* Attempts to read input data and pass the input data to the sample pipeline.
*
* @return Whether it may be possible to read more data immediately by calling this method again.
* @throws TransformationException If a {@link SamplePipeline} problem occurs.
*/
@RequiresNonNull("samplePipeline")
private boolean feedPipelineFromInput() throws TransformationException {
@Nullable DecoderInputBuffer samplePipelineInputBuffer = samplePipeline.dequeueInputBuffer();
if (samplePipelineInputBuffer == null) {
return false;
}
@ReadDataResult int result = readSource(getFormatHolder(), samplePipelineInputBuffer, /* readFlags= */
0);
switch(result) {
case C.RESULT_BUFFER_READ:
samplePipelineInputBuffer.flip();
if (samplePipelineInputBuffer.isEndOfStream()) {
samplePipeline.queueInputBuffer();
return false;
}
mediaClock.updateTimeForTrackType(getTrackType(), samplePipelineInputBuffer.timeUs);
samplePipelineInputBuffer.timeUs -= streamOffsetUs;
checkStateNotNull(samplePipelineInputBuffer.data);
maybeQueueSampleToPipeline(samplePipelineInputBuffer);
return true;
case C.RESULT_FORMAT_READ:
throw new IllegalStateException("Format changes are not supported.");
case C.RESULT_NOTHING_READ:
default:
return false;
}
}
use of androidx.media3.decoder.DecoderInputBuffer in project media by androidx.
the class FfmpegAudioDecoder method decode.
@Override
@Nullable
protected FfmpegDecoderException decode(DecoderInputBuffer inputBuffer, SimpleDecoderOutputBuffer outputBuffer, boolean reset) {
if (reset) {
nativeContext = ffmpegReset(nativeContext, extraData);
if (nativeContext == 0) {
return new FfmpegDecoderException("Error resetting (see logcat).");
}
}
ByteBuffer inputData = Util.castNonNull(inputBuffer.data);
int inputSize = inputData.limit();
ByteBuffer outputData = outputBuffer.init(inputBuffer.timeUs, outputBufferSize);
int result = ffmpegDecode(nativeContext, inputData, inputSize, outputData, outputBufferSize);
if (result == AUDIO_DECODER_ERROR_OTHER) {
return new FfmpegDecoderException("Error decoding (see logcat).");
} else if (result == AUDIO_DECODER_ERROR_INVALID_DATA) {
// Treat invalid data errors as non-fatal to match the behavior of MediaCodec. No output will
// be produced for this buffer, so mark it as decode-only to ensure that the audio sink's
// position is reset when more audio is produced.
outputBuffer.setFlags(C.BUFFER_FLAG_DECODE_ONLY);
return null;
} else if (result == 0) {
// There's no need to output empty buffers.
outputBuffer.setFlags(C.BUFFER_FLAG_DECODE_ONLY);
return null;
}
if (!hasOutputFormat) {
channelCount = ffmpegGetChannelCount(nativeContext);
sampleRate = ffmpegGetSampleRate(nativeContext);
if (sampleRate == 0 && "alac".equals(codecName)) {
Assertions.checkNotNull(extraData);
// ALAC decoder did not set the sample rate in earlier versions of FFmpeg. See
// https://trac.ffmpeg.org/ticket/6096.
ParsableByteArray parsableExtraData = new ParsableByteArray(extraData);
parsableExtraData.setPosition(extraData.length - 4);
sampleRate = parsableExtraData.readUnsignedIntToInt();
}
hasOutputFormat = true;
}
outputData.position(0);
outputData.limit(result);
return null;
}
Aggregations