mirror of
https://github.com/samsonjs/media.git
synced 2026-04-10 12:05:47 +00:00
Some cleanup to TS H264/H265 readers.
This commit is contained in:
parent
d96fe37c05
commit
b1e4283058
2 changed files with 87 additions and 87 deletions
|
|
@ -102,56 +102,60 @@ import java.util.List;
|
|||
output.sampleData(data, data.bytesLeft());
|
||||
|
||||
// Scan the appended data, processing NAL units as they are encountered
|
||||
while (offset < limit) {
|
||||
int nextNalUnitOffset = NalUnitUtil.findNalUnit(dataArray, offset, limit, prefixFlags);
|
||||
if (nextNalUnitOffset < limit) {
|
||||
// We've seen the start of a NAL unit.
|
||||
while (true) {
|
||||
int nalUnitOffset = NalUnitUtil.findNalUnit(dataArray, offset, limit, prefixFlags);
|
||||
|
||||
// This is the length to the start of the unit. It may be negative if the NAL unit
|
||||
// actually started in previously consumed data.
|
||||
int lengthToNalUnit = nextNalUnitOffset - offset;
|
||||
if (lengthToNalUnit > 0) {
|
||||
feedNalUnitTargetBuffersData(dataArray, offset, nextNalUnitOffset);
|
||||
}
|
||||
|
||||
int nalUnitType = NalUnitUtil.getNalUnitType(dataArray, nextNalUnitOffset);
|
||||
int bytesWrittenPastNalUnit = limit - nextNalUnitOffset;
|
||||
switch (nalUnitType) {
|
||||
case NAL_UNIT_TYPE_IDR:
|
||||
isKeyframe = true;
|
||||
break;
|
||||
case NAL_UNIT_TYPE_AUD:
|
||||
if (foundFirstSample) {
|
||||
if (ifrParserBuffer != null && ifrParserBuffer.isCompleted()) {
|
||||
int sliceType = ifrParserBuffer.getSliceType();
|
||||
isKeyframe |= (sliceType == FRAME_TYPE_I || sliceType == FRAME_TYPE_ALL_I);
|
||||
ifrParserBuffer.reset();
|
||||
}
|
||||
if (isKeyframe && !hasOutputFormat && sps.isCompleted() && pps.isCompleted()) {
|
||||
parseMediaFormat(sps, pps);
|
||||
}
|
||||
int flags = isKeyframe ? C.SAMPLE_FLAG_SYNC : 0;
|
||||
int size = (int) (totalBytesWritten - samplePosition) - bytesWrittenPastNalUnit;
|
||||
output.sampleMetadata(sampleTimeUs, flags, size, bytesWrittenPastNalUnit, null);
|
||||
}
|
||||
foundFirstSample = true;
|
||||
samplePosition = totalBytesWritten - bytesWrittenPastNalUnit;
|
||||
sampleTimeUs = pesTimeUs;
|
||||
isKeyframe = false;
|
||||
break;
|
||||
}
|
||||
|
||||
// If the length to the start of the unit is negative then we wrote too many bytes to the
|
||||
// NAL buffers. Discard the excess bytes when notifying that the unit has ended.
|
||||
feedNalUnitTargetEnd(pesTimeUs, lengthToNalUnit < 0 ? -lengthToNalUnit : 0);
|
||||
// Notify the start of the next NAL unit.
|
||||
feedNalUnitTargetBuffersStart(nalUnitType);
|
||||
// Continue scanning the data.
|
||||
offset = nextNalUnitOffset + 3;
|
||||
} else {
|
||||
if (nalUnitOffset == limit) {
|
||||
// We've scanned to the end of the data without finding the start of another NAL unit.
|
||||
feedNalUnitTargetBuffersData(dataArray, offset, limit);
|
||||
offset = limit;
|
||||
return;
|
||||
}
|
||||
|
||||
// We've seen the start of a NAL unit of the following type.
|
||||
int nalUnitType = NalUnitUtil.getNalUnitType(dataArray, nalUnitOffset);
|
||||
|
||||
// This is the number of bytes from the current offset to the start of the next NAL unit.
|
||||
// It may be negative if the NAL unit started in the previously consumed data.
|
||||
int lengthToNalUnit = nalUnitOffset - offset;
|
||||
if (lengthToNalUnit > 0) {
|
||||
feedNalUnitTargetBuffersData(dataArray, offset, nalUnitOffset);
|
||||
}
|
||||
|
||||
switch (nalUnitType) {
|
||||
case NAL_UNIT_TYPE_IDR:
|
||||
isKeyframe = true;
|
||||
break;
|
||||
case NAL_UNIT_TYPE_AUD:
|
||||
int bytesWrittenPastNalUnit = limit - nalUnitOffset;
|
||||
if (foundFirstSample) {
|
||||
if (ifrParserBuffer != null && ifrParserBuffer.isCompleted()) {
|
||||
int sliceType = ifrParserBuffer.getSliceType();
|
||||
isKeyframe |= (sliceType == FRAME_TYPE_I || sliceType == FRAME_TYPE_ALL_I);
|
||||
ifrParserBuffer.reset();
|
||||
}
|
||||
if (isKeyframe && !hasOutputFormat && sps.isCompleted() && pps.isCompleted()) {
|
||||
output.format(parseMediaFormat(sps, pps));
|
||||
hasOutputFormat = true;
|
||||
}
|
||||
int flags = isKeyframe ? C.SAMPLE_FLAG_SYNC : 0;
|
||||
int size = (int) (totalBytesWritten - samplePosition) - bytesWrittenPastNalUnit;
|
||||
output.sampleMetadata(sampleTimeUs, flags, size, bytesWrittenPastNalUnit, null);
|
||||
}
|
||||
foundFirstSample = true;
|
||||
samplePosition = totalBytesWritten - bytesWrittenPastNalUnit;
|
||||
sampleTimeUs = pesTimeUs;
|
||||
isKeyframe = false;
|
||||
break;
|
||||
}
|
||||
|
||||
// Indicate the end of the previous NAL unit. If the length to the start of the next unit
|
||||
// is negative then we wrote too many bytes to the NAL buffers. Discard the excess bytes
|
||||
// when notifying that the unit has ended.
|
||||
feedNalUnitTargetEnd(pesTimeUs, lengthToNalUnit < 0 ? -lengthToNalUnit : 0);
|
||||
// Indicate the start of the next NAL unit.
|
||||
feedNalUnitTargetBuffersStart(nalUnitType);
|
||||
// Continue scanning the data.
|
||||
offset = nalUnitOffset + 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -194,14 +198,10 @@ import java.util.List;
|
|||
}
|
||||
}
|
||||
|
||||
private void parseMediaFormat(NalUnitTargetBuffer sps, NalUnitTargetBuffer pps) {
|
||||
byte[] spsData = new byte[sps.nalLength];
|
||||
byte[] ppsData = new byte[pps.nalLength];
|
||||
System.arraycopy(sps.nalData, 0, spsData, 0, sps.nalLength);
|
||||
System.arraycopy(pps.nalData, 0, ppsData, 0, pps.nalLength);
|
||||
private static MediaFormat parseMediaFormat(NalUnitTargetBuffer sps, NalUnitTargetBuffer pps) {
|
||||
List<byte[]> initializationData = new ArrayList<>();
|
||||
initializationData.add(spsData);
|
||||
initializationData.add(ppsData);
|
||||
initializationData.add(Arrays.copyOf(sps.nalData, sps.nalLength));
|
||||
initializationData.add(Arrays.copyOf(pps.nalData, pps.nalLength));
|
||||
|
||||
// Unescape and parse the SPS unit.
|
||||
NalUnitUtil.unescapeStream(sps.nalData, sps.nalLength);
|
||||
|
|
@ -209,11 +209,9 @@ import java.util.List;
|
|||
bitArray.skipBits(32); // NAL header
|
||||
SpsData parsedSpsData = CodecSpecificDataUtil.parseSpsNalUnit(bitArray);
|
||||
|
||||
// Construct and output the format.
|
||||
output.format(MediaFormat.createVideoFormat(null, MimeTypes.VIDEO_H264, MediaFormat.NO_VALUE,
|
||||
return MediaFormat.createVideoFormat(null, MimeTypes.VIDEO_H264, MediaFormat.NO_VALUE,
|
||||
MediaFormat.NO_VALUE, C.UNKNOWN_TIME_US, parsedSpsData.width, parsedSpsData.height,
|
||||
initializationData, MediaFormat.NO_VALUE, parsedSpsData.pixelWidthAspectRatio));
|
||||
hasOutputFormat = true;
|
||||
initializationData, MediaFormat.NO_VALUE, parsedSpsData.pixelWidthAspectRatio);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -101,32 +101,34 @@ import java.util.Collections;
|
|||
// Scan the appended data, processing NAL units as they are encountered
|
||||
while (offset < limit) {
|
||||
int nalUnitOffset = NalUnitUtil.findNalUnit(dataArray, offset, limit, prefixFlags);
|
||||
if (nalUnitOffset < limit) {
|
||||
// We've seen the start of a NAL unit.
|
||||
|
||||
// This is the length to the start of the unit. It may be negative if the NAL unit
|
||||
// actually started in previously consumed data.
|
||||
int lengthToNalUnit = nalUnitOffset - offset;
|
||||
if (lengthToNalUnit > 0) {
|
||||
nalUnitData(dataArray, offset, nalUnitOffset);
|
||||
}
|
||||
int bytesWrittenPastPosition = limit - nalUnitOffset;
|
||||
long absolutePosition = totalBytesWritten - bytesWrittenPastPosition;
|
||||
// Indicate the end of the previous NAL unit. If the length to the start of the next unit
|
||||
// is negative then we wrote too many bytes to the NAL buffers. Discard the excess bytes
|
||||
// when notifying that the unit has ended.
|
||||
nalUnitEnd(absolutePosition, bytesWrittenPastPosition,
|
||||
lengthToNalUnit < 0 ? -lengthToNalUnit : 0, pesTimeUs);
|
||||
|
||||
// Indicate the start of the next NAL unit.
|
||||
int nalUnitType = NalUnitUtil.getH265NalUnitType(dataArray, nalUnitOffset);
|
||||
startNalUnit(absolutePosition, bytesWrittenPastPosition, nalUnitType, pesTimeUs);
|
||||
// Continue scanning the data.
|
||||
offset = nalUnitOffset + 3;
|
||||
} else {
|
||||
if (nalUnitOffset == limit) {
|
||||
// We've scanned to the end of the data without finding the start of another NAL unit.
|
||||
nalUnitData(dataArray, offset, limit);
|
||||
offset = limit;
|
||||
return;
|
||||
}
|
||||
|
||||
// We've seen the start of a NAL unit of the following type.
|
||||
int nalUnitType = NalUnitUtil.getH265NalUnitType(dataArray, nalUnitOffset);
|
||||
|
||||
// This is the number of bytes from the current offset to the start of the next NAL unit.
|
||||
// It may be negative if the NAL unit started in the previously consumed data.
|
||||
int lengthToNalUnit = nalUnitOffset - offset;
|
||||
if (lengthToNalUnit > 0) {
|
||||
nalUnitData(dataArray, offset, nalUnitOffset);
|
||||
}
|
||||
|
||||
int bytesWrittenPastPosition = limit - nalUnitOffset;
|
||||
long absolutePosition = totalBytesWritten - bytesWrittenPastPosition;
|
||||
// Indicate the end of the previous NAL unit. If the length to the start of the next unit
|
||||
// is negative then we wrote too many bytes to the NAL buffers. Discard the excess bytes
|
||||
// when notifying that the unit has ended.
|
||||
nalUnitEnd(absolutePosition, bytesWrittenPastPosition,
|
||||
lengthToNalUnit < 0 ? -lengthToNalUnit : 0, pesTimeUs);
|
||||
// Indicate the start of the next NAL unit.
|
||||
startNalUnit(absolutePosition, bytesWrittenPastPosition, nalUnitType, pesTimeUs);
|
||||
// Continue scanning the data.
|
||||
offset = nalUnitOffset + 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -167,7 +169,8 @@ import java.util.Collections;
|
|||
sps.endNalUnit(discardPadding);
|
||||
pps.endNalUnit(discardPadding);
|
||||
if (vps.isCompleted() && sps.isCompleted() && pps.isCompleted()) {
|
||||
parseMediaFormat(vps, sps, pps);
|
||||
output.format(parseMediaFormat(vps, sps, pps));
|
||||
hasOutputFormat = true;
|
||||
}
|
||||
}
|
||||
if (prefixSei.endNalUnit(discardPadding)) {
|
||||
|
|
@ -188,7 +191,7 @@ import java.util.Collections;
|
|||
}
|
||||
}
|
||||
|
||||
private void parseMediaFormat(NalUnitTargetBuffer vps, NalUnitTargetBuffer sps,
|
||||
private static MediaFormat parseMediaFormat(NalUnitTargetBuffer vps, NalUnitTargetBuffer sps,
|
||||
NalUnitTargetBuffer pps) {
|
||||
// Build codec-specific data.
|
||||
byte[] csd = new byte[vps.nalLength + sps.nalLength + pps.nalLength];
|
||||
|
|
@ -294,14 +297,13 @@ import java.util.Collections;
|
|||
}
|
||||
}
|
||||
|
||||
output.format(MediaFormat.createVideoFormat(null, MimeTypes.VIDEO_H265, MediaFormat.NO_VALUE,
|
||||
return MediaFormat.createVideoFormat(null, MimeTypes.VIDEO_H265, MediaFormat.NO_VALUE,
|
||||
MediaFormat.NO_VALUE, C.UNKNOWN_TIME_US, picWidthInLumaSamples, picHeightInLumaSamples,
|
||||
Collections.singletonList(csd), MediaFormat.NO_VALUE, pixelWidthHeightRatio));
|
||||
hasOutputFormat = true;
|
||||
Collections.singletonList(csd), MediaFormat.NO_VALUE, pixelWidthHeightRatio);
|
||||
}
|
||||
|
||||
/** Skips scaling_list_data(). See H.265/HEVC (2014) 7.3.4. */
|
||||
private void skipScalingList(ParsableBitArray bitArray) {
|
||||
private static void skipScalingList(ParsableBitArray bitArray) {
|
||||
for (int sizeId = 0; sizeId < 4; sizeId++) {
|
||||
for (int matrixId = 0; matrixId < 6; matrixId += sizeId == 3 ? 3 : 1) {
|
||||
if (!bitArray.readBit()) { // scaling_list_pred_mode_flag[sizeId][matrixId]
|
||||
|
|
|
|||
Loading…
Reference in a new issue