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