FFmpeg音视频开发知识点(一)

系列文章目录


文章目录

  • 系列文章目录
  • 前言
  • 一、AVCodecContext详解
    • 1.视频编码器
  • 二、未完待续...


前言

最近在做音视频编解码实时流项目【h323+ffmpeg+rtp】,特意记录一下开发中遇到的部分问题,以及现学现用的部分知识点,前期急急忙忙没认真看,直接拿过来用,用的不对,各种问题,真的一言难尽,最终还是要静下心来认真研究才行;

温馨提示:我使用的ffmpeg版本是4.4,不同版本可能有所差异


一、AVCodecContext详解

分为音频编码、音频解码、视频编码、视频解码四个部分,虽说同用的是同一个结构体、但是含义却不一样,我分开记录一下

1.视频编码器

编码器上下文AVCodecContext是FFmpeg中用于描述编码器状态的结构体,包含了许多参数和配置选项,用于控制编码器的行为和性能。下面是一些常用的视频编码器上下文参数及其意义的详细讲解

1、codec_id:指定编码器的ID,如AV_CODEC_ID_H264表示H.264编码器。

pCodecCtx->codec_id = AV_CODEC_ID_H264;

2、bit_rate:指定编码的比特率,即视频数据每秒使用的比特数,通常以bit/s为单位。该参数的大小直接影响到视频的质量和大小,过高的比特率可能会导致视频过大,而过低的比特率可能会导致视频质量下降。

pCodecCtx->bit_rate = 3000000; // 比特率3000Kbps

2、width/height:指定视频的宽度和高度,单位为像素。

pCodecCtx->width = 1920;        // 1080P
pCodecCtx->height = 1080;

3、gop_size:指定关键帧(I帧)的间隔大小,即每隔多少帧就产生一个I帧。该参数的大小通常与视频的帧率和编码器的性能有关,过小的间隔可能会导致视频质量下降,而过大的间隔可能会导致视频播放时的卡顿现象。

pCodecCtx->gop_size = 25;

4、max_b_frames:指定编码器允许使用的最大B帧数量。B帧通常是在前后两个关键帧之间插入的一种帧类型,可以提高视频压缩比和画面流畅度,但同时也增加了编码器的计算量。

pCodecCtx->max_b_frames = 2;

5、pix_fmt:指定输入数据的像素格式,例如AV_PIX_FMT_YUV420P表示420格式的YUV数据。

pCodecCtx->pix_fmt = AV_PIX_FMT_YUV420P;

6、time_base:指定视频的时间基准,即每个时间单位表示多少秒。通常为分数形式,例如{1, 25}表示每个时间单位为1/25秒。

pCodecCtx->time_base = (AVRational){1, 25};

7、workaround_bugs:用于指定编码器是否需要尝试解决一些已知的编码器或解码器的问题。将该参数设置为FF_BUG_AUTODETECT表示编码器会自动检测和解决一些已知的问题,包括一些标准不一致或解码器错误等问题。
在实际应用中,是否需要设置取决于具体的应用场景。如果您的应用程序需要处理多种不同的视频源或使用多种不同的解码器进行解码,那么可以考虑设置该参数,以确保编码器能够处理各种不同的视频源和解码器。但如果您的应用程序只处理特定类型的视频源或使用特定的解码器进行解码,可以考虑禁用该参数以提高编码效率。

pCodecCtx->workaround_bugs = FF_BUG_AUTODETECT; // 0是禁用

8、thread_count:指定编码器使用的线程数量,用于提高编码器的并行处理能力。线程数的大小应根据实际情况和计算资源进行设置。

pCodecCtx->thread_count = 4;

9、refs:表示编码器在编码过程中可以参考的前向帧的数量。参考帧的数量对编码效果和编码速度都有影响。一般情况下,参考帧数量越多,编码效果越好,但编码速度也越慢。
对于参考帧的设置,需要综合考虑编码效果和编码速度。如果您的视频场景比较简单,可以将ref设置为1,这样可以提高编码速度,但可能会影响编码质量。如果您需要更好的编码质量,可以将ref设置为2或更高,但这样会降低编码速度。
所以,具体的ref设置要根据您的具体场景和需求来进行选择。如果您的视频场景比较简单,可以将ref设置为1,否则可以考虑适当增加ref的值。
需要注意的是,ref的值不能超过编码器支持的最大值,否则会导致编码器初始化失败。对于H.264编码器,默认的最大参考帧数是16,因此将ref设置为16或更高可能会导致编码器初始化失败。

pCodecCtx->refs = 1;

10、flags:指定编码器的各种标志,用于控制编码器的行为和性能。

// 生成全局头信息,在某些情况下非常有用,例如将H.264码流封装为MP4或MKV格式时,可以让封装器更容易地处理。
// 具体来说,全局头包含编码器的配置参数和SPS/PPS信息,这些信息对于解码器的正确解码非常重要。
// 因此,如果您需要将编码后的视频流进行封装,建议设置该标志。如果您仅仅需要将编码后的视频流保存为裸流,则不必设置该标志。
pCodecCtx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;

// 表示输出的视频流可能会被截断。在一些情况下,输出的视频流可能会被截断,例如网络传输过程中发生了丢包,
//或者存储设备写入速度不足等。如果输出的视频流被截断,那么解码器可能无法正确解码视频流,导致输出的视频出现异常。
// 因此,是否需要设置取决于具体的应用场景。如果您的应用程序需要保证输出的视频流的完整性,那么可以考虑设置该参数。但如果您的应用程序对视频流的完整性要求不高,可以不设置该参数。
pCodecCtx->flags |= AV_CODEC_FLAG_TRUNCATED;

11、bit_rate_tolerance:参数则是指编码器输出比特率的容差,单位同样为bit/s。它表示编码器在进行比特率控制时,可以允许的比特率偏差范围。如果比特率超过了这个容差范围,编码器会尝试进行调整,以保持输出比特率在指定范围内。通常情况下,bit_rate_tolerance参数应该设置为bit_rate参数的10%左右;
需要注意的是,在设置bit_rate参数时,还需要考虑到编码器支持的最大比特率。如果bit_rate超过了编码器支持的最大比特率,编码器会自动进行调整。因此,为了避免比特率过高导致编码器自动调整输出比特率,可以查询编码器支持的最大比特率,并根据其进行设置

pCodecCtx->bit_rate_tolerance = pCodecCtx->bit_rate / 10;

12、profile:影响编码器的性能和输出视频的兼容性,H.264编码器支持多个profile,包括baseline、main、high等。不同的profile对应着不同的编码复杂度和输出视频兼容性。其中,baseline编码速度快,但是编码复杂度和输出视频兼容性一般,high则刚好相反;
对于H.264编码器而言,默认情况下profile参数的值是未定义的,需要手动设置。一般来说,如果不进行设置,编码器会根据当前的参数自动选择一个合适的profile。但是,在特定的应用场景下,手动设置profile参数可以带来更好的编码效果和更高的兼容性。

pCodecCtx->profile = FF_PROFILE_H264_BASELINE;

constrained profile可以使得输出的视频更加稳定、兼容性更好,但是可能会影响视频的质量。在一些情况下,constrained profile会限制一些高级的编码特性,使得编码效果与非constrained profile相比略有差别,如果您的应用程序对视频质量要求较高,且不希望受到任何限制,那么可以不设置该参数。但如果您希望输出的视频具有更高的兼容性、更加稳定,那么可以考虑设置该参数

pCodecCtx->profile |= FF_PROFILE_H264_CONSTRAINED;

13、priv_data:私有数据,即编码器的私有数据,用于存储编码器的内部状态和数据结构;
可以注意到,有些参数可以直接通过AVCodecContext的成员赋值,有些是通过priv_data来赋值,两个设置作用一样,理论上只需要通过一种方式设置就行;但两者之间还是有所差异,可以根据自己的需要进行设置,具体如下:

1、有些参数必须使用priv_data来设置,比如字符串类型的;或者AVCodecContext的成员没有的;
2、将配置参数设置到编码器的私有数据中,可以确保这些参数只对该编码器实例有效,并且不会对其他编码器实例产生影响。这对于同时处理多个视频流的应用程序非常重要,因为每个流可能需要不同的编码参数。此外,使用私有数据设置参数可以避免在参数传递过程中出现不必要的副作用或错误,提高代码的健壮性和可维护性

preset:参数是x264编码器的一种预设选项,用于设置编码速度和编码质量的平衡。不同的预设选项可以在编码速度和编码质量之间进行权衡,通常可以选择的预设选项包括:ultrafast、superfast、veryfast、faster、fast、medium、slow、slower、veryslow、placebo,其中ultrafast是最快的预设,placebo是最慢但是编码效果最好的预设;
如果对编码速度没有过高的要求,可以设置preset参数为slow或者slower,这样可以获得更好的编码质量。但是需要注意的是,使用更慢的预设会增加编码时间和计算资源的消耗,对于某些场景可能会影响实时性能。
因此,如果在实时场景中需要编码视频,并且需要保证编码速度和实时性能,那么可以考虑设置预设为ultrafast或superfast。如果需要更高的编码质量,并且可以承受一定的延迟,可以选择更慢的预设

av_opt_set(pCodecCtx->priv_data, "preset", "slow", 0);

slice-max-size:用于指定编码器在生成码流时,切片(slice)的最大大小(字节数)。这个参数的默认值是0,表示不限制切片大小。
如果设置了slice-max-size参数,则编码器将尝试将生成的每个切片大小限制在指定的最大大小内,从而可以控制编码输出码率的变化范围。通常情况下,设置slice-max-size参数可以有效地控制输出码率和码流大小,并提高编码输出的质量和稳定性。
在具体应用中,是否需要设置slice-max-size参数取决于视频源的特点和应用需求。如果您的视频源较为稳定,码率变化不大,可以不设置该参数。但是如果您的视频源波动较大,码率变化较大,则可以考虑设置slice-max-size参数以控制输出码率和码流大小。

// 我这边用的rtp封包发送,减去头部12
av_opt_set_int(pCodecCtx->priv_data, "slice-max-size", 1500-12, 0);

crf:设置 H.264 编码时使用的 Constant Rate Factor (CRF) 的值。CRF 是一种自适应比特率控制方法,可以在保持视频质量不变的情况下,自动调整输出码率。具体来说,CRF 值越小,输出的视频质量越高,但输出的码率也会越大。CRF 值一般取值范围为 0-51,其中 0 表示无损编码,而 51 则表示最低质量的编码。一般来说,推荐的 CRF 值为 18-28 之间。默认值为 23。因此,如果你希望自适应控制视频码率,同时又想保持较高的视频质量,可以设置一个较小的 CRF 值,如 18。如果你想在保证视频质量的情况下控制视频码率,可以将 CRF 值调大一些,如 28。
注意,如果你设置了 CRF 值,那么其他控制比特率的参数(如 bit_rate 和 bit_rate_tolerance)将会被忽略,因为 CRF 会自动调整输出码率

av_opt_set_int(pCodecCtx->priv_data, "crf", 18, 0);

16、level:参数用于控制输出视频的级别。H.264标准规定了不同级别的输出视频所能达到的最大帧率、最大码率、最大分辨率等参数,因此选择合适的级别可以确保输出视频的兼容性和质量;

pCodecCtx->level = 41;

二、未完待续…

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