Support CEA-608 subtitles in Dolby Vision

Issue: androidx/media#1820

#cherrypick

PiperOrigin-RevId: 691378476
This commit is contained in:
ibaker 2024-10-30 05:14:28 -07:00 committed by Copybara-Service
parent 08a141328d
commit 27371db225
3 changed files with 29 additions and 2 deletions

View File

@ -44,6 +44,8 @@
* Fix CEA-608 subtitles in H.264 MPEG-TS streams not being output (this
was broken in `1.5.0-alpha01` by
https://github.com/androidx/media/commit/03a205f220ecf7681f85f8a752227e3986e257ff).
* Support CEA-608 subtitles in Dolby Vision content
([#1820](https://github.com/androidx/media/issues/1820)).
* Metadata:
* Image:
* DRM:

View File

@ -15,6 +15,7 @@
*/
package androidx.media3.container;
import static androidx.media3.common.MimeTypes.containsCodecsCorrespondingToMimeType;
import static com.google.common.math.DoubleMath.log2;
import static java.lang.Math.max;
import static java.lang.Math.min;
@ -33,6 +34,7 @@ import java.math.RoundingMode;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
/** Utility methods for handling H.264/AVC and H.265/HEVC NAL units. */
@UnstableApi
@ -614,6 +616,24 @@ public final class NalUnitUtil {
&& ((nalUnitHeaderFirstByte & 0x7E) >> 1) == H265_NAL_UNIT_TYPE_PREFIX_SEI);
}
/**
* Returns whether the NAL unit with the specified header contains supplemental enhancement
* information.
*
* @param format The sample {@link Format}.
* @param nalUnitHeaderFirstByte The first byte of nal_unit().
* @return Whether the NAL unit with the specified header is an SEI NAL unit. False is returned if
* the {@code MimeType} is {@code null}.
*/
public static boolean isNalUnitSei(Format format, byte nalUnitHeaderFirstByte) {
return ((Objects.equals(format.sampleMimeType, MimeTypes.VIDEO_H264)
|| containsCodecsCorrespondingToMimeType(format.codecs, MimeTypes.VIDEO_H264))
&& (nalUnitHeaderFirstByte & 0x1F) == H264_NAL_UNIT_TYPE_SEI)
|| ((Objects.equals(format.sampleMimeType, MimeTypes.VIDEO_H265)
|| containsCodecsCorrespondingToMimeType(format.codecs, MimeTypes.VIDEO_H265))
&& ((nalUnitHeaderFirstByte & 0x7E) >> 1) == H265_NAL_UNIT_TYPE_PREFIX_SEI);
}
/**
* Returns the type of the NAL unit in {@code data} that starts at {@code offset}.
*

View File

@ -1608,7 +1608,7 @@ public class FragmentedMp4Extractor implements Extractor {
output.sampleData(nalPrefix, 1);
processSeiNalUnitPayload =
ceaTrackOutputs.length > 0
&& NalUnitUtil.isNalUnitSei(track.format.sampleMimeType, nalPrefixData[4]);
&& NalUnitUtil.isNalUnitSei(track.format, nalPrefixData[4]);
sampleBytesWritten += 5;
sampleSize += nalUnitLengthFieldLengthDiff;
if (!isSampleDependedOn
@ -1629,7 +1629,12 @@ public class FragmentedMp4Extractor implements Extractor {
int unescapedLength =
NalUnitUtil.unescapeStream(nalBuffer.getData(), nalBuffer.limit());
// If the format is H.265/HEVC the NAL unit header has two bytes so skip one more byte.
nalBuffer.setPosition(MimeTypes.VIDEO_H265.equals(track.format.sampleMimeType) ? 1 : 0);
nalBuffer.setPosition(
Objects.equals(track.format.sampleMimeType, MimeTypes.VIDEO_H265)
|| MimeTypes.containsCodecsCorrespondingToMimeType(
track.format.codecs, MimeTypes.VIDEO_H265)
? 1
: 0);
nalBuffer.setLimit(unescapedLength);
if (track.format.maxNumReorderSamples != Format.NO_VALUE