Add fragmented mp4 test

The new test file
video_480x360_mp4_h264_1350kbps_30fps_aac_stereo_128kbps_44100hz_fragmented
was generated from the existing
video_480x360_mp4_h264_1350kbps_30fps_aac_stereo_128kbps_44100hz
with ffmpeg:
$ ffmpeg -re \
 -i video_480x360_mp4_h264_1350kbps_30fps_aac_stereo_128kbps_44100hz.mp4 \
 -f mp4 -movflags frag_keyframe+empty_moov -codec copy \
 video_480x360_mp4_h264_1350kbps_30fps_aac_stereo_128kbps_44100hz_fragmented.mp4
and contains the same data, just fragmented. It has no sidx box, since ffmpeg
does not appear to be capable of generating those.

Change-Id: I81ed29241e6ef91dd574447182e04c6b359b3e8a
diff --git a/tests/tests/media/res/raw/video_480x360_mp4_h264_1350kbps_30fps_aac_stereo_128kbps_44100hz_fragmented.mp4 b/tests/tests/media/res/raw/video_480x360_mp4_h264_1350kbps_30fps_aac_stereo_128kbps_44100hz_fragmented.mp4
new file mode 100644
index 0000000..c321586
--- /dev/null
+++ b/tests/tests/media/res/raw/video_480x360_mp4_h264_1350kbps_30fps_aac_stereo_128kbps_44100hz_fragmented.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 0fd4ef4..a43bc25 100644
--- a/tests/tests/media/src/android/media/cts/DecoderTest.java
+++ b/tests/tests/media/src/android/media/cts/DecoderTest.java
@@ -125,6 +125,248 @@
         monoTest(R.raw.monotestogg);
     }
 
+    public void testTrackSelection() throws Exception {
+        testTrackSelection(R.raw.video_480x360_mp4_h264_1350kbps_30fps_aac_stereo_128kbps_44100hz);
+        testTrackSelection(
+                R.raw.video_480x360_mp4_h264_1350kbps_30fps_aac_stereo_128kbps_44100hz_fragmented);
+    }
+
+    private void testTrackSelection(int resid) throws Exception {
+        AssetFileDescriptor fd1 = null;
+        try {
+            fd1 = mResources.openRawResourceFd(resid);
+            MediaExtractor ex1 = new MediaExtractor();
+            ex1.setDataSource(fd1.getFileDescriptor(), fd1.getStartOffset(), fd1.getLength());
+
+            ByteBuffer buf1 = ByteBuffer.allocate(1024*1024);
+            ArrayList<Integer> vid = new ArrayList<Integer>();
+            ArrayList<Integer> aud = new ArrayList<Integer>();
+
+            // scan the file once and build lists of audio and video samples
+            ex1.selectTrack(0);
+            ex1.selectTrack(1);
+            while(true) {
+                int n1 = ex1.readSampleData(buf1, 0);
+                if (n1 < 0) {
+                    break;
+                }
+                int idx = ex1.getSampleTrackIndex();
+                if (idx == 0) {
+                    vid.add(n1);
+                } else if (idx == 1) {
+                    aud.add(n1);
+                } else {
+                    fail("unexpected track index: " + idx);
+                }
+                ex1.advance();
+            }
+
+            // read the video track once, then rewind and do it again, and
+            // verify we get the right samples
+            ex1.release();
+            ex1 = new MediaExtractor();
+            ex1.setDataSource(fd1.getFileDescriptor(), fd1.getStartOffset(), fd1.getLength());
+            ex1.selectTrack(0);
+            for (int i = 0; i < 2; i++) {
+                ex1.seekTo(0, MediaExtractor.SEEK_TO_NEXT_SYNC);
+                int idx = 0;
+                while(true) {
+                    int n1 = ex1.readSampleData(buf1, 0);
+                    if (n1 < 0) {
+                        assertEquals(vid.size(), idx);
+                        break;
+                    }
+                    assertEquals(vid.get(idx++).intValue(), n1);
+                    ex1.advance();
+                }
+            }
+
+            // read the audio track once, then rewind and do it again, and
+            // verify we get the right samples
+            ex1.release();
+            ex1 = new MediaExtractor();
+            ex1.setDataSource(fd1.getFileDescriptor(), fd1.getStartOffset(), fd1.getLength());
+            ex1.selectTrack(1);
+            for (int i = 0; i < 2; i++) {
+                ex1.seekTo(0, MediaExtractor.SEEK_TO_NEXT_SYNC);
+                int idx = 0;
+                while(true) {
+                    int n1 = ex1.readSampleData(buf1, 0);
+                    if (n1 < 0) {
+                        assertEquals(aud.size(), idx);
+                        break;
+                    }
+                    assertEquals(aud.get(idx++).intValue(), n1);
+                    ex1.advance();
+                }
+            }
+
+            // read the video track first, then rewind and get the audio track instead, and
+            // verify we get the right samples
+            ex1.release();
+            ex1 = new MediaExtractor();
+            ex1.setDataSource(fd1.getFileDescriptor(), fd1.getStartOffset(), fd1.getLength());
+            for (int i = 0; i < 2; i++) {
+                ex1.selectTrack(i);
+                ex1.seekTo(0, MediaExtractor.SEEK_TO_NEXT_SYNC);
+                int idx = 0;
+                while(true) {
+                    int n1 = ex1.readSampleData(buf1, 0);
+                    if (i == 0) {
+                        if (n1 < 0) {
+                            assertEquals(vid.size(), idx);
+                            break;
+                        }
+                        assertEquals(vid.get(idx++).intValue(), n1);
+                    } else if (i == 1) {
+                        if (n1 < 0) {
+                            assertEquals(aud.size(), idx);
+                            break;
+                        }
+                        assertEquals(aud.get(idx++).intValue(), n1);
+                    } else {
+                        fail("unexpected track index: " + idx);
+                    }
+                    ex1.advance();
+                }
+                ex1.unselectTrack(i);
+            }
+
+            // read the video track first, then rewind, enable the audio track in addition
+            // to the video track, and verify we get the right samples
+            ex1.release();
+            ex1 = new MediaExtractor();
+            ex1.setDataSource(fd1.getFileDescriptor(), fd1.getStartOffset(), fd1.getLength());
+            for (int i = 0; i < 2; i++) {
+                ex1.selectTrack(i);
+                ex1.seekTo(0, MediaExtractor.SEEK_TO_NEXT_SYNC);
+                int vididx = 0;
+                int audidx = 0;
+                while(true) {
+                    int n1 = ex1.readSampleData(buf1, 0);
+                    if (n1 < 0) {
+                        // we should have read all audio and all video samples at this point
+                        assertEquals(vid.size(), vididx);
+                        if (i == 1) {
+                            assertEquals(aud.size(), audidx);
+                        }
+                        break;
+                    }
+                    int trackidx = ex1.getSampleTrackIndex();
+                    if (trackidx == 0) {
+                        assertEquals(vid.get(vididx++).intValue(), n1);
+                    } else if (trackidx == 1) {
+                        assertEquals(aud.get(audidx++).intValue(), n1);
+                    } else {
+                        fail("unexpected track index: " + trackidx);
+                    }
+                    ex1.advance();
+                }
+            }
+
+            // read both tracks from the start, then rewind and verify we get the right
+            // samples both times
+            ex1.release();
+            ex1 = new MediaExtractor();
+            ex1.setDataSource(fd1.getFileDescriptor(), fd1.getStartOffset(), fd1.getLength());
+            for (int i = 0; i < 2; i++) {
+                ex1.selectTrack(0);
+                ex1.selectTrack(1);
+                ex1.seekTo(0, MediaExtractor.SEEK_TO_NEXT_SYNC);
+                int vididx = 0;
+                int audidx = 0;
+                while(true) {
+                    int n1 = ex1.readSampleData(buf1, 0);
+                    if (n1 < 0) {
+                        // we should have read all audio and all video samples at this point
+                        assertEquals(vid.size(), vididx);
+                        assertEquals(aud.size(), audidx);
+                        break;
+                    }
+                    int trackidx = ex1.getSampleTrackIndex();
+                    if (trackidx == 0) {
+                        assertEquals(vid.get(vididx++).intValue(), n1);
+                    } else if (trackidx == 1) {
+                        assertEquals(aud.get(audidx++).intValue(), n1);
+                    } else {
+                        fail("unexpected track index: " + trackidx);
+                    }
+                    ex1.advance();
+                }
+            }
+
+        } finally {
+            if (fd1 != null) {
+                fd1.close();
+            }
+        }
+    }
+
+    public void testDecodeFragmented() throws Exception {
+        AssetFileDescriptor fd1 = null;
+        AssetFileDescriptor fd2 = null;
+        try {
+            fd1 = mResources.openRawResourceFd(
+                R.raw.video_480x360_mp4_h264_1350kbps_30fps_aac_stereo_128kbps_44100hz);
+            MediaExtractor ex1 = new MediaExtractor();
+            ex1.setDataSource(fd1.getFileDescriptor(), fd1.getStartOffset(), fd1.getLength());
+
+            fd2 = mResources.openRawResourceFd(
+                R.raw.video_480x360_mp4_h264_1350kbps_30fps_aac_stereo_128kbps_44100hz_fragmented);
+            MediaExtractor ex2 = new MediaExtractor();
+            ex2.setDataSource(fd2.getFileDescriptor(), fd2.getStartOffset(), fd2.getLength());
+
+            assertEquals("different track count", ex1.getTrackCount(), ex2.getTrackCount());
+
+            ByteBuffer buf1 = ByteBuffer.allocate(1024*1024);
+            ByteBuffer buf2 = ByteBuffer.allocate(1024*1024);
+
+            for (int i = 0; i < ex1.getTrackCount(); i++) {
+                // note: this assumes the tracks are reported in the order in which they appear
+                // in the file.
+                ex1.seekTo(0, MediaExtractor.SEEK_TO_NEXT_SYNC);
+                ex1.selectTrack(i);
+                ex2.seekTo(0, MediaExtractor.SEEK_TO_NEXT_SYNC);
+                ex2.selectTrack(i);
+
+                while(true) {
+                    int n1 = ex1.readSampleData(buf1, 0);
+                    int n2 = ex2.readSampleData(buf2, 0);
+                    assertEquals("different buffer size on track " + i, n1, n2);
+
+                    if (n1 < 0) {
+                        break;
+                    }
+                    // see bug 13008204
+                    buf1.limit(n1);
+                    buf2.limit(n2);
+                    buf1.rewind();
+                    buf2.rewind();
+
+                    assertEquals("limit does not match return value on track " + i,
+                            n1, buf1.limit());
+                    assertEquals("limit does not match return value on track " + i,
+                            n2, buf2.limit());
+
+                    assertEquals("buffer data did not match on track " + i, buf1, buf2);
+
+                    ex1.advance();
+                    ex2.advance();
+                }
+                ex1.unselectTrack(i);
+                ex2.unselectTrack(i);
+            }
+        } finally {
+            if (fd1 != null) {
+                fd1.close();
+            }
+            if (fd2 != null) {
+                fd2.close();
+            }
+        }
+    }
+
+
     private void monoTest(int res) throws Exception {
         short [] mono = decodeToMemory(res, RESET_MODE_NONE, CONFIG_MODE_NONE, -1, null);
         if (mono.length == 44100) {
diff --git a/tests/tests/media/src/android/media/cts/MediaPlayerTest.java b/tests/tests/media/src/android/media/cts/MediaPlayerTest.java
index a31bcbb..247209d 100644
--- a/tests/tests/media/src/android/media/cts/MediaPlayerTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaPlayerTest.java
@@ -691,6 +691,14 @@
                 R.raw.video_480x360_mp4_h264_1350kbps_30fps_aac_stereo_128kbps_44100hz, 480, 360);
     }
 
+    public void testLocalVideo_MP4_H264_480x360_1350kbps_30fps_AAC_Stereo_128kbps_44110Hz_frag()
+            throws Exception {
+        playVideoTest(
+                R.raw.video_480x360_mp4_h264_1350kbps_30fps_aac_stereo_128kbps_44100hz_fragmented,
+                480, 360);
+    }
+
+
     public void testLocalVideo_MP4_H264_480x360_1350kbps_30fps_AAC_Stereo_192kbps_44110Hz()
             throws Exception {
         playVideoTest(