From 9c3ac92ae833575a9e2ef06eec797b207dd13b97 Mon Sep 17 00:00:00 2001 From: andrewlewis Date: Fri, 8 Feb 2019 15:32:31 +0000 Subject: [PATCH] Allow extension of MatroskaExtractor Subclasses can handle arbitrary elements. PiperOrigin-RevId: 233057241 --- .../extractor/mkv/DefaultEbmlReader.java | 38 +-- ...mlReaderOutput.java => EbmlProcessor.java} | 43 +-- .../exoplayer2/extractor/mkv/EbmlReader.java | 16 +- .../extractor/mkv/MatroskaExtractor.java | 283 +++++++++++------- .../extractor/mkv/DefaultEbmlReaderTest.java | 79 ++--- 5 files changed, 261 insertions(+), 198 deletions(-) rename library/core/src/main/java/com/google/android/exoplayer2/extractor/mkv/{EbmlReaderOutput.java => EbmlProcessor.java} (79%) diff --git a/library/core/src/main/java/com/google/android/exoplayer2/extractor/mkv/DefaultEbmlReader.java b/library/core/src/main/java/com/google/android/exoplayer2/extractor/mkv/DefaultEbmlReader.java index 0987bc473f..40908b9680 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/extractor/mkv/DefaultEbmlReader.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/extractor/mkv/DefaultEbmlReader.java @@ -52,7 +52,7 @@ import java.util.ArrayDeque; private final ArrayDeque masterElementsStack; private final VarintReader varintReader; - private EbmlReaderOutput output; + private EbmlProcessor processor; private @ElementState int elementState; private int elementId; private long elementContentSize; @@ -64,8 +64,8 @@ import java.util.ArrayDeque; } @Override - public void init(EbmlReaderOutput eventHandler) { - this.output = eventHandler; + public void init(EbmlProcessor processor) { + this.processor = processor; } @Override @@ -77,11 +77,11 @@ import java.util.ArrayDeque; @Override public boolean read(ExtractorInput input) throws IOException, InterruptedException { - Assertions.checkState(output != null); + Assertions.checkNotNull(processor); while (true) { if (!masterElementsStack.isEmpty() && input.getPosition() >= masterElementsStack.peek().elementEndPosition) { - output.endMasterElement(masterElementsStack.pop().elementId); + processor.endMasterElement(masterElementsStack.pop().elementId); return true; } @@ -103,42 +103,42 @@ import java.util.ArrayDeque; elementState = ELEMENT_STATE_READ_CONTENT; } - @EbmlReaderOutput.ElementType int type = output.getElementType(elementId); + @EbmlProcessor.ElementType int type = processor.getElementType(elementId); switch (type) { - case EbmlReaderOutput.TYPE_MASTER: + case EbmlProcessor.ELEMENT_TYPE_MASTER: long elementContentPosition = input.getPosition(); long elementEndPosition = elementContentPosition + elementContentSize; masterElementsStack.push(new MasterElement(elementId, elementEndPosition)); - output.startMasterElement(elementId, elementContentPosition, elementContentSize); + processor.startMasterElement(elementId, elementContentPosition, elementContentSize); elementState = ELEMENT_STATE_READ_ID; return true; - case EbmlReaderOutput.TYPE_UNSIGNED_INT: + case EbmlProcessor.ELEMENT_TYPE_UNSIGNED_INT: if (elementContentSize > MAX_INTEGER_ELEMENT_SIZE_BYTES) { throw new ParserException("Invalid integer size: " + elementContentSize); } - output.integerElement(elementId, readInteger(input, (int) elementContentSize)); + processor.integerElement(elementId, readInteger(input, (int) elementContentSize)); elementState = ELEMENT_STATE_READ_ID; return true; - case EbmlReaderOutput.TYPE_FLOAT: + case EbmlProcessor.ELEMENT_TYPE_FLOAT: if (elementContentSize != VALID_FLOAT32_ELEMENT_SIZE_BYTES && elementContentSize != VALID_FLOAT64_ELEMENT_SIZE_BYTES) { throw new ParserException("Invalid float size: " + elementContentSize); } - output.floatElement(elementId, readFloat(input, (int) elementContentSize)); + processor.floatElement(elementId, readFloat(input, (int) elementContentSize)); elementState = ELEMENT_STATE_READ_ID; return true; - case EbmlReaderOutput.TYPE_STRING: + case EbmlProcessor.ELEMENT_TYPE_STRING: if (elementContentSize > Integer.MAX_VALUE) { throw new ParserException("String element size: " + elementContentSize); } - output.stringElement(elementId, readString(input, (int) elementContentSize)); + processor.stringElement(elementId, readString(input, (int) elementContentSize)); elementState = ELEMENT_STATE_READ_ID; return true; - case EbmlReaderOutput.TYPE_BINARY: - output.binaryElement(elementId, (int) elementContentSize, input); + case EbmlProcessor.ELEMENT_TYPE_BINARY: + processor.binaryElement(elementId, (int) elementContentSize, input); elementState = ELEMENT_STATE_READ_ID; return true; - case EbmlReaderOutput.TYPE_UNKNOWN: + case EbmlProcessor.ELEMENT_TYPE_UNKNOWN: input.skipFully((int) elementContentSize); elementState = ELEMENT_STATE_READ_ID; break; @@ -167,7 +167,7 @@ import java.util.ArrayDeque; int varintLength = VarintReader.parseUnsignedVarintLength(scratch[0]); if (varintLength != C.LENGTH_UNSET && varintLength <= MAX_ID_BYTES) { int potentialId = (int) VarintReader.assembleVarint(scratch, varintLength, false); - if (output.isLevel1Element(potentialId)) { + if (processor.isLevel1Element(potentialId)) { input.skipFully(varintLength); return potentialId; } @@ -243,7 +243,7 @@ import java.util.ArrayDeque; /** * Used in {@link #masterElementsStack} to track when the current master element ends, so that - * {@link EbmlReaderOutput#endMasterElement(int)} can be called. + * {@link EbmlProcessor#endMasterElement(int)} can be called. */ private static final class MasterElement { diff --git a/library/core/src/main/java/com/google/android/exoplayer2/extractor/mkv/EbmlReaderOutput.java b/library/core/src/main/java/com/google/android/exoplayer2/extractor/mkv/EbmlProcessor.java similarity index 79% rename from library/core/src/main/java/com/google/android/exoplayer2/extractor/mkv/EbmlReaderOutput.java rename to library/core/src/main/java/com/google/android/exoplayer2/extractor/mkv/EbmlProcessor.java index cc17af5632..43e911e7f3 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/extractor/mkv/EbmlReaderOutput.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/extractor/mkv/EbmlProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016 The Android Open Source Project + * 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. @@ -23,41 +23,48 @@ import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; -/** - * Defines EBML element IDs/types and reacts to events. - */ -/* package */ interface EbmlReaderOutput { +/** Defines EBML element IDs/types and processes events. */ +public interface EbmlProcessor { /** - * EBML element types. One of {@link #TYPE_UNKNOWN}, {@link #TYPE_MASTER}, {@link - * #TYPE_UNSIGNED_INT}, {@link #TYPE_STRING}, {@link #TYPE_BINARY} or {@link #TYPE_FLOAT}. + * EBML element types. One of {@link #ELEMENT_TYPE_UNKNOWN}, {@link #ELEMENT_TYPE_MASTER}, {@link + * #ELEMENT_TYPE_UNSIGNED_INT}, {@link #ELEMENT_TYPE_STRING}, {@link #ELEMENT_TYPE_BINARY} or + * {@link #ELEMENT_TYPE_FLOAT}. */ @Documented @Retention(RetentionPolicy.SOURCE) - @IntDef({TYPE_UNKNOWN, TYPE_MASTER, TYPE_UNSIGNED_INT, TYPE_STRING, TYPE_BINARY, TYPE_FLOAT}) + @IntDef({ + ELEMENT_TYPE_UNKNOWN, + ELEMENT_TYPE_MASTER, + ELEMENT_TYPE_UNSIGNED_INT, + ELEMENT_TYPE_STRING, + ELEMENT_TYPE_BINARY, + ELEMENT_TYPE_FLOAT + }) @interface ElementType {} /** Type for unknown elements. */ - int TYPE_UNKNOWN = 0; + int ELEMENT_TYPE_UNKNOWN = 0; /** Type for elements that contain child elements. */ - int TYPE_MASTER = 1; + int ELEMENT_TYPE_MASTER = 1; /** Type for integer value elements of up to 8 bytes. */ - int TYPE_UNSIGNED_INT = 2; + int ELEMENT_TYPE_UNSIGNED_INT = 2; /** Type for string elements. */ - int TYPE_STRING = 3; + int ELEMENT_TYPE_STRING = 3; /** Type for binary elements. */ - int TYPE_BINARY = 4; + int ELEMENT_TYPE_BINARY = 4; /** Type for IEEE floating point value elements of either 4 or 8 bytes. */ - int TYPE_FLOAT = 5; + int ELEMENT_TYPE_FLOAT = 5; /** * Maps an element ID to a corresponding type. * - *

If {@link #TYPE_UNKNOWN} is returned then the element is skipped. Note that all children of - * a skipped element are also skipped. + *

If {@link #ELEMENT_TYPE_UNKNOWN} is returned then the element is skipped. Note that all + * children of a skipped element are also skipped. * * @param id The element ID to map. - * @return One of {@link #TYPE_UNKNOWN}, {@link #TYPE_MASTER}, {@link #TYPE_UNSIGNED_INT}, {@link - * #TYPE_STRING}, {@link #TYPE_BINARY} and {@link #TYPE_FLOAT}. + * @return One of {@link #ELEMENT_TYPE_UNKNOWN}, {@link #ELEMENT_TYPE_MASTER}, {@link + * #ELEMENT_TYPE_UNSIGNED_INT}, {@link #ELEMENT_TYPE_STRING}, {@link #ELEMENT_TYPE_BINARY} and + * {@link #ELEMENT_TYPE_FLOAT}. */ @ElementType int getElementType(int id); diff --git a/library/core/src/main/java/com/google/android/exoplayer2/extractor/mkv/EbmlReader.java b/library/core/src/main/java/com/google/android/exoplayer2/extractor/mkv/EbmlReader.java index 9987b3c8e6..c3f00a222f 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/extractor/mkv/EbmlReader.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/extractor/mkv/EbmlReader.java @@ -20,20 +20,20 @@ import com.google.android.exoplayer2.extractor.ExtractorInput; import java.io.IOException; /** - * Event-driven EBML reader that delivers events to an {@link EbmlReaderOutput}. - *

- * EBML can be summarized as a binary XML format somewhat similar to Protocol Buffers. It was - * originally designed for the Matroska container format. More information about EBML and - * Matroska is available here. + * Event-driven EBML reader that delivers events to an {@link EbmlProcessor}. + * + *

EBML can be summarized as a binary XML format somewhat similar to Protocol Buffers. It was + * originally designed for the Matroska container format. More information about EBML and Matroska + * is available here. */ /* package */ interface EbmlReader { /** - * Initializes the extractor with an {@link EbmlReaderOutput}. + * Initializes the extractor with an {@link EbmlProcessor}. * - * @param output An {@link EbmlReaderOutput} to receive events. + * @param processor An {@link EbmlProcessor} to process events. */ - void init(EbmlReaderOutput output); + void init(EbmlProcessor processor); /** * Resets the state of the reader. diff --git a/library/core/src/main/java/com/google/android/exoplayer2/extractor/mkv/MatroskaExtractor.java b/library/core/src/main/java/com/google/android/exoplayer2/extractor/mkv/MatroskaExtractor.java index 187b9ae443..e7ca6de910 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/extractor/mkv/MatroskaExtractor.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/extractor/mkv/MatroskaExtractor.java @@ -15,6 +15,7 @@ */ package com.google.android.exoplayer2.extractor.mkv; +import android.support.annotation.CallSuper; import android.support.annotation.IntDef; import android.support.annotation.Nullable; import android.util.Pair; @@ -57,10 +58,8 @@ import java.util.List; import java.util.Locale; import java.util.UUID; -/** - * Extracts data from the Matroska and WebM container formats. - */ -public final class MatroskaExtractor implements Extractor { +/** Extracts data from the Matroska and WebM container formats. */ +public class MatroskaExtractor implements Extractor { /** Factory for {@link MatroskaExtractor} instances. */ public static final ExtractorsFactory FACTORY = () -> new Extractor[] {new MatroskaExtractor()}; @@ -387,7 +386,7 @@ public final class MatroskaExtractor implements Extractor { /* package */ MatroskaExtractor(EbmlReader reader, @Flags int flags) { this.reader = reader; - this.reader.init(new InnerEbmlReaderOutput()); + this.reader.init(new InnerEbmlProcessor()); seekForCuesEnabled = (flags & FLAG_DISABLE_SEEK_FOR_CUES) == 0; varintReader = new VarintReader(); tracks = new SparseArray<>(); @@ -403,17 +402,17 @@ public final class MatroskaExtractor implements Extractor { } @Override - public boolean sniff(ExtractorInput input) throws IOException, InterruptedException { + public final boolean sniff(ExtractorInput input) throws IOException, InterruptedException { return new Sniffer().sniff(input); } @Override - public void init(ExtractorOutput output) { + public final void init(ExtractorOutput output) { extractorOutput = output; } @Override - public void seek(long position, long timeUs) { + public final void seek(long position, long timeUs) { clusterTimecodeUs = C.TIME_UNSET; blockState = BLOCK_STATE_START; reader.reset(); @@ -425,13 +424,13 @@ public final class MatroskaExtractor implements Extractor { } @Override - public void release() { + public final void release() { // Do nothing } @Override - public int read(ExtractorInput input, PositionHolder seekPosition) throws IOException, - InterruptedException { + public final int read(ExtractorInput input, PositionHolder seekPosition) + throws IOException, InterruptedException { sampleRead = false; boolean continueReading = true; while (continueReading && !sampleRead) { @@ -449,7 +448,125 @@ public final class MatroskaExtractor implements Extractor { return Extractor.RESULT_CONTINUE; } - /* package */ void startMasterElement(int id, long contentPosition, long contentSize) + /** + * Maps an element ID to a corresponding type. + * + * @see EbmlProcessor#getElementType(int) + */ + @CallSuper + @EbmlProcessor.ElementType + protected int getElementType(int id) { + switch (id) { + case ID_EBML: + case ID_SEGMENT: + case ID_SEEK_HEAD: + case ID_SEEK: + case ID_INFO: + case ID_CLUSTER: + case ID_TRACKS: + case ID_TRACK_ENTRY: + case ID_AUDIO: + case ID_VIDEO: + case ID_CONTENT_ENCODINGS: + case ID_CONTENT_ENCODING: + case ID_CONTENT_COMPRESSION: + case ID_CONTENT_ENCRYPTION: + case ID_CONTENT_ENCRYPTION_AES_SETTINGS: + case ID_CUES: + case ID_CUE_POINT: + case ID_CUE_TRACK_POSITIONS: + case ID_BLOCK_GROUP: + case ID_PROJECTION: + case ID_COLOUR: + case ID_MASTERING_METADATA: + return EbmlProcessor.ELEMENT_TYPE_MASTER; + case ID_EBML_READ_VERSION: + case ID_DOC_TYPE_READ_VERSION: + case ID_SEEK_POSITION: + case ID_TIMECODE_SCALE: + case ID_TIME_CODE: + case ID_BLOCK_DURATION: + case ID_PIXEL_WIDTH: + case ID_PIXEL_HEIGHT: + case ID_DISPLAY_WIDTH: + case ID_DISPLAY_HEIGHT: + case ID_DISPLAY_UNIT: + case ID_TRACK_NUMBER: + case ID_TRACK_TYPE: + case ID_FLAG_DEFAULT: + case ID_FLAG_FORCED: + case ID_DEFAULT_DURATION: + case ID_CODEC_DELAY: + case ID_SEEK_PRE_ROLL: + case ID_CHANNELS: + case ID_AUDIO_BIT_DEPTH: + case ID_CONTENT_ENCODING_ORDER: + case ID_CONTENT_ENCODING_SCOPE: + case ID_CONTENT_COMPRESSION_ALGORITHM: + case ID_CONTENT_ENCRYPTION_ALGORITHM: + case ID_CONTENT_ENCRYPTION_AES_SETTINGS_CIPHER_MODE: + case ID_CUE_TIME: + case ID_CUE_CLUSTER_POSITION: + case ID_REFERENCE_BLOCK: + case ID_STEREO_MODE: + case ID_COLOUR_RANGE: + case ID_COLOUR_TRANSFER: + case ID_COLOUR_PRIMARIES: + case ID_MAX_CLL: + case ID_MAX_FALL: + case ID_PROJECTION_TYPE: + return EbmlProcessor.ELEMENT_TYPE_UNSIGNED_INT; + case ID_DOC_TYPE: + case ID_NAME: + case ID_CODEC_ID: + case ID_LANGUAGE: + return EbmlProcessor.ELEMENT_TYPE_STRING; + case ID_SEEK_ID: + case ID_CONTENT_COMPRESSION_SETTINGS: + case ID_CONTENT_ENCRYPTION_KEY_ID: + case ID_SIMPLE_BLOCK: + case ID_BLOCK: + case ID_CODEC_PRIVATE: + case ID_PROJECTION_PRIVATE: + return EbmlProcessor.ELEMENT_TYPE_BINARY; + case ID_DURATION: + case ID_SAMPLING_FREQUENCY: + case ID_PRIMARY_R_CHROMATICITY_X: + case ID_PRIMARY_R_CHROMATICITY_Y: + case ID_PRIMARY_G_CHROMATICITY_X: + case ID_PRIMARY_G_CHROMATICITY_Y: + case ID_PRIMARY_B_CHROMATICITY_X: + case ID_PRIMARY_B_CHROMATICITY_Y: + case ID_WHITE_POINT_CHROMATICITY_X: + case ID_WHITE_POINT_CHROMATICITY_Y: + case ID_LUMNINANCE_MAX: + case ID_LUMNINANCE_MIN: + case ID_PROJECTION_POSE_YAW: + case ID_PROJECTION_POSE_PITCH: + case ID_PROJECTION_POSE_ROLL: + return EbmlProcessor.ELEMENT_TYPE_FLOAT; + default: + return EbmlProcessor.ELEMENT_TYPE_UNKNOWN; + } + } + + /** + * Checks if the given id is that of a level 1 element. + * + * @see EbmlProcessor#isLevel1Element(int) + */ + @CallSuper + protected boolean isLevel1Element(int id) { + return id == ID_SEGMENT_INFO || id == ID_CLUSTER || id == ID_CUES || id == ID_TRACKS; + } + + /** + * Called when the start of a master element is encountered. + * + * @see EbmlProcessor#startMasterElement(int, long, long) + */ + @CallSuper + protected void startMasterElement(int id, long contentPosition, long contentSize) throws ParserException { switch (id) { case ID_SEGMENT: @@ -505,7 +622,13 @@ public final class MatroskaExtractor implements Extractor { } } - /* package */ void endMasterElement(int id) throws ParserException { + /** + * Called when the end of a master element is encountered. + * + * @see EbmlProcessor#endMasterElement(int) + */ + @CallSuper + protected void endMasterElement(int id) throws ParserException { switch (id) { case ID_SEGMENT_INFO: if (timecodeScale == C.TIME_UNSET) { @@ -576,7 +699,13 @@ public final class MatroskaExtractor implements Extractor { } } - /* package */ void integerElement(int id, long value) throws ParserException { + /** + * Called when an integer element is encountered. + * + * @see EbmlProcessor#integerElement(int, long) + */ + @CallSuper + protected void integerElement(int id, long value) throws ParserException { switch (id) { case ID_EBML_READ_VERSION: // Validate that EBMLReadVersion is supported. This extractor only supports v1. @@ -787,7 +916,13 @@ public final class MatroskaExtractor implements Extractor { } } - /* package */ void floatElement(int id, double value) { + /** + * Called when a float element is encountered. + * + * @see EbmlProcessor#floatElement(int, double) + */ + @CallSuper + protected void floatElement(int id, double value) throws ParserException { switch (id) { case ID_DURATION: durationTimecode = (long) value; @@ -839,7 +974,13 @@ public final class MatroskaExtractor implements Extractor { } } - /* package */ void stringElement(int id, String value) throws ParserException { + /** + * Called when a string element is encountered. + * + * @see EbmlProcessor#stringElement(int, String) + */ + @CallSuper + protected void stringElement(int id, String value) throws ParserException { switch (id) { case ID_DOC_TYPE: // Validate that DocType is supported. @@ -861,7 +1002,13 @@ public final class MatroskaExtractor implements Extractor { } } - /* package */ void binaryElement(int id, int contentSize, ExtractorInput input) + /** + * Called when a binary element is encountered. + * + * @see EbmlProcessor#binaryElement(int, int, ExtractorInput) + */ + @CallSuper + protected void binaryElement(int id, int contentSize, ExtractorInput input) throws IOException, InterruptedException { switch (id) { case ID_SEEK_ID: @@ -1431,110 +1578,18 @@ public final class MatroskaExtractor implements Extractor { } } - /** - * Passes events through to the outer {@link MatroskaExtractor}. - */ - private final class InnerEbmlReaderOutput implements EbmlReaderOutput { + /** Passes events through to the outer {@link MatroskaExtractor}. */ + private final class InnerEbmlProcessor implements EbmlProcessor { @Override + @ElementType public int getElementType(int id) { - switch (id) { - case ID_EBML: - case ID_SEGMENT: - case ID_SEEK_HEAD: - case ID_SEEK: - case ID_INFO: - case ID_CLUSTER: - case ID_TRACKS: - case ID_TRACK_ENTRY: - case ID_AUDIO: - case ID_VIDEO: - case ID_CONTENT_ENCODINGS: - case ID_CONTENT_ENCODING: - case ID_CONTENT_COMPRESSION: - case ID_CONTENT_ENCRYPTION: - case ID_CONTENT_ENCRYPTION_AES_SETTINGS: - case ID_CUES: - case ID_CUE_POINT: - case ID_CUE_TRACK_POSITIONS: - case ID_BLOCK_GROUP: - case ID_PROJECTION: - case ID_COLOUR: - case ID_MASTERING_METADATA: - return TYPE_MASTER; - case ID_EBML_READ_VERSION: - case ID_DOC_TYPE_READ_VERSION: - case ID_SEEK_POSITION: - case ID_TIMECODE_SCALE: - case ID_TIME_CODE: - case ID_BLOCK_DURATION: - case ID_PIXEL_WIDTH: - case ID_PIXEL_HEIGHT: - case ID_DISPLAY_WIDTH: - case ID_DISPLAY_HEIGHT: - case ID_DISPLAY_UNIT: - case ID_TRACK_NUMBER: - case ID_TRACK_TYPE: - case ID_FLAG_DEFAULT: - case ID_FLAG_FORCED: - case ID_DEFAULT_DURATION: - case ID_CODEC_DELAY: - case ID_SEEK_PRE_ROLL: - case ID_CHANNELS: - case ID_AUDIO_BIT_DEPTH: - case ID_CONTENT_ENCODING_ORDER: - case ID_CONTENT_ENCODING_SCOPE: - case ID_CONTENT_COMPRESSION_ALGORITHM: - case ID_CONTENT_ENCRYPTION_ALGORITHM: - case ID_CONTENT_ENCRYPTION_AES_SETTINGS_CIPHER_MODE: - case ID_CUE_TIME: - case ID_CUE_CLUSTER_POSITION: - case ID_REFERENCE_BLOCK: - case ID_STEREO_MODE: - case ID_COLOUR_RANGE: - case ID_COLOUR_TRANSFER: - case ID_COLOUR_PRIMARIES: - case ID_MAX_CLL: - case ID_MAX_FALL: - case ID_PROJECTION_TYPE: - return TYPE_UNSIGNED_INT; - case ID_DOC_TYPE: - case ID_NAME: - case ID_CODEC_ID: - case ID_LANGUAGE: - return TYPE_STRING; - case ID_SEEK_ID: - case ID_CONTENT_COMPRESSION_SETTINGS: - case ID_CONTENT_ENCRYPTION_KEY_ID: - case ID_SIMPLE_BLOCK: - case ID_BLOCK: - case ID_CODEC_PRIVATE: - case ID_PROJECTION_PRIVATE: - return TYPE_BINARY; - case ID_DURATION: - case ID_SAMPLING_FREQUENCY: - case ID_PRIMARY_R_CHROMATICITY_X: - case ID_PRIMARY_R_CHROMATICITY_Y: - case ID_PRIMARY_G_CHROMATICITY_X: - case ID_PRIMARY_G_CHROMATICITY_Y: - case ID_PRIMARY_B_CHROMATICITY_X: - case ID_PRIMARY_B_CHROMATICITY_Y: - case ID_WHITE_POINT_CHROMATICITY_X: - case ID_WHITE_POINT_CHROMATICITY_Y: - case ID_LUMNINANCE_MAX: - case ID_LUMNINANCE_MIN: - case ID_PROJECTION_POSE_YAW: - case ID_PROJECTION_POSE_PITCH: - case ID_PROJECTION_POSE_ROLL: - return TYPE_FLOAT; - default: - return TYPE_UNKNOWN; - } + return MatroskaExtractor.this.getElementType(id); } @Override public boolean isLevel1Element(int id) { - return id == ID_SEGMENT_INFO || id == ID_CLUSTER || id == ID_CUES || id == ID_TRACKS; + return MatroskaExtractor.this.isLevel1Element(id); } @Override diff --git a/library/core/src/test/java/com/google/android/exoplayer2/extractor/mkv/DefaultEbmlReaderTest.java b/library/core/src/test/java/com/google/android/exoplayer2/extractor/mkv/DefaultEbmlReaderTest.java index 7383f8a538..b1c5171746 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/extractor/mkv/DefaultEbmlReaderTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/extractor/mkv/DefaultEbmlReaderTest.java @@ -37,19 +37,19 @@ public class DefaultEbmlReaderTest { @Test public void testMasterElement() throws IOException, InterruptedException { ExtractorInput input = createTestInput(0x1A, 0x45, 0xDF, 0xA3, 0x84, 0x42, 0x85, 0x81, 0x01); - TestOutput expected = new TestOutput(); - expected.startMasterElement(TestOutput.ID_EBML, 5, 4); - expected.integerElement(TestOutput.ID_DOC_TYPE_READ_VERSION, 1); - expected.endMasterElement(TestOutput.ID_EBML); + TestProcessor expected = new TestProcessor(); + expected.startMasterElement(TestProcessor.ID_EBML, 5, 4); + expected.integerElement(TestProcessor.ID_DOC_TYPE_READ_VERSION, 1); + expected.endMasterElement(TestProcessor.ID_EBML); assertEvents(input, expected.events); } @Test public void testMasterElementEmpty() throws IOException, InterruptedException { ExtractorInput input = createTestInput(0x18, 0x53, 0x80, 0x67, 0x80); - TestOutput expected = new TestOutput(); - expected.startMasterElement(TestOutput.ID_SEGMENT, 5, 0); - expected.endMasterElement(TestOutput.ID_SEGMENT); + TestProcessor expected = new TestProcessor(); + expected.startMasterElement(TestProcessor.ID_SEGMENT, 5, 0); + expected.endMasterElement(TestProcessor.ID_SEGMENT); assertEvents(input, expected.events); } @@ -57,8 +57,8 @@ public class DefaultEbmlReaderTest { public void testUnsignedIntegerElement() throws IOException, InterruptedException { // 0xFE is chosen because for signed integers it should be interpreted as -2 ExtractorInput input = createTestInput(0x42, 0xF7, 0x81, 0xFE); - TestOutput expected = new TestOutput(); - expected.integerElement(TestOutput.ID_EBML_READ_VERSION, 254); + TestProcessor expected = new TestProcessor(); + expected.integerElement(TestProcessor.ID_EBML_READ_VERSION, 254); assertEvents(input, expected.events); } @@ -66,8 +66,8 @@ public class DefaultEbmlReaderTest { public void testUnsignedIntegerElementLarge() throws IOException, InterruptedException { ExtractorInput input = createTestInput(0x42, 0xF7, 0x88, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); - TestOutput expected = new TestOutput(); - expected.integerElement(TestOutput.ID_EBML_READ_VERSION, Long.MAX_VALUE); + TestProcessor expected = new TestProcessor(); + expected.integerElement(TestProcessor.ID_EBML_READ_VERSION, Long.MAX_VALUE); assertEvents(input, expected.events); } @@ -76,32 +76,32 @@ public class DefaultEbmlReaderTest { throws IOException, InterruptedException { ExtractorInput input = createTestInput(0x42, 0xF7, 0x88, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); - TestOutput expected = new TestOutput(); - expected.integerElement(TestOutput.ID_EBML_READ_VERSION, -1); + TestProcessor expected = new TestProcessor(); + expected.integerElement(TestProcessor.ID_EBML_READ_VERSION, -1); assertEvents(input, expected.events); } @Test public void testStringElement() throws IOException, InterruptedException { ExtractorInput input = createTestInput(0x42, 0x82, 0x86, 0x41, 0x62, 0x63, 0x31, 0x32, 0x33); - TestOutput expected = new TestOutput(); - expected.stringElement(TestOutput.ID_DOC_TYPE, "Abc123"); + TestProcessor expected = new TestProcessor(); + expected.stringElement(TestProcessor.ID_DOC_TYPE, "Abc123"); assertEvents(input, expected.events); } @Test public void testStringElementWithZeroPadding() throws IOException, InterruptedException { ExtractorInput input = createTestInput(0x42, 0x82, 0x86, 0x41, 0x62, 0x63, 0x00, 0x00, 0x00); - TestOutput expected = new TestOutput(); - expected.stringElement(TestOutput.ID_DOC_TYPE, "Abc"); + TestProcessor expected = new TestProcessor(); + expected.stringElement(TestProcessor.ID_DOC_TYPE, "Abc"); assertEvents(input, expected.events); } @Test public void testStringElementEmpty() throws IOException, InterruptedException { ExtractorInput input = createTestInput(0x42, 0x82, 0x80); - TestOutput expected = new TestOutput(); - expected.stringElement(TestOutput.ID_DOC_TYPE, ""); + TestProcessor expected = new TestProcessor(); + expected.stringElement(TestProcessor.ID_DOC_TYPE, ""); assertEvents(input, expected.events); } @@ -109,8 +109,8 @@ public class DefaultEbmlReaderTest { public void testFloatElementFourBytes() throws IOException, InterruptedException { ExtractorInput input = createTestInput(0x44, 0x89, 0x84, 0x3F, 0x80, 0x00, 0x00); - TestOutput expected = new TestOutput(); - expected.floatElement(TestOutput.ID_DURATION, 1.0); + TestProcessor expected = new TestProcessor(); + expected.floatElement(TestProcessor.ID_DURATION, 1.0); assertEvents(input, expected.events); } @@ -118,8 +118,8 @@ public class DefaultEbmlReaderTest { public void testFloatElementEightBytes() throws IOException, InterruptedException { ExtractorInput input = createTestInput(0x44, 0x89, 0x88, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); - TestOutput expected = new TestOutput(); - expected.floatElement(TestOutput.ID_DURATION, -2.0); + TestProcessor expected = new TestProcessor(); + expected.floatElement(TestProcessor.ID_DURATION, -2.0); assertEvents(input, expected.events); } @@ -127,8 +127,10 @@ public class DefaultEbmlReaderTest { public void testBinaryElement() throws IOException, InterruptedException { ExtractorInput input = createTestInput(0xA3, 0x88, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08); - TestOutput expected = new TestOutput(); - expected.binaryElement(TestOutput.ID_SIMPLE_BLOCK, 8, + TestProcessor expected = new TestProcessor(); + expected.binaryElement( + TestProcessor.ID_SIMPLE_BLOCK, + 8, createTestInput(0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08)); assertEvents(input, expected.events); } @@ -136,7 +138,7 @@ public class DefaultEbmlReaderTest { private static void assertEvents(ExtractorInput input, List expectedEvents) throws IOException, InterruptedException { DefaultEbmlReader reader = new DefaultEbmlReader(); - TestOutput output = new TestOutput(); + TestProcessor output = new TestProcessor(); reader.init(output); // We expect the number of successful reads to equal the number of expected events. @@ -164,10 +166,8 @@ public class DefaultEbmlReaderTest { .build(); } - /** - * An {@link EbmlReaderOutput} that records each event callback. - */ - private static final class TestOutput implements EbmlReaderOutput { + /** An {@link EbmlProcessor} that records each event callback. */ + private static final class TestProcessor implements EbmlProcessor { // Element IDs private static final int ID_EBML = 0x1A45DFA3; @@ -182,22 +182,23 @@ public class DefaultEbmlReaderTest { private final List events = new ArrayList<>(); @Override - public @ElementType int getElementType(int id) { + @EbmlProcessor.ElementType + public int getElementType(int id) { switch (id) { case ID_EBML: case ID_SEGMENT: - return TYPE_MASTER; + return EbmlProcessor.ELEMENT_TYPE_MASTER; case ID_EBML_READ_VERSION: case ID_DOC_TYPE_READ_VERSION: - return TYPE_UNSIGNED_INT; + return EbmlProcessor.ELEMENT_TYPE_UNSIGNED_INT; case ID_DOC_TYPE: - return TYPE_STRING; + return EbmlProcessor.ELEMENT_TYPE_STRING; case ID_SIMPLE_BLOCK: - return TYPE_BINARY; + return EbmlProcessor.ELEMENT_TYPE_BINARY; case ID_DURATION: - return TYPE_FLOAT; + return EbmlProcessor.ELEMENT_TYPE_FLOAT; default: - return TYPE_UNKNOWN; + return EbmlProcessor.ELEMENT_TYPE_UNKNOWN; } } @@ -219,12 +220,12 @@ public class DefaultEbmlReaderTest { @Override public void integerElement(int id, long value) { - events.add(formatEvent(id, "integer=" + String.valueOf(value))); + events.add(formatEvent(id, "integer=" + value)); } @Override public void floatElement(int id, double value) { - events.add(formatEvent(id, "float=" + String.valueOf(value))); + events.add(formatEvent(id, "float=" + value)); } @Override