Home Divertissementc – Pratique de développement de lecteur vidéo MJPEG ESP32-P4 : solution complète de la caméra à la carte SD – Teardown Technology

c – Pratique de développement de lecteur vidéo MJPEG ESP32-P4 : solution complète de la caméra à la carte SD – Teardown Technology

by Antoine Girard

Publié le 7 décembre 2025 à 07h59. Des développeurs ont mis au point une solution complète pour lire des vidéos MJPEG stockées sur carte SD avec la puce ESP32-P4, intégrant un écran LCD ST7703 et atteignant une fréquence d’images stable de 24 images par seconde.

  • Le projet a abouti à un système de carrousel multi-vidéo stable fonctionnant à 24 images par seconde (ips).
  • Le passage du format AVI au format MJPEG pur a résolu des problèmes de décodage et de synchronisation du cache.
  • L’activation de DMA2D (Direct Memory Access 2D) a permis d’optimiser considérablement les performances de l’écran LCD.

Le développement d’un lecteur vidéo MJPEG sur la carte ESP32-P4, équipé d’un écran LCD ST7703 (720×720), a nécessité une approche méthodique et la résolution de plusieurs défis techniques. L’équipe de développement a documenté l’ensemble du processus, de la sélection des technologies à l’optimisation des performances, en passant par le débogage des problèmes rencontrés.

Initialement, le format conteneur AVI, choisi pour sa maturité et sa capacité à stocker des métadonnées complètes, s’est avéré problématique. L’implémentation d’un analyseur AVI basé sur la recherche en mémoire, visant à extraire les données d’image JPEG, a fonctionné correctement dans un premier temps. Le code pertinent pour cette étape est le suivant :

// Recherche dans la zone de données de positionnement du logo "movi"
uint32_t movi_offset = search_fourcc(header_buf, read_size, "movi");

//Lire le morceau 00dc image par image
while (fread(chunk_header, 1, 8, fp) == 8) {
    if (chunk_id == 0x63643030) {  // "00dc"
        // 读取JPEG帧数据
        fread(jpeg_data, 1, chunk_size, fp);
    }
}

Cependant, des difficultés sont rapidement apparues. Le décodage JPEG, utilisant le décodeur matériel intégré de l’ESP32-P4, entraînait des délais d’expiration (ESP_ERR_TIMEOUT) et des données de sortie nulles, même lorsque la taille de la sortie était correcte. L’écran affichait des blocs de couleurs irréguliers (mosaïques vertes, violettes et roses). Les journaux indiquaient des erreurs de décodage :

E (6392) jpeg.decoder : délai d'attente jpeg_decoder_process

I (6392) video_player : données de sortie de l'image décodée n° 1 : 00 00 00 00 00 00 00 00 00 00 00 00 ...

W (6392) video_player : délai d'expiration du décodage JPEG mais données complètes (sortie : 691 200 octets)

Plusieurs hypothèses ont été testées. L’intégrité des données JPEG a été vérifiée, confirmant la présence des balises de début et de fin (0xFF D8 et 0xFF D9). Des tentatives de modification de l’ordre des couleurs RVB (JPEG_DEC_RGB_ELEMENT_ORDER_BGR) et d’ajout d’une conversion de l’espace colorimétrique YUV en RVB (JPEG_YUV_RGB_CONV_STD_BT601) se sont avérées infructueuses. La cause principale du problème s’est finalement révélée être une incohérence du cache. Des tentatives de synchronisation du cache (esp_cache_msync) ont conduit à des erreurs d’alignement et à des données de sortie nulles.

Un test comparatif a révélé qu’une seule image JPEG pouvait être décodée et affichée correctement, tandis que la lecture d’une vidéo AVI échouait à chaque image. Cette observation a conduit à un changement de stratégie : l’abandon du conteneur AVI au profit du format MJPEG pur.

En s’inspirant d’un exemple de lecture MJPEG officiel d’Espressif, l’équipe a converti les vidéos au format MJPEG pur à l’aide de FFmpeg. La commande correcte pour la conversion est :

Mauvaise façon (forçant YUV422p)

ffmpeg -i input.avi -pix_fmt yuvj422p -f mjpeg sortie.mjpeg # ❌

La bonne manière (laissez FFmpeg choisir automatiquement)

ffmpeg -i input.mp4 -q:v 3 -f mjpeg sortie.mjpeg # ✅

La principale différence réside dans le choix de l’espace colorimétrique. Forcer l’utilisation de yuvj422p peut entraîner des problèmes de compatibilité, tandis que laisser FFmpeg choisir automatiquement (généralement yuv420p) assure une meilleure compatibilité.

L’intégration du composant officiel esp_mjpeg_decode a permis de décoder et d’afficher les vidéos MJPEG sans problème. Le code pertinent est le suivant :

FILE *input;
uint8_t *mjpeg_buf;
uint8_t *output_buf;
jpeg_decoder_handle_t decoder_engine;
int16_t w, h;
// ...

esp_mjpeg_decode_read_mjpeg_buf(&mjpeg);
esp_mjpeg_decode_jpg(&mjpeg);
esp_lcd_panel_draw_bitmap(..., esp_mjpeg_decode_get_out_buf(&mjpeg));

Après avoir adopté le format MJPEG pur, la fréquence d’images initiale était de 16 à 18 ips. L’analyse des goulots d’étranglement a révélé que le décodage JPEG prenait environ 40 ms, la lecture de la carte SD environ 2 ms et le rafraîchissement de l’écran LCD environ 18 ms, pour un total d’environ 60 ms.

L’activation de DMA2D dans la configuration LCD a permis d’améliorer considérablement les performances, en passant de 16 ips à 70-82 ips. DMA2D permet au matériel de transférer directement les données de pixel vers l’écran LCD, réduisant ainsi la charge du processeur.

L’optimisation de la configuration du cache, en augmentant la taille du cache L2 à 256 Ko et la taille de la ligne de cache à 128 octets, a également contribué à améliorer la stabilité de la transmission DMA.

Enfin, l’utilisation d’une carte SD haute vitesse (SDHC) a permis d’améliorer les performances globales. Une ancienne carte SDSC (40 MHz) atteignait 16-18 ips, tandis qu’une nouvelle carte SDHC (52 MHz) atteignait 70-82 ips.

Pour contrôler précisément la fréquence d’images à 24 ips, une méthode à intervalle de temps fixe a été implémentée, basée sur l’utilisation de la minuterie de haute précision esp_timer_get_time. Cette méthode a permis d’éliminer les erreurs cumulées et de compenser automatiquement les images lentes, atteignant une fréquence d’images de 23,9-24,06 ips avec une erreur inférieure à 0,3 %.

Le projet a démontré l’importance de choisir le bon format de fichier, d’optimiser l’utilisation du matériel (DMA2D) et de synchroniser correctement le cache. Les performances finales du système sont les suivantes : capacité de décodage JPEG de 70-82 ips, fréquence d’images de lecture réelle de 24 ips, commutation vidéo fluide entre 7 vidéos et une stabilité prouvée par plus de 85 000 images affichées sans crash.

Le code source est disponible sur GitHub. Une vidéo de démonstration est également disponible sur YouTube (lien non fourni dans la source).

Références : Documentation du codec JPEG ESP-IDF, documentation du pilote hôte SDMMC, exemple de code MJPEG officiel ESP32-P4, documentation officielle de FFmpeg.

You may also like

Leave a Comment