使用NAudio播放FFMPEG音频会带来很多噪音

时间:2018-08-28 13:37:20

标签: c# c++ audio ffmpeg naudio

我正在尝试使用FFMPEG框架播放视频,并使用NAudio播放音频帧。视频可以正常播放,但是当我使用BufferedWaveProvider播放音频而基础音频听起来正确时,则具有大量的静态/噪声。在附加的代码中要注意的重要一点是,当事件从托管C ++类触发时,C#类接收该事件,然后获取最新的相关AVFrame数据。这对于视频来说是完美的,但是就像我说的那样,当我尝试播放音频时,会产生很多噪音。现在,我已经对NAudio WaveFormat设置进行了硬编码,但是它们应该与视频的音频匹配。

    ///////////////////////// C# /////////////////////////////

    // Gets the size of the data from the audio AVFrame (audioFrame->linesize[0])
    int size = _Decoder.GetAVAudioFrameSize();

    if (!once)
    {
        managedArray = new byte[size];
        once = true;
    }

    // Gets the data array from the audio AVFrame
    IntPtr data = _Decoder.GetAVAudioFrameData();

    Marshal.Copy(data, managedArray, 0, size);

    if (_waveProvider == null)
    {
        _waveProvider = new BufferedWaveProvider(new WaveFormat(44100, 16, 2));
        _waveOut.NumberOfBuffers = 2;
        _waveOut.DesiredLatency = 300;
        _waveOut.Init(_waveProvider);
        _waveOut.Play();
    }

    _waveProvider.AddSamples(managedArray, 0, size);


    //////////////////////// Managed C++ /////////////////////////
    while (_shouldRead)
    {
        // if we're not initialized, sleep
        if (!_initialized || !_FFMpegObject->AVFormatContextReady())
        {
            Thread::Sleep(READ_INIT_WAIT_TIME);
        }
        else if (_sequentialFailedReadCount > MAX_SEQUENTIAL_READ_FAILS)
        {
            // we've failed a lot and probably lost the stream, try to reconnect.
            _sequentialFailedReadCount = 0;
            _initialized = false;
            StartInitThread();
            Thread::Sleep(READ_INIT_WAIT_TIME << 1);
        }
        else // otherwise, try reading one AV packet 
        {
            if (_FFMpegObject->AVReadFrame())
            {
                if (_FFMpegObject->GetAVPacketStreamIndex() == _videoStreamIndex)
                {
                    _sequentialFailedReadCount = 0;

                    // decode the video packet
                    _frameLock->WaitOne();
                    frameFinished = _FFMpegObject->AVCodecDecodeVideo2();
                    _frameLock->ReleaseMutex();

                    if (frameFinished)
                    {
                        _framesDecoded++;

                        if (!_isPaused) // If paused and AFAP playback, just don't call the callback
                        {
                            FrameFinished(this, EventArgs::Empty);

                            Thread::Sleep((int)(1000 / (GetFrameRate() * _speed)));
                        }
                    }
                }
                else if (_FFMpegObject->GetAVPacketStreamIndex() == _audioStreamIndex)
                {
                    // decode the audio packet.
                    _frameLock->WaitOne();
                    audioFrameFinished = _FFMpegObject->AVCodecDecodeAudio4();
                    _frameLock->ReleaseMutex();

                    if (audioFrameFinished)
                    {
                        if (!_isPaused) // If paused and AFAP playback, just don't call the callback
                        {
                            // Fire the event - leaving it up to video to do the sleeps -- not sure if that will work or not
                            AudioFrameFinished(this, EventArgs::Empty);
                        }
                    }
                }

                _FFMpegObject->AVFreeFramePacket();

            }
            else // failed to read an AV packet
            {
                _sequentialFailedReadCount++;
                _failedReadCount++;
                Thread::Sleep(READ_FAILED_WAIT_TIME);
            }
        }
    }

0 个答案:

没有答案