【问题标题】:Libav and xaudio2 - audio not playingLibav 和 xaudio2 - 音频不播放
【发布时间】:2013-08-27 17:09:20
【问题描述】:

我正在尝试使用 xaudio2 使用 libav 播放音频。我正在使用的 xaudio2 代码适用于使用 avcodec_decode_audio2 的较旧的 ffmpeg,但 avcodec_decode_audio4 已弃用该代码。我尝试了各种 libav 示例,但似乎无法播放音频。视频播放正常(或者说它现在播放很快,因为我还没有编写任何同步代码)。

首先音频被初始化,没有错误,视频被初始化,然后是数据包:

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);
    }
}

然后在 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;
}

我似乎无法找出问题所在,我在 init、打开视频、编解码器处理等中添加了错误消息。如前所述,xaudio2 代码正在使用较旧的 ffmpeg,所以也许我错过了一些与avcodec_decode_audio4?

如果这个代码片段还不够,我可以发布整个代码,这些只是代码中我认为问题所在的地方:(

【问题讨论】:

    标签: audio ffmpeg decode libav xaudio2


    【解决方案1】:

    解码后,我看不到您在任何地方访问decoded_frame。否则,您希望如何获取数据?

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

    这看起来也很可疑,因为data_size 是从数据包大小得出的。包大小是压缩后数据的大小,与解码后的PCM帧大小关系不大。

    解码后的数据位于decoded_frame-&gt;extended_data,这是一个指向数据平面的指针数组,详见here。解码数据的大小由decoded_frame-&gt;nb_samples 决定。请注意,在最近的 Libav 版本中,许多解码器返回平面音频,因此不同的通道存在于不同的数据缓冲区中。对于许多用例,您需要将其转换为交错格式,其中只有一个包含所有通道的缓冲区。为此使用libavresample

    【讨论】:

    • 感谢您的快速回复。昨晚看到没有访问decoded_frame,代码稍微改了一下。我认为它现在可以访问音频,因为视频是同步的(播放速度与任何其他媒体播放器相同)。第 34 行在 pastebin.com/Bv1fBA5M 中,AudioBytes 是 xmemcpy 中的 src 缓冲区,但现在应该是 decoded_frame->data[0]。 AudioBytes 是 (BYTE ) 而 data[0] 是 uint8_t。我曾尝试 (const void *) decoded_frame->data[0] 等,但得到一个 ptr 错误 xmemset。已尝试使用 memcpy 和 memset,但我没有运气。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-28
    • 2021-05-26
    • 1970-01-01
    • 2021-10-06
    相关资源
    最近更新 更多