@@ -2,7 +2,7 @@ use cap_media_info::{AudioInfo, VideoInfo};
22use  cidre:: { cm:: SampleTimingInfo ,  objc:: Obj ,  * } ; 
33use  ffmpeg:: frame; 
44use  std:: { ops:: Sub ,  path:: PathBuf ,  time:: Duration } ; 
5- use  tracing:: { debug ,  error ,  info ,  trace } ; 
5+ use  tracing:: * ; 
66
77// before pausing at all, subtract 0. 
88// on pause, record last frame time. 
@@ -48,23 +48,23 @@ pub enum InitError {
4848} 
4949
5050#[ derive( thiserror:: Error ,  Debug ) ]  
51- pub  enum  QueueVideoFrameError  { 
51+ pub  enum  QueueFrameError  { 
5252    #[ error( "AppendError/{0}" ) ]  
5353    AppendError ( arc:: R < ns:: Exception > ) , 
5454    #[ error( "Failed" ) ]  
5555    Failed , 
56+     #[ error( "Construct/{0}" ) ]  
57+     Construct ( cidre:: os:: Error ) , 
58+     #[ error( "NotReadyForMore" ) ]  
59+     NotReadyForMore , 
5660} 
5761
5862#[ derive( thiserror:: Error ,  Debug ) ]  
59- pub  enum  QueueAudioFrameError  { 
60-     #[ error( "No audio input" ) ]  
61-     NoAudioInput , 
62-     #[ error( "Not ready" ) ]  
63-     NotReady , 
64-     #[ error( "Setup/{0}" ) ]  
65-     Setup ( cidre:: os:: Error ) , 
66-     #[ error( "AppendError/{0}" ) ]  
67-     AppendError ( & ' static  cidre:: ns:: Exception ) , 
63+ pub  enum  FinishError  { 
64+     #[ error( "NotWriting" ) ]  
65+     NotWriting , 
66+     #[ error( "NoFrames" ) ]  
67+     NoFrames , 
6868    #[ error( "Failed" ) ]  
6969    Failed , 
7070} 
@@ -219,11 +219,15 @@ impl MP4Encoder {
219219        & mut  self , 
220220        frame :  arc:: R < cm:: SampleBuf > , 
221221        timestamp :  Duration , 
222-     )  -> Result < ( ) ,  QueueVideoFrameError >  { 
223-         if  self . is_paused  || ! self . video_input . is_ready_for_more_media_data ( )   { 
222+     )  -> Result < ( ) ,  QueueFrameError >  { 
223+         if  self . is_paused  { 
224224            return  Ok ( ( ) ) ; 
225225        } ; 
226226
227+         if  !self . video_input . is_ready_for_more_media_data ( )  { 
228+             return  Err ( QueueFrameError :: NotReadyForMore ) ; 
229+         } 
230+ 
227231        if  !self . is_writing  { 
228232            self . is_writing  = true ; 
229233            self . asset_writer 
@@ -270,10 +274,7 @@ impl MP4Encoder {
270274        timing. pts  = cm:: Time :: new ( pts_duration. as_millis ( )  as  i64 ,  1_000 ) ; 
271275        let  frame = frame. copy_with_new_timing ( & [ timing] ) . unwrap ( ) ; 
272276
273-         self . video_input 
274-             . append_sample_buf ( & frame) 
275-             . map_err ( |e| QueueVideoFrameError :: AppendError ( e. retained ( ) ) ) 
276-             . and_then ( |v| v. then_some ( ( ) ) . ok_or ( QueueVideoFrameError :: Failed ) ) ?; 
277+         append_sample_buf ( & mut  self . video_input ,  & self . asset_writer ,  & frame) ?; 
277278
278279        self . video_frames_appended  += 1 ; 
279280        self . last_timestamp  = Some ( timestamp) ; 
@@ -285,26 +286,26 @@ impl MP4Encoder {
285286     /// in the timebase of 1 / sample rate 
286287     pub  fn  queue_audio_frame ( 
287288        & mut  self , 
288-         frame :  frame:: Audio , 
289+         frame :  & frame:: Audio , 
289290        timestamp :  Duration , 
290-     )  -> Result < ( ) ,  QueueAudioFrameError >  { 
291+     )  -> Result < ( ) ,  QueueFrameError >  { 
291292        if  self . is_paused  || !self . is_writing  { 
292293            return  Ok ( ( ) ) ; 
293294        } 
294295
296+         let  Some ( audio_input)  = & mut  self . audio_input  else  { 
297+             return  Err ( QueueFrameError :: Failed ) ; 
298+         } ; 
299+ 
295300        if  let  Some ( pause_timestamp)  = self . pause_timestamp 
296301            && let  Some ( gap)  = timestamp. checked_sub ( pause_timestamp) 
297302        { 
298303            self . timestamp_offset  += gap; 
299304            self . pause_timestamp  = None ; 
300305        } 
301306
302-         let  Some ( audio_input)  = & mut  self . audio_input  else  { 
303-             return  Err ( QueueAudioFrameError :: NoAudioInput ) ; 
304-         } ; 
305- 
306307        if  !audio_input. is_ready_for_more_media_data ( )  { 
307-             return  Ok ( ( ) ) ; 
308+             return  Err ( QueueFrameError :: NotReadyForMore ) ; 
308309        } 
309310
310311        let  audio_desc = cat:: audio:: StreamBasicDesc :: common_f32 ( 
@@ -316,11 +317,11 @@ impl MP4Encoder {
316317        let  total_data = frame. samples ( )  *  frame. channels ( )  as  usize  *  frame. format ( ) . bytes ( ) ; 
317318
318319        let  mut  block_buf =
319-             cm:: BlockBuf :: with_mem_block ( total_data,  None ) . map_err ( QueueAudioFrameError :: Setup ) ?; 
320+             cm:: BlockBuf :: with_mem_block ( total_data,  None ) . map_err ( QueueFrameError :: Construct ) ?; 
320321
321322        let  block_buf_slice = block_buf
322323            . as_mut_slice ( ) 
323-             . map_err ( QueueAudioFrameError :: Setup ) ?; 
324+             . map_err ( QueueFrameError :: Construct ) ?; 
324325
325326        if  frame. is_planar ( )  { 
326327            let  mut  offset = 0 ; 
@@ -335,7 +336,7 @@ impl MP4Encoder {
335336        } 
336337
337338        let  format_desc =
338-             cm:: AudioFormatDesc :: with_asbd ( & audio_desc) . map_err ( QueueAudioFrameError :: Setup ) ?; 
339+             cm:: AudioFormatDesc :: with_asbd ( & audio_desc) . map_err ( QueueFrameError :: Construct ) ?; 
339340
340341        let  mut  pts_duration = timestamp
341342            . checked_sub ( self . timestamp_offset ) 
@@ -344,7 +345,7 @@ impl MP4Encoder {
344345        if  let  Some ( last_pts)  = self . last_audio_pts 
345346            && pts_duration <= last_pts
346347        { 
347-             let  frame_duration = Self :: audio_frame_duration ( & frame) ; 
348+             let  frame_duration = Self :: audio_frame_duration ( frame) ; 
348349            let  adjusted_pts = last_pts + frame_duration; 
349350
350351            trace ! ( 
@@ -383,12 +384,9 @@ impl MP4Encoder {
383384            } ] , 
384385            & [ ] , 
385386        ) 
386-         . map_err ( QueueAudioFrameError :: Setup ) ?; 
387+         . map_err ( QueueFrameError :: Construct ) ?; 
387388
388-         audio_input
389-             . append_sample_buf ( & buffer) 
390-             . map_err ( QueueAudioFrameError :: AppendError ) 
391-             . and_then ( |v| v. then_some ( ( ) ) . ok_or ( QueueAudioFrameError :: Failed ) ) ?; 
389+         append_sample_buf ( audio_input,  & self . asset_writer ,  & buffer) ?; 
392390
393391        self . audio_frames_appended  += 1 ; 
394392        self . last_timestamp  = Some ( timestamp) ; 
@@ -449,13 +447,14 @@ impl MP4Encoder {
449447        self . is_paused  = false ; 
450448    } 
451449
452-     pub  fn  finish ( & mut  self ,  timestamp :  Option < Duration > )  { 
450+     pub  fn  finish ( & mut  self ,  timestamp :  Option < Duration > )  ->  Result < ( ) ,   FinishError >   { 
453451        if  !self . is_writing  { 
454-             return ; 
452+             return   Err ( FinishError :: NotWriting ) ; 
455453        } 
456454
457455        let  Some ( mut  most_recent_frame)  = self . most_recent_frame . take ( )  else  { 
458-             return ; 
456+             warn ! ( "Encoder attempted to finish with no frame" ) ; 
457+             return  Err ( FinishError :: NoFrames ) ; 
459458        } ; 
460459
461460        // We extend the video to the provided timestamp if possible 
@@ -489,16 +488,17 @@ impl MP4Encoder {
489488        debug ! ( "Appended {} video frames" ,  self . video_frames_appended) ; 
490489        debug ! ( "Appended {} audio frames" ,  self . audio_frames_appended) ; 
491490
492-         // debug!("First video timestamp: {:?}", self.first_timestamp); 
493-         // debug!("Last video timestamp: {:?}", self.last_pts); 
491+         wait_for_writer_finished ( & self . asset_writer ) . map_err ( |_| FinishError :: Failed ) ?; 
494492
495493        info ! ( "Finished writing" ) ; 
494+ 
495+         Ok ( ( ) ) 
496496    } 
497497} 
498498
499499impl  Drop  for  MP4Encoder  { 
500500    fn  drop ( & mut  self )  { 
501-         self . finish ( None ) ; 
501+         let  _ =  self . finish ( None ) ; 
502502    } 
503503} 
504504
@@ -621,3 +621,35 @@ impl SampleBufExt for cm::SampleBuf {
621621        } 
622622    } 
623623} 
624+ 
625+ fn  append_sample_buf ( 
626+     input :  & mut  av:: AssetWriterInput , 
627+     writer :  & av:: AssetWriter , 
628+     frame :  & cm:: SampleBuf , 
629+ )  -> Result < ( ) ,  QueueFrameError >  { 
630+     match  input. append_sample_buf ( frame)  { 
631+         Ok ( true )  => { } 
632+         Ok ( false )  => { 
633+             if  writer. status ( )  == av:: asset:: writer:: Status :: Failed  { 
634+                 return  Err ( QueueFrameError :: Failed ) ; 
635+             } 
636+             if  writer. status ( )  == av:: asset:: writer:: Status :: Writing  { 
637+                 return  Err ( QueueFrameError :: NotReadyForMore ) ; 
638+             } 
639+         } 
640+         Err ( e)  => return  Err ( QueueFrameError :: AppendError ( e. retained ( ) ) ) , 
641+     } 
642+ 
643+     Ok ( ( ) ) 
644+ } 
645+ 
646+ fn  wait_for_writer_finished ( writer :  & av:: AssetWriter )  -> Result < ( ) ,  ( ) >  { 
647+     use  av:: asset:: writer:: Status ; 
648+     loop  { 
649+         match  writer. status ( )  { 
650+             Status :: Completed  | Status :: Cancelled  => return  Ok ( ( ) ) , 
651+             Status :: Failed  | Status :: Unknown  => return  Err ( ( ) ) , 
652+             Status :: Writing  => std:: thread:: sleep ( Duration :: from_millis ( 2 ) ) , 
653+         } 
654+     } 
655+ } 
0 commit comments