- 1 #include <stdio.h>
- 2 #include <stdlib.h>
- 3 #include <string.h>
- 4 #include <arpa/inet.h>
- 5
- 6 #define TAB44 " "
- 7 #define PRINTF_DEBUG
- 8
- 9 #define MAX_SIGNATURE_LEN 3
- 10 #define MAX_PRE_TAG_SIZE_LEN 4
- 11 #define MIN_FLV_HEADER_LEN 9
- 12 #define MAX_TAG_HEADER_LEN 11
- 13 #define MAX_PARSE_TAG_NUM 15
- 14 #define MAX_AMF_STR_SIZE 255
- 15
- 16 /************************************************************************************************************
- 17 ** flv header: 记录了flv的类型, 版本等信息, 是flv的开头, 一般都差不多, 占9bytes
- 18 **
- 19 -------------------------------------------------------------------------------------------------------------
- 20 ** 字段名称 | 长度(bytes) | 有关描述
- 21 -------------------------------------------------------------------------------------------------------------
- 22 ** signature | 3 | 文件标识, 总是为"FLV", 0x46 0x4c 0x56
- 23 ** version | 1 | 版本(目前为0x01)
- 24 ** flag | 3 | 文件的标志位说明. 前5位保留, 必须为0;
- 25 第6位为音频Tag: 1表示有音频; 第七位保留, 为0; 第8位为视频Tag: 1表示有视频
- 26 ** headersize | 4 | 整个header的长度, 一般为9(版本为0x01时); 大于9表示下面还有扩展信息
- 27 ************************************************************************************************************/
- 28 /*
- 29 1. unsigned char reserved5: 5, flags_audio: 1, reserved1: 1, flags_video: 1;
- 30 2. unsigned char : 5, flags_audio: 1, : 1, flags_video: 1; (无名说明无法使用, 仅占位)
- 31 3. 下面结构体位域的另外两种写法.
- 32 */
- 33 typedef struct t_flv_header
- 34 {
- 35 unsigned char signature[MAX_SIGNATURE_LEN+1];
- 36 unsigned char version;
- 37 unsigned char : 5;
- 38 unsigned char flags_audio: 1;
- 39 unsigned char : 1;
- 40 unsigned char flags_video: 1;
- 41
- 42 int headersize;
- 43 } T_FLV_HEADER;
- 44
- 45 /************************************************************************************************************
- 46 ** tag header
- 47 **
- 48 -------------------------------------------------------------------------------------------------------------
- 49 ** 字段名称 | 长度(bytes) | 有关描述
- 50 -------------------------------------------------------------------------------------------------------------
- 51 ** type | 1 | 数据类型, (0x12)为脚本类型; (0x08)为音频类型; (0x09)为视频类型
- 52 ** data_size | 3 | 数据区长度
- 53 ** timestamp | 3 | 时间戳, 类型为(0x12)的tag时间戳一直为0, (0xFFFFFF)可以表示长度为4小时, 单位为毫秒.
- 54 ** timestamp_extended | 1 | 将时间戳扩展为4bytes, 代表高8位, 一般都为0, 长度为4小时的flv一般很少见了
- 55 ** streamid | 3 | 总为0
- 56 ************************************************************************************************************/
- 57 typedef struct t_flv_tag_header
- 58 {
- 59 int type;
- 60 int data_size;
- 61 int timestamp;
- 62 int timestamp_extended;
- 63 int streamid;
- 64 } T_FLV_TAG_HEADER;
- 65
- 66 /************************************************************************************************************
- 67 ** video tag header
- 68 **
- 69 -------------------------------------------------------------------------------------------------------------
- 70 ** 字段名称 | 长度(bytes) | 有关描述
- 71 -------------------------------------------------------------------------------------------------------------
- 72 ** FreameType | 4(bits) | FrameType为数据类型, 1为关键帧, 2为非关键帧, 3为h263的非关键帧,
- 73 4为服务器生成关键帧, 5为视频信息或命令帧.
- 74 ** CodecId | 4(bits) | CodecID为包装类型, 1为JPEG, 2为H263, 3为Screen video,
- 75 4为On2 VP6, 5为On2 VP6, 6为Screen videoversion 2, 7为AVC
- 76
- 77 CodecID=2, 为H263VideoPacket;
- 78 CodecID=3, 为ScreenVideopacket;
- 79 CodecID=4, 为VP6FLVVideoPacket;
- 80 CodecID=5, 为VP6FLVAlphaVideoPacket;
- 81 CodecID=6, 为ScreenV2VideoPacket;
- 82 CodecID=7, 为AVCVideoPacket.
- 83 ************************************************************************************************************/
- 84 typedef struct t_flv_tag_video_header
- 85 {
- 86 unsigned char freameType:4, codecId:4;
- 87 } T_FLV_TAG_VIDEO_HEADER;
- 88
- 89 /************************************************************************************************************
- 90 ** AVCDecoderConfigurationRecord
- 91 **
- 92 -------------------------------------------------------------------------------------------------------------
- 93 ** 字段名称 | 长度(bytes) | 有关描述
- 94 -------------------------------------------------------------------------------------------------------------
- 95 ** configurationVersion | 1 | 配置版本占用8位, 一定为1
- 96 ** AVCProfileIndication | 1 | profile_idc占用8位, 从H.264标准SPS第一个字段profile_idc拷贝而来, 指明所用profile
- 97 ** profile_compatibility | 1 | 占用8位, 从H.264标准SPS拷贝的冗余字
- 98 ** AVCLevelIndication | 1 | level_idc占用8位, 从H.264标准SPS第一个字段level_idc拷贝而来, 指明所用 level
- 99 ** reserved | 6b | 保留位占6位, 值一定为'111111'
- 100 ** lengthSizeMinusOne | 2b | 占用2位, 表示NAL单元头的长度, 0表示1字节, 1表示2字节, 2表示3字节, 3表示4字节
- 101 ** reserved | 3b | 保留位占3位, 值一定为'111'
- 102 ** numOfSPS | 5b | numOfSequenceParameterSets占用5位, 表示当前SPS的个数
- 103 ** SPSLength | 2 | sequenceParameterSetLength占用16位, SPS占用的长度
- 104 ** SPSData | * |
- 105 ** numOfPPS | 5b | numOfPictureParameterSets占用8位, 表示当前PPS的个数
- 106 ** PPSLength | 2 | pictureParameterSetLength占用16位, PPS占用的长度
- 107 ** PPSData | * | numOfPictureParameterSets占用8位, 表示当前PPS的个数
- 108
- 109 AVCProfileIndication, profile_compatibility, AVCLevelIndication就是拷贝SPS的前3个字节
- 110 ************************************************************************************************************/
- 111 typedef struct t_flv_tag_avc_dec_cfg
- 112 {
- 113 unsigned char configurationVersion;
- 114 unsigned char AVCProfileIndication;
- 115 unsigned char profile_compatibility;
- 116 unsigned char AVCLevelIndication;
- 117 unsigned char :6, lengthSizeMinusOne:2;
- 118
- 119 unsigned char :3, numOfSequenceParameterSets:5;
- 120 unsigned short spsLen;
- 121 unsigned char *spsData;
- 122
- 123 unsigned char numOfPictureParameterSets;
- 124 unsigned short ppsLen;
- 125 unsigned char *ppsData;
- 126 } T_FLV_TAG_AVC_DEC_CFG;
- 127
- 128 /************************************************************************************************************
- 129 ** avc video packet header
- 130 **
- 131 -------------------------------------------------------------------------------------------------------------
- 132 ** 字段名称 | 长度(bytes) | 有关描述
- 133 -------------------------------------------------------------------------------------------------------------
- 134 ** AVCPacketType占用1字节 | 1 |
- 135 ** CompositionTime | 3 |
- 136
- 137 AVCVideoPacket同样包括Packet Header和Packet Body两部分:
- 138 Packet Header:
- 139 AVCPacketType占用1字节, 仅在AVC时有此字段
- 140 0, AVC sequence header (SPS、PPS信息等)
- 141 1, AVC NALU
- 142 2, AVC end of sequence (lower level NALU sequence ender is not required or supported)
- 143
- 144 CompositionTime占用24位, 相对时间戳, 如果AVCPacketType=0x01为相对时间戳; 其它, 均为0;
- 145 该值表示当前帧的显示时间, tag的时间为解码时间, 显示时间等于 解码时间+CompositionTime.
- 146 ************************************************************************************************************/
- 147 typedef struct t_flv_tag_avc_video_packet
- 148 {
- 149 unsigned char avcPacketType;
- 150
- 151 int compositionTime;
- 152
- 153 union videoPacket
- 154 {
- 155 T_FLV_TAG_AVC_DEC_CFG avcDecCfg;
- 156 } vp;
- 157 } T_FLV_TAG_AVC_VIDEO_PACKET;
- 158
- 159 typedef struct t_flv_tag_audio_header
- 160 {
- 161 unsigned char soundFormat:4, soundRate:2, soundSize:1, soundType:1;
- 162 } T_FLV_TAG_AUDIO_HEADER;
- 163
- 164 typedef struct t_flv_tag_aac_spec_cfg
- 165 {
- 166 unsigned char audioObjectType:5;
- 167 unsigned char samplingFreqIndex:4, channelCfg:2;
- 168 } T_FLV_TAG_AAC_SPEC_CFG;
- 169
- 170 typedef struct t_flv_tag_aac_audio_packet
- 171 {
- 172 unsigned char aacPacketType;
- 173
- 174 union audioPacket
- 175 {
- 176 T_FLV_TAG_AAC_SPEC_CFG aacSpecCfg;
- 177 } ap;
- 178 } T_FLV_TAG_AAC_AUDIO_PACKET;
- 179
- 180 typedef struct t_flv_tag
- 181 {
- 182 } T_FLV_TAG;
- 183
- 184 /* 小端转double */
- 185 static double dealAmfNumber(unsigned char *amfNum)
- 186 {
- 187 double d = 0;
- 188
- 189 unsigned char *dp = (unsigned char *)&d;
- 190
- 191 dp[0] = amfNum[7];
- 192 dp[1] = amfNum[6];
- 193 dp[2] = amfNum[5];
- 194 dp[3] = amfNum[4];
- 195 dp[4] = amfNum[3];
- 196 dp[5] = amfNum[2];
- 197 dp[6] = amfNum[1];
- 198 dp[7] = amfNum[0];
- 199
- 200 return d;
- 201 }
- 202
- 203 /*
- 204 1. DealHeader(const unsigned char* headerData);
- 205 这样定义会报warning: assignment discards 'const' qualifier from pointer target type,
- 206 大意是指针丢掉"const"限定符.
- 207 2. 原因是: data = headerData; 这一句存在丢掉的风险(可通过给*data赋予不同的值, 使得headerData的数据也被修改, 失去const的作用)
- 208 3. const int *p; //这种情况表示*p是const无法进行修改, 而p是可以进行修改的;
- 209 int* const p; //这种情况表示p是const无法进行修改, 而*p是可以进行修改的;
- 210 const int* const p; //这种情况表示*p与p都无法进行修改.
- 211 */
- 212 static void DealFlvHeader(unsigned char* const headerData)
- 213 {
- 214 unsigned char *data = NULL;
- 215
- 216 T_FLV_HEADER flvHeader = {0};
- 217
- 218 data = headerData;
- 219
- 220 memset(&flvHeader, 0x0, sizeof(T_FLV_HEADER));
- 221
- 222 memcpy(flvHeader.signature, data, MAX_SIGNATURE_LEN);
- 223
- 224 flvHeader.signature[MAX_SIGNATURE_LEN] = '\0';
- 225
- 226 data += MAX_SIGNATURE_LEN;
- 227
- 228 flvHeader.version = data[0];
- 229
- 230 data += 1;
- 231
- 232 flvHeader.flags_audio = data[0] >> 2 & 0x1;
- 233 flvHeader.flags_video = data[0] & 0x1;
- 234
- 235 data += 1;
- 236
- 237 flvHeader.headersize = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];
- 238
- 239 if (0x1 != flvHeader.version)
- 240 {
- 241 printf("version is not 1, todo...\n");
- 242 }
- 243
- 244 #ifdef PRINTF_DEBUG
- 245 printf("+FLV Header\n");
- 246 printf("%ssignature: %s, version: %d, flags_audio: %d, flags_video: %d, headersize: %d\n",
- 247 TAB44, flvHeader.signature, flvHeader.version, flvHeader.flags_audio, flvHeader.flags_video, flvHeader.headersize);
- 248 #endif
- 249 }
- 250
- 251 static void DealTagHeader(unsigned char* const headerData, T_FLV_TAG_HEADER *tagHeader)
- 252 {
- 253 static int videoTagNum = 0;
- 254 static int audioTagNum = 0;
- 255
- 256 unsigned char *data = NULL;
- 257
- 258 T_FLV_TAG_HEADER header = {0};
- 259
- 260 data = headerData;
- 261
- 262 memset(&header, 0x0, sizeof(T_FLV_TAG_HEADER));
- 263
- 264 header.type = data[0];
- 265
- 266 data += 1;
- 267
- 268 header.data_size = (data[0] << 16) | (data[1] << 8) | data[2];
- 269
- 270 data += 3;
- 271
- 272 header.timestamp = (data[0] << 16) | (data[1] << 8) | data[2];
- 273
- 274 data += 3;
- 275
- 276 header.timestamp_extended = data[0];
- 277
- 278 data += 1;
- 279
- 280 header.streamid = (data[0] << 16) | (data[1] << 8) | data[2];
- 281
- 282 memcpy(tagHeader, &header, sizeof(T_FLV_TAG_HEADER));
- 283
- 284 #ifdef PRINTF_DEBUG
- 285 switch (tagHeader->type)
- 286 {
- 287 case 0x12:
- 288 printf("%s+Script Tag\n", TAB44);
- 289
- 290 break;
- 291
- 292 case 0x9:
- 293 videoTagNum++;
- 294
- 295 printf("%s+Video Tag[%d]\n", TAB44, videoTagNum);
- 296
- 297 break;
- 298
- 299 case 0x8:
- 300 audioTagNum++;
- 301
- 302 printf("%s+Audio Tag[%d]\n", TAB44, audioTagNum);
- 303
- 304 break;
- 305
- 306 default:
- 307 break;
- 308 }
- 309
- 310 printf("%s%s+Tag Header\n", TAB44, TAB44);
- 311 printf("%s%s%stype: %d, data_size: %d, timestamp: %d, timestamp_extended: %d, streamid: %d\n",
- 312 TAB44, TAB44, TAB44, tagHeader->type, tagHeader->data_size, tagHeader->timestamp, tagHeader->timestamp_extended, tagHeader->streamid);
- 313 #endif
- 314 }
- 315
- 316 /*
- 317 第一个AMF包:
- 318 第1个字节表示AMF包类型, 一般总是0x02, 表示字符串, 其他值表示意义请查阅文档.
- 319 第2-3个字节为UI16类型值, 表示字符串的长度, 一般总是0x000A("onMetaData"长度).
- 320 后面字节为字符串数据, 一般总为"onMetaData".
- 321
- 322 第二个AMF包:
- 323 第1个字节表示AMF包类型, 一般总是0x08, 表示数组.
- 324 第2-5个字节为UI32类型值, 表示数组元素的个数.
- 325 后面即为各数组元素的封装, 数组元素为元素名称和值组成的对. 表示方法如下:
- 326 第1-2个字节表示元素名称的长度, 假设为L. 后面跟着为长度为L的字符串. 第L+3个字节表示元素值的类型.
- 327 后面跟着为对应值, 占用字节数取决于值的类型.
- 328
- 329 0 = Number type (double, 8)
- 330 1 = Boolean type
- 331 2 = String type
- 332 3 = Object type
- 333 4 = MovieClip type
- 334 5 = Null type
- 335 6 = Undefined type
- 336 7 = Reference type
- 337 8 = ECMA array type
- 338 10 = Strict array type
- 339 11 = Date type
- 340 12 = Long string type
- 341
- 342 1. 不要频繁的malloc小内存(内存碎片, 代价);
- 343 2. 如该函数中arrayKey, arrayValue, amfStrData设置成指针, 然后malloc就有问题(字符串后残留上述三个最大长度中的字符);
- 344 3. 可能的解释: 当用free释放的你用malloc分配的存储空间, 释放的存储空间并没有从进程的地址空间中删除, 而是保留在可用存储区池中,
- 345 当再次用malloc时只要可用存储区池中有足够的地址空间, 都不会再向内可申请内存了, 而是在可用存储区池中分配了.
- 346
- 347 实际分析时: 8的数组后还有一串 00 00 09, 暂时不清楚, 先跳过if (tagDataSize <= 3)
- 348 */
- 349 static void DealScriptTagData(unsigned char* const tagData, unsigned int tagDataSize)
- 350 {
- 351 int i = 0;
- 352 int amfType = 0;
- 353 int amfIndex = 0;
- 354 int valueType = 0;
- 355 int valueSize = 0;
- 356 int keySize = 0;
- 357 int arrayCount = 0;
- 358 int amfStringSize = 0;
- 359
- 360 double amfNum = 0;
- 361
- 362 unsigned char amfStr[MAX_AMF_STR_SIZE+1] = {0};
- 363
- 364 unsigned char *data = NULL;
- 365
- 366 data = tagData;
- 367
- 368 for (;;)
- 369 {
- 370 if (tagDataSize <= 3)
- 371 {
- 372 break;
- 373 }
- 374
- 375 amfType = data[0];
- 376
- 377 amfIndex += 1;
- 378
- 379 data += 1;
- 380 tagDataSize -= 1;
- 381
- 382 #ifdef PRINTF_DEBUG
- 383 printf("%s%s%sAMF%d type: %d\n", TAB44, TAB44, TAB44, amfIndex, amfType);
- 384 #endif
- 385
- 386 switch (amfType)
- 387 {
- 388 case 2:
- 389 amfStringSize = (data[0] << 8) | data[1];
- 390
- 391 #ifdef PRINTF_DEBUG
- 392 printf("%s%s%sAMF%d String size: %d\n", TAB44, TAB44, TAB44, amfIndex, amfStringSize);
- 393 #endif
- 394
- 395 data += 2;
- 396 tagDataSize -= 2;
- 397
- 398 memset(amfStr, 0x0, sizeof(amfStr));
- 399
- 400 memcpy(amfStr, data, amfStringSize);
- 401
- 402 amfStr[amfStringSize] = '\0';
- 403
- 404 #ifdef PRINTF_DEBUG
- 405 printf("%s%s%sAMF%d String: %s\n", TAB44, TAB44, TAB44, amfIndex, amfStr);
- 406 #endif
- 407
- 408 data += amfStringSize;
- 409 tagDataSize -= amfStringSize;
- 410
- 411 break;
- 412
- 413 case 8:
- 414 arrayCount = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];
- 415
- 416 #ifdef PRINTF_DEBUG
- 417 printf("%s%s%sAMF%d Metadata count: %d\n", TAB44, TAB44, TAB44, amfIndex, arrayCount);
- 418 printf("%s%s%s+Metadata\n", TAB44, TAB44, TAB44);
- 419 #endif
- 420
- 421 data += 4;
- 422 tagDataSize -= 4;
- 423
- 424 for (i=0; i<arrayCount; i++)
- 425 {
- 426 keySize = (data[0] << 8) | data[1];
- 427
- 428 data += 2;
- 429 tagDataSize -= 2;
- 430
- 431 memset(amfStr, 0x0, sizeof(amfStr));
- 432
- 433 memcpy(amfStr, data, keySize);
- 434
- 435 amfStr[keySize] = '\0';
- 436
- 437 #ifdef PRINTF_DEBUG
- 438 printf("%s%s%s%s%s: ", TAB44, TAB44, TAB44, TAB44, amfStr);
- 439 #endif
- 440
- 441 data += keySize;
- 442 tagDataSize -= keySize;
- 443
- 444 valueType = data[0];
- 445
- 446 data += 1;
- 447 tagDataSize -= 1;
- 448
- 449 if (0 == valueType)
- 450 {
- 451 amfNum = dealAmfNumber(data);
- 452 #ifdef PRINTF_DEBUG
- 453 printf("%lf\n", amfNum);
- 454 #endif
- 455
- 456 data += 8;
- 457 tagDataSize -= 8;
- 458 }
- 459 else if (1 == valueType)
- 460 {
- 461 #ifdef PRINTF_DEBUG
- 462 printf("%d\n", data[0]);
- 463 #endif
- 464 data += 1;
- 465 tagDataSize -= 1;
- 466 }
- 467 else if (2 == valueType)
- 468 {
- 469 valueSize = (data[0] << 8) | data[1];
- 470
- 471 data += 2;
- 472 tagDataSize -= 2;
- 473
- 474 memset(amfStr, 0x0, sizeof(amfStr));
- 475
- 476 memcpy(amfStr, data, valueSize);
- 477
- 478 amfStr[valueSize] = '\0';
- 479
- 480 #ifdef PRINTF_DEBUG
- 481 printf("%s\n", amfStr);
- 482 #endif
- 483
- 484 data += valueSize;
- 485 tagDataSize -= valueSize;
- 486 }
- 487 else
- 488 {
- 489 //printf("now can not parse value type: %d\n", valueType);
- 490
- 491 return;
- 492 }
- 493 }
- 494
- 495 break;
- 496
- 497 default:
- 498 break;
- 499 }
- 500 }
- 501 }
- 502
- 503 /*
- 504 Video Header = | FrameType(4) | CodecID(4) |
- 505 VideoData = | FrameType(4) | CodecID(4) | VideoData(n) |
- 506 */
- 507 static void DealVideoTagData(unsigned char* const tagData)
- 508 {
- 509 unsigned char *data = NULL;
- 510
- 511 data = tagData;
- 512
- 513 T_FLV_TAG_VIDEO_HEADER vTagHeader = {0};
- 514 T_FLV_TAG_AVC_VIDEO_PACKET avcVideoPacket = {0};
- 515
- 516 memset(&vTagHeader, 0x0, sizeof(vTagHeader));
- 517
- 518 vTagHeader.freameType = data[0] >> 4 & 0xf;
- 519 vTagHeader.codecId = data[0] & 0xf;
- 520
- 521 data++;
- 522
- 523 #ifdef PRINTF_DEBUG
- 524 printf("%s%s%sFrameType: %d\n", TAB44, TAB44, TAB44, vTagHeader.freameType);
- 525 printf("%s%s%sCodecId: %d\n", TAB44, TAB44, TAB44, vTagHeader.codecId);
- 526 #endif
- 527
- 528 /* now just avc(h264) */
- 529 switch (vTagHeader.codecId)
- 530 {
- 531 case 0x07:
- 532 memset(&avcVideoPacket, 0x0, sizeof(avcVideoPacket));
- 533
- 534 avcVideoPacket.avcPacketType = data[0];
- 535 avcVideoPacket.compositionTime = (data[1] << 16) | (data[2] << 8) | data[3];
- 536
- 537 data += 4;
- 538
- 539 if (0 == avcVideoPacket.avcPacketType)
- 540 {
- 541 #ifdef PRINTF_DEBUG
- 542 printf("%s%s%s+AVCVideoPacket\n", TAB44, TAB44, TAB44);
- 543 printf("%s%s%s%sAVCPacketType: %d\n", TAB44, TAB44, TAB44, TAB44, avcVideoPacket.avcPacketType);
- 544 printf("%s%s%s%sCompositionTime Offset: %d\n", TAB44, TAB44, TAB44, TAB44, avcVideoPacket.compositionTime);
- 545 #endif
- 546 printf("%s%s%s%s+AVCDecoderConfigurationRecord\n", TAB44, TAB44, TAB44, TAB44);
- 547
- 548 avcVideoPacket.vp.avcDecCfg.configurationVersion = data[0];
- 549 avcVideoPacket.vp.avcDecCfg.AVCProfileIndication = data[1];
- 550 avcVideoPacket.vp.avcDecCfg.profile_compatibility = data[2];
- 551 avcVideoPacket.vp.avcDecCfg.AVCLevelIndication = data[3];
- 552 avcVideoPacket.vp.avcDecCfg.lengthSizeMinusOne = data[4] & 0x3;
- 553 avcVideoPacket.vp.avcDecCfg.numOfSequenceParameterSets = data[5] & 0x1f;
- 554 avcVideoPacket.vp.avcDecCfg.spsLen = (data[6] << 8) | data[7];
- 555
- 556 // todo, parse sps
- 557
- 558 data += (8+avcVideoPacket.vp.avcDecCfg.spsLen);
- 559
- 560 avcVideoPacket.vp.avcDecCfg.numOfPictureParameterSets = data[0];
- 561 avcVideoPacket.vp.avcDecCfg.ppsLen = (data[1] << 8) | data[2];
- 562
- 563 // todo, parse pps
- 564
- 565 #ifdef PRINTF_DEBUG
- 566 printf("%s%s%s%s%sconfigurationVersion: %d\n", TAB44, TAB44, TAB44, TAB44, TAB44, avcVideoPacket.vp.avcDecCfg.configurationVersion);
- 567 printf("%s%s%s%s%sAVCProfileIndication: %d\n", TAB44, TAB44, TAB44, TAB44, TAB44, avcVideoPacket.vp.avcDecCfg.AVCProfileIndication);
- 568 printf("%s%s%s%s%sprofile_compatibility: %d\n", TAB44, TAB44, TAB44, TAB44, TAB44, avcVideoPacket.vp.avcDecCfg.profile_compatibility);
- 569 printf("%s%s%s%s%sAVCLevelIndication: %d\n", TAB44, TAB44, TAB44, TAB44, TAB44, avcVideoPacket.vp.avcDecCfg.AVCLevelIndication);
- 570 printf("%s%s%s%s%slengthSizeMinusOne: %d\n", TAB44, TAB44, TAB44, TAB44, TAB44, avcVideoPacket.vp.avcDecCfg.lengthSizeMinusOne);
- 571 printf("%s%s%s%s%snumOfSequenceParameterSets: %d\n", TAB44, TAB44, TAB44, TAB44, TAB44, avcVideoPacket.vp.avcDecCfg.numOfSequenceParameterSets);
- 572 printf("%s%s%s%s%ssequenceParameterSetLength: %d\n", TAB44, TAB44, TAB44, TAB44, TAB44, avcVideoPacket.vp.avcDecCfg.spsLen);
- 573 printf("%s%s%s%s%snumOfPictureParameterSets: %d\n", TAB44, TAB44, TAB44, TAB44, TAB44, avcVideoPacket.vp.avcDecCfg.numOfPictureParameterSets);
- 574 printf("%s%s%s%s%spictureParameterSetLength: %d\n", TAB44, TAB44, TAB44, TAB44, TAB44, avcVideoPacket.vp.avcDecCfg.ppsLen);
- 575 #endif
- 576 }
- 577 else
- 578 {
- 579 #ifdef PRINTF_DEBUG
- 580 printf("%s%s%s+Video Data\n", TAB44, TAB44, TAB44);
- 581 printf("%s%s%s%sAVCPacketType: %d\n", TAB44, TAB44, TAB44, TAB44, avcVideoPacket.avcPacketType);
- 582 printf("%s%s%s%sCompositionTime Offset: %d\n", TAB44, TAB44, TAB44, TAB44, avcVideoPacket.compositionTime);
- 583 printf("%s%s%s%sData\n", TAB44, TAB44, TAB44, TAB44);
- 584 #endif
- 585 }
- 586
- 587 break;
- 588
- 589 default:
- 590 break;
- 591 }
- 592 }
- 593
- 594 static void DealAudioTagData(unsigned char* const tagData)
- 595 {
- 596 unsigned char *data = NULL;
- 597
- 598 data = tagData;
- 599
- 600 T_FLV_TAG_AUDIO_HEADER audioHeader = {0};
- 601 T_FLV_TAG_AAC_AUDIO_PACKET aPacket = {0};
- 602
- 603 memset(&audioHeader, 0x0, sizeof(T_FLV_TAG_AUDIO_HEADER));
- 604
- 605 audioHeader.soundFormat = (data[0] >> 4) & 0xf;
- 606 audioHeader.soundRate = (data[0] >> 2) & 0x3;
- 607 audioHeader.soundSize = (data[0] >> 1) & 0x1;
- 608 audioHeader.soundType = data[0] & 0x1;
- 609
- 610 #ifdef PRINTF_DEBUG
- 611 printf("%s%s%sSoundFormat: %d\n", TAB44, TAB44, TAB44, audioHeader.soundFormat);
- 612
- 613 switch (audioHeader.soundRate)
- 614 {
- 615 case 0:
- 616 printf("%s%s%sSoundRate: 5.5-KHz\n", TAB44, TAB44, TAB44);
- 617 break;
- 618
- 619 case 1:
- 620 printf("%s%s%sSoundRate: 11-KHz\n", TAB44, TAB44, TAB44);
- 621 break;
- 622
- 623 case 2:
- 624 printf("%s%s%sSoundRate: 22-KHz\n", TAB44, TAB44, TAB44);
- 625 break;
- 626
- 627 case 3:
- 628 printf("%s%s%sSoundRate: 44-KHz\n", TAB44, TAB44, TAB44);
- 629 break;
- 630
- 631 default:
- 632 printf("%s%s%sSoundRate: %d\n", TAB44, TAB44, TAB44, audioHeader.soundRate);
- 633 }
- 634
- 635 switch (audioHeader.soundSize)
- 636 {
- 637 case 0:
- 638 printf("%s%s%sSoundSize: snd8bit\n", TAB44, TAB44, TAB44);
- 639 break;
- 640
- 641 case 1:
- 642 printf("%s%s%sSoundSize: snd16bit\n", TAB44, TAB44, TAB44);
- 643 break;
- 644
- 645 default:
- 646 printf("%s%s%sSoundSize: %d\n", TAB44, TAB44, TAB44, audioHeader.soundSize);
- 647 }
- 648
- 649 switch (audioHeader.soundType)
- 650 {
- 651 case 0:
- 652 printf("%s%s%sSoundType: sndMono\n", TAB44, TAB44, TAB44);
- 653 break;
- 654
- 655 case 1:
- 656 printf("%s%s%sSoundType: sndStereo\n", TAB44, TAB44, TAB44);
- 657 break;
- 658
- 659 default:
- 660 printf("%s%s%sSoundSize: %d\n", TAB44, TAB44, TAB44, audioHeader.soundSize);
- 661 }
- 662 #endif
- 663
- 664 data++;
- 665
- 666 /* now just for aac */
- 667 switch (audioHeader.soundFormat)
- 668 {
- 669 case 0xa:
- 670 memset(&aPacket, 0x0, sizeof(T_FLV_TAG_AAC_AUDIO_PACKET));
- 671
- 672 aPacket.aacPacketType = data[0];
- 673
- 674 if (0 == aPacket.aacPacketType)
- 675 {
- 676 #ifdef PRINTF_DEBUG
- 677 printf("%s%s%s+AACAudioData\n", TAB44, TAB44, TAB44);
- 678 printf("%s%s%s%sAACPacketType: %d\n", TAB44, TAB44, TAB44, TAB44, aPacket.aacPacketType);
- 679 #endif
- 680 aPacket.ap.aacSpecCfg.audioObjectType = (data[1] >> 3) & 0x1f;
- 681 aPacket.ap.aacSpecCfg.samplingFreqIndex = ((data[1] & 0x7) << 1) | ((data[2] >> 7) & 0x1);
- 682 aPacket.ap.aacSpecCfg.channelCfg = (data[2] >> 3) & 0xf;
- 683
- 684 #ifdef PRINTF_DEBUG
- 685 printf("%s%s%s%s+AudioSpecificConfig\n", TAB44, TAB44, TAB44, TAB44);
- 686
- 687 printf("%s%s%s%s%sAudioObjectType: %d\n", TAB44, TAB44, TAB44, TAB44, TAB44, aPacket.ap.aacSpecCfg.audioObjectType);
- 688 printf("%s%s%s%s%sSamplingFrequencyIndex: %d\n", TAB44, TAB44, TAB44, TAB44, TAB44, aPacket.ap.aacSpecCfg.samplingFreqIndex);
- 689 printf("%s%s%s%s%sChannelConfiguration: %d\n", TAB44, TAB44, TAB44, TAB44, TAB44, aPacket.ap.aacSpecCfg.channelCfg);
- 690 #endif
- 691 }
- 692 else
- 693 {
- 694 #ifdef PRINTF_DEBUG
- 695 printf("%s%s%s+AACAudioData\n", TAB44, TAB44, TAB44);
- 696 printf("%s%s%s%sAACPacketType: %d\n", TAB44, TAB44, TAB44, TAB44, aPacket.aacPacketType);
- 697 printf("%s%s%s%sData(Raw AAC frame data)\n", TAB44, TAB44, TAB44, TAB44);
- 698 #endif
- 699 }
- 700
- 701 break;
- 702
- 703 default:
- 704 break;
- 705 }
- 706 }
- 707
- 708 static void DealTagData(unsigned char* const tagData, const int tagType, const unsigned int tagSize)
- 709 {
- 710 #ifdef PRINTF_DEBUG
- 711 printf("%s%s%s\n", TAB44, TAB44, "+Tag Data");
- 712 #endif
- 713
- 714 switch (tagType)
- 715 {
- 716 case 0x12:
- 717 DealScriptTagData(tagData, tagSize);
- 718
- 719 break;
- 720
- 721 case 0x9:
- 722 DealVideoTagData(tagData);
- 723
- 724 break;
- 725
- 726 case 0x8:
- 727 DealAudioTagData(tagData);
- 728
- 729 break;
- 730
- 731 default:
- 732 break;
- 733 }
- 734 }
- 735
- 736 int main(int argc, char *argv[])
- 737 {
- 738 int dataLen = 0;
- 739 int previousTagSize = 0;
- 740
- 741 FILE *fp = NULL;
- 742
- 743 unsigned char *tagData = NULL;
- 744
- 745 unsigned char flvHeaderData[MIN_FLV_HEADER_LEN+1] = {0};
- 746 unsigned char preTagSizeData[MAX_PRE_TAG_SIZE_LEN+1] = {0};
- 747 unsigned char tagHeaderData[MAX_TAG_HEADER_LEN+1] = {0};
- 748
- 749 T_FLV_TAG_HEADER tagHeader = {0};
- 750
- 751 if (2 != argc)
- 752 {
- 753 printf("Usage: flvparse **.flv\n");
- 754
- 755 return -1;
- 756 }
- 757
- 758 fp = fopen(argv[1], "rb");
- 759 if (!fp)
- 760 {
- 761 printf("open file[%s] error!\n", argv[1]);
- 762
- 763 return -1;
- 764 }
- 765
- 766 memset(flvHeaderData, 0x0, sizeof(flvHeaderData));
- 767
- 768 dataLen = fread(flvHeaderData, 1, MIN_FLV_HEADER_LEN, fp);
- 769 if (dataLen != MIN_FLV_HEADER_LEN)
- 770 {
- 771 printf("read flv header error!\n");
- 772
- 773 return -1;
- 774 }
- 775
- 776 flvHeaderData[MIN_FLV_HEADER_LEN] = '\0';
- 777
- 778 DealFlvHeader(flvHeaderData);
- 779
- 780 #ifdef PRINTF_DEBUG
- 781 printf("+FLV Body\n");
- 782 #endif
- 783
- 784 while (1)
- 785 {
- 786 memset(preTagSizeData, 0x0, sizeof(preTagSizeData));
- 787
- 788 dataLen = fread(preTagSizeData, 1, MAX_PRE_TAG_SIZE_LEN, fp);
- 789 if (dataLen != MAX_PRE_TAG_SIZE_LEN)
- 790 {
- 791 break;
- 792 }
- 793
- 794 preTagSizeData[MAX_PRE_TAG_SIZE_LEN] = '\0';
- 795
- 796 #ifdef PRINTF_DEBUG
- 797 printf("%spreviousTagSize: %d\n", TAB44, (preTagSizeData[0]<<24) | (preTagSizeData[1]<<16) | (preTagSizeData[2]<<8) | preTagSizeData[3]);
- 798 #endif
- 799
- 800 memset(tagHeaderData, 0x0, sizeof(tagHeaderData));
- 801
- 802 dataLen = fread(tagHeaderData, 1, MAX_TAG_HEADER_LEN, fp);
- 803 if (dataLen != MAX_TAG_HEADER_LEN)
- 804 {
- 805 continue;
- 806 }
- 807
- 808 memset(&tagHeader, 0x0, sizeof(T_FLV_TAG_HEADER));
- 809
- 810 DealTagHeader(tagHeaderData, &tagHeader);
- 811
- 812 tagData = (unsigned char*)malloc(tagHeader.data_size);
- 813 if (!tagData)
- 814 {
- 815 continue;
- 816 }
- 817
- 818 memset(tagData, 0x0, tagHeader.data_size);
- 819
- 820 dataLen = fread(tagData, 1, tagHeader.data_size, fp);
- 821 if (dataLen != tagHeader.data_size)
- 822 {
- 823 continue;
- 824 }
- 825
- 826 DealTagData(tagData, tagHeader.type, tagHeader.data_size);
- 827
- 828 free(tagData);
- 829 tagData = NULL;
- 830 }
- 831
- 832 return 0;
- 833 }