mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
Support CEA 608/708 captions in MPEG2 TS stream
[Problem] Sarnoff spec complaince tests streams are MPEG2 TS. Currently, parsing CC data from MPEG2 TS is not supported [Solution] Parsed CC data from MPEG2 stream because all Sarnoff streams are MPEG2
This commit is contained in:
parent
18d208ab93
commit
2a388ff852
9 changed files with 301 additions and 32 deletions
|
|
@ -80,6 +80,12 @@ public final class C {
|
||||||
/** The number of bits per byte. */
|
/** The number of bits per byte. */
|
||||||
public static final int BITS_PER_BYTE = 8;
|
public static final int BITS_PER_BYTE = 8;
|
||||||
|
|
||||||
|
/** non-Wide aspect ratio */
|
||||||
|
public static final int NON_WIDE_ASPECT_RATIO_TYPE = 1;
|
||||||
|
|
||||||
|
/** Wide aspect ratio */
|
||||||
|
public static final int WIDE_ASPECT_RATIO_TYPE = 2;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The name of the ASCII charset.
|
* The name of the ASCII charset.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -15,9 +15,11 @@
|
||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer2;
|
package com.google.android.exoplayer2;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
import com.google.android.exoplayer2.drm.DrmInitData;
|
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;
|
||||||
|
|
@ -44,6 +46,7 @@ public final class Format implements Parcelable {
|
||||||
*/
|
*/
|
||||||
public static final long OFFSET_SAMPLE_RELATIVE = Long.MAX_VALUE;
|
public static final long OFFSET_SAMPLE_RELATIVE = Long.MAX_VALUE;
|
||||||
|
|
||||||
|
|
||||||
/** An identifier for the format, or null if unknown or not applicable. */
|
/** An identifier for the format, or null if unknown or not applicable. */
|
||||||
public final @Nullable String id;
|
public final @Nullable String id;
|
||||||
/**
|
/**
|
||||||
|
|
@ -148,7 +151,16 @@ public final class Format implements Parcelable {
|
||||||
*/
|
*/
|
||||||
public final int encoderPadding;
|
public final int encoderPadding;
|
||||||
|
|
||||||
|
/** A Bundle of custom parameters. Could be null or empty */
|
||||||
|
public final Bundle params;
|
||||||
|
|
||||||
// Audio and text specific.
|
// Audio and text specific.
|
||||||
|
/**
|
||||||
|
* Indicates if the video is wide aspect ratio (16:9) or not (4:3)
|
||||||
|
* Only influences captions if the lines are not middle aligned.
|
||||||
|
* Values are {@link C#NON_WIDE_ASPECT_RATIO} or {@link C#WIDE_ASPECT_RATIO},
|
||||||
|
*/
|
||||||
|
public static final String KEY_ASPECT_RATIO_TYPE = "aspect-ratio-type";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Track selection flags.
|
* Track selection flags.
|
||||||
|
|
@ -183,7 +195,7 @@ public final class Format implements Parcelable {
|
||||||
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, null, 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, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Format createVideoSampleFormat(
|
public static Format createVideoSampleFormat(
|
||||||
|
|
@ -238,7 +250,7 @@ public final class Format implements Parcelable {
|
||||||
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,
|
frameRate, rotationDegrees, pixelWidthHeightRatio, projectionData, stereoMode,
|
||||||
colorInfo, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, 0, null, NO_VALUE,
|
colorInfo, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, 0, null, NO_VALUE,
|
||||||
OFFSET_SAMPLE_RELATIVE, initializationData, drmInitData, null);
|
OFFSET_SAMPLE_RELATIVE, initializationData, drmInitData, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Audio.
|
// Audio.
|
||||||
|
|
@ -257,7 +269,7 @@ public final class Format implements Parcelable {
|
||||||
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, null, channelCount, sampleRate,
|
NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, null, NO_VALUE, null, channelCount, sampleRate,
|
||||||
NO_VALUE, 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, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Format createAudioSampleFormat(
|
public static Format createAudioSampleFormat(
|
||||||
|
|
@ -313,7 +325,7 @@ public final class Format implements Parcelable {
|
||||||
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, null, 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, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Text.
|
// Text.
|
||||||
|
|
@ -342,7 +354,7 @@ public final class Format implements Parcelable {
|
||||||
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, null, 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,
|
NO_VALUE, NO_VALUE, NO_VALUE, selectionFlags, language, accessibilityChannel,
|
||||||
OFFSET_SAMPLE_RELATIVE, null, null, null);
|
OFFSET_SAMPLE_RELATIVE, null, null, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Format createTextSampleFormat(
|
public static Format createTextSampleFormat(
|
||||||
|
|
@ -389,6 +401,24 @@ public final class Format implements Parcelable {
|
||||||
NO_VALUE, drmInitData, subsampleOffsetUs, Collections.<byte[]>emptyList());
|
NO_VALUE, drmInitData, subsampleOffsetUs, Collections.<byte[]>emptyList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Format createTextSampleFormat(
|
||||||
|
@Nullable String id,
|
||||||
|
@Nullable String sampleMimeType,
|
||||||
|
@Nullable String codecs,
|
||||||
|
int bitrate,
|
||||||
|
@C.SelectionFlags int selectionFlags,
|
||||||
|
String language,
|
||||||
|
int accessibilityChannel,
|
||||||
|
DrmInitData drmInitData,
|
||||||
|
Bundle params) {
|
||||||
|
return new Format(id, null, sampleMimeType, codecs, bitrate,
|
||||||
|
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, OFFSET_SAMPLE_RELATIVE,
|
||||||
|
null, drmInitData, null, params);
|
||||||
|
}
|
||||||
|
|
||||||
public static Format createTextSampleFormat(
|
public static Format createTextSampleFormat(
|
||||||
@Nullable String id,
|
@Nullable String id,
|
||||||
@Nullable String sampleMimeType,
|
@Nullable String sampleMimeType,
|
||||||
|
|
@ -399,11 +429,12 @@ public final class Format implements Parcelable {
|
||||||
int accessibilityChannel,
|
int accessibilityChannel,
|
||||||
@Nullable DrmInitData drmInitData,
|
@Nullable DrmInitData drmInitData,
|
||||||
long subsampleOffsetUs,
|
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, null, 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, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Image.
|
// Image.
|
||||||
|
|
@ -443,7 +474,7 @@ public final class Format implements Parcelable {
|
||||||
OFFSET_SAMPLE_RELATIVE,
|
OFFSET_SAMPLE_RELATIVE,
|
||||||
initializationData,
|
initializationData,
|
||||||
drmInitData,
|
drmInitData,
|
||||||
null);
|
null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generic.
|
// Generic.
|
||||||
|
|
@ -459,14 +490,14 @@ public final class Format implements Parcelable {
|
||||||
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, null, 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, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Format createSampleFormat(
|
public static Format createSampleFormat(
|
||||||
@Nullable String id, @Nullable String sampleMimeType, long subsampleOffsetUs) {
|
@Nullable String id, @Nullable String sampleMimeType, 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, null, 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, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Format createSampleFormat(
|
public static Format createSampleFormat(
|
||||||
|
|
@ -477,7 +508,7 @@ public final class Format implements Parcelable {
|
||||||
@Nullable DrmInitData drmInitData) {
|
@Nullable 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, null, 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, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* package */ Format(
|
/* package */ Format(
|
||||||
|
|
@ -506,7 +537,8 @@ public final class Format implements Parcelable {
|
||||||
long subsampleOffsetUs,
|
long subsampleOffsetUs,
|
||||||
@Nullable List<byte[]> initializationData,
|
@Nullable List<byte[]> initializationData,
|
||||||
@Nullable DrmInitData drmInitData,
|
@Nullable DrmInitData drmInitData,
|
||||||
@Nullable Metadata metadata) {
|
@Nullable Metadata metadata,
|
||||||
|
Bundle params) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.containerMimeType = containerMimeType;
|
this.containerMimeType = containerMimeType;
|
||||||
this.sampleMimeType = sampleMimeType;
|
this.sampleMimeType = sampleMimeType;
|
||||||
|
|
@ -535,6 +567,7 @@ public final class Format implements Parcelable {
|
||||||
: initializationData;
|
: initializationData;
|
||||||
this.drmInitData = drmInitData;
|
this.drmInitData = drmInitData;
|
||||||
this.metadata = metadata;
|
this.metadata = metadata;
|
||||||
|
this.params = params;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("ResourceType")
|
@SuppressWarnings("ResourceType")
|
||||||
|
|
@ -570,6 +603,7 @@ public final class Format implements Parcelable {
|
||||||
}
|
}
|
||||||
drmInitData = in.readParcelable(DrmInitData.class.getClassLoader());
|
drmInitData = in.readParcelable(DrmInitData.class.getClassLoader());
|
||||||
metadata = in.readParcelable(Metadata.class.getClassLoader());
|
metadata = in.readParcelable(Metadata.class.getClassLoader());
|
||||||
|
params = in.readBundle(getClass().getClassLoader());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Format copyWithMaxInputSize(int maxInputSize) {
|
public Format copyWithMaxInputSize(int maxInputSize) {
|
||||||
|
|
@ -577,7 +611,7 @@ public final class Format implements Parcelable {
|
||||||
height, frameRate, rotationDegrees, pixelWidthHeightRatio, projectionData, stereoMode,
|
height, frameRate, rotationDegrees, pixelWidthHeightRatio, projectionData, stereoMode,
|
||||||
colorInfo, channelCount, sampleRate, pcmEncoding, encoderDelay, encoderPadding,
|
colorInfo, channelCount, sampleRate, pcmEncoding, encoderDelay, encoderPadding,
|
||||||
selectionFlags, language, accessibilityChannel, subsampleOffsetUs, initializationData,
|
selectionFlags, language, accessibilityChannel, subsampleOffsetUs, initializationData,
|
||||||
drmInitData, metadata);
|
drmInitData, metadata, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Format copyWithSubsampleOffsetUs(long subsampleOffsetUs) {
|
public Format copyWithSubsampleOffsetUs(long subsampleOffsetUs) {
|
||||||
|
|
@ -585,7 +619,7 @@ public final class Format implements Parcelable {
|
||||||
height, frameRate, rotationDegrees, pixelWidthHeightRatio, projectionData, stereoMode,
|
height, frameRate, rotationDegrees, pixelWidthHeightRatio, projectionData, stereoMode,
|
||||||
colorInfo, channelCount, sampleRate, pcmEncoding, encoderDelay, encoderPadding,
|
colorInfo, channelCount, sampleRate, pcmEncoding, encoderDelay, encoderPadding,
|
||||||
selectionFlags, language, accessibilityChannel, subsampleOffsetUs, initializationData,
|
selectionFlags, language, accessibilityChannel, subsampleOffsetUs, initializationData,
|
||||||
drmInitData, metadata);
|
drmInitData, metadata, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Format copyWithContainerInfo(
|
public Format copyWithContainerInfo(
|
||||||
|
|
@ -601,7 +635,7 @@ public final class Format implements Parcelable {
|
||||||
height, frameRate, rotationDegrees, pixelWidthHeightRatio, projectionData, stereoMode,
|
height, frameRate, rotationDegrees, pixelWidthHeightRatio, projectionData, stereoMode,
|
||||||
colorInfo, channelCount, sampleRate, pcmEncoding, encoderDelay, encoderPadding,
|
colorInfo, channelCount, sampleRate, pcmEncoding, encoderDelay, encoderPadding,
|
||||||
selectionFlags, language, accessibilityChannel, subsampleOffsetUs, initializationData,
|
selectionFlags, language, accessibilityChannel, subsampleOffsetUs, initializationData,
|
||||||
drmInitData, metadata);
|
drmInitData, metadata, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("ReferenceEquality")
|
@SuppressWarnings("ReferenceEquality")
|
||||||
|
|
@ -622,7 +656,7 @@ public final class Format implements Parcelable {
|
||||||
height, frameRate, rotationDegrees, pixelWidthHeightRatio, projectionData, stereoMode,
|
height, frameRate, rotationDegrees, pixelWidthHeightRatio, projectionData, stereoMode,
|
||||||
colorInfo, channelCount, sampleRate, pcmEncoding, encoderDelay, encoderPadding,
|
colorInfo, channelCount, sampleRate, pcmEncoding, encoderDelay, encoderPadding,
|
||||||
selectionFlags, language, accessibilityChannel, subsampleOffsetUs, initializationData,
|
selectionFlags, language, accessibilityChannel, subsampleOffsetUs, initializationData,
|
||||||
drmInitData, metadata);
|
drmInitData, metadata, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Format copyWithGaplessInfo(int encoderDelay, int encoderPadding) {
|
public Format copyWithGaplessInfo(int encoderDelay, int encoderPadding) {
|
||||||
|
|
@ -630,7 +664,7 @@ public final class Format implements Parcelable {
|
||||||
height, frameRate, rotationDegrees, pixelWidthHeightRatio, projectionData, stereoMode,
|
height, frameRate, rotationDegrees, pixelWidthHeightRatio, projectionData, stereoMode,
|
||||||
colorInfo, channelCount, sampleRate, pcmEncoding, encoderDelay, encoderPadding,
|
colorInfo, channelCount, sampleRate, pcmEncoding, encoderDelay, encoderPadding,
|
||||||
selectionFlags, language, accessibilityChannel, subsampleOffsetUs, initializationData,
|
selectionFlags, language, accessibilityChannel, subsampleOffsetUs, initializationData,
|
||||||
drmInitData, metadata);
|
drmInitData, metadata, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Format copyWithDrmInitData(@Nullable DrmInitData drmInitData) {
|
public Format copyWithDrmInitData(@Nullable DrmInitData drmInitData) {
|
||||||
|
|
@ -638,7 +672,7 @@ public final class Format implements Parcelable {
|
||||||
height, frameRate, rotationDegrees, pixelWidthHeightRatio, projectionData, stereoMode,
|
height, frameRate, rotationDegrees, pixelWidthHeightRatio, projectionData, stereoMode,
|
||||||
colorInfo, channelCount, sampleRate, pcmEncoding, encoderDelay, encoderPadding,
|
colorInfo, channelCount, sampleRate, pcmEncoding, encoderDelay, encoderPadding,
|
||||||
selectionFlags, language, accessibilityChannel, subsampleOffsetUs, initializationData,
|
selectionFlags, language, accessibilityChannel, subsampleOffsetUs, initializationData,
|
||||||
drmInitData, metadata);
|
drmInitData, metadata, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Format copyWithMetadata(@Nullable Metadata metadata) {
|
public Format copyWithMetadata(@Nullable Metadata metadata) {
|
||||||
|
|
@ -646,7 +680,7 @@ public final class Format implements Parcelable {
|
||||||
height, frameRate, rotationDegrees, pixelWidthHeightRatio, projectionData, stereoMode,
|
height, frameRate, rotationDegrees, pixelWidthHeightRatio, projectionData, stereoMode,
|
||||||
colorInfo, channelCount, sampleRate, pcmEncoding, encoderDelay, encoderPadding,
|
colorInfo, channelCount, sampleRate, pcmEncoding, encoderDelay, encoderPadding,
|
||||||
selectionFlags, language, accessibilityChannel, subsampleOffsetUs, initializationData,
|
selectionFlags, language, accessibilityChannel, subsampleOffsetUs, initializationData,
|
||||||
drmInitData, metadata);
|
drmInitData, metadata, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Format copyWithRotationDegrees(int rotationDegrees) {
|
public Format copyWithRotationDegrees(int rotationDegrees) {
|
||||||
|
|
@ -654,7 +688,7 @@ public final class Format implements Parcelable {
|
||||||
height, frameRate, rotationDegrees, pixelWidthHeightRatio, projectionData, stereoMode,
|
height, frameRate, rotationDegrees, pixelWidthHeightRatio, projectionData, stereoMode,
|
||||||
colorInfo, channelCount, sampleRate, pcmEncoding, encoderDelay, encoderPadding,
|
colorInfo, channelCount, sampleRate, pcmEncoding, encoderDelay, encoderPadding,
|
||||||
selectionFlags, language, accessibilityChannel, subsampleOffsetUs, initializationData,
|
selectionFlags, language, accessibilityChannel, subsampleOffsetUs, initializationData,
|
||||||
drmInitData, metadata);
|
drmInitData, metadata, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -825,6 +859,8 @@ public final class Format implements Parcelable {
|
||||||
}
|
}
|
||||||
dest.writeParcelable(drmInitData, 0);
|
dest.writeParcelable(drmInitData, 0);
|
||||||
dest.writeParcelable(metadata, 0);
|
dest.writeParcelable(metadata, 0);
|
||||||
|
dest.writeBundle(params);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final Creator<Format> CREATOR = new Creator<Format>() {
|
public static final Creator<Format> CREATOR = new Creator<Format>() {
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,11 @@
|
||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer2.extractor.ts;
|
package com.google.android.exoplayer2.extractor.ts;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
import android.support.annotation.IntDef;
|
import android.support.annotation.IntDef;
|
||||||
import android.util.SparseArray;
|
import android.util.SparseArray;
|
||||||
|
|
||||||
|
import com.google.android.exoplayer2.C;
|
||||||
import com.google.android.exoplayer2.Format;
|
import com.google.android.exoplayer2.Format;
|
||||||
import com.google.android.exoplayer2.extractor.ts.TsPayloadReader.EsInfo;
|
import com.google.android.exoplayer2.extractor.ts.TsPayloadReader.EsInfo;
|
||||||
import com.google.android.exoplayer2.util.MimeTypes;
|
import com.google.android.exoplayer2.util.MimeTypes;
|
||||||
|
|
@ -79,6 +82,13 @@ public final class DefaultTsPayloadReaderFactory implements TsPayloadReader.Fact
|
||||||
*/
|
*/
|
||||||
public DefaultTsPayloadReaderFactory(@Flags int flags, List<Format> closedCaptionFormats) {
|
public DefaultTsPayloadReaderFactory(@Flags int flags, List<Format> closedCaptionFormats) {
|
||||||
this.flags = flags;
|
this.flags = flags;
|
||||||
|
if (!isSet(FLAG_OVERRIDE_CAPTION_DESCRIPTORS) && closedCaptionFormats.isEmpty()) {
|
||||||
|
closedCaptionFormats = new ArrayList();
|
||||||
|
closedCaptionFormats.add(Format.createTextSampleFormat(null,
|
||||||
|
MimeTypes.APPLICATION_CEA608, 0, null));
|
||||||
|
closedCaptionFormats.add(Format.createTextSampleFormat(null,
|
||||||
|
MimeTypes.APPLICATION_CEA708, 0, null));
|
||||||
|
}
|
||||||
this.closedCaptionFormats = closedCaptionFormats;
|
this.closedCaptionFormats = closedCaptionFormats;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -106,7 +116,7 @@ public final class DefaultTsPayloadReaderFactory implements TsPayloadReader.Fact
|
||||||
case TsExtractor.TS_STREAM_TYPE_HDMV_DTS:
|
case TsExtractor.TS_STREAM_TYPE_HDMV_DTS:
|
||||||
return new PesReader(new DtsReader(esInfo.language));
|
return new PesReader(new DtsReader(esInfo.language));
|
||||||
case TsExtractor.TS_STREAM_TYPE_H262:
|
case TsExtractor.TS_STREAM_TYPE_H262:
|
||||||
return new PesReader(new H262Reader());
|
return new PesReader(new H262Reader(buildUserDataReader(esInfo)));
|
||||||
case TsExtractor.TS_STREAM_TYPE_H264:
|
case TsExtractor.TS_STREAM_TYPE_H264:
|
||||||
return isSet(FLAG_IGNORE_H264_STREAM) ? null
|
return isSet(FLAG_IGNORE_H264_STREAM) ? null
|
||||||
: new PesReader(new H264Reader(buildSeiReader(esInfo),
|
: new PesReader(new H264Reader(buildSeiReader(esInfo),
|
||||||
|
|
@ -136,8 +146,34 @@ public final class DefaultTsPayloadReaderFactory implements TsPayloadReader.Fact
|
||||||
* @return A {@link SeiReader} for closed caption tracks.
|
* @return A {@link SeiReader} for closed caption tracks.
|
||||||
*/
|
*/
|
||||||
private SeiReader buildSeiReader(EsInfo esInfo) {
|
private SeiReader buildSeiReader(EsInfo esInfo) {
|
||||||
|
return new SeiReader(getCCformats(esInfo));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If {@link #FLAG_OVERRIDE_CAPTION_DESCRIPTORS} is set, returns a {@link UserDataReader} for
|
||||||
|
* {@link #closedCaptionFormats}. If unset, parses the PMT descriptor information and returns a
|
||||||
|
* {@link UserDataReader} for the declared formats, or {@link #closedCaptionFormats} if the descriptor
|
||||||
|
* is not present.
|
||||||
|
*
|
||||||
|
* @param esInfo The {@link EsInfo} passed to {@link #createPayloadReader(int, EsInfo)}.
|
||||||
|
* @return A {@link UserDataReader} for closed caption tracks.
|
||||||
|
*/
|
||||||
|
private UserDataReader buildUserDataReader(EsInfo esInfo) {
|
||||||
|
return new UserDataReader(getCCformats(esInfo));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If {@link #FLAG_OVERRIDE_CAPTION_DESCRIPTORS} is set, returns a {@link List<Format>} of
|
||||||
|
* {@link #closedCaptionFormats}. If unset, parses the PMT descriptor information and returns a
|
||||||
|
* {@link List<Format>} for the declared formats, or {@link #closedCaptionFormats} if the descriptor
|
||||||
|
* is not present.
|
||||||
|
*
|
||||||
|
* @param esInfo The {@link EsInfo} passed to {@link #createPayloadReader(int, EsInfo)}.
|
||||||
|
* @return A {@link List<Format>} containing list of closed caption formats.
|
||||||
|
*/
|
||||||
|
private List<Format> getCCformats(EsInfo esInfo) {
|
||||||
if (isSet(FLAG_OVERRIDE_CAPTION_DESCRIPTORS)) {
|
if (isSet(FLAG_OVERRIDE_CAPTION_DESCRIPTORS)) {
|
||||||
return new SeiReader(closedCaptionFormats);
|
return closedCaptionFormats;
|
||||||
}
|
}
|
||||||
ParsableByteArray scratchDescriptorData = new ParsableByteArray(esInfo.descriptorBytes);
|
ParsableByteArray scratchDescriptorData = new ParsableByteArray(esInfo.descriptorBytes);
|
||||||
List<Format> closedCaptionFormats = this.closedCaptionFormats;
|
List<Format> closedCaptionFormats = this.closedCaptionFormats;
|
||||||
|
|
@ -162,17 +198,24 @@ public final class DefaultTsPayloadReaderFactory implements TsPayloadReader.Fact
|
||||||
mimeType = MimeTypes.APPLICATION_CEA608;
|
mimeType = MimeTypes.APPLICATION_CEA608;
|
||||||
accessibilityChannel = 1;
|
accessibilityChannel = 1;
|
||||||
}
|
}
|
||||||
closedCaptionFormats.add(Format.createTextSampleFormat(null, mimeType, null,
|
|
||||||
Format.NO_VALUE, 0, language, accessibilityChannel, null));
|
|
||||||
// Skip easy_reader(1), wide_aspect_ratio(1), reserved(14).
|
// Skip easy_reader(1), wide_aspect_ratio(1), reserved(14).
|
||||||
scratchDescriptorData.skipBytes(2);
|
byte misc = (byte)scratchDescriptorData.readUnsignedByte();
|
||||||
|
boolean isWideAspectRatio = ((misc & 0x60) == 0x60);
|
||||||
|
Bundle params = new Bundle();
|
||||||
|
params.putInt(Format.KEY_ASPECT_RATIO_TYPE,
|
||||||
|
isWideAspectRatio ? C.WIDE_ASPECT_RATIO_TYPE: C.NON_WIDE_ASPECT_RATIO_TYPE);
|
||||||
|
closedCaptionFormats.add(Format.createTextSampleFormat(null, mimeType, null,
|
||||||
|
Format.NO_VALUE, 0, language, accessibilityChannel, null,
|
||||||
|
params));
|
||||||
|
scratchDescriptorData.skipBytes(1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Unknown descriptor. Ignore.
|
// Unknown descriptor. Ignore.
|
||||||
}
|
}
|
||||||
scratchDescriptorData.setPosition(nextDescriptorPosition);
|
scratchDescriptorData.setPosition(nextDescriptorPosition);
|
||||||
}
|
}
|
||||||
return new SeiReader(closedCaptionFormats);
|
|
||||||
|
return closedCaptionFormats;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isSet(@Flags int flag) {
|
private boolean isSet(@Flags int flag) {
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ public final class H262Reader implements ElementaryStreamReader {
|
||||||
private static final int START_SEQUENCE_HEADER = 0xB3;
|
private static final int START_SEQUENCE_HEADER = 0xB3;
|
||||||
private static final int START_EXTENSION = 0xB5;
|
private static final int START_EXTENSION = 0xB5;
|
||||||
private static final int START_GROUP = 0xB8;
|
private static final int START_GROUP = 0xB8;
|
||||||
|
private static final int START_USER_DATA = 0xB2;
|
||||||
|
|
||||||
private String formatId;
|
private String formatId;
|
||||||
private TrackOutput output;
|
private TrackOutput output;
|
||||||
|
|
@ -62,16 +63,30 @@ public final class H262Reader implements ElementaryStreamReader {
|
||||||
private long sampleTimeUs;
|
private long sampleTimeUs;
|
||||||
private boolean sampleIsKeyframe;
|
private boolean sampleIsKeyframe;
|
||||||
private boolean sampleHasPicture;
|
private boolean sampleHasPicture;
|
||||||
|
private NalUnitTargetBuffer userData = null;
|
||||||
|
private UserDataReader userDataReader = null;
|
||||||
|
// Scratch variables to avoid allocations.
|
||||||
|
private ParsableByteArray userDataParsable = null;
|
||||||
public H262Reader() {
|
public H262Reader() {
|
||||||
|
this(null);
|
||||||
|
}
|
||||||
|
public H262Reader(UserDataReader userDataReader) {
|
||||||
|
this.userDataReader = userDataReader;
|
||||||
prefixFlags = new boolean[4];
|
prefixFlags = new boolean[4];
|
||||||
csdBuffer = new CsdBuffer(128);
|
csdBuffer = new CsdBuffer(128);
|
||||||
|
if (userDataReader != null) {
|
||||||
|
userData = new NalUnitTargetBuffer(START_USER_DATA, 128);
|
||||||
|
userDataParsable = new ParsableByteArray();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void seek() {
|
public void seek() {
|
||||||
NalUnitUtil.clearPrefixFlags(prefixFlags);
|
NalUnitUtil.clearPrefixFlags(prefixFlags);
|
||||||
csdBuffer.reset();
|
csdBuffer.reset();
|
||||||
|
if (userData != null) {
|
||||||
|
userData.reset();
|
||||||
|
}
|
||||||
totalBytesWritten = 0;
|
totalBytesWritten = 0;
|
||||||
startedFirstSample = false;
|
startedFirstSample = false;
|
||||||
}
|
}
|
||||||
|
|
@ -81,6 +96,9 @@ public final class H262Reader implements ElementaryStreamReader {
|
||||||
idGenerator.generateNewId();
|
idGenerator.generateNewId();
|
||||||
formatId = idGenerator.getFormatId();
|
formatId = idGenerator.getFormatId();
|
||||||
output = extractorOutput.track(idGenerator.getTrackId(), C.TRACK_TYPE_VIDEO);
|
output = extractorOutput.track(idGenerator.getTrackId(), C.TRACK_TYPE_VIDEO);
|
||||||
|
if (userDataReader != null) {
|
||||||
|
userDataReader.createTracks(extractorOutput, idGenerator);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -106,6 +124,9 @@ public final class H262Reader implements ElementaryStreamReader {
|
||||||
if (!hasOutputFormat) {
|
if (!hasOutputFormat) {
|
||||||
csdBuffer.onData(dataArray, offset, limit);
|
csdBuffer.onData(dataArray, offset, limit);
|
||||||
}
|
}
|
||||||
|
if (userData != null) {
|
||||||
|
userData.appendToNalUnit(dataArray, offset, limit);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -130,7 +151,25 @@ public final class H262Reader implements ElementaryStreamReader {
|
||||||
hasOutputFormat = true;
|
hasOutputFormat = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (userDataReader != null && userData != null) {
|
||||||
|
int lengthToStartCode = startCodeOffset - offset;
|
||||||
|
int bytesAlreadyPassed = 0;
|
||||||
|
if (lengthToStartCode > 0) {
|
||||||
|
userData.appendToNalUnit(dataArray, offset, startCodeOffset);
|
||||||
|
} else {
|
||||||
|
bytesAlreadyPassed = -lengthToStartCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userData.endNalUnit(bytesAlreadyPassed)) {
|
||||||
|
int unescapedLength = NalUnitUtil.unescapeStream(userData.nalData, userData.nalLength);
|
||||||
|
userDataParsable.reset(userData.nalData, unescapedLength);
|
||||||
|
userDataReader.consume(sampleTimeUs, userDataParsable);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (startCodeValue == START_USER_DATA && data.data[startCodeOffset + 2] == 0x1) {
|
||||||
|
userData.startNalUnit(startCodeValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (startCodeValue == START_PICTURE || startCodeValue == START_SEQUENCE_HEADER) {
|
if (startCodeValue == START_PICTURE || startCodeValue == START_SEQUENCE_HEADER) {
|
||||||
int bytesWrittenPastStartCode = limit - startCodeOffset;
|
int bytesWrittenPastStartCode = limit - startCodeOffset;
|
||||||
if (startedFirstSample && sampleHasPicture && hasOutputFormat) {
|
if (startedFirstSample && sampleHasPicture && hasOutputFormat) {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,92 @@
|
||||||
|
/*
|
||||||
|
* 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.extractor.ts;
|
||||||
|
|
||||||
|
import com.google.android.exoplayer2.C;
|
||||||
|
import com.google.android.exoplayer2.Format;
|
||||||
|
import com.google.android.exoplayer2.extractor.ExtractorOutput;
|
||||||
|
import com.google.android.exoplayer2.extractor.TrackOutput;
|
||||||
|
import com.google.android.exoplayer2.util.Assertions;
|
||||||
|
import com.google.android.exoplayer2.util.MimeTypes;
|
||||||
|
import com.google.android.exoplayer2.util.ParsableByteArray;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Consumes user data structure, outputting contained CEA-608/708 messages to a {@link TrackOutput}.
|
||||||
|
*/
|
||||||
|
/* package */ final class UserDataReader {
|
||||||
|
private final List<Format> closedCaptionFormats;
|
||||||
|
private final TrackOutput[] outputs;
|
||||||
|
private final int USER_DATA_START_CODE = 0x0001B2;
|
||||||
|
private final int USER_DATA_IDENTIFIER_GA94 = 0x47413934;
|
||||||
|
private final int USER_DATA_TYPE_CODE_MPEG_CC = 0x03;
|
||||||
|
public UserDataReader(List<Format> closedCaptionFormats) {
|
||||||
|
this.closedCaptionFormats = closedCaptionFormats;
|
||||||
|
outputs = new TrackOutput[closedCaptionFormats.size()];
|
||||||
|
}
|
||||||
|
|
||||||
|
public void createTracks(ExtractorOutput extractorOutput,
|
||||||
|
TsPayloadReader.TrackIdGenerator idGenerator) {
|
||||||
|
for (int i = 0; i < outputs.length; i++) {
|
||||||
|
idGenerator.generateNewId();
|
||||||
|
TrackOutput output = extractorOutput.track(idGenerator.getTrackId(), C.TRACK_TYPE_TEXT);
|
||||||
|
Format channelFormat = closedCaptionFormats.get(i);
|
||||||
|
String channelMimeType = channelFormat.sampleMimeType;
|
||||||
|
Assertions.checkArgument(MimeTypes.APPLICATION_CEA608.equals(channelMimeType)
|
||||||
|
|| MimeTypes.APPLICATION_CEA708.equals(channelMimeType),
|
||||||
|
"Invalid closed caption mime type provided: " + channelMimeType);
|
||||||
|
output.format(Format.createTextSampleFormat(idGenerator.getFormatId(), channelMimeType, null,
|
||||||
|
Format.NO_VALUE, channelFormat.selectionFlags, channelFormat.language,
|
||||||
|
channelFormat.accessibilityChannel, null, channelFormat.params));
|
||||||
|
outputs[i] = output;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void consume(long pesTimeUs, ParsableByteArray userDataPayload) {
|
||||||
|
if (userDataPayload.bytesLeft() < 9) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//check if payload is used_data_type (0x01B2)
|
||||||
|
int userDataStartCode = userDataPayload.readInt();
|
||||||
|
int userDataIdentifier = userDataPayload.readInt();
|
||||||
|
int userDataTypeCode = userDataPayload.readUnsignedByte();
|
||||||
|
|
||||||
|
if (userDataStartCode == USER_DATA_START_CODE && userDataIdentifier == USER_DATA_IDENTIFIER_GA94
|
||||||
|
&& userDataTypeCode == USER_DATA_TYPE_CODE_MPEG_CC) {
|
||||||
|
if (userDataPayload.bytesLeft() < 2) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// read cc_count and process_cc_data_flag byte.
|
||||||
|
int ccByte = userDataPayload.readUnsignedByte();
|
||||||
|
boolean processCCDataFlag = ((ccByte & 0x40) != 0);
|
||||||
|
int ccCount = (ccByte & 0x1F);
|
||||||
|
// skip reserved em_data byte of MPEG_CC structure
|
||||||
|
userDataPayload.skipBytes(1);
|
||||||
|
int payLoadSize = ccCount * 3;
|
||||||
|
if (processCCDataFlag && payLoadSize != 0) {
|
||||||
|
int ccPos = userDataPayload.getPosition();
|
||||||
|
for (TrackOutput output : outputs) {
|
||||||
|
output.sampleData(userDataPayload, payLoadSize);
|
||||||
|
output.sampleMetadata(pesTimeUs, C.BUFFER_FLAG_KEY_FRAME, payLoadSize, 0, null);
|
||||||
|
userDataPayload.setPosition(ccPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -2,7 +2,7 @@ seekMap:
|
||||||
isSeekable = false
|
isSeekable = false
|
||||||
duration = 66733
|
duration = 66733
|
||||||
getPosition(0) = [[timeUs=0, position=0]]
|
getPosition(0) = [[timeUs=0, position=0]]
|
||||||
numberOfTracks = 2
|
numberOfTracks = 3
|
||||||
track 256:
|
track 256:
|
||||||
format:
|
format:
|
||||||
bitrate = -1
|
bitrate = -1
|
||||||
|
|
@ -76,4 +76,28 @@ track 257:
|
||||||
time = 100822
|
time = 100822
|
||||||
flags = 1
|
flags = 1
|
||||||
data = length 1254, hash 73FB07B8
|
data = length 1254, hash 73FB07B8
|
||||||
|
track 8448:
|
||||||
|
format:
|
||||||
|
bitrate = -1
|
||||||
|
id = 1/8448
|
||||||
|
containerMimeType = null
|
||||||
|
sampleMimeType = application/cea-608
|
||||||
|
maxInputSize = -1
|
||||||
|
width = -1
|
||||||
|
height = -1
|
||||||
|
frameRate = -1.0
|
||||||
|
rotationDegrees = 0
|
||||||
|
pixelWidthHeightRatio = 1.0
|
||||||
|
channelCount = -1
|
||||||
|
sampleRate = -1
|
||||||
|
pcmEncoding = -1
|
||||||
|
encoderDelay = 0
|
||||||
|
encoderPadding = 0
|
||||||
|
subsampleOffsetUs = 9223372036854775807
|
||||||
|
selectionFlags = 0
|
||||||
|
language = null
|
||||||
|
drmInitData = -
|
||||||
|
initializationData:
|
||||||
|
total output bytes = 0
|
||||||
|
sample count = 0
|
||||||
tracksEnded = true
|
tracksEnded = true
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ seekMap:
|
||||||
isSeekable = false
|
isSeekable = false
|
||||||
duration = UNSET TIME
|
duration = UNSET TIME
|
||||||
getPosition(0) = [[timeUs=0, position=0]]
|
getPosition(0) = [[timeUs=0, position=0]]
|
||||||
numberOfTracks = 2
|
numberOfTracks = 3
|
||||||
track 256:
|
track 256:
|
||||||
format:
|
format:
|
||||||
bitrate = -1
|
bitrate = -1
|
||||||
|
|
@ -76,4 +76,28 @@ track 257:
|
||||||
time = 100822
|
time = 100822
|
||||||
flags = 1
|
flags = 1
|
||||||
data = length 1254, hash 73FB07B8
|
data = length 1254, hash 73FB07B8
|
||||||
|
track 8448:
|
||||||
|
format:
|
||||||
|
bitrate = -1
|
||||||
|
id = 1/8448
|
||||||
|
containerMimeType = null
|
||||||
|
sampleMimeType = application/cea-608
|
||||||
|
maxInputSize = -1
|
||||||
|
width = -1
|
||||||
|
height = -1
|
||||||
|
frameRate = -1.0
|
||||||
|
rotationDegrees = 0
|
||||||
|
pixelWidthHeightRatio = 1.0
|
||||||
|
channelCount = -1
|
||||||
|
sampleRate = -1
|
||||||
|
pcmEncoding = -1
|
||||||
|
encoderDelay = 0
|
||||||
|
encoderPadding = 0
|
||||||
|
subsampleOffsetUs = 9223372036854775807
|
||||||
|
selectionFlags = 0
|
||||||
|
language = null
|
||||||
|
drmInitData = -
|
||||||
|
initializationData:
|
||||||
|
total output bytes = 0
|
||||||
|
sample count = 0
|
||||||
tracksEnded = true
|
tracksEnded = true
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,9 @@ import static com.google.android.exoplayer2.util.MimeTypes.VIDEO_MP4;
|
||||||
import static com.google.android.exoplayer2.util.MimeTypes.VIDEO_WEBM;
|
import static com.google.android.exoplayer2.util.MimeTypes.VIDEO_WEBM;
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
|
|
||||||
import com.google.android.exoplayer2.drm.DrmInitData;
|
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.metadata.id3.TextInformationFrame;
|
import com.google.android.exoplayer2.metadata.id3.TextInformationFrame;
|
||||||
|
|
@ -63,11 +65,12 @@ public final class FormatTest {
|
||||||
new TextInformationFrame("id2", "description2", "value2"));
|
new TextInformationFrame("id2", "description2", "value2"));
|
||||||
ColorInfo colorInfo = new ColorInfo(C.COLOR_SPACE_BT709,
|
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});
|
C.COLOR_RANGE_LIMITED, C.COLOR_TRANSFER_SDR, new byte[] {1, 2, 3, 4, 5, 6, 7});
|
||||||
|
Bundle params = new Bundle();
|
||||||
|
params.putInt(Format.KEY_ASPECT_RATIO_TYPE, 100);
|
||||||
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, colorInfo, 6,
|
1024, 2048, 1920, 1080, 24, 90, 2, projectionData, C.STEREO_MODE_TOP_BOTTOM, colorInfo, 6,
|
||||||
44100, C.ENCODING_PCM_24BIT, 1001, 1002, 0, "und", Format.NO_VALUE,
|
44100, C.ENCODING_PCM_24BIT, 1001, 1002, 0, "und", Format.NO_VALUE,
|
||||||
Format.OFFSET_SAMPLE_RELATIVE, INIT_DATA, drmInitData, metadata);
|
Format.OFFSET_SAMPLE_RELATIVE, INIT_DATA, drmInitData, metadata, params);
|
||||||
|
|
||||||
Parcel parcel = Parcel.obtain();
|
Parcel parcel = Parcel.obtain();
|
||||||
formatToParcel.writeToParcel(parcel, 0);
|
formatToParcel.writeToParcel(parcel, 0);
|
||||||
|
|
@ -75,6 +78,8 @@ public final class FormatTest {
|
||||||
|
|
||||||
Format formatFromParcel = Format.CREATOR.createFromParcel(parcel);
|
Format formatFromParcel = Format.CREATOR.createFromParcel(parcel);
|
||||||
assertThat(formatFromParcel).isEqualTo(formatToParcel);
|
assertThat(formatFromParcel).isEqualTo(formatToParcel);
|
||||||
|
int aspectRatio = formatFromParcel.params.getInt(Format.KEY_ASPECT_RATIO_TYPE);
|
||||||
|
assertThat(aspectRatio).isEqualTo(100);
|
||||||
|
|
||||||
parcel.recycle();
|
parcel.recycle();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ public class DefaultTrackNameProvider implements TrackNameProvider {
|
||||||
} else {
|
} else {
|
||||||
trackName = buildLanguageString(format);
|
trackName = buildLanguageString(format);
|
||||||
}
|
}
|
||||||
return trackName.length() == 0 ? resources.getString(R.string.exo_track_unknown) : trackName;
|
return trackName.length() == 0 ? resources.getString(R.string.exo_track_unknown) : trackName + " - " + format.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String buildResolutionString(Format format) {
|
private String buildResolutionString(Format format) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue