@@ -667,38 +667,131 @@ pub async fn spawn_decoder(
667667
668668 #[ cfg( target_os = "windows" ) ]
669669 {
670- let _ = force_ffmpeg;
671- let ( ready_tx, ready_rx) = oneshot:: channel :: < Result < DecoderInitResult , String > > ( ) ;
672- let ( tx, rx) = mpsc:: channel ( ) ;
670+ if force_ffmpeg {
671+ info ! (
672+ "Video '{}' using FFmpeg decoder (forced via experimental setting)" ,
673+ name
674+ ) ;
675+ let ( ready_tx, ready_rx) = oneshot:: channel :: < Result < DecoderInitResult , String > > ( ) ;
676+ let ( tx, rx) = mpsc:: channel ( ) ;
673677
674- ffmpeg:: FfmpegDecoder :: spawn ( name, path, fps, rx, ready_tx)
675- . map_err ( |e| format ! ( "'{name}' FFmpeg decoder / {e}" ) ) ?;
678+ ffmpeg:: FfmpegDecoder :: spawn ( name, path, fps, rx, ready_tx)
679+ . map_err ( |e| format ! ( "'{name}' FFmpeg decoder / {e}" ) ) ?;
676680
677- match tokio:: time:: timeout ( timeout_duration, ready_rx) . await {
678- Ok ( Ok ( Ok ( init_result) ) ) => {
679- info ! (
680- "Video '{}' using {} decoder ({}x{})" ,
681- name, init_result. decoder_type, init_result. width, init_result. height
681+ return match tokio:: time:: timeout ( timeout_duration, ready_rx) . await {
682+ Ok ( Ok ( Ok ( init_result) ) ) => {
683+ info ! (
684+ "Video '{}' using {} decoder ({}x{})" ,
685+ name, init_result. decoder_type, init_result. width, init_result. height
686+ ) ;
687+ let status = DecoderStatus {
688+ decoder_type : init_result. decoder_type ,
689+ video_width : init_result. width ,
690+ video_height : init_result. height ,
691+ fallback_reason : None ,
692+ } ;
693+ Ok ( AsyncVideoDecoderHandle {
694+ sender : tx,
695+ offset,
696+ status,
697+ } )
698+ }
699+ Ok ( Ok ( Err ( e) ) ) => Err ( format ! (
700+ "'{name}' FFmpeg decoder initialization failed: {e}"
701+ ) ) ,
702+ Ok ( Err ( e) ) => Err ( format ! ( "'{name}' FFmpeg decoder channel closed: {e}" ) ) ,
703+ Err ( _) => Err ( format ! (
704+ "'{name}' FFmpeg decoder timed out after 30s initializing: {path_display}"
705+ ) ) ,
706+ } ;
707+ }
708+
709+ let mf_result = {
710+ let ( ready_tx, ready_rx) = oneshot:: channel :: < Result < DecoderInitResult , String > > ( ) ;
711+ let ( tx, rx) = mpsc:: channel ( ) ;
712+
713+ match media_foundation:: MFDecoder :: spawn ( name, path. clone ( ) , fps, rx, ready_tx) {
714+ Ok ( ( ) ) => match tokio:: time:: timeout ( timeout_duration, ready_rx) . await {
715+ Ok ( Ok ( Ok ( init_result) ) ) => {
716+ info ! (
717+ "Video '{}' using {} decoder ({}x{})" ,
718+ name, init_result. decoder_type, init_result. width, init_result. height
719+ ) ;
720+ let status = DecoderStatus {
721+ decoder_type : init_result. decoder_type ,
722+ video_width : init_result. width ,
723+ video_height : init_result. height ,
724+ fallback_reason : None ,
725+ } ;
726+ Ok ( AsyncVideoDecoderHandle {
727+ sender : tx,
728+ offset,
729+ status,
730+ } )
731+ }
732+ Ok ( Ok ( Err ( e) ) ) => Err ( format ! (
733+ "'{name}' MediaFoundation initialization failed: {e} ({path_display})"
734+ ) ) ,
735+ Ok ( Err ( e) ) => Err ( format ! (
736+ "'{name}' MediaFoundation channel closed: {e} ({path_display})"
737+ ) ) ,
738+ Err ( _) => Err ( format ! (
739+ "'{name}' MediaFoundation timed out after 30s initializing: {path_display}"
740+ ) ) ,
741+ } ,
742+ Err ( e) => Err ( format ! (
743+ "'{name}' MediaFoundation spawn failed: {e} ({path_display})"
744+ ) ) ,
745+ }
746+ } ;
747+
748+ match mf_result {
749+ Ok ( handle) => Ok ( handle) ,
750+ Err ( mf_error) => {
751+ tracing:: warn!(
752+ name = name,
753+ error = %mf_error,
754+ "MediaFoundation failed, falling back to FFmpeg decoder"
682755 ) ;
683- let status = DecoderStatus {
684- decoder_type : init_result. decoder_type ,
685- video_width : init_result. width ,
686- video_height : init_result. height ,
687- fallback_reason : None ,
688- } ;
689- Ok ( AsyncVideoDecoderHandle {
690- sender : tx,
691- offset,
692- status,
693- } )
756+
757+ let ( ready_tx, ready_rx) = oneshot:: channel :: < Result < DecoderInitResult , String > > ( ) ;
758+ let ( tx, rx) = mpsc:: channel ( ) ;
759+
760+ if let Err ( e) = ffmpeg:: FfmpegDecoder :: spawn ( name, path, fps, rx, ready_tx) {
761+ return Err ( format ! (
762+ "'{name}' decoder failed - MediaFoundation: {mf_error}, FFmpeg: {e}"
763+ ) ) ;
764+ }
765+
766+ match tokio:: time:: timeout ( timeout_duration, ready_rx) . await {
767+ Ok ( Ok ( Ok ( init_result) ) ) => {
768+ info ! (
769+ "Video '{}' using {} decoder ({}x{}) after MediaFoundation failure" ,
770+ name, init_result. decoder_type, init_result. width, init_result. height
771+ ) ;
772+ let status = DecoderStatus {
773+ decoder_type : init_result. decoder_type ,
774+ video_width : init_result. width ,
775+ video_height : init_result. height ,
776+ fallback_reason : Some ( mf_error) ,
777+ } ;
778+ Ok ( AsyncVideoDecoderHandle {
779+ sender : tx,
780+ offset,
781+ status,
782+ } )
783+ }
784+ Ok ( Ok ( Err ( e) ) ) => Err ( format ! (
785+ "'{name}' decoder failed - MediaFoundation: {mf_error}, FFmpeg: {e}"
786+ ) ) ,
787+ Ok ( Err ( e) ) => Err ( format ! (
788+ "'{name}' decoder failed - MediaFoundation: {mf_error}, FFmpeg channel: {e}"
789+ ) ) ,
790+ Err ( _) => Err ( format ! (
791+ "'{name}' decoder failed - MediaFoundation: {mf_error}, FFmpeg timed out"
792+ ) ) ,
793+ }
694794 }
695- Ok ( Ok ( Err ( e) ) ) => Err ( format ! (
696- "'{name}' FFmpeg decoder initialization failed: {e}"
697- ) ) ,
698- Ok ( Err ( e) ) => Err ( format ! ( "'{name}' FFmpeg decoder channel closed: {e}" ) ) ,
699- Err ( _) => Err ( format ! (
700- "'{name}' FFmpeg decoder timed out after 30s initializing: {path_display}"
701- ) ) ,
702795 }
703796 }
704797
0 commit comments