Merge 5f71939e0d into fc5b83c08f
This commit is contained in:
commit
97a93a9828
|
|
@ -196,9 +196,9 @@ export class H264Context {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parser.profileIdc !== null) {
|
if (parser.profileIdc !== null) {
|
||||||
self._profileIdc = parser.profileIdc;
|
this._profileIdc = parser.profileIdc;
|
||||||
self._constraintSet = parser.constraintSet;
|
this._constraintSet = parser.constraintSet;
|
||||||
self._levelIdc = parser.levelIdc;
|
this._levelIdc = parser.levelIdc;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this._decoder === null || this._decoder.state !== 'configured') {
|
if (this._decoder === null || this._decoder.state !== 'configured') {
|
||||||
|
|
@ -206,12 +206,12 @@ export class H264Context {
|
||||||
Log.Warn("Missing key frame. Can't decode until one arrives");
|
Log.Warn("Missing key frame. Can't decode until one arrives");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (self._profileIdc === null) {
|
if (this._profileIdc === null) {
|
||||||
Log.Warn('Cannot config decoder. Have not received SPS and PPS yet.');
|
Log.Warn('Cannot config decoder. Have not received SPS and PPS yet.');
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
this._configureDecoder(self._profileIdc, self._constraintSet,
|
this._configureDecoder(this._profileIdc, this._constraintSet,
|
||||||
self._levelIdc);
|
this._levelIdc);
|
||||||
}
|
}
|
||||||
|
|
||||||
result = this._preparePendingFrame(timestamp);
|
result = this._preparePendingFrame(timestamp);
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ export default class Display {
|
||||||
|
|
||||||
this._renderQ = []; // queue drawing actions for in-order rendering
|
this._renderQ = []; // queue drawing actions for in-order rendering
|
||||||
this._flushPromise = null;
|
this._flushPromise = null;
|
||||||
|
this._pendingFrames = []; // video frames awaiting decoder output
|
||||||
|
|
||||||
// the full frame buffer (logical canvas) size
|
// the full frame buffer (logical canvas) size
|
||||||
this._fbWidth = 0;
|
this._fbWidth = 0;
|
||||||
|
|
@ -479,6 +480,22 @@ export default class Display {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_drawVideoFrame(pendingFrame, rect) {
|
||||||
|
let frame = pendingFrame.frame;
|
||||||
|
if (!frame) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (frame.codedWidth < rect.width || frame.codedHeight < rect.height) {
|
||||||
|
Log.Warn("Decoded video frame does not cover its full rectangle area. Expecting at least " +
|
||||||
|
rect.width + "x" + rect.height + " but got " +
|
||||||
|
frame.codedWidth + "x" + frame.codedHeight);
|
||||||
|
}
|
||||||
|
this.drawImage(frame,
|
||||||
|
0, 0, rect.width, rect.height,
|
||||||
|
rect.x, rect.y, rect.width, rect.height);
|
||||||
|
frame.close();
|
||||||
|
}
|
||||||
|
|
||||||
_renderQPush(action) {
|
_renderQPush(action) {
|
||||||
this._renderQ.push(action);
|
this._renderQ.push(action);
|
||||||
if (this._renderQ.length === 1) {
|
if (this._renderQ.length === 1) {
|
||||||
|
|
@ -501,7 +518,21 @@ export default class Display {
|
||||||
const a = this._renderQ[0];
|
const a = this._renderQ[0];
|
||||||
switch (a.type) {
|
switch (a.type) {
|
||||||
case 'flip':
|
case 'flip':
|
||||||
|
if (this._pendingFrames.length > 0) {
|
||||||
|
// Wait for all pending video frames to be
|
||||||
|
// decoded before flipping, so they are
|
||||||
|
// visible on screen.
|
||||||
|
let display = this;
|
||||||
|
let frames = this._pendingFrames;
|
||||||
|
this._pendingFrames = [];
|
||||||
|
Promise.all(frames.map(f => f.promise)).then(() => {
|
||||||
|
display.flip(true);
|
||||||
|
display._scanRenderQ();
|
||||||
|
});
|
||||||
|
ready = false;
|
||||||
|
} else {
|
||||||
this.flip(true);
|
this.flip(true);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 'copy':
|
case 'copy':
|
||||||
this.copyImage(a.oldX, a.oldY, a.x, a.y, a.width, a.height, true);
|
this.copyImage(a.oldX, a.oldY, a.x, a.y, a.width, a.height, true);
|
||||||
|
|
@ -533,32 +564,20 @@ export default class Display {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'frame':
|
case 'frame':
|
||||||
if (a.frame.ready) {
|
if (!a.frame.ready) {
|
||||||
// The encoded frame may be larger than the rect due to
|
// Don't block the queue — the video decoder
|
||||||
// limitations of the encoder, so we need to crop the
|
// pipeline needs continued input to produce
|
||||||
// frame.
|
// output. Register a callback to draw later,
|
||||||
let frame = a.frame.frame;
|
// and let the queue keep feeding the decoder.
|
||||||
if (frame.codedWidth < a.width || frame.codedHeight < a.height) {
|
|
||||||
Log.Warn("Decoded video frame does not cover its full rectangle area. Expecting at least " +
|
|
||||||
a.width + "x" + a.height + " but got " +
|
|
||||||
frame.codedWidth + "x" + frame.codedHeight);
|
|
||||||
}
|
|
||||||
const sx = 0;
|
|
||||||
const sy = 0;
|
|
||||||
const sw = a.width;
|
|
||||||
const sh = a.height;
|
|
||||||
const dx = a.x;
|
|
||||||
const dy = a.y;
|
|
||||||
const dw = sw;
|
|
||||||
const dh = sh;
|
|
||||||
this.drawImage(frame, sx, sy, sw, sh, dx, dy, dw, dh);
|
|
||||||
frame.close();
|
|
||||||
} else {
|
|
||||||
let display = this;
|
let display = this;
|
||||||
a.frame.promise.then(() => {
|
let pendingFrame = a.frame;
|
||||||
display._scanRenderQ();
|
let rect = { x: a.x, y: a.y, width: a.width, height: a.height };
|
||||||
|
pendingFrame.promise.then(() => {
|
||||||
|
display._drawVideoFrame(pendingFrame, rect);
|
||||||
});
|
});
|
||||||
ready = false;
|
this._pendingFrames.push(pendingFrame);
|
||||||
|
} else {
|
||||||
|
this._drawVideoFrame(a.frame, a);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue