2013-05-11 2 views
2

J'essaie de créer un lecteur multimédia simple pour une introduction au monde de ffmpeg, le problème est que chaque fois que j'appelle av_freep(void*ptr) l'application se bloque.av_free bloque l'application de manière aléatoire - FFMPEG C++

Si je n'appelle av_freep je reçois une fuite de mémoire et la mémoire utilisée par le programme augmente jusqu'à 1000Mo (déjà mesurée), voici le code:

int16_t* audioBuffer=(int16_t*)av_malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE+FF_INPUT_BUFFER_PADDING_SIZE); 

if(!audioBuffer){ 
    MessageBox(0,"Error allocating in audioBuffer","Error: Mem",MB_ICONWARNING | MB_OK); 
    return -1; 
} 

int sz = MEDIA->DecodeAudioFrame((void*)audioBuffer,0); 

Pa_WriteStream(MEDIA->output_stream,(int16_t*)audioBuffer,MEDIA->_audio_ccontext->frame_size); 

av_freep(audioBuffer); 

Voici mon « DecodeAudioFrame » le code de fonction:

int WbMedia::DecodeAudioFrame(void *audio_buf, int buf_size){ 
static AVFrame frame; 
static AVPacket pkt; 
static uint8_t *audio_pkt_data = NULL; 
static int audio_pkt_size = 0; 

int len1=0; 

for(;;){ 
    bool do_rt = false; 


    while(audio_pkt_size > 0){ 
     int obt_frame = 0; 

     len1 = avcodec_decode_audio4(_audio_ccontext,&frame,&obt_frame,&pkt); 
     if(len1 < 0){ 
      audio_pkt_size = 0; 
      break; 
     } 

     audio_pkt_data+=len1; 
     audio_pkt_size-=len1; 

     if(obt_frame){ 
      data_size = av_samples_get_buffer_size(frame.linesize,channel_count,sample_fr,_audio_ccontext->sample_fmt,1); 
      memcpy(audio_buf,frame.data[0],data_size); 
     } 

     if(data_size < 0){ 
      continue; 
     } 

     if(pkt.data){ 
      av_free_packet(&pkt); 
     } 
     return data_size; 

    } 

    if(pkt.data){ 
     av_free_packet(&pkt); 
    } 

    if(do_rt){ 
     return data_size; 
    } 

    // Try to get a new packet 
    if(!audio_packets.empty()){ 
     WaitForSingleObject(Queue_Audio_Mutex,INFINITE); 
      pkt = audio_packets.front(); 
      audio_packets.pop(); 
     ReleaseMutex(Queue_Audio_Mutex); 

     audio_pkt_size = pkt.size; 
     audio_pkt_data = pkt.data; 
    }else{ 
     return -1; 
    } 
} 
return 0; 
} 

Je besoin d'aide à ce problème, je ne sais pas s'il est un bug ou que je dois faire. Ce qui se passe là-bas? Pourquoi se bloque-t-il sur l'appel av_freep? Comment puis-je le réparer?

Merci

+2

Essayez 'av_freep (& audioBuffer);' [Doc:] (http: // wiki.aasimon.org/doku.php?id=ffmpeg:av_freep) 'NOTE: ptr devrait être déclaré comme un void **' – mwerschy

+0

Changé l'argument 'av_freep' de' & audioBuffer', maintenant, il plante encore mais cette fois le débogueur pointe vers le 'memcpy' sur le' DecodeAudioFrame' – Spamdark

Répondre

4

av_freep prend un pointeur au pointeur que vous voulez libérer; il définit le pointeur libéré à NULL ensuite. , Vous devez donc l'utiliser comme

av_freep(&audioBuffer); 

Vous pouvez également utiliser

av_free(audioBuffer); 
audioBuffer = NULL; 

qui est équivalent.

+0

Merci pour la réponse, la dernière erreur est corrigée, mais maintenant je reçois une nouvelle erreur.Le débogueur me dit que le problème vient dans le 'memcpy' de la fonction' DecodeAudioFrame' – Spamdark

+0

C'est clairement un problème différent. Assurez-vous que vous ne transmettez pas quelque chose d'invalide comme 'data_size', par exemple. -1. – nneonneo

+0

Je vais vérifier ce qui se passe là-bas. Je vais marquer votre réponse comme acceptée. Merci quand même, je vais essayer de continuer à regarder ce qui se passe sur le mémcpy – Spamdark

0
int16_t* audioBuffer=(int16_t*)av_malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE+FF_INPUT_BUFFER_PADDING_SIZE); 

Ceci est faux. AVCODEC_MAX_AUDIO_FRAME_SIZE est déprécié (supprimé dans les nouvelles versions). Avec la nouvelle API de décodage, vous pouvez obtenir des images plus grandes et décodées.

static AVFrame frame; 

Non N'allouez pas AVFrame sur la pile, il va se casser. Utilisez avcodec_alloc_frame() (ou av_frame_alloc() avec les nouvelles versions). Vous réalisez que vous êtes en train d'écrire la taille d'image d'origine (AKA la taille du plan), n'est-ce pas? Je me demande si c'est prévu.

En outre, ce qui est sample_fr? Est-ce que c'est une constante de quelque part? Utilisez simplement AVFrame.nb_samples. Enfin, votre code suppose de manière appropriée l'audio entrelacé (c'est-à-dire les échantillons audio pour tous les canaux entrelacés dans un tampon). De nombreux décodeurs produisent maintenant un son planaire (c'est-à-dire les échantillons pour chaque canal dans un tampon séparé). Cela peut être la raison de l'accident, car av_samples_get_buffer_size calcule la taille totale pour tous les échantillons dans tous les canaux, tandis que data[0] contiendra uniquement les échantillons pour le premier canal.

Si l'audio plan est en effet la raison, vous devez soit modifier votre code pour le soutenir, ou utiliser libavresample pour convertir plan à intercalés

Questions connexes