Salut Cet article est une continuation de
mon article FFmpeg pour démarrer avec Visual Studio. Ici, nous passons au décodage matériel du flux FULL HD RTSP. Je dirai à l'avance que même l'Intel ATOM Z8350 peut facilement faire face à cette tâche.
Objectif: décodage matériel et enregistrement jusqu'à 4 images dans la RAM pour un traitement parallèle ultérieur (quatre cœurs de processeur) à partir d'une caméra IP h.264 RTSP. J'affiche les images traitées à l'aide des fonctions WinAPI. En conséquence, nous obtenons un système à grande vitesse pour le traitement informatique du flux RTSP en mode parallèle. Ensuite, vous pouvez connecter les algorithmes de
vision par ordinateur pour le traitement des trames en
temps réel .
Entrée
Pourquoi ai-je besoin d'un décodage matériel? Vous voulez décoder la vidéo en temps réel avec un processeur faible et bon marché ou vous voulez décharger le processeur autant que possible, alors il est temps de vous familiariser avec le décodage matériel.
DirectX Video Acceleration (DXVA) est une API permettant d'utiliser l'accélération matérielle pour accélérer le traitement vidéo avec les GPU. DXVA 2.0 vous permet de rediriger davantage d'opérations vers le GPU, y compris les opérations de capture vidéo et de traitement vidéo.
Après avoir écrit l'article précédent, on m'a posé pas mal de questions: "pourquoi est-il utilisé FFmpeg?" Je vais commencer par les problèmes. La principale difficulté du décodage matériel est d'écrire la trame décodée sur la RAM. Pour Full HD, c'est 1920 x 1080 x 3 = 6 220 800 octets. Même en tenant compte du fait que la trame est stockée au format NV12, cela représente également beaucoup de 1920 x 1080 x 1,5 = 3 110 400 octets. L'écrasement de 75 Mo par seconde est une tâche sérieuse pour tout processeur. Pour résoudre ce problème, Intel a ajouté des commandes SSE 4, qui vous permettent de réécrire des données sans processeur. Malheureusement, toutes les bibliothèques ne l'ont pas implémenté. J'ai testé les bibliothèques suivantes:
- Ffmpeg
- VLC
- Opencv
VLC - fonctionne avec les caméras IP via le décodage matériel (très faible charge du processeur), un lecteur de flux RTSP primitif peut être construit en seulement 10 lignes de code, mais la réception de trames décodées en RAM prend trop de temps processeur.
OpenCV - RTSP utilise FFmpeg pour travailler avec le flux, il a donc été décidé de travailler sans intermédiaires, c'est-à-dire utilisez la bibliothèque FFmpeg. De plus, FFmpeg, qui est installé par défaut, est intégré à OpenCV sans décodage matériel.
FFmpeg - a montré de bons résultats, à mon avis, cela fonctionne de manière stable. Le seul inconvénient n'est pas implémenté avec les caméras WEB pour la version X86 (X64 semble vous permettre de travailler) sous Windows.
Le décodage vidéo matériel est facile
En fait, le décodage matériel utilisant la bibliothèque FFmpeg n'est pas plus compliqué que le logiciel. Les paramètres du projet sont les mêmes que pour l'implémentation du logiciel, le schéma fonctionnel est resté inchangé.
Vous pouvez afficher une liste des méthodes de décodage matériel prises en charge par FFmpeg.
fprintf(stderr, " %s", av_hwdevice_get_type_name(type));
La première chose que nous devons faire est de dire à FFmpeg avec quel décodeur matériel vous voulez décoder la vidéo. Dans mon cas, Windows10 + Intel Atom Z8350 ne laisse que DXVA2:
type = av_hwdevice_find_type_by_name("dxva2");
Vous pouvez choisir CUDA, D3D11VA, QSV ou VAAPI (Linux uniquement) comme décodeur matériel. En conséquence, vous devriez avoir cette solution matérielle et FFmpeg devrait être construit avec son support.
Ouvrez le flux vidéo:
avformat_open_input(&input_ctx, filename, NULL, NULL;
Nous obtenons des informations sur le flux vidéo:
av_find_best_stream(input_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, &decoder, 0);
Allouer de la mémoire:
frame = av_frame_alloc();
Cette fonction écrase le fichier décodé en RAM:
av_hwframe_transfer_data(sw_frame, frame, 0);
Un peu sur le format NV12
Nous avons donc obtenu un cadre dans la structure sw_frame. La trame reçue est stockée au format NV12. Ce format a été inventé par Microsoft. Il vous permet de stocker des informations sur les pixels sur 12 bits. Où 8 bits est l'intensité et 4 bits décrivent la couleur (ou plutôt, la couleur est immédiatement décrite pour 4 pixels 2x2 adjacents). De plus, sw_frame.data [0] - l'intensité est stockée et dans sw_frame.data [1] - la couleur est stockée. Pour convertir de NV-12 en RVB, vous pouvez utiliser la fonction suivante:
Traduction C ++ de NV12 à RGB void SaveFrame(uint8_t * f1, uint8_t * f2, int iFrame) { FILE *pFile; char szFilename[32]; int x, i, j;
Bien que travailler avec NV12 vous permet d'accélérer la mise en œuvre de procédures telles que le flou, Retinex et l'obtention d'images en niveaux de gris (simplement en supprimant la couleur). Dans mes tâches, je ne traduis pas le format NV12 en RVB, car cela prend plus de temps.
Et nous avons donc appris à décoder les fichiers vidéo dans le matériel et à les afficher dans une fenêtre. Nous nous sommes rencontrés au format NV12 et comment le convertir en RVB familier.
Décodage matériel dll
FFmpeg émet des images après 40 ms (à 25 images par seconde). En règle générale, le traitement d'une image Full HD prend beaucoup plus de temps. Cela nécessite le multithreading pour maximiser la charge des 4 cœurs de processeur. En pratique, je lance une fois 6 threads et ne les supprime plus, ce qui simplifie grandement le travail et augmente la fiabilité du programme. Le schéma de fonctionnement est illustré à la Fig. 1
Fig.1 Schéma de construction d'un programme multi-thread avec FFmpegJ'ai écrit mon décodeur sous
* .dll (FFmpegD.DLL) pour l'inclure dans mes projets. Cela vous permet de réduire le code du projet, ce qui améliore la compréhension du code et de l'inclure dans n'importe quel langage de programmation, jusqu'à Assembleur (vérifié :)). En l'utilisant, nous allons écrire notre lecteur de flux RTSP à partir de la caméra IP.
Pour commencer à travailler avec une DLL, vous devez passer un pointeur vers un tableau int [13], un HANDLE d'un nouvel événement d'arrivée de trame, un HANDLE pour commencer à traiter un nouveau paquet de données de la caméra et un tableau de caractères de l'adresse de la caméra.
La structure du tableau est donnée dans le tableau 1.

Avant d'appeler, vous devez réinitialiser les numéros de trame 1-4.
La DLL prendra toutes les mesures nécessaires pour initialiser FFmpeg et enregistrera les pointeurs et les numéros de trame. Après avoir défini l'événement «Nouvelle arrivée de trame». Il suffit de traiter les trames entrantes et d'écrire 0 au lieu du numéro de trame (cela signifie que la trame est traitée et n'est plus utilisée).
Ci-dessous, vous trouverez un exemple de lecteur avec le code source. L'exemple est ShowDib3 Charles Petzold.
→
Archiver avec le projet→
Archive FFmpegD.dllRÉSULTATS: Le détecteur de mouvement matériel FFmpeg même sur Intel Atom Z8350 décode le h264 Full HD en temps réel avec un chargement du processeur jusqu'à 20% avec un détecteur de mouvement connecté.
Exemple de fonctionnement du détecteur de mouvement sur Intel ATOM Z8350. Les 30 premières secondes correspondent au calcul de l'arrière-plan. Après cela, le détecteur de mouvement fonctionne par la méthode de soustraction de l'arrière-plan.PS Vous pouvez également décoder des fichiers vidéo (h.264 compressé) !!!
Références:
- Diverses informations utiles sur FFmpeg
- Informations sur l'utilisation des différentes bibliothèques fournies par FFmpeg
- Informations sur les formats et la conversion en RVB