@@ -392,8 +392,28 @@ impl DecoderInit {
392392            Ok ( ( ) )  => { 
393393                self . first_frame  = match  frame. format ( )  { 
394394                    ffmpeg:: format:: Pixel :: VIDEOTOOLBOX  => { 
395+                         let  sw_format = unsafe  { 
396+                             let  ctx_ref = ( * self . decoder . as_ptr ( ) ) . hw_frames_ctx ; 
397+                             assert ! ( !ctx_ref. is_null( ) ) ; 
398+ 
399+                             let  mut  transfer_fmt_list = std:: ptr:: null_mut ( ) ; 
400+                             if  ffmpeg_sys:: av_hwframe_transfer_get_formats ( 
401+                             ctx_ref, 
402+                             ffmpeg_sys:: AVHWFrameTransferDirection :: AV_HWFRAME_TRANSFER_DIRECTION_FROM , 
403+                             & mut  transfer_fmt_list, 
404+                             0 )  < 0 
405+                                 { 
406+                                     bail ! ( "call to av_hwframe_transfer_get_formats failed" ) ; 
407+                                 } ; 
408+ 
409+                             let  transfer_formats = read_format_list ( transfer_fmt_list) ; 
410+                             assert ! ( !transfer_formats. is_empty( ) ) ; 
411+ 
412+                             transfer_formats[ 0 ] 
413+                         } ; 
414+ 
395415                        let  mut  sw_frame = ffmpeg:: frame:: Video :: new ( 
396-                             ffmpeg :: format :: Pixel :: P010LE ,   // xxx 
416+                             sw_format , 
397417                            self . decoder . width ( ) , 
398418                            self . decoder . height ( ) , 
399419                        ) ; 
@@ -1025,38 +1045,51 @@ fn copy_frame(
10251045#[ no_mangle]  
10261046unsafe  extern  "C"  fn  get_hw_format_videotoolbox ( 
10271047    ctx :  * mut  ffmpeg_sys:: AVCodecContext , 
1028-     mut   formats :  * const  ffmpeg_sys:: AVPixelFormat , 
1048+     list :  * const  ffmpeg_sys:: AVPixelFormat , 
10291049)  -> ffmpeg_sys:: AVPixelFormat  { 
10301050    use  ffmpeg_sys:: AVPixelFormat :: * ; 
10311051
1032-     while  * formats != AV_PIX_FMT_NONE  { 
1033-         if  * formats == AV_PIX_FMT_VIDEOTOOLBOX  { 
1034-             let  frames_ctx_ref = ffmpeg_sys:: av_hwframe_ctx_alloc ( ( * ctx) . hw_device_ctx ) ; 
1035-             if  frames_ctx_ref. is_null ( )  { 
1036-                 error ! ( "call to av_hwframe_ctx_alloc failed" ) ; 
1037-                 break ; 
1038-             } 
1052+     let  sw_pix_fmt = ( * ctx) . sw_pix_fmt ; 
1053+     let  formats = read_format_list ( list) ; 
1054+ 
1055+     if  formats. contains ( & ffmpeg:: format:: Pixel :: VIDEOTOOLBOX )  { 
1056+         let  frames_ctx_ref = ffmpeg_sys:: av_hwframe_ctx_alloc ( ( * ctx) . hw_device_ctx ) ; 
1057+         if  frames_ctx_ref. is_null ( )  { 
1058+             error ! ( "call to av_hwframe_ctx_alloc failed" ) ; 
1059+             return  sw_pix_fmt; 
1060+         } 
10391061
1040-             let  frames_ctx = ( * frames_ctx_ref) . data  as  * mut  ffmpeg_sys:: AVHWFramesContext ; 
1041-             ( * frames_ctx) . width  = ( * ctx) . width ; 
1042-             ( * frames_ctx) . height  = ( * ctx) . height ; 
1043-             ( * frames_ctx) . format  = AV_PIX_FMT_VIDEOTOOLBOX ; 
1044-             ( * frames_ctx) . sw_format  = ( * ctx) . sw_pix_fmt ; 
1062+         debug ! ( ?formats,  sw_pix_fmt = ?sw_pix_fmt,  "get_hw_format_videotoolbox" ) ; 
10451063
1046-              let  res =  ffmpeg_sys:: av_hwframe_ctx_init ( frames_ctx_ref ) ; 
1047-              if  res <  0   { 
1048-                  error ! ( "call to av_hwframe_ctx_init failed" ) ; 
1049-                  break ; 
1050-              } 
1064+         let  frames_ctx =  ( * frames_ctx_ref ) . data   as   * mut   ffmpeg_sys:: AVHWFramesContext ; 
1065+         ( * frames_ctx ) . width  =  ( * ctx ) . width ; 
1066+         ( * frames_ctx ) . height  =  ( * ctx ) . height ; 
1067+         ( * frames_ctx ) . format  =  AV_PIX_FMT_VIDEOTOOLBOX ; 
1068+         ( * frames_ctx ) . sw_format  =  AV_PIX_FMT_YUV420P ; 
10511069
1052-             debug ! ( "using VideoToolbox hardware encoder" ) ; 
1053-             ( * ctx) . hw_frames_ctx  = frames_ctx_ref; 
1054-             return  * formats; 
1070+         let  res = ffmpeg_sys:: av_hwframe_ctx_init ( frames_ctx_ref) ; 
1071+         if  res < 0  { 
1072+             error ! ( "call to av_hwframe_ctx_init failed" ) ; 
1073+             return  sw_pix_fmt; 
10551074        } 
10561075
1057-         formats = formats. add ( 1 ) ; 
1076+         debug ! ( "using VideoToolbox hardware encoder" ) ; 
1077+         ( * ctx) . hw_frames_ctx  = frames_ctx_ref; 
1078+         return  AV_PIX_FMT_VIDEOTOOLBOX ; 
1079+     } 
1080+ 
1081+     warn ! ( "unable to determine ffmpeg hw format" ) ; 
1082+     sw_pix_fmt
1083+ } 
1084+ 
1085+ unsafe  fn  read_format_list ( 
1086+     mut  ptr :  * const  ffmpeg_sys:: AVPixelFormat , 
1087+ )  -> Vec < ffmpeg:: format:: Pixel >  { 
1088+     let  mut  formats = Vec :: new ( ) ; 
1089+     while  !ptr. is_null ( )  && * ptr != ffmpeg_sys:: AVPixelFormat :: AV_PIX_FMT_NONE  { 
1090+         formats. push ( ( * ptr) . into ( ) ) ; 
1091+         ptr = ptr. add ( 1 ) ; 
10581092    } 
10591093
1060-     warn ! ( "VideoToolbox setup failed, falling back to CPU decoder" ) ; 
1061-     AV_PIX_FMT_YUV420P10LE 
1094+     formats
10621095} 
0 commit comments