The simplest FFMPEG-based avdevice example (screen recording)

Source: Internet
Author: User
?? FFmpeg has a class library that interacts with multimedia devices: libavdevice. You can use this library to read data from multimedia devices on your computer or output data to a specified multimedia device.

We plan to write two examples of libavdevice class libraries related to FFMPEG. The previous article documented an example of using the libavdevice class library based on FFMPEG to read camera data. This article records an example of recording screen of libavdevice class library based on FFMPEG. In this article, the program records the current desktop content and decodes it to display it. The code for decoding and display is not described in this article. For details, refer to the article:
100-line code implementation of the simplest Video Player (sdl1.x) based on FFMPEG + SDL

Screen capture method

The previous article records how to use libavdevice. In Windows, you can use libavdevice to capture screen data in two ways: gdigrab and dshow. The following sections describe each other.
1. gdigrab
Gdigrab is a FFMPEG device used to capture Windows desktops. It is ideal for screen recording. It supports two methods of capturing through different input urls:
(1) "desktop": captures the entire desktop. Or capture a specific area on the desktop.
(2) "Title = {window name}": captures a specific window on the screen (currently, Chinese Windows still have garbled characters ).
Gdigrab also supports some parameters to set the position of the screen capture:
Offset_x: the abscissa of the starting point of the screen capture.
Offset_y: The ordinate of the starting point of the screen capture.
Video_size: the size of the captured screen.
Framerate: Specifies the Frame Rate of the captured screen.
The reference code is as follows:

// 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_dic T_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. (The input stream cannot be opened) \ n"); Return-1 ;}

2. dshow
Screen capture software: screen-capture-recorder
Address: http://sourceforge.net/projects/screencapturer/
After installing the downloaded software, you can specify the dshow input device as "Screen-capture-recorder. The usage of dshow devices has been described in detail in the previous article. The reference code is as follows:
Avinputformat * ifmt = av_find_input_format ("dshow"); If (avformat_open_input (& pformatctx, "Video = screen-capture-recorder", ifmt, null )! = 0) {printf ("couldn't open input stream. (The input stream cannot be opened) \ n"); Return-1 ;}

Note: The two screenshot capture methods can also be directly executed using the command line of ffmpeg.exe. For details, refer to the article:

Use FFMPEG to obtain data from the DirectShow device (camera, screen recording)

In Linux, you can use x11grab for screen capture.

Code

Paste the program code below:

/*** The simplest FFMPEG-based avdevice example (screen recording) * simplest FFMPEG device (screen capture) ** leixiao Li Lei Xiaohua * [email protected] * China Media University/Digital TV technology * Communication University of China/Digital TV technology * http://blog.csdn.net/leixiaohua1020 ** this program implements the screen recording function. You can record and play desktop data. It is the simplest example of libavdevice class library based on FFMPEG. In this example, you can learn how to use * libavdevice class library in FFMPEG. * In Windows, you can use two recording methods: * 1. gdigrab: a GDI-based screen recording device under Win32. * When capturing a desktop, enter "desktop" as the URL ". * 2. dshow: Use DirectShow. Note that you need to install additional software screen-capture-recorder * in Linux, you can use the x11grab recording screen. ** This software capture screen of computer. it's the simplest example * about usage of FFMPEG's libavdevice library. * It's suiltable for the beginner of FFMPEG. * This software support 2 methods to capture screen in Microsoft Windows: * 1. gdigrab: Win32 GDI-based screen capture device. * input URL in avformat_open_input () is "desktop ". * 2. dshow: Use DirectShow. need to install screen-capture-R Ecorder. * It use x11grab to capture screen in Linux. */# include "stdafx. H "extern" C "{# include" libavcodec/avcodec. H "# include" libavformat/avformat. H "# include" libswscale/swscale. H "# include" libavdevice/avdevice. H "// SDL # include" SDL/SDL. H "# include" SDL/sdl_thread.h "}; // output yuv420p # define output_yuv420p 0 // '1' use dshow // '0' use gdigrab # define use_dshow 0int main (INT argc, char * argv []) {avform Atcontext * pformatctx; Inti, videoindex; avcodeccontext * pcodecctx; avcodec * pcodec; av_register_all (); avformat_network_init (); pformatctx = avformat_alloc_context (); // open file // char filepath [] = "src0109480x272_22.h265"; // avformat_open_input (& pformatctx, filepath, null, null) // register deviceavdevice_register_all (); // windows # ifdef _ Win32 # If use_dshow // use dshow // need to install screen-capture-recorder // scre En-capture-recorder // Website: http://sourceforge.net/projects/screencapturer///AVInputFormat * ifmt = av_find_input_format ("dshow"); If (avformat_open_input (& pformatctx, "Video = screen-capture-recorder", ifmt, null )! = 0) {printf ("couldn't open input stream. (The input stream cannot be opened) \ n "); Return-1 ;}# else // use gdigrabavdictionary * 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 fr Ame 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. (The input stream cannot be opened) \ n "); Return-1 ;}# endif # else // linuxavdictionary * Options = NULL; // set some options // grabbing Frame Rate // av_dict_set (& options, "framerate", "5", 0 ); // make the grabbed area follow the mouse // av_dict_set (& options, "follow_mouse", "centered", 0); // video frame size. the default is to capture the full screen // av_dict_set (& options, "video_size", "640x480", 0); avinput Format * ifmt = av_find_input_format ("x11grab"); // grab at position 10, 20if (avformat_open_input (& pformatctx, ": 0.0 +", ifmt, & options )! = 0) {printf ("couldn't open input stream. (The input stream cannot be opened) \ n "); Return-1 ;}# endifif (avformat_find_stream_info (pformatctx, null) <0) {printf (" couldn't find stream information. (stream information cannot be obtained) \ 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; break;} If (videoindex =-1) {printf ("didn't find a video stream. (Video Stream not found) \ n "); return- 1;} pcodecctx = pformatctx-> streams [videoindex]-> codec; pcodec = avcodec_find_decoder (pcodecctx-> codec_id); If (pcodec = NULL) {printf ("codec not found. (decoder not found) \ n "); Return-1;} If (avcodec_open2 (pcodecctx, pcodec, null) <0) {printf (" cocould not open codec. (decoder cannot be enabled) \ n "); Return-1;} avframe * pframe, * pframeyuv; pframe = avcodec_alloc_frame (); pframeyuv = avcodec_alloc_frame (); uint8_t * out_buffer = (uint8_t *) av_malloc (avpictu Re_get_size (bytes, pcodecctx-> width, pcodecctx-> height); avpicture_fill (avpicture *) pframeyuv, out_buffer, bytes, pcodecctx-> width, pcodecctx-> height ); // SDL encode if (sdl_init (sdl_init_video | sdl_init_audio | sdl_init_timer) {printf ("cocould not initialize SDL-% s \ n", sdl_geterror (); Return-1 ;} int screen_w = 640, screen_h = 360; const sdl_videoinfo * Vi = SD Rochelle getvideoinfo (); // half of the desktop's width and height. screen_w = vi-> current_w/2; screen_h = vi-> current_h/2; sdl_surface * screen; screen = sdl_setvideomode (screen_w, screen_h, 0, 0); If (! Screen) {printf ("SDL: cocould not set video mode-exiting: % s \ n", sdl_geterror (); Return-1;} sdl_overlay * BMP; BMP = sdl_createyuvoverlay (pcodecctx-> width, pcodecctx-> height, accuracy, screen); sdl_rect rect; // SDL end destination int ret, got_picture; avpacket * packet = (avpacket *) av_malloc (sizeof (avpacket); // output information embedded printf ("File Information (File Information) --------------------- \ n"); av_dump_format (pformatctx, 0, null, 0 ); printf ("------------------------------------------------- \ n"); # If output_yuv420p file * fp_yuv = fopen ("output. YUV "," WB + "); # endif struct swscontext * img_convert_ctx; Convert = sws_getcontext (pcodecctx-> width, pcodecctx-> height, pcodecctx-> pix_fmt, pcodecctx-> width, pcodecctx-> height, pix_fmt_yuv420p, sws_bicubic, null, null); // ------------------------------ while (av_read_frame (pformatctx, packet)> = 0) {If (packet-> stream_index = videoindex) {ret = avcodec_decode_video2 (pcodecctx, pframe, & got_picture, packet); If (Ret <0) {printf ("decode error. (decoding 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); # If output_yuv420pint 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 ); // ufwrite (pframeyuv-> data [2], 1, y_size/4, fp_yuv); // v # endifsdl_lockyuvoverlay (BMP ); BMP-> pixels [0] = pframeyuv-> data [0]; BMP-> pixels [2] = pframeyuv-> data [1]; BMP-> pixels [1] = pframeyuv-> data [2]; BMP-> pitches [0] = pframeyuv-> linesize [0]; BMP-> pitches [2] = pframeyuv-> linesize [1]; BMP-> pitches [1] = pframeyuv-> linesize [2]; sdl_unlockyuvoverlay (BMP); rect. X = 0; rect. y = 0; rect. W = screen_w; rect. H = screen_h; sdl_displayyuvoverlay (BMP, & rect); // delay 40mssdl_delay (40) ;}} av_free_packet (packet);} sws_freecontext (img_convert_ctx ); # If export fclose (fp_yuv); # endif sdl_quit (); av_free (out_buffer); av_free (pframeyuv); avcodec_close (pcodecctx); avformat_close_input (& pformatctx); Return 0 ;}

The result program runs as follows. The running result is very interesting, and a screen is "nested" in another screen.
You can determine whether to output the decoded yuv420p data into a file through the macro defined in the Code:
#define OUTPUT_YUV420P 0


SourceForge project homepage:
Https://sourceforge.net/projects/simplestffmpegdevice/
Csdn project:
Http://download.csdn.net/detail/leixiaohua1020/7994049

Note:
This project contains two examples of FFMPEG-based libavdevice:
Simplest_ffmpeg_grabdesktop: screen recording.
Simplest_ffmpeg_readcamera: Read the camera.

The simplest FFMPEG-based avdevice example (screen recording)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.