blob: a105bbd192a1cd7730643a3238de95617978aad8 [file] [log] [blame]
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.providers.media.util;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import android.content.Context;
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
import com.android.providers.media.R;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@RunWith(AndroidJUnit4.class)
public class IsoInterfaceTest {
@Test
public void testSupportedMimeTypes() throws Exception {
assertTrue(IsoInterface.isSupportedMimeType("video/mp4"));
assertFalse(IsoInterface.isSupportedMimeType("image/jpeg"));
}
@Test
public void testTypeToString() throws Exception {
assertEquals("moov", IsoInterface.typeToString(0x6d6f6f76));
}
@Test
public void testRepeated() throws Exception {
final File file = stageFile(R.raw.test_video);
final IsoInterface mp4 = IsoInterface.fromFile(file);
final long[] ranges = mp4.getBoxRanges(0x746b6864); // tkhd
assertEquals(4, ranges.length);
assertEquals(105534 + 8, ranges[0]);
assertEquals(105534 + 92, ranges[1]);
assertEquals(118275 + 8, ranges[2]);
assertEquals(118275 + 92, ranges[3]);
}
@Test
public void testGps() throws Exception {
final File file = stageFile(R.raw.test_video_gps);
final IsoInterface mp4 = IsoInterface.fromFile(file);
final long[] ranges = mp4.getBoxRanges(0xa978797a); // ?xyz
assertEquals(2, ranges.length);
assertEquals(3369 + 8, ranges[0]);
assertEquals(3369 + 30, ranges[1]);
}
@Test
public void testGpsInIlst() throws Exception {
final File file = stageFile(R.raw.test_video_gps_ilst_tag);
final IsoInterface mp4 = IsoInterface.fromFile(file);
final long[] ranges = mp4.getBoxRanges(0xa978797a); // ?xyz
assertEquals(4, ranges.length);
assertEquals(2267, ranges[0]);
assertEquals(2267, ranges[1]);
assertEquals(2275, ranges[2]);
assertEquals(2309, ranges[3]);
}
@Test
public void testXmp() throws Exception {
final File file = stageFile(R.raw.test_video_xmp);
final IsoInterface mp4 = IsoInterface.fromFile(file);
final XmpInterface xmp = XmpInterface.fromContainer(mp4);
assertEquals("image/dng", xmp.getFormat());
assertEquals("xmp.did:041dfd42-0b46-4302-918a-836fba5016ed", xmp.getDocumentId());
assertEquals("xmp.iid:041dfd42-0b46-4302-918a-836fba5016ed", xmp.getInstanceId());
assertEquals("3F9DD7A46B26513A7C35272F0D623A06", xmp.getOriginalDocumentId());
}
@Test
@Ignore // This test creates a file that causes MediaProvider to OOM with our current
// IsoInterface implementation.
// While MediaProvider should now be resistant to that, we cannot leave this test safely enabled
// in a test suite as for b/316578793
// Leaving its implementation here to test further improvement to IsoInterface implementation.
public void testFileWithTooManyBoxesDoesNotRunOutOfMemory() throws Exception {
final File file = createFileWithLotsOfBoxes("too-many-boxes");
assertThrows(IOException.class, () -> IsoInterface.fromFile(file));
}
@Test
public void testIsoMeta() throws Exception {
final IsoInterface isoMeta = IsoInterface.fromFile(stageFile(R.raw.test_video_xmp));
final long[] hdlrRanges = isoMeta.getBoxRanges(IsoInterface.BOX_HDLR);
// There are 3 hdlr boxes, the 3rd is inside the meta box. Check it was parsed correctly.
assertEquals(3 * 2, hdlrRanges.length);
assertEquals(30145, hdlrRanges[2 * 2 + 0]);
assertEquals(30170, hdlrRanges[2 * 2 + 1]);
}
@Test
public void testQtMeta() throws Exception {
final IsoInterface qtMeta = IsoInterface.fromFile(stageFile(R.raw.testvideo_meta));
final long[] hdlrRanges = qtMeta.getBoxRanges(IsoInterface.BOX_HDLR);
// There are 3 hdlr boxes, the 1st is inside the meta box. Check it was parsed correctly.
assertEquals(3 * 2, hdlrRanges.length);
assertEquals(16636, hdlrRanges[2 * 0 + 0]);
assertEquals(16661, hdlrRanges[2 * 0 + 1]);
}
private static File stageFile(int resId) throws Exception {
final Context context = InstrumentationRegistry.getContext();
final File file = File.createTempFile("test", ".mp4");
try (InputStream in = context.getResources().openRawResource(resId);
OutputStream out = new FileOutputStream(file)) {
FileUtils.copy(in, out);
}
return file;
}
private static File createFileWithLotsOfBoxes(String filename) throws Exception {
File file = File.createTempFile(filename, ".mp4");
try (BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(file))) {
byte[] sizeHeader = new byte[]{0x00, 0x00, 0x00, 0x08};
out.write(sizeHeader);
out.write("ftyp".getBytes());
byte[] freeBlock = "free".getBytes();
for (int i = 0; i < 5000000; i++) {
out.write(sizeHeader);
out.write(freeBlock);
}
}
return file;
}
}