您的位置:首页 > 游戏 > 手游 > 网络推广是什么职位_高德地图澳大利亚能用吗_新公司做网站多少钱_爱站查询

网络推广是什么职位_高德地图澳大利亚能用吗_新公司做网站多少钱_爱站查询

2024/12/23 16:45:28 来源:https://blog.csdn.net/qq_44144025/article/details/144443132  浏览:    关键词:网络推广是什么职位_高德地图澳大利亚能用吗_新公司做网站多少钱_爱站查询
网络推广是什么职位_高德地图澳大利亚能用吗_新公司做网站多少钱_爱站查询

参考文章

音视频 H264 编解码协议-知乎
视频H264编码详解(上)-知乎
H.264媒体流AnnexB和AVCC格式分析-CSDN
H264之NALU解析-知乎
H264帧,SPS,PPS概念-知乎
H.264流媒体协议格式中的Annex B格式和AVCC格式深度解析-CSDN

H264简介

H.264从1999年开始,到2003年形成草案,最后在2007年定稿有待核实。在ITU的标准⾥称为H.264,在MPEG的标准⾥是MPEG-4的⼀个组成部分–MPEG-4 Part 10,⼜叫Advanced Video Codec,因此常常称为MPEG-4 AVC或直接叫AVC。

带宽

Mbps(Million bits per second)即“传输速率”,也叫“带宽”。Mbps和MB/s是怎么换算的呢?
8Mbps=1MB/s;8Mbps换算成下载速度就是1MB/s,不过由于种种限制,实际情况中8M的宽带往往达不到1MB/s的下载速度,能达到800KB/s以上算是正常情况。

NALU(Network Abstract Layer Unit)网络抽象层单元

H.264原始码流(裸流)由⼀个接⼀个NALU组成.

SPS:序列参数集,包含解码配置,如profile level分辨率和帧率等。编码后的第一帧。
PPS:图像参数集,包含有关熵编码模式、分片组、运动预测和去块滤波器等信息。编码后的第二帧。
I帧:帧内编码,可独立解码生成完整的图片。
P帧:前向预测编码帧,需要参考其前⾯的⼀个I 或者B 来⽣成⼀张完整的图⽚。
B帧: 双向预测内插编码帧,则要参考其前⼀个I或者P帧及其后⾯的⼀个P帧来⽣成⼀张完整的图⽚。
NALU = StartCode + ⼀组对应于视频编码的NALU头部信息 + ⼀个原始字节序列负荷(RBSP, Raw Byte Sequence Payload)
其中 Start Code⽤于标示这是⼀个NALU单元的开始,必须是"00 00 00 01" 或"00 00 01",除此之外基本相当于⼀个NAL header + RBSP:

值得注意的是,一个NALU即使是VCL NALU 也并不一定表示一个视频帧。因为一个帧的数据可能比较多,可以分片为多个NALU来储存。一个或者多个NALU组成一个访问单元AU,一个AU包含一个完整的帧。

H264编码分层

  • NAL层:(Network Abstraction Layer,视频数据网络抽象层)
    它的作用是H264只要在网络上传输,在传输的过程每个包以太网是1500字节. 而H264的帧往往会大于1500字节的.所以就要进行拆包. 将一个帧拆成多个包进行传输.所有的拆包或者组包都是通过NAL层去处理的.
  • VCL层:(Video Coding Layer,视频数据编码层)
    它的作用就是对视频原始数据进行压缩.

H264 码流格式

H264有两种封装:

  • ⼀种是AnnexB模式
    [start code]NALU | [start code] NALU |...
    这种格式比较常见,也就是我们熟悉的每个帧前面都有0x00 00 00 01或者0x00 00 01作为起始码。.h264文件就是采用的这种格式,每个帧前面都要有个起始码。SPS PPS等也作为一类NALU存储在这个码流中,一般在码流最前面。也就是说这种格式包含VCL 和 非VCL 类型的NALU。

  • ⼀种是AVCC模式
    ([extradata]) | ([length] NALU) | ([length] NALU) | ...
    FLV/MP4/MKV中H264采用的是AVCC模式,也叫AVC1格式。
    没有startcode,每⼀个frame前⾯4个字节是frame⻓度。SPS和PPS等参数信息被封装在extradata中。
    比如ffmpeg中解析mp4文件后sps pps存在streams[index]->codecpar->extradata中。也就是说这种码流通常只包含VCL类型NALU。
    此时将前4个字节替换为0x00000001才能得到AnnexB模式的NALU数据。
    很多解码器只⽀持AnnexB这种模式,因此需要将MP4做转换。在ffmpeg中⽤ h264_mp4toannexb_filter接口可以做转换。

FFmpeg解析mp4中H264码流

MP4文件中编码信息是存储在文件开始或者文件末尾的,详细结构这里不详述了。就知道不是和图像数据放在一起的就可以了。
FFmpeg使用av_read_frame(AVFormatContext *s, AVPacket *pkt)函数读mp4文件,读到packet里面仅仅是VCL编码数据NAL,并且这个编码数据是AVCC格式组织的码流,直接保存成.264文件没法播放。

  1. avFmtCtx->streams[_videoStreamIndex]->codecpar->extradata中解析SPS和PPS数据,解析出SPS PPS数据加上4字节的0001的起始码拼装成AnnexB格式的NALU,先写入文件.
  2. 通过av_read_frame(AVFormatContext *s, AVPacket *pkt)读取到数据存放在pkt->data中,长度为pkt->size
    注意:这1个pkt->data中的数据可能是多个NALU的数据!!!这些数据按([length] NALU) | ([length] NALU) | ...规则排列。先取前4字节作为长度,读取指定长度的数据加上起始码拼NALU。然后同样的方式读取后面的数据,直到总长度等于pkt->size。

FFmpeg 解析mp4中H264码流 代码示例

参考链接:

H.264媒体流AnnexB和AVCC格式分析-CSDN

	//...AVPacket spsPacket, ppsPacket, tmpPacket;uint8_t startCode[4] = {0x00, 0x00, 0x00, 0x01};bool sendSpsPps = false;while (av_read_frame(_avFmtCtx, _avPacket) == 0) { // 能读到数据返回0,循环读取// 根据pkt->stream_index判断是不是视频流if (_avPacket->stream_index == _videoStreamIndex) {// 仅1次处理sps pps,也可以拿在while外面if (!sendSpsPps) { int spsLength = 0;int ppsLength = 0;// extradata 数据指针,方便操作取其指针uint8_t *ex = _avFmtCtx->streams[_videoStreamIndex]->codecpar->extradata;// extradata;第6字节后5位表示SPS个数,通常为1,这里就省略判断处理,严谨期间还是要判断// 直接 取第7 8 俩字节作为SPS长度spsLength = (ex[6] << 8) | ex[7];// x[8+spsLength]表示PPS个数,通常为1,这里就省略判断处理// 取接下来两位作为PPS长度ppsLength = (ex[8 + spsLength + 1] << 8) | ex[8 + spsLength + 2];// 为spsPacket ppsPacket的data分配内存,类似malloc// 如果只是为了保存文件,可以不使用pkt结构,直接malloc就行// 分配的空间为sps或pps长度加上4字节的起始码av_new_packet(&spsPacket, spsLength + 4);av_new_packet(&ppsPacket, ppsLength + 4);// 给SPS拼前4字节起始码memcpy(spsPacket.data, startCode, 4);// 把SPS数据拼在起始码后面memcpy(spsPacket.data + 4, ex + 8, spsLength);// TODO: 这里可以把spsPacket.data数据写入文件 // 给PPS拼前4字节起始码memcpy(ppsPacket.data, startCode, 4);// 把PPS数据拼在起始码后面memcpy(ppsPacket.data + 4, ex + 8 + spsLength + 2 + 1, ppsLength);// TODO: 这里可以把ppsPacket.data数据写入文件 sendSpsPps = true;}// 下面处理读到pkt中的数据int nalLength = 0;uint8_t *data = _avPacket->data;// _avPacket->data中可能有多个NALU,循环处理while (data < _avPacket->data + _avPacket->size) {// 取前4字节作为nal的长度nalLength = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];if (nalLength > 0) {memcpy(data, startCode, 4);  // 拼起始码tmpPacket = *_avPacket;      // 仅为了复制packet的其他信息,保存文件可忽略tmpPacket.data = data;		 // 把tmpPkt指针偏移到实际数据位置tmpPacket.size = nalLength + 4; // 长度为nal长度+起始码4//TODO: 处理这个NALU的数据,可以直接把tmpPacket.data写入文件}data = data + 4 + nalLength; // 处理data中下一个NALU数据}}av_packet_unref(_avPacket);}

通过FFMPEG的h264_mp4toannexb进行格式转换

参考链接:

FFmpeg简单使用:过滤器 ---- h264_mp4toannexb-CSDN
ffmpeg 新接口 :从flv文件中提取h264码流-3ms

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com