音视频开发—FFmpeg处理流数据的基本概念详解

文章目录

    • 多媒体文件的基本概念
    • 相关重要的结构体
    • 操作数据流的基本步骤
      • 1.解复用(Demuxing)
      • 2.获取流(Stream)
      • 3. 读取数据包(Packet)
      • 4. 释放资源(Free Resources)
      • 完整示例

多媒体文件的基本概念

  • 多媒体文件其实是个容器

多媒体文件(如MP4、MKV、AVI等)实际上是一个容器格式。容器的作用是将不同类型的数据(如视频、音频、字幕等)封装在一个文件中,方便管理和播放。每种容器格式都有自己的规范,定义了如何组织和存储这些不同类型的数据。

  • 在容器里有很多流

在多媒体容器文件中,可以包含多个不同的流。每个流代表一种媒体数据,例如视频流、音频流、字幕流等。一个典型的多媒体文件通常至少包含一个视频流和一个音频流,但也可以包含多个视频流、多个音频流和其他类型的流(如字幕、章节信息、元数据等)。

  • 每种流是由不同的编码器编码实现的

每个流的数据在存储之前需要经过编码。编码器(如H.264、AAC、MP3等)将原始的多媒体数据(如未压缩的视频和音频)转换成压缩格式,以减少存储空间和传输带宽。不同的编码器适用于不同类型的数据和使用场景。例如,视频流可能使用H.264编码器,音频流可能使用AAC编码器。

  • 从流中读出的数据叫做包

在流中,数据被分成一个个的数据包(packet)。每个包包含一段编码后的多媒体数据,以及一些元数据(如时间戳、流的标识等)。在解码和播放时,播放器会从容器文件中读取这些数据包,并将其传递给相应的解码器进行解码。

  • 在一个包中包含多个帧

数据包中的内容进一步细分为帧。帧是视频或音频数据的最小单位。例如,在视频流中,每一帧代表一个静止的图像,连续播放这些图像可以形成视频。在音频流中,每一帧代表一段音频采样数据。帧的数量和类型(如关键帧、预测帧等)取决于编码器的工作方式和编码参数。

相关重要的结构体

  • AVFormatContext 结构体

AVFormatContext 是 FFmpeg 中用于描述多媒体文件或流的上下文结构体。它包含了文件格式、输入输出协议、文件信息以及多个流等信息。

  • AVStream 结构体

AVStream 是 FFmpeg 中用于描述多媒体文件中的一个流(如视频流、音频流、字幕流等)的结构体。每个 AVStream 包含了流的编解码信息、时间基准等。

  • AVPacket

AVPacket 是 FFmpeg 中用于描述存储在容器中的多媒体数据包的结构体。数据包是编码后的数据,包含一组帧。

操作数据流的基本步骤

在这里插入图片描述

1.解复用(Demuxing)

解复用是指从多媒体容器中提取出独立的音频、视频和其他流的过程。在FFmpeg中,解复用通过打开文件并解析文件头部信息来实现。

主要步骤

  • 注册所有格式和编解码器: 使用 av_register_all() 注册FFmpeg支持的所有格式和编解码器(FFmpeg 4.x及以前版本需要,FFmpeg 5.0及以后版本不需要)。
  • 打开输入文件: 使用 avformat_open_input() 打开输入文件。
  • 读取文件头部信息: 使用 avformat_find_stream_info() 读取文件头部信息。

示例代码

AVFormatContext *fmt_ctx = NULL;
int ret;// 注册所有格式和编解码器(FFmpeg 4.x及以前版本需要)
av_register_all();// 打开输入文件
if ((ret = avformat_open_input(&fmt_ctx, "input.mp4", NULL, NULL)) < 0) {av_log(NULL, AV_LOG_ERROR, "Cannot open input file: %s\n", av_err2str(ret));return ret;
}// 读取文件头部信息
if ((ret = avformat_find_stream_info(fmt_ctx, NULL)) < 0) {av_log(NULL, AV_LOG_ERROR, "Cannot find stream information: %s\n", av_err2str(ret));avformat_close_input(&fmt_ctx);return ret;
}// 打印输入文件的信息
av_dump_format(fmt_ctx, 0, "input.mp4", 0);

2.获取流(Stream)

获取流是指从多媒体文件中提取出各个独立的流,例如音频流和视频流。每个流包含了相关的编解码信息。

主要步骤

  • 查找音频和视频流: 遍历 AVFormatContext 中的流,查找音频和视频流。
  • 打印流信息: 打印每个流的信息。

示例代码

AVStream *video_stream = NULL;
AVStream *audio_stream = NULL;for (unsigned int i = 0; i < fmt_ctx->nb_streams; i++) {AVStream *stream = fmt_ctx->streams[i];if (stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {video_stream = stream;} else if (stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {audio_stream = stream;}
}if (!video_stream && !audio_stream) {av_log(NULL, AV_LOG_ERROR, "No video or audio stream found\n");avformat_close_input(&fmt_ctx);return -1;
}

3. 读取数据包(Packet)

读取数据包是指从文件中逐个读取编码后的数据包。数据包可以包含音频、视频或其他类型的数据。

主要步骤

  • 初始化数据包: 使用 av_init_packet() 初始化数据包。
  • 读取数据包: 使用 av_read_frame() 读取数据包。
  • 处理数据包: 根据数据包所属的流进行相应处理。
  • 释放数据包: 使用 av_packet_unref() 释放数据包。

示例代码

AVPacket pkt;
av_init_packet(&pkt);
pkt.data = NULL;
pkt.size = 0;while (av_read_frame(fmt_ctx, &pkt) >= 0) {if (pkt.stream_index == video_stream->index) {// 处理视频数据包av_log(NULL, AV_LOG_INFO, "Video Packet: PTS=%" PRId64 ", DTS=%" PRId64 ", size=%d\n",pkt.pts, pkt.dts, pkt.size);} else if (pkt.stream_index == audio_stream->index) {// 处理音频数据包av_log(NULL, AV_LOG_INFO, "Audio Packet: PTS=%" PRId64 ", DTS=%" PRId64 ", size=%d\n",pkt.pts, pkt.dts, pkt.size);}av_packet_unref(&pkt);
}

4. 释放资源(Free Resources)

释放资源是指在完成数据流操作后,释放分配的所有内存和资源,以避免内存泄漏。

主要步骤

  • 释放数据包: 使用 av_packet_unref() 释放每个数据包。
  • 关闭输入文件: 使用 avformat_close_input() 关闭输入文件并释放 AVFormatContext
  • 释放其他资源: 释放任何其他分配的资源。

示例代码

// 释放数据包
av_packet_unref(&pkt);// 关闭输入文件并释放AVFormatContext
avformat_close_input(&fmt_ctx);

完整示例

#include <libavformat/avformat.h>
#include <libavutil/log.h>int main(int argc, char *argv[]) {AVFormatContext *fmt_ctx = NULL;AVPacket pkt;AVStream *video_stream = NULL;AVStream *audio_stream = NULL;int ret;if (argc < 2) {fprintf(stderr, "Usage: %s <input file>\n", argv[0]);return 1;}// 注册所有格式和编解码器(FFmpeg 4.x及以前版本需要)av_register_all();// 打开输入文件if ((ret = avformat_open_input(&fmt_ctx, argv[1], NULL, NULL)) < 0) {av_log(NULL, AV_LOG_ERROR, "Cannot open input file: %s\n", av_err2str(ret));return ret;}// 读取文件头部信息if ((ret = avformat_find_stream_info(fmt_ctx, NULL)) < 0) {av_log(NULL, AV_LOG_ERROR, "Cannot find stream information: %s\n", av_err2str(ret));avformat_close_input(&fmt_ctx);return ret;}// 打印输入文件的信息av_dump_format(fmt_ctx, 0, argv[1], 0);// 查找音频和视频流for (unsigned int i = 0; i < fmt_ctx->nb_streams; i++) {AVStream *stream = fmt_ctx->streams[i];if (stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {video_stream = stream;} else if (stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {audio_stream = stream;}}if (!video_stream && !audio_stream) {av_log(NULL, AV_LOG_ERROR, "No video or audio stream found\n");avformat_close_input(&fmt_ctx);return -1;}// 初始化数据包av_init_packet(&pkt);pkt.data = NULL;pkt.size = 0;// 读取数据包while (av_read_frame(fmt_ctx, &pkt) >= 0) {if (pkt.stream_index == video_stream->index) {// 处理视频数据包av_log(NULL, AV_LOG_INFO, "Video Packet: PTS=%" PRId64 ", DTS=%" PRId64 ", size=%d\n",pkt.pts, pkt.dts, pkt.size);} else if (pkt.stream_index == audio_stream->index) {// 处理音频数据包av_log(NULL, AV_LOG_INFO, "Audio Packet: PTS=%" PRId64 ", DTS=%" PRId64 ", size=%d\n",pkt.pts, pkt.dts, pkt.size);}av_packet_unref(&pkt);}// 关闭输入文件并释放AVFormatContextavformat_close_input(&fmt_ctx);return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/373225.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于SpringBoot构造超简易QQ邮件服务发送(分离-图解-新手)

目录 获取QQ 授权码 SpringBoot构建 依赖 Yaml配置 服务编写 测试 获取QQ 授权码 https://mail.qq.com/ 接着后就会有对应的密钥了 SpringBoot构建 依赖 这里的建议是 2.0系列的Springboot版本用低一点的邮件依赖 <!-- 电子邮件 --> <dependency>&…

字节码编程javassist之生成带有注解的类

写在前面 本文看下如何使用javassist生成带有注解的类。 1&#xff1a;程序 测试类 package com.dahuyou.javassist.huohuo.cc;import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import ja…

神经网络设计过程

1.可根据Iris特征直接判断 2.神经网络方法&#xff0c;采集大量的Iris特征&#xff0c;分类对应标签&#xff0c;构成数据集。 将数据集喂入搭好的神经网络结构&#xff0c;网络通过反向传播优化参数得到模型。 有新的网络送入到模型里&#xff0c;模型会给出识别结果。 3.…

低空经济火爆:无人机培训机构工作开展详解

随着低空经济的迅速崛起&#xff0c;无人机技术在多个领域得到了广泛应用&#xff0c;从航拍摄影、农业植保到物流配送、环境监测等&#xff0c;都显示出了巨大的市场潜力。无人机培训机构作为培养专业无人机驾驶和操作人才的摇篮&#xff0c;在低空经济的发展中扮演着至关重要…

Vue项目openlayers中使用jsts处理wkt和geojson的交集-(geojson来源zpi解析)

Vue项目openlayers中使用jsts处理wkt和geojson的交集-(geojson来源zpi解析) 读取压缩包中的shape看上一篇笔记&#xff1a;Vue项目读取zip中的ShapeFile文件&#xff0c;并解析为GeoJson openlayers使用jsts官方示例&#xff1a;https://openlayers.org/en/latest/examples/j…

已解决 javax.xml.transform.TransformerFactoryConfigurationError 异常的正确解决方法,亲测有效!!!

已解决 javax.xml.transform.TransformerFactoryConfigurationError 异常的正确解决方法&#xff0c;亲测有效&#xff01;&#xff01;&#xff01; 目录 一、问题分析 二、报错原因 三、解决思路 四、解决方法 五、总结 博主v&#xff1a;XiaoMing_Java 博主v&#x…

昇思25天学习打卡营第16天|Vision Transformer图像分类

昇思25天学习打卡营第16天|Vision Transformer图像分类 前言Vision Transformer图像分类Vision Transformer&#xff08;ViT&#xff09;简介模型结构模型特点 环境准备与数据读取模型解析Transformer基本原理Attention模块 Transformer EncoderViT模型的输入整体构建ViT 模型训…

【自学网络安全】:安全策略与用户认证综合实验

实验拓扑图&#xff1a; 实验任务&#xff1a; 1、DMZ区内的服务器&#xff0c;办公区仅能在办公时间内(9:00-18:00)可以访问&#xff0c;生产区的设备全天可以访问 2、生产区不允许访问互联网&#xff0c;办公区和游客区允许访问互联网 3、办公区设备10.0.2.10不允许访问Dmz区…

代理详解之静态代理、动态代理、SpringAOP实现

1、代理介绍 代理是指一个对象A通过持有另一个对象B&#xff0c;可以具有B同样的行为的模式。为了对外开放协议&#xff0c;B往往实现了一个接口&#xff0c;A也会去实现接口。但是B是“真正”实现类&#xff0c;A则比较“虚”&#xff0c;他借用了B的方法去实现接口的方法。A…

未羽研发测试管理平台

突然有一些觉悟&#xff0c;程序猿不能只会吭哧吭哧的低头做事&#xff0c;应该学会怎么去展示自己&#xff0c;怎么去宣传自己&#xff0c;怎么把自己想做的事表述清楚。 于是&#xff0c;这两天一直在整理自己的作品&#xff0c;也为接下来的找工作多做点准备。接下来…

wordpress外贸建站公司案例英文模板

Indirect Trade WP外贸网站模板 WordPress Indirect Trade外贸网站模板&#xff0c;建外贸独立站用wordpress模板&#xff0c;快速搭建十分便捷。 衣物清洁wordpress独立站模板 洗衣粉、洗衣液、衣物柔顺剂、干洗剂、衣领净、洗衣皂等衣物清洁wordpress独立站模板。 家具wordpr…

Apache部署与配置

概述 介绍 Apache HTTP Server(简称Apache)是Apache的一个开源的网页服务器&#xff0c;它源自NCSAhttpd服务器&#xff0c;并经过多次修改和发展&#xff0c;如今已经成为全球范围内广泛使用的Web服务器软件之一 特点 跨平台&#xff1a;可以运行在几乎所有广泛使用的计算机平…

哪个充电宝口碑比较好?怎么选充电宝?2024年口碑优秀充电宝推荐

在如今快节奏的生活中&#xff0c;充电宝已然成为我们日常生活中的必备品。然而&#xff0c;市场上充电宝品牌众多&#xff0c;质量参差不齐&#xff0c;如何选择一款安全、可靠且口碑优秀的充电宝成为了消费者关注的焦点。安全性能不仅关系到充电宝的使用寿命&#xff0c;更关…

【正点原子i.MX93开发板试用连载体验】项目计划和开箱体验

本文最早发表于电子发烧友&#xff1a;【   】【正点原子i.MX93开发板试用连载体验】基于深度学习的语音本地控制 - 正点原子学习小组 - 电子技术论坛 - 广受欢迎的专业电子论坛! (elecfans.com)https://bbs.elecfans.com/jishu_2438354_1_1.html 有一段时间没有参加电子发…

clickhouse-jdbc-bridge rce

clickhouse-jdbc-bridge 是什么 JDBC bridge for ClickHouse. It acts as a stateless proxy passing queries from ClickHouse to external datasources. With this extension, you can run distributed query on ClickHouse across multiple datasources in real time, whic…

支持向量机 (support vector machine,SVM)

支持向量机 &#xff08;support vector machine&#xff0c;SVM&#xff09; flyfish 支持向量机是一种用于分类和回归的机器学习模型。在分类任务中&#xff0c;SVM试图找到一个最佳的分隔超平面&#xff0c;使得不同类别的数据点在空间中被尽可能宽的间隔分开。 超平面方…

MMGPL: 多模态医学数据分析与图提示学习| 文献速递-基于深度学习的多模态数据分析与生存分析

Title 题目 MMGPL: Multimodal Medical Data Analysis with Graph Prompt Learning MMGPL: 多模态医学数据分析与图提示学习 01 文献速递介绍 神经学障碍&#xff0c;包括自闭症谱系障碍&#xff08;ASD&#xff09;&#xff08;Lord等&#xff0c;2018年&#xff09;和阿…

kafka的副本replica

指定topic的分区和副本 通过kafka命令行工具 kafka-topics.sh --create --topic myTopic --partitions 3 --replication-factor 1 --bootstrap-server localhost:9092 执行代码时指定分区个数

基于Spring Boot框架的EAM系统设计与实现

摘 要&#xff1a;文章设计并实现一个基于Spring Boot框架的EAM系统&#xff0c;以应对传统人工管理模式存在的低效与信息管理难题。系统利用Java语言、JSP技术、MySQL数据库等技术栈&#xff0c;构建了一个B/S架构的高效管理平台&#xff0c;提升了资产管理的信息化水平。该系…

大小端详解

引例 我们知道整形(int)是4个字节&#xff0c;例如随便举个例子&#xff1a;0x01020304&#xff0c;它一共占了四个地址位&#xff0c;01,02,03,04分别占了一个字节&#xff08;一个字节就对应了一个地址&#xff09;。 那么就会有个问题&#xff1a;我们的01到底是存储在高地…