| 11 | |
| 12 | // Define the class that extends the Transform stream |
| 13 | class MjpegParser extends Transform { |
| 14 | private buffer: Buffer | null = null; |
| 15 | private reading: boolean = false; |
| 16 | private contentLength: number | null = null; |
| 17 | private bytesWritten: number = 0; |
| 18 | |
| 19 | constructor(options?: TransformOptions) { |
| 20 | super(options); |
| 21 | } |
| 22 | |
| 23 | private _initFrame(len: number, chunk: Buffer, start: number, end: number) { |
| 24 | this.contentLength = len; |
| 25 | this.buffer = Buffer.alloc(len); |
| 26 | this.bytesWritten = 0; |
| 27 | |
| 28 | const hasStart = typeof start !== "undefined" && start > -1; |
| 29 | const hasEnd = typeof end !== "undefined" && end > -1 && end > start; |
| 30 | |
| 31 | if (hasStart) { |
| 32 | let bufEnd = chunk.length; |
| 33 | |
| 34 | if (hasEnd) { |
| 35 | bufEnd = end + eoi.length; |
| 36 | } |
| 37 | |
| 38 | chunk.copy(this.buffer, 0, start, bufEnd); |
| 39 | this.bytesWritten = chunk.length - start; |
| 40 | |
| 41 | // If we have the EOI bytes, send the frame |
| 42 | if (hasEnd) { |
| 43 | this._sendFrame(); |
| 44 | } else { |
| 45 | this.reading = true; |
| 46 | } |
| 47 | } |
| 48 | } |
| 49 | |
| 50 | private _readFrame(chunk: Buffer, start: number, end: number) { |
| 51 | const bufStart = start > -1 && start < end ? start : 0; |
| 52 | const bufEnd = end > -1 ? end + eoi.length : chunk.length; |
| 53 | |
| 54 | chunk.copy(this.buffer!, this.bytesWritten, bufStart, bufEnd); |
| 55 | this.bytesWritten += bufEnd - bufStart; |
| 56 | |
| 57 | if (end > -1 || this.bytesWritten === this.contentLength) { |
| 58 | this._sendFrame(); |
| 59 | } else { |
| 60 | this.reading = true; |
| 61 | } |
| 62 | } |
| 63 | |
| 64 | /** |
| 65 | * Handle sending the frame to the next stream and resetting state |
| 66 | */ |
| 67 | private async _sendFrame() { |
| 68 | this.reading = false; |
| 69 | if (this.buffer) { |
| 70 | sharp(this.buffer) |
nothing calls this directly
no outgoing calls
no test coverage detected