FFmpeg C++ 无法获取有关音频流的正确信息

问题描述 投票:0回答:1

我需要在我的视频播放应用程序中启用 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,但情况不应该是这样。视频文件必须有第二个音频通道 enter image description here

c++ ffmpeg
1个回答
0
投票

看一下函数avcodec_alloc_context3的说明。该函数只是分配上下文并将其字段设置为默认值。分配之后、avcode_open2之前,您需要使用avcodec_parameters_to_context函数复制流编解码器参数,或手动设置参数。

© www.soinside.com 2019 - 2024. All rights reserved.