Check for correct frame ordering

Check that B frames come out of the decoder in the correct order,
for both fragmented and non-fragmented h264 mp4 files.

The new test files were created with:

 ffmpeg -i video_480x360_mp4_h264_1350kbps_30fps_aac_stereo_128kbps_44100hz.mp4\
    -f mp4 -vcodec h264 -profile:main -acodec copy video_h264_main_b_frames.mp4
and
 ffmpeg -i video_h264_main_b_frames.mp4 -f mp4\
    -movflags frag_keyframe+empty_moov -codec copy\
    video_h264_main_b_frames_frag.mp4

Change-Id: I33b4ced8688ab606689d7e8390caf1082c9df0c1
diff --git a/tests/tests/media/res/raw/video_h264_main_b_frames.mp4 b/tests/tests/media/res/raw/video_h264_main_b_frames.mp4
new file mode 100644
index 0000000..448ad3c
--- /dev/null
+++ b/tests/tests/media/res/raw/video_h264_main_b_frames.mp4
Binary files differ
diff --git a/tests/tests/media/res/raw/video_h264_main_b_frames_frag.mp4 b/tests/tests/media/res/raw/video_h264_main_b_frames_frag.mp4
new file mode 100644
index 0000000..b54a4d6c
--- /dev/null
+++ b/tests/tests/media/res/raw/video_h264_main_b_frames_frag.mp4
Binary files differ
diff --git a/tests/tests/media/src/android/media/cts/DecoderTest.java b/tests/tests/media/src/android/media/cts/DecoderTest.java
index 0b6e0d7..c870a53 100644
--- a/tests/tests/media/src/android/media/cts/DecoderTest.java
+++ b/tests/tests/media/src/android/media/cts/DecoderTest.java
@@ -133,6 +133,62 @@
                 R.raw.video_480x360_mp4_h264_1350kbps_30fps_aac_stereo_128kbps_44100hz_dash);
     }
 
+    public void testBFrames() throws Exception {
+        testBFrames(R.raw.video_h264_main_b_frames);
+        testBFrames(R.raw.video_h264_main_b_frames_frag);
+    }
+
+    public void testBFrames(int res) throws Exception {
+        AssetFileDescriptor fd = mResources.openRawResourceFd(res);
+        MediaExtractor ex = new MediaExtractor();
+        ex.setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getLength());
+        MediaFormat format = ex.getTrackFormat(0);
+        String mime = format.getString(MediaFormat.KEY_MIME);
+        assertTrue("not a video track. Wrong test file?", mime.startsWith("video/"));
+        MediaCodec dec = MediaCodec.createDecoderByType(mime);
+        Surface s = getActivity().getSurfaceHolder().getSurface();
+        dec.configure(format, s, null, 0);
+        dec.start();
+        ByteBuffer[] buf = dec.getInputBuffers();
+        ex.selectTrack(0);
+        MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
+        long lastPresentationTimeUsFromExtractor = -1;
+        long lastPresentationTimeUsFromDecoder = -1;
+        boolean inputoutoforder = false;
+        while(true) {
+            int flags = ex.getSampleFlags();
+            long time = ex.getSampleTime();
+            if (time >= 0 && time < lastPresentationTimeUsFromExtractor) {
+                inputoutoforder = true;
+            }
+            lastPresentationTimeUsFromExtractor = time;
+            int bufidx = dec.dequeueInputBuffer(5000);
+            if (bufidx >= 0) {
+                int n = ex.readSampleData(buf[bufidx], 0);
+                if (n < 0) {
+                    flags = MediaCodec.BUFFER_FLAG_END_OF_STREAM;
+                    time = 0;
+                    n = 0;
+                }
+                dec.queueInputBuffer(bufidx, 0, n, time, flags);
+                ex.advance();
+            }
+            int status = dec.dequeueOutputBuffer(info, 5000);
+            if (status >= 0) {
+                if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
+                    break;
+                }
+                assertTrue("out of order timestamp from decoder",
+                        info.presentationTimeUs > lastPresentationTimeUsFromDecoder);
+                dec.releaseOutputBuffer(status, true);
+                lastPresentationTimeUsFromDecoder = info.presentationTimeUs;
+            }
+        }
+        assertTrue("extractor timestamps were ordered, wrong test file?", inputoutoforder);
+        dec.release();
+        ex.release();
+      }
+
     private void testTrackSelection(int resid) throws Exception {
         AssetFileDescriptor fd1 = null;
         try {