mirror of
https://github.com/samsonjs/media.git
synced 2026-03-31 10:25:48 +00:00
Added test cases to the MP4Webvtt parser
This CL is prepares the ground for refactoring the Webvtt parser, so as to use the common parsing algorithms in both parsers. In order to do this, the Webvtt Parser will be refactored. As a side note, many more test cases will be added once the new subtitle features are implemented. Some useful test cases have also been left for a following CL, to allow an easy code review. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=110466914
This commit is contained in:
parent
dd497b1259
commit
33a2b2d0c5
2 changed files with 207 additions and 2 deletions
|
|
@ -0,0 +1,206 @@
|
|||
/*
|
||||
* Copyright (C) 2014 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.google.android.exoplayer.text.mp4webvtt;
|
||||
|
||||
import com.google.android.exoplayer.ParserException;
|
||||
import com.google.android.exoplayer.text.Cue;
|
||||
import com.google.android.exoplayer.text.Subtitle;
|
||||
import com.google.android.exoplayer.util.Util;
|
||||
|
||||
import android.util.ArraySet;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Unit test for {@link Mp4WebvttParser}.
|
||||
* As a side effect, it also involves the {@link Mp4WebvttSubtitle}.
|
||||
*/
|
||||
public final class Mp4WebvttParserTest extends TestCase {
|
||||
|
||||
private static final byte[] SINGLE_CUE_SAMPLE = {
|
||||
0x00, 0x00, 0x00, 0x1C, // Size
|
||||
0x76, 0x74, 0x74, 0x63, // "vttc" Box type. VTT Cue box begins:
|
||||
|
||||
0x00, 0x00, 0x00, 0x14, // Contained payload box's size
|
||||
0x70, 0x61, 0x79, 0x6c, // Contained payload box's type (payl), Cue Payload Box begins:
|
||||
|
||||
0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x0a // Hello World\n
|
||||
};
|
||||
|
||||
private static final byte[] DOUBLE_CUE_SAMPLE = {
|
||||
0x00, 0x00, 0x00, 0x1B, // Size
|
||||
0x76, 0x74, 0x74, 0x63, // "vttc" Box type. First VTT Cue box begins:
|
||||
|
||||
0x00, 0x00, 0x00, 0x13, // First contained payload box's size
|
||||
0x70, 0x61, 0x79, 0x6c, // First contained payload box's type (payl), Cue Payload Box begins:
|
||||
|
||||
0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, // Hello World
|
||||
|
||||
0x00, 0x00, 0x00, 0x17, // Size
|
||||
0x76, 0x74, 0x74, 0x63, // "vttc" Box type. Second VTT Cue box begins:
|
||||
|
||||
0x00, 0x00, 0x00, 0x0F, // Contained payload box's size
|
||||
0x70, 0x61, 0x79, 0x6c, // Contained payload box's type (payl), Payload begins:
|
||||
|
||||
0x42, 0x79, 0x65, 0x20, 0x42, 0x79, 0x65 // Bye Bye
|
||||
};
|
||||
|
||||
private static final byte[] NO_CUE_SAMPLE = {
|
||||
0x00, 0x00, 0x00, 0x1B, // Size
|
||||
0x74, 0x74, 0x74, 0x63, // "tttc" Box type, which is not a Cue. Should be skipped:
|
||||
|
||||
0x00, 0x00, 0x00, 0x13, // Contained payload box's size
|
||||
0x70, 0x61, 0x79, 0x6c, // Contained payload box's type (payl), Cue Payload Box begins:
|
||||
|
||||
0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64 // Hello World
|
||||
};
|
||||
|
||||
private static final byte[] NO_PAYLOAD_CUE_SAMPLE = {
|
||||
0x00, 0x00, 0x00, 0x1B, // Size
|
||||
0x76, 0x74, 0x74, 0x63, // Box type. First VTT Cue box begins:
|
||||
|
||||
0x00, 0x00, 0x00, 0x13, // First contained payload box's size
|
||||
0x71, 0x61, 0x79, 0x6c, // Type of box, which is not payload (qayl)
|
||||
|
||||
0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, // Hello World
|
||||
};
|
||||
|
||||
private static final byte[] INCOMPLETE_HEADER_SAMPLE = {
|
||||
0x00, 0x00, 0x00, 0x23, // Size
|
||||
0x76, 0x74, 0x74, 0x63, // "vttc" Box type. VTT Cue box begins:
|
||||
|
||||
0x00, 0x00, 0x00, 0x14, // Contained payload box's size
|
||||
0x70, 0x61, 0x79, 0x6c, // Contained payload box's type (payl), Cue Payload Box begins:
|
||||
|
||||
0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x0a, // Hello World\n
|
||||
|
||||
0x00, 0x00, 0x00, 0x07, // Size of an incomplete header, which belongs to the first vttc box.
|
||||
0x76, 0x74, 0x74
|
||||
};
|
||||
|
||||
|
||||
private Mp4WebvttParser parser;
|
||||
|
||||
@Override
|
||||
public void setUp() {
|
||||
parser = new Mp4WebvttParser();
|
||||
}
|
||||
|
||||
// Positive tests.
|
||||
|
||||
public void testSingleCueSample() throws IOException {
|
||||
Subtitle result = parser.parse(new ByteArrayInputStream(SINGLE_CUE_SAMPLE));
|
||||
Cue expectedCue = new Cue("Hello World"); // Line feed must be trimmed by the parser
|
||||
assertMp4WebvttSubtitleEquals(result, expectedCue);
|
||||
}
|
||||
|
||||
public void testTwoCuesSample() throws IOException {
|
||||
Subtitle result = parser.parse(new ByteArrayInputStream(DOUBLE_CUE_SAMPLE));
|
||||
Cue firstExpectedCue = new Cue("Hello World");
|
||||
Cue secondExpectedCue = new Cue("Bye Bye");
|
||||
assertMp4WebvttSubtitleEquals(result, firstExpectedCue, secondExpectedCue);
|
||||
}
|
||||
|
||||
public void testNoCueSample() throws IOException {
|
||||
Subtitle result = parser.parse(new ByteArrayInputStream(NO_CUE_SAMPLE));
|
||||
assertMp4WebvttSubtitleEquals(result, new Cue[] {});
|
||||
}
|
||||
|
||||
// Negative tests.
|
||||
|
||||
public void testSampleWithVttCueWithNoPayload() throws IOException {
|
||||
try {
|
||||
parser.parse(new ByteArrayInputStream(NO_PAYLOAD_CUE_SAMPLE));
|
||||
} catch (ParserException e) {
|
||||
// Expected.
|
||||
return;
|
||||
}
|
||||
fail("The parser should have failed, no payload was included in the VTTCue.");
|
||||
}
|
||||
|
||||
public void testSampleWithIncompleteHeader() throws IOException {
|
||||
try {
|
||||
parser.parse(new ByteArrayInputStream(INCOMPLETE_HEADER_SAMPLE));
|
||||
} catch (ParserException e) {
|
||||
return;
|
||||
}
|
||||
fail("The parser should have failed, no payload was included in the VTTCue.");
|
||||
}
|
||||
|
||||
// Util methods
|
||||
|
||||
/**
|
||||
* Asserts that the Subtitle's cues (which are all part of the event at t=0) are equal to the
|
||||
* expected Cues.
|
||||
*
|
||||
* @param sub The parsed {@link Subtitle} to check.
|
||||
* @param expectedCues Expected {@link Cue}s in order of appearance.
|
||||
*/
|
||||
private static void assertMp4WebvttSubtitleEquals(Subtitle sub, Cue... expectedCues) {
|
||||
assertEquals(1, sub.getEventTimeCount());
|
||||
assertEquals(0, sub.getEventTime(0));
|
||||
List<Cue> subtitleCues = sub.getCues(0);
|
||||
assertEquals(expectedCues.length, subtitleCues.size());
|
||||
for (int i = 0; i < subtitleCues.size(); i++) {
|
||||
Set<String> differences = getCueDifferences(subtitleCues.get(i), expectedCues[i]);
|
||||
assertTrue("Cues at position " + i + " are not equal. Different fields are "
|
||||
+ Arrays.toString(differences.toArray()), differences.isEmpty());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether two non null cues are equal. Check fails if any of the Cues are null.
|
||||
*
|
||||
* @return a set that contains the names of the different fields.
|
||||
*/
|
||||
private static Set<String> getCueDifferences(Cue aCue, Cue anotherCue) {
|
||||
assertNotNull(aCue);
|
||||
assertNotNull(anotherCue);
|
||||
Set<String> differences = new ArraySet<>();
|
||||
if (aCue.line != anotherCue.line) {
|
||||
differences.add("line: " + aCue.line + " | " + anotherCue.line);
|
||||
}
|
||||
if (aCue.lineAnchor != anotherCue.lineAnchor) {
|
||||
differences.add("lineAnchor: " + aCue.lineAnchor + " | " + anotherCue.lineAnchor);
|
||||
}
|
||||
if (aCue.lineType != anotherCue.lineType) {
|
||||
differences.add("lineType: " + aCue.lineType + " | " + anotherCue.lineType);
|
||||
}
|
||||
if (aCue.position != anotherCue.position) {
|
||||
differences.add("position: " + aCue.position + " | " + anotherCue.position);
|
||||
}
|
||||
if (aCue.positionAnchor != anotherCue.positionAnchor) {
|
||||
differences.add("positionAnchor: " + aCue.positionAnchor + " | " + anotherCue.positionAnchor);
|
||||
}
|
||||
if (aCue.size != anotherCue.size) {
|
||||
differences.add("size: " + aCue.size + " | " + anotherCue.size);
|
||||
}
|
||||
if (!Util.areEqual(aCue.text, anotherCue.text)) {
|
||||
differences.add("text: " + aCue.text + " | " + anotherCue.text);
|
||||
}
|
||||
if (!Util.areEqual(aCue.textAlignment, anotherCue.textAlignment)) {
|
||||
differences.add("textAlignment: " + aCue.textAlignment + " | " + anotherCue.textAlignment);
|
||||
}
|
||||
return differences;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -17,7 +17,6 @@ package com.google.android.exoplayer.text.mp4webvtt;
|
|||
|
||||
import com.google.android.exoplayer.ParserException;
|
||||
import com.google.android.exoplayer.text.Cue;
|
||||
import com.google.android.exoplayer.text.Subtitle;
|
||||
import com.google.android.exoplayer.text.SubtitleParser;
|
||||
import com.google.android.exoplayer.util.MimeTypes;
|
||||
import com.google.android.exoplayer.util.ParsableByteArray;
|
||||
|
|
@ -51,7 +50,7 @@ public final class Mp4WebvttParser implements SubtitleParser {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Subtitle parse(InputStream inputStream) throws IOException {
|
||||
public Mp4WebvttSubtitle parse(InputStream inputStream) throws IOException {
|
||||
// Webvtt in Mp4 samples have boxes inside of them, so we have to do a traditional box parsing:
|
||||
// first 4 bytes size and then 4 bytes type.
|
||||
int inputStreamByteCount = inputStream.available();
|
||||
|
|
|
|||
Loading…
Reference in a new issue