我正在尝试使用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的东西吗?
如果仅此代码片段还不够,我可以发布整个代码,这些只是代码中的位置,我认为问题可能是:(
最佳答案
解码后,我看不到您在任何地方访问decoded_frame
。您如何期望以其他方式获取数据?
BYTE * snd = (BYTE *)malloc( data_size * sizeof(BYTE));
鉴于
data_size
是从数据包大小派生的,所以这看起来也很混乱。分组大小是压缩数据的大小,与解码的PCM帧的大小几乎没有关系。解码后的数据位于
decoded_frame->extended_data
中,它是指向数据平面的指针的数组,有关详细信息,请参见here。解码数据的大小由decoded_frame->nb_samples
确定。请注意,在最新的Libav版本中,许多解码器返回平面音频,因此不同的通道位于不同的数据缓冲区中。对于许多用例,您需要将其转换为交错格式,其中所有通道只有一个缓冲区。为此使用libavresample。关于audio - Libav和XAudio2-音频无法播放,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/18423324/