diff --git a/Unosquare.FFME.Windows.Sample/MainWindow.MediaEvents.cs b/Unosquare.FFME.Windows.Sample/MainWindow.MediaEvents.cs index c82c43fe..aa05a95b 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 a5988c4f..edced8bb 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 05bfcdbd..7a50985d 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 e4dd49ea..c490fe3a 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 8643f1da..42a14ac7 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; } ///