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

这篇具有很好参考价值的文章主要介绍了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;
    }
    文章来源地址https://www.toymoban.com/news/detail-633408.html

到了这里,关于c++调用ffmpeg api录屏 并进行udp组播推流的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 利用FFmpeg实现录屏、直播推流、音频视频格式转换、剪裁等功能

    一、FFmpeg简介。 二、FFmpeg常用参数及命令。 三、FFmpeg在Unity 3D中的使用。 1、FFmpeg 录屏。 2、FFmpeg 推流。 3、FFmpeg 其他功能简述。 对于FFmpeg,其官网上是这样介绍的: FFmpeg is the leading multimedia framework, able to decode, encode, transcode, mux, demux, stream, filter and play pretty much anything th

    2024年02月09日
    浏览(39)
  • FFmpeg/opencv + C++ 实现直播拉流和直播推流(对视频帧进行处理)

    本文主要使用C++ ffmpeg库实现对除去webrtc的视频流进行拉流,而后经过自身的处理,而后通过将处理后的视频帧进行编码,最后进行推流处理。详情请看代码 参考链接: https://blog.csdn.net/weixin_45807901/article/details/129086344 https://blog.csdn.net/T__zxt/article/details/126827167

    2024年02月16日
    浏览(40)
  • ffmpeg SDL播放器--播放udp组播流

    c++调用ffmpeg api及SDL库播放播放udp组播流。 代码及工程见https://download.csdn.net/download/daqinzl/88168574 参考文档:https://blog.csdn.net/a53818742/article/details/109312740 开发工具:visual studio 2019 记得推送udp流,可采用ffmpeg工具集里的ffmpeg.exe推送, 执行命令 ffmpeg -f gdigrab -r 23 -i desktop -pkt_size

    2024年02月14日
    浏览(28)
  • windows10|音视频剪辑|FFMPEG录屏和网络推流源初步的生成

    FFMPEG的功能强大是毋庸置疑的,那么录屏的需求大家在某些时候大家可能是非常需要的,例如,现有的项目需要演示,因此录制一段演示视频;亦或者做内容分发直播的,比如游戏主播,需要录制在玩某个游戏的精彩片段,以创建一个后期的视频素材库; 亦或者通过FFMPEG抓取

    2024年02月20日
    浏览(53)
  • ffmpeg推流rtmp指定udp传输

    RTMP (Real-Time Messaging Protocol) 是一个用于音频、视频和数据的传输协议。RTMP 协议本身可以支持 TCP 或 UDP 作为其底层传输协议。 在 RTMP 中,TCP 是默认的传输协议,它的稳定性和可靠性比 UDP 更好。但是,TCP 的延迟较高,对于实时性要求较高的音视频应用来说可能不太适合。 相

    2024年02月15日
    浏览(26)
  • QT软件开发-基于FFMPEG设计录屏与rtsp、rtmp推流软件(支持桌面与摄像头)(四)

    QT软件开发-基于FFMPEG设计录屏与rtsp、rtmp推流软件(支持桌面与摄像头)(一) https://xiaolong.blog.csdn.net/article/details/126954626 QT软件开发-基于FFMPEG设计录屏与rtsp、rtmp推流软件(支持桌面与摄像头)(二) https://xiaolong.blog.csdn.net/article/details/126958188 QT软件开发-基于FFMPEG设计录屏与rt

    2023年04月19日
    浏览(42)
  • 使用FFmpeg将本地文件通过UDP推流的音视频

    推流是指将音视频数据通过网络传输到指定的目标端,而FFmpeg是一个功能强大的跨平台多媒体处理工具,可以用于音视频编解码、转码、处理等操作。本文将介绍如何使用FFmpeg将本地文件通过UDP协议进行推流,实现音视频数据的传输。 首先,需要确保已经安装了FFmpeg工具。如

    2024年03月19日
    浏览(43)
  • W6100-EVB-PICO进行UDP组播数据回环测试(九)

            上一章我们用我们的开发板作为UDP客户端连接服务器进行数据回环测试,那么本章我们进行UDP组播数据回环测试。         组播是主机间一对多的通讯模式, 组播是一种允许一个或多个组播源发送同一报文到多个接收者的技术。组播源将一份报文发送到特定的

    2024年02月11日
    浏览(29)
  • W5500-EVB-PICO进行UDP组播数据回环测试(九)

            上一章我们用我们的开发板作为UDP客户端连接服务器进行数据回环测试,那么本章我们进行UDP组播数据回环测试。         组播是主机间一对多的通讯模式, 组播是一种允许一个或多个组播源发送同一报文到多个接收者的技术。组播源将一份报文发送到特定的

    2024年02月11日
    浏览(23)
  • 基于FFmpeg进行rtsp推流及拉流

    1. 安装FFmpeg FFmpeg 是一个免费、开源的跨平台视频和音频流处理工具。 首先,打开终端(在 Windows 中是命令提示符,在 Windows 搜索栏中输入“cmd”,然后打开命令提示符),然后运行以下命令以检查您的系统上是否已安装 FFmpeg: ffmpeg -version 如果显示安装的版本号,表明 FF

    2024年04月17日
    浏览(24)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包