From 6ceff206c9b845d7bb160b89f8c06e06674dd655 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zavark=C3=B3=20G=C3=A1bor?= Date: Wed, 26 Jun 2024 21:10:24 +0200 Subject: [PATCH] remove setting of the seekable field (#663) * remove setting of the seekable field remove setting of the seekable field, since it causes access violation errors, and unnecessary. Check the comment from june 6, 2023: https://github.com/unosquare/ffmediaelement/issues/642 Or: https://github.com/Ruslan-B/FFmpeg.AutoGen/issues/255 Currently I'm uusing my own package, but I'd liek to swicth your original version, but this issue block me. Reproduce the issue: Just open any local video file with the following url: customfile://C:\myfolder\myfile.mkv It will use the FileInputStream which sets the seekable field. => access violation when trying to open the media. * fix the hw acceleration * using fix --- .../MainWindow.MediaEvents.cs | 9 ++-- Unosquare.FFME/Common/MediaOptions.cs | 2 +- Unosquare.FFME/Container/MediaComponent.cs | 2 +- Unosquare.FFME/Container/MediaContainer.cs | 3 -- Unosquare.FFME/Container/VideoComponent.cs | 48 ++++++++++--------- 5 files changed, 33 insertions(+), 31 deletions(-) diff --git a/Unosquare.FFME.Windows.Sample/MainWindow.MediaEvents.cs b/Unosquare.FFME.Windows.Sample/MainWindow.MediaEvents.cs index c82c43fee..aa05a95bf 100644 --- a/Unosquare.FFME.Windows.Sample/MainWindow.MediaEvents.cs +++ b/Unosquare.FFME.Windows.Sample/MainWindow.MediaEvents.cs @@ -3,6 +3,7 @@ using ClosedCaptions; using FFmpeg.AutoGen; using System; + using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; @@ -286,16 +287,16 @@ private async void OnMediaOpening(object sender, MediaOpeningEventArgs e) // Hardware device selection if (videoStream.FPS <= 30) { + var devices = new List(deviceCandidates.Length); foreach (var deviceType in deviceCandidates) { var accelerator = videoStream.HardwareDevices.FirstOrDefault(d => d.DeviceType == deviceType); if (accelerator == null) continue; - if (Debugger.IsAttached) - e.Options.VideoHardwareDevice = accelerator; - - break; + devices.Add(accelerator); } + + e.Options.VideoHardwareDevices = devices.ToArray(); } // Start building a video filter diff --git a/Unosquare.FFME/Common/MediaOptions.cs b/Unosquare.FFME/Common/MediaOptions.cs index a5988c4fa..edced8bbf 100644 --- a/Unosquare.FFME/Common/MediaOptions.cs +++ b/Unosquare.FFME/Common/MediaOptions.cs @@ -43,7 +43,7 @@ internal MediaOptions() /// Use Stream's HardwareDevices property to get a list of /// compatible hardware accelerators. /// - public HardwareDeviceInfo VideoHardwareDevice { get; set; } + public HardwareDeviceInfo[] VideoHardwareDevices { get; set; } /// /// Prevent reading from audio stream components. diff --git a/Unosquare.FFME/Container/MediaComponent.cs b/Unosquare.FFME/Container/MediaComponent.cs index 05bfcdbdc..7a50985d4 100644 --- a/Unosquare.FFME/Container/MediaComponent.cs +++ b/Unosquare.FFME/Container/MediaComponent.cs @@ -167,7 +167,7 @@ protected MediaComponent(MediaContainer container, int streamIndex) codecOptions.SetCopyOpaque(); // Enable Hardware acceleration if requested - (this as VideoComponent)?.AttachHardwareDevice(container.MediaOptions.VideoHardwareDevice); + (this as VideoComponent)?.AttachHardwareDevice(container.MediaOptions.VideoHardwareDevices); // Open the CodecContext. This requires exclusive FFmpeg access lock (CodecLock) diff --git a/Unosquare.FFME/Container/MediaContainer.cs b/Unosquare.FFME/Container/MediaContainer.cs index e4dd49ea8..c490fe3a0 100644 --- a/Unosquare.FFME/Container/MediaContainer.cs +++ b/Unosquare.FFME/Container/MediaContainer.cs @@ -682,9 +682,6 @@ private void StreamInitialize() CustomInputStreamContext = ffmpeg.avio_alloc_context( inputBuffer, CustomInputStream.ReadBufferLength, 0, null, CustomInputStreamRead, null, CustomInputStreamSeek); - // Set the seekable flag based on the custom input stream implementation - CustomInputStreamContext->seekable = CustomInputStream.CanSeek ? ffmpeg.AVIO_SEEKABLE_NORMAL : 0; - // Assign the AVIOContext to the input context inputContextPtr->pb = CustomInputStreamContext; } diff --git a/Unosquare.FFME/Container/VideoComponent.cs b/Unosquare.FFME/Container/VideoComponent.cs index 8643f1da3..42a14ac72 100644 --- a/Unosquare.FFME/Container/VideoComponent.cs +++ b/Unosquare.FFME/Container/VideoComponent.cs @@ -157,37 +157,41 @@ internal VideoComponent(MediaContainer container, int streamIndex) /// /// Attaches a hardware accelerator to this video component. /// - /// The selected configuration. + /// The selected configurations. /// /// Whether or not the hardware accelerator was attached. /// - public bool AttachHardwareDevice(HardwareDeviceInfo selectedConfig) + public bool AttachHardwareDevice(HardwareDeviceInfo[] selectedConfigs) { // Check for no device selection - if (selectedConfig == null) + if (selectedConfigs == null || selectedConfigs.Length == 0) return false; - try - { - var accelerator = new HardwareAccelerator(this, selectedConfig); - - AVBufferRef* devContextRef = null; - var initResultCode = ffmpeg.av_hwdevice_ctx_create(&devContextRef, accelerator.DeviceType, null, null, 0); - if (initResultCode < 0) - throw new MediaContainerException($"Unable to initialize hardware context for device {accelerator.Name}"); - - HardwareDeviceContext = devContextRef; - HardwareAccelerator = accelerator; - CodecContext->hw_device_ctx = ffmpeg.av_buffer_ref(HardwareDeviceContext); - CodecContext->get_format = accelerator.GetFormatCallback; - - return true; - } - catch (Exception ex) + foreach (var selectedConfig in selectedConfigs) { - this.LogError(Aspects.Component, "Could not attach hardware decoder.", ex); - return false; + try + { + AVBufferRef* devContextRef = null; + var initResultCode = ffmpeg.av_hwdevice_ctx_create(&devContextRef, selectedConfig.DeviceType, null, null, 0); + if (initResultCode < 0) + continue; + + var accelerator = new HardwareAccelerator(this, selectedConfig); + HardwareDeviceContext = devContextRef; + HardwareAccelerator = accelerator; + CodecContext->hw_device_ctx = ffmpeg.av_buffer_ref(HardwareDeviceContext); + CodecContext->get_format = accelerator.GetFormatCallback; + + return true; + } + catch (Exception ex) + { + this.LogError(Aspects.Component, "Could not attach hardware decoder.", ex); + } } + + this.LogError(Aspects.Component, "Could not attach any hardware decoder."); + return false; } ///