FFMPEG录屏(1)----录制桌面

首先录制桌面有很多种方法,原生windows api进行GDI抓屏,Mirror,Direct等,本文针对ffmpeg gdi抓屏进行介绍,也开始录屏软件开发之旅。

准备ffmpeg,无所谓是动态库、静态库,请自行前往下载并引入工程。

在本系列文章中,一些FFMPEG的结构、函数并不会做过多说明,请自行了解,重点放在了桌面录制的整体流程。

参考资料:

ffmpeg 源代码简单分析

初始化FFMPEG

av_register_all();
avdevice_register_all();

准备屏幕参数,包含了帧率、录制区域的起始坐标、大小、是否绘制鼠标等参数。

char buff_video_size[50] = { 0 };
sprintf_s(buff_video_size, 50, "%dx%d", rect.right - rect.left, rect.bottom - rect.top);

AVDictionary *options = NULL;
av_dict_set_int(&options, "framerate", fps, AV_DICT_MATCH_CASE);
av_dict_set_int(&options, "offset_x", rect.left, AV_DICT_MATCH_CASE);
av_dict_set_int(&options, "offset_y", rect.top, AV_DICT_MATCH_CASE);
av_dict_set(&options, "video_size", buff_video_size, AV_DICT_MATCH_CASE);
av_dict_set_int(&options, "draw_mouse", 1, AV_DICT_MATCH_CASE);

创建一个AVformatContext句柄,这个结构了不得,将会贯穿整个录屏软件的所有模块,描述了众多音视频信息。

AVFormatContext *_fmt_ctx = avformat_alloc_context();

获取gdigrab

AVInputFormat *_input_fmt = av_find_input_format("gdigrab");

打开gidgrab,这时候就要把准备好的捕获区域等配置信息一同传入api

avformat_open_input(&_fmt_ctx, "desktop", _input_fmt, &options);

获取桌面流信息和索引

avformat_find_stream_info(_fmt_ctx, NULL);
int stream_index = -1;
for (int i = 0; i < _fmt_ctx->nb_streams; i++) {
    if (_fmt_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
		stream_index = i;
		break;
	}
}

请务必保存上面获取的索引,他将用于后面的捕获线程。

为gidgrab创建对应的解码器,这一点在后续的声音录制中也很重要,可以通过解码器获取数据的基本信息,如数据格式、采样率等等。

AVCodecContext *_codec_ctx = _fmt_ctx->streams[stream_index]->codec;
AVCodec *_codec = avcodec_find_decoder(_codec_ctx->codec_id);

查找到对应的解码器后,打开或初始化解码器。

avcodec_open2(_codec_ctx, _codec, NULL);

至此我们的初始化工作已经完成,这其中的API调用请务必判断所有的返回值,并进行相应的错误处理。最后,在初始化函数中进行最后一步,释放存放配置信息的字典。

av_dict_free(&options);

接下来就是我们的第一个录制线程了,请以喜欢或者习惯的方式启动一个线程。

为捕获出来的数据初始化两个结构体,AVFrame和AVPacket,这两个结构体也将在各种捕获、压缩、转码过程中出现,最好能读一下结构体介绍。

AVPacket *packet = (AVPacket*)av_malloc(sizeof(AVPacket));
AVFrame *frame_rgb = av_frame_alloc();

随后就是一个while循环进行屏幕数据的捕获以及解码。注意av_read_frame函数将会在某些情况下阻塞,例如读取网络流时,在本例中他将尽可能的按照我们所设定的帧率返回桌面图像数据。

int got_pic = 0;
while (_running == true) {
    ret = av_read_frame(_fmt_ctx, packet);

    if (ret < 0) {
        al_fatal("read frame failed:%d", ret);
        break;
    }

    if (packet->stream_index == _stream_index) {
      ret = avcodec_decode_video2(_codec_ctx, frame_rgb, &got_pic, packet);
      if (ret < 0) {
        if (_on_error) _on_error(AE_FFMPEG_DECODE_FRAME_FAILED);
        al_fatal("decode desktop frame failed");
        break;
      }

      if (got_pic) {
        //do something here with frame_rgba
      }
    }

    av_free_packet(packet);
}

av_free(frame_rgb);

以上就是通过ffmpeg进行gdi抓屏的全部过程了。下一篇将对桌面数据压缩进行介绍。

 

CSDN源码下载

GitHub持续更新地址

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
使用Qt和FFmpeg开发一个简易录屏软件是可行的。你可以通过调用FFmpeg的命令行来进行屏幕录制。具体的命令行如下所示: ``` ffmpeg -f gdigrab -i desktop -framerate 60 -offset_x 0 -offset_y 0 -video_size 1600x900 -pix_fmt yuv420p -vcodec libx264 -crf 18 D:/out1.mp4 ``` 其中,`-f gdigrab` 表示使用gdigrab来抓取屏幕,`-i desktop` 表示抓取整个桌面, `-framerate 60` 表示设置帧率为60,`-offset_x 0` 和 `-offset_y 0` 表示设置抓取的起始位置为(0, 0),`-video_size 1600x900` 表示设置录制视频的分辨率为1600x900, `-pix_fmt yuv420p` 表示设置像素格式为yuv420p,`-vcodec libx264` 表示使用libx264作为视频编码器,`-crf 18` 表示设置视频质量为18,`D:/out1.mp4`表示保存的视频文件路径和文件名。 在开发过程中,你也可以使用FFmpeg的API来实现录屏功能。你可以参考一个简易录屏软件的Demo,通过使用FFmpeg的软解码功能实现录制视频图像,不过需要注意的是该Demo只录制视频图像,没有引入音频等信息。 最后,为了方便学习,你也可以使用FFmpeg自带的sws_scale()函数进行图像格式转换,不过也可以考虑使用性能更强的libyuv库。 <span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [Qt调用ffmpeg录制屏幕](https://blog.csdn.net/yao_hou/article/details/125294832)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [Qt-FFmpeg开发-实现录屏功能(10)](https://blog.csdn.net/qq_43627907/article/details/129152776)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值