ffmpeg实现屏幕录制

 

1. gdigrab

gdigrab是FFmpeg专门用于抓取Windows桌面的设备。非常适合用于屏幕录制。它通过不同的输入URL支持两种方式的抓取:
(1)“desktop”:抓取整张桌面。或者抓取桌面中的一个特定的区域。
(2)“title={窗口名称}”:抓取屏幕中特定的一个窗口(目前中文窗口还有乱码问题)。
gdigrab另外还支持一些参数,用于设定抓屏的位置:
offset_x:抓屏起始点横坐标。
offset_y:抓屏起始点纵坐标。
video_size:抓屏的大小。
framerate:抓屏的帧率。
参考的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//Use gdigrab    
     AVDictionary* options = NULL;
     //Set some options
     //grabbing frame rate
     //av_dict_set(&options,"framerate","5",0);
     //The distance from the left edge of the screen or desktop
     //av_dict_set(&options,"offset_x","20",0);
     //The distance from the top edge of the screen or desktop
     //av_dict_set(&options,"offset_y","40",0);
     //Video frame size. The default is to capture the full screen
     //av_dict_set(&options,"video_size","640x480",0);
     AVInputFormat *ifmt=av_find_input_format( "gdigrab" );
     if (avformat_open_input(&pFormatCtx, "desktop" ,ifmt,&options)!=0){
         printf ("Couldn't open input stream.
");
         return  -1;
     }

//下面的代码默认设置为====================屏幕大小

#include <stdio.h>
 
extern "C"
{
    #include "libavcodec/avcodec.h"
    #include "libavformat/avformat.h"
    #include "libswscale/swscale.h"
    #include "libavdevice/avdevice.h"
}
 
//'1' Use Dshow
//'0' Use VFW
#define USE_DSHOW 0
 
 
//Show Dshow Device
void show_dshow_device()
{
    AVFormatContext *pFormatCtx = avformat_alloc_context();
    AVDictionary* options = NULL;
    av_dict_set(&options,"list_devices","true",0);
    AVInputFormat *iformat = av_find_input_format("dshow");
    printf("========Device Info=============\n");
    avformat_open_input(&pFormatCtx,"video=dummy",iformat,&options);
    printf("================================\n");
}
 
//Show Dshow Device Option
void show_dshow_device_option()
{
    AVFormatContext *pFormatCtx = avformat_alloc_context();
    AVDictionary* options = NULL;
    av_dict_set(&options,"list_options","true",0);
    AVInputFormat *iformat = av_find_input_format("dshow");
    printf("========Device Option Info======\n");
    avformat_open_input(&pFormatCtx,"video=Integrated Camera",iformat,&options);
    printf("================================\n");
}
 
//Show VFW Device
void show_vfw_device()
{
    AVFormatContext *pFormatCtx = avformat_alloc_context();
    AVInputFormat *iformat = av_find_input_format("vfwcap");
    printf("========VFW Device Info======\n");
    avformat_open_input(&pFormatCtx,"list",iformat,NULL);
    printf("=============================\n");
}
 
//Show AVFoundation Device
void show_avfoundation_device()
{
    AVFormatContext *pFormatCtx = avformat_alloc_context();
    AVDictionary* options = NULL;
    av_dict_set(&options,"list_devices","true",0);
    AVInputFormat *iformat = av_find_input_format("avfoundation");
    printf("==AVFoundation Device Info===\n");
    avformat_open_input(&pFormatCtx,"",iformat,&options);
    printf("=============================\n");
}
 
#define USE_DSHOW 1
int main(int argc, char* argv[])
{
 
    AVFormatContext	*pFormatCtx;
    int				i, videoindex;
    AVCodecContext	*pCodecCtx;
    AVCodec			*pCodec;
 
    av_register_all();
    avformat_network_init();
    avdevice_register_all();//Register Device
    pFormatCtx = avformat_alloc_context();
 
    //抓取屏幕
    AVInputFormat *ifmt=av_find_input_format("gdigrab");
    if(avformat_open_input(&pFormatCtx,"desktop",ifmt,NULL)!=0){
            printf("Couldn't open input stream. ");
            return -1;
        }
 
    if(avformat_find_stream_info(pFormatCtx,NULL)<0)
    {
        printf("Couldn't find stream information.\n");
        return -1;
    }
 
    videoindex=-1;
        for(i=0; i<pFormatCtx->nb_streams; i++)
        {
            if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO)
            {
                videoindex=i;
            }
        }
        if(videoindex==-1)
        {
            printf("Couldn't find a video stream.\n");
            return -1;
        }
        pCodecCtx=pFormatCtx->streams[videoindex]->codec;
        pCodec=avcodec_find_decoder(pCodecCtx->codec_id);
        if(pCodec==NULL)
        {
            printf("Codec not found.\n");
            return -1;
        }
        if(avcodec_open2(pCodecCtx, pCodec,NULL)<0)
        {
            printf("Could not open codec.\n");
            return -1;
        }
        AVFrame	*pFrame,*pFrameYUV;
        pFrame=av_frame_alloc();
        pFrameYUV=av_frame_alloc();
        uint8_t *out_buffer=(uint8_t *)av_malloc(avpicture_get_size(PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height));
        avpicture_fill((AVPicture *)pFrameYUV, out_buffer, PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height);
        int ret, got_picture;
        AVPacket *packet=(AVPacket *)av_malloc(sizeof(AVPacket));
        FILE *fp_yuv=fopen("output.yuv","wb");
        struct SwsContext *img_convert_ctx;
        img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);
        ///这里打印出视频的宽高
        fprintf(stderr,"w= %d h= %d\n",pCodecCtx->width, pCodecCtx->height);
        ///我们就读取100张图像
        for(int i=0;i<100;i++)
        {
            if(av_read_frame(pFormatCtx, packet) < 0)
            {
                break;
            }
            if(packet->stream_index==videoindex)
            {
                ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, packet);
                if(ret < 0){
                    printf("Decode Error.\n");
                    return -1;
                }
                if(got_picture)
                {
                    sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameYUV->data, pFrameYUV->linesize);
                    int y_size=pCodecCtx->width*pCodecCtx->height;
                    fwrite(pFrameYUV->data[0],1,y_size,fp_yuv);    //Y
                    fwrite(pFrameYUV->data[1],1,y_size/4,fp_yuv);  //U
                    fwrite(pFrameYUV->data[2],1,y_size/4,fp_yuv);  //V
                }
            }
            av_free_packet(packet);
        }
        sws_freeContext(img_convert_ctx);
 
        fclose(fp_yuv);
        av_free(out_buffer);
        av_free(pFrameYUV);
        avcodec_close(pCodecCtx);
        avformat_close_input(&pFormatCtx);
        return 0;
 
}
 
 
 
 

 
 
 

                
  • 4
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值