2013-08-24 3 views
0

J'essaie d'obtenir de la musique avec libav en utilisant xaudio2. Le code xaudio2 que j'utilise fonctionne avec un ffmpeg plus ancien utilisant avcodec_decode_audio2, mais cela a été abandonné pour avcodec_decode_audio4. J'ai essayé plusieurs exemples de libav, mais je n'arrive pas à lire l'audio. La vidéo fonctionne bien (ou plutôt elle joue juste bien vite maintenant, car je n'ai encore codé aucun code de synchronisation).Libav et xaudio2 - audio ne joue pas

Tout d'abord audio s'init, aucune erreur, vidéo s'init, puis paquet:

while (1) { 
    //is this packet from the video or audio stream? 
    if (packet.stream_index == player.v_id) { 
     add_video_to_queue(&packet); 
    } else if (packet.stream_index == player.a_id) { 
     add_sound_to_queue(&packet); 
    } else { 
     av_free_packet(&packet); 
    } 
} 

Puis, en add_sound_to_queue:

int add_sound_to_queue(AVPacket * packet) { 
AVFrame *decoded_frame = NULL; 
int done = AVCODEC_MAX_AUDIO_FRAME_SIZE; 
int got_frame = 0; 

if (!decoded_frame) { 
    if (!(decoded_frame = avcodec_alloc_frame())) { 
     printf("[ADD_SOUND_TO_QUEUE] Out of memory\n"); 
     return -1; 
    } 
} else { 
    avcodec_get_frame_defaults(decoded_frame); 
} 

if (avcodec_decode_audio4(player.av_acodecctx, decoded_frame, &got_frame, packet) < 0) { 
    printf("[ADD_SOUND_TO_QUEUE] Error in decoding audio\n"); 
    av_free_packet(packet); 
    //continue; 
    return -1; 
} 
if (got_frame) { 
    int data_size; 
    if (packet->size > done) { 
     data_size = done; 
    } else { 
     data_size = packet->size; 
    } 
    BYTE * snd = (BYTE *)malloc(data_size * sizeof(BYTE)); 

    XMemCpy(snd, 
     AudioBytes, 
     data_size * sizeof(BYTE) 
    ); 

    XMemSet(&g_SoundBuffer,0,sizeof(XAUDIO2_BUFFER)); 

    g_SoundBuffer.AudioBytes = data_size; 
    g_SoundBuffer.pAudioData = snd; 
    g_SoundBuffer.pContext = (VOID*)snd; 

    XAUDIO2_VOICE_STATE state; 
    while(g_pSourceVoice->GetState(&state), state.BuffersQueued > 60) { 
     WaitForSingleObject(XAudio2_Notifier.hBufferEndEvent, INFINITE); 
    } 

    g_pSourceVoice->SubmitSourceBuffer(&g_SoundBuffer); 
} 
return 0; 
} 

Je ne peux pas à comprendre le problème, je Ajout de messages d'erreur dans init, ouverture vidéo, manipulation de codec etc. Comme mentionné précédemment, le code xaudio2 fonctionne avec un ffmpeg plus ancien, alors peut-être que j'ai raté quelque chose avec avcodec_decode_audio4?

Si ce snappet code ne suffit pas, je peux poster tout le code, ce ne sont que les endroits dans le code, je pense que le problème serait :(

Répondre

1

Je ne vous vois pas accéder decoded_frame partout après décodage. Comment voulez-vous pour obtenir les données sur autrement?

BYTE * snd = (BYTE *)malloc(data_size * sizeof(BYTE));

Cela semble également très louche, étant donné que data_size est dérivé de la taille du paquet. la taille du paquet est la taille des données compressées, il a très peu à voir avec la taille de la trame PCM décodée

Les données décodées se trouvent dans decoded_frame->extended_data, qui est un tableau de pointeurs vers des plans de données, voir here pour plus de détails. La taille des données décodées est déterminée par decoded_frame->nb_samples. Notez qu'avec les versions récentes de Libav, de nombreux décodeurs retournent l'audio planaire, de sorte que différents canaux vivent dans des tampons de données différents. Pour de nombreux cas d'utilisation, vous devez convertir ce format au format entrelacé, où il n'y a qu'un seul tampon avec tous les canaux. Utilisez libavresample pour cela.

+0

Merci pour la réponse rapide. J'ai vu que je n'avais pas accès à decoded_frame hier soir, et j'ai un peu changé le code. Je pense qu'il accède à l'audio maintenant parce que la vidéo est synchronisée (la vitesse de lecture est la même que sur n'importe quel autre lecteur multimédia). Ligne 34 Dans http://pastebin.com/Bv1fBA5M, AudioBytes était le tampon src dans xmemcpy, mais decoded_frame-> data [0] devrait l'être maintenant. AudioBytes est (BYTE *) alors que data [0] est uint8_t *. J'ai essayé de (const void *) decoded_frame-> data [0] etc. mais j'obtiens une erreur ptr xmemset. J'ai essayé d'utiliser memcpy et memset, pas de chance pour moi. – siz