Java 解析问题H.264序列参数集数据

Java 解析问题H.264序列参数集数据,java,parsing,h.264,Java,Parsing,H.264,我需要解析原始H.264数据中的图像大小。以下测试代码适用于案例I testet,但现在如果“Z0IAIOKQCgDLYC3AQEBpB4kRUA==”失败。结果应该是1280x800,但它给出了640x1616: public static void main(String[] args) { decode(StringUtils.fromBase64("Z0IAKeKQCgDLYC3AQEBpB4kRUA==")); decode(StringUtils.fromBase64

我需要解析原始H.264数据中的图像大小。以下测试代码适用于案例I testet,但现在如果“Z0IAIOKQCgDLYC3AQEBpB4kRUA==”失败。结果应该是1280x800,但它给出了640x1616:

public static void main(String[] args) {
    decode(StringUtils.fromBase64("Z0IAKeKQCgDLYC3AQEBpB4kRUA=="));
    decode(StringUtils.fromBase64("Z0IAIOKQCgDLYC3AQEBpB4kRUA=="));
    decode(StringUtils.fromBase64("Z0IAHuNQFAe2AtwEBAaQeJEV"));
}

static int pos;
static byte[] data;

private static void decode(byte[] data) {
    try {
        System.out.println();
        System.out.println(StringUtils.toHex(data));
        System.out.println(StringUtils.toBin(data, 0, data.length, true));
        System.out.println();
        pos = 0;
        T.data = data;
        int profile_idc = getU(8);
        int constraint_set0_flag = getU(1);
        int constraint_set1_flag = getU(1);
        int constraint_set2_flag = getU(1);
        int constraint_set3_flag = getU(1);
        int reserved_zero_4bits = getU(4);
        int level_idc = getU(8);
        int seq_parameter_set_id = uev();
        int log2_max_frame_num_minus4 = uev();
        int pict_order_cnt_type = uev();
        System.out.println("pict_order_cnt_type=" + pict_order_cnt_type);
        if (pict_order_cnt_type == 0) {
            uev();
        } else if (pict_order_cnt_type == 1) {
            getU(1);
            sev();
            sev();
            int n = uev();
            System.out.println("n*sev, n=" + n);
            for (int i = 0; i < n; i++)
                sev();
        }
        int num_ref_frames = uev();
        getU(1);
        int pic_width = (uev() + 1) * 16;
        int pic_height = (uev() + 1) * 16;
        int frame_mbs_only_flag = getU(1);
        System.out.println(pic_width + " x " + pic_height);
    } catch (Exception e) {
        e.printStackTrace(System.out);
    }
}

private static int ev(boolean signed) {
    int bitcount = 0;
    StringBuilder expGolomb = new StringBuilder();
    while (getBit() == 0) {
        expGolomb.append('0');
        bitcount++;
    }
    expGolomb.append("/1");
    int result = 1;
    for (int i = 0; i < bitcount; i++) {
        int b = getBit();
        expGolomb.append(b);
        result = result * 2 + b;
    }
    result--;
    if (signed) {
        result = (result + 1) / 2 * (result % 2 == 0 ? -1 : 1);
        System.out.println("getSe(v) = " + (result) + " " + expGolomb);
    } else {
        System.out.println("getUe(v) = " + (result) + " " + expGolomb);
    }
    return result;
}

private static int uev() {
    return ev(false);
}

private static int sev() {
    return ev(true);
}

private static int getU(int bits) {
    int result = 0;
    for (int i = 0; i < bits; i++) {
        result = result * 2 + getBit();
    }
    System.out.println("getU(" + bits + ") = " + result);
    return result;
}

private static int getBit() {
    int mask = 1 << (7 - (pos & 7));
    int idx = pos >> 3;
    pos++;
    return ((data[idx] & mask) == 0) ? 0 : 1;
}
publicstaticvoidmain(字符串[]args){
解码(StringUtils.fromBase64(“Z0IAKeKQCgDLYC3AQEBpB4kRUA=”);
解码(StringUtils.fromBase64(“Z0IAIOKQCgDLYC3AQEBpB4kRUA=”);
解码(StringUtils.fromBase64(“z0iahunqfae2atwebaqejev”);
}
静态int-pos;
静态字节[]数据;
专用静态无效解码(字节[]数据){
试一试{
System.out.println();
System.out.println(StringUtils.toHex(数据));
System.out.println(StringUtils.toBin(data,0,data.length,true));
System.out.println();
pos=0;
T.数据=数据;
int profile_idc=getU(8);
int constraint_set0_flag=getU(1);
int constraint_set1_flag=getU(1);
int constraint_set2_flag=getU(1);
int constraint_set3_flag=getU(1);
int保留的0位=getU(4);
国际水平(国际数据中心)(8),;
int seq_参数_set_id=uev();
int log2_max_frame_num_minus4=uev();
int pict_order_cnt_type=uev();
System.out.println(“pict_order_cnt_type=“+pict_order_cnt_type”);
如果(图像顺序控制类型==0){
uev();
}else if(图像顺序信息类型==1){
格图(1);
sev();
sev();
int n=uev();
System.out.println(“n*sev,n=“+n”);
对于(int i=0;i3;
pos++;
返回((数据[idx]&掩码)==0)?0:1;
}
失败案例的输出:

67420020E2900A00CB602DC040406907891150
01100111 01000010 00000000 00100000 11100010 10010000 00001010 00000000 11001011 01100000 00101101 11000000 01000000 01000000 01101001 00000111 10001001 00010001 01010000 

getU(8) = 103
getU(1) = 0
getU(1) = 1
getU(1) = 0
getU(1) = 0
getU(4) = 2   << shouldn't this be 0 ? is same with correct parsing!
getU(8) = 0
getUe(v) = 3 00/100
getUe(v) = 13 000/1110   << log2_max_frame_num_minus4 shall be 0-12, inclusive.
getUe(v) = 4 00/101    
pict_order_cnt_type=4    << pic_order_cnt_type shall be 0-2, inclusive.
getUe(v) = 3 00/100       
getU(1) = 0
getUe(v) = 39 00000/101000
getUe(v) = 100 000000/1100101
getU(1) = 1
640 x 1616
67420020E2900A00CB602DC0404040406907891150
01100111 01000010 00000000 00100000 11100010 10010000 00001010 00000000 11001011 01100000 00101101 11000000 01000000 01000000 01101001 00000111 10001001 00010001 01010000 
格图(8)=103
getU(1)=0
格图(1)=1
getU(1)=0
getU(1)=0

getU(4)=2也许不是您所要求的,但是请查看参考实现,看看它们是如何进行解析的

  • 从下载h.264解析器(从这个线程@doom9)

  • 从下载H.264参考软件


  • 这应该让你开始。BTW比特流在附件中描述。B.在规范中。从ITU下载它

    如果代码中有错误,应丢弃第一个字节,即NAL单元类型:

    67 - NAL unit type ( SPS )
    42 - Profile Idc ( Baseline profile in your case )
    00 - reserved zero
    29 - level ( 41 )
    e2 - SPS id ( 0 ), max frame num - 4 ( 0 ), POC type ( 0 ), 
    90 - uev ( 5 ), num ref frames ( 1 ), u ( 0 )
    etc
    

    实际上,您可以使用JCodec类作为现成的SPS解析例程。

    代码中确实存在一个bug(实际上有三个bug)

    • 第一个错误是,第一个字节是NAL头(包含:
      禁止位(1bit)、
      NAL参考位(idc)
      (2bit)和
      NAL单元类型(5bit,值应为7以指示SPS单元)
    • 第二个bug是总共有5个
      constraint_set#u flag
      s,而不是3个(占bug 3中描述的两个位)
    • 第三个错误是,在当前规范中,
      保留零位的数量是2。我想这在过去可能有所不同,但我不确定
    因此,我对decode方法做了一些修改,并提出了适合我的版本(顺便说一句,我的类被称为H264Parser,因此语句
    H264Parser.data=data;
    ):

    私有静态无效解码(字节[]数据){
    试一试{
    System.out.println();
    System.out.println(StringUtils.toHex(数据));
    System.out.println(StringUtils.toBin(data,0,data.length,true));
    System.out.println();
    pos=0;
    H264Parser.data=数据;
    int禁止的0位=getU(1);
    System.out.println(“禁止零位”+禁止零位);
    int nal_ref_idc=getU(2);
    int nal_单位类型=getU(5);
    System.out.println(“nal\u单元类型(SPS应为7)”+nal\u单元类型);
    //NAL_头的末尾
    //SPS数据的启动
    int profile_idc=getU(8);
    int constraint_set0_flag=getU(1);
    int constraint_set1_flag=getU(1);
    int constraint_set2_flag=getU(1);
    int constraint_set3_flag=getU(1);
    int constraint_set4_flag=getU(1);
    int constraint_set5_flag=getU(1);
    //规范的当前版本声明有两个保留位
    int reserved_zero_2bits=getU(2);
    System.out.println(“保留零位”+保留零位);
    国际水平(国际数据中心)(8),;
    int seq_参数_set_id=uev();
    int log2_max_frame_num_minus4=uev()
    
    private static void decode(byte[] data) {
        try {
            System.out.println();
                System.out.println(StringUtils.toHex(data));
                System.out.println(StringUtils.toBin(data, 0, data.length, true));
                System.out.println();
            pos = 0;
            H264Parser.data = data;
    
            int forbidden_zero_bit = getU(1);
            System.out.println("forbidden_zero_bit " + forbidden_zero_bit);
            int nal_ref_idc = getU(2);
            int nal_unit_type = getU(5);
            System.out.println("nal_unit_type (should be 7 for SPS) " + nal_unit_type);
            //END of NAL_header
    
            //Start of SPS data
            int profile_idc = getU(8);
            int constraint_set0_flag = getU(1);
            int constraint_set1_flag = getU(1);
            int constraint_set2_flag = getU(1);
            int constraint_set3_flag = getU(1);
            int constraint_set4_flag = getU(1);
            int constraint_set5_flag = getU(1);
            //The current version of the spec states that there are two reserved bits
            int reserved_zero_2bits = getU(2);
            System.out.println("reserved_zero_2bits" + reserved_zero_2bits);
            int level_idc = getU(8);
            int seq_parameter_set_id = uev();
            int log2_max_frame_num_minus4 = uev();
            int pict_order_cnt_type = uev();
            System.out.println("pict_order_cnt_type=" + pict_order_cnt_type);
            if (pict_order_cnt_type == 0) {
                uev();
            } else if (pict_order_cnt_type == 1) {
                getU(1);
                sev();
                sev();
                int n = uev();
                System.out.println("n*sev, n=" + n);
                for (int i = 0; i < n; i++)
                    sev();
            }
            int num_ref_frames = uev();
            getU(1);
            int pic_width = (uev() + 1) * 16;
            int pic_height = (uev() + 1) * 16;
            int frame_mbs_only_flag = getU(1);
            System.out.println(pic_width + " x " + pic_height);
        } catch (Exception e) {
            e.printStackTrace(System.out);
        }
    }
    
            int seq_parameter_set_id = uev();
    
            if (profile_idc == 100 || profile_idc == 110 ||
                    profile_idc == 122 || profile_idc == 244 || profile_idc == 44 ||
                    profile_idc == 83 || profile_idc == 86 || profile_idc == 118 ||
                    profile_idc == 128) {
                int chroma_format_idc = uev();
                if( chroma_format_idc == 3 ){
                    int separate_colour_plane_flag = getU(1);
                }
    
                int bit_depth_luma_minus8 = uev();
                int bit_depth_chroma_minus8 = uev();
                int qpprime_y_zero_transform_bypass_flag = getU(1);
                int seq_scaling_matrix_present_flag = getU(1);
                if( seq_scaling_matrix_present_flag == 1) {
                    int count = (chroma_format_idc != 3) ? 8 : 12;
                    for (int i = 0; i <count; i++) {
                        int seq_scaling_list_present_flag_i_ = getU(1);
                        if (seq_scaling_list_present_flag_i_ == 1) {
                            if (i < 6)
                                scaling_list(16);
    
                            else
                                scaling_list(64);
                        }
                    }
                }
            }
    
    
            int log2_max_frame_num_minus4 = uev();
    
    int[] scaling_list(int sizeOfScalingList){
        int lastScale = 8;
        int nextScale = 8;
        int delta_scale;
        boolean useDefaultScalingMatrixFlag;
        int[] scalingList = new int[sizeOfScalingList];
        for(int j = 0; j < sizeOfScalingList; j++ ) {
            if( nextScale != 0 ) {
                delta_scale = sev();
                nextScale = ( lastScale + delta_scale + 256 ) % 256;
                useDefaultScalingMatrixFlag = ( j == 0 && nextScale == 0 );
            }
            scalingList[ j ] = ( nextScale == 0 ) ? lastScale : nextScale;
            lastScale = scalingList[ j ];
        }
        return scalingList;
    }