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

import org.bytedeco.ffmpeg.avcodec.AVCodecParameters;
import org.bytedeco.javacv.FFmpegFrameGrabber;

import java.util.Arrays;

/**
 * 从 RTSP/FLV extradata (AVCDecoderConfigurationRecord) 提取 SPS/PPS。
 */
public final class H264ExtradataUtils {

    private H264ExtradataUtils() {
    }

    public static void seedParameterSets(FFmpegFrameGrabber grabber, H264AccessUnitBuilder builder) {
        if (grabber == null || builder == null) {
            return;
        }
        try {
            if (grabber.getFormatContext() == null || grabber.getVideoStream() < 0) {
                return;
            }
            AVCodecParameters codecpar = grabber.getFormatContext()
                    .streams(grabber.getVideoStream()).codecpar();
            if (codecpar == null || codecpar.extradata_size() <= 0 || codecpar.extradata() == null) {
                return;
            }
            byte[] extradata = new byte[codecpar.extradata_size()];
            codecpar.extradata().get(extradata);
            parseAvccExtradata(extradata, builder);
        } catch (Exception ignored) {
        }
    }

    private static void parseAvccExtradata(byte[] avcc, H264AccessUnitBuilder builder) {
        if (avcc.length < 8 || avcc[0] != 0x01) {
            return;
        }
        int offset = 5;
        int numSps = avcc[offset] & 0x1F;
        offset++;
        for (int i = 0; i < numSps && offset + 2 <= avcc.length; i++) {
            int len = ((avcc[offset] & 0xFF) << 8) | (avcc[offset + 1] & 0xFF);
            offset += 2;
            if (len > 0 && offset + len <= avcc.length) {
                builder.setSps(Arrays.copyOfRange(avcc, offset, offset + len));
                offset += len;
            }
        }
        if (offset >= avcc.length) {
            return;
        }
        int numPps = avcc[offset] & 0xFF;
        offset++;
        for (int i = 0; i < numPps && offset + 2 <= avcc.length; i++) {
            int len = ((avcc[offset] & 0xFF) << 8) | (avcc[offset + 1] & 0xFF);
            offset += 2;
            if (len > 0 && offset + len <= avcc.length) {
                builder.setPps(Arrays.copyOfRange(avcc, offset, offset + len));
                offset += len;
            }
        }
    }
}
