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

铭豹扩展坞 USB转网口 突然无法识别解决方法
当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...
内存分配函数malloc kmalloc vmalloc
内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...
Java 语言特性(面试系列1)
一、面向对象编程 1. 封装(Encapsulation) 定义:将数据(属性)和操作数据的方法绑定在一起,通过访问控制符(private、protected、public)隐藏内部实现细节。示例: public …...

Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例
使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件,常用于在两个集合之间进行数据转移,如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model:绑定右侧列表的值&…...
uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖
在前面的练习中,每个页面需要使用ref,onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入,需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...

SCAU期末笔记 - 数据分析与数据挖掘题库解析
这门怎么题库答案不全啊日 来简单学一下子来 一、选择题(可多选) 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘:专注于发现数据中…...
基于Uniapp开发HarmonyOS 5.0旅游应用技术实践
一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架,支持"一次开发,多端部署",可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务,为旅游应用带来…...

srs linux
下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935,SRS管理页面端口是8080,可…...

Keil 中设置 STM32 Flash 和 RAM 地址详解
文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...

相机从app启动流程
一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...