RTMP FLV H.264 NALU GOP

RTMP

RTMP FLV H.264 NALU GOP_第1张图片
RTMP FLV H.264 NALU GOP_第2张图片

GOP (通常是 2倍的帧率, 2s左右)

GOP说白了就是两个I帧之间的间隔.比较说GOP为120,如果是720p60的话,那就是2s一次I帧.

RTMP FLV H.264 NALU GOP_第3张图片
IDR帧是I帧,但I帧不一定是IDR帧,比如在编码的时候设置GOP为30,那么就是说30帧图像有一个I帧,这样60帧就有2个I帧,但是60帧只有1个IDR帧。

宏块

RTMP FLV H.264 NALU GOP_第4张图片
一个NAL单元就是一个Slice(片),而一帧不一定就是一个NAL单元,一帧里面可能会有多个NAL单元(多个片)。

  • GOP:一段时间内图像变化不大的图像集我们就可以称之为一个序列,这里的图像又在H264里面称为帧,所以就是一组视频帧,其中第一个我们称为是IDR帧。
  • 帧:一副图像编码后的视频数据也叫做一帧,其中有I帧、B帧、P帧
  • 片:一帧图像又可以划分为很多片,由一个片或者多个片组成(这里视频帧被划分为一个片或者多个片,片数据主要就是通过NLAU进行传输);
  • 宏块:视频编码的最小处理单元,承载了视频的具体YUV信息,一片由一个或者多个宏块组成;

所以视频流分析的对象可以用下面的图片描述:

  1. 将图像分割成若干个16*16个像素(不一定, 可能是 16 * 8, 可能是 8 * 8)的块, 每个块就叫做宏块

  2. 每个宏块的压缩(记录第一行像素的颜色和第一列像素的颜色, 然后记录渐变色的角度, 渐变重点的颜色, 帧内压缩).
    RTMP FLV H.264 NALU GOP_第5张图片

  3. 帧预测(2 , 2 , 2 , 7 , 2 , 2 , 2 , 2 , 2 , 13. 我们也可以用下面的方式来表示:prediction = 2;Difference = { (5, 3), (11, 9) };(都是2, 低三个和第9个不同, 差值是5和11)

  4. 宏块越大, 最终压缩后生成的视频就越小(h.265的宏块比h.264的宏块大, 但是画面细腻的地方, 宏块更小).

  5. 视频的播放本质就是宏块的运动 (宏块运动的方向形成了运动矢量). 视频播放时候(下一帧会删除重复的宏块, 用运动矢量代替, 差异信息用宏块编码)

  6. h.264编码: 当与I帧的相似程度 > 95%, 编码成B帧, 相似程度 > 70%, 编码成P帧,
    RTMP FLV H.264 NALU GOP_第6张图片
    第四帧图像相似程度 > 70%, 编码成P帧.
    RTMP FLV H.264 NALU GOP_第7张图片

此时, 在码流中, 第一帧是画面1, 第二帧是画面4, 第三帧是画面2, 第四帧是画面3.(第一帧一定是I帧, 第二帧一定是P帧, 一定是先编码I帧, 然后编码P这帧, 然后根据I帧和P帧, 编码B帧, DTS(解码顺序) : 画面1, 画面4, 画面2, 画面3, PTS:(播放顺序), 画面1, 画面2, 画面3, 画面4)

NALU

RTMP FLV H.264 NALU GOP_第8张图片

NALU结构分为两层,包含了视频编码层(VCL)和网络适配层(NAL):
  1. 视频编码层(VCL即Video Coding Layer):负责高效的视频内容表示,这是核心算法引擎,其中对宏块、片的处理都包含在这个层级上,它输出的数据是SODB;
  2. 网络适配层(NAL即Network Abstraction Layer):以网络所要求的恰当方式对数据进行打包和发送,比较简单,先报VCL吐出来的数据SODB进行字节对齐,形成RBSP,最后再RBSP数据前面加上NAL头则组成一个NALU单元。
分层目的:
  1. 这样做的目的:VCL只负责视频的信号处理,包含压缩,量化等处理,NAL解决编码后数据的网络传输,这样可以将VCL和NAL的处理放到不同平台来处理,可以减少因为网络环境不同对VCL的比特流进行重构和重编码;

RTMP FLV H.264 NALU GOP_第9张图片
其实NALU的承载数据真实并不是RBSP而是EBSP即(Extent Byte Sequence Payload),EBSP和RBSP的区别就是在 RBSP里面加入防伪起始码字节(0x03),因为H.264规范规定,编码器吐出来的数据需要在每个NALU添加起始码:0x00 00 01或者0x00 00 00 01,用来指示一个NALU的起始和终止位置,那么RBSP数据内部是有可能含有这种字节序列的,为了防止解析错误,所以在RBSP数据流里面碰到0x 00 00 00 01的0x01前面就会加上0x03,解码时将NALU的EBSP中的0x03去掉成为RBSP,称为脱壳操作。
RTMP FLV H.264 NALU GOP_第10张图片

case LFLiveVideoQuality_Low1:{
        configuration.sessionPreset = LFCaptureSessionPreset360x640;
        configuration.videoFrameRate = 15;
        configuration.videoMaxFrameRate = 15;
        configuration.videoMinFrameRate = 10;
        configuration.videoBitRate = 500 * 1000;
        configuration.videoMaxBitRate = 600 * 1000;
        configuration.videoMinBitRate = 400 * 1000;
        configuration.videoSize = CGSizeMake(360, 640);
    }
        break;
    case LFLiveVideoQuality_Low2:{
        configuration.sessionPreset = LFCaptureSessionPreset360x640;
        configuration.videoFrameRate = 24;
        configuration.videoMaxFrameRate = 24;
        configuration.videoMinFrameRate = 12;
        configuration.videoBitRate = 600 * 1000;
        configuration.videoMaxBitRate = 720 * 1000;
        configuration.videoMinBitRate = 500 * 1000;
        configuration.videoSize = CGSizeMake(360, 640);
    }
        break;
    case LFLiveVideoQuality_Low3: {
        configuration.sessionPreset = LFCaptureSessionPreset360x640;
        configuration.videoFrameRate = 30;
        configuration.videoMaxFrameRate = 30;
        configuration.videoMinFrameRate = 15;
        configuration.videoBitRate = 800 * 1000;
        configuration.videoMaxBitRate = 960 * 1000;
        configuration.videoMinBitRate = 600 * 1000;
        configuration.videoSize = CGSizeMake(360, 640);
    }
        break;
    case LFLiveVideoQuality_Medium1:{
        configuration.sessionPreset = LFCaptureSessionPreset540x960;
        configuration.videoFrameRate = 15;
        configuration.videoMaxFrameRate = 15;
        configuration.videoMinFrameRate = 10;
        configuration.videoBitRate = 800 * 1000;
        configuration.videoMaxBitRate = 960 * 1000;
        configuration.videoMinBitRate = 500 * 1000;
        configuration.videoSize = CGSizeMake(540, 960);
    }
        break;
    case LFLiveVideoQuality_Medium2:{
        configuration.sessionPreset = LFCaptureSessionPreset540x960;
        configuration.videoFrameRate = 24;
        configuration.videoMaxFrameRate = 24;
        configuration.videoMinFrameRate = 12;
        configuration.videoBitRate = 800 * 1000;
        configuration.videoMaxBitRate = 960 * 1000;
        configuration.videoMinBitRate = 500 * 1000;
        configuration.videoSize = CGSizeMake(540, 960);
    }
        break;
    case LFLiveVideoQuality_Medium3:{
        configuration.sessionPreset = LFCaptureSessionPreset540x960;
        configuration.videoFrameRate = 30;
        configuration.videoMaxFrameRate = 30;
        configuration.videoMinFrameRate = 15;
        configuration.videoBitRate = 1000 * 1000;
        configuration.videoMaxBitRate = 1200 * 1000;
        configuration.videoMinBitRate = 500 * 1000;
        configuration.videoSize = CGSizeMake(540, 960);
    }
        break;
    case LFLiveVideoQuality_High1:{
        configuration.sessionPreset = LFCaptureSessionPreset720x1280;
        configuration.videoFrameRate = 15;
        configuration.videoMaxFrameRate = 15;
        configuration.videoMinFrameRate = 10;
        configuration.videoBitRate = 1000 * 1000;
        configuration.videoMaxBitRate = 1200 * 1000;
        configuration.videoMinBitRate = 500 * 1000;
        configuration.videoSize = CGSizeMake(720, 1280);
    }
        break;
    case LFLiveVideoQuality_High2:{
        configuration.sessionPreset = LFCaptureSessionPreset720x1280;
        configuration.videoFrameRate = 24;
        configuration.videoMaxFrameRate = 24;
        configuration.videoMinFrameRate = 12;
        configuration.videoBitRate = 1200 * 1000;
        configuration.videoMaxBitRate = 1440 * 1000;
        configuration.videoMinBitRate = 800 * 1000;
        configuration.videoSize = CGSizeMake(720, 1280);
    }
        break;
    case LFLiveVideoQuality_High3:{
        configuration.sessionPreset = LFCaptureSessionPreset720x1280;
        configuration.videoFrameRate = 30;
        configuration.videoMaxFrameRate = 30;
        configuration.videoMinFrameRate = 15;
        configuration.videoBitRate = 1200 * 1000;
        configuration.videoMaxBitRate = 1440 * 1000;
        configuration.videoMinBitRate = 500 * 1000;
        configuration.videoSize = CGSizeMake(720, 1280);
    }

case LFLiveAudioQuality_Low: {
        audioConfig.audioBitrate = audioConfig.numberOfChannels == 1 ? LFLiveAudioBitRate_32Kbps : LFLiveAudioBitRate_64Kbps;
        audioConfig.audioSampleRate = LFLiveAudioSampleRate_16000Hz;
    }
        break;
    case LFLiveAudioQuality_Medium: {
        audioConfig.audioBitrate = LFLiveAudioBitRate_96Kbps;
        audioConfig.audioSampleRate = LFLiveAudioSampleRate_44100Hz;
    }
        break;
    case LFLiveAudioQuality_High: {
        audioConfig.audioBitrate = LFLiveAudioBitRate_128Kbps;
        audioConfig.audioSampleRate = LFLiveAudioSampleRate_44100Hz;
    }
        break;
    case LFLiveAudioQuality_VeryHigh: {
        audioConfig.audioBitrate = LFLiveAudioBitRate_128Kbps;
        audioConfig.audioSampleRate = LFLiveAudioSampleRate_48000Hz;
    }
  1. 视频到放的原理(重新编码成新的视频, 从后往前, 每一个I帧与后边的帧正着解码, 然后生成的每个帧倒着编码)

采样频率

  • 每秒进行多少次取样

位深

  • 用多少位去表示每个采样的结果的数值

SPS PPS

  • SPS又称作序列参数集。SPS中保存了一组编码视频序列的全局参数。包含了profile、level、宽高和颜色空间等信息。
  • PPS是图像参数集。每一帧的编码后数据所依赖的参数保存于图像参数集中。
  • P帧以前的一个I帧或P帧为参考帧,
  • B帧以前面的I或P帧和后面的P帧为参考帧,
  • 一个序列的第一个图像叫做 IDR 图像(立即刷新图像),IDR 图像都是 I 帧图像。H.264 引入 IDR 图像是为了解码的重同步,当解码器解码到 IDR 图像时,立即将参考帧队列清空,将已解码的数据全部输出或抛弃,重新查找参数集,开始一个新的序列。这样,如果前一个序列出现重大错误,在这里可以获得重新同步的机会。IDR图像之后的图像永远不会使用IDR之前的图像的数据来解码。一个序列就是一段内容差异不太大的图像编码后生成的一串数据流。当运动变化比较少时,一个序列可以很长,因为运动变化少就代表图像画面的内容变动很小,所以就可以编一个I帧,然后一直P帧、B帧了。当运动变化多时,可能一个序列就比较短了,比如就包含一个I帧和3、4个P帧。

你可能感兴趣的:(音视频)