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

【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语言实现的&#xff0c;引入用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 使用&#xff08;个人和家庭版 免费去官方下载&#xff09; init 3 关闭界面 减小内存使用空间 init 5 回复图形界面 runlevel显示的是状态 此时和上…...

Netty 介绍、使用场景及案例

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

小游戏选型(一):游戏化设计助力直播间互动和营收

一、社交直播间小游戏火爆 大家好&#xff0c;作为一个技术宅和游戏迷&#xff0c;今天来聊聊近期爆火的社交直播间小游戏的潮流。喜欢冲浪玩社交产品的小伙伴会发现&#xff0c;近期各大平台都推出了直播间社交小游戏&#xff0c;直播间氛围火爆&#xff0c;小游戏玩法简单&a…...

社区嵌入式服务设施建设为社区居家养老服务供给增加赋能

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

SpringBoot请求参数加密、响应参数解密

SpringBoot请求参数加密、响应参数解密 1.说明 在项目开发工程中&#xff0c;有的项目可能对参数安全要求比较高&#xff0c;在整个http数据传输的过程中都需要对请求参数、响应参数进行加密&#xff0c;也就是说整个请求响应的过程都是加密处理的&#xff0c;不在浏览器上暴…...

Mysql适配国产化数据库人大金仓冲突记录

1、mysql中查询中如果使用双引号&#xff0c;在人大金仓数据库中不支持&#xff0c;需改为单引号 例如&#xff1a; select 字段A&#xff0c;字段B&#xff0c;字段C from tableA where 字段A "1" 改为&#xff1a; select 字段A&#xff0c;字段B&#xff0c;字段…...

在微服务架构中认证和授权的那些事儿

在微服务架构中认证和授权是最基础的服务能力&#xff0c;其中这一块行业类的标准就是OAuth2 和 SSO &#xff0c;而OAuth2 和 SSO 可以归类为“用户管理和身份验证”工具&#xff0c;OpenID Connect 1.0是 OAuth 2.0 协议之上的一个简单身份层。 Part.1 认识OAuth 2.0 OAuth…...

Git使用统一规范

为什么要统一git使用的风格&#xff1f; 统一的风格使我们在工作的时候无需考虑工作流程上该如何去做的问题&#xff0c;按照一个风格去做就好了每个人风格不同&#xff0c;格式凌乱&#xff0c;查看很不方便commit没有准确的message&#xff0c;后续难以追踪问题 git messag…...

如何在前端优化中处理大量的图像资源?

在前端优化中&#xff0c;处理大量的图像资源是一项重要的任务。由于图像占据了网站带宽的大部分&#xff0c;因此优化图像可以显著提高网站的性能和用户体验。下面将介绍一些在前端优化中处理大量图像资源的常见方法。 一、压缩图像 压缩图像是减少图像文件大小和优化图像的…...

【MYSQL】性能相关

SQL 语句的性能分析是一个非常重要的任务&#xff0c;尤其是在处理大数据时。下面是一些常用的 SQL 性能分析方法&#xff1a; 执行计划: 使用 EXPLAIN 命令来查看 SQL 语句的执行计划。这可以帮助你了解查询是如何被数据库执行的&#xff0c;从而发现可能的性能瓶颈。 注意&…...

【Jmeter之get请求传递的值为JSON体实践】

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

(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的安装和使用

一、安装 第一步&#xff0c;在你的项目中找到解决方案&#xff0c;右键-管理解决方案的Nuget 第二步&#xff0c;下载对应的包&#xff0c;注意你的框架是哪个就下载哪个的包&#xff0c;一个项目安装一次包即可 点击应用和确定 安装好后会显示sqlsugar的包 二、使用&#xf…...

Redis面试题10

Redis 支持哪些数据结构&#xff1f; Redis 支持以下几种常用的数据结构&#xff1a; 字符串&#xff08;String&#xff09;&#xff1a;用于存储字符串值&#xff0c;可以是文本或二进制数据。 列表&#xff08;List&#xff09;&#xff1a;用于存储一个有序的字符串列表&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设计软件“犀牛”&#xff0c;在当今众多三维建模软件中&#xff0c;Rhinoceros 版因为其体积小、功能强大、对硬件要求低而广受欢迎&#xff0c;对于专业的3D设计人员来说它是一款不错的3D建模软件&#xff0c;Rhinoceros Mac中文版能轻易整合3DS MAX与…...

视频号下载小助手:教你微信视频号怎么提取视频出来

作为一名剪辑师或自由职业者,我们作为短视频创作者有时候需要下载多个视频用于制作多个解说系列的视频或者连续剧。然而,下载这些视频通常需要花费大量时间和精力,尤其是在没有合适的工具的情况下&#xff0c;让我们制作视频也确实困难&#xff0c;那么我们该如何解决呢&#x…...

C#-委托

委托类型 (delegate type) 表示对具有特定参数列表和返回类型的方法的引用。通过委托&#xff0c;我们能够将方法作为实体赋值给变量和作为参数传递。委托类似于在其他某些语言中的函数指针的概念&#xff0c;但是与函数指针不同&#xff0c;委托是面向对象的&#xff0c;并且是…...

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...

Objective-C常用命名规范总结

【OC】常用命名规范总结 文章目录 【OC】常用命名规范总结1.类名&#xff08;Class Name)2.协议名&#xff08;Protocol Name)3.方法名&#xff08;Method Name)4.属性名&#xff08;Property Name&#xff09;5.局部变量/实例变量&#xff08;Local / Instance Variables&…...

C++ 基础特性深度解析

目录 引言 一、命名空间&#xff08;namespace&#xff09; C 中的命名空间​ 与 C 语言的对比​ 二、缺省参数​ C 中的缺省参数​ 与 C 语言的对比​ 三、引用&#xff08;reference&#xff09;​ C 中的引用​ 与 C 语言的对比​ 四、inline&#xff08;内联函数…...

C++.OpenGL (10/64)基础光照(Basic Lighting)

基础光照(Basic Lighting) 冯氏光照模型(Phong Lighting Model) #mermaid-svg-GLdskXwWINxNGHso {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GLdskXwWINxNGHso .error-icon{fill:#552222;}#mermaid-svg-GLd…...

leetcodeSQL解题:3564. 季节性销售分析

leetcodeSQL解题&#xff1a;3564. 季节性销售分析 题目&#xff1a; 表&#xff1a;sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...

Pinocchio 库详解及其在足式机器人上的应用

Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库&#xff0c;专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性&#xff0c;并提供了一个通用的框架&…...

4. TypeScript 类型推断与类型组合

一、类型推断 (一) 什么是类型推断 TypeScript 的类型推断会根据变量、函数返回值、对象和数组的赋值和使用方式&#xff0c;自动确定它们的类型。 这一特性减少了显式类型注解的需要&#xff0c;在保持类型安全的同时简化了代码。通过分析上下文和初始值&#xff0c;TypeSc…...

6️⃣Go 语言中的哈希、加密与序列化:通往区块链世界的钥匙

Go 语言中的哈希、加密与序列化:通往区块链世界的钥匙 一、前言:离区块链还有多远? 区块链听起来可能遥不可及,似乎是只有密码学专家和资深工程师才能涉足的领域。但事实上,构建一个区块链的核心并不复杂,尤其当你已经掌握了一门系统编程语言,比如 Go。 要真正理解区…...

链式法则中 复合函数的推导路径 多变量“信息传递路径”

非常好&#xff0c;我们将之前关于偏导数链式法则中不能“约掉”偏导符号的问题&#xff0c;统一使用 二重复合函数&#xff1a; z f ( u ( x , y ) , v ( x , y ) ) \boxed{z f(u(x,y),\ v(x,y))} zf(u(x,y), v(x,y))​ 来全面说明。我们会展示其全微分形式&#xff08;偏导…...

Linux基础开发工具——vim工具

文章目录 vim工具什么是vimvim的多模式和使用vim的基础模式vim的三种基础模式三种模式的初步了解 常用模式的详细讲解插入模式命令模式模式转化光标的移动文本的编辑 底行模式替换模式视图模式总结 使用vim的小技巧vim的配置(了解) vim工具 本文章仍然是继续讲解Linux系统下的…...