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

FFMPEG解码+SDL2播放视频

FFMPEG解码+SDL2播放

本项目通过FFmpeg对音视频进行解码,得到原始数据格式AVFrame,再通过SDL2在窗口渲染图像数据进行播放。

配置环境:vs 2022 + FFmpeg5.0 + SDL2 2.28

项目源码:https://github.com/say-Hai/FFmpeg-videoPlayDemo/tree/PlaySDL2

附录1:FFMPEG解码调用API流程

图片

附录2:SDL2库播放调用API流程

图片

关键代码:

///初始化ffmpeg相关结构体
int init_ffmpeg(FFmpeg_V_Param* p_ffmpeg_param, const char* filePath)
{
	//AVFormatContext初始化
	p_ffmpeg_param->pFormatCtx = avformat_alloc_context();
	//解码器
	const AVCodec* pcodec = NULL;
	//1.初始化网络
	//av_register_all()已被弃用
	avformat_network_init();
	//2.open输入流
	int ret = avformat_open_input(&(p_ffmpeg_param->pFormatCtx), filePath, NULL, NULL);
	if (ret < 0)
	{
		output_log(LOG_ERROR, "avformat_open_input error");
		return -1;
	}
	//3.读取媒体的数据包以获取具体的流信息,如媒体存入的编码格式。
	ret = avformat_find_stream_info(p_ffmpeg_param->pFormatCtx, NULL);
	if (ret < 0)
	{
		output_log(LOG_ERROR, "avformat_find_stream_info error");
		return -1;
	}
	//4.遍历 FFmpeg 中 AVFormatContext 的所有媒体流
	//get video pCodecParms, codec and frame rate
	//nb_streams 表示多媒体文件或流中包含的媒体流的数量
	for (int i = 0; i < p_ffmpeg_param->pFormatCtx->nb_streams; i++)
	{
		//4.1AVStream:存储音频流或视频流的结构体
		AVStream* pStream = p_ffmpeg_param->pFormatCtx->streams[i];
		if (pStream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
		{
			//4.2查找匹配解码器ID的已注的解码器
			pcodec = avcodec_find_decoder(pStream->codecpar->codec_id);
			//4.3 分配并初始化 AVCodecContext 结构体(参数为编解码器)
			p_ffmpeg_param->pCodecCtx = avcodec_alloc_context3(pcodec);
			avcodec_parameters_to_context(p_ffmpeg_param->pCodecCtx, pStream->codecpar);
			//4.4计算视频的帧率
			g_frame_rate = pStream->avg_frame_rate.num / pStream->avg_frame_rate.den;
			//流的索引
			p_ffmpeg_param->video_index = i;
		}
	}
	if (!p_ffmpeg_param->pCodecCtx)
	{
		output_log(LOG_ERROR, "could not find video codecCtx");
		return -1;
	}
	//5 通过给定的AVCodec来初始化一个视音频编解码器的 AVCodecContext
	ret = avcodec_open2(p_ffmpeg_param->pCodecCtx, pcodec, NULL);
	if (ret < 0)
	{
		output_log(LOG_ERROR, "avcodec_open2 error");
		return -1;
	}
	//6初始化一个缩放上下文 (SwsContext),以便进行视频像素格式的转换或尺寸缩放。(这里是转成YUV420P)
	p_ffmpeg_param->pSwsCtx = sws_getContext(
		p_ffmpeg_param->pCodecCtx->width, p_ffmpeg_param->pCodecCtx->height, p_ffmpeg_param->pCodecCtx->pix_fmt,
		p_ffmpeg_param->pCodecCtx->width, p_ffmpeg_param->pCodecCtx->height, AV_PIX_FMT_YUV420P,
		SWS_BICUBIC, NULL, NULL, NULL);

	/*
	 *打印将媒体文件的格式和流信息
	av_dump_format(p_ffmpeg_param->pFormatCtx, p_ffmpeg_param->video_index, filePath, 0);
	*/
	return 0;
	//ffmpeg初始化全部完成
}

http://www.kler.cn/a/455479.html

相关文章:

  • Llama 3 预训练(二)
  • 基于BiTCN双向时间卷积网络实现电力负荷多元时序预测(PyTorch版)
  • LeetCode-最长回文子串(005)
  • “拍卖认证平台”:网上拍卖系统的诚信体系建设
  • Redis——数据过期策略
  • STM32开发笔记123:使用FlyMcu下载程序
  • Oracle 11G还有新BUG?ORACLE 表空间迷案!
  • Debian安装配置RocketMQ
  • 组件库TDesign的表格<t-table>的使用,行列合并以及嵌入插槽实现图标展示,附踩坑
  • UGUI源码分析 --- UI的更新入口
  • “游戏信息化”:游戏后台系统的未来发展
  • Windows 11 系统下,通过 WSL(Windows Subsystem for Linux)里的 Ubuntu 24.04 安装 CUDNN 记录
  • 【C++决策和状态管理】从状态模式,有限状态机,行为树到决策树(一):从电梯出发的状态模式State Pattern
  • 面试题整理13----deployment和statefulset区别
  • DeepSpeed的json配置讲解:ds_config_zero3.json
  • 【代码随想录|动态规划背包问题应用】
  • 使用VS Code开发ThinkPHP项目
  • windows nvm 切换node版本后,npm找不到
  • Transformer++架构:突破性的创新与优化
  • 注意⚠️:矩阵系统源码开发/SaaS矩阵系统开源/抖音矩阵开发优势和方向
  • AI绘图开源工具Stable Diffusion WebUI前端API调用
  • Springboot jar包加密加固并进行机器绑定
  • 知迪科技荣获合肥高新区“瞪羚企业” “潜在独角兽企业”双认证
  • JVM -垃圾回收机制
  • 山东大学软件学院2024秋季大数据安全期末
  • Docker Container 可观测性最佳实践