[FFmpeg学习]初级的SDL播放mp4测试
在之前的学习中,通过AVFrame来保存为图片来认识了AVFrame,
[FFmpeg学习]从视频中获取图片_ffmpeg 获取图片-CSDN博客
在获取到AVFrame时,还可以调用SDL方法来进行展现,实现播放效果。
参考资料
SDL,ffmpeg实现简单视频播放器_ffmpeg sdl 播放器-CSDN博客
SDL2 简单介绍以及Windows开发环境搭建-CSDN博客
这里只显示了视频,没有处理声音,
// ffmpegTest.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//#include <iostream>/*
int main()
{std::cout << "Hello World!\n";
}*/extern "C" {
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include <libavutil/log.h>
#include <libavformat/avformat.h>
}using namespace std;//要使用FFmpeg库从MP4文件中提取一张图片,你需要使用FFmpeg的解码器来读取视频帧,并将其保存为图片。以下是一个简单的示例程序,演示如何使用FFmpeg库从MP4文件中提取一张图片:
#include <stdio.h>
#include <stdlib.h>
#include <string.h> #include "SDL.h"int savePicture(AVFrame* pFrame, char* out_name) {//编码保存图片int width = pFrame->width;int height = pFrame->height;AVCodecContext* pCodeCtx = NULL;AVFormatContext* pFormatCtx = avformat_alloc_context();// 设置输出文件格式pFormatCtx->oformat = av_guess_format("mjpeg", NULL, NULL);// 创建并初始化输出AVIOContextif (avio_open(&pFormatCtx->pb, out_name, AVIO_FLAG_READ_WRITE) < 0) {printf("Couldn't open output file.");return -1;}// 构建一个新streamAVStream* pAVStream = avformat_new_stream(pFormatCtx, 0);if (pAVStream == NULL) {return -1;}AVCodecParameters* parameters = pAVStream->codecpar;parameters->codec_id = pFormatCtx->oformat->video_codec;parameters->codec_type = AVMEDIA_TYPE_VIDEO;parameters->format = AV_PIX_FMT_YUVJ420P;parameters->width = pFrame->width;parameters->height = pFrame->height;const AVCodec* pCodec = avcodec_find_encoder(pAVStream->codecpar->codec_id); //查找编码器if (!pCodec) {printf("Could not find encoder\n");return -1;}pCodeCtx = avcodec_alloc_context3(pCodec); //为AVCodecContext分配内存if (!pCodeCtx) {fprintf(stderr, "Could not allocate video codec context\n");exit(1);}if ((avcodec_parameters_to_context(pCodeCtx, pAVStream->codecpar)) < 0) {fprintf(stderr, "Failed to copy %s codec parameters to decoder context\n",av_get_media_type_string(AVMEDIA_TYPE_VIDEO));return -1;}// AVRational tmp = { 1, 25 };pCodeCtx->time_base = { 1, 25 };if (avcodec_open2(pCodeCtx, pCodec, NULL) < 0) { //打开编码器printf("Could not open codec.");return -1;}int ret = avformat_write_header(pFormatCtx, NULL);if (ret < 0) {printf("write_header fail\n");return -1;}int y_size = width * height;//Encode// 给AVPacket分配足够大的空间AVPacket pkt;av_new_packet(&pkt, y_size * 3);// 编码数据ret = avcodec_send_frame(pCodeCtx, pFrame);if (ret < 0) {printf("Could not avcodec_send_frame.");return -1;}// 得到编码后数据ret = avcodec_receive_packet(pCodeCtx, &pkt);if (ret < 0) {printf("Could not avcodec_receive_packet");return -1;}ret = av_write_frame(pFormatCtx, &pkt);if (ret < 0) {printf("Could not av_write_frame");return -1;}av_packet_unref(&pkt);//Write Trailerav_write_trailer(pFormatCtx);avcodec_close(pCodeCtx);avio_close(pFormatCtx->pb);avformat_free_context(pFormatCtx);return 0;
}class SDLHandle
{
public:SDLHandle(int w, int h){m_rect.x = 0;m_rect.y = 0;m_rect.w = w;m_rect.h = h;SdlInit();}~SDLHandle(){if (m_pTexture){SDL_DestroyTexture(m_pTexture);}if (m_pRender){SDL_DestroyRenderer(m_pRender);}if (m_pWnd){SDL_DestroyWindow(m_pWnd);}SDL_Quit();}bool CreateSDLWindow(const char* title, Uint32 flag){m_pWnd = SDL_CreateWindow(title, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, m_rect.w, m_rect.h, flag);if (!m_pWnd){printf("CreateWindows error:%s.\n", SDL_GetError());return false;}m_pRender = SDL_CreateRenderer(m_pWnd, -1, 0);if (!m_pRender){return false;}m_pTexture = SDL_CreateTexture(m_pRender, SDL_PIXELFORMAT_IYUV, SDL_TEXTUREACCESS_STREAMING, m_rect.w, m_rect.h);if (!m_pTexture){return false;}return true;}void UpdateTexture(AVFrame* pFrame){if (!pFrame){return;}//SDL_UpdateTexture(m_pTexture, &m_rect, pFrame->data[0], pFrame->linesize[0]);SDL_UpdateYUVTexture(m_pTexture, &m_rect, pFrame->data[0], pFrame->linesize[0], pFrame->data[1], pFrame->linesize[1], pFrame->data[2], pFrame->linesize[2]);SDL_RenderClear(m_pRender);SDL_RenderCopy(m_pRender, m_pTexture, nullptr, &m_rect);SDL_RenderPresent(m_pRender);SDL_Delay(40);}
private:bool SdlInit(){if (SDL_Init(SDL_INIT_AUDIO | SDL_INIT_VIDEO | SDL_INIT_TIMER) < 0){printf("sdl_init error:%s\n", SDL_GetError());return false;}return true;}
private:SDL_Renderer* m_pRender = nullptr;SDL_Window* m_pWnd = nullptr;SDL_Texture* m_pTexture = nullptr;SDL_Rect m_rect;
};int getpic4() {std::string filename = "test.mp4"; // 输入MP4文件名std::string outputFilename = "output4.jpg"; // 输出图片文件名SDL_Window* pScreen = nullptr; // 播放窗口SDL_Renderer* pRender = nullptr; // 渲染器SDL_Texture* pSDLTexture = nullptr; // 纹理SDLHandle* m_pSDlHandle = nullptr;AVFormatContext* formatContext = nullptr;if (avformat_open_input(&formatContext, filename.c_str(), nullptr, nullptr) != 0) {std::cerr << "Error opening input file" << std::endl;return -1;}if (avformat_find_stream_info(formatContext, nullptr) < 0) {std::cerr << "Error finding stream information" << std::endl;avformat_close_input(&formatContext);return -1;}const AVCodec* codec = nullptr;int videoStreamIndex = -1;for (unsigned int i = 0; i < formatContext->nb_streams; i++) {if (formatContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {videoStreamIndex = i;codec = avcodec_find_decoder(formatContext->streams[i]->codecpar->codec_id);break;}}if (videoStreamIndex == -1 || codec == nullptr) {std::cerr << "Error finding video stream or decoder" << std::endl;avformat_close_input(&formatContext);return -1;}AVCodecContext* codecContext = avcodec_alloc_context3(codec);if (codecContext == nullptr) {std::cerr << "Error allocating codec context" << std::endl;avformat_close_input(&formatContext);return -1;}if (avcodec_parameters_to_context(codecContext, formatContext->streams[videoStreamIndex]->codecpar) < 0) {std::cerr << "Error setting codec parameters" << std::endl;avcodec_free_context(&codecContext);avformat_close_input(&formatContext);return -1;}if (avcodec_open2(codecContext, codec, nullptr) < 0) {std::cerr << "Error opening codec" << std::endl;avcodec_free_context(&codecContext);avformat_close_input(&formatContext);return -1;}m_pSDlHandle = new SDLHandle(codecContext->width, codecContext->height);if (!m_pSDlHandle->CreateSDLWindow("SDL_TEXT", SDL_WINDOW_OPENGL)){printf("CreateSDLWindow error:%s\n", SDL_GetError());return -1;}AVPacket packet;av_init_packet(&packet);// 查找目标时间戳所对应的帧AVFrame* frame = av_frame_alloc();bool foundTargetFrame = false;int count = 0;while (av_read_frame(formatContext, &packet) >= 0) {if (packet.stream_index == videoStreamIndex) {int response = avcodec_send_packet(codecContext, &packet);if (response < 0) {std::cerr << "Error sending packet to decoder" << std::endl;break;}count++;response = avcodec_receive_frame(codecContext, frame);if (response == AVERROR(EAGAIN) || response == AVERROR_EOF) {continue;}else if (response < 0) {std::cerr << "Error receiving frame from decoder" << std::endl;break;}m_pSDlHandle->UpdateTexture(frame);}av_packet_unref(&packet);}if (!foundTargetFrame) {std::cerr << "Target frame not found" << std::endl;av_frame_free(&frame);avcodec_free_context(&codecContext);avformat_close_input(&formatContext);return -1;}// 清理资源av_frame_free(&frame);av_packet_unref(&packet);avcodec_free_context(&codecContext);return 1;
}#undef main
int main(int argc, char* argv[]) {av_log(NULL, AV_LOG_INFO, "...Hello world\n");getpic4();return 0;
}
相关文章:
[FFmpeg学习]初级的SDL播放mp4测试
在之前的学习中,通过AVFrame来保存为图片来认识了AVFrame, [FFmpeg学习]从视频中获取图片_ffmpeg 获取图片-CSDN博客 在获取到AVFrame时,还可以调用SDL方法来进行展现,实现播放效果。 参考资料 SDL,ffmpeg实现简单…...
情景题之小明的Linux实习之旅:linux实战练习1(下)【基础命令,权限修改,日志查询,进程管理...】
小明的Linux实习之旅:基础指令练习情景练习题下 前景提要小明是怎么做的场景1:初识Linux,创建目录和文件场景2:权限管理,小明的权限困惑场景3:打包与解压,小明的备份操作场景4:使用G…...
k8s 证书更新
如何使用脚本更新Kubernetes集群证书 引言 Kubernetes集群中,由kubeadm初始化的证书有效期默认为一年。当这些证书接近或已经超过有效期时,它们必须被更新以保证集群的正常运作。本文将介绍如何使用特定脚本来更新这些证书,将它们的有效期延…...
Linux操作系统学习:day01
内容来自:Linux介绍 视频推荐:Linux基础入门教程-linux命令-vim-gcc/g -动态库/静态库 -makefile-gdb调试 day01 基础概念 Linux 是 UNIX 操作系统的一个克隆系统, 但是Linux是开源的。 Linux是一个基于文件的操作系统。操作系统需要和硬件进行交互…...
【Oracle生产运维】数据库服务器负载过高异常排查处理
说明 在Oracle数据库运维工作中,经常会遇到Oracle数据库服务器平均负载(load average)突然异常升高,如果放任不管,严重的情况下会出现数据库宕机、服务器重启等重大故障。因此,当发现数据库服务器平均负载…...
IIR和FIR两种滤波器有什么区别?
概念的区分 IIR(Infinite Impulse Response,无限脉冲响应)和FIR(Finite Impulse Response,有限脉冲响应)滤波器是两种常见的数字信号处理滤波器类型,它们在结构、性能和用途上有显著区别&#…...
让GNSSRTK不再难【第二天-第4部分】
第12讲 GNSS授时与PPS 12.1 为什么需要高精度时间 授时的传统理解就是时间传递或者对时。比如以前手机没这么方便时,大家还都使用石英钟手表看时间时,大家都习惯晚上七点准时对着中央一套的报时,来校准你家的机械钟或者挂钟,这就…...
「OC」UI练习(一)—— 登陆界面
「OC」登陆界面 明确要求 一个登陆界面的组成,用户名提示以及输入框,密码提示提示以及输入框,登陆按钮,以及注册按钮,根据以上要求我们将我们的组件设置为成员变量。 //viewControl.h #import <UIKit/UIKit.h>…...
基于机器学习和深度学习的NASA涡扇发动机剩余使用寿命预测(C-MAPSS数据集,Python代码,ipynb 文件)
以美国航空航天局提供的航空涡扇发动机退化数据集为研究对象,该数据集包含多台发动机从启动到失效期间多个运行周期的多源传感器时序状态监测数据,它们共同表征了发动机的性能退化情况。为减小计算成本,需要对原始多源传感器监测数据进行数据…...
计算机组成原理-常见计算题含IEE754
一、补码加减运算 二、溢出判断 采用一位符号位 采用双符号位 三、定点数的移位运算 算术右移 算数左移 反码的算术移位 补码的算术移位 四、浮点数的表示 一个右规的例子 五、IEEE754 移码...
InnoDB存储引擎非常重要的一个机制--MVCC(多版本并发控制)
Mysql是如何实现隔离性的?(锁MVCC) 隔离性是指一个事务内部的操作以及操作的数据对正在进行的其他事务是隔离的,并发执行的各个事务之间不能相互干扰。隔离性可以防止多个事务并发执行时,可能存在交叉执行导致数据的不…...
【DevOps】服务器硬件基础知识
目录 前言 1、处理器(CPU):服务器的“大脑” 2、内存(RAM):服务器的“工作台” 3、存储(Storage):服务器的“仓库” 4、 网络接口(NIC)&…...
6.10 c语言
7.1 if-else语句 简化形式 if(表达式)语句块 阶梯形式 if(表达式1)语句块1 else if(表达式2)语句块2 嵌套形式 if() if() 语句1 else 语句2 else if() 语句3 else 语句4 表达式一般情况下为逻辑表达式或关系表达式 #include <stdio.h>//从小到大排序,输出顺…...
jenkins插件之Jdepend
JDepend插件是一个为构建生成JDepend报告的插件。 安装插件 JDepend Dashboard -->> 系统管理 -->> 插件管理 -->> Available plugins 搜索 Jdepend, 点击安装构建步骤新增执行shell #执行pdepend if docker exec phpfpm82 /tmp/composer/vendor/bin/pdepe…...
vue3之基于el-image实现图片预览
实现的功能: 图片可放大预览,支持放大、缩小、向左向右旋转查看可点击任意一张图后进行左右切换查看大图 主要使用的方法:splice和concat 主要代码 // template中 <div><el-imagev-for"(item, index) in imgsData":src&q…...
wooyun_2015_110216-Elasticsearch-vulfocus
1.原理 ElasticSearch具有备份数据的功能,用户可以传入一个路径,让其将数据备份到该路径下,且文件名和后缀都可控。 所以,如果同文件系统下还跑着其他服务,如Tomcat、PHP等,我们可以利用ElasticSearch的备…...
Fedora的远程桌面
要在 Fedora 40 上开启远程桌面功能。 首先,要确保已安装 gnome-remote-desktop 和 vino 包。 这些软件包通常默认安装在 Fedora 的 GNOME 桌面环境中。 可以按照以下步骤操作: 1、判断电脑是否安装了 gnome-remote-desktop 和 vino 包: tomfedora:…...
CSS id选择器
目录 任务描述 相关知识 id选择器 id选择器语法 类选择器与id选择器的区别 编程要求 任务描述 在本关中,你将通过id选择器的方式完成页面菜单栏样式布局,栏目导航等任务。 完成任务之后,基本页面效果如下: 动态效果如下&am…...
22.搭积木
上海市计算机学会竞赛平台 | YACSYACS 是由上海市计算机学会于2019年发起的活动,旨在激发青少年对学习人工智能与算法设计的热情与兴趣,提升青少年科学素养,引导青少年投身创新发现和科研实践活动。https://www.iai.sh.cn/problem/717 题目描述 小爱用积木搭起一座金字塔。为…...
手机投屏到电脑时,手机提示连接失败
前言 注意,本方法建立在你已经通过其他帖子等解决了前置条件的情况下,手机提示连接失败情况下,包括但不限于关闭防火墙、安装无线投屏工具、手机和电脑连接在同一个WiFi频段下、关闭杀毒软件等。 具体操作方法 1、请进入设置 > 系统和…...
SpringBoot-17-MyBatis动态SQL标签之常用标签
文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...
业务系统对接大模型的基础方案:架构设计与关键步骤
业务系统对接大模型:架构设计与关键步骤 在当今数字化转型的浪潮中,大语言模型(LLM)已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中,不仅可以优化用户体验,还能为业务决策提供…...
【网络】每天掌握一个Linux命令 - iftop
在Linux系统中,iftop是网络管理的得力助手,能实时监控网络流量、连接情况等,帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...
深入剖析AI大模型:大模型时代的 Prompt 工程全解析
今天聊的内容,我认为是AI开发里面非常重要的内容。它在AI开发里无处不在,当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗",或者让翻译模型 "将这段合同翻译成商务日语" 时,输入的这句话就是 Prompt。…...
MongoDB学习和应用(高效的非关系型数据库)
一丶 MongoDB简介 对于社交类软件的功能,我们需要对它的功能特点进行分析: 数据量会随着用户数增大而增大读多写少价值较低非好友看不到其动态信息地理位置的查询… 针对以上特点进行分析各大存储工具: mysql:关系型数据库&am…...
QT: `long long` 类型转换为 `QString` 2025.6.5
在 Qt 中,将 long long 类型转换为 QString 可以通过以下两种常用方法实现: 方法 1:使用 QString::number() 直接调用 QString 的静态方法 number(),将数值转换为字符串: long long value 1234567890123456789LL; …...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
初学 pytest 记录
安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...
Reasoning over Uncertain Text by Generative Large Language Models
https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829 1. 概述 文本中的不确定性在许多语境中传达,从日常对话到特定领域的文档(例如医学文档)(Heritage 2013;Landmark、Gulbrandsen 和 Svenevei…...
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...
