PSM的当前时间解析

发布时间 2023-12-14 16:27:20作者: 邗影

海康PSM分析

来源:https://www.cnblogs.com/feixiang-energy/p/17735762.html
00
00 01 BC 00 5A E0 FF 00 24 40 0E 48 4B 00 00 17 9D 3E B4 60 00 00 FF FF FF 41 12 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 2C 1B E0 00 10 42 0E 00 00 A0 21 05 00 02 D0 12 1C 3F 00 1C 21 0F C0 00 0C 43 0A 00 00 FE 00 FA 03 01 F4 03 FF BD BD 00 00 BF BF 00 00 00 00 00 00 4byte start: 00 00 01 BC 2byte packlen: 00 5A = 90 2byte packinfo: E0 FF 2byte program_strem_info_len: 00 24 = 36 36byte descriptor: 40 0E 48 4B 00 00 17 9D 3E B4 60 00 00 FF FF FF 41 12 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 aa 0x40 表示当前为BASIC信息 aa+1 0x0E = 14 BASIC信息长度 aa+2~aa+3 0x48 0x4B 公司描述符 aa+6~aa+11 0x17 0x9D 0x3E 0xB4 0x60 0x00 0x00 当前年月日时分秒及加密类型 bb 0x41 表示当前为DEVICE信息 bb+1 0x12 = 18 DEVICE信息的长度 bb+4~bb+19 设备ID号 2byte elementary_stream_map_length: 00 2C = 44 1byte stream_type: 1B 0x1B --> H264 0x24 --> H265 1byte elementary_stream_id: E0 0xE0 --> 视频 0xC0 --> 音频 2byte elementary_stream_info_len: 00 10 = 16 16byte descriptor: 42 0E 00 00 A0 21 05 00 02 D0 12 1C 3F 00 1C 21 aa 0x42 表示当前为VIDEO信息 aa+1 0x0E = 14 VIDEO信息长度 aa+2~aa+3 0x00 0x00 编码器版本 aa+4~aa+5 0xA0 0x21 编码器年月日 aa+6~aa+7 0x05 0x00 = 1280 图像宽度 aa+8~aa+9 0x02 0xD0 = 720 图像高度 aa+10 0x12 是否隔行扫描,b帧数目,是否为SVC码流,是否使用e帧,最大参考帧数目 aa+11 0x1C 水印类型,显示时是否需要反隔行 aa+12 0x3F JPEG的Q值 aa+13~aa+15 0x00 0x1C 0x21 以1/90000s为单位的两帧间时间间隔,是否使用固定帧率 1byte stream_type: 0F 0x90 --> g711 0x0F --> aac 1byte elementary_stream_id: C0 0xE0 --> 视频 0xC0 --> 音频 2byte elementary_stream_info_len: 00 0C = 12 12byte descriptor: 43 0A 00 00 FE 00 FA 03 01 F4 03 FF dd 0x43 表示当前为AUDIO信息 dd+1 0x0A AUDIO信息长度 dd+2~dd+3 0x00 0x00 音频帧长度 dd+4 0xFE 音频声道数 dd+5~dd+7 0x00 0xFA 0x03 音频采样率 dd+8~dd+10 0x01 0xF4 0x03 音频比特率 2byte 私有数据信息 BD BD 4byte CRC校验 00 00 BF BF

下边我们找一段来解析一下( 随便挖一段海康的来看看吧,网上比较多;详细的字段解析见最后附图):

1, PSM头标记: 00 00 01 BC

2,  00 46:长度=70字节

3, packinfo: E2 FF

4, 00 24基本流长度:36字节 跳过就是音视频基本流的长度了;但是这36个字节是有用的,存储了公司 ,时间,加密信息,设备,版本号等等

5、解析基本流:

      40 0E 48 4B 01 00 17 C7 35 46 6D A0 00 FF FF FF 41 12 48 4B 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

  在这段信息中,一般会存在0x40 ,0x41,0x80(不一定有)三段信息;

  其中40表示basic信息:解析遵循一下规定

 

  

   40 0E 48 4B 01 00 17 C7 35 46 6D A0 00 FF FF FF :

    这段码流中的0E 表示basic长度,14字节;0x48 0x4b正好是HK,海康;

    17 C7 35 46 6D A0就是当前系统时间和加密类型,其加密类型我们并不好 分析,但是可以简单分析下时间戳

   以老陈大佬的PSM clock写入的逻辑来解析一下,注意海康那个记录年月日的方式跟这个可能并不一样

size_t clock_extension_descriptor_write(uint8_t* data, size_t bytes, int64_t clock)
{
    struct tm* t;
    time_t seconds;
    if (bytes < 16)
        return 0;

    seconds = (time_t)(clock / 1000);
    t = localtime(&seconds);

    data[0] = 0x40;
    data[1] = 0x0E;
    data[2] = 0x48;
    data[3] = 0x4B;
    data[4] = 0x01;
    data[5] = 0x00;
    data[6] = (uint8_t)(t->tm_year + 1900 - 2000); // base 2000
    data[7] = (uint8_t)((t->tm_mon + 1) << 4) | ((t->tm_mday >> 1) & 0x0F);
    data[8] = (uint8_t)((t->tm_mday & 0x01) << 7) | ((t->tm_hour & 0x1F) << 2) | ((t->tm_min >> 4) & 0x03);
    data[9] = (uint8_t)((t->tm_min & 0x0F) << 4) | ((t->tm_sec >> 2) & 0x0F);
    data[10] = (uint8_t)((t->tm_sec & 0x03) << 6);
    data[11] = 0x00;
    data[12] = 0x00;
    data[13] = 0xFF;
    data[14] = 0xFF;
    data[15] = 0xFF;
    return 16;
}

所以:

(十六进制)17 C7 35 46 6D A0

0x17:23=(t->tm_year + 1900 - 2000;年是2023年,这里的t->tm_year + 1900 表示当前的年,因为tm的time记录年是从1900年开始的;

0xc7: 11000111 =(uint8_t)((t->tm_mon + 1) << 4) | ((t->tm_mday >> 1) & 0x0F);  所以t->tm_mon=00001011=11【tm的月份0-11范围内的真实日期月值】实际从0记录月份,实际是12月,(1011+1)<<4 =1100,日期=01110或者01111

0x35:用来进一步确定日期已经小时和分钟:00110101=(uint8_t)((t->tm_mday & 0x01) << 7) | ((t->tm_hour & 0x1F) << 2) | ((t->tm_min >> 4) & 0x03);

  0=(uint8_t)((t->tm_mday & 0x01) << 7);所以日期的最后一个二进制是0,日期是01110=14号

  01101(5位)= ((t->tm_hour & 0x1F) << 2) ;所以小时等于1101=13点

  01 = ((t->tm_min >> 4) & 0x03),分钟对应的二进制是:01****

0x46: 01000110 =(uint8_t)((t->tm_min & 0x0F) << 4) | ((t->tm_sec >> 2) & 0x0F);

  0100就是分钟的低四位,0100 = ((t->tm_min & 0x0F) << 4);组合上边解析的高二位,010100=20分

  0110=((t->tm_sec >> 2) & 0x0F);秒最大是59,最多占6个小bit;所以秒的高四位是0110,

0x6D:01101101=(uint8_t)((t->tm_sec & 0x03) << 6); 秒的低二位是01,所以综合上边的前4位,秒=011001=25秒(十进制)

至于 0x6d a0剩余的部分,可能是某些公司的私有标记,0xff是补充位

 

basic解析完要解析device了41 12 48 4B 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 

0x41:device信息

0x12:18个字节,是device的长度

48 4B:HK

00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00:设备ID

因为我这个里没有私有的东西,后边就是0x 00 18 24 e0就是265了,所以就不解析