use of com.google.android.exoplayer2.extractor.TrueHdSampleRechunker in project ExoPlayer by google.
the class Mp4Extractor method readSample.
/**
* Attempts to extract the next sample in the current mdat atom for the specified track.
*
* <p>Returns {@link #RESULT_SEEK} if the source should be reloaded from the position in {@code
* positionHolder}.
*
* <p>Returns {@link #RESULT_END_OF_INPUT} if no samples are left. Otherwise, returns {@link
* #RESULT_CONTINUE}.
*
* @param input The {@link ExtractorInput} from which to read data.
* @param positionHolder If {@link #RESULT_SEEK} is returned, this holder is updated to hold the
* position of the required data.
* @return One of the {@code RESULT_*} flags in {@link Extractor}.
* @throws IOException If an error occurs reading from the input.
*/
private int readSample(ExtractorInput input, PositionHolder positionHolder) throws IOException {
long inputPosition = input.getPosition();
if (sampleTrackIndex == C.INDEX_UNSET) {
sampleTrackIndex = getTrackIndexOfNextReadSample(inputPosition);
if (sampleTrackIndex == C.INDEX_UNSET) {
return RESULT_END_OF_INPUT;
}
}
Mp4Track track = castNonNull(tracks)[sampleTrackIndex];
TrackOutput trackOutput = track.trackOutput;
int sampleIndex = track.sampleIndex;
long position = track.sampleTable.offsets[sampleIndex];
int sampleSize = track.sampleTable.sizes[sampleIndex];
@Nullable TrueHdSampleRechunker trueHdSampleRechunker = track.trueHdSampleRechunker;
long skipAmount = position - inputPosition + sampleBytesRead;
if (skipAmount < 0 || skipAmount >= RELOAD_MINIMUM_SEEK_DISTANCE) {
positionHolder.position = position;
return RESULT_SEEK;
}
if (track.track.sampleTransformation == Track.TRANSFORMATION_CEA608_CDAT) {
// The sample information is contained in a cdat atom. The header must be discarded for
// committing.
skipAmount += Atom.HEADER_SIZE;
sampleSize -= Atom.HEADER_SIZE;
}
input.skipFully((int) skipAmount);
if (track.track.nalUnitLengthFieldLength != 0) {
// Zero the top three bytes of the array that we'll use to decode nal unit lengths, in case
// they're only 1 or 2 bytes long.
byte[] nalLengthData = nalLength.getData();
nalLengthData[0] = 0;
nalLengthData[1] = 0;
nalLengthData[2] = 0;
int nalUnitLengthFieldLength = track.track.nalUnitLengthFieldLength;
int nalUnitLengthFieldLengthDiff = 4 - track.track.nalUnitLengthFieldLength;
// start codes as we encounter them.
while (sampleBytesWritten < sampleSize) {
if (sampleCurrentNalBytesRemaining == 0) {
// Read the NAL length so that we know where we find the next one.
input.readFully(nalLengthData, nalUnitLengthFieldLengthDiff, nalUnitLengthFieldLength);
sampleBytesRead += nalUnitLengthFieldLength;
nalLength.setPosition(0);
int nalLengthInt = nalLength.readInt();
if (nalLengthInt < 0) {
throw ParserException.createForMalformedContainer("Invalid NAL length", /* cause= */
null);
}
sampleCurrentNalBytesRemaining = nalLengthInt;
// Write a start code for the current NAL unit.
nalStartCode.setPosition(0);
trackOutput.sampleData(nalStartCode, 4);
sampleBytesWritten += 4;
sampleSize += nalUnitLengthFieldLengthDiff;
} else {
// Write the payload of the NAL unit.
int writtenBytes = trackOutput.sampleData(input, sampleCurrentNalBytesRemaining, false);
sampleBytesRead += writtenBytes;
sampleBytesWritten += writtenBytes;
sampleCurrentNalBytesRemaining -= writtenBytes;
}
}
} else {
if (MimeTypes.AUDIO_AC4.equals(track.track.format.sampleMimeType)) {
if (sampleBytesWritten == 0) {
Ac4Util.getAc4SampleHeader(sampleSize, scratch);
trackOutput.sampleData(scratch, Ac4Util.SAMPLE_HEADER_SIZE);
sampleBytesWritten += Ac4Util.SAMPLE_HEADER_SIZE;
}
sampleSize += Ac4Util.SAMPLE_HEADER_SIZE;
} else if (trueHdSampleRechunker != null) {
trueHdSampleRechunker.startSample(input);
}
while (sampleBytesWritten < sampleSize) {
int writtenBytes = trackOutput.sampleData(input, sampleSize - sampleBytesWritten, false);
sampleBytesRead += writtenBytes;
sampleBytesWritten += writtenBytes;
sampleCurrentNalBytesRemaining -= writtenBytes;
}
}
long timeUs = track.sampleTable.timestampsUs[sampleIndex];
@C.BufferFlags int flags = track.sampleTable.flags[sampleIndex];
if (trueHdSampleRechunker != null) {
trueHdSampleRechunker.sampleMetadata(trackOutput, timeUs, flags, sampleSize, /* offset= */
0, /* cryptoData= */
null);
if (sampleIndex + 1 == track.sampleTable.sampleCount) {
trueHdSampleRechunker.outputPendingSampleMetadata(trackOutput, /* cryptoData= */
null);
}
} else {
trackOutput.sampleMetadata(timeUs, flags, sampleSize, /* offset= */
0, /* cryptoData= */
null);
}
track.sampleIndex++;
sampleTrackIndex = C.INDEX_UNSET;
sampleBytesRead = 0;
sampleBytesWritten = 0;
sampleCurrentNalBytesRemaining = 0;
return RESULT_CONTINUE;
}
Aggregations