1, overview of the simplest ffmpeg-based Avdevice example (screen recording + sound capture), video using MPEG4 encoding, audio using AAC encoding, and generate MP4 files, which FIFO is the key to this program, this program is just a demo a lot of optimizations are not done, for reference only.
2. Code
/** * Simplest ffmpeg-based Avdevice example (screen recording + sound capture), video with MPEG4 encoding, audio using AAC encoding, and generating MP4 file * Miu MK *[email protected] */#include " StdAfx.h "#ifdef__cplusplusextern" C "{#endif # include" libavcodec/avcodec.h "#include" libavformat/avformat.h "# Include "Libswscale/swscale.h" #include "libavdevice/avdevice.h" #include "libavutil/audio_fifo.h" #pragma comment ( LIB, "Avcodec.lib") #pragma comment (lib, "Avformat.lib") #pragma comment (lib, "Avutil.lib") #pragma comment (lib, " Avdevice.lib ") #pragma comment (lib," Avfilter.lib ")//#pragma comment (lib," Avfilter.lib ")//#pragma comment (lib," Postproc.lib ")//#pragma comment (lib," Swresample.lib ") #pragma comment (lib," Swscale.lib ") #ifdef __cplusplus};# Endifavformatcontext*pformatctx_video = null, *pformatctx_audio = NULL, *pformatctx_out = NULL; Avcodeccontext*pcodecctx_video; Avcodec*pcodec_video; Avfifobuffer*fifo_video = NULL; Avaudiofifo*fifo_audio = Null;int Videoindex, audioindex; critical_section audiosection, videosection; Swscontext *img_convert_ctx;int frame_size = 0;uint8_T *picture_buf = NULL, *frame_buf = Null;bool BCap = True;dword WINAPI screencapthreadproc (lpvoid lpparam);D word WINAPI Audiocapthreadproc (LPVOID lpparam); int openvideocapture () {Avinputformat *ifmt=av_find_input_format ("Gdigrab");// Here you can add parameters to open, for example, you can specify the acquisition frame rate avdictionary *options = Null;av_dict_set (&options, "framerate", "All", NULL);//av_dict_set ( &options, "offset_x", "0",//the distance from the top edge of the the screen or Desktop//av_dict_set (&options, " Offset_y "," Max ", 0);//video frame size. The default is to capture the full Screenav_dict_set (&options, "Video_size", "", 0); if (Avformat_open_input ( &pformatctx_video, "desktop", Ifmt, &options)!=0) {printf ("couldn ' t open input stream. (Unable to turn on video input streams) \ n"); return- 1;} if (Avformat_find_stream_info (pformatctx_video,null) <0) {printf ("couldn ' t find stream information. (Unable to get video stream information) \ n" ); return-1;} if (pformatctx_video->streams[0]->codec->codec_type! = avmedia_type_video) {printf ("couldn ' t find Video Stream information. (CannotGet video stream information) \ n "); return-1;} Pcodecctx_video = Pformatctx_video->streams[0]->codec;pcodec_video = Avcodec_find_decoder (pCodecCtx_Video- >CODEC_ID); if (Pcodec_video = = NULL) {printf ("Codec not found. (no decoder found) \ n"); return-1;} if (Avcodec_open2 (Pcodecctx_video, Pcodec_video, NULL) < 0) {printf ("Could not open codec. (Unable to turn on decoder) \ n"); return-1;} Img_convert_ctx = Sws_getcontext (Pcodecctx_video->width, Pcodecctx_video->height, PCodecCtx_Video->pix_ FMT, Pcodecctx_video->width, Pcodecctx_video->height, pix_fmt_yuv420p, sws_bicubic, NULL, NULL, and NULL); Frame_size = Avpicture_get_size (pcodecctx_video->pix_fmt, Pcodecctx_video->width, PCodecCtx_Video->height );//Apply 30 Frame Cache Fifo_video = Av_fifo_alloc (* avpicture_get_size (av_pix_fmt_yuv420p, Pcodecctx_video->width, Pcodecctx_video->height)); return 0;} Static char *dup_wchar_to_utf8 (wchar_t *w) {char *s = null;int L = WideCharToMultiByte (Cp_utf8, 0, W,-1, 0, 0, 0, 0); s = ( char *) Av_malloc (L), if (s) widechartomultibyte (Cp_utf8, 0, W,-1, S, l, 0, 0); return s;} int Openaudiocapture () {//Lookup input mode Avinputformat *paudioinputfmt = Av_find_input_format ("DShow");//Open the device in direct show mode, and associates the input method to the format context char * Psdevname = Dup_wchar_to_utf8 (L "audio= microphone (Realtek high Definition Au); if (Avformat_open_input (&A Mp;pformatctx_audio, Psdevname, Paudioinputfmt,null) < 0) {printf ("couldn ' t open input stream. (Unable to turn on audio input streams) \ n"); return-1;} if (Avformat_find_stream_info (pformatctx_audio,null) <0) return-1; if (pformatctx_audio->streams[0]->codec->codec_type! = Avmedia_type_audio) {printf ("couldn ' t find video Stream information (unable to get audio stream information) \ n "); return-1;} Avcodec *tmpcodec = Avcodec_find_decoder (pformatctx_audio->streams[0]->codec->codec_id); if (0 > Avcodec_ Open2 (Pformatctx_audio->streams[0]->codec, Tmpcodec, NULL)) {printf ("Can not find or open Audio decoder!\n");} return 0;} int Openoutput () {Avstream *pvideostream = NULL, *paudiostream = null;const char *outfilename = "Test.mp4"; avformat_alloc_ OUTPUT_CONTEXT2 (&p formatctx_out, NULL, NULL, outfilename); if (Pformatctx_video->streams[0]->codec->codec_type = = AVMEDIA_ Type_video) {Avcodeccontext *videocodecctx; Videoindex = 0;pvideostream = Avformat_new_stream (Pformatctx_out, NULL), if (!pvideostream) {printf ("can not new stream For output!\n "); return-1;} Set Codec Context Parampvideostream->codec->codec = Avcodec_find_encoder (AV_CODEC_ID_MPEG4);p videostream- >codec->height = Pformatctx_video->streams[0]->codec->height;pvideostream->codec->width = Pformatctx_video->streams[0]->codec->width;pvideostream->codec->time_base = pFormatCtx_Video-> Streams[0]->codec->time_base;pvideostream->codec->sample_aspect_ratio = PFormatCtx_Video->streams [0]->codec->sample_aspect_ratio;//take first format from List of supported formatspvideostream->codec-> PIX_FMT = Pformatctx_out->streams[videoindex]->codec->codec->pix_fmts[0];//open Encoderif (! Pvideostream->codec->codec) {printf ("Can not find the encoder!\n"); return-1;} if (Pformatctx_out->oformat->flags & Avfmt_globalheader) pvideostream->codec->flags |= CODEC_FLAG_ Global_header;if ((Avcodec_open2 (Pvideostream->codec, Pvideostream->codec->codec, NULL)) < 0) {printf (" Can not open the encoder\n "); return-1;}} if (Pformatctx_audio->streams[0]->codec->codec_type = = Avmedia_type_audio) {Avcodeccontext * Poutputcodecctx; Audioindex = 1;paudiostream = Avformat_new_stream (pformatctx_out, NULL);p Audiostream->codec->codec = avcodec_ Find_encoder (pformatctx_out->oformat->audio_codec);p outputcodecctx = paudiostream->codec; Poutputcodecctx->sample_rate = pformatctx_audio->streams[0]->codec->sample_rate;poutputcodecctx-> Channel_layout = Pformatctx_out->streams[0]->codec->channel_layout;poutputcodecctx->channels = av_get_ Channel_layout_nb_channels (paudiostream->codec->channel_layout); if (poutputcodecctx->channel_layout = = 0 ) {PoutputcodecCtx->channel_layout = Av_ch_layout_stereo;poutputcodecctx->channels = Av_get_channel_layout_nb_channels ( Poutputcodecctx->channel_layout);} POUTPUTCODECCTX->SAMPLE_FMT = paudiostream->codec->codec->sample_fmts[0]; Avrational time_base={1, paudiostream->codec->sample_rate};p audiostream->time_base = time_base;// audiocodecctx->time_base = Time_base;poutputcodecctx->codec_tag = 0; if (Pformatctx_out->oformat->flags & Avfmt_globalheader) poutputcodecctx->flags |= CODEC_FLAG_GLOBAL_ Header;if (Avcodec_open2 (poutputcodecctx, Poutputcodecctx->codec, 0) < 0) {//Encoder open failed, exit program return-1;}} if (! ( Pformatctx_out->oformat->flags & Avfmt_nofile) {if (Avio_open (&PFORMATCTX_OUT->PB, OutFileName, Avio_flag_write) < 0) {printf ("Can not open output file handle!\n"); return-1;}} if (Avformat_write_header (Pformatctx_out, NULL) < 0) {printf ("Can not write the header of the output file!\n"); return-1; }return 0;} int _tmain (int argc, _tchar* argV[]) {av_register_all (); Avdevice_register_all (); if (Openvideocapture () < 0) {return-1;} if (openaudiocapture () < 0) {return-1;} if (Openoutput () < 0) {return-1;} InitializeCriticalSection (&videosection); initializecriticalsection (&audiosection); Avframe *picture = Av_frame_alloc (); int size = Avpicture_get_size (pformatctx_out->streams[videoindex]->codec- >PIX_FMT, Pformatctx_out->streams[videoindex]->codec->width, pformatctx_out->streams[videoindex]- >codec->height);p icture_buf = new Uint8_t[size];avpicture_fill ((Avpicture *) picture, picture_buf, pFormatCtx_ OUT->STREAMS[VIDEOINDEX]->CODEC->PIX_FMT, Pformatctx_out->streams[videoindex]->codec->width, pformatctx_out->streams[videoindex]->codec->height);//star cap Screen threadcreatethread (NULL, 0, Screencapthreadproc, 0, 0, null);//star cap Audio Threadcreatethread (NULL, 0, audiocapthreadproc, 0, 0, null); int64_t cur _pts_v=0,cur_pts_a=0;int videoframeindex = 0, Audioframeindex = 0;while (1) {if (_kbhit () = 0 && bCap) {bCap = false; Sleep (2000);//simply use sleep to wait for the capture thread to close}if (Fifo_audio && fifo_video) {int sizeaudio = av_audio_fifo_size (Fifo_audio) ; int sizevideo = Av_fifo_size (Fifo_video);//end loop If cache data is finished (Av_audio_fifo_size (fifo_audio) <= pformatctx_out-> Streams[audioindex]->codec->frame_size && av_fifo_size (fifo_video) <= frame_size &&!bCap) { Break;}} if (Av_compare_ts (Cur_pts_v, Pformatctx_out->streams[videoindex]->time_base, cur_pts_a,pformatctx_out-> Streams[audioindex]->time_base) <= 0) {//read data from fifoif (Av_fifo_size (Fifo_video) < Frame_size & &!bcap) {cur_pts_v = 0x7fffffffffffffff;} if (Av_fifo_size (fifo_video) >= size) {entercriticalsection (&videosection); Av_fifo_generic_read (Fifo_video, Picture_buf, size, NULL); LeaveCriticalSection (&videosection); Avpicture_fill (avpicture *) picture, picture_buf, pformatctx_out-> STREAMS[VIDEOINDEX]->CODEC->PIX_FMT, Pformatctx_out->stReams[videoindex]->codec->width, pformatctx_out->streams[videoindex]->codec->height);//pts = n * (1 /timbase)/fps);p icture->pts = Videoframeindex * ((pformatctx_video->streams[0]->time_base.den/pformatctx_ video->streams[0]->time_base.num), int got_picture = 0; Avpacket Pkt;av_init_packet (&pkt);p kt.data = Null;pkt.size = 0;int ret = Avcodec_encode_video2 (pFormatCtx_Out-> Streams[videoindex]->codec, &pkt, picture, &got_picture); if (Ret < 0) {//Encode error, ignore this frame continue;} if (got_picture==1) {pkt.stream_index = Videoindex;pkt.pts = Av_rescale_q_rnd (pkt.pts, pformatctx_video->streams[0 ]->time_base, Pformatctx_out->streams[videoindex]->time_base, (avrounding) (AV_ROUND_NEAR_INF| Av_round_pass_minmax)); Pkt.dts = Av_rescale_q_rnd (Pkt.dts, Pformatctx_video->streams[0]->time_base, pFormatCtx_Out->streams[ Videoindex]->time_base, (avrounding) (av_round_near_inf| Av_round_pass_minmax)); Pkt.duration = ((pformatctx_out->strEams[0]->time_base.den/pformatctx_out->streams[0]->time_base.num)/Cur_pts_v = Pkt.pts;ret = av_ Interleaved_write_frame (Pformatctx_out, &PKT);//delete[] Pkt.data;av_free_packet (&PKT);} videoframeindex++;}} Else{if (NULL = = Fifo_audio) {continue;//not yet initialized fifo}if (av_audio_fifo_size (Fifo_audio) < Pformatctx_out->streams [Audioindex]->codec->frame_size &&!bcap] {cur_pts_a = 0X7FFFFFFFFFFFFFFF;} if (Av_audio_fifo_size (Fifo_audio) >= (pformatctx_out->streams[audioindex]->codec->frame_size > 0?) pformatctx_out->streams[audioindex]->codec->frame_size:1024)) {Avframe *frame;frame = Av_frame_alloc (); Frame->nb_samples = pformatctx_out->streams[audioindex]->codec->frame_size>0? Pformatctx_out->streams[audioindex]->codec->frame_size:1024;frame->channel_layout = pFormatCtx_Out- >streams[audioindex]->codec->channel_layout;frame->format = pformatctx_out->streams[audioindex]- >codec->sample_fmt; frame->sample_rate = Pformatctx_out->streams[audioindex]->codec->sample_rate;av_frame_get_buffer ( frame, 0); EnterCriticalSection (&audiosection); Av_audio_fifo_read (Fifo_audio, (void * *) Frame->data, (pFormatCtx_Out- >streams[audioindex]->codec->frame_size > 0? pformatctx_out->streams[audioindex]->codec->frame_size:1024)); LeaveCriticalSection (&audiosection); if (pformatctx_out->streams[0]->codec->sample_fmt! = PFormatCtx_ audio->streams[audioindex]->codec->sample_fmt | | Pformatctx_out->streams[0]->codec->channels! = pformatctx_audio->streams[audioindex]->codec-> Channels | | Pformatctx_out->streams[0]->codec->sample_rate! = pformatctx_audio->streams[audioindex]->codec- >sample_rate) {//if the input and output audio formats do not need to be resampled, here is the same as not done}avpacket Pkt_out;av_init_packet (&pkt_out); int got_picture = -1;pkt_out.data = Null;pkt_out.size = 0;frame->pts = Audioframeindex * pformatctx_out->streams[audioindex]->cOdec->frame_size;if (Avcodec_encode_audio2 (Pformatctx_out->streams[audioindex]->codec, &pkt_out, Frame, &got_picture) < 0) {printf ("Can not decoder a frame");} Av_frame_free (&frame); if (got_picture) {pkt_out.stream_index = Audioindex;pkt_out.pts = AudioFrameIndex * Pformatctx_out->streams[audioindex]->codec->frame_size;pkt_out.dts = AudioFrameIndex * pFormatCtx_Out- >streams[audioindex]->codec->frame_size;pkt_out.duration = pformatctx_out->streams[audioindex]-> Codec->frame_size;cur_pts_a = pkt_out.pts;int ret = av_interleaved_write_frame (pformatctx_out, &pkt_out); av_ Free_packet (&pkt_out);} audioframeindex++;}}} Av_write_trailer (pformatctx_out); Avio_close (PFORMATCTX_OUT->PB); Avformat_free_context (PFormatCtx_Out); if ( Pformatctx_video! = null) {Avformat_free_context (pformatctx_video);p formatctx_video = null;} if (Pformatctx_audio! = null) {Avformat_free_context (pformatctx_audio);p formatctx_audio = null;} return 0;} DWORD WINAPI ScreenCapThreadProc (LPVOID lpparam) {avpacket *packet = (Avpacket *) av_malloc (sizeof (avpacket)); int got_picture; Avframe*pframe;pframe=avcodec_alloc_frame (); Avframe *picture = Avcodec_alloc_frame (); int size = Avpicture_get_size (pformatctx_out->streams[videoindex]-> CODEC->PIX_FMT, Pformatctx_out->streams[videoindex]->codec->width, pFormatCtx_Out->streams[ videoindex]->codec->height);p icture_buf = new Uint8_t[size];avpicture_fill ((Avpicture *) picture, PICTURE_BUF, PFORMATCTX_OUT->STREAMS[VIDEOINDEX]->CODEC->PIX_FMT, pformatctx_out->streams[videoindex]->codec- >width, Pformatctx_out->streams[videoindex]->codec->height); FILE *p = Null;p = fopen ("Proc_test.yuv", "wb+"); int height = pformatctx_out->streams[videoindex]->codec-> Height;int width = pformatctx_out->streams[videoindex]->codec->width;int y_size=height*width;while (bCap) { if (Av_read_frame (pformatctx_video, packet) < 0) {continue;} if (Packet->stream_index = = 0) {if (avcodEc_decode_video2 (Pcodecctx_video, Pframe, &got_picture, packet) < 0) {printf ("Decode error. (decoding errors) \ n"); continue ;} if (got_picture) {Sws_scale (Img_convert_ctx, (const uint8_t* const*) Pframe->data, pframe->linesize, 0, Pformatctx_out->streams[videoindex]->codec->height, Picture->data, picture->linesize); if (av_fifo_ Space (Fifo_video) >= size) {entercriticalsection (&videosection); Av_fifo_generic_write (Fifo_video, picture- >data[0], y_size, null); Av_fifo_generic_write (Fifo_video, picture->data[1], Y_SIZE/4, NULL); av_fifo_generic_ Write (Fifo_video, picture->data[2], Y_SIZE/4, NULL); LeaveCriticalSection (&videosection);}}} Av_frame_free (&pframe); Av_frame_free (&picture);d elete[] Picture_buf;return 0;} DWORD WINAPI Audiocapthreadproc (lpvoid lpparam) {Avpacket pkt; Avframe *frame;frame = Av_frame_alloc (); int Gotframe;while (BCAP) {if (Av_read_frame (PFORMATCTX_AUDIO,&PKT) < 0) {continue;} if (Avcodec_decode_audio4 (PFORMATCTX_AUDIO->STREAMS[0]->codec, Frame, &gotframe, &PKT) < 0) {Av_frame_free (&frame);p rintf ("Can not decoder a frame"); Av_free_packet (&PKT); if (!gotframe) {continue;//did not get to data, continue next}if (NULL = = Fifo_audio) {Fifo_audio = Av_audio_fifo_ Alloc (PFORMATCTX_AUDIO->STREAMS[0]->CODEC->SAMPLE_FMT, pformatctx_audio->streams[0]->codec-> Channels, * frame->nb_samples);} int buf_space = Av_audio_fifo_space (Fifo_audio), if (Av_audio_fifo_space (fifo_audio) >= frame->nb_samples) { EnterCriticalSection (&audiosection); Av_audio_fifo_write (Fifo_audio, (void * *) Frame->data, frame->nb_ samples); LeaveCriticalSection (&audiosection);}} Av_frame_free (&frame); return 0;}3. Project Address http://download.csdn.net/detail/dancing_night/8855409
Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.
FFmpeg Realization Recording screen + record