/**
 * Copyright Microsoft Corporation. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import { spawnSync } from 'child_process';
import fs from 'fs';
import { PNG } from 'playwright-core/lib/utilsBundle';
import { registry } from '../../packages/playwright-core/lib/coreBundle';
export class VideoPlayer {
    fileName;
    output;
    duration;
    frames;
    videoWidth;
    videoHeight;
    cache = new Map();
    constructor(fileName) {
        this.fileName = fileName;
        const ffmpeg = registry.registry.findExecutable('ffmpeg').executablePathOrDie('javascript');
        // Force output frame rate to 25 fps as otherwise it would produce one image per timebase unit
        // which is 1 / (25 * 1000).
        this.output = spawnSync(ffmpeg, ['-i', this.fileName, '-r', '25', `${this.fileName}-%04d.png`]).stderr.toString();
        const lines = this.output.split('\n');
        let framesLine = lines.find(l => l.startsWith('frame='));
        if (!framesLine)
            throw new Error(`No frame data in the output:\n${this.output}`);
        framesLine = framesLine.substring(framesLine.lastIndexOf('frame='));
        const framesMatch = framesLine.match(/frame=\s+(\d+)/);
        const streamLine = lines.find(l => l.trim().startsWith('Stream #0:0'));
        const resolutionMatch = streamLine.match(/, (\d+)x(\d+),/);
        const durationMatch = lines.find(l => l.trim().startsWith('Duration')).match(/Duration: (\d+):(\d\d):(\d\d.\d\d)/);
        this.duration = (((parseInt(durationMatch[1], 10) * 60) + parseInt(durationMatch[2], 10)) * 60 + parseFloat(durationMatch[3])) * 1000;
        this.frames = parseInt(framesMatch[1], 10);
        this.videoWidth = parseInt(resolutionMatch[1], 10);
        this.videoHeight = parseInt(resolutionMatch[2], 10);
    }
    findFrame(framePredicate, offset) {
        for (let f = 1; f <= this.frames; ++f) {
            const frame = this.frame(f, offset);
            if (framePredicate(frame.data))
                return frame;
        }
    }
    seekLastFrame(offset) {
        return this.frame(this.frames, offset);
    }
    frame(frame, offset = { x: 10, y: 10 }) {
        if (!this.cache.has(frame)) {
            const gap = '0'.repeat(4 - String(frame).length);
            const buffer = fs.readFileSync(`${this.fileName}-${gap}${frame}.png`);
            this.cache.set(frame, PNG.sync.read(buffer));
        }
        const decoded = this.cache.get(frame);
        const dst = new PNG({ width: 10, height: 10 });
        PNG.bitblt(decoded, dst, offset.x, offset.y, 10, 10, 0, 0);
        return dst;
    }
}
//# sourceMappingURL=videoPlayer.js.map