@@ -17,6 +17,8 @@ public class BH_VideoEncoder
1717 private int maxSegments = 6 ; // Number of segments to keep (covering 60 seconds)
1818 private CircularBuffer < string > errorBuffer = new CircularBuffer < string > ( 256 ) ; // Circular buffer for stderr
1919
20+ private string _functionalEncoder = null ;
21+
2022 private byte [ ] lastFrame ;
2123 private float frameInterval ;
2224
@@ -276,15 +278,65 @@ private void CleanupSegments()
276278 }
277279 }
278280
279- private static string FindPreferredEncoder ( )
281+ private string FindPreferredEncoder ( )
282+ {
283+ string [ ] encoders = FindAvailableEncoders ( ) ;
284+ if ( ! string . IsNullOrEmpty ( _functionalEncoder ) && encoders . Contains ( _functionalEncoder ) )
285+ {
286+ return _functionalEncoder ;
287+ }
288+
289+ // execute ffmpeg -f lavfi -i nullsrc=d=1 -c:v h264_nvenc -t 1 -f null - for each encoder on the list,
290+ // exit code 0 menas the encoder is available
291+
292+ string ffmpegPath = GetFfmpegPath ( ) ;
293+ if ( ffmpegPath == null )
294+ {
295+ return encoders [ encoders . Length - 1 ] ;
296+ }
297+
298+ foreach ( var encoder in encoders )
299+ {
300+ UnityEngine . Debug . Log ( $ "Checking encoder: { encoder } ") ;
301+
302+ var process = new Process ( ) ;
303+ process . StartInfo . FileName = ffmpegPath ;
304+ process . StartInfo . Arguments = $ "-f lavfi -i nullsrc=d=1 -c:v { encoder } -t 1 -f null -";
305+ process . StartInfo . UseShellExecute = false ;
306+ process . StartInfo . RedirectStandardOutput = true ;
307+ process . StartInfo . CreateNoWindow = true ;
308+ process . Start ( ) ;
309+
310+ process . WaitForExit ( ) ;
311+
312+ if ( process . ExitCode == 0 )
313+ {
314+ UnityEngine . Debug . Log ( $ "Encoder { encoder } is available.") ;
315+ _functionalEncoder = encoder ;
316+
317+ return encoder ;
318+ }
319+ else
320+ {
321+ UnityEngine . Debug . Log ( $ "Encoder { encoder } is not available.") ;
322+ }
323+ }
324+
325+ return encoders [ encoders . Length - 1 ] ;
326+ }
327+
328+ // It returns the preferred encoder based on the available encoders in order of preference
329+ private static string [ ] FindAvailableEncoders ( )
280330 {
331+ List < string > encoders = new List < string > ( ) ;
332+
281333 // Run ffmpeg to get the list of available encoders
282334 var process = new Process ( ) ;
283335
284336 string ffmpegPath = GetFfmpegPath ( ) ;
285337 if ( ffmpegPath == null )
286338 {
287- return "libx264" ;
339+ return encoders . ToArray ( ) ;
288340 }
289341
290342 process . StartInfo . FileName = ffmpegPath ;
@@ -300,21 +352,28 @@ private static string FindPreferredEncoder()
300352 // Check for specific hardware encoders in the output
301353 if ( output . Contains ( "h264_nvenc" ) )
302354 {
303- return "h264_nvenc" ;
355+ encoders . Add ( "h264_nvenc" ) ;
304356 }
305- else if ( output . Contains ( "h264_videotoolbox" ) )
357+
358+ if ( output . Contains ( "h264_amf" ) )
306359 {
307- return "h264_videotoolbox" ;
360+ encoders . Add ( "h264_amf" ) ;
308361 }
309- else if ( output . Contains ( "h264_vaapi" ) )
362+
363+ if ( output . Contains ( "h264_videotoolbox" ) )
310364 {
311- return "h264_vaapi" ;
365+ encoders . Add ( "h264_videotoolbox" ) ;
312366 }
313- else
367+
368+ if ( output . Contains ( "h264_vaapi" ) )
314369 {
315- // Default to software encoding if no hardware encoder is found
316- return "libx264" ;
370+ encoders . Add ( "h264_vaapi" ) ;
317371 }
372+
373+ // Always add libx264 as a fallback
374+ encoders . Add ( "libx264" ) ;
375+
376+ return encoders . ToArray ( ) ;
318377 }
319378
320379 // It returns the fastest preset for the given encoder
0 commit comments