package com.usky.cdi.service.sip.ps;

import lombok.extern.slf4j.Slf4j;
import org.bytedeco.javacpp.Loader;
import org.bytedeco.ffmpeg.ffmpeg;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeUnit;

/**
 * 将 Annex-B H264 通过 FFmpeg 标准 remux 为 MPEG-PS（与 demo 解码器兼容）。
 */
@Slf4j
public final class FfmpegPsRemuxer implements AutoCloseable {

    private final Process process;
    private final OutputStream stdin;
    private final InputStream stdout;

    public FfmpegPsRemuxer(double frameRate) throws IOException {
        int fps = frameRate > 1 && frameRate < 121 ? (int) Math.round(frameRate) : 25;
        ProcessBuilder pb = new ProcessBuilder(
                resolveFfmpegCommand(),
                "-hide_banner",
                "-loglevel", "error",
                "-fflags", "+nobuffer+flush_packets",
                "-f", "h264",
                "-framerate", String.valueOf(fps),
                "-probesize", "32768",
                "-analyzeduration", "0",
                "-i", "pipe:0",
                "-an",
                "-c:v", "copy",
                "-f", "mpeg",
                "-muxrate", "10000000",
                "-muxdelay", "0",
                "-muxpreload", "0",
                "-flush_packets", "1",
                "-"
        );
        process = pb.start();
        stdin = process.getOutputStream();
        stdout = process.getInputStream();
        startStderrDrainer(process.getErrorStream());
        log.info("FFmpeg PS remux 已启动: framerate={}", fps);
    }

    public void writeAccessUnit(byte[] annexBFrame) throws IOException {
        if (annexBFrame == null || annexBFrame.length == 0) {
            return;
        }
        stdin.write(annexBFrame);
        stdin.flush();
    }

    public InputStream psOutput() {
        return stdout;
    }

    public boolean isAlive() {
        return process.isAlive();
    }

    @Override
    public void close() {
        try {
            stdin.flush();
            stdin.close();
        } catch (IOException ignored) {
        }
        try {
            process.waitFor(3, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        if (process.isAlive()) {
            process.destroyForcibly();
        }
    }

    private static void startStderrDrainer(InputStream stderr) {
        Thread t = new Thread(() -> {
            try (BufferedReader reader = new BufferedReader(
                    new InputStreamReader(stderr, StandardCharsets.UTF_8))) {
                String line;
                while ((line = reader.readLine()) != null) {
                    log.warn("FFmpeg PS remux: {}", line);
                }
            } catch (IOException ignored) {
            }
        }, "ffmpeg-ps-stderr");
        t.setDaemon(true);
        t.start();
    }

    private static String resolveFfmpegCommand() {
        try {
            return Loader.load(ffmpeg.class);
        } catch (Throwable e) {
            log.warn("未找到 JavaCV 内置 ffmpeg，尝试系统 PATH: {}", e.getMessage());
            return "ffmpeg";
        }
    }
}
