FFmpeg音视频分离器(二)

news/2024/7/24 5:06:10 标签: ffmpeg, 音视频
处理逻辑:

1.程序初始化:代码一开始初始化了所需的变量和数据结构,包括输入文件、输出文件的格式上下文以及其他参数。

2.输入文件打开和信息检索:程序尝试打开输入文件(in_filename),并检索输入文件中的流信息(视频流和音频流)。

3.输出文件创建:程序创建两个输出文件,一个用于存储视频码流(out_filename_v),另一个用于存储音频码流(out_filename_a)。这两个输出文件的格式上下文也被创建。

4.流拷贝和设置:程序遍历输入文件中的每个流,根据流的类型(视频或音频)创建相应的输出流。然后,它复制输入流的编解码器上下文到输出流,并设置一些必要的标志。

5.输出格式信息打印:程序打印出输入文件和输出文件的格式信息,以便用户了解这些文件的详细信息。

6.输出文件打开:如果输出文件不是标准输出,程序尝试打开输出文件。

7.写入文件头:程序写入输出文件的文件头,以准备开始写入数据。

8.数据分离和写入:程序进入主循环,不断读取输入文件中的数据包(AVPacket),然后将这些数据包根据它们所属的流类型(视频或音频)写入到相应的输出文件中。

9.对于视频流,如果启用了H.264比特流过滤(USE_H264BSF),程序将对视频数据包进行处理,确保它们的格式正确。

10.然后,程序将时间戳(PTS和DTS)进行转换,并写入输出文件。

11.写入文件尾:当所有数据包都被处理后,程序写入输出文件的文件尾,以完成输出。

12.资源清理:最后,程序关闭输入文件和输出文件,释放相应的资源,然后退出。

13.错误处理:在任何阶段如果出现错误,程序会打印错误消息并返回适当的错误代码。

总的来说,这段代码的主要目标是将输入文件中的视频和音频码流分离并写入到两个独立的输出文件中。这有助于将媒体文件的视频和音频部分进行拆分和处理。

重要功能代码解释

int avformat_open_input(AVFormatContext **ps, const char *url, AVInputFormat *fmt, AVDictionary **options);

FFmpeg库中用于打开输入媒体文件的函数
参数解释如下:
ps: 一个指向 AVFormatContext 指针的指针,用于存储打开文件后创建的输入格式上下文。
url: 输入媒体文件的路径或URL。
fmt: 可选参数,指定要使用的输入格式。通常情况下,你可以将其设置为 NULL,以便 FFmpeg 根据文件扩展名或内容自动检测输入格式。
options: 可选参数,用于传递额外的选项。
这个函数的作用是打开指定的输入媒体文件,并为其创建一个输入格式上下文 AVFormatContext。该上下文包含了有关输入媒体文件的信息,例如流的数量、流的类型(视频、音频等)、时长等等。一旦成功打开输入文件并创建了上下文,你可以使用这个上下文来访问媒体文件的信息以及读取其中的数据包(AVPacket)。

int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options);

用于从输入媒体文件中获取流信息的FFmpeg库函数
参数解释如下:
ic:输入媒体文件的格式上下文,也就是通过 avformat_open_input 函数打开的上下文。
options:可选参数,用于传递额外的选项。通常情况下,你可以将其设置为 NULL。
这个函数的作用是分析输入媒体文件并从中提取流(如视频流、音频流)的信息,包括流的数量、流的编解码器信息、时长、帧率等等。这些信息存储在 AVFormatContext 结构体中的 streams 数组中,每个元素对应一个流的信息。
总之,这个函数是在打开输入媒体文件后,为了了解媒体文件的结构和内容,以便后续的处理和解码操作。
相关问题:是否可以理解这个函数是用来初始化streams数组?
回答:不完全正确。avformat_find_stream_info 函数并不用于初始化 streams 数组,而是用于在打开输入媒体文件后,从实际媒体文件中解析和获取流信息,并将这些信息存储到 streams 数组中。
具体来说,这个函数的主要任务是:
1.识别输入媒体文件中存在的各种流(例如,视频流、音频流、字幕流等)。
2.获取每个流的详细信息,包括流的编解码器信息、时长、帧率、分辨率等。
3.将这些信息存储到 AVFormatContext 结构体中的 streams 数组中,使得后续的操作可以访问和利用这些流信息。
所以,它的主要作用是填充 AVFormatContext 结构体中的 streams 数组,而不是初始化该数组。初始化通常是在创建 AVFormatContext 结构体时完成的。这个函数的调用是为了获取有关媒体文件中流的更多详细信息,以便后续的媒体处理操作。

int avformat_alloc_output_context2(AVFormatContext **ctx, AVOutputFormat *oformat, const char *format_name, const char *filename);

用于创建输出媒体文件的格式上下文(AVFormatContext)
参数解释如下:
ctx:一个指向 AVFormatContext 指针的指针,用于存储创建的输出格式上下文。
oformat:可选参数,用于指定输出格式,通常可以将其设置为 NULL,以便 FFmpeg 根据输出文件的扩展名自动选择输出格式。
format_name:可选参数,用于指定输出格式的名称。
filename:输出文件的路径或URL。
这个函数的主要作用是创建一个输出格式上下文,用于准备将媒体数据写入输出文件。该上下文包含有关输出文件格式的信息,例如容器格式、编码器等。
一旦成功创建了输出格式上下文,你可以将其用于配置输出文件的各种属性,如视频编码器、音频编码器、流信息等,然后准备开始写入数据到输出文件。

AVStream *avformat_new_stream(AVFormatContext *s, const AVCodec *c);

参数解释如下:
s:指向输出格式上下文的指针,即通过 avformat_alloc_output_context2 创建的上下文。
c:指向表示流所使用编解码器的 AVCodec 结构体的指针。
这个函数的主要作用是创建一个新的输出流,以便将媒体数据(如视频、音频)写入到输出文件中。输出流包含了有关流的信息,例如编码器、时基、索引等等。
通常,在创建输出格式上下文之后,你需要为每个要写入输出文件的流类型(例如,视频、音频)创建一个相应的输出流。
一旦创建了输出流,你可以配置它,设置流的编码器和其他属性,以准备将数据写入到输出文件中。这个函数返回一个指向新创建的输出流的指针,你可以使用这个指针来进一步配置输出流的参数。

int avcodec_copy_context(AVCodecContext *dest, const AVCodecContext *src);

用于复制一个编解码器上下文(AVCodecContext)的内容到另一个编解码器上下文中
参数解释如下:
dest:目标编解码器上下文,即你要将信息复制到的上下文。
src:源编解码器上下文,即你要从中复制信息的上下文。
这个函数的主要作用是将一个编解码器上下文的配置信息(例如,编码器、编码参数、解码参数等)从源上下文复制到目标上下文中,以便两者具有相同的配置。这通常用于确保输出流的编码器配置与输入流的编码器配置相匹配。
这样做是为了确保在将媒体数据从输入流复制到输出流时,编解码器的配置保持一致,从而保持媒体数据的质量和格式。

先到这,明天继续分享!!!


http://www.niftyadmin.cn/n/5045260.html

相关文章

【Spring Cloud】 Gateway配置说明示例

Spring Cloud Gateway 是 Spring Cloud 中的一个项目,它用于构建微服务应用程序的 API 网关。Spring Cloud Gateway 建立在 Spring Boot 和 Spring WebFlux 之上,它提供了许多有用的功能,例如路由、断路器、限流、过滤器等。 在Spring Cloud…

Python经典练习题(二)

文章目录 🍀题目一🍀第二题🍀第三题🍀第四题🍀第五题 🍀题目一 古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子&am…

Java 基于微信小程序的学生选课系统

博主介绍:✌程序员徐师兄、7年大厂程序员经历。全网粉丝30W、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 文章目录 第一章: 简介第二章 技术栈第三章: 功能分析第四章 系统设计第五章 系统功…

【云原生】k8s新版本与Docker和Containerd的关联关系

目录 1.在安装k8s新版本时,没有检测到系统安装了 docker,k8s会用什么代替? 2.在安装过程中k8s如何跟docker关联的? 在较新版本的 Kubernetes 中,Docker 和 Containerd 之间的关系是相互独立的,而不是替代…

深度学习(一)读取数据 图片数据

若label作为文件夹名字,图片存放在里面: from torch.utils.data import Dataset import os import cv2 as cvclass MyData(Dataset):def __init__(self,root_dir,label_dir):self.root_dir root_dir #读取训练集的路径self.label_dir label_dir #读…

数据可视化 -- ECharts 入门

文章目录 引言1. ECharts的基本使用1.1 ECharts的快速上手1.2 相关配置讲解 2. ECharts常用图表2.1 图表1 柱状图2.1.1 柱状图的实现步骤2.1.2 柱状图的常见效果2.1.3 柱状图特点2.1.4 通用配置 2.2 图表2 折线图2.2.1 折线图的实现步骤2.2.2 折线图的常见效果2.2.3 折线图的特…

基于QT和UDP实现一个实时RTP数据包的接收,并将数据包转化成文件

简单介绍&#xff1a;代码写的比较详细&#xff0c;需要留意的地方看结尾介绍 头文件 #ifndef RTPRECEIVER_H #define RTPRECEIVER_H#include <QDialog> #include <QUdpSocket> #include <QFile> #include <QTextStream> #include <httpclient.h&g…

力扣-228.汇总区间

AC Code 自己做出来的&#xff0c;代码写的很烂&#xff0c;但是也浅浅记录一下叭&#xff0c;下面有看答案思路写出来的双指针代码 class Solution { public:vector<string> summaryRanges(vector<int>& nums) {vector<string> ans;int n nums.size();…