我需要在我的视频播放应用程序中启用 FFmpeg。然而,FFmpeg应用程序无法监听正确的音频流数据。这是代码中无法正常工作的部分:
if (avformat_open_input(&m_data->formatContext, Filename.c_str(), nullptr, nullptr) != 0)
{
std::cout << "Motion: Failed to open file: '" << Filename << "'" << std::endl;
return false;
}
if (avformat_find_stream_info(m_data->formatContext, nullptr) < 0)
{
std::cout << "Motion: Failed to find stream information" << std::endl;
return false;
}
for (unsigned int i = 0; i < m_data->formatContext->nb_streams; i++)
{
// Получаем параметры кодека для текущего потока
AVCodecParameters *codecParams = m_data->formatContext->streams[i]->codecpar;
switch (codecParams->codec_type)
{
case AVMEDIA_TYPE_AUDIO:
if (m_data->audioStreamID == -1 && EnableAudio)
m_data->audioStreamID = i;
break;
default:
break;
}
}
if (HasAudio())
{
const AVCodec* codec = avcodec_find_decoder(m_data->formatContext->streams[m_data->audioStreamID]->codecpar->codec_id);
std::cout << m_data->formatContext->streams[m_data->audioStreamID]->codecpar->codec_id<< std::endl;
m_data->audioContext = avcodec_alloc_context3(codec);
if (!m_data->audioContext)
{
std::cout << "Motion: Failed to get audio codec context" << std::endl;
m_data->audioStreamID = -1;
}
else
{
m_data->audioCodec = codec;
if (!m_data->audioCodec)
{
std::cout << "Motion: Failed to find audio codec" << std::endl;
m_data->audioStreamID = -1;
}
else
{
if (avcodec_open2(m_data->audioContext, m_data->audioCodec, nullptr) != 0)
{
std::cout << "Motion: Failed to load audio codec" << std::endl;
m_data->audioStreamID = -1;
}
else
{
m_data->audioRawBuffer = av_frame_alloc();
if (!m_data->audioRawBuffer)
{
std::cout << "Motion: Failed to allocate audio buffer" << std::endl;
m_data->audioStreamID = -1;
}
else
{
int buffer_size = av_samples_get_buffer_size(nullptr, m_data->audioContext->channels, MAX_AUDIO_SAMPLES, AV_SAMPLE_FMT_S16, 0);
if (buffer_size < 0) {
char err_buf[AV_ERROR_MAX_STRING_SIZE];
av_strerror(buffer_size, err_buf, sizeof(err_buf));
std::cerr << "Motion: Failed to calculating buffer size: " << err_buf << std::endl;
m_data->audioStreamID = -1;
}
else if (av_samples_alloc(&m_data->audioPCMBuffer, nullptr, m_data->audioContext->channels, av_samples_get_buffer_size(nullptr, m_data->audioContext->channels, MAX_AUDIO_SAMPLES, AV_SAMPLE_FMT_S16, 0), AV_SAMPLE_FMT_S16, 0) < 0)
{
std::cout << "Motion: Failed to create audio samples buffer" << std::endl;
m_data->audioStreamID = -1;
}
else
{
av_frame_unref(m_data->audioRawBuffer);
uint64_t inchanlayout = m_data->audioContext->channel_layout;
uint64_t outchanlayout = inchanlayout;
if (inchanlayout == 0)
inchanlayout = av_get_default_channel_layout(m_data->audioContext->channels);
if (outchanlayout != AV_CH_LAYOUT_MONO)
outchanlayout = AV_CH_LAYOUT_STEREO;
m_data->audioSWContext = swr_alloc();
std::cout << m_data->audioContext->sample_rate << std::endl;
std::cout << m_data->audioContext->sample_fmt << std::endl;
av_opt_set_int(m_data->audioSWContext, "in_channel_layout", inchanlayout, 0);
av_opt_set_int(m_data->audioSWContext, "out_channel_layout", outchanlayout, 0);
av_opt_set_int(m_data->audioSWContext, "in_sample_rate", m_data->audioContext->sample_rate, 0);
av_opt_set_int(m_data->audioSWContext, "out_sample_rate", m_data->audioContext->sample_rate, 0);
av_opt_set_sample_fmt(m_data->audioSWContext, "in_sample_fmt", m_data->audioContext->sample_fmt, 0);
av_opt_set_sample_fmt(m_data->audioSWContext, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0);
swr_init(m_data->audioSWContext);
m_audioChannelCount = av_get_channel_layout_nb_channels(outchanlayout);
}
}
}
}
}
}
控制台显示错误“Motion: 无法计算缓冲区大小: Invalid argument”。出现此错误是因为 avcodec_alloc_context 3(codec)->channels == 0,但情况不应该是这样。视频文件必须有第二个音频通道
看一下函数avcodec_alloc_context3的说明。该函数只是分配上下文并将其字段设置为默认值。分配之后、avcode_open2之前,您需要使用avcodec_parameters_to_context函数复制流编解码器参数,或手动设置参数。