FFMediaToolkit icon indicating copy to clipboard operation
FFMediaToolkit copied to clipboard

Cannot handle exception when extract frame and encode video

Open huyphamquang opened this issue 3 years ago • 3 comments

I use this package to do some video task like extract frame and remake video from frame image. My code sometime raise exception like below. I try to add try-catch block to handle it but no luck. Pls show me how to handle exception from ffmpeg lib.

Exception info: System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt. at FFMediaToolkit.Decoding.Internal.InputContainer.ReadPacket() in C:\projects\ffmediatoolkit\FFMediaToolkit\Decoding\Internal\InputContainer.cs:line 174 at FFMediaToolkit.Decoding.Internal.InputContainer.GetPacketFromStream(Int32 streamIndex) in C:\projects\ffmediatoolkit\FFMediaToolkit\Decoding\Internal\InputContainer.cs:line 90 at FFMediaToolkit.Decoding.Internal.Decoder.DecodePacket() in C:\projects\ffmediatoolkit\FFMediaToolkit\Decoding\Internal\Decoder.cs:line 146 at FFMediaToolkit.Decoding.Internal.Decoder.ReadNextFrame() in C:\projects\ffmediatoolkit\FFMediaToolkit\Decoding\Internal\Decoder.cs:line 136 at FFMediaToolkit.Decoding.VideoStream.GetNextFrame() in C:\projects\ffmediatoolkit\FFMediaToolkit\Decoding\VideoStream.cs:line 51 at FFMediaToolkit.Decoding.VideoStream.TryGetNextFrame(ImageData& bitmap) in C:\projects\ffmediatoolkit\FFMediaToolkit\Decoding\VideoStream.cs:line 68

huyphamquang avatar Mar 12 '21 03:03 huyphamquang

Can you provide a code snippet and the video file? It's a bit hard to tell what's going on from just this

jrz371 avatar Mar 12 '21 07:03 jrz371

here is the source for extract frame:

`[HandleProcessCorruptedStateExceptions] [SecurityCritical] private void timerCallback(object state) { MediaFile file = null; long startTick = DateTime.Now.Ticks; try { //int duration = 1000 / Properties.Settings.Default.FrameProcess; if (PlayListInfo == null || PlayListInfo.Count == 0) return; int idx = 0; bool newVideo = true; TimeSpan endTime = new TimeSpan(); double time_4_frame_ms = 0; while (idx < PlayListInfo.Count && !request_stop) { var startProcess = DateTime.Now; var curVideo = PlayListInfo[idx]; bool firstFrame = false; if (newVideo) { if (file != null) file.Dispose(); startTick = DateTime.Now.Ticks; file = MediaFile.Open(curVideo.fileName); newVideo = false; endTime = curVideo.stopTime < 0 ? file.Info.Duration : TimeSpan.FromSeconds(curVideo.stopTime); if (!file.HasVideo) { Console.WriteLine($"Cannot load video file: {curVideo.fileName}"); } else { Console.WriteLine($"Process video: {curVideo.fileName}, frame rate: {file.Video.Info.AvgFrameRate}"); time_4_frame_ms = file.Video.Info.NumberOfFrames == null ? 0 : file.Video.Info.Duration.TotalMilliseconds / file.Video.Info.NumberOfFrames.Value; firstFrame = true; } } TimeSpan sp = new TimeSpan(DateTime.Now.Ticks - startTick); sp.Add(TimeSpan.FromSeconds(curVideo.startTime <= file.Info.StartTime.TotalSeconds ? file.Info.StartTime.TotalSeconds : curVideo.startTime)); ImageData img; if (sp > endTime) { idx++; newVideo = true; continue; } if (file != null && file.HasVideo) { var t1 = DateTime.Now; bool ck = false; if (firstFrame) { ck = file.Video.TryGetFrame(sp, out img); firstFrame = false; } else { do { ck = file.Video.TryGetNextFrame(out img); } while (ck && file.Video.Position < sp); } if (!ck) { Console.WriteLine($"Cannot read frame at {sp} of {curVideo.fileName}"); idx++; newVideo = true; continue; } else using (var bitmap = ToBitmap(img)) { var frametime = DateTime.Now - t1; //Console.WriteLine($"Take {frametime.TotalMilliseconds} to extract frame of {curVideo.fileName}"); // dataShare.WriteFrameData(img.ImageSize.Width, img.ImageSize.Height, //DataUtils.PixelFormatToBitCount(bitmap.PixelFormat), img.Data.ToArray()); if (checkBlankFrame(bitmap)) { Console.WriteLine($"Found black frame at {sp} of {curVideo.fileName}"); } else ProcessFrame(bitmap); } } var processTime = DateTime.Now - startProcess; //Console.WriteLine($"Process time of {curVideo.fileName}: {processTime.TotalMilliseconds}/ms"); int sleeptime = (int)(time_4_frame_ms - processTime.TotalMilliseconds); if (sleeptime > 0) System.Threading.Thread.Sleep(sleeptime); } } catch (AccessViolationException ex) { Console.WriteLine(ex.ToString()); } catch {

        }

        finally
        {
            if (file != null)
            {
                try
                {
                    file.Dispose();
                }
                catch
                {

                }
                file = null;
            }
        }

    }`

here is the source code for making video from bitmap: `private unsafe void PushFrame(Bitmap bitmap) { try { lock (this) { var data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb); try { int len = data.Stride * data.Height; byte[] bitmapData = new byte[len]; Marshal.Copy(data.Scan0, bitmapData, 0, len); if (frameList.Count == 0) startTime = DateTime.Now.Ticks; frameList.Add(bitmapData); } finally { bitmap.UnlockBits(data); } //ImageData data = VideoProcessEx.ToImageData(bitmap); //mediaFile.Video.AddFrame(data); TimeSpan sp = new TimeSpan(DateTime.Now.Ticks - startTime); if (sp.TotalSeconds >= Properties.Settings.Default.LiveVideoDuration) { if (frameList.Count == 0) return; videoCount++; videoIndex = videoCount % 10;

                    var settings = new VideoEncoderSettings(width: bitmap.Width, height: bitmap.Height,
                        framerate: (int)(frameList.Count / sp.TotalSeconds), codec: VideoCodec.H264);
                    settings.EncoderPreset = EncoderPreset.Fast;
                    settings.CRF = 17;
                    //settings.VideoFormat = ImagePixelFormat.Rgb24;
                    string path = $"{VideoFolder}\\{videoIndex}.{videoExt}";
                    using (var mediaFile = MediaBuilder.CreateContainer(path)/*.UseFormatOption("g", "10").UseFormatOption("movflags", "frag_keyframe+empty_moov")*/.WithVideo(settings).Create())
                    {
                        Console.WriteLine($"create video: {MappingFile}.{videoIndex}.{videoExt} -- duration: {sp.TotalSeconds}, total frame: {frameList.Count}");
                        foreach (var item in frameList)
                        {
                            Span<byte> imgData = new Span<byte>(item, 0, item.Length);
                            //return new ImageData(imgData, ImagePixelFormat.Rgb24, bitmap.Size);
                            mediaFile.Video.AddFrame(new ImageData(imgData, ImagePixelFormat.Bgr24, bitmap.Size));
                            
                            //mediaFile.Video.Configuration.Framerate = (int)(mediaFile.Video.FramesCount / sp.TotalSeconds);
                        }
                        AddFileToPlayList(videoCount, $"{videoIndex}.{videoExt}", (decimal)sp.TotalSeconds);
                        //Task.Delay((int)(2) * 1000)
                        //    .ContinueWith((t) =>
                        //    {

                        //        AddFileToPlayList(videoCount, $"{videoIndex}.{videoExt}", (decimal)sp.TotalSeconds);
                        //    });
                    }
                    frameList.Clear();
                }
            }
        }
        catch(Exception ex)
        {
            Console.WriteLine(ex.ToString());
        }
    }`

huyphamquang avatar Mar 12 '21 07:03 huyphamquang

my application process a list of video file and that exeption occur ramdom, i'm not sure about the reson but I only want to catch if it raise exception

huyphamquang avatar Mar 12 '21 07:03 huyphamquang