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

c++调用ffmpeg api录屏 并进行udp组播推流

代码及工程见https://download.csdn.net/download/daqinzl/88155241

开发工具:visual studio 2019

播放,采用ffmpeg工具集里的ffplay.exe, 执行命令 ffplay udp://224.1.1.1:5001

主要代码如下:


#include "pch.h"
#include <iostream>
using namespace std;

#include <stdio.h>

#define __STDC_CONSTANT_MACROS

extern "C"
{
#include "include/libavcodec/avcodec.h"
#include "include/libavformat/avformat.h"
#include "include/libswscale/swscale.h"
#include "include/libavdevice/avdevice.h"
#include "include/libavutil/imgutils.h"
#include "include/libavutil/opt.h"
#include "include/libavutil/imgutils.h"
#include "include/libavutil/mathematics.h"
#include "include/libavutil/time.h"
};


#pragma comment (lib,"avcodec.lib")
#pragma comment (lib,"avdevice.lib")
#pragma comment (lib,"avfilter.lib")
#pragma comment (lib,"avformat.lib")
#pragma comment (lib,"avutil.lib")
#pragma comment (lib,"swresample.lib")
#pragma comment (lib,"swscale.lib")


int main(int argc, char* argv[])
{

            AVFormatContext* m_fmt_ctx = NULL;
        AVInputFormat* m_input_fmt = NULL;
        int video_stream = -1;
        avdevice_register_all();
        avcodec_register_all();
        const char* deviceName =  "desktop";
        const char* inputformat = "gdigrab";
        int FPS = 23;  //15
        m_fmt_ctx = avformat_alloc_context();
        m_input_fmt = av_find_input_format(inputformat);
        AVDictionary* deoptions = NULL;
        av_dict_set_int(&deoptions, "framerate", FPS, AV_DICT_MATCH_CASE);
        av_dict_set_int(&deoptions, "rtbufsize", 3041280 * 100 * 5, 0);

        //如果不设置的话,在输入源是直播流的时候,会花屏。单位bytes
        //av_dict_set(&deoptions, "buffer_size", "10485760", 0);
        //av_dict_set(&deoptions, "reuse", "1", 0);

        int ret = avformat_open_input(&m_fmt_ctx, deviceName, m_input_fmt, &deoptions);
        if (ret != 0) {
            
                return ret;
        }
        av_dict_free(&deoptions);
        ret = avformat_find_stream_info(m_fmt_ctx, NULL);
        if (ret < 0) {
            
                return ret;
        }
        av_dump_format(m_fmt_ctx, 0, deviceName, 0);
        video_stream = av_find_best_stream(m_fmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0);
        if (video_stream < 0) {
            
                return -1;
        }

        AVCodecContext * _codec_ctx = m_fmt_ctx->streams[video_stream]->codec;
        AVCodec* _codec = avcodec_find_decoder(_codec_ctx->codec_id);
        if (_codec == NULL) {
            
                return -1;
        }
        ret = avcodec_open2(_codec_ctx, _codec, NULL);
        if (ret != 0) {
            
                return -1;
        }
        int width = m_fmt_ctx->streams[video_stream]->codec->width;
        int height = m_fmt_ctx->streams[video_stream]->codec->height;
        int fps = m_fmt_ctx->streams[video_stream]->codec->framerate.num > 0 ? m_fmt_ctx->streams[video_stream]->codec->framerate.num : 25;
        AVPixelFormat videoType = m_fmt_ctx->streams[video_stream]->codec->pix_fmt;
        std::cout << "avstream timebase : " << m_fmt_ctx->streams[video_stream]->time_base.num << " / " << m_fmt_ctx->streams[video_stream]->time_base.den << endl;
            AVDictionary* enoptions = 0;
        //av_dict_set(&enoptions, "preset", "superfast", 0);
        //av_dict_set(&enoptions, "tune", "zerolatency", 0);
        av_dict_set(&enoptions, "preset", "ultrafast", 0);
        av_dict_set(&enoptions, "tune", "zerolatency", 0); 

        //TODO
        //av_dict_set(&enoptions, "pkt_size", "1316", 0);    //Maximum UDP packet size
        av_dict_set(&dic, "fifo_size", "18800", 0);
        av_dict_set(&enoptions, "buffer_size", "0", 1);
        av_dict_set(&dic, "bitrate", "11000000", 0);
        av_dict_set(&dic, "buffer_size", "1000000", 0);//1316
        //av_dict_set(&enoptions, "reuse", "1", 0);

        AVCodec* codec = avcodec_find_encoder(AV_CODEC_ID_H264);
        if (!codec)
        {
            
                std::cout << "avcodec_find_encoder failed!" << endl;
            return NULL;
        }
        AVCodecContext* vc = avcodec_alloc_context3(codec);
        if (!vc)
        {
            
                std::cout << "avcodec_alloc_context3 failed!" << endl;
            return NULL;
        }
        std::cout << "avcodec_alloc_context3 success!" << endl;
        vc->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
        vc->codec_id = AV_CODEC_ID_H264;
        vc->codec_type = AVMEDIA_TYPE_VIDEO;
        vc->pix_fmt = AV_PIX_FMT_YUV420P;
        vc->width = width;
        vc->height = height;
        vc->time_base.num = 1;
        vc->time_base.den = FPS;
        vc->framerate = { FPS,1 };
        vc->bit_rate = 10241000;
        vc->gop_size = 120;
        vc->qmin = 10;
        vc->qmax = 51;
        vc->max_b_frames = 0;
        vc->profile = FF_PROFILE_H264_MAIN;                
        ret = avcodec_open2(vc, codec, &enoptions);
        if (ret != 0)
        {
            return ret;
        }
        std::cout << "avcodec_open2 success!" << endl;
        av_dict_free(&enoptions);
        SwsContext *vsc = nullptr;
        vsc = sws_getCachedContext(vsc,
            width, height, (AVPixelFormat)videoType, //源宽、高、像素格式
            width, height, AV_PIX_FMT_YUV420P,//目标宽、高、像素格式
            SWS_BICUBIC, // 尺寸变化使用算法
            0, 0, 0
        );
        if (!vsc)
        {
            
                cout << "sws_getCachedContext failed!";
            return false;
        }
        AVFrame* yuv = av_frame_alloc();
        yuv->format = AV_PIX_FMT_YUV420P;
        yuv->width = width;
        yuv->height = height;
        yuv->pts = 0;
        ret = av_frame_get_buffer(yuv, 32);
        if (ret != 0)
        {
            
                return ret;
        }
        //const char* rtmpurl = "rtmp://192.168.0.105:1935/live/desktop";
        const char* rtmpurl = "udp://224.1.1.1:5001";
        AVFormatContext * ic = NULL;
        //ret = avformat_alloc_output_context2(&ic, 0, "flv", rtmpurl);
        ret = avformat_alloc_output_context2(&ic, NULL, "mpegts", rtmpurl);//UDP
        if (ret < 0)
        {
            
                return ret;
        }
        AVStream* st = avformat_new_stream(ic, NULL);
        if (!st)
        {
            
                return -1;
        }
        st->codecpar->codec_tag = 0;
        avcodec_parameters_from_context(st->codecpar, vc);
        av_dump_format(ic, 0, rtmpurl, 1);
        ret = avio_open(&ic->pb, rtmpurl, AVIO_FLAG_WRITE);
        if (ret != 0)
        {
            
                return ret;
        }
        ret = avformat_write_header(ic, NULL);
        if (ret != 0)
        {
            
                return ret;
        }
        AVPacket* packet = av_packet_alloc();
        AVPacket* Encodepacket = av_packet_alloc();
        int frameIndex = 0;
        int EncodeIndex = 0;
        AVFrame* rgb = av_frame_alloc();
        AVBitStreamFilterContext* h264bsfc = av_bitstream_filter_init("h264_mp4toannexb");
        long long startpts = m_fmt_ctx->start_time;
        long long lastpts = 0;
        long long duration = av_rescale_q(1, { 1,FPS }, { 1,AV_TIME_BASE });
        int got_picture = 0;
        while (frameIndex < 2000000)
        {
            
                ret = av_read_frame(m_fmt_ctx, packet);
            if (ret < 0) {
                
                    break;
            }
            if (packet->stream_index == video_stream)
            {
                
                    ret = avcodec_decode_video2(_codec_ctx, rgb, &got_picture, packet);
                if (ret < 0) {
                    
                        printf("Decode Error.\n");
                    return ret;
                }
                if (got_picture) {
                    
                        int h = sws_scale(vsc, rgb->data, rgb->linesize, 0, height, //源数据
                            yuv->data, yuv->linesize);
                    int guesspts = frameIndex * duration;
                    yuv->pts = guesspts;
                    frameIndex++;
                    ret = avcodec_encode_video2(vc, Encodepacket, yuv, &got_picture);
                    if (ret < 0) {
                        
                            printf("Failed to encode!\n");
                        break;
                    }
                    if (got_picture == 1) {
                        
                            Encodepacket->pts = av_rescale_q(EncodeIndex, vc->time_base, st->time_base);
                        Encodepacket->dts = Encodepacket->pts;
                        std::cout << "frameindex : " << EncodeIndex << " pts : " << Encodepacket->pts << " dts: " << Encodepacket->dts << " encodeSize:" << Encodepacket->size << " curtime - lasttime " << Encodepacket->pts - lastpts << endl;
                            lastpts = Encodepacket->pts;
                        ret = av_interleaved_write_frame(ic, Encodepacket);
                        EncodeIndex++;
                        av_packet_unref(Encodepacket);
                    }
                }
            }
            av_packet_unref(packet);
        }
        ret = avcodec_send_frame(vc, NULL);
        while (ret >= 0) {
            
                ret = avcodec_receive_packet(vc, Encodepacket);
            if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
                
                    break;
            }
            if (ret < 0) {
                
                    break;
            }
            ret = av_interleaved_write_frame(ic, Encodepacket);
            EncodeIndex++;
        }
        av_write_trailer(ic);
        av_packet_free(&packet);
        av_packet_free(&Encodepacket);
        av_frame_free(&rgb);
        av_frame_free(&yuv);
        av_bitstream_filter_close(h264bsfc);
        h264bsfc = NULL;
        if (vsc)
        {
            
                sws_freeContext(vsc);
            vsc = NULL;
        }
        if (_codec_ctx)
            avcodec_close(_codec_ctx);
        _codec_ctx = NULL;
        _codec = NULL;
        if (vc)
            avcodec_free_context(&vc);
        if (m_fmt_ctx)
            avformat_close_input(&m_fmt_ctx);
        if (ic && !(ic->flags & AVFMT_NOFILE))
            avio_closep(&ic->pb);
        if (ic) {
            
                avformat_free_context(ic);
            ic = NULL;
        }
        m_input_fmt = NULL;
        return 0;
    }
    

相关文章:

c++调用ffmpeg api录屏 并进行udp组播推流

代码及工程见https://download.csdn.net/download/daqinzl/88155241 开发工具&#xff1a;visual studio 2019 播放&#xff0c;采用ffmpeg工具集里的ffplay.exe, 执行命令 ffplay udp://224.1.1.1:5001 主要代码如下: #include "pch.h" #include <iostream>…...

war包方式安装linux和windows的geoserver

注意&#xff1a; 从Java 9开始&#xff0c;Oracle已经不再单独提供JRE&#xff08;Java Runtime Environment&#xff09;了&#xff0c;而是直接将JRE集成在JDK&#xff08;Java Development Kit&#xff09;中。这是因为JRE包含了运行Java程序所需的环境&#xff0c;而JDK除…...

安装CUDA与CUDNN与Pytorch(最新超级详细图文版本2023年8月最新)

一、安装CUDA 1.1、下载安装包 cuda可以认为就是Nvidia为了显卡炼丹搞的一个软件&#xff0c;其下载地址为&#xff1a;CUDA Toolkit 12.2 Update 1 Downloads | NVIDIA Developer 当你点进这个链接的时候&#xff0c;你需要依次选择 1是选择系统&#xff0c;这里选windows…...

内存快照:宕机后,Redis如何实现快速恢复?RDB

AOF的回顾 回顾Redis 的AOF的持久化机制。 Redis 避免数据丢失的 AOF 方法。这个方法的好处&#xff0c;是每次执行只需要记录操作命令&#xff0c;需要持久化的数据量不大。一般而言&#xff0c;只要你采用的不是 always 的持久化策略&#xff0c;就不会对性能造成太大影响。 …...

Linux之 Ubuntu 安装常见服务 (二) Tomcat

安装TomCat 服务 1、安装JDK环境 https://www.oracle.com/java/technologies/downloads/ 下载的官网 wget https://download.oracle.com/java/20/latest/jdk-20_linux-x64_bin.deb (sha256) 使用dpkg进行软件安装时&#xff0c;提示&#xff1a;dpkg&#xff1a;处理软件包XX…...

docker 配置 Mysql主从集群

Docker version 20.10.17, build 100c701 MySQL Image version: 8.0.32 Docker container mysql-master is source. mys ql-replica is replication. master source. replica slave.名称叫法不一样而已。 Choose one of the way&#xff0c;与replica同步数据两种情况&…...

Layui实现OA会议系统之会议管理模块总合

目录 一、项目背景 二、项目概述 1. 概述 2. 环境搭建 3. 工具类引用 4. 功能设计 4.1 会议发布 4.2 我的会议 4.3 会议审批 4.4 会议通知 4.5 待开会议 4.6 历史会议 4.7 所有会议 5. 性能优点 5.1 兼容性好 5.2 可维护性和可扩展性 5.3 轻量灵活 5.4 模块化设计…...

fishing之踩坑篇捕获数据不齐全

文章目录 一、问题记录二、解决方法三、更新钓鱼模板四、进行点击邮件五、查看仪表盘免责声明 一、问题记录 通过点击邮件内的链接&#xff0c;提交数据&#xff0c;但是只记录密码&#xff0c;无法记录username 二、解决方法 对于需要被捕获的表单数据&#xff0c;除了inp…...

ppt使用笔记

文章目录 如何让文档好看纯文字绝对不可行多用流程图和效果图切换动画母版音乐视频 作品渐变星空放大镜随机抽奖 其他快捷键 作为一个开发&#xff0c;对这种表现类型的软件一直不太上心&#xff0c;但有些场景要用到ppt&#xff0c;例如述职和项目案例分享。 很直观的体验就是…...

java中的hashmap和concurrenthashmap解析

hashmap的初始化数组大小为16&#xff0c;如果发生哈希冲突的时候在当前的索引后面采用头插法以链表的形式继续插入节点。 concurrenthashmap的结构图如下所示&#xff1a; 本身不是16个节点吗&#xff1f;这里分为两个长度为4的数组&#xff0c;变成了4*4总共16个节点&#x…...

元素2D转3D 椭圆形旋转实现

椭圆旋转功能展示 transform-style: preserve-3d;&#xff08;主要css代码&#xff09; gif示例&#xff08;背景图可插入透明以此实现边框线的旋转&#xff09; 导致的无法点击遮挡问题可以参考我的另一个文章 穿透属性-----------------------css穿透属性 实时代码展示...

Centos7.9 制作openssh9.2p2 rpm升级包和升级实战

一、背景说明 Centos7.9 默认安装的openssh 版本为7.4p1&#xff0c;经绿盟扫描&#xff0c;存在高危漏洞&#xff0c;需要升级到最新。 官网只提供编译安装包&#xff0c;为了方便升级&#xff0c;先通过编译安装包&#xff0c;制作rpm包&#xff0c;并进行升级 如下为做好…...

JavaScript学习(3)

Web API 是开发人员的梦想。 它可以扩展浏览器的功能它可以极大简化复杂的功能它可以为复杂的代码提供简单的语法 什么是 Web API&#xff1f; API 指的是应用程序编程接口&#xff08;Application Programming Interface&#xff09;。 Web API 是 Web 的应用程序编程接口…...

2023华为OD机试真题Java实现【寻找最大价值的矿堆/深度优先搜索】

前言 本题使用Java实现,如果需要Python代码,请点击以下链接 点我 题目 我们规定,0表示空地,1表示银矿、2表示金矿,矿堆表示由相邻的金矿或银矿连接形成的地图。 银矿价值是1 ,金矿价值是2 ,你的目标是找出地图中最大价值的矿堆,并且输出该矿堆的价值 示例1 输入:…...

MyCat概述

1.MyCat概述 MyCat是阿里巴巴的产品&#xff0c;他是开源的、基于Java语言编写的MySQL数据库中间件。可以像使用mysql一样来使用mycat&#xff0c;对于开发人员来说根本感觉不到mycat的存在。 MyCat下载地址&#xff1a;http://dl.mycat.org.cn/ MyCat官网&#xff1a;http:/…...

【LeetCode】【数据结构】单链表OJ常见题型(一)

&#x1f440;樊梓慕&#xff1a;个人主页 &#x1f3a5;个人专栏&#xff1a;《C语言》《数据结构》《蓝桥杯试题》《LeetCode刷题笔记》 &#x1f31d;每一个不曾起舞的日子&#xff0c;都是对生命的辜负。 目录 前言&#xff1a; 【LeetCode】203.移除链表元素 【LeetCo…...

QGraphicsView实现简易地图3『局部加载-地图缩放』

前文链接&#xff1a;QGraphicsView实现简易地图2『瓦片经纬度』 第一篇文章提到过&#xff0c;当地图层级较大时&#xff0c;暴力全加载地图会造成程序卡顿&#xff0c;因此需要实现地图的局部加载。 实现思路&#xff1a;以地图窗口&#xff08;以下称为视口&#xff09;为地…...

bash的特性(二)IO重定向与管道

bash的I/O重定向及管道 一、概述 在shell中&#xff0c;最常使用的fd(file descriptor)有三个&#xff0c;标准输入&#xff0c;标准输出&#xff0c;错误输出。进程用文件描述符来管理打开的文件。 名称 文件描述符 标准输入&#xff08;stdin) 0 键盘&#xff0c;也可以…...

elb 直接配置到后端服务器组

出现上图报错的原因是&#xff0c;前面elb配置了https证书&#xff0c;后端的nginx也配置了证书&#xff0c;导致冲突。 需要修改后端的nginx配置文件&#xff0c;将证书配置注释掉。 如果出现健康检查异常&#xff0c;需要在对应服务器的安全组上配置elb所在的网段的访问权限…...

安卓:BottomNavigationBar——底部导航栏控件

目录 一、BottomNavigationBar介绍 二、BottomNavigationBar的常用方法及其常用类 &#xff08;一&#xff09;、常用方法 1. 添加菜单项 2. 移除菜单项 3. 设置选中监听器 4. 设置当前选中项 5. 设置徽章 6. 样式和颜色定制 7. 动画效果 8. 隐藏底部导航栏。 9、设…...

网络六边形受到攻击

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 抽象 现代智能交通系统 &#xff08;ITS&#xff09; 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 &#xff08;…...

Oracle查询表空间大小

1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...

全球首个30米分辨率湿地数据集(2000—2022)

数据简介 今天我们分享的数据是全球30米分辨率湿地数据集&#xff0c;包含8种湿地亚类&#xff0c;该数据以0.5X0.5的瓦片存储&#xff0c;我们整理了所有属于中国的瓦片名称与其对应省份&#xff0c;方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...

Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具

文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...

React19源码系列之 事件插件系统

事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...

用docker来安装部署freeswitch记录

今天刚才测试一个callcenter的项目&#xff0c;所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...

前端中slice和splic的区别

1. slice slice 用于从数组中提取一部分元素&#xff0c;返回一个新的数组。 特点&#xff1a; 不修改原数组&#xff1a;slice 不会改变原数组&#xff0c;而是返回一个新的数组。提取数组的部分&#xff1a;slice 会根据指定的开始索引和结束索引提取数组的一部分。不包含…...

内窥镜检查中基于提示的息肉分割|文献速递-深度学习医疗AI最新文献

Title 题目 Prompt-based polyp segmentation during endoscopy 内窥镜检查中基于提示的息肉分割 01 文献速递介绍 以下是对这段英文内容的中文翻译&#xff1a; ### 胃肠道癌症的发病率呈上升趋势&#xff0c;且有年轻化倾向&#xff08;Bray等人&#xff0c;2018&#x…...

Qt的学习(二)

1. 创建Hello Word 两种方式&#xff0c;实现helloworld&#xff1a; 1.通过图形化的方式&#xff0c;在界面上创建出一个控件&#xff0c;显示helloworld 2.通过纯代码的方式&#xff0c;通过编写代码&#xff0c;在界面上创建控件&#xff0c; 显示hello world&#xff1b; …...

RabbitMQ 各类交换机

为什么要用交换机&#xff1f; 交换机用来路由消息。如果直发队列&#xff0c;这个消息就被处理消失了&#xff0c;那别的队列也需要这个消息怎么办&#xff1f;那就要用到交换机 交换机类型 1&#xff0c;fanout&#xff1a;广播 特点 广播所有消息​​&#xff1a;将消息…...