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

FFmpeg【SDK02】关于AVIO的一些使用

 读取本地文件(网络流)信息

#include <iostream>
#include <stdio.h>extern "C"
{
#include <libavformat\avformat.h>
#include <libavutil\avutil.h>
#include <libavutil\log.h>
#include <libavformat\avio.h>
#include <libavutil\file.h>
#include <libavcodec\avcodec.h>
#include <libavutil\error.h>
}#pragma comment(lib, "avformat.lib")
#pragma comment(lib, "avutil.lib")// 1. 读取本地文件 和 网络流(rtsp)
void readLoadHostFile()
{// av_register_all();		// ffmpeg4.0 版本后被抛弃avformat_network_init();	// 使用网络流时需要添加AVFormatContext* pAVFmtCtx = NULL;AVInputFormat*   pAVInputFmt = NULL;pAVFmtCtx = avformat_alloc_context();		// 申请AVFormatContext内存// 打开文件流或网络流// No1. 本地文件流		input_5s.mp4// No2. VLC推rtsp流		rtsp://:8554/rtsp1	rtsp://localhost:8554/rtsp1if (avformat_open_input(&pAVFmtCtx, "input_5s.mp4", pAVInputFmt, NULL)){av_log(pAVFmtCtx, AV_LOG_WARNING, "open file/networkStream faild!\n");avformat_free_context(pAVFmtCtx);		// 释放AVFormatContext内存avformat_network_deinit();return;}av_log(pAVFmtCtx, AV_LOG_INFO, "open file/networkStream success!\n");// 查找流信息if (avformat_find_stream_info(pAVFmtCtx, NULL) < 0){av_log(pAVFmtCtx, AV_LOG_WARNING, "find stream info faild!\n");	avformat_close_input(&pAVFmtCtx); avformat_free_context(pAVFmtCtx);		avformat_network_deinit();return;}av_log(pAVFmtCtx, AV_LOG_INFO, "find stream info success!\n");// 打印流的个数av_log(pAVFmtCtx, AV_LOG_INFO, "nbstream: %d\n", pAVFmtCtx->nb_streams);avformat_close_input(&pAVFmtCtx);			// 先关闭再释放avformat_free_context(pAVFmtCtx);		avformat_network_deinit();
}

 使AVIO获取视频文件信息

// 2. 自定义AVIO
// 读回调(返回读取的字节数)
int read_callback(void *opaque, uint8_t *buf, int buf_size)
{FILE* fp = (FILE*)opaque;size_t size = fread(buf, sizeof(uint8_t), buf_size, fp);printf("Read Bytes: %d\n", size);return (int)size;
}// 返回seek到的位置
int64_t seek_callback(void *opaque, int64_t offset, int whence)
{FILE *fp = (FILE*)opaque;if (whence == AVSEEK_SIZE) {return -1;}fseek(fp, offset, whence);return ftell(fp);
}void selfDefAVIO()
{AVFormatContext* pAVFmtCtx = NULL;AVInputFormat*   pAVInputFmt = NULL;pAVFmtCtx = avformat_alloc_context();FILE* fp = fopen("input_5s.mp4", "rb");int nBuffSize = 1024;// unsigned char* buffer = (unsigned char*)malloc(nBuffSize);	// 此处使用malloc会中断uint8_t* buffer = (uint8_t*)av_malloc(nBuffSize);AVIOContext* pAVIOCtx = avio_alloc_context(buffer, nBuffSize, 0,fp,				// 文件指针read_callback,	// 读回调0,				// 写回调seek_callback);	// 定位回调if (NULL == pAVIOCtx){av_log(NULL, AV_LOG_WARNING, "AVIOContext alloc faild!\n");av_free(pAVIOCtx);return;}pAVFmtCtx->pb = pAVIOCtx;					// 将AVIOContext绑定到AVFormatContextpAVFmtCtx->flags = AVFMT_FLAG_CUSTOM_IO;	// 告诉ffmpeg自己创建AVIOContext(不需要它再创建)// 打开流if (avformat_open_input(&pAVFmtCtx, "", pAVInputFmt, NULL) < 0){av_log(pAVFmtCtx, AV_LOG_WARNING, "open file stream faild!\n");av_free(pAVIOCtx);avformat_free_context(pAVFmtCtx);		// 释放AVFormatContext内存return;}av_log(pAVFmtCtx, AV_LOG_INFO, "open file stream success!\n");// 进一步读取流信息(为 pFormatCtx->streams 填充上正确的信息)if (avformat_find_stream_info(pAVFmtCtx, NULL) < 0){av_log(pAVFmtCtx, AV_LOG_WARNING, "find stream info faild!\n");avformat_close_input(&pAVFmtCtx);av_free(pAVIOCtx);avformat_free_context(pAVFmtCtx);	return;}av_log(pAVFmtCtx, AV_LOG_INFO, "find stream info success!\n");// 打印流的个数av_log(pAVFmtCtx, AV_LOG_INFO, " nbstream: %d\n", pAVFmtCtx->nb_streams);avformat_close_input(&pAVFmtCtx);av_free(pAVIOCtx);avformat_free_context(pAVFmtCtx);
}

 使用AVIO和自定义数据类型获取视频文件信息

// 3. 自定义数据来源(可以是文件,内存,网络流)
struct buffer_data	// 自定义缓冲区
{uint8_t *ptr;size_t size;	// size left in the buffer
};//读取数据(回调函数)
static int read_packet(void *opaque, uint8_t *buf, int buf_size)
{struct buffer_data *bd = (struct buffer_data*)opaque;buf_size = FFMIN(buf_size, bd->size);if (!buf_size)			// 0return AVERROR_EOF;printf("ptr:%p size:%d\n", bd->ptr, bd->size);/// 灵活应用[内存buf]:读取的是内存,例如:加密播放器,这里解密memcpy(buf, bd->ptr, buf_size);bd->ptr += buf_size;bd->size -= buf_size;return buf_size;
}void selfDefDataSrc()
{struct buffer_data bd = { 0 };// 1. 将文件映射到内存上int nRet = av_file_map("input_5s.mp4", &bd.ptr, &bd.size, 0, NULL);if (nRet < 0){av_log(NULL, AV_LOG_ERROR, "map file to memory faild!\n");return;}av_log(NULL, AV_LOG_INFO, "map file to memory success!\n");// 2. 创建AVFormatContext对象AVFormatContext* pAVFmtCtx = NULL;pAVFmtCtx = avformat_alloc_context();if (NULL == pAVFmtCtx){av_log(NULL, AV_LOG_ERROR, "create AVFormatContext faild!\n");av_file_unmap(bd.ptr, bd.size);	// 内存映射文件:解绑定return;}av_log(NULL, AV_LOG_INFO, "create AVFormatContext success!\n");// 3. 为avio buffer分配内存uint8_t* avio_ctx_buffer = NULL;size_t avio_ctx_buffer_size = 4096;				// 回调每次读取 4096 bytesavio_ctx_buffer = (uint8_t*)av_malloc(avio_ctx_buffer_size);if (!avio_ctx_buffer) {av_log(NULL, AV_LOG_ERROR, "av_malloc avio_ctx_buffer faild!\n");avformat_free_context(pAVFmtCtx);av_file_unmap(bd.ptr, bd.size);return;}av_log(NULL, AV_LOG_INFO, "av_malloc avio_ctx_buffer success!\n");AVIOContext* avio_ctx = avio_alloc_context(avio_ctx_buffer, avio_ctx_buffer_size,0,&bd,					// 从bd里面读数据&read_packet,			NULL,NULL);if (!avio_ctx) {av_log(NULL, AV_LOG_ERROR, "avio_alloc_context AVIOContext faild!\n");av_freep(avio_ctx_buffer);avformat_free_context(pAVFmtCtx);av_file_unmap(bd.ptr, bd.size);return;}pAVFmtCtx->pb = avio_ctx;av_log(NULL, AV_LOG_INFO, "avio_alloc_context AVIOContext success!\n");nRet = avformat_open_input(&pAVFmtCtx, NULL, NULL, NULL);if (nRet){av_log(NULL, AV_LOG_ERROR, "avformat_open_input faild!\n");avio_context_free(&avio_ctx);av_freep(avio_ctx_buffer);avformat_free_context(pAVFmtCtx);av_file_unmap(bd.ptr, bd.size);return;}av_log(NULL, AV_LOG_INFO, "avformat_open_input success!\n");// 查找流信息nRet = avformat_find_stream_info(pAVFmtCtx, NULL);if (nRet < 0) {av_log(NULL, AV_LOG_ERROR, "avformat_find_stream_info faild!\n");avformat_close_input(&pAVFmtCtx);avio_context_free(&avio_ctx);av_freep(avio_ctx_buffer);avformat_free_context(pAVFmtCtx);av_file_unmap(bd.ptr, bd.size);return;}av_log(NULL, AV_LOG_INFO, "avformat_find_stream_info success!\n");printf(" 》》》nb_streams=%d\n", pAVFmtCtx->nb_streams);av_dump_format(pAVFmtCtx, 0, "input_5s.mp4", 0);// 关闭释放资源avformat_close_input(&pAVFmtCtx);if (avio_ctx)av_freep(&avio_ctx->buffer);avio_context_free(&avio_ctx);av_file_unmap(bd.ptr, bd.size);
}

相关文章:

  • Jenkins设置使用163邮箱发送邮件
  • html基本标签
  • 【力扣经典面试题】14. 最长公共前缀
  • 【JavaEE】_Spring MVC项目使用数组与集合传参
  • 模拟退火算法(带你了解原理 实践)
  • 【ELK日志分析系统】ELK+Filebeat分布式日志管理平台部署
  • Linux:kubernetes(k8s)搭建mater节点(kubeadm,kubectl,kubelet)(2)
  • 如何关闭远程桌面连接
  • day12_SpringCloud(Gateway,Nacos配置中心,Sentinel组件)
  • Linux - 进程概念
  • 补点基础——几何尺寸和公差
  • Linux设备模型(八) - sysfs
  • 全量知识系统问题及SmartChat给出的答复 之13 解析器+DDD+文法型
  • Java,数组加元素,反转数组
  • http和https的区别是什么?
  • 77. Combinations
  • Angular js 常用指令ng-if、ng-class、ng-option、ng-value、ng-click是如何使用的?
  • Java面向对象及其三大特征
  • Map集合、散列表、红黑树介绍
  • SwizzleMethod 黑魔法
  • Web设计流程优化:网页效果图设计新思路
  • 表单中readonly的input等标签,禁止光标进入(focus)的几种方式
  • 利用DataURL技术在网页上显示图片
  • 前端学习笔记之观察者模式
  • 设计模式走一遍---观察者模式
  • 详解移动APP与web APP的区别
  • 一道闭包题引发的思考
  • 因为阿里,他们成了“杭漂”
  • Java数据解析之JSON
  • scrapy中间件源码分析及常用中间件大全
  • ​Java并发新构件之Exchanger
  • #Java第九次作业--输入输出流和文件操作
  • #Linux(权限管理)
  • #NOIP 2014#day.2 T1 无限网络发射器选址
  • (32位汇编 五)mov/add/sub/and/or/xor/not
  • (C语言)球球大作战
  • (Python) SOAP Web Service (HTTP POST)
  • (八)Docker网络跨主机通讯vxlan和vlan
  • (附源码)计算机毕业设计高校学生选课系统
  • (十八)用JAVA编写MP3解码器——迷你播放器
  • (一)SpringBoot3---尚硅谷总结
  • (转)JVM内存分配 -Xms128m -Xmx512m -XX:PermSize=128m -XX:MaxPermSize=512m
  • (转)shell中括号的特殊用法 linux if多条件判断
  • ... 是什么 ?... 有什么用处?
  • .L0CK3D来袭:如何保护您的数据免受致命攻击
  • .NET 8 中引入新的 IHostedLifecycleService 接口 实现定时任务
  • .net CHARTING图表控件下载地址
  • .NET Core实战项目之CMS 第一章 入门篇-开篇及总体规划
  • .NET 使用 XPath 来读写 XML 文件
  • .net知识和学习方法系列(二十一)CLR-枚举
  • .NET值类型变量“活”在哪?
  • .net中的Queue和Stack
  • @ModelAttribute 注解
  • [ C++ ] STL priority_queue(优先级队列)使用及其底层模拟实现,容器适配器,deque(双端队列)原理了解
  • [ Linux 长征路第二篇] 基本指令head,tail,date,cal,find,grep,zip,tar,bc,unname