H264 SPS中得到宽高的代码(java/c),测试通过

简介: H264 SPS中得到宽高的代码(java/c),测试通过

代码已经过测试,能正确获取宽高。


 SPS数据是完整的,没有去掉头。如果要去掉,注意NAL_HEADER即可。测试时应该是:0, 0, 0, 1, 0x67, 0x42。。。



JAVA版


package net.quantum6.mediacodec;
import net.quantum6.kit.Log;
public class H264SpsParser
{
    private final static String TAG = H264SpsParser.class.getCanonicalName();
    private final static int NAL_HEADER = 4;
    private static int nStartBit = 0;
    private static int Ue(byte[] pBuff, int nLen)
    {
        int nZeroNum = 0;
        while (nStartBit < nLen * 8)
        {
            if ((pBuff[nStartBit / 8] & (0x80 >> (nStartBit % 8))) != 0)
            {
                break;
            }
            nZeroNum++;
            nStartBit++;
        }
        nStartBit ++;
        int dwRet = 0;
        for (int i=0; i<nZeroNum; i++)
        {
            dwRet <<= 1;
            if ((pBuff[nStartBit / 8] & (0x80 >> (nStartBit % 8))) != 0)
            {
                dwRet += 1;
            }
            nStartBit++;
        }
        return (1 << nZeroNum) - 1 + dwRet;
    }
    private static int Se(byte[] pBuff, int nLen)
    {
        int UeVal =Ue(pBuff,nLen);
        double k  =UeVal;
        int nValue=(int)Math.ceil(k/2);
        if (UeVal % 2==0)
        {    
            nValue=-nValue;
        }
        return nValue;
    }
    private static int u(int BitCount, byte[] buf)
    {
        int dwRet = 0;
        for (int i=0; i<BitCount; i++)
        {
            dwRet <<= 1;
            if ((buf[nStartBit / 8] & (0x80 >> (nStartBit % 8))) != 0)
            {
                dwRet += 1;
            }
            nStartBit++;
        }
        return dwRet;
    }
    private static boolean h264_decode_seq_parameter_set(byte[] buf, int nLen, int[] size)
    {
        nStartBit = NAL_HEADER*8;
        int forbidden_zero_bit=u(1, buf);
        int nal_ref_idc       =u(2, buf);
        int nal_unit_type     =u(5, buf);
        if(nal_unit_type==7)
        {
            int profile_idc         =u(8, buf);
            int constraint_set0_flag=u(1, buf);//(buf[1] & 0x80)>>7;
            int constraint_set1_flag=u(1, buf);//(buf[1] & 0x40)>>6;
            int constraint_set2_flag=u(1, buf);//(buf[1] & 0x20)>>5;
            int constraint_set3_flag=u(1, buf);//(buf[1] & 0x10)>>4;
            int reserved_zero_4bits =u(4, buf);
            int level_idc           =u(8, buf);
            int seq_parameter_set_id=Ue(buf, nLen);
            if ( profile_idc == 100 || profile_idc == 110 ||
                 profile_idc == 122 || profile_idc == 144 )
            {
                int chroma_format_idc=Ue(buf, nLen);
                if ( chroma_format_idc == 3 )
                {
                    int residual_colour_transform_flag=u(1,buf);
                }
                int bit_depth_luma_minus8               =Ue(buf, nLen);
                int bit_depth_chroma_minus8             =Ue(buf, nLen);
                int qpprime_y_zero_transform_bypass_flag=u(1, buf);
                int seq_scaling_matrix_present_flag     =u(1, buf);
                int[] seq_scaling_list_present_flag = new int[8];
                if ( seq_scaling_matrix_present_flag != 0)
                {
                    for( int i = 0; i < 8; i++ )
                    {
                        seq_scaling_list_present_flag[i]=u(1, buf);
                    }
                }
            }
            int log2_max_frame_num_minus4=Ue(buf, nLen);
            int pic_order_cnt_type       =Ue(buf, nLen);
            if ( pic_order_cnt_type == 0 )
            {
                int log2_max_pic_order_cnt_lsb_minus4=Ue(buf, nLen);
            }
            else if( pic_order_cnt_type == 1 )
            {
                int delta_pic_order_always_zero_flag     =u(1,     buf);
                int offset_for_non_ref_pic               =Se(buf, nLen);
                int offset_for_top_to_bottom_field       =Se(buf, nLen);
                int num_ref_frames_in_pic_order_cnt_cycle=Ue(buf, nLen);
                int[] offset_for_ref_frame=new int[num_ref_frames_in_pic_order_cnt_cycle];
                for( int i = 0; i < num_ref_frames_in_pic_order_cnt_cycle; i++ )
                {
                    offset_for_ref_frame[i]=Se(buf, nLen);
                }
            }
            int num_ref_frames                      =Ue(buf, nLen);
            int gaps_in_frame_num_value_allowed_flag=u(1,     buf);
            int pic_width_in_mbs_minus1             =Ue(buf, nLen);
            int pic_height_in_map_units_minus1      =Ue(buf, nLen);
            size[0]=(pic_width_in_mbs_minus1       +1)*16;
            size[1]=(pic_height_in_map_units_minus1+1)*16;
/*
        int frame_mbs_only_flag=u(1,buf,StartBit);  
        if(!frame_mbs_only_flag)  
            int mb_adaptive_frame_field_flag=u(1,buf,StartBit);  
        int direct_8x8_inference_flag=u(1,buf,StartBit);  
        int frame_cropping_flag=u(1,buf,StartBit);  
        if(frame_cropping_flag)  
        {  
            int frame_crop_left_offset=Ue(buf,nLen,StartBit);  
            int frame_crop_right_offset=Ue(buf,nLen,StartBit);  
            int frame_crop_top_offset=Ue(buf,nLen,StartBit);  
            int frame_crop_bottom_offset=Ue(buf,nLen,StartBit);  
        }  
        int vui_parameter_present_flag=u(1,buf,StartBit);  
        if(vui_parameter_present_flag)  
        {  
            int aspect_ratio_info_present_flag=u(1,buf,StartBit);  
            if(aspect_ratio_info_present_flag)  
            {  
                int aspect_ratio_idc=u(8,buf,StartBit);  
                if(aspect_ratio_idc==255)  
                {  
                    int sar_width=u(16,buf,StartBit);  
                    int sar_height=u(16,buf,StartBit);  
                }  
            }  
            int overscan_info_present_flag=u(1,buf,StartBit);  
            if(overscan_info_present_flag)  
                int overscan_appropriate_flagu=u(1,buf,StartBit);  
            int video_signal_type_present_flag=u(1,buf,StartBit);  
            if(video_signal_type_present_flag)  
            {  
                int video_format=u(3,buf,StartBit);  
                int video_full_range_flag=u(1,buf,StartBit);  
                int colour_description_present_flag=u(1,buf,StartBit);  
                if(colour_description_present_flag)  
                {  
                    int colour_primaries=u(8,buf,StartBit);  
                    int transfer_characteristics=u(8,buf,StartBit);  
                    int matrix_coefficients=u(8,buf,StartBit);  
                }  
            }  
            int chroma_loc_info_present_flag=u(1,buf,StartBit);  
            if(chroma_loc_info_present_flag)  
            {  
                int chroma_sample_loc_type_top_field=Ue(buf,nLen,StartBit);  
                int chroma_sample_loc_type_bottom_field=Ue(buf,nLen,StartBit);  
            }  
            int timing_info_present_flag=u(1,buf,StartBit);  
            if(timing_info_present_flag)  
            {  
                int num_units_in_tick=u(32,buf,StartBit);  
                int time_scale=u(32,buf,StartBit);  
                fps=time_scale/num_units_in_tick;  
                int fixed_frame_rate_flag=u(1,buf,StartBit);  
                if(fixed_frame_rate_flag)  
                {  
                    fps=fps/2;  
                }  
            }  
        }  
*/
            return true;
        }
        return false;
    }
    public static int[] getSizeFromSps(byte[] data)
    {
        for (int i=0; i<data.length-4; i++)
        {
            if (data[i]==0 && data[i+1]==0 && data[i+2]==0 && data[i+3]==1 && data[i+4]==0x67)
            {
                int[] size = new int[2];
                h264_decode_seq_parameter_set(data, data.length, size);
                Log.d(TAG, "Sps=("+size[0]+", "+size[1]+")");
                return size;
            }
        }
        return null;
    }
}


C版

  JAVA代码是从C改过来的。没有运行。也许有小错误,各位参考JAVA再改。


#include <cstdint>
#include <cmath>
#define NAL_HEADEER 4
uint32_t Ue(uint8_t *pBuff, uint32_t nLen, uint32_t &nStartBit)
{
    //计算0bit的个数
    uint32_t nZeroNum = 0;
    while (nStartBit < nLen * 8)
    {
        if (pBuff[nStartBit / 8] & (0x80 >> (nStartBit % 8))) //&:按位与,%取余
        {
            break;
        }
        nZeroNum++;
        nStartBit++;
    }
    nStartBit ++;
    //计算结果
    uint32_t dwRet = 0;
    for (uint32_t i=0; i<nZeroNum; i++)
    {
        dwRet <<= 1;
        if (pBuff[nStartBit / 8] & (0x80 >> (nStartBit % 8)))
        {
            dwRet += 1;
        }
        nStartBit++;
    }
    return (1 << nZeroNum) - 1 + dwRet;
}
int Se(uint8_t *pBuff, uint32_t nLen, uint32_t &nStartBit)
{
    int UeVal=Ue(pBuff,nLen,nStartBit);
    double k=UeVal;
    int nValue=ceil(k/2);//ceil函数:ceil函数的作用是求不小于给定实数的最小整数。ceil(2)=ceil(1.2)=cei(1.5)=2.00
    if (UeVal % 2==0)
    {
        nValue=-nValue;
    }
    return nValue;
}
uint32_t u(uint32_t BitCount, uint8_t * buf, uint32_t &nStartBit)
{
    uint32_t dwRet = 0;
    for (uint32_t i=0; i<BitCount; i++)
    {
        dwRet <<= 1;
        if (buf[nStartBit / 8] & (0x80 >> (nStartBit % 8)))
        {
            dwRet += 1;
        }
        nStartBit++;
    }
    return dwRet;
}
bool h264_decode_seq_parameter_set(uint8_t * buf, uint32_t nLen ,int &Width, int &Height)
{
    uint32_t StartBit=NAL_HEADEER*8;
    int forbidden_zero_bit=u(1, buf, StartBit);
    int nal_ref_idc       =u(2, buf, StartBit);
    int nal_unit_type     =u(5, buf, StartBit);
    if (nal_unit_type==7)
    {
        int profile_idc         =u(8, buf, StartBit);
        int constraint_set0_flag=u(1, buf, StartBit);//(buf[1] & 0x80)>>7;
        int constraint_set1_flag=u(1, buf, StartBit);//(buf[1] & 0x40)>>6;
        int constraint_set2_flag=u(1, buf, StartBit);//(buf[1] & 0x20)>>5;
        int constraint_set3_flag=u(1, buf, StartBit);//(buf[1] & 0x10)>>4;
        int reserved_zero_4bits =u(4, buf, StartBit);
        int level_idc=u(8, buf, StartBit);
        int seq_parameter_set_id=Ue(buf, nLen, StartBit);
        if ( profile_idc == 100 || profile_idc == 110 ||
            profile_idc == 122 || profile_idc == 144 )
        {
            int chroma_format_idc=Ue(buf, nLen, StartBit);
            if ( chroma_format_idc == 3 )
            {
                int residual_colour_transform_flag  =u(1, buf, StartBit);
            }
            int bit_depth_luma_minus8               =Ue(buf, nLen, StartBit);
            int bit_depth_chroma_minus8             =Ue(buf, nLen, StartBit);
            int qpprime_y_zero_transform_bypass_flag=u(1,     buf, StartBit);
            int seq_scaling_matrix_present_flag     =u(1,     buf, StartBit);
            int seq_scaling_list_present_flag[8];
            if ( seq_scaling_matrix_present_flag )
            {
                for ( int i = 0; i < 8; i++ )
                {
                    seq_scaling_list_present_flag[i]=u(1, buf, StartBit);
                }
            }
        }
        int log2_max_frame_num_minus4=Ue(buf, nLen, StartBit);
        int pic_order_cnt_type       =Ue(buf, nLen, StartBit);
        if ( pic_order_cnt_type == 0 )
        {
            int log2_max_pic_order_cnt_lsb_minus4=Ue(buf, nLen, StartBit);
        }
        else if ( pic_order_cnt_type == 1 )
        {
            int delta_pic_order_always_zero_flag     =u(1,     buf, StartBit);
            int offset_for_non_ref_pic               =Se(buf, nLen, StartBit);
            int offset_for_top_to_bottom_field       =Se(buf, nLen, StartBit);
            int num_ref_frames_in_pic_order_cnt_cycle=Ue(buf, nLen, StartBit);
            int *offset_for_ref_frame=new int[num_ref_frames_in_pic_order_cnt_cycle];
            for ( int i = 0; i < num_ref_frames_in_pic_order_cnt_cycle; i++ )
            {
                offset_for_ref_frame[i]=Se(buf, nLen, StartBit);
            }
            delete [] offset_for_ref_frame;
        }
        int num_ref_frames=Ue(buf,nLen,StartBit);
        int gaps_in_frame_num_value_allowed_flag=u(1,    buf, StartBit);
        int pic_width_in_mbs_minus1             =Ue(buf, nLen, StartBit);
        int pic_height_in_map_units_minus1      =Ue(buf, nLen, StartBit);
        Width =(pic_width_in_mbs_minus1       +1)*16;
        Height=(pic_height_in_map_units_minus1+1)*16;
        return true;
    }
    return false;
}
int main()
{
    int Width, Height;
    if (h264_decode_seq_parameter_set(str, 11, Width, Height))
    {
    }
    return 0;
}
目录
相关文章
|
9天前
|
数据采集 机器学习/深度学习 大数据
行为检测代码(一):超详细介绍C3D架构训练+测试步骤
这篇文章详细介绍了C3D架构在行为检测领域的应用,包括训练和测试步骤,使用UCF101数据集进行演示。
21 1
行为检测代码(一):超详细介绍C3D架构训练+测试步骤
|
7天前
|
安全 Java API
Java 17新特性让你的代码起飞!
【10月更文挑战第4天】自Java 8发布以来,Java语言经历了多次重大更新,每一次都引入了令人兴奋的新特性,极大地提升了开发效率和代码质量。本文将带你从Java 8一路走到Java 17,探索那些能让你的代码起飞的关键特性。
32 1
|
6天前
|
Java 程序员 API
Java中的Lambda表达式:简化代码的秘密武器
【10月更文挑战第11天】 在Java编程中,Lambda表达式是一种简洁而强大的工具,它允许我们将函数作为参数传递给其他方法。本文将介绍Lambda表达式的基本概念、使用方法以及在实际项目中的应用案例,帮助你更好地理解和利用这一特性来简化代码。
21 8
|
2天前
|
存储 人工智能 Java
将 Spring AI 与 LLM 结合使用以生成 Java 测试
AIDocumentLibraryChat 项目通过 GitHub URL 为指定的 Java 类生成测试代码,支持 granite-code 和 deepseek-coder-v2 模型。项目包括控制器、服务和配置,能处理源代码解析、依赖加载及测试代码生成,旨在评估 LLM 对开发测试的支持能力。
9 1
|
4天前
|
Java 开发者
在Java编程中,正确的命名规范不仅能提升代码的可读性和可维护性,还能有效避免命名冲突。
【10月更文挑战第13天】在Java编程中,正确的命名规范不仅能提升代码的可读性和可维护性,还能有效避免命名冲突。本文将带你深入了解Java命名规则,包括标识符的基本规则、变量和方法的命名方式、常量的命名习惯以及如何避免关键字冲突,通过实例解析,助你写出更规范、优雅的代码。
25 3
|
4天前
|
Java 程序员
在Java编程中,关键字不仅是简单的词汇,更是赋予代码强大功能的“魔法咒语”。
【10月更文挑战第13天】在Java编程中,关键字不仅是简单的词汇,更是赋予代码强大功能的“魔法咒语”。本文介绍了Java关键字的基本概念及其重要性,并通过定义类和对象、控制流程、访问修饰符等示例,展示了关键字的实际应用。掌握这些关键字,是成为优秀Java程序员的基础。
12 3
|
9天前
|
jenkins Java 测试技术
如何使用 Jenkins 自动发布 Java 代码,通过一个电商公司后端服务的实际案例详细说明
【10月更文挑战第8天】本文介绍了如何使用 Jenkins 自动发布 Java 代码,通过一个电商公司后端服务的实际案例,详细说明了从 Jenkins 安装配置到自动构建、测试和部署的全流程。文中还提供了一个 Jenkinsfile 示例,并分享了实践经验,强调了版本控制、自动化测试等关键点的重要性。
21 5
|
7天前
|
Java 编译器 API
从Java 8到Java 17,这些新特性让你的代码起飞!
【10月更文挑战第10天】在软件开发领域,Java作为一种历史悠久且广泛使用的编程语言,不断进化以适应新的需求和挑战。从Java 8到Java 17,每一次版本更新都带来了诸多新特性和改进,极大地提升了开发效率和代码质量。今天,我们就来一起探讨这些新特性,看看它们是如何让我们的代码“起飞”的。
72 0
|
2月前
|
Java 数据安全/隐私保护
Java代码的执行顺序和构造方法
构造方法是类的一种特殊方法,用于初始化新对象。在 Java 中,每个类默认都有一个与类名同名的构造方法,无需返回类型。构造方法不能用 static、final、synchronized、abstract 或 native 修饰。它可以重载,通过不同的参数列表实现多种初始化方式。构造方法在对象实例化时自动调用,若未显式声明,默认提供一个无参构造方法。构造代码块和静态代码块分别用于对象和类的初始化,按特定顺序执行。
26 0
|
4月前
|
Java
Java代码的执行顺序
Java代码的执行顺序
27 1