The simplest example of an AVDevice Based on FFmpeg (reading a camera ),

Source: Internet
Author: User

The simplest example of an AVDevice Based on FFmpeg (reading a camera ),
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 other devices) or output data to a specified multimedia device.
Libavdevice supports the following devices as input:

Alsa
Avfoundation
Bktr
Dshow
Dv1394
Fbdev
Gdigrab
83
Jack
Lavfi
Libcdio
Libdc1394
Openal
Oss
Pulse
Qtkit
Sndio
Video4linux2, v4l2
Vfwcap
X11grab
Decklink
Libavdevice supports the following devices as the output end:
Alsa
Caca
Decklink
Fbdev
Opengl
Oss
Pulse
Sdl
Sndio
Xv


Libavdevice uses plans to record two examples of FFmpeg-based libavdevice class libraries, which are written in two articles. This article records an example of using the Libavdevice class library based on FFmpeg to read camera data. The next article records an example of recording screen of Libavdevice class library based on FFmpeg. The program in this article reads the data of the camera on the computer and decodes and displays the data. 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


This document describes the steps to use libavdevice.

First, you must include the header file when using libavdevice:
#include "libavdevice/avdevice.h"
Then, you need to register libavdevice in the program:
avdevice_register_all();

Next, you can use the libavdevice function.
Reading data using libavdevice is similar to opening a video file directly. Because the system device is also considered as an input format (AVInputFormat) by FFmpeg ). Use the following function to open a common video file using FFmpeg:
AVFormatContext *pFormatCtx = avformat_alloc_context();avformat_open_input(&pFormatCtx, "test.h265",NULL,NULL);

When using libavdevice, the only difference is that you need to first find the device used for input. Here av_find_input_format () is used to complete:
AVFormatContext *pFormatCtx = avformat_alloc_context();AVInputFormat *ifmt=av_find_input_format("vfwcap");avformat_open_input(&pFormatCtx, 0, ifmt,NULL);

The above code first specifies the vfw device as the input device, and then specify to enable the 0th devices in the URL (which is the camera Device on my own computer ).
On Windows, in addition to using a vfw device as the input device, you can also use DirectShow as the input device:
AVFormatContext *pFormatCtx = avformat_alloc_context();AVInputFormat *ifmt=av_find_input_format("dshow");avformat_open_input(&pFormatCtx,"video=Integrated Camera",ifmt,NULL) ;

You can use ffmpeg.exe to enable the vfw and Directshow devices. For more information, see:
Use FFmpeg to obtain data from the DirectShow device (camera, screen recording)

Note 1. The URL format is "video = {Device name}", but the device name cannot be enclosed by quotation marks. For example, in the preceding example, the URL is "video = Integrated Camera" and cannot be written as "video = \" Integrated Camera \ ". Otherwise, the device cannot be opened. This is very different from using ffmpeg.exe to open a dshow device (command: ffmpeg-list_options true-f dshow-I video = "Integrated Camera.
2. Dshow device names must be obtained in advance. There are two methods:

(1) implemented through FFmpeg programming. Use the following code:

//Show Devicevoid 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");}

The above code is equivalent to entering the following command:
ffmpeg -list_devices true -f dshow -i dummy  

Shows the execution result:

 

This method can be used to automatically obtain the name. However, when the device name contains Chinese characters, the device name may be garbled. If you directly enter a device name with garbled characters, the device cannot be opened. At this time, we need to convert the garbled ANSI into a UTF-8. For example, if the first audio device in the figure is displayed as "audio? (Conexant 20672 SmartAudi ", after transcoding, it is the" built-in microphone (Conexant 20672 SmartAudi ". Use the name after transcoding to open the device.


(2) view it in the system.
This method is simpler, but the disadvantage is that manual operations are required. This method uses the DirectShow debugging tool GraphEdit (or the next GraphStudioNext on the Internet) to view the input name.
Open GraphEdit and select "image-> Insert filter"
Then you can view the Simplified Chinese name of the Audio input device by viewing Audio Capture Sources. It can be seen that the microphone is "Conexant 20672 SmartAudi ".
 

On Linux, you can use video4linux2 to open a video device.


Directly paste the program code below the Code:
/*** The Simplest FFmpeg-based AVDevice example (Read Camera) * Simplest FFmpeg Device (Read Camera) ** leixiao Li Lei Xiaohua * leixiaohua1020@126.com * China Communications University/Digital TV Technology * Communication University of China/Digital TV Technology * http://blog.csdn.net/leixiaohua1020 ** this program realizes the local camera data acquisition and Decoding and display. 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, this program can read camera data in two ways: * 1.VFW: Video for Windows screen capture devices. Note that the entered URL is the serial number of the device, * from 0 to 9.*2. dshow: Use Directshow. Note that the name of the Camera device on the author's machine is * "Integrated Camera". You must change it to the name set by the Camera * on your computer. * In Linux, you can use video4linux2 to read the camera device. ** This software read data from Computer's Camera and play it. * 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 read camera in Microsoft Windows: * 1. gdigrab: VfW (Video for Windows) capture input device. * The filename passed as input is the capture driver number, * ranging from 0 to 9.*2. Dshow: Use Directshow. camera's name in author's computer is * "Integrated Camera ". * It use video4linux2 to read Camera 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 Ds How // '0' Use VFW # define USE_DSHOW 0 // Show Devicevoid 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 Device Optionvoid 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 Dev Icevoid 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");} int main (int argc, char * argv []) {AVFormatContext * pFormatCtx; inti, videoindex; AVCodecContext * pCodecCtx; AVCodec * pCodec; av_register_all (); avform At_network_init (); pFormatCtx = avformat_alloc_context (); // Open File // char filepath [] = "src0109480x272_22.h265"; // avformat_open_input (& pFormatCtx, filepath, NULL, NULL) // Register Deviceavdevice_register_all (); // Show Dshow Deviceshow_dshow_device (); // Show Device failed (); // Show VFW Optionsshow_vfw_device (); // Windows # ifdef _ WIN32 # if USE_DSHOWAVInputFormat * ifmt = av_find_input_forma T ("dshow"); // Set own video device's nameif (avformat_open_input (& pFormatCtx, "video = Integrated Camera", ifmt, NULL )! = 0) {printf ("Couldn't open input stream. (The input stream cannot be opened) \ n "); return-1 ;}# elseAVInputFormat * ifmt = av_find_input_format (" vfwcap "); if (avformat_open_input (& pFormatCtx," 0 ", ifmt, NULL )! = 0) {printf ("Couldn't open input stream. (The input stream cannot be opened) \ n "); return-1 ;}# endif # endif // Linux # ifdef linuxAVInputFormat * ifmt = av_find_input_format (" video4linux2 "); if (avformat_open_input (& pFormatCtx, "/dev/video0", ifmt, NULL )! = 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 ("Couldn'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 (avpic Ture_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 = 0, screen_h = 0; SDL_Surface * screen; screen_w = PCodecCtx-> width; screen_h = pCodecCtx-> height; 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 ;}



Result

The Running Effect of the program is as follows. Output the camera data.


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.




Related Article

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.