2016-09-16 6 views
0

Lors de la lecture des fichiers image en utilisant une version récente de FFmpeg Je rencontre une fuite de mémoire que j'ai des problèmes de suivi.FFmpeg fuite lors de la lecture des fichiers image

Il semble que après avoir rempli le AVFrame avec avcodec_send_packet et avcodec_receive_frame, mon appel à av_frame_free ne fait désaffecter les objets AVBuffer withing le cadre. La seule chose que je ne libère pas est le AVCodecContext. Si j'essaye de faire ça, je vais avoir un accident.

J'ai créé cet exemple de programme, il est aussi simple que je peux l'obtenir. Cela permet de continuer à ouvrir, lire et fermer le même fichier image dans une boucle. Sur mon système, cela fuit la mémoire à un rythme alarmant.

#include <libavcodec/avcodec.h> 
#include <libavformat/avformat.h> 

int main(int argc, char **argv) { 
    av_register_all(); 

    while(1) { 
     AVFormatContext *fmtCtx = NULL; 

     if (avformat_open_input(&fmtCtx, "/path/to/test.jpg", NULL, NULL) == 0) { 
      if (avformat_find_stream_info(fmtCtx, NULL) >= 0) { 
       for (unsigned int i = 0u; i < fmtCtx -> nb_streams; ++i) { 
        AVStream *stream = fmtCtx -> streams[i]; 
        AVCodecContext *codecCtx = stream -> codec; 
        AVCodec *codec = avcodec_find_decoder(codecCtx -> codec_id); 

        if (avcodec_open2(codecCtx, codec, NULL) == 0) { 
         AVPacket packet; 

         if (av_read_frame(fmtCtx, &packet) >= 0) { 
          if (avcodec_send_packet(codecCtx, &packet) == 0) { 
           AVFrame *frame = av_frame_alloc(); 

           avcodec_receive_frame(codecCtx, frame); 
           av_frame_free(&frame); 
          } 
         } 

         av_packet_unref(&packet); 
        } 
       } 
      } 

      avformat_close_input(&fmtCtx); 
     } 
    } 

    return 0; 
} 

Répondre

1

La solution est de créer une copie de la AVCodecContext qui a été créé automatiquement lorsque le fichier a été ouvert et utiliser cette copie dans avcodec_open2. Cela permet de supprimer cette copie avec avcodec_free_context. Avec les versions récentes de FFmpeg, avcodec_copy_context a été abandonné et remplacé par AVCodecParameters. À l'aide de l'extrait suivant dans l'exemple de programme de la question se branche la fuite:

AVCodecParameters *param = avcodec_parameters_alloc(); 
AVCodecContext *codecCtx = avcodec_alloc_context3(NULL); 
AVCodec *codec = avcodec_find_decoder(stream -> codec -> codec_id); 

avcodec_parameters_from_context(param, stream -> codec); 
avcodec_parameters_to_context(codecCtx, param); 
avcodec_parameters_free(&param); 
[...] 
avcodec_free_context(&codecCtx);