summaryrefslogtreecommitdiffstats
path: root/mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/metadata/scte35/SpliceInfoDecoder.java
diff options
context:
space:
mode:
Diffstat (limited to 'mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/metadata/scte35/SpliceInfoDecoder.java')
-rw-r--r--mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/metadata/scte35/SpliceInfoDecoder.java102
1 files changed, 102 insertions, 0 deletions
diff --git a/mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/metadata/scte35/SpliceInfoDecoder.java b/mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/metadata/scte35/SpliceInfoDecoder.java
new file mode 100644
index 0000000000..a90bddb078
--- /dev/null
+++ b/mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/metadata/scte35/SpliceInfoDecoder.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2016 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 org.mozilla.thirdparty.com.google.android.exoplayer2.metadata.scte35;
+
+import androidx.annotation.Nullable;
+import org.mozilla.thirdparty.com.google.android.exoplayer2.metadata.Metadata;
+import org.mozilla.thirdparty.com.google.android.exoplayer2.metadata.MetadataDecoder;
+import org.mozilla.thirdparty.com.google.android.exoplayer2.metadata.MetadataInputBuffer;
+import org.mozilla.thirdparty.com.google.android.exoplayer2.util.Assertions;
+import org.mozilla.thirdparty.com.google.android.exoplayer2.util.ParsableBitArray;
+import org.mozilla.thirdparty.com.google.android.exoplayer2.util.ParsableByteArray;
+import org.mozilla.thirdparty.com.google.android.exoplayer2.util.TimestampAdjuster;
+import java.nio.ByteBuffer;
+import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
+
+/**
+ * Decodes splice info sections and produces splice commands.
+ */
+public final class SpliceInfoDecoder implements MetadataDecoder {
+
+ private static final int TYPE_SPLICE_NULL = 0x00;
+ private static final int TYPE_SPLICE_SCHEDULE = 0x04;
+ private static final int TYPE_SPLICE_INSERT = 0x05;
+ private static final int TYPE_TIME_SIGNAL = 0x06;
+ private static final int TYPE_PRIVATE_COMMAND = 0xFF;
+
+ private final ParsableByteArray sectionData;
+ private final ParsableBitArray sectionHeader;
+
+ @MonotonicNonNull private TimestampAdjuster timestampAdjuster;
+
+ public SpliceInfoDecoder() {
+ sectionData = new ParsableByteArray();
+ sectionHeader = new ParsableBitArray();
+ }
+
+ @SuppressWarnings("ByteBufferBackingArray")
+ @Override
+ public Metadata decode(MetadataInputBuffer inputBuffer) {
+ ByteBuffer buffer = Assertions.checkNotNull(inputBuffer.data);
+
+ // Internal timestamps adjustment.
+ if (timestampAdjuster == null
+ || inputBuffer.subsampleOffsetUs != timestampAdjuster.getTimestampOffsetUs()) {
+ timestampAdjuster = new TimestampAdjuster(inputBuffer.timeUs);
+ timestampAdjuster.adjustSampleTimestamp(inputBuffer.timeUs - inputBuffer.subsampleOffsetUs);
+ }
+
+ byte[] data = buffer.array();
+ int size = buffer.limit();
+ sectionData.reset(data, size);
+ sectionHeader.reset(data, size);
+ // table_id(8), section_syntax_indicator(1), private_indicator(1), reserved(2),
+ // section_length(12), protocol_version(8), encrypted_packet(1), encryption_algorithm(6).
+ sectionHeader.skipBits(39);
+ long ptsAdjustment = sectionHeader.readBits(1);
+ ptsAdjustment = (ptsAdjustment << 32) | sectionHeader.readBits(32);
+ // cw_index(8), tier(12).
+ sectionHeader.skipBits(20);
+ int spliceCommandLength = sectionHeader.readBits(12);
+ int spliceCommandType = sectionHeader.readBits(8);
+ @Nullable SpliceCommand command = null;
+ // Go to the start of the command by skipping all fields up to command_type.
+ sectionData.skipBytes(14);
+ switch (spliceCommandType) {
+ case TYPE_SPLICE_NULL:
+ command = new SpliceNullCommand();
+ break;
+ case TYPE_SPLICE_SCHEDULE:
+ command = SpliceScheduleCommand.parseFromSection(sectionData);
+ break;
+ case TYPE_SPLICE_INSERT:
+ command = SpliceInsertCommand.parseFromSection(sectionData, ptsAdjustment,
+ timestampAdjuster);
+ break;
+ case TYPE_TIME_SIGNAL:
+ command = TimeSignalCommand.parseFromSection(sectionData, ptsAdjustment, timestampAdjuster);
+ break;
+ case TYPE_PRIVATE_COMMAND:
+ command = PrivateCommand.parseFromSection(sectionData, spliceCommandLength, ptsAdjustment);
+ break;
+ default:
+ // Do nothing.
+ break;
+ }
+ return command == null ? new Metadata() : new Metadata(command);
+ }
+
+}