我正在尝试使用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);
}
}
}