mirror of
https://github.com/androidx/media.git
synced 2025-05-15 19:49:50 +08:00
Fix H262 segmentation.
Prepend sequence headers to the next frame, instead of appending them to the previous frame. Tested decoders like FFMPEG and Google's Android/MPEG2 expects to read the sequence headers before the first frame they apply to. When sequence headers are appended to the previous frame, these are ignored and this leads to incorrect decoding.
This commit is contained in:
parent
4a6a5b527f
commit
893c7f34ba
@ -51,7 +51,7 @@ public final class H262Reader implements ElementaryStreamReader {
|
||||
// State that should be reset on seek.
|
||||
private final boolean[] prefixFlags;
|
||||
private final CsdBuffer csdBuffer;
|
||||
private boolean foundFirstFrameInGroup;
|
||||
private boolean foundPicture;
|
||||
private long totalBytesWritten;
|
||||
|
||||
// Per packet state that gets reset at the start of each packet.
|
||||
@ -60,8 +60,8 @@ public final class H262Reader implements ElementaryStreamReader {
|
||||
|
||||
// Per sample state that gets reset at the start of each frame.
|
||||
private boolean isKeyframe;
|
||||
private long framePosition;
|
||||
private long frameTimeUs;
|
||||
private long samplePosition;
|
||||
private long sampleTimeUs;
|
||||
|
||||
public H262Reader() {
|
||||
prefixFlags = new boolean[4];
|
||||
@ -73,7 +73,8 @@ public final class H262Reader implements ElementaryStreamReader {
|
||||
NalUnitUtil.clearPrefixFlags(prefixFlags);
|
||||
csdBuffer.reset();
|
||||
pesPtsUsAvailable = false;
|
||||
foundFirstFrameInGroup = false;
|
||||
foundPicture = false;
|
||||
samplePosition = C.POSITION_UNSET;
|
||||
totalBytesWritten = 0;
|
||||
}
|
||||
|
||||
@ -136,25 +137,28 @@ public final class H262Reader implements ElementaryStreamReader {
|
||||
}
|
||||
}
|
||||
|
||||
if (hasOutputFormat && (startCodeValue == START_GROUP || startCodeValue == START_PICTURE)) {
|
||||
if (hasOutputFormat && (startCodeValue == START_PICTURE || startCodeValue == START_SEQUENCE_HEADER)) {
|
||||
int bytesWrittenPastStartCode = limit - startCodeOffset;
|
||||
if (foundFirstFrameInGroup) {
|
||||
boolean resetSample = (samplePosition == C.POSITION_UNSET);
|
||||
if (foundPicture) {
|
||||
@C.BufferFlags int flags = isKeyframe ? C.BUFFER_FLAG_KEY_FRAME : 0;
|
||||
int size = (int) (totalBytesWritten - framePosition) - bytesWrittenPastStartCode;
|
||||
output.sampleMetadata(frameTimeUs, flags, size, bytesWrittenPastStartCode, null);
|
||||
int size = (int) (totalBytesWritten - samplePosition) - bytesWrittenPastStartCode;
|
||||
output.sampleMetadata(sampleTimeUs, flags, size, bytesWrittenPastStartCode, null);
|
||||
isKeyframe = false;
|
||||
resetSample = true;
|
||||
}
|
||||
if (startCodeValue == START_GROUP) {
|
||||
foundFirstFrameInGroup = false;
|
||||
isKeyframe = true;
|
||||
} else /* startCodeValue == START_PICTURE */ {
|
||||
frameTimeUs = pesPtsUsAvailable ? pesTimeUs : (frameTimeUs + frameDurationUs);
|
||||
framePosition = totalBytesWritten - bytesWrittenPastStartCode;
|
||||
foundPicture = (startCodeValue == START_PICTURE);
|
||||
if (resetSample) {
|
||||
samplePosition = totalBytesWritten - bytesWrittenPastStartCode;
|
||||
sampleTimeUs = (pesPtsUsAvailable ? pesTimeUs : sampleTimeUs + frameDurationUs);
|
||||
pesPtsUsAvailable = false;
|
||||
foundFirstFrameInGroup = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasOutputFormat && startCodeValue == START_GROUP) {
|
||||
isKeyframe = true;
|
||||
}
|
||||
|
||||
offset = startCodeOffset;
|
||||
searchOffset = offset + 3;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user