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

c++调用ffmpeg api录屏 并进行rtmp推流

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

开发工具:visual studio 2019

记得启动rtmp流媒体服务 nginx的rtmp服务见https://download.csdn.net/download/daqinzl/20478812

播放,采用ffmpeg工具集里的ffplay.exe, 执行命令 ffplay rtmp://192.168.0.105:1935/live/desktop

主要代码如下:


#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);
        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);
        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";
       
        AVFormatContext * ic = NULL;
        ret = avformat_alloc_output_context2(&ic, 0, "flv", rtmpurl);
        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录屏 并进行rtmp推流

代码及工程见https://download.csdn.net/download/daqinzl/88156528 开发工具&#xff1a;visual studio 2019 记得启动rtmp流媒体服务 nginx的rtmp服务见https://download.csdn.net/download/daqinzl/20478812 播放&#xff0c;采用ffmpeg工具集里的ffplay.exe, 执行命令 f…...

SQL分类及通用语法数据类型(超详细版)

一、SQL分类 SQL是结构化查询语言&#xff08;Structured Query Language&#xff09;的缩写。它是一种用于管理和操作关系型数据库系统的标准化语言。SQL分类如下&#xff1a; DDL: 数据定义语言&#xff0c;用来定义数据库对象&#xff08;数据库、表、字段&#xff09;DML:…...

配置Hive远程服务详细步骤

HiveServer2支持多客户端的并发和认证&#xff0c;为开放API客户端如JDBC、ODBC提供了更好的支持。 &#xff08;1&#xff09;修改hive-site.xml&#xff0c;在文件中添加以下内容&#xff1a; <property><name>hive.metastore.event.db.notification.api.auth&l…...

Java中实现图片和Base64的互相转化

文章目录 前言一、代码二、测试三、结果 前言 公司项目中用到了实名认证此&#xff0c;采用的第三方平台。后端中用到的单项功能为身份证信息人像对比功能&#xff0c;在写demo的过程中发现&#xff0c;它们所要求的图片信息为base64编码格式。 一、代码 package com.bajiao…...

视频添加字幕

1、依靠ffmpeg 命令 package zimu;import java.io.IOException;public class TestSrt {public static void main(String[] args) {String videoFile "/test/test1.mp4";String subtitleFile "/test/test1.SRT";String outputFile "/test/testout13…...

Vue VS React:两大前端框架的对比与分析

Vue和React是当前最流行的前端框架之一&#xff0c;它们都有着广泛的应用和开发者社区。下面是Vue和React之间的深度对比与分析&#xff1a; 学习曲线&#xff1a; Vue&#xff1a;Vue拥有简单直观的API和文档&#xff0c;对初学者友好。Vue的设计初衷是逐步增强的&#xff0c;…...

【机密计算标准解读】 基于TEE的安全计算(IEEE 2952)

目录 1.概述2.定义、术语、缩略语3.技术框架3.1 架构框架3.2 分层功能4.基础组件4.1 基础层4.2 平台层4.3 应用层4.4 服务层4.5 交叉层5.安全计算参考过程6.技术和安全要求6.1 隔离要求6.2 互操作要求6.3 性能要求6.4 可用性要求6.5 数据安全要求6.6 密码学要求 1. 概述 随着…...

程序员编写文档的 10 个技巧

编写好的文档在软件开发领域具有重大意义。文档是概述特定问题陈述、方法、功能、工作流程、架构、挑战和开发过程的书面数据或指令。文档可以让你全面了解解决方案的功能、安装和配置。 文档不仅是为其他人编写的&#xff0c;也是为自己编写的。它让我们自己知道我们以前做过什…...

【ES问题总结】

文章目录 1、什么是ElasticSearch;2、ElasticSearch的基本概念&#xff1b;3、什么是倒排索引&#xff1b;4、DocValue的作用&#xff1b;5、text和keyword类型的区别&#xff1b;7、query和filter的区别&#xff1b;8、es写数据的过程&#xff1b;9、es的更新和删除流程&#…...

数据结构----结构--线性结构--顺序存储--数组

数据结构----结构–线性结构–顺序存储–数组 数组&#xff1a;类型相同&#xff0c;空间连续&#xff0c;长度固定 搜索&#xff1a; &#xff08;1&#xff09;基于索引搜索&#xff0c;时间复杂度O(1) &#xff08;2&#xff09;基于数值搜索&#xff1a; ​ 1.有序的&…...

docker 启动kitex 的opentelemetry

https://github.com/cloudwego/kitex-examples/blob/main/opentelemetry/docker-compose.yaml 下载两个yaml文件&#xff1a;docker-compose.yaml otel-collector-config.yaml 在该目录下执行 docker-compose up -d...

Excel中——日期列后添加星期

需求&#xff1a;在日期列中添加星期几&#xff1f; 第一步&#xff1a;打开需要添加星期的Excel文件&#xff0c;在日期后面添加日期 第二步&#xff1a;选择日期列&#xff0c;点击鼠标右键&#xff0c;在下拉列表中&#xff0c;选择“设置单元格格式” 第三步&#xff1a; 在…...

谈谈DNS是什么?它的作用以及工作流程

作者&#xff1a;Insist-- 个人主页&#xff1a;insist--个人主页 作者会持续更新网络知识和python基础知识&#xff0c;期待你的关注 目录 一、DNS是什么&#xff1f; 二、DNS的作用 三、DNS查询流程 1、查看浏览器缓存 2、查看系统缓存 3、查看路由器缓存 4、查看ISP …...

Qt小项目贪吃蛇实线,主要掌握定时器、信号与槽、按键事件、绘制事件、坐标运算、随机数生成等

Qt小项目贪吃蛇实线&#xff0c;主要掌握定时器、信号与槽、按键事件、绘制事件、坐标运算、随机数生成等 Qt 贪吃蛇演示QWidget 绘制界面项目源文件 注释清晰widget.hwidget.cpp 拓展QTimerQKeyEventQRectFQPointFQPainterQIcon Qt 贪吃蛇演示 QWidget 绘制界面 项目源文件 注…...

使用HTTP隧道时如何应对目标网站的反爬虫监测?

在进行网络抓取时&#xff0c;我们常常会遇到目标网站对反爬虫的监测和封禁。为了规避这些风险&#xff0c;使用代理IP成为一种常见的方法。然而&#xff0c;如何应对目标网站的反爬虫监测&#xff0c;既能保证数据的稳定性&#xff0c;又能确保抓取过程的安全性呢&#xff1f;…...

怎么样通过Bootstrap已经编译好(压缩好)的源码去查看符合阅读习惯的源码【通过Source Map(源映射)文件实现】

阅读本篇博文前&#xff0c;建议大家先看看下面这篇博文&#xff1a; https://blog.csdn.net/wenhao_ir/article/details/132089650 Bootstrap经编译(压缩)后的源码百度网盘下载地址&#xff1a; https://pan.baidu.com/s/14BM9gpC3K-LKxhyLGh4J9Q?pwdm02m Bootstrap未经编译…...

【排序算法】python之冒泡,选择,插入,快速,归并

参考资料&#xff1a; 《Python实现5大排序算法》《六大排序算法&#xff1a;插入排序、希尔排序、选择排序、冒泡排序、堆排序、快速排序》 --代码似乎是C语言 ———————— 本文介绍5种常见的排序算法和基于Python实现&#xff1a; 冒泡排序&#xff08;Bubble Sort&am…...

UML—用例图的那些事

目录 背景: 1.用例图的发展史 过程: 1.用例图中的元素和关系 2.应用中的例子 总结&#xff1a; 背景: 1.用例图的发展史 用例图是一种常用的软件工程工具&#xff0c;用于描述系统的功能需求和用户与系统的交互。它在软件开发过程中起到了重要的作用&#xff0c;并且经历了…...

迷宫出口问题求解(DFS)

题面 一天Extense在森林里探险的时候不小心走入了一个迷宫&#xff0c;迷宫可以看成是由 nn 的格点组成&#xff0c;每个格点只有 22 种状态&#xff0c; 00 和 11&#xff0c;前者表示可以通行后者表示不能通行。 同时当Extense处在某个格点时&#xff0c;他只能移动到东南西北…...

基础算法模板

数据结构 单链表的插入删除 const int N=1e6+10; int head,e[N],ne[N],idx; //head 存储头节点的下标 //idx 存储当前已经用到的那个点 void init() {head=-1;idx=0; } void add_to_head(int x)//插入头节点操作 {e[idx]=x;ne[idx]=head;head=idx;idx++; } void add(int k)/…...

7.4.分块查找

一.分块查找的算法思想&#xff1a; 1.实例&#xff1a; 以上述图片的顺序表为例&#xff0c; 该顺序表的数据元素从整体来看是乱序的&#xff0c;但如果把这些数据元素分成一块一块的小区间&#xff0c; 第一个区间[0,1]索引上的数据元素都是小于等于10的&#xff0c; 第二…...

IGP(Interior Gateway Protocol,内部网关协议)

IGP&#xff08;Interior Gateway Protocol&#xff0c;内部网关协议&#xff09; 是一种用于在一个自治系统&#xff08;AS&#xff09;内部传递路由信息的路由协议&#xff0c;主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...

1.3 VSCode安装与环境配置

进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件&#xff0c;然后打开终端&#xff0c;进入下载文件夹&#xff0c;键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...

新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案

随着新能源汽车的快速普及&#xff0c;充电桩作为核心配套设施&#xff0c;其安全性与可靠性备受关注。然而&#xff0c;在高温、高负荷运行环境下&#xff0c;充电桩的散热问题与消防安全隐患日益凸显&#xff0c;成为制约行业发展的关键瓶颈。 如何通过智慧化管理手段优化散…...

Unit 1 深度强化学习简介

Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库&#xff0c;例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体&#xff0c;比如 SnowballFight、Huggy the Do…...

第7篇:中间件全链路监控与 SQL 性能分析实践

7.1 章节导读 在构建数据库中间件的过程中&#xff0c;可观测性 和 性能分析 是保障系统稳定性与可维护性的核心能力。 特别是在复杂分布式场景中&#xff0c;必须做到&#xff1a; &#x1f50d; 追踪每一条 SQL 的生命周期&#xff08;从入口到数据库执行&#xff09;&#…...

【学习笔记】erase 删除顺序迭代器后迭代器失效的解决方案

目录 使用 erase 返回值继续迭代使用索引进行遍历 我们知道类似 vector 的顺序迭代器被删除后&#xff0c;迭代器会失效&#xff0c;因为顺序迭代器在内存中是连续存储的&#xff0c;元素删除后&#xff0c;后续元素会前移。 但一些场景中&#xff0c;我们又需要在执行删除操作…...

【Linux系统】Linux环境变量:系统配置的隐形指挥官

。# Linux系列 文章目录 前言一、环境变量的概念二、常见的环境变量三、环境变量特点及其相关指令3.1 环境变量的全局性3.2、环境变量的生命周期 四、环境变量的组织方式五、C语言对环境变量的操作5.1 设置环境变量&#xff1a;setenv5.2 删除环境变量:unsetenv5.3 遍历所有环境…...

一些实用的chrome扩展0x01

简介 浏览器扩展程序有助于自动化任务、查找隐藏的漏洞、隐藏自身痕迹。以下列出了一些必备扩展程序&#xff0c;无论是测试应用程序、搜寻漏洞还是收集情报&#xff0c;它们都能提升工作流程。 FoxyProxy 代理管理工具&#xff0c;此扩展简化了使用代理&#xff08;如 Burp…...

Qt的学习(一)

1.什么是Qt Qt特指用来进行桌面应用开发&#xff08;电脑上写的程序&#xff09;涉及到的一套技术Qt无法开发网页前端&#xff0c;也不能开发移动应用。 客户端开发的重要任务&#xff1a;编写和用户交互的界面。一般来说和用户交互的界面&#xff0c;有两种典型风格&…...