FFMpeg rtmp 无压缩推送本地yuv文件 压缩推送本地yuv文件
可以借鉴的:C++使用FFmpeg实现YUV数据编码转视频文件_C 语言_脚本之家
yuv文件下载地址:YUV Sequences
无压缩的方式推送本地yuv文件 代码:
#include <stdio.h>
#include <unistd.h>
#include <iostream>
extern "C" {
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libavcodec/avcodec.h"
#include "libswscale/swscale.h"
};
using namespace std;const char* input_file = "/mnt/hgfs/shareVM/BigBuckBunny_CIF_24fps.yuv";
const char* output_rtmp_url = "rtmp://10.10.18.94:1935/live/test";int main(int argc, char *argv[]) {AVFormatContext *pFormatCtx = nullptr;AVOutputFormat *fmt = nullptr;AVStream *video_st = nullptr;AVCodecContext *pCodecCtx = nullptr;AVCodec *pCodec = nullptr;uint8_t *picture_buf = nullptr;int size;//打开视频文件FILE *in_file = fopen(input_file, "rb");if (!in_file) {cout << "can not open file!" << endl;return -1;}//[1] --注册所有ffmpeg组件avcodec_register_all();av_register_all();//[2] --初始化AVFormatContext结构体,根据文件名获取到合适的封装格式avformat_alloc_output_context2(&pFormatCtx, NULL, "flv", output_rtmp_url);fmt = pFormatCtx->oformat;//[3] --打开文件if (avio_open(&pFormatCtx->pb, output_rtmp_url, AVIO_FLAG_READ_WRITE)) {cout << "output file open fail!";return -1;}//[3]//[4] --初始化视频码流video_st = avformat_new_stream(pFormatCtx, 0);if (video_st == NULL){printf("failed allocating output stram\n");return -1;}video_st->time_base.num = 1;video_st->time_base.den = 25;//[4]//[5] --编码器Context设置参数pCodecCtx = video_st->codec;pCodecCtx->codec_id = fmt->video_codec;pCodecCtx->codec_type = AVMEDIA_TYPE_VIDEO;pCodecCtx->pix_fmt = AV_PIX_FMT_YUV420P;pCodecCtx->width = 352;pCodecCtx->height = 288;pCodecCtx->time_base = {1, 25};pCodecCtx->framerate = {25, 1};pCodecCtx->bit_rate = 400000;pCodecCtx->gop_size = 50;//[5]//[6] --寻找编码器并打开编码器pCodec = avcodec_find_encoder(AV_CODEC_ID_FLV1);if (!pCodec){cout << "no right encoder!" << endl;return -1;}if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0){cout << "open encoder fail!" << endl;return -1;}//[6]//输出格式信息av_dump_format(pFormatCtx, 0, output_rtmp_url, 1);//初始化帧AVFrame *picture = av_frame_alloc();picture->width = pCodecCtx->width;picture->height = pCodecCtx->height;picture->format = pCodecCtx->pix_fmt;av_frame_get_buffer(picture, 32);size = avpicture_get_size(pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height);picture_buf = (uint8_t*)av_malloc(size);avpicture_fill((AVPicture*)picture, picture_buf, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height);//[7] --写头文件avformat_write_header(pFormatCtx, NULL);//[7]//[8] --循环编码每一帧AVPacket pkt; //创建已编码帧int frame_count = 0;while (!feof(in_file)) {// 读取一帧 YUV 数据uint8_t yuv_buf[pCodecCtx->width * pCodecCtx->height * 3 / 2];size_t read_size = fread(yuv_buf, 1, pCodecCtx->width * pCodecCtx->height * 3 / 2, in_file);if (read_size <= 0) {break;}av_init_packet(&pkt);pkt.data = NULL;pkt.size = 0;// 将 YUV 数据编码为 H.264memcpy(picture->data[0], yuv_buf, pCodecCtx->width * pCodecCtx->height);memcpy(picture->data[1], yuv_buf + pCodecCtx->width * pCodecCtx->height, pCodecCtx->width * pCodecCtx->height / 4);memcpy(picture->data[2], yuv_buf + pCodecCtx->width * pCodecCtx->height * 5 / 4, pCodecCtx->width * pCodecCtx->height / 4);picture->pts = frame_count;int got_picture = 0;//编码int ret = avcodec_encode_video2(pCodecCtx, &pkt, picture, &got_picture);if (ret < 0){cout << "encoder fail!" << endl;return -1;}if (!got_picture){ret = 0;break;}cout << "encoder success! " <<picture->pts<< endl;// parpare packet for muxingpkt.stream_index = video_st->index;pkt.pts = frame_count * (pCodecCtx->time_base.den) / ((pCodecCtx->time_base.num) * 25);pkt.dts = pkt.pts;av_packet_rescale_ts(&pkt, pCodecCtx->time_base, video_st->time_base);pkt.pos = -1;ret = av_interleaved_write_frame(pFormatCtx, &pkt);if(ret < 0)break;av_free_packet(&pkt);frame_count++;usleep(30*1000);}//[8]//[9] --写文件尾av_write_trailer(pFormatCtx);//[9]//释放内存if (video_st){avcodec_close(video_st->codec);av_free(picture);av_free(picture_buf);}if (pFormatCtx){avio_close(pFormatCtx->pb);avformat_free_context(pFormatCtx);}fclose(in_file);return 0;
}
压缩一半的方式推送本地yuv文件 代码:
#include <stdio.h>
#include <unistd.h>
#include <iostream>
extern "C" {
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libavcodec/avcodec.h"
#include "libswscale/swscale.h"
};
using namespace std;const char* input_file = "/mnt/hgfs/shareVM/BigBuckBunny_CIF_24fps.yuv";
const char* output_rtmp_url = "rtmp://10.10.18.94:1935/live/test";
const int fps = 25;int main(int argc, char *argv[]) {AVFormatContext *pFormatCtx = nullptr;AVCodecContext *pCodecCtx = nullptr;//打开视频文件FILE *in_file = fopen(input_file, "rb");if (!in_file) {cout << "can not open file!" << endl;return -1;}//[1] --注册所有ffmpeg组件avcodec_register_all();av_register_all();//[2] --初始化AVFormatContext结构体,根据文件名获取到合适的封装格式avformat_alloc_output_context2(&pFormatCtx, NULL, "flv", output_rtmp_url);AVOutputFormat *fmt = pFormatCtx->oformat;//[3] --打开文件if (avio_open(&pFormatCtx->pb, output_rtmp_url, AVIO_FLAG_READ_WRITE)) {cout << "output file open fail!";return -1;}//[3]//[4] --初始化视频码流AVStream *video_st = avformat_new_stream(pFormatCtx, 0);if (video_st == NULL){printf("failed allocating output stram\n");avio_close(pFormatCtx->pb);avformat_free_context(pFormatCtx);return -1;}video_st->time_base.num = 1;video_st->time_base.den = fps;//[4]struct SwsContext* swsContext = sws_getContext(352, 288, AV_PIX_FMT_YUV420P,352 / 2, 288 / 2, AV_PIX_FMT_YUV420P,SWS_BICUBIC, NULL, NULL, NULL);if(swsContext == NULL) {printf("failed sws_getContext\n");avio_close(pFormatCtx->pb);avformat_free_context(pFormatCtx);return -1;}//[5] --编码器Context设置参数pCodecCtx = video_st->codec;pCodecCtx->codec_id = fmt->video_codec;pCodecCtx->codec_type = AVMEDIA_TYPE_VIDEO;pCodecCtx->pix_fmt = AV_PIX_FMT_YUV420P;pCodecCtx->width = 352 / 2;pCodecCtx->height = 288 / 2;pCodecCtx->time_base = {1, fps};pCodecCtx->framerate = {fps, 1};pCodecCtx->bit_rate = 400000;pCodecCtx->gop_size = 50;//[5]//[6] --寻找编码器并打开编码器AVCodec *pCodec = avcodec_find_encoder(AV_CODEC_ID_FLV1);if (!pCodec){cout << "no right encoder!" << endl;return -1;}if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0){cout << "open encoder fail!" << endl;avformat_free_context(pFormatCtx);return -1;}//[6]//输出格式信息av_dump_format(pFormatCtx, 0, output_rtmp_url, 1);//初始化帧AVFrame *originalFrame = av_frame_alloc();originalFrame->width = 352;originalFrame->height = 288;originalFrame->format = pCodecCtx->pix_fmt;av_frame_get_buffer(originalFrame, 32);int originalFrame_size = avpicture_get_size(pCodecCtx->pix_fmt, 352, 288);uint8_t* originalFrame_buf = (uint8_t*)av_malloc(originalFrame_size);avpicture_fill((AVPicture*)originalFrame, originalFrame_buf, pCodecCtx->pix_fmt, 352, 288);AVFrame *compressFrame = av_frame_alloc();compressFrame->width = pCodecCtx->width;compressFrame->height = pCodecCtx->height;compressFrame->format = pCodecCtx->pix_fmt;av_frame_get_buffer(compressFrame, 32);int compressFrame_size = avpicture_get_size((AVPixelFormat)compressFrame->format, compressFrame->width, compressFrame->height);uint8_t* compressFrame_buf = (uint8_t*)av_malloc(compressFrame_size);avpicture_fill((AVPicture*)compressFrame, compressFrame_buf, (AVPixelFormat)compressFrame->format, compressFrame->width, compressFrame->height);//[7] --写头文件avformat_write_header(pFormatCtx, NULL);//[7] //[8] --循环编码每一帧AVPacket pkt; //创建已编码帧int frame_count = 0;while (!feof(in_file)) {// 读取一帧 YUV 数据uint8_t yuv_buf[352 * 288 * 3 / 2];size_t read_size = fread(yuv_buf, 1, 352 * 288 * 3 / 2, in_file);if (read_size <= 0) {break;}av_init_packet(&pkt);pkt.data = NULL;pkt.size = 0;// 将 YUV 数据编码为 H.264memcpy(originalFrame->data[0], yuv_buf, 352 * 288);memcpy(originalFrame->data[1], yuv_buf + 352 * 288, 352 * 288 / 4);memcpy(originalFrame->data[2], yuv_buf + 352 * 288 * 5 / 4, 352 * 288 / 4);originalFrame->pts = compressFrame->pts = frame_count;int got_picture = 0;sws_scale(swsContext, (const uint8_t* const*)originalFrame->data, originalFrame->linesize, 0,288, compressFrame->data, compressFrame->linesize);//编码int ret = avcodec_encode_video2(pCodecCtx, &pkt, compressFrame, &got_picture);if (ret < 0){cout << "encoder fail!" << endl;return -1;}if (got_picture){cout << "encoder success! " <<compressFrame->pts<< endl;// parpare packet for muxingpkt.stream_index = video_st->index;pkt.pts = frame_count * (pCodecCtx->time_base.den) / ((pCodecCtx->time_base.num) * fps);pkt.dts = pkt.pts;av_packet_rescale_ts(&pkt, pCodecCtx->time_base, video_st->time_base);pkt.pos = -1;ret = av_interleaved_write_frame(pFormatCtx, &pkt);if(ret < 0)break;}av_free_packet(&pkt);frame_count++;usleep(30 * 1000);}//[8]//[9] --写文件尾av_write_trailer(pFormatCtx);//[9]//释放内存if (video_st){avcodec_close(video_st->codec);av_free(originalFrame);av_free(originalFrame_buf);av_free(compressFrame);av_free(compressFrame_buf);}if (pFormatCtx){avio_close(pFormatCtx->pb);avformat_free_context(pFormatCtx);}fclose(in_file);return 0;
}
相关文章:
FFMpeg rtmp 无压缩推送本地yuv文件 压缩推送本地yuv文件
可以借鉴的:C使用FFmpeg实现YUV数据编码转视频文件_C 语言_脚本之家 yuv文件下载地址:YUV Sequences 无压缩的方式推送本地yuv文件 代码: #include <stdio.h> #include <unistd.h> #include <iostream> extern "C&…...
PostgreSQL LIMIT 子句
PostgreSQL LIMIT 子句 PostgreSQL 是一种功能强大的开源对象关系数据库管理系统,广泛用于各种应用中。在处理大量数据时,我们通常只需要检索部分记录,而不是整个数据集。这时,LIMIT 子句就变得非常有用。本文将详细介绍 Postgre…...

误删分区后的数据拯救:双管齐下恢复策略
在数字化时代,数据的价值日益凸显,而误删分区作为常见的数据安全威胁之一,常常让用户措手不及。本文将深入探讨误删分区的现象,并为您揭示两种高效的数据恢复方案,旨在帮助您在最短时间内找回失去的数据,同…...
git 添加本地分支, clean
//以develop为源创建本地分支fromdevelop git checkout -b fromdevelop git add . git commit -m "local" git checkout -b local/dev //切换到远程分支. git checkout dev git clean_git clean -f -d-CSDN博客 git clean -f -d #删除当前目录下没有被track…...

Linux:进程间通信(一.初识进程间通信、匿名管道与命名管道、共享内存)
上次结束了基础IO:Linux:基础IO(三.软硬链接、动态库和静态库、动精态库的制作和加载) 文章目录 1.认识进程间通信2.管道2.1匿名管道2.2pipe()函数 —创建匿名管道2.3匿名管道的四种情况2.4管道的特征 3.基于管道的进程池设计4.命…...
QML-各类布局
Colunm布局 Column{id:colspacing: 30Repeater{id:repmodel: ListModel{}Button{width: 100height: 50text: "btn"index}}//开始时候移动move: Transition {NumberAnimation { properties: "x,y"; easing.type: Easing.OutBounce }}//添加时变化add:Transi…...

el-table封装点击列筛选行数据功能,支持筛选,搜索,排序功能
数据少的话,可以前端实现,如果多的话,建议还是请求接口比较合理父组件: <template> <div class"home"> <!-- <img alt"Vue logo" src"../assets/logo.png"> <HelloWorld …...

【SpringBoot3学习 | 第1篇】SpringBoot3介绍与配置文件
文章目录 前言 一. SpringBoot3介绍1.1 SpringBoot项目创建1. 创建Maven工程2. 添加依赖(springboot父工程依赖 , web启动器依赖)3. 编写启动引导类(springboot项目运行的入口)4. 编写处理器Controller5. 启动项目 1.2 项目理解1. 依赖不需要写版本原因2. 启动器(Starter)3. Sp…...

SpringBoot整合Dubbo的快速使用教程
目录 一、什么是Dubbo? 二、SpringBoot整合Dubbo 1、父工程引入依赖 2、各个Dubbo服务子模块引入依赖 3、服务提供者 (1)启动类添加注解EnableDubbo (2)服务类添加注解DubboService (3)配置文件…...
昇思25天学习打卡营第12天| 基于MindNLP+MusicGen生成自己的个性化音乐
之前都是看图文类的东西,今天体验一点不一样的。来点听力的内容。 mindspore有音乐生成模型MusicGen,MusicGen支持两种生成模式:贪心(greedy)和采样(sampling)。在实际执行过程中,采…...

代理设计模式和装饰器设计模式的区别
代理设计模式: 作用:为目标(原始对象)增加功能(额外功能,拓展功能) 三种经典应用场景: 1:给原始对象增加额外功能(spring添加事务,Mybatis通过代理实现缓存功能等等) 2:远程代理(网络通信,输出传输(RPC,D…...

[Microsoft Office]Word设置页码从第二页开始为1
目录 第一步:设置页码格式 第二步:设置“起始页码”为0 第三步:双击页码,出现“页脚”提示 第四步:选中“首页不同” 第一步:设置页码格式 第二步:设置“起始页码”为0 第三步:双…...

【C++】日期类
鼠鼠实现了一个日期类,用来练习印证前几篇博客介绍的内容!! 目录 1.日期类的定义 2.得到某年某月的天数 3.检查日期是否合法 4.(全缺省)构造函数 5.拷贝构造函数 6.析构函数 7.赋值运算符重载 8.>运算符重…...

力扣热100 滑动窗口
这里写目录标题 3. 无重复字符的最长子串438. 找到字符串中所有字母异位词 3. 无重复字符的最长子串 左右指针left和right里面的字符串一直是没有重复的 class Solution:def lengthOfLongestSubstring(self, s: str) -> int:# 左右指针leftright0ans0#初始化结果tablecolle…...

三万字带你一遍跑通uer
三万字带你一遍跑通uer 参考文档 今天给大家介绍个非常强大的项目uer,集成了许多可以做自然语言的东西,效果的话也非常好,很适合企业级的应用! 1. 先将项目uer从github拉取下来(zip或git都ok) 2. 用pycha…...

Ubuntu24.04LTS基础软件下载
librewolf: deb文件link 作用:访问github,无痕浏览,这个速度,不指望了 vscodium: 从deb安装,ubuntu sudo dpkg -i xxx.debpaste-image 插件替代 markdown wps: libreoffice: 替换USTC源 sudo nano /etc/apt/sourc…...
SQLAlchemy配置连接多个数据库
1.定义配置项 首先定义两个数据库的配置信息 # PostgreSQL database configuration DB_USERNAMEpostgres DB_PASSWORDpassord DB_HOST127.0.0.1 DB_PORT5432 DB_DATABASEtest# mysql database configuration DB_USERNAME_MYSQLroot DB_PASSWORD_MYSQLpassword DB_HOST_MYSQL127…...
NLP+LLM从入门到精通系列
NLPLLM从入门到精通系列 前言:笔者从事于NLPLLM的对话智能机器人的相关行业,现在的大模型的技术日新月异,传统的NLP业务显然是要被淘汰的,那么这也是我着笔写这一系列文章的初衷。本系列将由浅到深,结合实际代码案例&…...
用数组手搓一个小顶堆
堆默认从数组下标为1开始存储。 const int N201000; int heap[N]; int len; 插入操作: 将元素插入到堆的末尾位置向上调整。 void up(int k){while(k>1&&heap[k/2]>heap[k]){swap(heap[k],heap[k/2]);k/2;} } //len为当前存在元素长度 void Inser…...

【Linux开发】基于ALSA库实现音量调节
基于ALSA库实现音量调节 ALSA库实现音量调节1、使用alsamixer工具查看音频接口2、完整代码2.1、snd_mixer_open2.2、snd_mixer_attach、2.3、snd_mixer_selem_register2.4、snd_mixer_load2.5、snd_mixer_first_elem/snd_mixer_elem_next2.6、snd_mixer_selem_get_playback_vol…...

大数据学习栈记——Neo4j的安装与使用
本文介绍图数据库Neofj的安装与使用,操作系统:Ubuntu24.04,Neofj版本:2025.04.0。 Apt安装 Neofj可以进行官网安装:Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...

工业安全零事故的智能守护者:一体化AI智能安防平台
前言: 通过AI视觉技术,为船厂提供全面的安全监控解决方案,涵盖交通违规检测、起重机轨道安全、非法入侵检测、盗窃防范、安全规范执行监控等多个方面,能够实现对应负责人反馈机制,并最终实现数据的统计报表。提升船厂…...
模型参数、模型存储精度、参数与显存
模型参数量衡量单位 M:百万(Million) B:十亿(Billion) 1 B 1000 M 1B 1000M 1B1000M 参数存储精度 模型参数是固定的,但是一个参数所表示多少字节不一定,需要看这个参数以什么…...
基于Uniapp开发HarmonyOS 5.0旅游应用技术实践
一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架,支持"一次开发,多端部署",可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务,为旅游应用带来…...

dedecms 织梦自定义表单留言增加ajax验证码功能
增加ajax功能模块,用户不点击提交按钮,只要输入框失去焦点,就会提前提示验证码是否正确。 一,模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...

基于 TAPD 进行项目管理
起因 自己写了个小工具,仓库用的Github。之前在用markdown进行需求管理,现在随着功能的增加,感觉有点难以管理了,所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD,需要提供一个企业名新建一个项目&#…...
站群服务器的应用场景都有哪些?
站群服务器主要是为了多个网站的托管和管理所设计的,可以通过集中管理和高效资源的分配,来支持多个独立的网站同时运行,让每一个网站都可以分配到独立的IP地址,避免出现IP关联的风险,用户还可以通过控制面板进行管理功…...
django blank 与 null的区别
1.blank blank控制表单验证时是否允许字段为空 2.null null控制数据库层面是否为空 但是,要注意以下几点: Django的表单验证与null无关:null参数控制的是数据库层面字段是否可以为NULL,而blank参数控制的是Django表单验证时字…...

通过 Ansible 在 Windows 2022 上安装 IIS Web 服务器
拓扑结构 这是一个用于通过 Ansible 部署 IIS Web 服务器的实验室拓扑。 前提条件: 在被管理的节点上安装WinRm 准备一张自签名的证书 开放防火墙入站tcp 5985 5986端口 准备自签名证书 PS C:\Users\azureuser> $cert New-SelfSignedCertificate -DnsName &…...

ubuntu22.04有线网络无法连接,图标也没了
今天突然无法有线网络无法连接任何设备,并且图标都没了 错误案例 往上一顿搜索,试了很多博客都不行,比如 Ubuntu22.04右上角网络图标消失 最后解决的办法 下载网卡驱动,重新安装 操作步骤 查看自己网卡的型号 lspci | gre…...