media: Test flush before and after CSD for decoders
Bug: 13205664
Change-Id: Ifeafc7ea61fb67d752d9581e2560a11f75d4a411
diff --git a/tests/tests/media/src/android/media/cts/AdaptivePlaybackTest.java b/tests/tests/media/src/android/media/cts/AdaptivePlaybackTest.java
index 0edbc61..34469b79 100644
--- a/tests/tests/media/src/android/media/cts/AdaptivePlaybackTest.java
+++ b/tests/tests/media/src/android/media/cts/AdaptivePlaybackTest.java
@@ -327,20 +327,42 @@
* Queue some frames with an EOS on the last one. Test that we have decoded as many
* frames as we queued. This tests the EOS handling of the codec to see if all queued
* (and out-of-order) frames are actually decoded and returned.
+ *
+ * Also test flushing prior to sending CSD, and immediately after sending CSD.
*/
class EarlyEosTest extends ActivityTest {
+ // using bitfields to create a directed state graph that terminates at FLUSH_NEVER
+ static final int FLUSH_BEFORE_CSD = (1 << 1);
+ static final int FLUSH_AFTER_CSD = (1 << 0);
+ static final int FLUSH_NEVER = 0;
+
public boolean isValid(Codec c) {
return getFormat(c) != null;
}
public void addTests(TestList tests, final Codec c) {
- for (int i = NUM_FRAMES / 2; i > 0; i--) {
+ int state = FLUSH_BEFORE_CSD;
+ for (int i = NUM_FRAMES / 2; i > 0; --i, state >>= 1) {
final int queuedFrames = i;
+ final int earlyFlushMode = state;
tests.add(
new Step("testing early EOS at " + queuedFrames, this, c) {
public void run() {
Decoder decoder = new Decoder(c.name);
try {
- decoder.configureAndStart(stepFormat(), stepSurface());
+ MediaFormat fmt = stepFormat();
+ MediaFormat configFmt = fmt;
+ if (earlyFlushMode == FLUSH_BEFORE_CSD) {
+ // flush before CSD requires not submitting CSD with configure
+ configFmt = Media.removeCSD(fmt);
+ }
+ decoder.configureAndStart(configFmt, stepSurface());
+ if (earlyFlushMode != FLUSH_NEVER) {
+ decoder.flush();
+ // We must always queue CSD after a flush that is potentially
+ // before we receive output format has changed. This should
+ // work even after we receive the format change.
+ decoder.queueCSD(fmt);
+ }
int decodedFrames = -decoder.queueInputBufferRange(
stepMedia(),
0 /* startFrame */,
@@ -817,6 +839,7 @@
class Decoder implements MediaCodec.OnFrameRenderedListener {
private final static String TAG = "AdaptiveDecoder";
final long kTimeOutUs = 5000;
+ final long kCSDTimeOutUs = 1000000;
MediaCodec mCodec;
ByteBuffer[] mInputBuffers;
ByteBuffer[] mOutputBuffers;
@@ -1029,6 +1052,31 @@
return queueInputBufferRange(media,frameStartIx,frameEndIx,sendEosAtEnd,waitForEos,0);
}
+ public void queueCSD(MediaFormat format) {
+ MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
+ for (int csdIx = 0; ; ++csdIx) {
+ ByteBuffer csdBuf = format.getByteBuffer("csd-" + csdIx);
+ if (csdBuf == null) {
+ break;
+ }
+
+ int ix = mCodec.dequeueInputBuffer(kCSDTimeOutUs);
+ if (ix < 0) {
+ fail("Could not dequeue input buffer for CSD #" + csdIx);
+ return;
+ }
+
+ ByteBuffer buf = mInputBuffers[ix];
+ buf.clear();
+ buf.put((ByteBuffer)csdBuf.clear());
+ Log.v(TAG, "queue-CSD { [" + buf.position() + "]=" +
+ byteBufferToString(buf, 0, 16) + "} => #" + ix);
+ mCodec.queueInputBuffer(
+ ix, 0 /* offset */, buf.position(), 0 /* timeUs */,
+ MediaCodec.BUFFER_FLAG_CODEC_CONFIG);
+ }
+ }
+
public int queueInputBufferRange(
Media media, int frameStartIx, int frameEndIx, boolean sendEosAtEnd,
boolean waitForEos, long adjustTimeUs) {
@@ -1174,6 +1222,31 @@
return mFormat;
}
+ public static MediaFormat removeCSD(MediaFormat orig) {
+ MediaFormat copy = MediaFormat.createVideoFormat(
+ orig.getString(orig.KEY_MIME),
+ orig.getInteger(orig.KEY_WIDTH), orig.getInteger(orig.KEY_HEIGHT));
+ for (String k : new String[] {
+ orig.KEY_FRAME_RATE, orig.KEY_MAX_WIDTH, orig.KEY_MAX_HEIGHT,
+ orig.KEY_MAX_INPUT_SIZE
+ }) {
+ if (orig.containsKey(k)) {
+ try {
+ copy.setInteger(k, orig.getInteger(k));
+ } catch (ClassCastException e) {
+ try {
+ copy.setFloat(k, orig.getFloat(k));
+ } catch (ClassCastException e2) {
+ // Could not copy value. Don't fail here, as having non-standard
+ // value types for defined keys is permissible by the media API
+ // for optional keys.
+ }
+ }
+ }
+ }
+ return copy;
+ }
+
public MediaFormat getAdaptiveFormat(int width, int height) {
mAdaptiveFormat.setInteger(MediaFormat.KEY_MAX_WIDTH, width);
mAdaptiveFormat.setInteger(MediaFormat.KEY_MAX_HEIGHT, height);