mp4v2实时将h.264封装成mp4格式

一、背景

如上一次的问题,目前h.264的裸流有了,但是手机和windows电脑都无法正常播放,还需要弄成 mp4或者flv格式。
鉴于车机解码的同事,用的是mp4,这里也就忍痛放弃更容易的flv了。
第一步,下载Mp4v2代码。找资料。封装这件事情,按理来说应该是常见的操作了,先看看网上有没有开源代码。OK,有一个Mp4v2。至于为什么不用ffmpeg,因为太大了,节约点车机内存吧。
https://launchpad.net/ubuntu/+source/mp4v2/2.0.0~dfsg0-6

第二步,编译。
./configure --prefix=/opt/grape-buildhf/staging/ --host=arm-linux --disable-debug --enable-shared CC=arm-linux-gnueabi-gcc CXX=arm-linux-gnueabi-g++

如果需要编译成静态库,那么编译的configure进行了修改
./configure --prefix=/home/code/mp4v2-2.0.0/output --host=arm-linux --disable-debug --with-pic --enable-shared CC=arm-linux-gnueabi-gcc CXX=arm-linux-gnueabi-g++ CFLAGS="-fPIC" CXXFLAGS="-fPIC"
在调用的文件Makefile中,
LIBLDFLAGS += -L /home/code/mp4v2-2.0.0/output/lib -lstdc++ -lmp4v2

第三步,参照示例,开始写咯。感谢Mp4v2进行的封装,用C语言能够直接调用真的是很爽。

二、用到的函数

1,MP4FileHandle MP4Create(const char* fileName,uint32_t flags DEFAULT(0) );
参照file.h中的描述,这个是必须第一个调用的(MP4Create is the first call that should be used when you want to create
* a new, empty mp4 file. It is equivalent to opening a file for writing,
* but also involved with creation of necessary mp4 framework structures.
* ie. invoking MP4Create() followed by MP4Close() will result in a file
* with a non-zero size.)
实际调用:m_mp4_file = MP4Create("/sdcard/DCIM/720p.mp4", 0); //创建mp4文件

2,bool MP4SetTimeScale(MP4FileHandle hFile, uint32_t value)
参数,value = 1000;//也有人写90000,感觉使用的时候没有差别,

3,MP4TrackId MP4AddH264VideoTrack(MP4FileHandle hFile,
uint32_t timeScale,
MP4Duration sampleDuration,
uint16_t width,
uint16_t height,
uint8_t AVCProfileIndication,
uint8_t profile_compat,
uint8_t AVCLevelIndication,
uint8_t sampleLenFieldSizeMinusOne)
实际使用:m_mp4_id = MP4AddH264VideoTrack(m_mp4_file, 1000, 40, dst_width, dst_height, 0x4D, 0x00, 0x1f, 0x03);    duration=40,是25fps帧率时,timescale/25得到的。

4,void MP4SetVideoProfileLevel(MP4FileHandle hFile, uint8_t value)
参数,value,ProfileLevel 不懂。有设置为1的,有设置为0x0f的,0x7f的,得看文档。
实际使用:MP4SetVideoProfileLevel(m_mp4_file, 0x0F); //do not know,need to know.

5,MP4AddH264SequenceParameterSet  //write sps
MP4AddH264SequenceParameterSet(m_mp4_file, m_mp4_id, (sps_pps_data.pBuffer+4), sps_length-4);
6,MP4AddH264PictureParameterSet  //write pps
MP4AddH264PictureParameterSet(m_mp4_file, m_mp4_id, (sps_pps_data.pBuffer+sps_length+4), pps_length-4);
使用的
00 00 00 01 67 4D 00 1F 96 54 02 80 2D 88  //sps
00 00 00 01 68 ee 3c 80  //pps
注意:这里sps需要将 00 00 00 01替换成00 00 00 0a,即除了00 00 00 01这个头之后,后面的长度.pps同理,替换成00 00 00 04

7,MP4WriteSample      //duration为invalid或者40都行。从结果来看,应该是将数据写到mdat中。这部分结构与slice部分相同。
前4位表示后面数据的长度,不包含自身。为什么是前4位,因为sampleLenFieldSizeMinusOne是3.所以sampleLenFieldSize=4.
*(outputBufferNew + 0) = (unsigned char)((outputBufferLen - 4) >> 24);
*(outputBufferNew + 1) = (unsigned char)((outputBufferLen - 4) >> 16);
*(outputBufferNew + 2) = (unsigned char)((outputBufferLen - 4) >> 8);
*(outputBufferNew + 3) = (unsigned char)((outputBufferLen - 4) & 0xff);
if (!MP4WriteSample(m_mp4_file, m_mp4_id,outputBufferNew, outputBufferLen, 40, 0, isSyncSample))
{
    printf("encode error\n");
}//这里面outputBufferNew是一个完整的数据帧,I或者P,B,内容为00 00 00 01 65 88 80 40 03 7f 00 3b 71 20 18 e6 11 fc.......

8,MP4FileClose

三、mp4封装格式分析

就这些函数看来,mp4流与h.264流的区别,是首先创建的mp4头,以及mp4尾部的table。然后将sps,pps以及每帧数据封装。封装的方法,只是去掉了00 00 00 01 这个头,变成了00,01,bd,8b这个数据长。
将mp4v2封装的mp4文件,与封装前的h.264文件对比(头部部分)。原始文件点此链接。
具体的分析,需要参见 ISO IEC 14496-12 以及 MP4相关的 part-14 

mp4:
00 00 00 18 66 74 79 70 6d 70 34 32 00 00 00 00 6d 70 34 32 69 73 6f 6d 00 00 00 88 66 72 65 65
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 1e a9 4b 6d 64 61 74 00 00 00 0a 67 4d 00 1f 96 54 02 80 2d 88 00 00 00 04 68 ee 3c 80 00 01
fc d2
 65 88 80 40 03 7f 00 3b 71 20 18 e6 11 fc

h.264:
00 00 00 01 67 4D 00 1F 96 54 02 80 2D 88  //sps , 无uvi信息
00 00 00 01 68 ee 3c 80  //pps
00 00 00 01 65 88 80 40 03 7F 00 3b 71 20 18 e6 11 fc..... //I帧

mp4解析:

最前面的是 ftyp Box,有且仅有一个。
      00 00 00 18:  size ,24,表示此BOX有24个字节,并且表示长度的四个字节也包含在24个字节内。以下同
      66 74 79 70:  type,表示BOX TYPE,此处为ftyp
      6d 70 34 32:  Major_brand      (“mp42”) //不懂啥意思。
      00 00 00 00:  Minor_version     (mp42 的版本号)
      6d 70 34 32:(“mp42”) //不懂啥意思。
      69 73 6F 6D:  isom  // 不懂啥意思,大概表示本文件兼容或者说遵循isom结构。
00 00 00 88 66 72 65 65 //看不懂 free box,百度的结果是不重要。
00 1e a9 4b 6d 64 61 74  mdat type box。里面包含多个slice,内容很重要。
slice 这部分的长度计算是不一样的,00 00 00 0a为data长度,后面是data数据,而00 00 00 0a这四个字节+data长度 = slice总体长度,这点是与box不一样的。一个slice结束后,紧接着是下一个slice的data长度,下一个data数据。如果只有一个mdat box。那么 mp4是将h.264所有的信息,都放在这些slice中了。mdat主要封装了sps.pps,以及h.264的帧数据,但是想要进行随机播放,以及获得其他的文件描述,还需要moov box。这部分的二进制贴在文末,有兴趣就去看, 默认32个字节一行紧接着mdat的是moov信息。
00 00 04 30 6D 6F 6F 76 //1072个moov信息。
00 00 00 6c  6D 76 68 64 //mvhd Box,6C个字节,mp4v2实时将h.264封装成mp4格式_第1张图片
  00 00 00 00:  version,flags
  c7 62 f5 92:  creation-time创建文件的时间,是距离1904年1月1日0点的秒数,
  c7 62 f5 96:  modifiation-time修改文件的时间,总时长4s。
  00 00 03 e8:  timescale时标,时间刻度的单位,为1/1000秒
  00 00 0e d8:  duration持续时间, //  duration/timescale=影片时长,精确时间3800ms.
  00 01 00 00:  rate播放描述的等级
  01 00:    volume播放时的音量
  00 00:    保留的16bits的0
  00 00 00 00 00 00 00 00:  保留的32×2bits的0。
  00 01 00 00  00 00 00 00  00 00 00 00
  00 00 00 00  00 01 00 00  00 00 00 00
  00 00 00 00  00 00 00 00  40 00 00 00 :  3*3matrix转换矩阵
  00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00 :  6个32bits的pre-defined 的0
  00 00 00 02:  next-track-ID //  话说,当前的track ID在哪里呢?
  00 00 00 18 69 6f 64 73  //Box Type: ‘iods’  //其实可以不要,高级内容或者Object Descriptor需要。
  00 00 00 00 10 80 80 80 07 00 4f ff ff ff 0f ff // 不懂
  00 00 03 a4 74 72 61 6b //track box  
  00 00 00 5c 74 6b 68 64 //tkhd box ,包含了单个track的特征。mp4v2实时将h.264封装成mp4格式_第2张图片

00// 00 00 01 //version 00,flag 00 00 01  //flag是不是应该改成 00 00 07,同时用于预览?
c7 62 f5 92 c7 62 f5 96 00 00 00 01 00 00 00 00 00 00 0e d8 起始时间,编辑时间,track Id,保留位,duration。话说,track Id,是不是出现问题了?mvhd box的next-track-ID为2。尝试着修改了一次,将的next-track-id变成了1,没发现啥问题。继续吧。
00 00 00 00   00 00 00 00   00 00 00 00 00 00 00 00  
00 01 00 00   00 00 00 00   00 00 00 00
00 00 00 00   00 01 00 00   00 00 00 00 
00 00 00 00   00 00 00 00    40 00 00 00
05 00 00 00   02 d0 00 00  //宽高。 0x50 和 0x2D 是 1280 × 720,后面的 00 00 不太懂了。
00 00 03 40 6d 64 69 61 //media box
00 00 00 20 6d 64 68 64 //mdhd box

mp4v2实时将h.264封装成mp4格式_第3张图片
00 00 00 00 c7 62 f5 92 c7 62 f5 96 00 00 03 e8 00 00 0e d8 55 c4 00 00//新面孔也就pad,language。0x55 0xc4 进行拆分,b0 10101 01110 00100 其中bit(1) pad = 0; language[0] = 10101,01110,00100。详细含义,需要看ISO     639‐2/T    

00 00 00 21 68 64 6c 72 //hdlr box


00 00 00 00 00 00 00 00 76 69 64 65 00 00 00 00 00 00 00 00 00 00 00 00 00 //version 0,predifined=0,handler_type=vide.默认可选的type有soun,hint和vide这三种。
00 00 02 f7 6d 69 6e 66 //minf box
00 00 00 14 76 6d 68 64 //vmhd box
00 00 00 01 00 00 00 00 00 00 00 00 //version = 1,for video media?
00 00 00 24 64 69 6e 66 //dinf box
00 00 00 1c 64 72 65 66 //dref box 
00 00 00 00 00 00 00 01
00 00 00 0c 75 72 6c 20 00 00 00 01// url ?
00 00 02 b7 73 74 62 6c //stbl


00 00 00 87 73 74 73 64 //stsd  BOX,135字节
00 00 00 00 //这段解析不一样,首先这个stsd继承了SampleEntry,所以解析的时候,fullbox,verison+flag
00 00 00 01 //Enrty Count =1 .sample descriptions的数目。
00 00 00 77 61 76 63 31 //AVC1
00 00 00 00 00 00 / 00 01 // reserved = 0;  data_reference_index=1;
00 00 pre_defined
00 00 reserved
00 00 00 00 00 00 00 00 00 00 00 00 pre_defined
05 00 02 d0    1280*720
00 48 00 00 / 00 48 00 00 //template unsigned int(32) horizresolution/vertresolution = 0x00480000; // 72 dpi
00 00 00 00  //reserved
00 01 //template unsigned int(16) frame_count = 1,视频必须为1.
0e 4a 56 54 2f 41 56 43 20 43 6f 64 69 6e 67 00 00 00 00 00 00 00 00 00 00 00 00 00 // JVT/AVC Coding//compressorname
00 00 00 00 //reserved 0
00 18 //depth
ff ff //pre_define = -1;
00 00 00 21 61 76 63 43 //avcC信息
01 4d 00 1f ff e1 00 0a 67 4d 00 1f 96 56 02 80 2d 88 01 00 04 68 ea 43 c8/

mp4v2实时将h.264封装成mp4格式_第4张图片
01 : configurationVersion
4D : AVCProfileIndication
00 : profile_compatibility
1f : AVCLevelIndication
FF : 1111 1111   前面6位为reserved,后面2位(0b11)为:lengthSizeMinusOne: 3,那么用来表示size的字节就有3+1=4个
E1 : 1110 0001    前面3位是reserved,后面5bit是numOfSequenceParameterSets,表示有1个。
00 0a : sequenceParameterSetLength 10
67 4d 00 1f 96 56 02 80 2d 88: SPS内容再重复
01 : numOfPictureParameterSets
00 04 : pictureParameterSetLength 4
68 ea 43 c8 : PPS的内容再重复

mp4v2实时将h.264封装成mp4格式_第5张图片
00 00 00 20 73 74 74 73 //stts
00 00 00 00 / 00 00 00 02 //version 0, entry_count =2
00 00 00 02 00 00 00 00 //entry_index 1, sample_count 2,sample_delta 0;
00 00 00 5f 00 00 00 28  //entry_index 2, sample_count 95,sample_delta 40; 总时长3800ms
00 00 01 98 73 74 73 7a //stsz 408个字节
mp4v2实时将h.264封装成mp4格式_第6张图片
00 00 00 00 // version + flags
00 00 00 00 //sample-size 这个值等于0,表示是至少有两种sample。
00 00 00 61 //sample-count  97 
00 00 00 0e  //entry_size,第一个sample有14个字节。也就是mdat之后的第一个slice,sps信息。
00 00 00 08 //第二个sample8个字节。也就是pps的信息加头部。
00 01 fc d6 // 第一个视频帧的长度。因此,用这个万一,就可以
00 00 18 27 // 第二个视频帧的长度。
00 00 0c 1e  // 第三个。。。
00 00 16 b7 00 00 25 82 00 00 48 86 00 00 39 19 00 00 4a 8b 00 00 48 b4 00 00 47 b2 00 00 61 ab
00 00 39 87 00 00 4b c8 00 00 4a 2e 00 00 49 d6 00 00 67 d3 00 00 3b 3b 00 00 4d 67 00 00 4c 41
00 00 4a 0b 00 00 6b 92 00 00 3b 2a 00 00 36 c2 00 00 2a 41 00 00 35 32 00 00 6c b0 00 00 4f 40
00 00 4b d7 00 00 49 f6 00 00 48 f2 00 00 6e 06 00 00 4f a1 00 00 4b 83 00 00 4a 6c 00 00 4a 4e
00 00 6c f4 00 00 50 2e 00 00 4b aa 00 00 49 cb 00 00 48 4f 00 00 ad dd 00 00 3e 4b 00 00 4f 58
00 00 4d 57 00 00 4b b4 00 00 59 ec 00 00 38 e4 00 00 4b 9a 00 00 37 7a 00 00 4c 77 00 00 5f 8a
00 00 4e 8d 00 00 4c eb 00 00 4b 69 00 00 4c 5d 00 00 69 ba 00 00 51 7a 00 00 4d ee 00 00 4d 17
00 00 4b 46 00 00 67 2f 00 00 51 e9 00 00 4f 90 00 00 4c fa 00 00 4d 88 00 00 5f b5 00 00 53 1d
00 00 53 7a 00 00 52 a2 00 00 51 24 00 00 64 ec 00 00 50 55 00 00 39 ab 00 00 4d f7 00 00 39 b3
00 00 62 90 00 00 51 d4 00 00 52 44 00 00 4d 12 00 00 4c 8a 00 00 a4 8d 00 00 40 f1 00 00 50 ff
00 00 4e 44 00 00 4e 4d 00 00 62 f1 00 00 53 9e 00 00 51 ec 00 00 4e 8e 00 00 4e 60 00 00 61 6e
00 00 4f 3f 00 00 4c 8e 00 00 4b f5 00 00 4c 36//第95个视屏帧长度。

00 00 00 34 73 74 73 63  //stsc
00 00 00 00 version+flags
00 00 00 03  //sample-to-chunk的数目
00 00 00 01 // first chunk //第一个chunk序号。
00 00 00 1b //sample per chunk
00 00 00 01 //sample description_index
00 00 00 02 // second chunk
00 00 00 19 //sample per chunk
00 00 00 01 //sample description_index
00 00 00 04 // third chunk
00 00 00 14  //sample per chunk
00 00 00 01 //sample description_index
所以,总共有4个chunk。其中1个chunk有27(0x1b)个chunk,第二个chunk和第三个chunk包含相同的sample数量25(0x19),第四个chunk只有20个sample。总共有97个sample就是这样分配的。

00 00 00 20 73 74 63 6f //stco  d
00 00 00 00 //version+flags
00 00 00 04 //chunk offset的数目。这个offset是相对整个文件的偏移。好处是快速查找,坏处是一旦遇到前面进行修改,所有的都要动。
00 00 00 a8 //第一个chunk的offset.
00 07 f9 52 //第二个chunk的offset.
00 10 03 b1 //第三个chunk的offset.
00 17 fb ca  //第四个chunk的offset.

00 00 00 1c 73 74 73 73 //stss
00 00 00 00  :version,flags
00 00 00 03 :entry_count  //sync sample的数目
00 00 00 03 : sample_number 1 //关键帧sync sample的序号
00 00 00 2b : sample_number 2 //关键帧sync sample
00 00 00 53 : sample_number 3 //关键帧sync sample
00 00 00 88 66 72 65 65 //freebox 全部是0,不重要。

算是全部结束。之所以解析这部分内容,是因为使用初次编码的mp4没法播放,对比二进制能够更容易的发现问题所在.
在linux下播放时,除了需要调用MP4AddH264SequenceParameterSet  以及MP4AddH264PictureParameterSet 以外,还需要调用 MP4WriteSample ,将sps,pps写在mdat前面,否则就没法播放。至于为什么这样,不是很明白.这里写的时候,可以将MP4WriteSample里面的duration以及bool isSyncSample都写成0,但是这种写法会使得 sample-size变多,最好还是将这个部分与第一个I帧进行数据合并.
在写帧的时候,只将I帧0x65开头的sample写成isSyncSample=1就行,其余的 0x41什么的,写成0没有什么影响.不过这个是音视频同步用的,没有音频的我,随意浪...
mp4v2的使用,到此结束.明天试着用ffmpeg来试试编码mp4.

三、MP4读取sample猜测

首先想,在拖动进度条的时候,mp4播放器怎么找到对应的sample,并且开始播放的。

1,先要将 time转换成sample Index。  这里需要用 stts box.

2,sample Index -> 找到所在的chunk Index。 这里是 stsc box

3,通过chunk Index找到 对应 chunk 在整个文件中的 offset。 stco box

4,找到 目标 sample 在当前 chunk中的offset。  stsz box

5,判断当前 sample 是不是 sync sample.          stss box

Over, 感觉如果仅仅是播放视屏,这样就够了。

附录:mdat之后的所有二进制。

00 00 04 30 6d 6f 6f 76/00 00 00 6c 6d 76 68 64 00 00 00 00 c7 62 f5 92 c7 62 f5 96 00 00 03 e8
00 00 0e d8 00 01 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02/00 00 00 18 69 6f 64 73 00 00 00 00
10 80 80 80 07 00 4f ff ff ff 0f ff/00 00 03 a4 74 72 61 6b 00 00 00 5c 74 6b 68 64 00 00 00 01
c7 62 f5 92 c7 62 f5 96 00 00 00 01 00 00 00 00 00 00 0e d8 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00
00 00 00 00 40 00 00 00 05 00 00 00 02 d0 00 00/00 00 03 40 6d 64 69 61 00 00 00 20 6d 64 68 64
00 00 00 00 c7 62 f5 92 c7 62 f5 96 00 00 03 e8 00 00 0e d8 55 c4 00 00/00 00 00 21 68 64 6c 72
00 00 00 00 00 00 00 00 76 69 64 65 00 00 00 00 00 00 00 00 00 00 00 00 00/00 00 02 f7 6d 69 6e 66 //本行多一个字节
00 00 00 14 76 6d 68 64 00 00 00 01 00 00 00 00 00 00 00 00/00 00 00 24 64 69 6e 66 00 00 00 1c
64 72 65 66 00 00 00 00 00 00 00 01/00 00 00 0c 75 72 6c 20 00 00 00 01/00 00 02 b7 73 74 62 6c
00 00 00 87 73 74 73 64 00 00 00 00 00 00 00 01 00 00 00 77 61 76 63 31 00 00 00 00 00 00 00 01
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05 00 02 d0 00 48 00 00 00 48 00 00 00 00 00 00 
00 01 0e 4a 56 54 2f 41 56 43 20 43 6f 64 69 6e 67 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 18 ff ff 00 00 00 21 61 76 63 43 01 4d 00 1f ff e1 00 0a 67 4d 00 1f 96 56 02 80 2d 88
01 00 04 68 ea 43 c8 00 00 00 20 73 74 74 73 00 00 00 00 00 00 00 02 00 00 00 02 00 00 00 00   //本行少一个字节
00 00 00 5f 00 00 00 28 00 00 01 98 73 74 73 7a 00 00 00 00 00 00 00 00 00 00 00 61 00 00 00 0e
00 00 00 08 00 01 fc d6 00 00 18 27 00 00 0c 1e 00 00 16 b7 00 00 25 82 00 00 48 86 00 00 39 19
00 00 4a 8b 00 00 48 b4 00 00 47 b2 00 00 61 ab 00 00 39 87 00 00 4b c8 00 00 4a 2e 00 00 49 d6
00 00 67 d3 00 00 3b 3b 00 00 4d 67 00 00 4c 41 00 00 4a 0b 00 00 6b 92 00 00 3b 2a 00 00 36 c2
00 00 2a 41 00 00 35 32 00 00 6c b0 00 00 4f 40 00 00 4b d7 00 00 49 f6 00 00 48 f2 00 00 6e 06
00 00 4f a1 00 00 4b 83 00 00 4a 6c 00 00 4a 4e 00 00 6c f4 00 00 50 2e 00 00 4b aa 00 00 49 cb
00 00 48 4f 00 00 ad dd 00 00 3e 4b 00 00 4f 58 00 00 4d 57 00 00 4b b4 00 00 59 ec 00 00 38 e4
00 00 4b 9a 00 00 37 7a 00 00 4c 77 00 00 5f 8a 00 00 4e 8d 00 00 4c eb 00 00 4b 69 00 00 4c 5d
00 00 69 ba 00 00 51 7a 00 00 4d ee 00 00 4d 17 00 00 4b 46 00 00 67 2f 00 00 51 e9 00 00 4f 90
00 00 4c fa 00 00 4d 88 00 00 5f b5 00 00 53 1d 00 00 53 7a 00 00 52 a2 00 00 51 24 00 00 64 ec
00 00 50 55 00 00 39 ab 00 00 4d f7 00 00 39 b3 00 00 62 90 00 00 51 d4 00 00 52 44 00 00 4d 12
00 00 4c 8a 00 00 a4 8d 00 00 40 f1 00 00 50 ff 00 00 4e 44 00 00 4e 4d 00 00 62 f1 00 00 53 9e
00 00 51 ec 00 00 4e 8e 00 00 4e 60 00 00 61 6e 00 00 4f 3f 00 00 4c 8e 00 00 4b f5 00 00 4c 36
00 00 00 34 73 74 73 63 00 00 00 00 00 00 00 03 00 00 00 01 00 00 00 1b 00 00 00 01 00 00 00 02
00 00 00 19 00 00 00 01 00 00 00 04 00 00 00 14 00 00 00 01 00 00 00 20 73 74 63 6f 00 00 00 00
00 00 00 04 00 00 00 a8 00 07 f9 52 00 10 03 b1 00 17 fb ca 00 00 00 1c 73 74 73 73 00 00 00 00
00 00 00 03 00 00 00 03 00 00 00 2b 00 00 00 53 00 00 00 88 66 72 65 65 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

你可能感兴趣的:(linux_drv)