Воспроизведение аудио FFMPEG с помощью NAudio имеет много шума - PullRequest
0 голосов
/ 28 августа 2018

У меня есть видео, которое я пытаюсь воспроизвести с использованием инфраструктуры 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);
            }
        }
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...