1.读flv文件jump over9个字节,再jump over4个字节。再读type,datalength,timestamp,streamid。
还是要对照协议看。
The FLV header9个字节的文件头
Field Type Comment Signature UI8 Signature byte always 'F' (0x46) Signature UI8 Signature byte always 'L' (0x4C) Signature UI8 Signature byte always 'V' (0x56) Version UI8 File version (for example, 0x01 for FLV version 1) TypeFlagsReserved UB [5] Shall be 0 TypeFlagsAudio UB [1] 1 = Audio tags are present TypeFlagsReserved UB [1] Shall be 0 TypeFlagsVideo UB [1] 1 = Video tags are present DataOffset UI32 The length of this header in bytesThe FLV File Body
4个字节的PreviousTagSize0,接着是FLVTAG
Field Type Comment PreviousTagSize0 UI32 Always 0 Tag1 FLVTAG First tag PreviousTagSize1 UI32 Size of previous tag, including its header, in bytes. \FLV Tag 读type,datalength,timestamp,streamid。type==8是音频,type==9是视频。 VideoTagHeader
For FLV version 1, this value is 11 plus the DataSize of the previous tag. Tag2 FLVTAG Second tag ...
结合前文《librtmp发送h264》 ,SendH264Packet函数,SendVideoSpsPps函数就是这样组包的。
//packet attributes uint32_t type=0; uint32_t datalength=0; uint32_t timestamp=0; uint32_t streamid=0; FILE*fp=NULL; fp=fopen("cuc_ieschool.flv","rb"); if (!fp){ RTMP_LogPrintf("Open File Error.\n"); CleanupSockets(); return -1; } //jump over FLV Header fseek(fp,9,SEEK_SET); //jump over previousTagSizen fseek(fp,4,SEEK_CUR); start_time=RTMP_GetTime(); while(1) { if((((now_time=RTMP_GetTime())-start_time) <(pre_frame_time)) && bNextIsKey){ //wait for 1 sec if the send process is too fast //this mechanism is not very good,need some improvement if(pre_frame_time>lasttime){ RTMP_LogPrintf("TimeStamp:%8lu ms\n",pre_frame_time); lasttime=pre_frame_time; } Sleep(1000); continue; } //not quite the same as FLV spec if(!ReadU8(&type,fp)) break; if(!ReadU24(&datalength,fp)) break; if(!ReadTime(×tamp,fp)) break; if(!ReadU24(&streamid,fp)) break; if (type!=0x08&&type!=0x09){ //jump over non_audio and non_video frame, //jump over next previousTagSizen at the same time fseek(fp,datalength+4,SEEK_CUR); continue; } if(fread(packet->m_body,1,datalength,fp)!=datalength) break; packet->m_headerType = RTMP_PACKET_SIZE_LARGE; packet->m_nTimeStamp = timestamp; packet->m_packetType = type; packet->m_nBodySize = datalength; pre_frame_time=timestamp; if (!RTMP_IsConnected(rtmp)){ RTMP_Log(RTMP_LOGERROR,"rtmp is not connect\n"); break; } if (!RTMP_SendPacket(rtmp,packet,0)){ RTMP_Log(RTMP_LOGERROR,"Send Error\n"); break; } if(!ReadU32(&preTagsize,fp)) break; if(!PeekU8(&type,fp)) break; if(type==0x09){ if(fseek(fp,11,SEEK_CUR)!=0) break; if(!PeekU8(&type,fp)){ break; } if(type==0x17) bNextIsKey=1; else bNextIsKey=0; fseek(fp,-11,SEEK_CUR); } } RTMP_LogPrintf("\nSend Data Over\n"); if(fp) fclose(fp);
https://blog.csdn.net/leixiaohua1020/article/details/42104945
https://depthlove.github.io/2015/11/13/flv-analysis-in-rtmp-live-play/
https://blog.csdn.net/yeyumin89/article/details/7932368