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

import com.usky.cdi.service.sip.rtp.AnnexBParser;
import com.usky.cdi.service.sip.rtp.H264RtpPacketizer;
import lombok.extern.slf4j.Slf4j;
import org.bytedeco.ffmpeg.avcodec.AVPacket;
import org.bytedeco.javacv.FFmpegFrameGrabber;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.List;

/**
 * 从 RTSP 拉取 H264 码流并封装为 RTP 发送到目标地址
 */
@Slf4j
public class RtspH264RtpSender {

    private static final int PAYLOAD_TYPE = 96;
    private static final long SSRC = 0x12345678L;
    private static final int TIMESTAMP_INCREMENT = 3000;

    private RtspH264RtpSender() {
    }

    public static long stream(String rtspUrl, String rtpHost, int rtpPort, int durationSeconds,
                              String rtspTransport) throws Exception {
        InetAddress address = InetAddress.getByName(rtpHost);
        FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(rtspUrl);
        grabber.setFormat("rtsp");
        grabber.setOption("rtsp_transport", rtspTransport != null ? rtspTransport : "tcp");
        grabber.setOption("stimeout", "5000000");
        grabber.setOption("max_delay", "500000");
        grabber.setOption("fflags", "nobuffer");
        grabber.setOption("flags", "low_delay");

        long packetCount = 0;
        int sequence = 0;
        long timestamp = 0;
        long endTime = System.currentTimeMillis() + durationSeconds * 1000L;

        try (DatagramSocket socket = new DatagramSocket()) {
            grabber.start();
            int videoStream = grabber.getVideoStream();
            log.info("RTSP 已连接: {}, videoStream={}", maskUrl(rtspUrl), videoStream);

            while (System.currentTimeMillis() < endTime) {
                AVPacket pkt = grabber.grabPacket();
                if (pkt == null || pkt.size() <= 0) {
                    Thread.sleep(5);
                    continue;
                }
                if (pkt.stream_index() != videoStream) {
                    continue;
                }
                byte[] data = new byte[pkt.size()];
                pkt.data().get(data, 0, pkt.size());
                List<byte[]> nals = AnnexBParser.extractNals(data);
                for (byte[] nal : nals) {
                    List<byte[]> rtpPackets = H264RtpPacketizer.packetize(
                            nal, PAYLOAD_TYPE, sequence, timestamp, SSRC);
                    for (byte[] rtp : rtpPackets) {
                        DatagramPacket dg = new DatagramPacket(rtp, rtp.length, address, rtpPort);
                        socket.send(dg);
                        packetCount++;
                        sequence++;
                    }
                }
                timestamp += TIMESTAMP_INCREMENT;
            }
        } finally {
            try {
                grabber.stop();
                grabber.release();
            } catch (Exception e) {
                log.debug("关闭 RTSP: {}", e.getMessage());
            }
        }
        log.info("RTSP 推流结束: target={}:{}, rtpPackets={}", rtpHost, rtpPort, packetCount);
        return packetCount;
    }

    private static String maskUrl(String rtspUrl) {
        if (rtspUrl == null) {
            return "";
        }
        return rtspUrl.replaceAll("://([^:]+):([^@]+)@", "://***:***@");
    }
}
