From 6592a6474e99d0710b0b03454bde750221a73d64 Mon Sep 17 00:00:00 2001 From: aquilescanta Date: Fri, 15 Sep 2017 03:44:41 -0700 Subject: [PATCH] Improve documentation for SCTE35-related metadata Also expose break_durations in microseconds instead of 90kHz. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=168816992 --- .../metadata/scte35/PrivateCommand.java | 9 +++ .../metadata/scte35/SpliceInsertCommand.java | 65 ++++++++++++++++--- .../scte35/SpliceScheduleCommand.java | 62 +++++++++++++++--- .../metadata/scte35/TimeSignalCommand.java | 6 ++ .../scte35/SpliceInfoDecoderTest.java | 4 +- 5 files changed, 127 insertions(+), 19 deletions(-) diff --git a/library/core/src/main/java/com/google/android/exoplayer2/metadata/scte35/PrivateCommand.java b/library/core/src/main/java/com/google/android/exoplayer2/metadata/scte35/PrivateCommand.java index beb4cb9b88..4334fa99cb 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/metadata/scte35/PrivateCommand.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/metadata/scte35/PrivateCommand.java @@ -24,8 +24,17 @@ import com.google.android.exoplayer2.util.ParsableByteArray; */ public final class PrivateCommand extends SpliceCommand { + /** + * The {@code pts_adjustment} as defined in SCTE35, Section 9.2. + */ public final long ptsAdjustment; + /** + * The identifier as defined in SCTE35, Section 9.3.6. + */ public final long identifier; + /** + * The private bytes as defined in SCTE35, Section 9.3.6. + */ public final byte[] commandBytes; private PrivateCommand(long identifier, byte[] commandBytes, long ptsAdjustment) { diff --git a/library/core/src/main/java/com/google/android/exoplayer2/metadata/scte35/SpliceInsertCommand.java b/library/core/src/main/java/com/google/android/exoplayer2/metadata/scte35/SpliceInsertCommand.java index 7ce8b47e2a..6f56d3b68c 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/metadata/scte35/SpliceInsertCommand.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/metadata/scte35/SpliceInsertCommand.java @@ -29,24 +29,72 @@ import java.util.List; */ public final class SpliceInsertCommand extends SpliceCommand { + /** + * The splice event id. + */ public final long spliceEventId; + /** + * True if the event with id {@link #spliceEventId} has been canceled. + */ public final boolean spliceEventCancelIndicator; + /** + * If true, the splice event is an opportunity to exit from the network feed. If false, indicates + * an opportunity to return to the network feed. + */ public final boolean outOfNetworkIndicator; + /** + * Whether the splice mode is program splice mode, whereby all PIDs/components are to be spliced. + * If false, splicing is done per PID/component. + */ public final boolean programSpliceFlag; + /** + * Whether splicing should be done at the nearest opportunity. If false, splicing should be done + * at the moment indicated by {@link #programSplicePlaybackPositionUs} or + * {@link ComponentSplice#componentSplicePlaybackPositionUs}, depending on + * {@link #programSpliceFlag}. + */ public final boolean spliceImmediateFlag; + /** + * If {@link #programSpliceFlag} is true, the PTS at which the program splice should occur. + * {@link C#TIME_UNSET} otherwise. + */ public final long programSplicePts; + /** + * Equivalent to {@link #programSplicePts} but in the playback timebase. + */ public final long programSplicePlaybackPositionUs; + /** + * If {@link #programSpliceFlag} is false, a non-empty list containing the + * {@link ComponentSplice}s. Otherwise, an empty list. + */ public final List componentSpliceList; + /** + * If {@link #breakDurationUs} is not {@link C#TIME_UNSET}, defines whether + * {@link #breakDurationUs} should be used to know when to return to the network feed. If + * {@link #breakDurationUs} is {@link C#TIME_UNSET}, the value is undefined. + */ public final boolean autoReturn; - public final long breakDuration; + /** + * The duration of the splice in microseconds, or {@link C#TIME_UNSET} if no duration is present. + */ + public final long breakDurationUs; + /** + * The unique program id as defined in SCTE35, Section 9.3.3. + */ public final int uniqueProgramId; + /** + * Holds the value of {@code avail_num} as defined in SCTE35, Section 9.3.3. + */ public final int availNum; + /** + * Holds the value of {@code avails_expected} as defined in SCTE35, Section 9.3.3. + */ public final int availsExpected; private SpliceInsertCommand(long spliceEventId, boolean spliceEventCancelIndicator, boolean outOfNetworkIndicator, boolean programSpliceFlag, boolean spliceImmediateFlag, long programSplicePts, long programSplicePlaybackPositionUs, - List componentSpliceList, boolean autoReturn, long breakDuration, + List componentSpliceList, boolean autoReturn, long breakDurationUs, int uniqueProgramId, int availNum, int availsExpected) { this.spliceEventId = spliceEventId; this.spliceEventCancelIndicator = spliceEventCancelIndicator; @@ -57,7 +105,7 @@ public final class SpliceInsertCommand extends SpliceCommand { this.programSplicePlaybackPositionUs = programSplicePlaybackPositionUs; this.componentSpliceList = Collections.unmodifiableList(componentSpliceList); this.autoReturn = autoReturn; - this.breakDuration = breakDuration; + this.breakDurationUs = breakDurationUs; this.uniqueProgramId = uniqueProgramId; this.availNum = availNum; this.availsExpected = availsExpected; @@ -78,7 +126,7 @@ public final class SpliceInsertCommand extends SpliceCommand { } this.componentSpliceList = Collections.unmodifiableList(componentSpliceList); autoReturn = in.readByte() == 1; - breakDuration = in.readLong(); + breakDurationUs = in.readLong(); uniqueProgramId = in.readInt(); availNum = in.readInt(); availsExpected = in.readInt(); @@ -98,7 +146,7 @@ public final class SpliceInsertCommand extends SpliceCommand { int availNum = 0; int availsExpected = 0; boolean autoReturn = false; - long duration = C.TIME_UNSET; + long breakDurationUs = C.TIME_UNSET; if (!spliceEventCancelIndicator) { int headerByte = sectionData.readUnsignedByte(); outOfNetworkIndicator = (headerByte & 0x80) != 0; @@ -124,7 +172,8 @@ public final class SpliceInsertCommand extends SpliceCommand { if (durationFlag) { long firstByte = sectionData.readUnsignedByte(); autoReturn = (firstByte & 0x80) != 0; - duration = ((firstByte & 0x01) << 32) | sectionData.readUnsignedInt(); + long breakDuration90khz = ((firstByte & 0x01) << 32) | sectionData.readUnsignedInt(); + breakDurationUs = breakDuration90khz * 1000 / 90; } uniqueProgramId = sectionData.readUnsignedShort(); availNum = sectionData.readUnsignedByte(); @@ -133,7 +182,7 @@ public final class SpliceInsertCommand extends SpliceCommand { return new SpliceInsertCommand(spliceEventId, spliceEventCancelIndicator, outOfNetworkIndicator, programSpliceFlag, spliceImmediateFlag, programSplicePts, timestampAdjuster.adjustTsTimestamp(programSplicePts), componentSplices, autoReturn, - duration, uniqueProgramId, availNum, availsExpected); + breakDurationUs, uniqueProgramId, availNum, availsExpected); } /** @@ -181,7 +230,7 @@ public final class SpliceInsertCommand extends SpliceCommand { componentSpliceList.get(i).writeToParcel(dest); } dest.writeByte((byte) (autoReturn ? 1 : 0)); - dest.writeLong(breakDuration); + dest.writeLong(breakDurationUs); dest.writeInt(uniqueProgramId); dest.writeInt(availNum); dest.writeInt(availsExpected); diff --git a/library/core/src/main/java/com/google/android/exoplayer2/metadata/scte35/SpliceScheduleCommand.java b/library/core/src/main/java/com/google/android/exoplayer2/metadata/scte35/SpliceScheduleCommand.java index 9b391cea6c..8696909c97 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/metadata/scte35/SpliceScheduleCommand.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/metadata/scte35/SpliceScheduleCommand.java @@ -33,22 +33,62 @@ public final class SpliceScheduleCommand extends SpliceCommand { */ public static final class Event { + /** + * The splice event id. + */ public final long spliceEventId; + /** + * True if the event with id {@link #spliceEventId} has been canceled. + */ public final boolean spliceEventCancelIndicator; + /** + * If true, the splice event is an opportunity to exit from the network feed. If false, + * indicates an opportunity to return to the network feed. + */ public final boolean outOfNetworkIndicator; + /** + * Whether the splice mode is program splice mode, whereby all PIDs/components are to be + * spliced. If false, splicing is done per PID/component. + */ public final boolean programSpliceFlag; + /** + * Represents the time of the signaled splice event as the number of seconds since 00 hours UTC, + * January 6th, 1980, with the count of intervening leap seconds included. + */ public final long utcSpliceTime; + /** + * If {@link #programSpliceFlag} is false, a non-empty list containing the + * {@link ComponentSplice}s. Otherwise, an empty list. + */ public final List componentSpliceList; + /** + * If {@link #breakDurationUs} is not {@link C#TIME_UNSET}, defines whether + * {@link #breakDurationUs} should be used to know when to return to the network feed. If + * {@link #breakDurationUs} is {@link C#TIME_UNSET}, the value is undefined. + */ public final boolean autoReturn; - public final long breakDuration; + /** + * The duration of the splice in microseconds, or {@link C#TIME_UNSET} if no duration is + * present. + */ + public final long breakDurationUs; + /** + * The unique program id as defined in SCTE35, Section 9.3.2. + */ public final int uniqueProgramId; + /** + * Holds the value of {@code avail_num} as defined in SCTE35, Section 9.3.2. + */ public final int availNum; + /** + * Holds the value of {@code avails_expected} as defined in SCTE35, Section 9.3.2. + */ public final int availsExpected; private Event(long spliceEventId, boolean spliceEventCancelIndicator, boolean outOfNetworkIndicator, boolean programSpliceFlag, List componentSpliceList, long utcSpliceTime, boolean autoReturn, - long breakDuration, int uniqueProgramId, int availNum, int availsExpected) { + long breakDurationUs, int uniqueProgramId, int availNum, int availsExpected) { this.spliceEventId = spliceEventId; this.spliceEventCancelIndicator = spliceEventCancelIndicator; this.outOfNetworkIndicator = outOfNetworkIndicator; @@ -56,7 +96,7 @@ public final class SpliceScheduleCommand extends SpliceCommand { this.componentSpliceList = Collections.unmodifiableList(componentSpliceList); this.utcSpliceTime = utcSpliceTime; this.autoReturn = autoReturn; - this.breakDuration = breakDuration; + this.breakDurationUs = breakDurationUs; this.uniqueProgramId = uniqueProgramId; this.availNum = availNum; this.availsExpected = availsExpected; @@ -75,7 +115,7 @@ public final class SpliceScheduleCommand extends SpliceCommand { this.componentSpliceList = Collections.unmodifiableList(componentSpliceList); this.utcSpliceTime = in.readLong(); this.autoReturn = in.readByte() == 1; - this.breakDuration = in.readLong(); + this.breakDurationUs = in.readLong(); this.uniqueProgramId = in.readInt(); this.availNum = in.readInt(); this.availsExpected = in.readInt(); @@ -93,7 +133,7 @@ public final class SpliceScheduleCommand extends SpliceCommand { int availNum = 0; int availsExpected = 0; boolean autoReturn = false; - long duration = C.TIME_UNSET; + long breakDurationUs = C.TIME_UNSET; if (!spliceEventCancelIndicator) { int headerByte = sectionData.readUnsignedByte(); outOfNetworkIndicator = (headerByte & 0x80) != 0; @@ -114,15 +154,16 @@ public final class SpliceScheduleCommand extends SpliceCommand { if (durationFlag) { long firstByte = sectionData.readUnsignedByte(); autoReturn = (firstByte & 0x80) != 0; - duration = ((firstByte & 0x01) << 32) | sectionData.readUnsignedInt(); + long breakDuration90khz = ((firstByte & 0x01) << 32) | sectionData.readUnsignedInt(); + breakDurationUs = breakDuration90khz * 1000 / 90; } uniqueProgramId = sectionData.readUnsignedShort(); availNum = sectionData.readUnsignedByte(); availsExpected = sectionData.readUnsignedByte(); } return new Event(spliceEventId, spliceEventCancelIndicator, outOfNetworkIndicator, - programSpliceFlag, componentSplices, utcSpliceTime, autoReturn, duration, uniqueProgramId, - availNum, availsExpected); + programSpliceFlag, componentSplices, utcSpliceTime, autoReturn, breakDurationUs, + uniqueProgramId, availNum, availsExpected); } private void writeToParcel(Parcel dest) { @@ -137,7 +178,7 @@ public final class SpliceScheduleCommand extends SpliceCommand { } dest.writeLong(utcSpliceTime); dest.writeByte((byte) (autoReturn ? 1 : 0)); - dest.writeLong(breakDuration); + dest.writeLong(breakDurationUs); dest.writeInt(uniqueProgramId); dest.writeInt(availNum); dest.writeInt(availsExpected); @@ -173,6 +214,9 @@ public final class SpliceScheduleCommand extends SpliceCommand { } + /** + * The list of scheduled events. + */ public final List events; private SpliceScheduleCommand(List events) { diff --git a/library/core/src/main/java/com/google/android/exoplayer2/metadata/scte35/TimeSignalCommand.java b/library/core/src/main/java/com/google/android/exoplayer2/metadata/scte35/TimeSignalCommand.java index f756b72d6d..e233a276ed 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/metadata/scte35/TimeSignalCommand.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/metadata/scte35/TimeSignalCommand.java @@ -25,7 +25,13 @@ import com.google.android.exoplayer2.util.TimestampAdjuster; */ public final class TimeSignalCommand extends SpliceCommand { + /** + * A PTS value, as defined in SCTE35, Section 9.3.4. + */ public final long ptsTime; + /** + * Equivalent to {@link #ptsTime} but in the playback timebase. + */ public final long playbackPositionUs; private TimeSignalCommand(long ptsTime, long playbackPositionUs) { diff --git a/library/core/src/test/java/com/google/android/exoplayer2/metadata/scte35/SpliceInfoDecoderTest.java b/library/core/src/test/java/com/google/android/exoplayer2/metadata/scte35/SpliceInfoDecoderTest.java index 15cb9b23c5..8cd90c7a64 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/metadata/scte35/SpliceInfoDecoderTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/metadata/scte35/SpliceInfoDecoderTest.java @@ -109,7 +109,7 @@ public final class SpliceInfoDecoderTest { assertThat(command.programSpliceFlag).isTrue(); assertThat(command.spliceImmediateFlag).isFalse(); assertThat(command.programSplicePlaybackPositionUs).isEqualTo(3000000); - assertThat(command.breakDuration).isEqualTo(TIME_UNSET); + assertThat(command.breakDurationUs).isEqualTo(TIME_UNSET); assertThat(command.uniqueProgramId).isEqualTo(16); assertThat(command.availNum).isEqualTo(1); assertThat(command.availsExpected).isEqualTo(2); @@ -155,7 +155,7 @@ public final class SpliceInfoDecoderTest { assertThat(command.programSpliceFlag).isFalse(); assertThat(command.spliceImmediateFlag).isFalse(); assertThat(command.programSplicePlaybackPositionUs).isEqualTo(TIME_UNSET); - assertThat(command.breakDuration).isEqualTo(TIME_UNSET); + assertThat(command.breakDurationUs).isEqualTo(TIME_UNSET); List componentSplices = command.componentSpliceList; assertThat(componentSplices).hasSize(2); assertThat(componentSplices.get(0).componentTag).isEqualTo(16);