FFmpeg pour démarrer avec Visual Studio

Salut Pour commencer, je développe un programme pour déterminer les numéros de voiture sur un processeur basse consommation bon marché comme Intel ATOM Z8350. Nous avons obtenu de trÚs bons résultats dans la détermination des nombres russes dans une image statique (jusqu'à 97%) avec de bonnes performances sans l'utilisation de réseaux de neurones. La seule chose qui reste est petite - travaillez avec la caméra IP Fig.1.

image
Figure 1 Ordinateur Intel ATOM Z83II et caméra IP ATIS

FFmpeg est une bibliothĂšque pour crĂ©er des applications vidĂ©o ou mĂȘme des utilitaires Ă  usage gĂ©nĂ©ral qui prend tout le travail de traitement vidĂ©o, en faisant tout le dĂ©codage, l'encodage, le multiplexage et le dĂ©multiplexage pour vous.

Tùche : la caméra IP Full HD en standard h.264 transmet le flux RTSP. La taille d'image décompressée est de 1920x1080 pixels, la fréquence est de 25 images par seconde. Il est nécessaire de recevoir des trames décodées en RAM et d'enregistrer toutes les 25 trames sur le disque.

Dans cet exemple, nous allons décoder les images par programmation. L'objectif est d'apprendre à utiliser FFmpeg et de comparer davantage les résultats obtenus à l'aide du décodage matériel. Vous verrez FFmpeg - c'est facile!

Installer FFmpeg : beaucoup de gens suggÚrent de construire FFmpeg pour leur matériel. Je suggÚre d'utiliser des builds zeranoe , ce qui simplifie considérablement la tùche. Il est trÚs important que les assemblages zeranoe incluent la prise en charge de DXVA2, qui nous sera utile plus tard pour le décodage matériel.

Nous allons sur le site https://ffmpeg.zeranoe.com/builds/ et tĂ©lĂ©chargeons 2 archives partagĂ©es et dev avant de choisir 32 ou 64 bits. L'archive de dĂ©veloppement stocke les bibliothĂšques (.lib) et inclut. L'archive partagĂ©e contient les .dll nĂ©cessaires qui devront ĂȘtre réécrits dans un dossier avec votre futur programme.

Créez donc le dossier ffmpeg sur le lecteur C: \. Nous allons réécrire les fichiers de l'archive de développement dedans.

Connexion de FFmpeg Ă  Visual Studio 2017: crĂ©ation d'un nouveau projet. AccĂ©dez aux propriĂ©tĂ©s du projet (Projet - propriĂ©tĂ©s). Ensuite, C / C ++ et sĂ©lectionnez "RĂ©pertoires supplĂ©mentaires pour les fichiers inclus". DĂ©finissez la valeur: «C: \ ffmpeg \ dev \ include;». Ensuite, accĂ©dez aux rĂ©pertoires de la bibliothĂšque de liens supplĂ©mentaires et dĂ©finissez la valeur sur "C: \ ffmpeg \ dev \ lib;". C’est tout. FFmpeg est connectĂ© Ă  notre projet.

Le premier projet avec FFmpeg: décodage vidéo logiciel et enregistrement de 25 images sur disque. Le principe de travailler avec un fichier vidéo dans FFmpeg est présenté dans le schéma fonctionnel de la figure 2

image
Fig. 2 Schéma fonctionnel de l'utilisation d'un fichier vidéo.

Voici le code du projet C ++
// 21  2019 //  ,  ,   http://dranger.com/ffmpeg/tutorial01.html // #include "pch.h" extern "C" { #include <libavcodec/avcodec.h> #include <libavformat/avformat.h> #include <libswscale/swscale.h> #include <libavformat/avio.h> #include <libavutil/pixdesc.h> #include <libavutil/hwcontext.h> #include <libavutil/opt.h> #include <libavutil/avassert.h> #include <libavutil/imgutils.h> #include <libavutil/motion_vector.h> #include <libavutil/frame.h> } <cut /> #include <stdio.h> #include <stdlib.h> #include <string.h> #pragma comment(lib, "avcodec.lib") #pragma comment(lib, "avformat.lib") #pragma comment(lib, "swscale.lib") #pragma comment(lib, "avdevice.lib") #pragma comment(lib, "avutil.lib") #pragma comment(lib, "avfilter.lib") #pragma comment(lib, "postproc.lib") #pragma comment(lib, "swresample.lib") #define _CRT_SECURE_NO_WARNINGS #pragma warning(disable : 4996) // compatibility with newer API #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55,28,1) #define av_frame_alloc avcodec_alloc_frame #define av_frame_free avcodec_free_frame #endif void SaveFrame(AVFrame *pFrame, int width, int height, int iFrame) { FILE *pFile; char szFilename[32]; int y; //        sprintf(szFilename, "frame%d.ppm", iFrame); pFile = fopen(szFilename, "wb"); if (pFile == NULL) return; //    fprintf(pFile, "P6\n%d %d\n255\n", width, height); //    for (y = 0; y < height; y++) fwrite(pFrame->data[0] + y * pFrame->linesize[0], 1, width * 3, pFile); //   fclose(pFile); } <cut /> int main(int argc, char *argv[]) { AVFormatContext *pFormatCtx = NULL; int i, videoStream; AVCodecContext *pCodecCtxOrig = NULL; AVCodecContext *pCodecCtx = NULL; AVCodec *pCodec = NULL; AVFrame *pFrame = NULL; AVFrame *pFrameRGB = NULL; AVPacket packet; int frameFinished; int numBytes; uint8_t *buffer = NULL; struct SwsContext *sws_ctx = NULL; if (argc < 2) { printf("Please provide a movie file\n"); return -1; } //      av_register_all(); //     if (avformat_open_input(&pFormatCtx, argv[1], NULL, NULL) != 0) return -1; //     //      if (avformat_find_stream_info(pFormatCtx, NULL) < 0) return -1; //     : , ,    av_dump_format(pFormatCtx, 0, argv[1], 0); //    videoStream = -1; for (i = 0; i < pFormatCtx->nb_streams; i++) if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) { videoStream = i; break; } if (videoStream == -1) return -1; //   <cut /> //      pCodecCtxOrig = pFormatCtx->streams[videoStream]->codec; //      pCodec = avcodec_find_decoder(pCodecCtxOrig->codec_id); if (pCodec == NULL) { fprintf(stderr, "Unsupported codec!\n"); return -1; //    } //   pCodecCtx = avcodec_alloc_context3(pCodec); if (avcodec_copy_context(pCodecCtx, pCodecCtxOrig) != 0) { fprintf(stderr, "Couldn't copy codec context"); return -1; //   } //   if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) return -1; //     //     pFrame = av_frame_alloc(); //      RGB pFrameRGB = av_frame_alloc(); if (pFrameRGB == NULL) return -1; //        numBytes = avpicture_get_size(AV_PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height); buffer = (uint8_t *)av_malloc(numBytes * sizeof(uint8_t)); //      . avpicture_fill((AVPicture *)pFrameRGB, buffer, AV_PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height); //  SWS context       RGB sws_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_RGB24, SWS_BILINEAR, NULL, NULL, NULL ); <cut /> //     25    i = 0; while (av_read_frame(pFormatCtx, &packet) >= 0) { //    ? if (packet.stream_index == videoStream) { //    avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet); //    ? if (frameFinished) { //    RGB sws_scale(sws_ctx, (uint8_t const * const *)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize); //     if (++i % 25 == 0) SaveFrame(pFrameRGB, pCodecCtx->width, pCodecCtx->height,i); } } //   av_free_packet(&packet); } //      av_free(buffer); av_frame_free(&pFrameRGB); av_frame_free(&pFrame); avcodec_close(pCodecCtx); avcodec_close(pCodecCtxOrig); avformat_close_input(&pFormatCtx); return 0; } 


Parce que ma caméra IP a IP 192.168.1.168, puis l'appel de programme:

 decode.exe rtsp://192.168.1.168 

De plus, cet exemple peut décoder des fichiers vidéo, il suffit d'indiquer son emplacement.

Et donc, dans cet exemple, nous avons appris à décoder par programme les fichiers vidéo et à enregistrer les images reçues sur le disque. Les images sont enregistrées au format .ppm. Vous pouvez utiliser IrfanView 64 ou GIMP sous Windows pour ouvrir ces fichiers.

Conclusion: le dĂ©codage logiciel du flux RTSP Full HD H.264 prend jusqu'Ă  deux cƓurs Intel ATOM Z8350; en outre, une perte de paquets se produit pĂ©riodiquement, en raison de la partie des trames mal dĂ©codĂ©e. Cette mĂ©thode est plus applicable au dĂ©codage de fichiers vidĂ©o enregistrĂ©s, car une opĂ©ration en temps rĂ©el n'est pas nĂ©cessaire.

Dans le prochain article, je vais vous expliquer comment décoder le flux RTSP en matériel.

Archive avec le projet

Programme de travail

Liens vers des documents sur FFmpeg:


1. Le tutoriel sur l'utilisation de FFmpeg, un peu dépassé.
2. Diverses informations utiles sur FFmpeg.
3. Informations sur l'utilisation des différentes bibliothÚques fournies par FFmpeg.

Source: https://habr.com/ru/post/fr449198/


All Articles