diff --git a/RELEASENOTES.md b/RELEASENOTES.md index a12c465753..19751c4600 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -38,6 +38,9 @@ ([#8349](https://github.com/google/ExoPlayer/issues/8349)). * Add `DefaultHttpDataSource.Factory` and deprecate `DefaultHttpDataSourceFactory`. + * Populate codecs string for H.264/AVC in MP4, Matroska and FLV streams to + allow decoder capability checks based on codec profile/level + ([#8393](https://github.com/google/ExoPlayer/issues/8393)). * Add option to `MergingMediaSource` to clip the durations of all sources to have the same length ([#8422](https://github.com/google/ExoPlayer/issues/8422)). @@ -46,13 +49,6 @@ creating subtitle media sources from `MediaItem.playbackProperties.subtitles` ([#8430](https://github.com/google/ExoPlayer/issues/8430)). -* Extractors: - * Populate codecs string for H.264/AVC in MP4, Matroska and FLV streams to - allow decoder capability checks based on codec profile/level - ([#8393](https://github.com/google/ExoPlayer/issues/8393)). - * Populate codecs string for H.265/HEVC in MP4, Matroska and MPEG-TS - streams to allow decoder capability checks based on codec profile/level - ([#8393](https://github.com/google/ExoPlayer/issues/8393)). * Track selection: * Allow parallel adaptation for video and audio ([#5111](https://github.com/google/ExoPlayer/issues/5111)). diff --git a/library/common/src/main/java/com/google/android/exoplayer2/util/CodecSpecificDataUtil.java b/library/common/src/main/java/com/google/android/exoplayer2/util/CodecSpecificDataUtil.java index 0f8edb4acd..3360e88d4f 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/util/CodecSpecificDataUtil.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/util/CodecSpecificDataUtil.java @@ -26,8 +26,6 @@ import java.util.List; public final class CodecSpecificDataUtil { private static final byte[] NAL_START_CODE = new byte[] {0, 0, 0, 1}; - private static final String[] HEVC_GENERAL_PROFILE_SPACE_STRINGS = - new String[] {"", "A", "B", "C"}; /** * Parses an ALAC AudioSpecificConfig (i.e. an 0 && constraintBytes[trailingZeroIndex - 1] == 0) { - trailingZeroIndex--; - } - for (int i = 0; i < trailingZeroIndex; i++) { - builder.append(String.format(".%02X", constraintBytes[i])); - } - return builder.toString(); - } - /** * Constructs a NAL unit consisting of the NAL start code followed by the specified data. * diff --git a/library/common/src/main/java/com/google/android/exoplayer2/video/HevcConfig.java b/library/common/src/main/java/com/google/android/exoplayer2/video/HevcConfig.java index b80b1e6942..100a824a97 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/video/HevcConfig.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/video/HevcConfig.java @@ -17,10 +17,8 @@ package com.google.android.exoplayer2.video; import androidx.annotation.Nullable; import com.google.android.exoplayer2.ParserException; -import com.google.android.exoplayer2.util.CodecSpecificDataUtil; import com.google.android.exoplayer2.util.NalUnitUtil; import com.google.android.exoplayer2.util.ParsableByteArray; -import com.google.android.exoplayer2.util.ParsableNalUnitBitArray; import java.util.Collections; import java.util.List; @@ -29,6 +27,9 @@ import java.util.List; */ public final class HevcConfig { + @Nullable public final List initializationData; + public final int nalUnitLengthFieldLength; + /** * Parses HEVC configuration data. * @@ -60,9 +61,8 @@ public final class HevcConfig { data.setPosition(csdStartPosition); byte[] buffer = new byte[csdLength]; int bufferPosition = 0; - @Nullable String codecs = null; for (int i = 0; i < numberOfArrays; i++) { - int nalUnitType = data.readUnsignedByte() & 0x7F; // completeness (1), nal_unit_type (7) + data.skipBytes(1); // completeness (1), nal_unit_type (7) int numberOfNalUnits = data.readUnsignedShort(); for (int j = 0; j < numberOfNalUnits; j++) { int nalUnitLength = data.readUnsignedShort(); @@ -71,49 +71,21 @@ public final class HevcConfig { bufferPosition += NalUnitUtil.NAL_START_CODE.length; System.arraycopy( data.getData(), data.getPosition(), buffer, bufferPosition, nalUnitLength); - if (nalUnitType == SPS_NAL_UNIT_TYPE && j == 0) { - codecs = - CodecSpecificDataUtil.buildHevcCodecStringFromSps( - new ParsableNalUnitBitArray(buffer, bufferPosition, nalUnitLength)); - } bufferPosition += nalUnitLength; data.skipBytes(nalUnitLength); } } - @Nullable List initializationData = csdLength == 0 ? null : Collections.singletonList(buffer); - return new HevcConfig(initializationData, lengthSizeMinusOne + 1, codecs); + return new HevcConfig(initializationData, lengthSizeMinusOne + 1); } catch (ArrayIndexOutOfBoundsException e) { throw new ParserException("Error parsing HEVC config", e); } } - private static final int SPS_NAL_UNIT_TYPE = 33; - - /** - * List of buffers containing the codec-specific data to be provided to the decoder, or {@code - * null} if not known. - * - * @see com.google.android.exoplayer2.Format#initializationData - */ - @Nullable public final List initializationData; - /** The length of the NAL unit length field in the bitstream's container, in bytes. */ - public final int nalUnitLengthFieldLength; - /** - * An RFC 6381 codecs string representing the video format, or {@code null} if not known. - * - * @see com.google.android.exoplayer2.Format#codecs - */ - @Nullable public final String codecs; - - private HevcConfig( - @Nullable List initializationData, - int nalUnitLengthFieldLength, - @Nullable String codecs) { + private HevcConfig(@Nullable List initializationData, int nalUnitLengthFieldLength) { this.initializationData = initializationData; this.nalUnitLengthFieldLength = nalUnitLengthFieldLength; - this.codecs = codecs; } } diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mkv/MatroskaExtractor.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mkv/MatroskaExtractor.java index 53a6fbabea..568385ad3b 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mkv/MatroskaExtractor.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mkv/MatroskaExtractor.java @@ -2093,7 +2093,6 @@ public class MatroskaExtractor implements Extractor { HevcConfig hevcConfig = HevcConfig.parse(new ParsableByteArray(getCodecPrivate(codecId))); initializationData = hevcConfig.initializationData; nalUnitLengthFieldLength = hevcConfig.nalUnitLengthFieldLength; - codecs = hevcConfig.codecs; break; case CODEC_ID_FOURCC: Pair> pair = diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/AtomParsers.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/AtomParsers.java index ff63798583..9d285fe8dc 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/AtomParsers.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/AtomParsers.java @@ -1066,7 +1066,6 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; HevcConfig hevcConfig = HevcConfig.parse(parent); initializationData = hevcConfig.initializationData; out.nalUnitLengthFieldLength = hevcConfig.nalUnitLengthFieldLength; - codecs = hevcConfig.codecs; } else if (childAtomType == Atom.TYPE_dvcC || childAtomType == Atom.TYPE_dvvC) { @Nullable DolbyVisionConfig dolbyVisionConfig = DolbyVisionConfig.parse(parent); if (dolbyVisionConfig != null) { diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/H265Reader.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/H265Reader.java index 0ef719c961..ea23e1ef7a 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/H265Reader.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/H265Reader.java @@ -24,7 +24,6 @@ import com.google.android.exoplayer2.extractor.ExtractorOutput; import com.google.android.exoplayer2.extractor.TrackOutput; import com.google.android.exoplayer2.extractor.ts.TsPayloadReader.TrackIdGenerator; import com.google.android.exoplayer2.util.Assertions; -import com.google.android.exoplayer2.util.CodecSpecificDataUtil; import com.google.android.exoplayer2.util.Log; import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.NalUnitUtil; @@ -337,15 +336,9 @@ public final class H265Reader implements ElementaryStreamReader { } } - // Parse the SPS to derive an RFC 6381 codecs string. - bitArray.reset(sps.nalData, 0, sps.nalLength); - bitArray.skipBits(24); // Skip start code. - String codecs = CodecSpecificDataUtil.buildHevcCodecStringFromSps(bitArray); - return new Format.Builder() .setId(formatId) .setSampleMimeType(MimeTypes.VIDEO_H265) - .setCodecs(codecs) .setWidth(picWidthInLumaSamples) .setHeight(picHeightInLumaSamples) .setPixelWidthHeightRatio(pixelWidthHeightRatio) diff --git a/testdata/src/test/assets/extractordumps/ts/sample_h265.ts.0.dump b/testdata/src/test/assets/extractordumps/ts/sample_h265.ts.0.dump index ca03201f88..1bf1d8af7f 100644 --- a/testdata/src/test/assets/extractordumps/ts/sample_h265.ts.0.dump +++ b/testdata/src/test/assets/extractordumps/ts/sample_h265.ts.0.dump @@ -12,7 +12,6 @@ track 256: format 0: id = 1/256 sampleMimeType = video/hevc - codecs = hvc1.1.6.L90.90 width = 854 height = 480 initializationData: diff --git a/testdata/src/test/assets/extractordumps/ts/sample_h265.ts.1.dump b/testdata/src/test/assets/extractordumps/ts/sample_h265.ts.1.dump index 7f26d0b1e9..18dc2ebabe 100644 --- a/testdata/src/test/assets/extractordumps/ts/sample_h265.ts.1.dump +++ b/testdata/src/test/assets/extractordumps/ts/sample_h265.ts.1.dump @@ -12,7 +12,6 @@ track 256: format 0: id = 1/256 sampleMimeType = video/hevc - codecs = hvc1.1.6.L90.90 width = 854 height = 480 initializationData: diff --git a/testdata/src/test/assets/extractordumps/ts/sample_h265.ts.2.dump b/testdata/src/test/assets/extractordumps/ts/sample_h265.ts.2.dump index d22d002651..1b81fef517 100644 --- a/testdata/src/test/assets/extractordumps/ts/sample_h265.ts.2.dump +++ b/testdata/src/test/assets/extractordumps/ts/sample_h265.ts.2.dump @@ -12,7 +12,6 @@ track 256: format 0: id = 1/256 sampleMimeType = video/hevc - codecs = hvc1.1.6.L90.90 width = 854 height = 480 initializationData: diff --git a/testdata/src/test/assets/extractordumps/ts/sample_h265.ts.3.dump b/testdata/src/test/assets/extractordumps/ts/sample_h265.ts.3.dump index 68a7e61768..1dd24c870e 100644 --- a/testdata/src/test/assets/extractordumps/ts/sample_h265.ts.3.dump +++ b/testdata/src/test/assets/extractordumps/ts/sample_h265.ts.3.dump @@ -12,7 +12,6 @@ track 256: format 0: id = 1/256 sampleMimeType = video/hevc - codecs = hvc1.1.6.L90.90 width = 854 height = 480 initializationData: diff --git a/testdata/src/test/assets/extractordumps/ts/sample_h265.ts.unknown_length.dump b/testdata/src/test/assets/extractordumps/ts/sample_h265.ts.unknown_length.dump index 920032dd23..09b1103840 100644 --- a/testdata/src/test/assets/extractordumps/ts/sample_h265.ts.unknown_length.dump +++ b/testdata/src/test/assets/extractordumps/ts/sample_h265.ts.unknown_length.dump @@ -9,7 +9,6 @@ track 256: format 0: id = 1/256 sampleMimeType = video/hevc - codecs = hvc1.1.6.L90.90 width = 854 height = 480 initializationData: