P10 RV1126推流项目——ffmpeg输出参数初始化

2024-01-05 00:12

本文主要是介绍P10 RV1126推流项目——ffmpeg输出参数初始化,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

 前言 

                             

从本章开始我们将要学习嵌入式音视频的学习了 ,使用的瑞芯微的开发板

🎬 个人主页:@ChenPi

🐻推荐专栏1: 《C++_@ChenPi的博客-CSDN博客》✨✨✨ 

🔥 推荐专栏2: 《Linux C应用编程(概念类)_@ChenPi的博客-CSDN博客》✨✨✨

🛸推荐专栏3:《嵌入式音视频_@ChenPi的博客-CSDN博客》
🌺本篇简介  :本章主要讲解ffmpeg模块输出参数的初始化

 

今天讲解的部分就是继上章未讲完的部分继续讲解

首先我们看上图红框里面的函数,函数内部就是实现ffmpeg初始化,合成复合流以及推流

里面内容比价多,我可能分为三章去分别讲解,今天我们先讲一下ffmpeg的参数初始化

01  ffmpeg输出模块结构体

在FFMPEG输出模块中用到了很多个结构体,分别是:AVFormatContext、AVStream、AVCodec、AVCodecContext、AVIOContext

  1. AVFormatContext:是存储音视频封装格式中包含的信息的结构体,它是FFMPEG中的核心,所有的文件封装、编码都是从它开始
  2.  AVStream:AVStream主要存储了音频流、视频流的具体信息
  3. ​​​​​​​ AVCodec:AVCodec是存储编解码信息的结构体
  4. ​​​​​​​ AVCodecContext:AVCodecContext 是编解码上下文,它主要的功能是除了存储AVCodec的信息外,还保存了额外的编码属性
  5. AVIOContext:其中AVIOContext是FFMPEG管理输入输出数据的结构体

 02 ffmpeg初始化代码分析

 这个代我们要我们要先从这个结构体开始看

这个结构体会有些许复杂

typedef struct
{AVStream *stream;  /*主要储存了音视频流的具体信息*/AVCodecContext *enc;   //编解码上下文,它主要的功能是除了存储 AVCodec 的信息外,还保存了额外的编码属性int64_t next_timestamp;  //int samples_count;AVPacket *packet;   //压缩后的数据和关于这些数据的一些附加的信息,如显示时间戳(pts),解码时间戳(dts),数据时长(duration),所在流媒体的索引(stream_index)等等。
} OutputStream;typedef struct
{unsigned int config_id;int protocol_type;                    //流媒体TYPEchar network_addr[NETWORK_ADDR_LENGTH];//流媒体地址enum AVCodecID video_codec; //视频编码器IDenum AVCodecID audio_codec; //音频编码器IDOutputStream video_stream; //VIDEO的STREAM配置OutputStream audio_stream; //AUDIO的STREAM配置AVFormatContext *oc; //是存储音视频封装格式中包含的信息的结构体,也是FFmpeg中统领全局的结构体,对文件的封装、编码操作从这里开始。
} RKMEDIA_FFMPEG_CONFIG; //FFMPEG配置

 

这个结构体很重要,这里面保存着配置相关的所有信息

其中最重要的结构体是AVFormatContext,里面存储音视频封装格式中包含的信息的结构体,

也是FFmpeg中统领全局的结构体,对文件的封装、编码操作从这里开始。

 将一些简单的参数配置完后,我们看一下如何初始化FFmpeg

 ffmpeg输出模块初始化大概就是这八步,我们一步一步解析

2.1 根据需要配置码流属性avformat_alloc_output_context2()

函数原型:

int avformat_alloc_output_context2(AVFormatContext **ctx, 
AVOutputFormat *oformat, const char *format_name, const char *filename)
  1. 第一个传输参数:AVFormatContext结构体指针的指针,是存储音视频封装格式中包含的信息的结构体,所有对文件的封装、编码都是从这个结构体开始。
  2. 第二个传输参数:AVOutputFormat的结构体指针,它主要存储复合流信息的常规配置,默认为设置NULL。
  3. 第三个传输参数:format_name指的是复合流的格式,比方说:flv、ts、mp4等等
  4. 第四个传输参数:filename是输出地址,输出地址可以是本地文件(如:xxx.mp4、xxx.ts等等)。也可以是网络流地址(如:rtmp://xxx.xxx.xxx.xxx:1935/live/01)

2.2配置推流器编码参数和AVStream结构体

AVStream主要是存储流信息结构体,这个流信息包含音频流和视频流。

创建的API是avformat_new_stream如下

 函数原型:

AVStream *avformat_new_stream(AVFormatContext *s, const AVCodec *c)
  • 参数1:AVFormatContext的结构体指针
  • 参数2:AVDictionary结构体指针的指针
  • 返回值:成功返回AVStream结构体指针,失败返回NULL

创建输出码流AVStream, AVStream是存储每一个视频/音频流信息的结构体


 2.3找到编码器avcodec_find_encoder

找到对应的编码ID

函数原型:

AVCodec *avcodec_find_encoder(AVCodecID id)

 

  •  参数1:请求编码器的编号
  • 返回值:返回查找到的解码器(没有找到就返回NULL

 2.4 avcodec_alloc_context3分配AVCodecContext结构体

函数原型:

AVCodecContext *avcodec_alloc_context3(const AVCodec *codec)

功能

  • 分配一个AVCodecContext,并将其字段设置为默认值。
  • 结果由avcodec_free_context()释放

参数

  • 如果非null,分配私有数据并初始化给定编解码器的默认值。使用不同的编解码器调用avcodec_open2()是非法的。
  • 如果为NULL,那么特定于编解码器的默认值将不会被初始化,这可能会导致默认设置不理想(这对于编码器(例如libx264)尤为重要)。

返回值

  • 一个用默认值填充的AVCodecContext,失败时为NULL。

 2.5 设置AVCodecContext的参数

 

FFMPEG的视频编码参数如:分辨率(WIDTHHEIGHT)、时间基(time_base)、 帧率(r_frame_rate)、GOP_SIZE等都需要和右边VENC的参数要一一对应起来。其中time_base的值要和视频帧率必须要一致。

FFMPEG的音频编码参数如:音频采样格式(sample_fmt)、音频码率(bit_rate)、 音频采样率(sample_rate)、 音频布局(channel_layout)、 音频通道(channels)、 时间基(time_base)等都需要和右边AENC的参数一一对应。其中time_base的值必须要和音频采样率要一致。

 

AV_CODEC_FLAG_GLOBAL_HEADER发送视频数据的时候都会在关键帧前面添加SPS/PPS,这个标识符在FFMPEG初始化的时候都需要添加。

 2.6 使能推流编码器

这里的open_videoopen_audio就是使能推流编码器,其中avcodec_open2让编码器和编码器上下文进行关联。并用avcodec_parameters_from_context把刚初始化的上下文传输到AVStream的编解码器。

 2.7打开IO文件操作

使用avio_open打开对应的文件,注意这里的文件不仅是指本地的文件也指的是网络流媒体文件,下面是avio_open的定义。

int avio_open(AVIOContext **s, const char *url, int flags);
  1. 第一个参数:AVIOContext的结构体指针,它主要是管理数据输入输出的结构体
  2. 第二个参数: url地址,这个URL地址既包括本地文件如(xxx.ts、xxx.mp4),也可以是网络流媒体地址,如(rtmp://192.168.22.22:1935/live/01)等
  3. 第三个参数:flags标识符

#define AVIO_FLAG_READ  1                                      /**< read-only */

#define AVIO_FLAG_WRITE 2                                      /**< write-only */

#define AVIO_FLAG_READ_WRITE (AVIO_FLAG_READ|AVIO_FLAG_WRITE)  /**< read-write pseudo flag */

2.8  avformat_write_header对头部进行初始化

int avformat_write_header(AVFormatContext *s, AVDictionary **options);
  • 第一个参数:传递AVFormatContext结构体指针
  • 第二个参数:传递AVDictionary结构体指针的指针

 

这篇关于P10 RV1126推流项目——ffmpeg输出参数初始化的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/571035

相关文章

SpringBoot请求参数接收控制指南分享

《SpringBoot请求参数接收控制指南分享》:本文主要介绍SpringBoot请求参数接收控制指南,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Spring Boot 请求参数接收控制指南1. 概述2. 有注解时参数接收方式对比3. 无注解时接收参数默认位置

SpringBoot项目中报错The field screenShot exceeds its maximum permitted size of 1048576 bytes.的问题及解决

《SpringBoot项目中报错ThefieldscreenShotexceedsitsmaximumpermittedsizeof1048576bytes.的问题及解决》这篇文章... 目录项目场景问题描述原因分析解决方案总结项目场景javascript提示:项目相关背景:项目场景:基于Spring

解决Maven项目idea找不到本地仓库jar包问题以及使用mvn install:install-file

《解决Maven项目idea找不到本地仓库jar包问题以及使用mvninstall:install-file》:本文主要介绍解决Maven项目idea找不到本地仓库jar包问题以及使用mvnin... 目录Maven项目idea找不到本地仓库jar包以及使用mvn install:install-file基

Python使用getopt处理命令行参数示例解析(最佳实践)

《Python使用getopt处理命令行参数示例解析(最佳实践)》getopt模块是Python标准库中一个简单但强大的命令行参数处理工具,它特别适合那些需要快速实现基本命令行参数解析的场景,或者需要... 目录为什么需要处理命令行参数?getopt模块基础实际应用示例与其他参数处理方式的比较常见问http

springboot项目如何开启https服务

《springboot项目如何开启https服务》:本文主要介绍springboot项目如何开启https服务方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录springboot项目开启https服务1. 生成SSL证书密钥库使用keytool生成自签名证书将

Java数组初始化的五种方式

《Java数组初始化的五种方式》数组是Java中最基础且常用的数据结构之一,其初始化方式多样且各具特点,本文详细讲解Java数组初始化的五种方式,分析其适用场景、优劣势对比及注意事项,帮助避免常见陷阱... 目录1. 静态初始化:简洁但固定代码示例核心特点适用场景注意事项2. 动态初始化:灵活但需手动管理代

将Java项目提交到云服务器的流程步骤

《将Java项目提交到云服务器的流程步骤》所谓将项目提交到云服务器即将你的项目打成一个jar包然后提交到云服务器即可,因此我们需要准备服务器环境为:Linux+JDK+MariDB(MySQL)+Gi... 目录1. 安装 jdk1.1 查看 jdk 版本1.2 下载 jdk2. 安装 mariadb(my

Linux内核参数配置与验证详细指南

《Linux内核参数配置与验证详细指南》在Linux系统运维和性能优化中,内核参数(sysctl)的配置至关重要,本文主要来聊聊如何配置与验证这些Linux内核参数,希望对大家有一定的帮助... 目录1. 引言2. 内核参数的作用3. 如何设置内核参数3.1 临时设置(重启失效)3.2 永久设置(重启仍生效

QT进行CSV文件初始化与读写操作

《QT进行CSV文件初始化与读写操作》这篇文章主要为大家详细介绍了在QT环境中如何进行CSV文件的初始化、写入和读取操作,本文为大家整理了相关的操作的多种方法,希望对大家有所帮助... 目录前言一、CSV文件初始化二、CSV写入三、CSV读取四、QT 逐行读取csv文件五、Qt如何将数据保存成CSV文件前言

Node.js 数据库 CRUD 项目示例详解(完美解决方案)

《Node.js数据库CRUD项目示例详解(完美解决方案)》:本文主要介绍Node.js数据库CRUD项目示例详解(完美解决方案),本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考... 目录项目结构1. 初始化项目2. 配置数据库连接 (config/db.js)3. 创建模型 (models/