【FFMPEG应用篇】基于FFmpeg的转码应用(FLV MP4)
方法声明
extern "C" //ffmpeg使用c语言实现的,引入用c写的代码就要用extern
{
#include <libavcodec/avcodec.h> //注册
#include <libavdevice/avdevice.h> //设备
#include <libavformat/avformat.h>
#include <libavutil/error.h>
#include <libswscale/swscale.h>
#include <libswresample/swresample.h>
}
#include<iostream>class fcoverh264
{
public:fcoverh264(int number);//打开H264视频文件void openFile(std::string file);//根据我们需要的封装格式进行处理void outPut(std::string fileout);
private:AVFormatContext* forContext, * formatout;//保存数据的结构体 forContext存输入进来的视频信息;formatout存储最终输出的视频信息AVPacket* pkt;//pktint videoType;
};
定义实现
#include "fcoverh264.h"extern "C" //ffmpeg使用c语言实现的,引入用c写的代码就要用extern
{
#include <libavcodec/avcodec.h> //注册
#include <libavdevice/avdevice.h> //设备
#include <libavformat/avformat.h>
#include <libavutil/error.h>
#include <libswscale/swscale.h>
#include <libswresample/swresample.h>
}
fcoverh264::fcoverh264(int number):videoType(number)
{/** 转码的流程:* 1.注册组件* 2.打开视频流 打开视频文件* 3.查找有没有流数据* 4.查找视频码流数据** 6.根据要的封装格式 来猜测格式对应编辑器* 7.打开对应文件* 8.新建流* 9.写入头部信息* 10.读取一帧一帧的码流数据* 11.转码---->时间基的转化* 所以在解码的时候:显示顺序和解码的顺序是一样的;处理其他视频的时候:就需要关注 显示顺序和解码的顺序是否一致了编码有B帧? 解码:IPB* 12.写入对应的一帧数据到文件中*///注册组件av_register_all();forContext = avformat_alloc_context();}void fcoverh264::openFile(std::string file)
{//打开输入视频int res = avformat_open_input(&forContext, file.c_str(), nullptr, nullptr);//判断是否打开成功if (res < 0){std::cout << "打开失败"<<std::endl;return;}//打开视频文件成功,获取文件信息res = avformat_find_stream_info(forContext, nullptr);//查看有没有相关视频流信息if (res < 0)//判断是否有流媒体{std::cout << "没有流媒体信息" << std::endl;return;}//一个视频流有多股码流,存在forContentext中streams数组中/*int videoType = -1;*/for (int i = 0; i < forContext->nb_streams; i++) //i小于流的个数{if (forContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)//视频流{videoType = i;//标识类型break;}}if (videoType == -1){std::cout << "没有视频流相关信息" << std::endl;return;}std::cout << "输入的准备已经完成"<<std::endl;
}//根据我们需要的封装格式进行处理
void fcoverh264::outPut(std::string fileout)
{//猜测编码器AVOutputFormat* avformat = av_guess_format(nullptr, fileout.c_str(), nullptr);if (avformat == nullptr){std::cout << "没有编码器!"<<std::endl;return;}std::cout << "AVOutputFormat"<<std::endl;//保存输出视频信息的结构体formatout = avformat_alloc_context();//设置输出格式formatout->oformat = avformat;//打开视频流 文件流//参数1:输入输出的上下文对象//参数2:文件流路径//参数3:文件打开格式 写的方式int res = avio_open(&formatout->pb, fileout.c_str(), AVIO_FLAG_WRITE);if (res < 0){std::cout << "open file error"<<std::endl;return;}std::cout << "avio_open"<<std::endl;//新建视频流//参数1:视频信息结构体//参数2:新建流 的 返回新建流 的地址AVStream* newStream = avformat_new_stream(formatout, nullptr);if (newStream == nullptr){std::cout << "打开视频流失败"<<std::endl;return;}std::cout << "newStream"<<std::endl;//编码器对应参数设置 拷贝参数设置 newStream:输入进入流的参数设置res = avcodec_parameters_copy(newStream->codecpar, forContext->streams[videoType]->codecpar);std::cout << "res=" << res<<std::endl;if (res < 0){std::cout << "拷贝失败!"<< std::endl;return;}std::cout << "res=" << res<<std::endl;//设置新的流里面 codec_tag 设置为0newStream->codecpar->codec_tag = 0;//头部信息写入----写入成功与否res = avformat_write_header(formatout, nullptr);//formatout封装格式的结构体//判断写入成功与否if (res < 0){std::cout << "写入头部信息失败!" <<std::endl;return;}std::cout << "res=" << res << std::endl;//开始读取码流数据pkt = (AVPacket*)malloc(sizeof(AVPacket));//算出这张图有多大int size = newStream->codecpar->width * newStream->codecpar->height;av_new_packet(pkt, size);int frameCount = 0;//一帧一帧的读取while (av_read_frame(forContext, pkt) == 0){//判断这一帧这是不是视频流if (pkt->stream_index == videoType){frameCount++;//如果是视频流----判断有没有设置过 时间基if (pkt->pts == AV_NOPTS_VALUE){//时间基 time_base AVRational属性AVRational timebase = forContext->streams[videoType]->time_base;//计算帧之间的长度(duration) double强制转换int64_t duration = (double)AV_TIME_BASE / av_q2d(forContext->streams[videoType]->r_frame_rate);//计算显示时间基(pts):公式:(当前帧数*两帧之间的长度))/(输入时间基*AV_TIME_BASE)pkt->pts = (double)(frameCount * duration) / (av_q2d(timebase) * AV_TIME_BASE);//解码时间基(dts)pkt->dts = pkt->pts;//目标两帧之间的长度pkt->duration = duration / (double)(av_q2d(timebase) * AV_TIME_BASE);}else if (pkt->pts < pkt->dts)//显示 时间基 小于 解码时间基 不要这样子的{continue;}//上述步骤为 时间基设置//解码 时间基 真正的转换 如下://显示时间基的转换pkt->pts = av_rescale_q_rnd(pkt->pts, forContext->streams[videoType]->time_base,newStream->time_base, (AVRounding)(AV_ROUND_INF | AV_ROUND_PASS_MINMAX));//解码时间基的转换pkt->dts = av_rescale_q_rnd(pkt->dts, forContext->streams[videoType]->time_base,newStream->time_base, (AVRounding)(AV_ROUND_INF | AV_ROUND_PASS_MINMAX));//数据时长设置pkt->duration = av_rescale_q(pkt->duration, forContext->streams[videoType]->time_base,newStream->time_base);//数据位置的设置 数据在流信息中的设置pkt->pos = -1;//数据包的标记:结合AV_PKT_FLAG_KEY使用 最小为1表示这一帧是一个关键帧pkt->flags |= AV_PKT_FLAG_KEY;//标记:当前写入的这一帧是视频流pkt->stream_index = 0;//转码后的数据包 写入 目标视频信息 结构体 中av_interleaved_write_frame(formatout, pkt);}//清空处理:重新设置包av_packet_unref(pkt);}//写入尾巴帧av_write_trailer(formatout);//用完之后进行 关闭 处理 :关闭猜测完的流avio_close(formatout->pb);//对应avio_open()std::cout << "avio_close"<<std::endl;//释放malloc的空间 释放保存信息的结构体av_free(formatout);std::cout << "av_free"<<std::endl;//关闭输入流avformat_close_input(&forContext);//对应avformat_open_inpustd::cout << "avformat_close_input"<<std::endl;//释放forContext结构体空间av_free(forContext);std::cout << "av_free"<<std::endl;
}
调用实例
#include <iostream>
#include "fcoverh264.h"int main() {fcoverh264* cover = new fcoverh264{-1}; //转码cover->openFile("test01.h264");cover->outPut("code_frame.flv");return 0;
}
相关文章:
【FFMPEG应用篇】基于FFmpeg的转码应用(FLV MP4)
方法声明 extern "C" //ffmpeg使用c语言实现的,引入用c写的代码就要用extern { #include <libavcodec/avcodec.h> //注册 #include <libavdevice/avdevice.h> //设备 #include <libavformat/avformat.h> #include <libavutil/…...

LInux初学之路linux的磁盘分区/远程控制/以及关闭图形界面/查看个人身份
虚拟机磁盘分配 hostname -I 查看ip地址 ssh root虚拟就ip 远程连接 win10之后才有 远程控制重新启动 reboot xshell 使用(个人和家庭版 免费去官方下载) init 3 关闭界面 减小内存使用空间 init 5 回复图形界面 runlevel显示的是状态 此时和上…...

Netty 介绍、使用场景及案例
Netty 介绍、使用场景及案例 1、Netty 介绍 https://github.com/netty/netty Netty是一个高性能、异步事件驱动的网络应用程序框架,用于快速开发可扩展的网络服务器和客户端。它是一个开源项目,最初由JBoss公司开发,现在由社区维护。Netty的…...

小游戏选型(一):游戏化设计助力直播间互动和营收
一、社交直播间小游戏火爆 大家好,作为一个技术宅和游戏迷,今天来聊聊近期爆火的社交直播间小游戏的潮流。喜欢冲浪玩社交产品的小伙伴会发现,近期各大平台都推出了直播间社交小游戏,直播间氛围火爆,小游戏玩法简单&a…...

社区嵌入式服务设施建设为社区居家养老服务供给增加赋能
近年来,沈阳市浑南区委、区政府牢记在辽宁考察时的重要指示精神,认真践行以人民为中心的发展思想,聚集“一老一小”民生关切,统筹推进以社区为骨干结点的养老服务探索实践。围绕“品质养老”民生服务理念,针对社区老年…...

SpringBoot请求参数加密、响应参数解密
SpringBoot请求参数加密、响应参数解密 1.说明 在项目开发工程中,有的项目可能对参数安全要求比较高,在整个http数据传输的过程中都需要对请求参数、响应参数进行加密,也就是说整个请求响应的过程都是加密处理的,不在浏览器上暴…...
Mysql适配国产化数据库人大金仓冲突记录
1、mysql中查询中如果使用双引号,在人大金仓数据库中不支持,需改为单引号 例如: select 字段A,字段B,字段C from tableA where 字段A "1" 改为: select 字段A,字段B,字段…...

在微服务架构中认证和授权的那些事儿
在微服务架构中认证和授权是最基础的服务能力,其中这一块行业类的标准就是OAuth2 和 SSO ,而OAuth2 和 SSO 可以归类为“用户管理和身份验证”工具,OpenID Connect 1.0是 OAuth 2.0 协议之上的一个简单身份层。 Part.1 认识OAuth 2.0 OAuth…...
Git使用统一规范
为什么要统一git使用的风格? 统一的风格使我们在工作的时候无需考虑工作流程上该如何去做的问题,按照一个风格去做就好了每个人风格不同,格式凌乱,查看很不方便commit没有准确的message,后续难以追踪问题 git messag…...
如何在前端优化中处理大量的图像资源?
在前端优化中,处理大量的图像资源是一项重要的任务。由于图像占据了网站带宽的大部分,因此优化图像可以显著提高网站的性能和用户体验。下面将介绍一些在前端优化中处理大量图像资源的常见方法。 一、压缩图像 压缩图像是减少图像文件大小和优化图像的…...
【MYSQL】性能相关
SQL 语句的性能分析是一个非常重要的任务,尤其是在处理大数据时。下面是一些常用的 SQL 性能分析方法: 执行计划: 使用 EXPLAIN 命令来查看 SQL 语句的执行计划。这可以帮助你了解查询是如何被数据库执行的,从而发现可能的性能瓶颈。 注意&…...

【Jmeter之get请求传递的值为JSON体实践】
Jmeter之get请求传递的值为JSON体实践 get请求的常见传参方式 1、在URL地址后面拼接,有多个key和value时,用&链接 2、在Parameters里面加上key和value 第一次遇到value的值不是字符串也不是整型,我尝试把json放到value里面࿰…...

(1)(1.13) SiK无线电高级配置(六)
文章目录 前言 15 使用FTDI转USB调试线配置SiK无线电设备 16 强制启动加载程序模式 17 名词解释 前言 本文提供 SiK 遥测无线电(SiK Telemetry Radio)的高级配置信息。它面向"高级用户"和希望更好地了解无线电如何运行的用户。 15 使用FTDI转USB调试线配置SiK无线…...
用JAVA实现樱花飘落
用java实现一个樱花飘落的方法 package Text2;import javax.swing.*; import java.awt.*; import java.util.ArrayList; import java.util.List;public class Sakura extends JFrame {private List<Point> sakuraList; // 樱花的位置列表public Sakura() {sakuraList n…...

Web开发:SQLsugar的安装和使用
一、安装 第一步,在你的项目中找到解决方案,右键-管理解决方案的Nuget 第二步,下载对应的包,注意你的框架是哪个就下载哪个的包,一个项目安装一次包即可 点击应用和确定 安装好后会显示sqlsugar的包 二、使用…...
Redis面试题10
Redis 支持哪些数据结构? Redis 支持以下几种常用的数据结构: 字符串(String):用于存储字符串值,可以是文本或二进制数据。 列表(List):用于存储一个有序的字符串列表&am…...
arm64架构编译electron长征路
文章目录 1. gn工具生成1.1 问题,找不到last_commit_position.h文件问题描述如下:解决方法1.2 ninja文件不是对应架构问题问题描述:解决方法1.3 问题3:clang++找不到问题描述解决方法2. electron 编译参数生成2.1 下载对应版本debian_bullseye_arm64-sysroot错误描述...

建模软件Rhinoceros mac介绍说明
Rhinoceros mac是一款3D设计软件“犀牛”,在当今众多三维建模软件中,Rhinoceros 版因为其体积小、功能强大、对硬件要求低而广受欢迎,对于专业的3D设计人员来说它是一款不错的3D建模软件,Rhinoceros Mac中文版能轻易整合3DS MAX与…...

视频号下载小助手:教你微信视频号怎么提取视频出来
作为一名剪辑师或自由职业者,我们作为短视频创作者有时候需要下载多个视频用于制作多个解说系列的视频或者连续剧。然而,下载这些视频通常需要花费大量时间和精力,尤其是在没有合适的工具的情况下,让我们制作视频也确实困难,那么我们该如何解决呢&#x…...
C#-委托
委托类型 (delegate type) 表示对具有特定参数列表和返回类型的方法的引用。通过委托,我们能够将方法作为实体赋值给变量和作为参数传递。委托类似于在其他某些语言中的函数指针的概念,但是与函数指针不同,委托是面向对象的,并且是…...

idea大量爆红问题解决
问题描述 在学习和工作中,idea是程序员不可缺少的一个工具,但是突然在有些时候就会出现大量爆红的问题,发现无法跳转,无论是关机重启或者是替换root都无法解决 就是如上所展示的问题,但是程序依然可以启动。 问题解决…...

基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容
基于 UniApp + WebSocket实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...

论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)
笔记整理:刘治强,浙江大学硕士生,研究方向为知识图谱表示学习,大语言模型 论文链接:http://arxiv.org/abs/2407.16127 发表会议:ISWC 2024 1. 动机 传统的知识图谱补全(KGC)模型通过…...
unix/linux,sudo,其发展历程详细时间线、由来、历史背景
sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...
拉力测试cuda pytorch 把 4070显卡拉满
import torch import timedef stress_test_gpu(matrix_size16384, duration300):"""对GPU进行压力测试,通过持续的矩阵乘法来最大化GPU利用率参数:matrix_size: 矩阵维度大小,增大可提高计算复杂度duration: 测试持续时间(秒&…...

智能仓储的未来:自动化、AI与数据分析如何重塑物流中心
当仓库学会“思考”,物流的终极形态正在诞生 想象这样的场景: 凌晨3点,某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径;AI视觉系统在0.1秒内扫描包裹信息;数字孪生平台正模拟次日峰值流量压力…...

听写流程自动化实践,轻量级教育辅助
随着智能教育工具的发展,越来越多的传统学习方式正在被数字化、自动化所优化。听写作为语文、英语等学科中重要的基础训练形式,也迎来了更高效的解决方案。 这是一款轻量但功能强大的听写辅助工具。它是基于本地词库与可选在线语音引擎构建,…...

MFC 抛体运动模拟:常见问题解决与界面美化
在 MFC 中开发抛体运动模拟程序时,我们常遇到 轨迹残留、无效刷新、视觉单调、物理逻辑瑕疵 等问题。本文将针对这些痛点,详细解析原因并提供解决方案,同时兼顾界面美化,让模拟效果更专业、更高效。 问题一:历史轨迹与小球残影残留 现象 小球运动后,历史位置的 “残影”…...
WebRTC从入门到实践 - 零基础教程
WebRTC从入门到实践 - 零基础教程 目录 WebRTC简介 基础概念 工作原理 开发环境搭建 基础实践 三个实战案例 常见问题解答 1. WebRTC简介 1.1 什么是WebRTC? WebRTC(Web Real-Time Communication)是一个支持网页浏览器进行实时语音…...
SQL Server 触发器调用存储过程实现发送 HTTP 请求
文章目录 需求分析解决第 1 步:前置条件,启用 OLE 自动化方式 1:使用 SQL 实现启用 OLE 自动化方式 2:Sql Server 2005启动OLE自动化方式 3:Sql Server 2008启动OLE自动化第 2 步:创建存储过程第 3 步:创建触发器扩展 - 如何调试?第 1 步:登录 SQL Server 2008第 2 步…...