mirror of
https://github.com/arcodange-org/mediabunny.git
synced 2026-09-27 10:53:50 +02:00
Fix AAC error in Matroska muxer, remove special VideoFrame path for VideoSample due to Chromium bug
This commit is contained in:
@@ -118,25 +118,52 @@ class ProresDecoder extends CustomVideoDecoder {
|
|||||||
this.trimCodedHeightToVisibleHeight(result);
|
this.trimCodedHeightToVisibleHeight(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
const sample = new VideoSample(result.frameData, {
|
const colorSpaceInit = {
|
||||||
format: result.pixelFormat,
|
primaries: result.colorPrimariesString as VideoColorPrimaries | undefined,
|
||||||
codedWidth: result.codedWidth,
|
matrix: result.colorMatrixString as VideoMatrixCoefficients | undefined,
|
||||||
codedHeight: result.codedHeight,
|
transfer: result.colorTransferString as VideoTransferCharacteristics | undefined,
|
||||||
visibleRect: {
|
fullRange: result.colorRangeFull,
|
||||||
left: 0,
|
};
|
||||||
top: 0,
|
|
||||||
width: result.visibleWidth,
|
let sample: VideoSample;
|
||||||
height: result.visibleHeight,
|
if (typeof VideoFrame !== 'undefined') {
|
||||||
},
|
// Create a VideoFrame directly; this avoids the frame data being copied twice
|
||||||
timestamp: packet.timestamp,
|
const frame = new VideoFrame(result.frameData, {
|
||||||
duration: packet.duration,
|
format: result.pixelFormat as VideoPixelFormat,
|
||||||
colorSpace: {
|
codedWidth: result.codedWidth,
|
||||||
primaries: result.colorPrimariesString as VideoColorPrimaries | undefined,
|
codedHeight: result.codedHeight,
|
||||||
matrix: result.colorMatrixString as VideoMatrixCoefficients | undefined,
|
visibleRect: {
|
||||||
transfer: result.colorTransferString as VideoTransferCharacteristics | undefined,
|
x: 0,
|
||||||
fullRange: result.colorRangeFull,
|
y: 0,
|
||||||
},
|
width: result.visibleWidth,
|
||||||
});
|
height: result.visibleHeight,
|
||||||
|
},
|
||||||
|
timestamp: packet.microsecondTimestamp,
|
||||||
|
duration: packet.microsecondDuration,
|
||||||
|
colorSpace: colorSpaceInit,
|
||||||
|
});
|
||||||
|
|
||||||
|
sample = new VideoSample(frame, {
|
||||||
|
timestamp: packet.timestamp,
|
||||||
|
duration: packet.duration,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
sample = new VideoSample(result.frameData, {
|
||||||
|
format: result.pixelFormat,
|
||||||
|
codedWidth: result.codedWidth,
|
||||||
|
codedHeight: result.codedHeight,
|
||||||
|
visibleRect: {
|
||||||
|
left: 0,
|
||||||
|
top: 0,
|
||||||
|
width: result.visibleWidth,
|
||||||
|
height: result.visibleHeight,
|
||||||
|
},
|
||||||
|
timestamp: packet.timestamp,
|
||||||
|
duration: packet.duration,
|
||||||
|
colorSpace: colorSpaceInit,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
this.onSample(sample);
|
this.onSample(sample);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -844,7 +844,7 @@ export class MatroskaMuxer extends Muxer {
|
|||||||
},
|
},
|
||||||
chunkQueue: [],
|
chunkQueue: [],
|
||||||
lastWrittenMsTimestamp: null,
|
lastWrittenMsTimestamp: null,
|
||||||
codecPrivate: meta.decoderConfig.description ?? null,
|
codecPrivate: decoderConfig.description ?? null,
|
||||||
closed: false,
|
closed: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+4
-35
@@ -469,41 +469,10 @@ export class VideoSample implements Disposable {
|
|||||||
this.squarePixelHeight = this.visibleRect.height;
|
this.squarePixelHeight = this.visibleRect.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If VideoFrame is available, route through it directly instead of holding onto the buffer. Going
|
// As an optimization, one could check if VideoFrame is defined and if it is, create a VideoFrame here from
|
||||||
// buffer -> VideoSample -> VideoFrame would copy the data twice (once here, once in toVideoFrame);
|
// the data. Since VideoFrames are typically needed anyway, doing it this way would avoid an additional
|
||||||
// building the VideoFrame now means it's only ever copied once.
|
// copy of the frame data. But due to https://issues.chromium.org/issues/529413114, this is currently
|
||||||
if (typeof VideoFrame !== 'undefined' && !init._doNotCopy) {
|
// not done.
|
||||||
let videoFrame: VideoFrame | null = null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
videoFrame = new VideoFrame(toUint8Array(data), {
|
|
||||||
format: init.format as VideoPixelFormat,
|
|
||||||
codedWidth: init.codedWidth!,
|
|
||||||
codedHeight: init.codedHeight!,
|
|
||||||
layout,
|
|
||||||
colorSpace: colorSpaceInit,
|
|
||||||
visibleRect: {
|
|
||||||
x: this.visibleRect.left,
|
|
||||||
y: this.visibleRect.top,
|
|
||||||
width: this.visibleRect.width,
|
|
||||||
height: this.visibleRect.height,
|
|
||||||
},
|
|
||||||
displayWidth: this.squarePixelWidth,
|
|
||||||
displayHeight: this.squarePixelHeight,
|
|
||||||
timestamp: Math.trunc(init.timestamp! * SECOND_TO_MICROSECOND_FACTOR),
|
|
||||||
// Drag 0 to undefined
|
|
||||||
duration: Math.trunc((init.duration ?? 0) * SECOND_TO_MICROSECOND_FACTOR) || undefined,
|
|
||||||
});
|
|
||||||
} catch {
|
|
||||||
// Ignore the error and move on like it didn't happen. We don't want errors caused by the local
|
|
||||||
// VideoFrame implementation to prevent us from creating the VideoSample. Errors, for example, could
|
|
||||||
// be caused by an unsupported pixel format.
|
|
||||||
}
|
|
||||||
|
|
||||||
if (videoFrame) {
|
|
||||||
return new VideoSample(videoFrame, init);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this._data = init._doNotCopy
|
this._data = init._doNotCopy
|
||||||
? toUint8Array(data)
|
? toUint8Array(data)
|
||||||
|
|||||||
Reference in New Issue
Block a user