From 25c241e5bc9c179cb5681072faed9b490fd8861e Mon Sep 17 00:00:00 2001 From: Drew Hill Date: Sat, 17 Feb 2018 13:08:14 -0500 Subject: [PATCH 1/3] add h263 format support in fourcc codecID --- .../extractor/mkv/MatroskaExtractor.java | 30 +++++++++++++++---- 1 file changed, 24 insertions(+), 6 deletions(-) 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 57128f45f0..0712434555 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 @@ -18,6 +18,7 @@ package com.google.android.exoplayer2.extractor.mkv; import android.support.annotation.IntDef; import android.support.annotation.Nullable; import android.util.Log; +import android.util.Pair; import android.util.SparseArray; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; @@ -219,6 +220,7 @@ public final class MatroskaExtractor implements Extractor { private static final int LACING_EBML = 3; private static final int FOURCC_COMPRESSION_VC1 = 0x31435657; + private static final int FOURCC_COMPRESSION_DIVX = 0x58564944; /** * A template for the prefix that must be added to each subrip sample. The 12 byte end timecode @@ -1711,9 +1713,22 @@ public final class MatroskaExtractor implements Extractor { nalUnitLengthFieldLength = hevcConfig.nalUnitLengthFieldLength; break; case CODEC_ID_FOURCC: - initializationData = parseFourCcVc1Private(new ParsableByteArray(codecPrivate)); - if (initializationData != null) { - mimeType = MimeTypes.VIDEO_VC1; + initializationData = null; + Pair> pair = parseFourCcVc1Private(new ParsableByteArray(codecPrivate)); + if (pair != null) { + initializationData = pair.second; + switch (pair.first) { + case FOURCC_COMPRESSION_VC1: + mimeType = MimeTypes.VIDEO_VC1; + break; + case FOURCC_COMPRESSION_DIVX: + mimeType = MimeTypes.VIDEO_H263; + break; + default: + Log.w(TAG, "Unknown FourCC. Setting mimeType to " + MimeTypes.VIDEO_UNKNOWN); + mimeType = MimeTypes.VIDEO_UNKNOWN; + break; + } } else { Log.w(TAG, "Unsupported FourCC. Setting mimeType to " + MimeTypes.VIDEO_UNKNOWN); mimeType = MimeTypes.VIDEO_UNKNOWN; @@ -1938,12 +1953,15 @@ public final class MatroskaExtractor implements Extractor { * not VC1. * @throws ParserException If the initialization data could not be built. */ - private static List parseFourCcVc1Private(ParsableByteArray buffer) + private static Pair> parseFourCcVc1Private(ParsableByteArray buffer) throws ParserException { try { buffer.skipBytes(16); // size(4), width(4), height(4), planes(2), bitcount(2). long compression = buffer.readLittleEndianUnsignedInt(); - if (compression != FOURCC_COMPRESSION_VC1) { + if (compression == FOURCC_COMPRESSION_DIVX) { + return new Pair(FOURCC_COMPRESSION_DIVX, null); + } + if (compression != FOURCC_COMPRESSION_VC1) { return null; } @@ -1956,7 +1974,7 @@ public final class MatroskaExtractor implements Extractor { && bufferData[offset + 2] == 0x01 && bufferData[offset + 3] == 0x0F) { // We've found the initialization data. byte[] initializationData = Arrays.copyOfRange(bufferData, offset, bufferData.length); - return Collections.singletonList(initializationData); + return new Pair(FOURCC_COMPRESSION_VC1, Collections.singletonList(initializationData)); } } From 9e340291dee9e828150ad948e535e5293afcd167 Mon Sep 17 00:00:00 2001 From: Drew Hill Date: Sun, 18 Feb 2018 16:53:56 -0500 Subject: [PATCH 2/3] mkv h263 CR changes --- .../extractor/mkv/MatroskaExtractor.java | 68 +++++++------------ 1 file changed, 26 insertions(+), 42 deletions(-) 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 0712434555..b32a634bcc 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 @@ -1713,26 +1713,9 @@ public final class MatroskaExtractor implements Extractor { nalUnitLengthFieldLength = hevcConfig.nalUnitLengthFieldLength; break; case CODEC_ID_FOURCC: - initializationData = null; - Pair> pair = parseFourCcVc1Private(new ParsableByteArray(codecPrivate)); - if (pair != null) { - initializationData = pair.second; - switch (pair.first) { - case FOURCC_COMPRESSION_VC1: - mimeType = MimeTypes.VIDEO_VC1; - break; - case FOURCC_COMPRESSION_DIVX: - mimeType = MimeTypes.VIDEO_H263; - break; - default: - Log.w(TAG, "Unknown FourCC. Setting mimeType to " + MimeTypes.VIDEO_UNKNOWN); - mimeType = MimeTypes.VIDEO_UNKNOWN; - break; - } - } else { - Log.w(TAG, "Unsupported FourCC. Setting mimeType to " + MimeTypes.VIDEO_UNKNOWN); - mimeType = MimeTypes.VIDEO_UNKNOWN; - } + Pair> pair = parseFourCcPrivate(new ParsableByteArray(codecPrivate)); + mimeType = pair.first; + initializationData = pair.second; break; case CODEC_ID_THEORA: // TODO: This can be set to the real mimeType if/when we work out what initializationData @@ -1947,41 +1930,42 @@ public final class MatroskaExtractor implements Extractor { /** * Builds initialization data for a {@link Format} from FourCC codec private data. *

- * VC1 is the only supported compression type. + * VC1 and H263 are the only supported compression types. * - * @return The initialization data for the {@link Format}, or null if the compression type is - * not VC1. + * @return A pair object with the first object being the codec mime type + * and the second object the initialization data for the {@link Format}, + * or null if the compression type is not VC1. * @throws ParserException If the initialization data could not be built. */ - private static Pair> parseFourCcVc1Private(ParsableByteArray buffer) + private static Pair> parseFourCcPrivate(ParsableByteArray buffer) throws ParserException { try { buffer.skipBytes(16); // size(4), width(4), height(4), planes(2), bitcount(2). long compression = buffer.readLittleEndianUnsignedInt(); if (compression == FOURCC_COMPRESSION_DIVX) { - return new Pair(FOURCC_COMPRESSION_DIVX, null); + return new Pair<>(MimeTypes.VIDEO_H263, null); } - if (compression != FOURCC_COMPRESSION_VC1) { - return null; - } - - // Search for the initialization data from the end of the BITMAPINFOHEADER. The last 20 - // bytes of which are: sizeImage(4), xPel/m (4), yPel/m (4), clrUsed(4), clrImportant(4). - int startOffset = buffer.getPosition() + 20; - byte[] bufferData = buffer.data; - for (int offset = startOffset; offset < bufferData.length - 4; offset++) { - if (bufferData[offset] == 0x00 && bufferData[offset + 1] == 0x00 - && bufferData[offset + 2] == 0x01 && bufferData[offset + 3] == 0x0F) { - // We've found the initialization data. - byte[] initializationData = Arrays.copyOfRange(bufferData, offset, bufferData.length); - return new Pair(FOURCC_COMPRESSION_VC1, Collections.singletonList(initializationData)); + else if (compression == FOURCC_COMPRESSION_VC1) { + // Search for the initialization data from the end of the BITMAPINFOHEADER. The last 20 + // bytes of which are: sizeImage(4), xPel/m (4), yPel/m (4), clrUsed(4), clrImportant(4). + int startOffset = buffer.getPosition() + 20; + byte[] bufferData = buffer.data; + for (int offset = startOffset; offset < bufferData.length - 4; offset++) { + if (bufferData[offset] == 0x00 && bufferData[offset + 1] == 0x00 + && bufferData[offset + 2] == 0x01 && bufferData[offset + 3] == 0x0F) { + // We've found the initialization data. + byte[] initializationData = Arrays.copyOfRange(bufferData, offset, bufferData.length); + return new Pair<>(MimeTypes.VIDEO_VC1, Collections.singletonList(initializationData)); + } } + throw new ParserException("Failed to find FourCC VC1 initialization data"); } - - throw new ParserException("Failed to find FourCC VC1 initialization data"); } catch (ArrayIndexOutOfBoundsException e) { - throw new ParserException("Error parsing FourCC VC1 codec private"); + throw new ParserException("Error parsing FourCC private data"); } + + Log.w(TAG, "Unknown FourCC. Setting mimeType to " + MimeTypes.VIDEO_UNKNOWN); + return new Pair<>(MimeTypes.VIDEO_UNKNOWN, null); } /** From eae1606b904935ce9641cfa1a37574b08ce59855 Mon Sep 17 00:00:00 2001 From: Drew Hill Date: Mon, 19 Feb 2018 16:57:54 -0500 Subject: [PATCH 3/3] comment and newline cleanup --- .../android/exoplayer2/extractor/mkv/MatroskaExtractor.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) 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 b32a634bcc..c2b3735265 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 @@ -1934,7 +1934,7 @@ public final class MatroskaExtractor implements Extractor { * * @return A pair object with the first object being the codec mime type * and the second object the initialization data for the {@link Format}, - * or null if the compression type is not VC1. + * or null if the compression type is not a currently supported type (VC1 or H263). * @throws ParserException If the initialization data could not be built. */ private static Pair> parseFourCcPrivate(ParsableByteArray buffer) @@ -1944,8 +1944,7 @@ public final class MatroskaExtractor implements Extractor { long compression = buffer.readLittleEndianUnsignedInt(); if (compression == FOURCC_COMPRESSION_DIVX) { return new Pair<>(MimeTypes.VIDEO_H263, null); - } - else if (compression == FOURCC_COMPRESSION_VC1) { + } else if (compression == FOURCC_COMPRESSION_VC1) { // Search for the initialization data from the end of the BITMAPINFOHEADER. The last 20 // bytes of which are: sizeImage(4), xPel/m (4), yPel/m (4), clrUsed(4), clrImportant(4). int startOffset = buffer.getPosition() + 20;