当前位置: 首页 > news >正文

FFmpeg--解封装流程

文章目录

      • 解复用流程:
      • 函数分析:
      • 代码实现:
      • 运行结果:

解复用流程:

  1. avformat_alloc_context 分配解复用器上下文
  2. avformat_open_input 根据url打开本地文件或网络流
  3. avformat_find_stream_info 读取媒体的部分数据包以获取码流信息
  4. av_read_frame 从文件中读取数据包
  5. avformat_close_input 关闭解复用器

函数分析:

1 avformat_open_input能否不调用avformat_alloc_context?
int avformat_open_input(AVFormatContext **ps, …);
函数说明:
May be a pointer to NULL, in which case an AVFormatContext is allocated by this
function and written into ps.
第一个参数可以传入空指针,内部为其分配空间
故可以在栈上定义的,AVFormatContext *ifmt_ctx = NULL;

2 AVFormatContext * ifmt_ctx 指针做参数传入解封装函数
AVFormatContext 是封装格式上下文结构体,保存了视频文件封装格式相关信息,可以通过ifmt_ctx指针可以用来读取文件相关信息,如文件路径,码流,文件时长,媒体流数量。

3 AVStream * in_stream 指针接收 ifmt_ctx指针指向的流文件
AVStream 对应文件中的一个流结构体,可以用来获取音频相关参数,如采样率

4 av_read_frame 音频包队列读取过程
首先对 AVPacket *pkt 申请空间,然后while(1)循环,循环体内部先通过av_read_frame读取音频包,获取音频信息,
之后将pkt 置空,读取完成后,释放pkt 空间

5 av_packet_unref 和 av_packet_free 的使用
void av_packet_unref(AVPacket *pkt);
void av_packet_free(AVPacket **pkt);
av_packet_unref(pkt) 将结构体置空,最后通过av_packet_free释放掉内存(先置空后释放内存,不然会导致内存泄露)

6 关闭解复用器
void avformat_close_input(AVFormatContext **s);

代码实现:

#include <stdio.h>
#include <libavformat/avformat.h>int main(int argc, char **argv)
{const char *filename = "123.mp4";AVFormatContext *ifmt_ctx = NULL;int audioindex = -1;        // 音频索引// 打开文件int ret = avformat_open_input(&ifmt_ctx, filename, NULL, NULL);avformat_find_stream_info(ifmt_ctx, NULL);// 文件名printf_s("open success file :%s\n", filename);//媒体流数量printf("stream number:%d\n", ifmt_ctx->nb_streams);for (uint32_t i = 0; i < ifmt_ctx->nb_streams; i++){AVStream *in_stream = ifmt_ctx->streams[i];// 音频流、视频流、字幕流//如果是音频流,则打印音频的信息if (AVMEDIA_TYPE_AUDIO == in_stream->codecpar->codec_type){// sample_rate: 音频编解码器的采样率,单位为Hzprintf("samplerate:%dHz\n", in_stream->codecpar->sample_rate);}audioindex = i; // 获取音频的索引}AVPacket *pkt = av_packet_alloc();int pkt_count = 0;printf("\nav_read_frame start:\n");while (1){ret = av_read_frame(ifmt_ctx, pkt);if (ret < 0){printf("av_read_frame end\n");break;}if(pkt_count++ < 2){if (pkt->stream_index == audioindex){printf("audio pts: %lld\n", pkt->pts);printf("audio pos: %lld\n", pkt->pos);}}av_packet_unref(pkt);}if(pkt)av_packet_free(&pkt);if(ifmt_ctx)avformat_close_input(&ifmt_ctx);getchar();return 0;
}

运行结果:

open success file :123.mp4
stream number:2
samplerate:48000Hzav_read_frame start:
audio pts: -678
audio pos: 48
av_read_frame end

相关文章:

  • 【Linux-磁盘管理】
  • DataGrip 连接 Centos MySql失败
  • “typescript“ “type predicate“ 陷阱记录
  • 牛客周赛 Round 36
  • 代码随想录刷题笔记 DAY 42 | 最后一块石头的重量 II No.1049 | 目标和 No.494 | 一和零 No.474
  • Unity使用Addressable热更新
  • 华为evpn简单配置案例
  • 【FAQ】HarmonyOS SDK 闭源开放能力 —Map Kit
  • c++之迭代器与反向迭代器
  • 学习笔记。。。
  • Vue快速开发一个主页
  • Java代码审计安全篇-常见Java SQL注入
  • Linux多线程之线程控制
  • IM6ULL学习总结(四-七-1)输入系统应用编程
  • 【SD学习】开始绘制你的第一张美图
  • avalon2.2的VM生成过程
  • echarts花样作死的坑
  • HomeBrew常规使用教程
  • JAVA SE 6 GC调优笔记
  • JavaScript标准库系列——Math对象和Date对象(二)
  • Java超时控制的实现
  • Koa2 之文件上传下载
  • Mocha测试初探
  • PHP 程序员也能做的 Java 开发 30分钟使用 netty 轻松打造一个高性能 websocket 服务...
  • Rancher-k8s加速安装文档
  • React 快速上手 - 06 容器组件、展示组件、操作组件
  • Unix命令
  • 从零开始的无人驾驶 1
  • 开源中国专访:Chameleon原理首发,其它跨多端统一框架都是假的?
  • 深入浏览器事件循环的本质
  • 字符串匹配基础上
  • 你学不懂C语言,是因为不懂编写C程序的7个步骤 ...
  • ​草莓熊python turtle绘图代码(玫瑰花版)附源代码
  • ​人工智能之父图灵诞辰纪念日,一起来看最受读者欢迎的AI技术好书
  • #我与Java虚拟机的故事#连载02:“小蓝”陪伴的日日夜夜
  • #在线报价接单​再坚持一下 明天是真的周六.出现货 实单来谈
  • (07)Hive——窗口函数详解
  • (2/2) 为了理解 UWP 的启动流程,我从零开始创建了一个 UWP 程序
  • (4)通过调用hadoop的java api实现本地文件上传到hadoop文件系统上
  • (C语言)输入一个序列,判断是否为奇偶交叉数
  • (阿里巴巴 dubbo,有数据库,可执行 )dubbo zookeeper spring demo
  • (附源码)springboot教学评价 毕业设计 641310
  • (附源码)ssm高校实验室 毕业设计 800008
  • (六)Hibernate的二级缓存
  • (十)DDRC架构组成、效率Efficiency及功能实现
  • (原創) 系統分析和系統設計有什麼差別? (OO)
  • (转)全文检索技术学习(三)——Lucene支持中文分词
  • .net Application的目录
  • .NET Core 2.1路线图
  • .NET构架之我见
  • .ui文件相关
  • @cacheable 是否缓存成功_让我们来学习学习SpringCache分布式缓存,为什么用?
  • @EnableAsync和@Async开始异步任务支持
  • [ C++ ] template 模板进阶 (特化,分离编译)
  • []T 还是 []*T, 这是一个问题