Commit e07b8fe7 by anjalibh Committed by Oliver Woodman

Parse ColorInfo from WebM Container and set it on MediaFormat.

* colorSpace, colorRange and colorTransfer are relevant to all videos.
* The rest of the fields are relevant only to HDR videos.
* Tested on a prototype device that decodes VP9 profile 2, 10 bit.
* The Webm spec spells color as 'colour' so the webm id reference use the same spelling.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=154098189
parent d3fe20cc
...@@ -29,6 +29,7 @@ import com.google.android.exoplayer2.metadata.id3.TextInformationFrame; ...@@ -29,6 +29,7 @@ import com.google.android.exoplayer2.metadata.id3.TextInformationFrame;
import com.google.android.exoplayer2.testutil.TestUtil; import com.google.android.exoplayer2.testutil.TestUtil;
import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.MimeTypes;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import com.google.android.exoplayer2.video.ColorInfo;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
...@@ -61,11 +62,13 @@ public final class FormatTest extends TestCase { ...@@ -61,11 +62,13 @@ public final class FormatTest extends TestCase {
Metadata metadata = new Metadata( Metadata metadata = new Metadata(
new TextInformationFrame("id1", "description1", "value1"), new TextInformationFrame("id1", "description1", "value1"),
new TextInformationFrame("id2", "description2", "value2")); new TextInformationFrame("id2", "description2", "value2"));
ColorInfo colorInfo = new ColorInfo(C.COLOR_SPACE_BT709,
C.COLOR_RANGE_LIMITED, C.COLOR_TRANSFER_SDR, new byte[] {1, 2, 3, 4, 5, 6, 7});
Format formatToParcel = new Format("id", MimeTypes.VIDEO_MP4, MimeTypes.VIDEO_H264, null, Format formatToParcel = new Format("id", MimeTypes.VIDEO_MP4, MimeTypes.VIDEO_H264, null,
1024, 2048, 1920, 1080, 24, 90, 2, projectionData, C.STEREO_MODE_TOP_BOTTOM, 6, 44100, 1024, 2048, 1920, 1080, 24, 90, 2, projectionData, C.STEREO_MODE_TOP_BOTTOM, colorInfo, 6,
C.ENCODING_PCM_24BIT, 1001, 1002, 0, "und", Format.NO_VALUE, Format.OFFSET_SAMPLE_RELATIVE, 44100, C.ENCODING_PCM_24BIT, 1001, 1002, 0, "und", Format.NO_VALUE,
INIT_DATA, drmInitData, metadata); Format.OFFSET_SAMPLE_RELATIVE, INIT_DATA, drmInitData, metadata);
Parcel parcel = Parcel.obtain(); Parcel parcel = Parcel.obtain();
formatToParcel.writeToParcel(parcel, 0); formatToParcel.writeToParcel(parcel, 0);
......
...@@ -20,6 +20,7 @@ import android.content.Context; ...@@ -20,6 +20,7 @@ import android.content.Context;
import android.media.AudioFormat; import android.media.AudioFormat;
import android.media.AudioManager; import android.media.AudioManager;
import android.media.MediaCodec; import android.media.MediaCodec;
import android.media.MediaFormat;
import android.support.annotation.IntDef; import android.support.annotation.IntDef;
import android.view.Surface; import android.view.Surface;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
...@@ -555,6 +556,67 @@ public final class C { ...@@ -555,6 +556,67 @@ public final class C {
public static final int STEREO_MODE_STEREO_MESH = 3; public static final int STEREO_MODE_STEREO_MESH = 3;
/** /**
* Video colorspaces.
*/
@Retention(RetentionPolicy.SOURCE)
@IntDef({Format.NO_VALUE, COLOR_SPACE_BT709, COLOR_SPACE_BT601, COLOR_SPACE_BT2020})
public @interface ColorSpace {}
/**
* @see MediaFormat#COLOR_STANDARD_BT709
*/
@SuppressWarnings("InlinedApi")
public static final int COLOR_SPACE_BT709 = MediaFormat.COLOR_STANDARD_BT709;
/**
* @see MediaFormat#COLOR_STANDARD_BT601_PAL
*/
@SuppressWarnings("InlinedApi")
public static final int COLOR_SPACE_BT601 = MediaFormat.COLOR_STANDARD_BT601_PAL;
/**
* @see MediaFormat#COLOR_STANDARD_BT2020
*/
@SuppressWarnings("InlinedApi")
public static final int COLOR_SPACE_BT2020 = MediaFormat.COLOR_STANDARD_BT2020;
/**
* Video color transfer characteristics.
*/
@Retention(RetentionPolicy.SOURCE)
@IntDef({Format.NO_VALUE, COLOR_TRANSFER_SDR, COLOR_TRANSFER_ST2084, COLOR_TRANSFER_HLG})
public @interface ColorTransfer {}
/**
* @see MediaFormat#COLOR_TRANSFER_SDR_VIDEO
*/
@SuppressWarnings("InlinedApi")
public static final int COLOR_TRANSFER_SDR = MediaFormat.COLOR_TRANSFER_SDR_VIDEO;
/**
* @see MediaFormat#COLOR_TRANSFER_ST2084
*/
@SuppressWarnings("InlinedApi")
public static final int COLOR_TRANSFER_ST2084 = MediaFormat.COLOR_TRANSFER_ST2084;
/**
* @see MediaFormat#COLOR_TRANSFER_HLG
*/
@SuppressWarnings("InlinedApi")
public static final int COLOR_TRANSFER_HLG = MediaFormat.COLOR_TRANSFER_HLG;
/**
* Video color range.
*/
@Retention(RetentionPolicy.SOURCE)
@IntDef({Format.NO_VALUE, COLOR_RANGE_LIMITED, COLOR_RANGE_FULL})
public @interface ColorRange {}
/**
* @see MediaFormat#COLOR_RANGE_LIMITED
*/
@SuppressWarnings("InlinedApi")
public static final int COLOR_RANGE_LIMITED = MediaFormat.COLOR_RANGE_LIMITED;
/**
* @see MediaFormat#COLOR_RANGE_FULL
*/
@SuppressWarnings("InlinedApi")
public static final int COLOR_RANGE_FULL = MediaFormat.COLOR_RANGE_FULL;
/**
* Priority for media playback. * Priority for media playback.
* *
* <p>Larger values indicate higher priorities. * <p>Larger values indicate higher priorities.
......
...@@ -24,6 +24,7 @@ import com.google.android.exoplayer2.drm.DrmInitData; ...@@ -24,6 +24,7 @@ import com.google.android.exoplayer2.drm.DrmInitData;
import com.google.android.exoplayer2.metadata.Metadata; import com.google.android.exoplayer2.metadata.Metadata;
import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.MimeTypes;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import com.google.android.exoplayer2.video.ColorInfo;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
...@@ -128,6 +129,10 @@ public final class Format implements Parcelable { ...@@ -128,6 +129,10 @@ public final class Format implements Parcelable {
* The projection data for 360/VR video, or null if not applicable. * The projection data for 360/VR video, or null if not applicable.
*/ */
public final byte[] projectionData; public final byte[] projectionData;
/**
* The color metadata associated with the video, helps with accurate color reproduction.
*/
public final ColorInfo colorInfo;
// Audio specific. // Audio specific.
...@@ -192,7 +197,7 @@ public final class Format implements Parcelable { ...@@ -192,7 +197,7 @@ public final class Format implements Parcelable {
String sampleMimeType, String codecs, int bitrate, int width, int height, String sampleMimeType, String codecs, int bitrate, int width, int height,
float frameRate, List<byte[]> initializationData, @C.SelectionFlags int selectionFlags) { float frameRate, List<byte[]> initializationData, @C.SelectionFlags int selectionFlags) {
return new Format(id, containerMimeType, sampleMimeType, codecs, bitrate, NO_VALUE, width, return new Format(id, containerMimeType, sampleMimeType, codecs, bitrate, NO_VALUE, width,
height, frameRate, NO_VALUE, NO_VALUE, null, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, height, frameRate, NO_VALUE, NO_VALUE, null, NO_VALUE, null, NO_VALUE, NO_VALUE, NO_VALUE,
NO_VALUE, NO_VALUE, selectionFlags, null, NO_VALUE, OFFSET_SAMPLE_RELATIVE, NO_VALUE, NO_VALUE, selectionFlags, null, NO_VALUE, OFFSET_SAMPLE_RELATIVE,
initializationData, null, null); initializationData, null, null);
} }
...@@ -210,17 +215,18 @@ public final class Format implements Parcelable { ...@@ -210,17 +215,18 @@ public final class Format implements Parcelable {
DrmInitData drmInitData) { DrmInitData drmInitData) {
return createVideoSampleFormat(id, sampleMimeType, codecs, bitrate, maxInputSize, width, return createVideoSampleFormat(id, sampleMimeType, codecs, bitrate, maxInputSize, width,
height, frameRate, initializationData, rotationDegrees, pixelWidthHeightRatio, null, height, frameRate, initializationData, rotationDegrees, pixelWidthHeightRatio, null,
NO_VALUE, drmInitData); NO_VALUE, null, drmInitData);
} }
public static Format createVideoSampleFormat(String id, String sampleMimeType, String codecs, public static Format createVideoSampleFormat(String id, String sampleMimeType, String codecs,
int bitrate, int maxInputSize, int width, int height, float frameRate, int bitrate, int maxInputSize, int width, int height, float frameRate,
List<byte[]> initializationData, int rotationDegrees, float pixelWidthHeightRatio, List<byte[]> initializationData, int rotationDegrees, float pixelWidthHeightRatio,
byte[] projectionData, @C.StereoMode int stereoMode, DrmInitData drmInitData) { byte[] projectionData, @C.StereoMode int stereoMode, ColorInfo colorInfo,
DrmInitData drmInitData) {
return new Format(id, null, sampleMimeType, codecs, bitrate, maxInputSize, width, height, return new Format(id, null, sampleMimeType, codecs, bitrate, maxInputSize, width, height,
frameRate, rotationDegrees, pixelWidthHeightRatio, projectionData, stereoMode, NO_VALUE, frameRate, rotationDegrees, pixelWidthHeightRatio, projectionData, stereoMode,
NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, 0, null, NO_VALUE, OFFSET_SAMPLE_RELATIVE, colorInfo, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, 0, null, NO_VALUE,
initializationData, drmInitData, null); OFFSET_SAMPLE_RELATIVE, initializationData, drmInitData, null);
} }
// Audio. // Audio.
...@@ -229,8 +235,8 @@ public final class Format implements Parcelable { ...@@ -229,8 +235,8 @@ public final class Format implements Parcelable {
String sampleMimeType, String codecs, int bitrate, int channelCount, int sampleRate, String sampleMimeType, String codecs, int bitrate, int channelCount, int sampleRate,
List<byte[]> initializationData, @C.SelectionFlags int selectionFlags, String language) { List<byte[]> initializationData, @C.SelectionFlags int selectionFlags, String language) {
return new Format(id, containerMimeType, sampleMimeType, codecs, bitrate, NO_VALUE, NO_VALUE, return new Format(id, containerMimeType, sampleMimeType, codecs, bitrate, NO_VALUE, NO_VALUE,
NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, null, NO_VALUE, channelCount, sampleRate, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, null, NO_VALUE, null, channelCount, sampleRate,
NO_VALUE, NO_VALUE, selectionFlags, language, NO_VALUE, OFFSET_SAMPLE_RELATIVE, NO_VALUE, NO_VALUE, NO_VALUE, selectionFlags, language, NO_VALUE, OFFSET_SAMPLE_RELATIVE,
initializationData, null, null); initializationData, null, null);
} }
...@@ -257,7 +263,7 @@ public final class Format implements Parcelable { ...@@ -257,7 +263,7 @@ public final class Format implements Parcelable {
List<byte[]> initializationData, DrmInitData drmInitData, List<byte[]> initializationData, DrmInitData drmInitData,
@C.SelectionFlags int selectionFlags, String language, Metadata metadata) { @C.SelectionFlags int selectionFlags, String language, Metadata metadata) {
return new Format(id, null, sampleMimeType, codecs, bitrate, maxInputSize, NO_VALUE, NO_VALUE, return new Format(id, null, sampleMimeType, codecs, bitrate, maxInputSize, NO_VALUE, NO_VALUE,
NO_VALUE, NO_VALUE, NO_VALUE, null, NO_VALUE, channelCount, sampleRate, pcmEncoding, NO_VALUE, NO_VALUE, NO_VALUE, null, NO_VALUE, null, channelCount, sampleRate, pcmEncoding,
encoderDelay, encoderPadding, selectionFlags, language, NO_VALUE, OFFSET_SAMPLE_RELATIVE, encoderDelay, encoderPadding, selectionFlags, language, NO_VALUE, OFFSET_SAMPLE_RELATIVE,
initializationData, drmInitData, metadata); initializationData, drmInitData, metadata);
} }
...@@ -275,8 +281,8 @@ public final class Format implements Parcelable { ...@@ -275,8 +281,8 @@ public final class Format implements Parcelable {
String sampleMimeType, String codecs, int bitrate, @C.SelectionFlags int selectionFlags, String sampleMimeType, String codecs, int bitrate, @C.SelectionFlags int selectionFlags,
String language, int accessibilityChannel) { String language, int accessibilityChannel) {
return new Format(id, containerMimeType, sampleMimeType, codecs, bitrate, NO_VALUE, NO_VALUE, return new Format(id, containerMimeType, sampleMimeType, codecs, bitrate, NO_VALUE, NO_VALUE,
NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, null, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, null, NO_VALUE, null, NO_VALUE, NO_VALUE,
NO_VALUE, NO_VALUE, selectionFlags, language, accessibilityChannel, NO_VALUE, NO_VALUE, NO_VALUE, selectionFlags, language, accessibilityChannel,
OFFSET_SAMPLE_RELATIVE, null, null, null); OFFSET_SAMPLE_RELATIVE, null, null, null);
} }
...@@ -305,7 +311,7 @@ public final class Format implements Parcelable { ...@@ -305,7 +311,7 @@ public final class Format implements Parcelable {
int accessibilityChannel, DrmInitData drmInitData, long subsampleOffsetUs, int accessibilityChannel, DrmInitData drmInitData, long subsampleOffsetUs,
List<byte[]> initializationData) { List<byte[]> initializationData) {
return new Format(id, null, sampleMimeType, codecs, bitrate, NO_VALUE, NO_VALUE, NO_VALUE, return new Format(id, null, sampleMimeType, codecs, bitrate, NO_VALUE, NO_VALUE, NO_VALUE,
NO_VALUE, NO_VALUE, NO_VALUE, null, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, null, NO_VALUE, null, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE,
NO_VALUE, selectionFlags, language, accessibilityChannel, subsampleOffsetUs, NO_VALUE, selectionFlags, language, accessibilityChannel, subsampleOffsetUs,
initializationData, drmInitData, null); initializationData, drmInitData, null);
} }
...@@ -315,7 +321,7 @@ public final class Format implements Parcelable { ...@@ -315,7 +321,7 @@ public final class Format implements Parcelable {
public static Format createImageSampleFormat(String id, String sampleMimeType, String codecs, public static Format createImageSampleFormat(String id, String sampleMimeType, String codecs,
int bitrate, List<byte[]> initializationData, String language, DrmInitData drmInitData) { int bitrate, List<byte[]> initializationData, String language, DrmInitData drmInitData) {
return new Format(id, null, sampleMimeType, codecs, bitrate, NO_VALUE, NO_VALUE, NO_VALUE, return new Format(id, null, sampleMimeType, codecs, bitrate, NO_VALUE, NO_VALUE, NO_VALUE,
NO_VALUE, NO_VALUE, NO_VALUE, null, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, null, NO_VALUE, null, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE,
NO_VALUE, 0, language, NO_VALUE, OFFSET_SAMPLE_RELATIVE, initializationData, drmInitData, NO_VALUE, 0, language, NO_VALUE, OFFSET_SAMPLE_RELATIVE, initializationData, drmInitData,
null); null);
} }
...@@ -326,7 +332,7 @@ public final class Format implements Parcelable { ...@@ -326,7 +332,7 @@ public final class Format implements Parcelable {
String sampleMimeType, String codecs, int bitrate, @C.SelectionFlags int selectionFlags, String sampleMimeType, String codecs, int bitrate, @C.SelectionFlags int selectionFlags,
String language) { String language) {
return new Format(id, containerMimeType, sampleMimeType, codecs, bitrate, NO_VALUE, NO_VALUE, return new Format(id, containerMimeType, sampleMimeType, codecs, bitrate, NO_VALUE, NO_VALUE,
NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, null, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, null, NO_VALUE, null, NO_VALUE, NO_VALUE, NO_VALUE,
NO_VALUE, NO_VALUE, selectionFlags, language, NO_VALUE, OFFSET_SAMPLE_RELATIVE, null, null, NO_VALUE, NO_VALUE, selectionFlags, language, NO_VALUE, OFFSET_SAMPLE_RELATIVE, null, null,
null); null);
} }
...@@ -334,22 +340,22 @@ public final class Format implements Parcelable { ...@@ -334,22 +340,22 @@ public final class Format implements Parcelable {
public static Format createSampleFormat(String id, String sampleMimeType, public static Format createSampleFormat(String id, String sampleMimeType,
long subsampleOffsetUs) { long subsampleOffsetUs) {
return new Format(id, null, sampleMimeType, null, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, return new Format(id, null, sampleMimeType, null, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE,
NO_VALUE, NO_VALUE, NO_VALUE, null, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, null, NO_VALUE, null, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE,
NO_VALUE, 0, null, NO_VALUE, subsampleOffsetUs, null, null, null); NO_VALUE, 0, null, NO_VALUE, subsampleOffsetUs, null, null, null);
} }
public static Format createSampleFormat(String id, String sampleMimeType, String codecs, public static Format createSampleFormat(String id, String sampleMimeType, String codecs,
int bitrate, DrmInitData drmInitData) { int bitrate, DrmInitData drmInitData) {
return new Format(id, null, sampleMimeType, codecs, bitrate, NO_VALUE, NO_VALUE, NO_VALUE, return new Format(id, null, sampleMimeType, codecs, bitrate, NO_VALUE, NO_VALUE, NO_VALUE,
NO_VALUE, NO_VALUE, NO_VALUE, null, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, null, NO_VALUE, null, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE,
NO_VALUE, 0, null, NO_VALUE, OFFSET_SAMPLE_RELATIVE, null, drmInitData, null); NO_VALUE, 0, null, NO_VALUE, OFFSET_SAMPLE_RELATIVE, null, drmInitData, null);
} }
/* package */ Format(String id, String containerMimeType, String sampleMimeType, String codecs, /* package */ Format(String id, String containerMimeType, String sampleMimeType, String codecs,
int bitrate, int maxInputSize, int width, int height, float frameRate, int rotationDegrees, int bitrate, int maxInputSize, int width, int height, float frameRate, int rotationDegrees,
float pixelWidthHeightRatio, byte[] projectionData, @C.StereoMode int stereoMode, float pixelWidthHeightRatio, byte[] projectionData, @C.StereoMode int stereoMode,
int channelCount, int sampleRate, @C.PcmEncoding int pcmEncoding, int encoderDelay, ColorInfo colorInfo, int channelCount, int sampleRate, @C.PcmEncoding int pcmEncoding,
int encoderPadding, @C.SelectionFlags int selectionFlags, String language, int encoderDelay, int encoderPadding, @C.SelectionFlags int selectionFlags, String language,
int accessibilityChannel, long subsampleOffsetUs, List<byte[]> initializationData, int accessibilityChannel, long subsampleOffsetUs, List<byte[]> initializationData,
DrmInitData drmInitData, Metadata metadata) { DrmInitData drmInitData, Metadata metadata) {
this.id = id; this.id = id;
...@@ -365,6 +371,7 @@ public final class Format implements Parcelable { ...@@ -365,6 +371,7 @@ public final class Format implements Parcelable {
this.pixelWidthHeightRatio = pixelWidthHeightRatio; this.pixelWidthHeightRatio = pixelWidthHeightRatio;
this.projectionData = projectionData; this.projectionData = projectionData;
this.stereoMode = stereoMode; this.stereoMode = stereoMode;
this.colorInfo = colorInfo;
this.channelCount = channelCount; this.channelCount = channelCount;
this.sampleRate = sampleRate; this.sampleRate = sampleRate;
this.pcmEncoding = pcmEncoding; this.pcmEncoding = pcmEncoding;
...@@ -396,6 +403,7 @@ public final class Format implements Parcelable { ...@@ -396,6 +403,7 @@ public final class Format implements Parcelable {
boolean hasProjectionData = in.readInt() != 0; boolean hasProjectionData = in.readInt() != 0;
projectionData = hasProjectionData ? in.createByteArray() : null; projectionData = hasProjectionData ? in.createByteArray() : null;
stereoMode = in.readInt(); stereoMode = in.readInt();
colorInfo = in.readParcelable(ColorInfo.class.getClassLoader());
channelCount = in.readInt(); channelCount = in.readInt();
sampleRate = in.readInt(); sampleRate = in.readInt();
pcmEncoding = in.readInt(); pcmEncoding = in.readInt();
...@@ -417,26 +425,26 @@ public final class Format implements Parcelable { ...@@ -417,26 +425,26 @@ public final class Format implements Parcelable {
public Format copyWithMaxInputSize(int maxInputSize) { public Format copyWithMaxInputSize(int maxInputSize) {
return new Format(id, containerMimeType, sampleMimeType, codecs, bitrate, maxInputSize, return new Format(id, containerMimeType, sampleMimeType, codecs, bitrate, maxInputSize,
width, height, frameRate, rotationDegrees, pixelWidthHeightRatio, projectionData, width, height, frameRate, rotationDegrees, pixelWidthHeightRatio, projectionData,
stereoMode, channelCount, sampleRate, pcmEncoding, encoderDelay, encoderPadding, stereoMode, colorInfo, channelCount, sampleRate, pcmEncoding, encoderDelay,
selectionFlags, language, accessibilityChannel, subsampleOffsetUs, initializationData, encoderPadding, selectionFlags, language, accessibilityChannel, subsampleOffsetUs,
drmInitData, metadata); initializationData, drmInitData, metadata);
} }
public Format copyWithSubsampleOffsetUs(long subsampleOffsetUs) { public Format copyWithSubsampleOffsetUs(long subsampleOffsetUs) {
return new Format(id, containerMimeType, sampleMimeType, codecs, bitrate, maxInputSize, return new Format(id, containerMimeType, sampleMimeType, codecs, bitrate, maxInputSize,
width, height, frameRate, rotationDegrees, pixelWidthHeightRatio, projectionData, width, height, frameRate, rotationDegrees, pixelWidthHeightRatio, projectionData,
stereoMode, channelCount, sampleRate, pcmEncoding, encoderDelay, encoderPadding, stereoMode, colorInfo, channelCount, sampleRate, pcmEncoding, encoderDelay,
selectionFlags, language, accessibilityChannel, subsampleOffsetUs, initializationData, encoderPadding, selectionFlags, language, accessibilityChannel, subsampleOffsetUs,
drmInitData, metadata); initializationData, drmInitData, metadata);
} }
public Format copyWithContainerInfo(String id, String codecs, int bitrate, int width, int height, public Format copyWithContainerInfo(String id, String codecs, int bitrate, int width, int height,
@C.SelectionFlags int selectionFlags, String language) { @C.SelectionFlags int selectionFlags, String language) {
return new Format(id, containerMimeType, sampleMimeType, codecs, bitrate, maxInputSize, return new Format(id, containerMimeType, sampleMimeType, codecs, bitrate, maxInputSize,
width, height, frameRate, rotationDegrees, pixelWidthHeightRatio, projectionData, width, height, frameRate, rotationDegrees, pixelWidthHeightRatio, projectionData,
stereoMode, channelCount, sampleRate, pcmEncoding, encoderDelay, encoderPadding, stereoMode, colorInfo, channelCount, sampleRate, pcmEncoding, encoderDelay,
selectionFlags, language, accessibilityChannel, subsampleOffsetUs, initializationData, encoderPadding, selectionFlags, language, accessibilityChannel, subsampleOffsetUs,
drmInitData, metadata); initializationData, drmInitData, metadata);
} }
@SuppressWarnings("ReferenceEquality") @SuppressWarnings("ReferenceEquality")
...@@ -455,33 +463,33 @@ public final class Format implements Parcelable { ...@@ -455,33 +463,33 @@ public final class Format implements Parcelable {
: this.drmInitData; : this.drmInitData;
return new Format(id, containerMimeType, sampleMimeType, codecs, bitrate, maxInputSize, width, return new Format(id, containerMimeType, sampleMimeType, codecs, bitrate, maxInputSize, width,
height, frameRate, rotationDegrees, pixelWidthHeightRatio, projectionData, stereoMode, height, frameRate, rotationDegrees, pixelWidthHeightRatio, projectionData, stereoMode,
channelCount, sampleRate, pcmEncoding, encoderDelay, encoderPadding, selectionFlags, colorInfo, channelCount, sampleRate, pcmEncoding, encoderDelay, encoderPadding,
language, accessibilityChannel, subsampleOffsetUs, initializationData, drmInitData, selectionFlags, language, accessibilityChannel, subsampleOffsetUs, initializationData,
metadata); drmInitData, metadata);
} }
public Format copyWithGaplessInfo(int encoderDelay, int encoderPadding) { public Format copyWithGaplessInfo(int encoderDelay, int encoderPadding) {
return new Format(id, containerMimeType, sampleMimeType, codecs, bitrate, maxInputSize, return new Format(id, containerMimeType, sampleMimeType, codecs, bitrate, maxInputSize,
width, height, frameRate, rotationDegrees, pixelWidthHeightRatio, projectionData, width, height, frameRate, rotationDegrees, pixelWidthHeightRatio, projectionData,
stereoMode, channelCount, sampleRate, pcmEncoding, encoderDelay, encoderPadding, stereoMode, colorInfo, channelCount, sampleRate, pcmEncoding, encoderDelay,
selectionFlags, language, accessibilityChannel, subsampleOffsetUs, initializationData, encoderPadding, selectionFlags, language, accessibilityChannel, subsampleOffsetUs,
drmInitData, metadata); initializationData, drmInitData, metadata);
} }
public Format copyWithDrmInitData(DrmInitData drmInitData) { public Format copyWithDrmInitData(DrmInitData drmInitData) {
return new Format(id, containerMimeType, sampleMimeType, codecs, bitrate, maxInputSize, return new Format(id, containerMimeType, sampleMimeType, codecs, bitrate, maxInputSize,
width, height, frameRate, rotationDegrees, pixelWidthHeightRatio, projectionData, width, height, frameRate, rotationDegrees, pixelWidthHeightRatio, projectionData,
stereoMode, channelCount, sampleRate, pcmEncoding, encoderDelay, encoderPadding, stereoMode, colorInfo, channelCount, sampleRate, pcmEncoding, encoderDelay,
selectionFlags, language, accessibilityChannel, subsampleOffsetUs, initializationData, encoderPadding, selectionFlags, language, accessibilityChannel, subsampleOffsetUs,
drmInitData, metadata); initializationData, drmInitData, metadata);
} }
public Format copyWithMetadata(Metadata metadata) { public Format copyWithMetadata(Metadata metadata) {
return new Format(id, containerMimeType, sampleMimeType, codecs, bitrate, maxInputSize, return new Format(id, containerMimeType, sampleMimeType, codecs, bitrate, maxInputSize,
width, height, frameRate, rotationDegrees, pixelWidthHeightRatio, projectionData, width, height, frameRate, rotationDegrees, pixelWidthHeightRatio, projectionData,
stereoMode, channelCount, sampleRate, pcmEncoding, encoderDelay, encoderPadding, stereoMode, colorInfo, channelCount, sampleRate, pcmEncoding, encoderDelay,
selectionFlags, language, accessibilityChannel, subsampleOffsetUs, initializationData, encoderPadding, selectionFlags, language, accessibilityChannel, subsampleOffsetUs,
drmInitData, metadata); initializationData, drmInitData, metadata);
} }
/** /**
...@@ -513,6 +521,7 @@ public final class Format implements Parcelable { ...@@ -513,6 +521,7 @@ public final class Format implements Parcelable {
for (int i = 0; i < initializationData.size(); i++) { for (int i = 0; i < initializationData.size(); i++) {
format.setByteBuffer("csd-" + i, ByteBuffer.wrap(initializationData.get(i))); format.setByteBuffer("csd-" + i, ByteBuffer.wrap(initializationData.get(i)));
} }
maybeSetColorInfoV24(format, colorInfo);
return format; return format;
} }
...@@ -569,6 +578,7 @@ public final class Format implements Parcelable { ...@@ -569,6 +578,7 @@ public final class Format implements Parcelable {
|| !Util.areEqual(codecs, other.codecs) || !Util.areEqual(codecs, other.codecs)
|| !Util.areEqual(drmInitData, other.drmInitData) || !Util.areEqual(drmInitData, other.drmInitData)
|| !Util.areEqual(metadata, other.metadata) || !Util.areEqual(metadata, other.metadata)
|| !Util.areEqual(colorInfo, other.colorInfo)
|| !Arrays.equals(projectionData, other.projectionData) || !Arrays.equals(projectionData, other.projectionData)
|| initializationData.size() != other.initializationData.size()) { || initializationData.size() != other.initializationData.size()) {
return false; return false;
...@@ -581,6 +591,17 @@ public final class Format implements Parcelable { ...@@ -581,6 +591,17 @@ public final class Format implements Parcelable {
return true; return true;
} }
@TargetApi(24)
private static void maybeSetColorInfoV24(MediaFormat format, ColorInfo colorInfo) {
if (colorInfo == null) {
return;
}
maybeSetIntegerV16(format, MediaFormat.KEY_COLOR_TRANSFER, colorInfo.colorTransfer);
maybeSetIntegerV16(format, MediaFormat.KEY_COLOR_STANDARD, colorInfo.colorSpace);
maybeSetIntegerV16(format, MediaFormat.KEY_COLOR_RANGE, colorInfo.colorRange);
maybeSetByteBufferV16(format, MediaFormat.KEY_HDR_STATIC_INFO, colorInfo.hdrStaticInfo);
}
@TargetApi(16) @TargetApi(16)
private static void maybeSetStringV16(MediaFormat format, String key, String value) { private static void maybeSetStringV16(MediaFormat format, String key, String value) {
if (value != null) { if (value != null) {
...@@ -602,6 +623,13 @@ public final class Format implements Parcelable { ...@@ -602,6 +623,13 @@ public final class Format implements Parcelable {
} }
} }
@TargetApi(16)
private static void maybeSetByteBufferV16(MediaFormat format, String key, byte[] value) {
if (value != null) {
format.setByteBuffer(key, ByteBuffer.wrap(value));
}
}
// Utility methods // Utility methods
/** /**
...@@ -659,6 +687,7 @@ public final class Format implements Parcelable { ...@@ -659,6 +687,7 @@ public final class Format implements Parcelable {
dest.writeByteArray(projectionData); dest.writeByteArray(projectionData);
} }
dest.writeInt(stereoMode); dest.writeInt(stereoMode);
dest.writeParcelable(colorInfo, flags);
dest.writeInt(channelCount); dest.writeInt(channelCount);
dest.writeInt(sampleRate); dest.writeInt(sampleRate);
dest.writeInt(pcmEncoding); dest.writeInt(pcmEncoding);
......
...@@ -37,6 +37,7 @@ import com.google.android.exoplayer2.util.NalUnitUtil; ...@@ -37,6 +37,7 @@ import com.google.android.exoplayer2.util.NalUnitUtil;
import com.google.android.exoplayer2.util.ParsableByteArray; import com.google.android.exoplayer2.util.ParsableByteArray;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import com.google.android.exoplayer2.video.AvcConfig; import com.google.android.exoplayer2.video.AvcConfig;
import com.google.android.exoplayer2.video.ColorInfo;
import com.google.android.exoplayer2.video.HevcConfig; import com.google.android.exoplayer2.video.HevcConfig;
import java.io.IOException; import java.io.IOException;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
...@@ -187,6 +188,23 @@ public final class MatroskaExtractor implements Extractor { ...@@ -187,6 +188,23 @@ public final class MatroskaExtractor implements Extractor {
private static final int ID_PROJECTION = 0x7670; private static final int ID_PROJECTION = 0x7670;
private static final int ID_PROJECTION_PRIVATE = 0x7672; private static final int ID_PROJECTION_PRIVATE = 0x7672;
private static final int ID_STEREO_MODE = 0x53B8; private static final int ID_STEREO_MODE = 0x53B8;
private static final int ID_COLOUR = 0x55B0;
private static final int ID_COLOUR_RANGE = 0x55B9;
private static final int ID_COLOUR_TRANSFER = 0x55BA;
private static final int ID_COLOUR_PRIMARIES = 0x55BB;
private static final int ID_MAX_CLL = 0x55BC;
private static final int ID_MAX_FALL = 0x55BD;
private static final int ID_MASTERING_METADATA = 0x55D0;
private static final int ID_PRIMARY_R_CHROMATICITY_X = 0x55D1;
private static final int ID_PRIMARY_R_CHROMATICITY_Y = 0x55D2;
private static final int ID_PRIMARY_G_CHROMATICITY_X = 0x55D3;
private static final int ID_PRIMARY_G_CHROMATICITY_Y = 0x55D4;
private static final int ID_PRIMARY_B_CHROMATICITY_X = 0x55D5;
private static final int ID_PRIMARY_B_CHROMATICITY_Y = 0x55D6;
private static final int ID_WHITE_POINT_CHROMATICITY_X = 0x55D7;
private static final int ID_WHITE_POINT_CHROMATICITY_Y = 0x55D8;
private static final int ID_LUMNINANCE_MAX = 0x55D9;
private static final int ID_LUMNINANCE_MIN = 0x55DA;
private static final int LACING_NONE = 0; private static final int LACING_NONE = 0;
private static final int LACING_XIPH = 1; private static final int LACING_XIPH = 1;
...@@ -393,6 +411,8 @@ public final class MatroskaExtractor implements Extractor { ...@@ -393,6 +411,8 @@ public final class MatroskaExtractor implements Extractor {
case ID_CUE_TRACK_POSITIONS: case ID_CUE_TRACK_POSITIONS:
case ID_BLOCK_GROUP: case ID_BLOCK_GROUP:
case ID_PROJECTION: case ID_PROJECTION:
case ID_COLOUR:
case ID_MASTERING_METADATA:
return EbmlReader.TYPE_MASTER; return EbmlReader.TYPE_MASTER;
case ID_EBML_READ_VERSION: case ID_EBML_READ_VERSION:
case ID_DOC_TYPE_READ_VERSION: case ID_DOC_TYPE_READ_VERSION:
...@@ -423,6 +443,11 @@ public final class MatroskaExtractor implements Extractor { ...@@ -423,6 +443,11 @@ public final class MatroskaExtractor implements Extractor {
case ID_CUE_CLUSTER_POSITION: case ID_CUE_CLUSTER_POSITION:
case ID_REFERENCE_BLOCK: case ID_REFERENCE_BLOCK:
case ID_STEREO_MODE: case ID_STEREO_MODE:
case ID_COLOUR_RANGE:
case ID_COLOUR_TRANSFER:
case ID_COLOUR_PRIMARIES:
case ID_MAX_CLL:
case ID_MAX_FALL:
return EbmlReader.TYPE_UNSIGNED_INT; return EbmlReader.TYPE_UNSIGNED_INT;
case ID_DOC_TYPE: case ID_DOC_TYPE:
case ID_CODEC_ID: case ID_CODEC_ID:
...@@ -438,6 +463,16 @@ public final class MatroskaExtractor implements Extractor { ...@@ -438,6 +463,16 @@ public final class MatroskaExtractor implements Extractor {
return EbmlReader.TYPE_BINARY; return EbmlReader.TYPE_BINARY;
case ID_DURATION: case ID_DURATION:
case ID_SAMPLING_FREQUENCY: 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:
return EbmlReader.TYPE_FLOAT; return EbmlReader.TYPE_FLOAT;
default: default:
return EbmlReader.TYPE_UNKNOWN; return EbmlReader.TYPE_UNKNOWN;
...@@ -496,6 +531,9 @@ public final class MatroskaExtractor implements Extractor { ...@@ -496,6 +531,9 @@ public final class MatroskaExtractor implements Extractor {
case ID_TRACK_ENTRY: case ID_TRACK_ENTRY:
currentTrack = new Track(); currentTrack = new Track();
break; break;
case ID_MASTERING_METADATA:
currentTrack.hasColorInfo = true;
break;
default: default:
break; break;
} }
...@@ -706,6 +744,60 @@ public final class MatroskaExtractor implements Extractor { ...@@ -706,6 +744,60 @@ public final class MatroskaExtractor implements Extractor {
break; break;
} }
break; break;
case ID_COLOUR_PRIMARIES:
currentTrack.hasColorInfo = true;
switch ((int) value) {
case 1:
currentTrack.colorSpace = C.COLOR_SPACE_BT709;
break;
case 4: // BT.470M.
case 5: // BT.470BG.
case 6: // SMPTE 170M.
case 7: // SMPTE 240M.
currentTrack.colorSpace = C.COLOR_SPACE_BT601;
break;
case 9:
currentTrack.colorSpace = C.COLOR_SPACE_BT2020;
break;
default:
break;
}
break;
case ID_COLOUR_TRANSFER:
switch ((int) value) {
case 1: // BT.709.
case 6: // SMPTE 170M.
case 7: // SMPTE 240M.
currentTrack.colorTransfer = C.COLOR_TRANSFER_SDR;
break;
case 16:
currentTrack.colorTransfer = C.COLOR_TRANSFER_ST2084;
break;
case 18:
currentTrack.colorTransfer = C.COLOR_TRANSFER_HLG;
break;
default:
break;
}
break;
case ID_COLOUR_RANGE:
switch((int) value) {
case 1: // Broadcast range.
currentTrack.colorRange = C.COLOR_RANGE_LIMITED;
break;
case 2:
currentTrack.colorRange = C.COLOR_RANGE_FULL;
break;
default:
break;
}
break;
case ID_MAX_CLL:
currentTrack.maxContentLuminance = (int) value;
break;
case ID_MAX_FALL:
currentTrack.maxFrameAverageLuminance = (int) value;
break;
default: default:
break; break;
} }
...@@ -719,6 +811,36 @@ public final class MatroskaExtractor implements Extractor { ...@@ -719,6 +811,36 @@ public final class MatroskaExtractor implements Extractor {
case ID_SAMPLING_FREQUENCY: case ID_SAMPLING_FREQUENCY:
currentTrack.sampleRate = (int) value; currentTrack.sampleRate = (int) value;
break; break;
case ID_PRIMARY_R_CHROMATICITY_X:
currentTrack.primaryRChromaticityX = (float) value;
break;
case ID_PRIMARY_R_CHROMATICITY_Y:
currentTrack.primaryRChromaticityY = (float) value;
break;
case ID_PRIMARY_G_CHROMATICITY_X:
currentTrack.primaryGChromaticityX = (float) value;
break;
case ID_PRIMARY_G_CHROMATICITY_Y:
currentTrack.primaryGChromaticityY = (float) value;
break;
case ID_PRIMARY_B_CHROMATICITY_X:
currentTrack.primaryBChromaticityX = (float) value;
break;
case ID_PRIMARY_B_CHROMATICITY_Y:
currentTrack.primaryBChromaticityY = (float) value;
break;
case ID_WHITE_POINT_CHROMATICITY_X:
currentTrack.whitePointChromaticityX = (float) value;
break;
case ID_WHITE_POINT_CHROMATICITY_Y:
currentTrack.whitePointChromaticityY = (float) value;
break;
case ID_LUMNINANCE_MAX:
currentTrack.maxMasteringLuminance = (float) value;
break;
case ID_LUMNINANCE_MIN:
currentTrack.minMasteringLuminance = (float) value;
break;
default: default:
break; break;
} }
...@@ -1330,6 +1452,16 @@ public final class MatroskaExtractor implements Extractor { ...@@ -1330,6 +1452,16 @@ public final class MatroskaExtractor implements Extractor {
private static final class Track { private static final class Track {
private static final int DISPLAY_UNIT_PIXELS = 0; private static final int DISPLAY_UNIT_PIXELS = 0;
private static final int MAX_CHROMATICITY = 50000; // Defined in CTA-861.3.
/**
* Default max content light level (CLL) that should be encoded into hdrStaticInfo.
*/
private static final int DEFAULT_MAX_CLL = 1000; // nits.
/**
* Default frame-average light level (FALL) that should be encoded into hdrStaticInfo.
*/
private static final int DEFAULT_MAX_FALL = 200; // nits.
// Common elements. // Common elements.
public String codecId; public String codecId;
...@@ -1351,6 +1483,25 @@ public final class MatroskaExtractor implements Extractor { ...@@ -1351,6 +1483,25 @@ public final class MatroskaExtractor implements Extractor {
public byte[] projectionData = null; public byte[] projectionData = null;
@C.StereoMode @C.StereoMode
public int stereoMode = Format.NO_VALUE; public int stereoMode = Format.NO_VALUE;
public boolean hasColorInfo = false;
@C.ColorSpace
public int colorSpace = Format.NO_VALUE;
@C.ColorTransfer
public int colorTransfer = Format.NO_VALUE;
@C.ColorRange
public int colorRange = Format.NO_VALUE;
public int maxContentLuminance = DEFAULT_MAX_CLL;
public int maxFrameAverageLuminance = DEFAULT_MAX_FALL;
public float primaryRChromaticityX = Format.NO_VALUE;
public float primaryRChromaticityY = Format.NO_VALUE;
public float primaryGChromaticityX = Format.NO_VALUE;
public float primaryGChromaticityY = Format.NO_VALUE;
public float primaryBChromaticityX = Format.NO_VALUE;
public float primaryBChromaticityY = Format.NO_VALUE;
public float whitePointChromaticityX = Format.NO_VALUE;
public float whitePointChromaticityY = Format.NO_VALUE;
public float maxMasteringLuminance = Format.NO_VALUE;
public float minMasteringLuminance = Format.NO_VALUE;
// Audio elements. Initially set to their default values. // Audio elements. Initially set to their default values.
public int channelCount = 1; public int channelCount = 1;
...@@ -1520,9 +1671,15 @@ public final class MatroskaExtractor implements Extractor { ...@@ -1520,9 +1671,15 @@ public final class MatroskaExtractor implements Extractor {
if (displayWidth != Format.NO_VALUE && displayHeight != Format.NO_VALUE) { if (displayWidth != Format.NO_VALUE && displayHeight != Format.NO_VALUE) {
pixelWidthHeightRatio = ((float) (height * displayWidth)) / (width * displayHeight); pixelWidthHeightRatio = ((float) (height * displayWidth)) / (width * displayHeight);
} }
ColorInfo colorInfo = null;
if (hasColorInfo) {
byte[] hdrStaticInfo = getHdrStaticInfo();
colorInfo = new ColorInfo(colorSpace, colorRange, colorTransfer, hdrStaticInfo);
}
format = Format.createVideoSampleFormat(Integer.toString(trackId), mimeType, null, format = Format.createVideoSampleFormat(Integer.toString(trackId), mimeType, null,
Format.NO_VALUE, maxInputSize, width, height, Format.NO_VALUE, initializationData, Format.NO_VALUE, maxInputSize, width, height, Format.NO_VALUE, initializationData,
Format.NO_VALUE, pixelWidthHeightRatio, projectionData, stereoMode, drmInitData); Format.NO_VALUE, pixelWidthHeightRatio, projectionData, stereoMode, colorInfo,
drmInitData);
} else if (MimeTypes.APPLICATION_SUBRIP.equals(mimeType)) { } else if (MimeTypes.APPLICATION_SUBRIP.equals(mimeType)) {
type = C.TRACK_TYPE_TEXT; type = C.TRACK_TYPE_TEXT;
format = Format.createTextSampleFormat(Integer.toString(trackId), mimeType, null, format = Format.createTextSampleFormat(Integer.toString(trackId), mimeType, null,
...@@ -1542,6 +1699,38 @@ public final class MatroskaExtractor implements Extractor { ...@@ -1542,6 +1699,38 @@ public final class MatroskaExtractor implements Extractor {
} }
/** /**
* Returns the HDR Static Info as defined in CTA-861.3.
*/
private byte[] getHdrStaticInfo() {
// Are all fields present.
if (primaryRChromaticityX == Format.NO_VALUE || primaryRChromaticityY == Format.NO_VALUE
|| primaryGChromaticityX == Format.NO_VALUE || primaryGChromaticityY == Format.NO_VALUE
|| primaryBChromaticityX == Format.NO_VALUE || primaryBChromaticityY == Format.NO_VALUE
|| whitePointChromaticityX == Format.NO_VALUE
|| whitePointChromaticityY == Format.NO_VALUE || maxMasteringLuminance == Format.NO_VALUE
|| minMasteringLuminance == Format.NO_VALUE) {
return null;
}
byte[] hdrStaticInfoData = new byte[25];
ByteBuffer hdrStaticInfo = ByteBuffer.wrap(hdrStaticInfoData);
hdrStaticInfo.put((byte) 0); // Type.
hdrStaticInfo.putShort((short) ((primaryRChromaticityX * MAX_CHROMATICITY) + 0.5f));
hdrStaticInfo.putShort((short) ((primaryRChromaticityY * MAX_CHROMATICITY) + 0.5f));
hdrStaticInfo.putShort((short) ((primaryGChromaticityX * MAX_CHROMATICITY) + 0.5f));
hdrStaticInfo.putShort((short) ((primaryGChromaticityY * MAX_CHROMATICITY) + 0.5f));
hdrStaticInfo.putShort((short) ((primaryBChromaticityX * MAX_CHROMATICITY) + 0.5f));
hdrStaticInfo.putShort((short) ((primaryBChromaticityY * MAX_CHROMATICITY) + 0.5f));
hdrStaticInfo.putShort((short) ((whitePointChromaticityX * MAX_CHROMATICITY) + 0.5f));
hdrStaticInfo.putShort((short) ((whitePointChromaticityY * MAX_CHROMATICITY) + 0.5f));
hdrStaticInfo.putShort((short) (maxMasteringLuminance + 0.5f));
hdrStaticInfo.putShort((short) (minMasteringLuminance + 0.5f));
hdrStaticInfo.putShort((short) maxContentLuminance);
hdrStaticInfo.putShort((short) maxFrameAverageLuminance);
return hdrStaticInfoData;
}
/**
* Builds initialization data for a {@link Format} from FourCC codec private data. * Builds initialization data for a {@link Format} from FourCC codec private data.
* <p> * <p>
* VC1 is the only supported compression type. * VC1 is the only supported compression type.
......
...@@ -762,7 +762,7 @@ import java.util.List; ...@@ -762,7 +762,7 @@ import java.util.List;
out.format = Format.createVideoSampleFormat(Integer.toString(trackId), mimeType, null, out.format = Format.createVideoSampleFormat(Integer.toString(trackId), mimeType, null,
Format.NO_VALUE, Format.NO_VALUE, width, height, Format.NO_VALUE, initializationData, Format.NO_VALUE, Format.NO_VALUE, width, height, Format.NO_VALUE, initializationData,
rotationDegrees, pixelWidthHeightRatio, projectionData, stereoMode, drmInitData); rotationDegrees, pixelWidthHeightRatio, projectionData, stereoMode, null, drmInitData);
} }
/** /**
......
/*
* Copyright (C) 2017 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.exoplayer2.video;
import android.os.Parcel;
import android.os.Parcelable;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format;
import java.util.Arrays;
/**
* Stores color info.
*/
public final class ColorInfo implements Parcelable {
/**
* The color space of the video. Valid values are {@link C#COLOR_SPACE_BT601}, {@link
* C#COLOR_SPACE_BT709}, {@link C#COLOR_SPACE_BT2020} or {@link Format#NO_VALUE} if unknown.
*/
@C.ColorSpace
public final int colorSpace;
/**
* The color range of the video. Valid values are {@link C#COLOR_RANGE_LIMITED}, {@link
* C#COLOR_RANGE_FULL} or {@link Format#NO_VALUE} if unknown.
*/
@C.ColorRange
public final int colorRange;
/**
* The color transfer characteristicks of the video. Valid values are {@link
* C#COLOR_TRANSFER_HLG}, {@link C#COLOR_TRANSFER_ST2084}, {@link C#COLOR_TRANSFER_SDR} or {@link
* Format#NO_VALUE} if unknown.
*/
@C.ColorTransfer
public final int colorTransfer;
/**
* HdrStaticInfo as defined in CTA-861.3.
*/
public final byte[] hdrStaticInfo;
// Lazily initialized hashcode.
private int hashCode;
/**
* Constructs the ColorInfo.
*
* @param colorSpace The color space of the video.
* @param colorRange The color range of the video.
* @param colorTransfer The color transfer characteristics of the video.
* @param hdrStaticInfo HdrStaticInfo as defined in CTA-861.3.
*/
public ColorInfo(@C.ColorSpace int colorSpace, @C.ColorRange int colorRange,
@C.ColorTransfer int colorTransfer, byte[] hdrStaticInfo) {
this.colorSpace = colorSpace;
this.colorRange = colorRange;
this.colorTransfer = colorTransfer;
this.hdrStaticInfo = hdrStaticInfo;
}
@SuppressWarnings("ResourceType")
/* package */ ColorInfo(Parcel in) {
colorSpace = in.readInt();
colorRange = in.readInt();
colorTransfer = in.readInt();
boolean hasHdrStaticInfo = in.readInt() != 0;
hdrStaticInfo = hasHdrStaticInfo ? in.createByteArray() : null;
}
// Parcelable implementation.
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
ColorInfo other = (ColorInfo) obj;
if (colorSpace != other.colorSpace || colorRange != other.colorRange
|| colorTransfer != other.colorTransfer
|| !Arrays.equals(hdrStaticInfo, other.hdrStaticInfo)) {
return false;
}
return true;
}
@Override
public String toString() {
return "ColorInfo(" + colorSpace + ", " + colorRange + ", " + colorTransfer
+ ", " + (hdrStaticInfo != null) + ")";
}
@Override
public int hashCode() {
if (hashCode == 0) {
int result = 17;
result = 31 * result + colorSpace;
result = 31 * result + colorRange;
result = 31 * result + colorTransfer;
result = 31 * result + Arrays.hashCode(hdrStaticInfo);
hashCode = result;
}
return hashCode;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(colorSpace);
dest.writeInt(colorRange);
dest.writeInt(colorTransfer);
dest.writeInt(hdrStaticInfo != null ? 1 : 0);
if (hdrStaticInfo != null) {
dest.writeByteArray(hdrStaticInfo);
}
}
public static final Parcelable.Creator<ColorInfo> CREATOR = new Parcelable.Creator<ColorInfo>() {
@Override
public ColorInfo createFromParcel(Parcel in) {
return new ColorInfo(in);
}
@Override
public ColorInfo[] newArray(int size) {
return new ColorInfo[0];
}
};
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment