mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
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
This commit is contained in:
parent
d3fe20cc64
commit
e07b8fe7d5
6 changed files with 476 additions and 44 deletions
|
|
@ -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 {
|
||||||
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;
|
||||||
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;
|
||||||
|
|
@ -554,6 +555,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.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
* 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 {
|
||||||
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 {
|
||||||
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 {
|
||||||
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 {
|
||||||
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 {
|
||||||
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 {
|
||||||
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 {
|
||||||
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 {
|
||||||
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 {
|
||||||
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 {
|
||||||
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 {
|
||||||
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 {
|
||||||
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 {
|
||||||
: 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 {
|
||||||
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 {
|
||||||
|| !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 {
|
||||||
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 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@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 {
|
||||||
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;
|
||||||
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 {
|
||||||
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 {
|
||||||
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 {
|
||||||
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 {
|
||||||
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 {
|
||||||
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 {
|
||||||
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 {
|
||||||
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 {
|
||||||
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 {
|
||||||
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 {
|
||||||
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,
|
||||||
|
|
@ -1541,6 +1698,38 @@ public final class MatroskaExtractor implements Extractor {
|
||||||
this.output.format(format);
|
this.output.format(format);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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>
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,149 @@
|
||||||
|
/*
|
||||||
|
* 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];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue