Merge "media: test MediaCodec flush right after first frame"
diff --git a/tests/tests/media/src/android/media/cts/MediaCodecTest.java b/tests/tests/media/src/android/media/cts/MediaCodecTest.java
index 90125d0..193345a 100644
--- a/tests/tests/media/src/android/media/cts/MediaCodecTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaCodecTest.java
@@ -2532,4 +2532,104 @@
}
}
}
+
+ /**
+ * Test if flushing early in the playback does not prevent client from getting the
+ * latest configuration. Empirically, this happens most often when the
+ * codec is flushed after the first buffer is queued, so this test walks
+ * through the scenario.
+ */
+ public void testFlushAfterFirstBuffer() throws Exception {
+ for (int i = 0; i < 100; ++i) {
+ doFlushAfterFirstBuffer();
+ }
+ }
+
+ private void doFlushAfterFirstBuffer() throws Exception {
+ MediaExtractor extractor = null;
+ MediaCodec codec = null;
+
+ try {
+ MediaFormat newFormat = null;
+ extractor = getMediaExtractorForMimeType(
+ R.raw.noise_2ch_48khz_aot29_dr_sbr_sig2_mp4, "audio/");
+ int trackIndex = extractor.getSampleTrackIndex();
+ MediaFormat format = extractor.getTrackFormat(trackIndex);
+ codec = createCodecByType(
+ format.getString(MediaFormat.KEY_MIME), false /* isEncoder */);
+ codec.configure(format, null, null, 0);
+ codec.start();
+ int firstInputIndex = codec.dequeueInputBuffer(0);
+ while (firstInputIndex == MediaCodec.INFO_TRY_AGAIN_LATER) {
+ firstInputIndex = codec.dequeueInputBuffer(5000);
+ }
+ assertTrue(firstInputIndex >= 0);
+ extractor.readSampleData(codec.getInputBuffer(firstInputIndex), 0);
+ codec.queueInputBuffer(
+ firstInputIndex, 0, Math.toIntExact(extractor.getSampleSize()),
+ extractor.getSampleTime(), extractor.getSampleFlags());
+ // Don't advance, so the first buffer will be read again after flush
+ codec.flush();
+ ByteBuffer csd = format.getByteBuffer("csd-0");
+ MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
+ // We don't need to decode many frames
+ int numFrames = 10;
+ boolean eos = false;
+ while (!eos) {
+ if (numFrames > 0) {
+ int inputIndex = codec.dequeueInputBuffer(0);
+ if (inputIndex == MediaCodec.INFO_TRY_AGAIN_LATER) {
+ inputIndex = codec.dequeueInputBuffer(5000);
+ }
+ if (inputIndex >= 0) {
+ ByteBuffer inputBuffer = codec.getInputBuffer(inputIndex);
+ if (csd != null) {
+ inputBuffer.clear();
+ inputBuffer.put(csd);
+ codec.queueInputBuffer(
+ inputIndex, 0, inputBuffer.position(), 0,
+ MediaCodec.BUFFER_FLAG_CODEC_CONFIG);
+ csd = null;
+ } else {
+ int size = extractor.readSampleData(inputBuffer, 0);
+ if (size <= 0) {
+ break;
+ }
+ int flags = extractor.getSampleFlags();
+ --numFrames;
+ if (numFrames <= 0) {
+ flags |= MediaCodec.BUFFER_FLAG_END_OF_STREAM;
+ }
+ codec.queueInputBuffer(
+ inputIndex, 0, size, extractor.getSampleTime(), flags);
+ extractor.advance();
+ }
+ }
+ }
+
+ int outputIndex = codec.dequeueOutputBuffer(bufferInfo, 0);
+ if (outputIndex == MediaCodec.INFO_TRY_AGAIN_LATER) {
+ outputIndex = codec.dequeueOutputBuffer(bufferInfo, 5000);
+ }
+ if (outputIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
+ newFormat = codec.getOutputFormat();
+ } else if (outputIndex >= 0) {
+ if ((bufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
+ eos = true;
+ }
+ codec.releaseOutputBuffer(outputIndex, false);
+ }
+ }
+ assertNotNull(newFormat);
+ assertEquals(48000, newFormat.getInteger(MediaFormat.KEY_SAMPLE_RATE));
+ } finally {
+ if (extractor != null) {
+ extractor.release();
+ }
+ if (codec != null) {
+ codec.stop();
+ codec.release();
+ }
+ }
+ }
}