Commit 7839955f by aquilescanta Committed by Ian Baker

Separate encryption data into a new TrackOutput method

Allows media parser to populate crypto data.

PiperOrigin-RevId: 307616083
parent 1ab5923f
...@@ -477,13 +477,15 @@ public class SampleQueue implements TrackOutput { ...@@ -477,13 +477,15 @@ public class SampleQueue implements TrackOutput {
} }
@Override @Override
public final int sampleData(DataReader input, int length, boolean allowEndOfInput) public final int sampleData(
DataReader input, int length, boolean allowEndOfInput, @SampleDataPart int sampleDataPart)
throws IOException { throws IOException {
return sampleDataQueue.sampleData(input, length, allowEndOfInput); return sampleDataQueue.sampleData(input, length, allowEndOfInput);
} }
@Override @Override
public final void sampleData(ParsableByteArray buffer, int length) { public final void sampleData(
ParsableByteArray buffer, int length, @SampleDataPart int sampleDataPart) {
sampleDataQueue.sampleData(buffer, length); sampleDataQueue.sampleData(buffer, length);
} }
......
...@@ -203,13 +203,14 @@ public final class ChunkExtractorWrapper implements ExtractorOutput { ...@@ -203,13 +203,14 @@ public final class ChunkExtractorWrapper implements ExtractorOutput {
} }
@Override @Override
public int sampleData(DataReader input, int length, boolean allowEndOfInput) public int sampleData(
DataReader input, int length, boolean allowEndOfInput, @SampleDataPart int sampleDataPart)
throws IOException { throws IOException {
return castNonNull(trackOutput).sampleData(input, length, allowEndOfInput); return castNonNull(trackOutput).sampleData(input, length, allowEndOfInput);
} }
@Override @Override
public void sampleData(ParsableByteArray data, int length) { public void sampleData(ParsableByteArray data, int length, @SampleDataPart int sampleDataPart) {
castNonNull(trackOutput).sampleData(data, length); castNonNull(trackOutput).sampleData(data, length);
} }
......
...@@ -300,13 +300,14 @@ public final class PlayerEmsgHandler implements Handler.Callback { ...@@ -300,13 +300,14 @@ public final class PlayerEmsgHandler implements Handler.Callback {
} }
@Override @Override
public int sampleData(DataReader input, int length, boolean allowEndOfInput) public int sampleData(
DataReader input, int length, boolean allowEndOfInput, @SampleDataPart int sampleDataPart)
throws IOException { throws IOException {
return sampleQueue.sampleData(input, length, allowEndOfInput); return sampleQueue.sampleData(input, length, allowEndOfInput);
} }
@Override @Override
public void sampleData(ParsableByteArray data, int length) { public void sampleData(ParsableByteArray data, int length, @SampleDataPart int sampleDataPart) {
sampleQueue.sampleData(data, length); sampleQueue.sampleData(data, length);
} }
......
...@@ -43,7 +43,9 @@ public final class DummyTrackOutput implements TrackOutput { ...@@ -43,7 +43,9 @@ public final class DummyTrackOutput implements TrackOutput {
} }
@Override @Override
public int sampleData(DataReader input, int length, boolean allowEndOfInput) throws IOException { public int sampleData(
DataReader input, int length, boolean allowEndOfInput, @SampleDataPart int sampleDataPart)
throws IOException {
int bytesToSkipByReading = Math.min(readBuffer.length, length); int bytesToSkipByReading = Math.min(readBuffer.length, length);
int bytesSkipped = input.read(readBuffer, /* offset= */ 0, bytesToSkipByReading); int bytesSkipped = input.read(readBuffer, /* offset= */ 0, bytesToSkipByReading);
if (bytesSkipped == C.RESULT_END_OF_INPUT) { if (bytesSkipped == C.RESULT_END_OF_INPUT) {
...@@ -56,7 +58,7 @@ public final class DummyTrackOutput implements TrackOutput { ...@@ -56,7 +58,7 @@ public final class DummyTrackOutput implements TrackOutput {
} }
@Override @Override
public void sampleData(ParsableByteArray data, int length) { public void sampleData(ParsableByteArray data, int length, @SampleDataPart int sampleDataPart) {
data.skipBytes(length); data.skipBytes(length);
} }
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
*/ */
package com.google.android.exoplayer2.extractor; package com.google.android.exoplayer2.extractor;
import androidx.annotation.IntDef;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Format;
...@@ -22,6 +23,9 @@ import com.google.android.exoplayer2.upstream.DataReader; ...@@ -22,6 +23,9 @@ import com.google.android.exoplayer2.upstream.DataReader;
import com.google.android.exoplayer2.util.ParsableByteArray; import com.google.android.exoplayer2.util.ParsableByteArray;
import java.io.EOFException; import java.io.EOFException;
import java.io.IOException; import java.io.IOException;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Arrays; import java.util.Arrays;
/** /**
...@@ -94,6 +98,41 @@ public interface TrackOutput { ...@@ -94,6 +98,41 @@ public interface TrackOutput {
} }
/** Defines the part of the sample data to which a call to {@link #sampleData} corresponds. */
@Documented
@Retention(RetentionPolicy.SOURCE)
@IntDef({SAMPLE_DATA_PART_MAIN, SAMPLE_DATA_PART_ENCRYPTION, SAMPLE_DATA_PART_SUPPLEMENTAL})
@interface SampleDataPart {}
/** Main media sample data. */
int SAMPLE_DATA_PART_MAIN = 0;
/**
* Sample encryption data.
*
* <p>The format for encryption information is:
*
* <ul>
* <li>(1 byte) {@code encryption_signal_byte}: Most significant bit signals whether the
* encryption data contains subsample encryption data. The remaining bits contain {@code
* initialization_vector_size}.
* <li>({@code initialization_vector_size} bytes) Initialization vector.
* <li>If subsample encryption data is present, as per {@code encryption_signal_byte}, the
* encryption data also contains:
* <ul>
* <li>(2 bytes) {@code subsample_encryption_data_length}.
* <li>({@code subsample_encryption_data_length} bytes) Subsample encryption data
* (repeated {@code subsample_encryption_data_length / 6} times:
* <ul>
* <li>(3 bytes) Size of a clear section in sample.
* <li>(3 bytes) Size of an encryption section in sample.
* </ul>
* </ul>
* </ul>
*/
int SAMPLE_DATA_PART_ENCRYPTION = 1;
/** Sample supplemental data. */
int SAMPLE_DATA_PART_SUPPLEMENTAL = 2;
/** /**
* Called when the {@link Format} of the track has been extracted from the stream. * Called when the {@link Format} of the track has been extracted from the stream.
* *
...@@ -102,6 +141,22 @@ public interface TrackOutput { ...@@ -102,6 +141,22 @@ public interface TrackOutput {
void format(Format format); void format(Format format);
/** /**
* Equivalent to {@link #sampleData(DataReader, int, boolean, int) sampleData(input, length,
* allowEndOfInput, SAMPLE_DATA_PART_MAIN)}.
*/
default int sampleData(DataReader input, int length, boolean allowEndOfInput) throws IOException {
return sampleData(input, length, allowEndOfInput, SAMPLE_DATA_PART_MAIN);
}
/**
* Equivalent to {@link #sampleData(ParsableByteArray, int, int)} sampleData(data, length,
* SAMPLE_DATA_PART_MAIN)}.
*/
default void sampleData(ParsableByteArray data, int length) {
sampleData(data, length, SAMPLE_DATA_PART_MAIN);
}
/**
* Called to write sample data to the output. * Called to write sample data to the output.
* *
* @param input A {@link DataReader} from which to read the sample data. * @param input A {@link DataReader} from which to read the sample data.
...@@ -109,18 +164,22 @@ public interface TrackOutput { ...@@ -109,18 +164,22 @@ public interface TrackOutput {
* @param allowEndOfInput True if encountering the end of the input having read no data is * @param allowEndOfInput True if encountering the end of the input having read no data is
* allowed, and should result in {@link C#RESULT_END_OF_INPUT} being returned. False if it * allowed, and should result in {@link C#RESULT_END_OF_INPUT} being returned. False if it
* should be considered an error, causing an {@link EOFException} to be thrown. * should be considered an error, causing an {@link EOFException} to be thrown.
* @param sampleDataPart The part of the sample data to which this call corresponds.
* @return The number of bytes appended. * @return The number of bytes appended.
* @throws IOException If an error occurred reading from the input. * @throws IOException If an error occurred reading from the input.
*/ */
int sampleData(DataReader input, int length, boolean allowEndOfInput) throws IOException; int sampleData(
DataReader input, int length, boolean allowEndOfInput, @SampleDataPart int sampleDataPart)
throws IOException;
/** /**
* Called to write sample data to the output. * Called to write sample data to the output.
* *
* @param data A {@link ParsableByteArray} from which to read the sample data. * @param data A {@link ParsableByteArray} from which to read the sample data.
* @param length The number of bytes to read, starting from {@code data.getPosition()}. * @param length The number of bytes to read, starting from {@code data.getPosition()}.
* @param sampleDataPart The part of the sample data to which this call corresponds.
*/ */
void sampleData(ParsableByteArray data, int length); void sampleData(ParsableByteArray data, int length, @SampleDataPart int sampleDataPart);
/** /**
* Called when metadata associated with a sample has been extracted from the stream. * Called when metadata associated with a sample has been extracted from the stream.
......
...@@ -1281,7 +1281,8 @@ public class MatroskaExtractor implements Extractor { ...@@ -1281,7 +1281,8 @@ public class MatroskaExtractor implements Extractor {
} else { } else {
// Append supplemental data. // Append supplemental data.
int blockAdditionalSize = blockAdditionalData.limit(); int blockAdditionalSize = blockAdditionalData.limit();
track.output.sampleData(blockAdditionalData, blockAdditionalSize); track.output.sampleData(
blockAdditionalData, blockAdditionalSize, TrackOutput.SAMPLE_DATA_PART_SUPPLEMENTAL);
size += blockAdditionalSize; size += blockAdditionalSize;
} }
} }
...@@ -1350,11 +1351,14 @@ public class MatroskaExtractor implements Extractor { ...@@ -1350,11 +1351,14 @@ public class MatroskaExtractor implements Extractor {
// Write the signal byte, containing the IV size and the subsample encryption flag. // Write the signal byte, containing the IV size and the subsample encryption flag.
scratch.data[0] = (byte) (ENCRYPTION_IV_SIZE | (hasSubsampleEncryption ? 0x80 : 0x00)); scratch.data[0] = (byte) (ENCRYPTION_IV_SIZE | (hasSubsampleEncryption ? 0x80 : 0x00));
scratch.setPosition(0); scratch.setPosition(0);
output.sampleData(scratch, 1); output.sampleData(scratch, 1, TrackOutput.SAMPLE_DATA_PART_ENCRYPTION);
sampleBytesWritten++; sampleBytesWritten++;
// Write the IV. // Write the IV.
encryptionInitializationVector.setPosition(0); encryptionInitializationVector.setPosition(0);
output.sampleData(encryptionInitializationVector, ENCRYPTION_IV_SIZE); output.sampleData(
encryptionInitializationVector,
ENCRYPTION_IV_SIZE,
TrackOutput.SAMPLE_DATA_PART_ENCRYPTION);
sampleBytesWritten += ENCRYPTION_IV_SIZE; sampleBytesWritten += ENCRYPTION_IV_SIZE;
} }
if (hasSubsampleEncryption) { if (hasSubsampleEncryption) {
...@@ -1402,7 +1406,10 @@ public class MatroskaExtractor implements Extractor { ...@@ -1402,7 +1406,10 @@ public class MatroskaExtractor implements Extractor {
encryptionSubsampleDataBuffer.putInt(0); encryptionSubsampleDataBuffer.putInt(0);
} }
encryptionSubsampleData.reset(encryptionSubsampleDataBuffer.array(), subsampleDataSize); encryptionSubsampleData.reset(encryptionSubsampleDataBuffer.array(), subsampleDataSize);
output.sampleData(encryptionSubsampleData, subsampleDataSize); output.sampleData(
encryptionSubsampleData,
subsampleDataSize,
TrackOutput.SAMPLE_DATA_PART_ENCRYPTION);
sampleBytesWritten += subsampleDataSize; sampleBytesWritten += subsampleDataSize;
} }
} }
...@@ -1421,7 +1428,7 @@ public class MatroskaExtractor implements Extractor { ...@@ -1421,7 +1428,7 @@ public class MatroskaExtractor implements Extractor {
scratch.data[1] = (byte) ((size >> 16) & 0xFF); scratch.data[1] = (byte) ((size >> 16) & 0xFF);
scratch.data[2] = (byte) ((size >> 8) & 0xFF); scratch.data[2] = (byte) ((size >> 8) & 0xFF);
scratch.data[3] = (byte) (size & 0xFF); scratch.data[3] = (byte) (size & 0xFF);
output.sampleData(scratch, 4); output.sampleData(scratch, 4, TrackOutput.SAMPLE_DATA_PART_SUPPLEMENTAL);
sampleBytesWritten += 4; sampleBytesWritten += 4;
} }
......
...@@ -1611,9 +1611,10 @@ public class FragmentedMp4Extractor implements Extractor { ...@@ -1611,9 +1611,10 @@ public class FragmentedMp4Extractor implements Extractor {
encryptionSignalByte.data[0] = encryptionSignalByte.data[0] =
(byte) (vectorSize | (writeSubsampleEncryptionData ? 0x80 : 0)); (byte) (vectorSize | (writeSubsampleEncryptionData ? 0x80 : 0));
encryptionSignalByte.setPosition(0); encryptionSignalByte.setPosition(0);
output.sampleData(encryptionSignalByte, 1); output.sampleData(encryptionSignalByte, 1, TrackOutput.SAMPLE_DATA_PART_ENCRYPTION);
// Write the vector. // Write the vector.
output.sampleData(initializationVectorData, vectorSize); output.sampleData(
initializationVectorData, vectorSize, TrackOutput.SAMPLE_DATA_PART_ENCRYPTION);
if (!writeSubsampleEncryptionData) { if (!writeSubsampleEncryptionData) {
return 1 + vectorSize; return 1 + vectorSize;
...@@ -1635,7 +1636,10 @@ public class FragmentedMp4Extractor implements Extractor { ...@@ -1635,7 +1636,10 @@ public class FragmentedMp4Extractor implements Extractor {
scratch.data[5] = (byte) ((sampleSize >> 16) & 0xFF); scratch.data[5] = (byte) ((sampleSize >> 16) & 0xFF);
scratch.data[6] = (byte) ((sampleSize >> 8) & 0xFF); scratch.data[6] = (byte) ((sampleSize >> 8) & 0xFF);
scratch.data[7] = (byte) (sampleSize & 0xFF); scratch.data[7] = (byte) (sampleSize & 0xFF);
output.sampleData(scratch, SINGLE_SUBSAMPLE_ENCRYPTION_DATA_LENGTH); output.sampleData(
scratch,
SINGLE_SUBSAMPLE_ENCRYPTION_DATA_LENGTH,
TrackOutput.SAMPLE_DATA_PART_ENCRYPTION);
return 1 + vectorSize + SINGLE_SUBSAMPLE_ENCRYPTION_DATA_LENGTH; return 1 + vectorSize + SINGLE_SUBSAMPLE_ENCRYPTION_DATA_LENGTH;
} }
...@@ -1658,7 +1662,8 @@ public class FragmentedMp4Extractor implements Extractor { ...@@ -1658,7 +1662,8 @@ public class FragmentedMp4Extractor implements Extractor {
subsampleEncryptionData = scratch; subsampleEncryptionData = scratch;
} }
output.sampleData(subsampleEncryptionData, subsampleDataLength); output.sampleData(
subsampleEncryptionData, subsampleDataLength, TrackOutput.SAMPLE_DATA_PART_ENCRYPTION);
return 1 + vectorSize + subsampleDataLength; return 1 + vectorSize + subsampleDataLength;
} }
......
...@@ -1521,7 +1521,8 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; ...@@ -1521,7 +1521,8 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
} }
@Override @Override
public int sampleData(DataReader input, int length, boolean allowEndOfInput) public int sampleData(
DataReader input, int length, boolean allowEndOfInput, @SampleDataPart int sampleDataPart)
throws IOException { throws IOException {
ensureBufferCapacity(bufferPosition + length); ensureBufferCapacity(bufferPosition + length);
int numBytesRead = input.read(buffer, bufferPosition, length); int numBytesRead = input.read(buffer, bufferPosition, length);
...@@ -1537,7 +1538,8 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; ...@@ -1537,7 +1538,8 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
} }
@Override @Override
public void sampleData(ParsableByteArray buffer, int length) { public void sampleData(
ParsableByteArray buffer, int length, @SampleDataPart int sampleDataPart) {
ensureBufferCapacity(bufferPosition + length); ensureBufferCapacity(bufferPosition + length);
buffer.readBytes(this.buffer, bufferPosition, length); buffer.readBytes(this.buffer, bufferPosition, length);
bufferPosition += length; bufferPosition += length;
......
...@@ -75,7 +75,9 @@ public final class FakeTrackOutput implements TrackOutput, Dumper.Dumpable { ...@@ -75,7 +75,9 @@ public final class FakeTrackOutput implements TrackOutput, Dumper.Dumpable {
} }
@Override @Override
public int sampleData(DataReader input, int length, boolean allowEndOfInput) throws IOException { public int sampleData(
DataReader input, int length, boolean allowEndOfInput, @SampleDataPart int sampleDataPart)
throws IOException {
byte[] newData = new byte[length]; byte[] newData = new byte[length];
int bytesAppended = input.read(newData, 0, length); int bytesAppended = input.read(newData, 0, length);
if (bytesAppended == C.RESULT_END_OF_INPUT) { if (bytesAppended == C.RESULT_END_OF_INPUT) {
...@@ -90,7 +92,7 @@ public final class FakeTrackOutput implements TrackOutput, Dumper.Dumpable { ...@@ -90,7 +92,7 @@ public final class FakeTrackOutput implements TrackOutput, Dumper.Dumpable {
} }
@Override @Override
public void sampleData(ParsableByteArray data, int length) { public void sampleData(ParsableByteArray data, int length, @SampleDataPart int sampleDataPart) {
byte[] newData = new byte[length]; byte[] newData = new byte[length];
data.readBytes(newData, 0, length); data.readBytes(newData, 0, length);
sampleData = TestUtil.joinByteArrays(sampleData, newData); sampleData = TestUtil.joinByteArrays(sampleData, newData);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment