accord-net / framework

Machine learning, computer vision, statistics and general scientific computing for .NET
http://accord-framework.net
GNU Lesser General Public License v2.1
4.49k stars 1.99k forks source link

VideoFileWriter WriteAudioFrame AccessViolationException #1428

Open yarus opened 6 years ago

yarus commented 6 years ago

Hi all, I am trying to record video from my webcam and add audio from my speaker to this video during recording. I used Screen Capture sample as a base for my code. The difference is that i need to write video file directly from my camera and not from desktop. So i used VideoCaptureDevice with camera GUID and NewFrame event handler to write video frames. For audio frames - i do the same thing like in sample app - using NewFrame event handler from mixer to write Signal with videoWriter.

The video part works well, but audio recording failing after some time with the following exception: System.AccessViolationException: 'Attempted to read or write protected memory. This is often an indication that other memory is corrupt.'

I am not sure how to properly initialize AudioDevice and Mixer with things like FrameSize, BitRate.

Could you guys please help to figure this out?

I see the following logs in console:

Exception thrown: 'Accord.Video.VideoException' in Accord.Video.FFMPEG.dll
pts:5.874000e+003   pts_time:193.842    dts:2.937000e+003   dts_time:96.921 duration:1.000000e+000  duration_time:0.033 stream_index:0
pts:5.876000e+003   pts_time:193.908    dts:2.938000e+003   dts_time:96.954 duration:1.000000e+000  duration_time:0.033 stream_index:0
pts:5.878000e+003   pts_time:193.974    dts:2.939000e+003   dts_time:96.987 duration:1.000000e+000  duration_time:0.033 stream_index:0
pts:5.880000e+003   pts_time:194.04 dts:2.940000e+003   dts_time:97.02  duration:1.000000e+000  duration_time:0.033 stream_index:0
pts:5.882000e+003   pts_time:194.106    dts:2.941000e+003   dts_time:97.053 duration:1.000000e+000  duration_time:0.033 stream_index:0
pts:5.886000e+003   pts_time:194.238    dts:2.943000e+003   dts_time:97.119 duration:1.000000e+000  duration_time:0.033 stream_index:0
pts:5.888000e+003   pts_time:194.304    dts:2.944000e+003   dts_time:97.152 duration:1.000000e+000  duration_time:0.033 stream_index:0
pts:5.890000e+003   pts_time:194.37 dts:2.945000e+003   dts_time:97.185 duration:1.000000e+000  duration_time:0.033 stream_index:0
pts:5.892000e+003   pts_time:194.436    dts:2.946000e+003   dts_time:97.218 duration:1.000000e+000  duration_time:0.033 stream_index:0
pts:5.894000e+003   pts_time:194.502    dts:2.947000e+003   dts_time:97.251 duration:1.000000e+000  duration_time:0.033 stream_index:0
pts:5.896000e+003   pts_time:194.568    dts:2.948000e+003   dts_time:97.284 duration:1.000000e+000  duration_time:0.033 stream_index:0
pts:5.898000e+003   pts_time:194.634    dts:2.949000e+003   dts_time:97.317 duration:1.000000e+000  duration_time:0.033 stream_index:0
pts:5.900000e+003   pts_time:194.7  dts:2.950000e+003   dts_time:97.35  duration:1.000000e+000  duration_time:0.033 stream_index:0
pts:5.902000e+003   pts_time:194.766    dts:2.951000e+003   dts_time:97.383 duration:1.000000e+000  duration_time:0.033 stream_index:0
pts:5.904000e+003   pts_time:194.832    dts:2.952000e+003   dts_time:97.416 duration:1.000000e+000  duration_time:0.033 stream_index:0
pts:5.904000e+003   pts_time:194.832    dts:2.952000e+003   dts_time:97.416 duration:1.000000e+000  duration_time:0.033 stream_index:0
Exception thrown: 'Accord.Video.VideoException' in Accord.Video.FFMPEG.dll
Exception thrown: 'System.AccessViolationException' in Accord.Video.FFMPEG.dll
An unhandled exception of type 'System.AccessViolationException' occurred in Accord.Video.FFMPEG.dll
Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

Time when this happens is different. Sometimes app can record 1-2 minutes, but sometimes not more than 15 seconds.

The code where error happening is the following:

    private void _audioMixer_NewFrame(object sender, Accord.Audio.NewFrameEventArgs e)
        {
            if (IsRecording)
            {
                lock (_syncObj) // Save the frame to the video file.
                {
                    _videoWriter.WriteAudioFrame(e.Signal);
                }
            }
        }

Audio initializes:

        private void InitRecordingComponents(RecorderConfiguration configuration)
        {
            int audioFrameSize = 4096 * 10;
            int audioBitRate = 1200 * 1000;

            try
            {
                _videoWriter = GetVideoWriter(configuration);

                var res = _videoCaptureDevice.VideoCapabilities.FirstOrDefault(p =>
                    p.FrameSize.Width == configuration.VideoWidth && p.FrameSize.Height == configuration.VideoHeight &&
                    p.AverageFrameRate == configuration.VideoFrameRate);

                if (res != null)
                {
                    _videoCaptureDevice.VideoResolution = res;
                }

                _audioMixer = GetAudioMixer(configuration, audioFrameSize);
                if (_videoWriter != null)
                {
                    if (_audioMixer != null)
                    {
                        AddAudioMixerToVideoWriter(_audioMixer, _videoWriter, audioFrameSize, audioBitRate);
                    }

                    _videoWriter.Open(_fileName);
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                CleanupInternalResources();
            }
        }
       private AudioSourceMixer GetAudioMixer(RecorderConfiguration configuration, int desiredFrameSize)
        {
            if (!configuration.AudioDeviceID.HasValue)
            {
                return null;
            }

            AudioSourceMixer mixer = null;

            // TODO: This code can be adjusted to provide list of audio souces instead of 1 device
            var audioDevices = GetAudioDevices(new List<Guid>{configuration.AudioDeviceID.Value}, desiredFrameSize); 

            if (audioDevices.Count > 0)
            {
                mixer = new AudioSourceMixer(audioDevices);
                mixer.NewFrame += _audioMixer_NewFrame;
                mixer.AudioSourceError += DeviceData_AudioSourceError;
                mixer.Start();
            }

            return mixer;
        }
  private List<AudioCaptureDevice> GetAudioDevices(IEnumerable<Guid> ids, int desiredFrameSize)
        {
            var audioDevices = new List<AudioCaptureDevice>();

            foreach (var id in ids)
            {
                AudioCaptureDevice deviceData = GetAudioDeviceData(id);

                if (deviceData == null)
                {
                    continue;
                }

                deviceData.AudioSourceError += DeviceData_AudioSourceError;
                deviceData.Format = SampleFormat.Format16Bit;
                deviceData.SampleRate = DEFAULT_SAMPLE_RATE;
                deviceData.DesiredFrameSize = desiredFrameSize;
                deviceData.Start();

                audioDevices.Add(deviceData);
            }

            return audioDevices;
        }
       private void AddAudioMixerToVideoWriter(AudioSourceMixer mixer, VideoFileWriter videoWriter, int frameSize, int bitRate)
        {
            videoWriter.AudioBitRate = bitRate;
            videoWriter.AudioCodec = AudioCodec.Aac;
            videoWriter.AudioLayout = mixer.NumberOfChannels == 1 ? AudioLayout.Mono : AudioLayout.Stereo;
            videoWriter.FrameSize = frameSize;
            videoWriter.SampleRate = mixer.SampleRate;
        }
yarus commented 6 years ago

Hey guys, its been a month already since I started this thread. Any updates?

Licymnius commented 6 years ago

Hi, I have the same issue. While I record without timespan in WriteVideoFrame recording goes well. But if I add TimeSpan WriteAudioFrame crashes with 'Protected Memory' exception. Without TimeSpan video captures without synchronisation, framerate floats. I tryed to store Signals in a collection, and write them afterwards, but when I add TimeSpan to WriteAudioFrame it also crashes an exception, that it couldn't write audiostream.

Any sudgestions?

germinton commented 6 years ago

Same issue producable on my side, writing with TimeSpan is necessary, but than the AccessViolation occurs. But I can avoid the problem by synchronising my threads with a lock() Also it looks like the Video/Audio settings, using with VideoWriter, makes any difference. I have no problem with following settings: VideoCodec = Mpeg4; AudioCodec = Aac. Or VideoCodec = Wmv1 and AudioCodec = WmaV1. As fileextension I use mp4/wmv.

yarus commented 6 years ago

Hey, germinton,

As you can see, i use lock when writing to audio stream same as when writing to video stream. Did i missed something?

germinton commented 5 years ago

Ok, it only works without TimeStamp on my side. And when using without TimeStamp, the audio soundtrack is sometimes messy. My consolusion: VideoFileWriter with Audio is not usable/working correctly in any case!

I'm actually trying to record video and audio as separate files, and merge them after recording. But I have no idea to do that, because it seem so, that videofilewriter crashes here too!

MATRIX812010 commented 5 years ago

My consolusion: VideoFileWriter with Audio is not usable/working correctly in any case! @germinton I think so.

jfrank14 commented 5 years ago

Same issue here, except I can't get audio writing to work at all. If I don't specify a codec, no audio is written and the video is silent, and if I do, it causes an Access Violation.

edgar-mtz-e commented 5 years ago

Still getting memory violation

CJHCapture commented 5 years ago

Yes

Thanks,

Christopher CTO Capture Technologies 973.890.7600 x125 capturetechnologies.com


From: edgar-mtz-e notifications@github.com Sent: Thursday, August 15, 2019 4:56:57 PM To: accord-net/framework framework@noreply.github.com Cc: Subscribed subscribed@noreply.github.com Subject: Re: [accord-net/framework] VideoFileWriter WriteAudioFrame AccessViolationException (#1428)

Still getting memory violation

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHubhttps://github.com/accord-net/framework/issues/1428?email_source=notifications&email_token=AMOVCEZO6KFHJYOJIDCYNZDQEW7JTA5CNFSM4FGIZOK2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD4M7H5I#issuecomment-521794549, or mute the threadhttps://github.com/notifications/unsubscribe-auth/AMOVCE3ZQ4C6A5YKORHP4YLQEW7JTANCNFSM4FGIZOKQ.

Confidentiality Warning: This e-mail contains information intended only for the use of the individual or entity named above. If the reader of this e-mail is not the intended recipient or the employee or agent responsible for delivering it to the intended recipient, any dissemination, publication or copying of this e-mail is strictly prohibited. The sender does not accept any responsibility for any loss, disruption or damage to your data or computer system that may occur while using data contained in, or transmitted with, this e-mail. If you have received this e-mail in error, please immediately notify us by return e-mail. Thank you.

zhuchkovdev commented 4 years ago

Has someone found a solution? I have stumbled upon same issue and I'm out of ideas now. Video recording works just fine, but when I add audio results in access violation.

luffyzhao commented 4 years ago

try
start:

videoSource.NewFrame +=

stop:

videoSource.NewFrame -=

rashad-farajullayev commented 4 years ago

I am having the same problem. with the similar source code. Could any of you solve this problem? If I write video frames with timespan, then writing audio frames throws this exception. otherwise video is recorded very well.

Please help if somebody solved this puzzle.