@@ -600,11 +600,8 @@ def __init__(
600600 super (PiVideoEncoder , self ).__init__ (
601601 parent , camera_port , input_port , format , resize , ** options )
602602 self ._next_output = []
603+ self ._split_frame = None
603604 self .frame = None
604- self .chunk_timestamp = None
605- self .next_pts = 0
606- self .last_pts = 0
607- self .split_pts = 0
608605
609606 def _create_encoder (
610607 self , format , bitrate = 17000000 , intra_period = None , profile = 'high' ,
@@ -811,7 +808,6 @@ def start(self, output, motion_output=None):
811808 timestamp = 0 ,
812809 complete = False ,
813810 )
814- self .chunk_timestamp = None
815811 if motion_output is not None :
816812 self ._open_output (motion_output , PiVideoFrameType .motion_data )
817813 super (PiVideoEncoder , self ).start (output )
@@ -849,7 +845,7 @@ def split(self, output, motion_output=None):
849845 # intra_period / framerate gives the time between I-frames (which
850846 # should also coincide with SPS headers). We multiply by three to
851847 # ensure the timeout is deliberately excessive, and clamp the minimum
852- # timeout to 10 seconds (otherwise unencoded formats tend to fail
848+ # timeout to 15 seconds (otherwise unencoded formats tend to fail
853849 # presumably due to I/O capacity)
854850 if self .parent :
855851 framerate = self .parent .framerate + self .parent .framerate_delta
@@ -861,37 +857,20 @@ def split(self, output, motion_output=None):
861857 if not self .event .wait (timeout ):
862858 raise PiCameraRuntimeError ('Timed out waiting for a split point' )
863859 self .event .clear ()
864- return self .split_pts
860+ return self ._split_frame
865861
866862 def _callback_write (self , buf , key = PiVideoFrameType .frame ):
867863 """
868864 Extended to implement video frame meta-data tracking, and to handle
869865 splitting video recording to the next output when :meth:`split` is
870866 called.
871867 """
872- timestamp = (
873- None
874- if buf .pts in (0 , mmal .MMAL_TIME_UNKNOWN ) else
875- buf .pts
876- )
877- complete = bool (buf .flags & mmal .MMAL_BUFFER_HEADER_FLAG_FRAME_END )
878- # Uncomment to observe skipped frames:
879- # if timestamp:
880- # while self.next_pts and timestamp > self.next_pts:
881- # print("<SKIP!>")
882- # self.next_pts += 1000000 / self.parent.framerate
883- # self.next_pts = timestamp + 1000000 / self.parent.framerate
884- if timestamp is None :
885- timestamp = self .chunk_timestamp
886- if complete :
887- self .chunk_timestamp = None
888- else :
889- self .chunk_timestamp = timestamp
890- self .frame = PiVideoFrame (
868+ last_frame = self .frame
869+ this_frame = PiVideoFrame (
891870 index =
892- self . frame .index + 1
893- if self . frame .complete else
894- self . frame .index ,
871+ last_frame .index + 1
872+ if last_frame .complete else
873+ last_frame .index ,
895874 frame_type =
896875 PiVideoFrameType .key_frame
897876 if buf .flags & mmal .MMAL_BUFFER_HEADER_FLAG_KEYFRAME else
@@ -902,18 +881,24 @@ def _callback_write(self, buf, key=PiVideoFrameType.frame):
902881 PiVideoFrameType .frame ,
903882 frame_size =
904883 buf .length
905- if self . frame .complete else
906- self . frame .frame_size + buf .length ,
884+ if last_frame .complete else
885+ last_frame .frame_size + buf .length ,
907886 video_size =
908- self . frame .video_size
887+ last_frame .video_size
909888 if buf .flags & mmal .MMAL_BUFFER_HEADER_FLAG_CODECSIDEINFO else
910- self . frame .video_size + buf .length ,
889+ last_frame .video_size + buf .length ,
911890 split_size =
912- self . frame .split_size
891+ last_frame .split_size
913892 if buf .flags & mmal .MMAL_BUFFER_HEADER_FLAG_CODECSIDEINFO else
914- self .frame .split_size + buf .length ,
915- timestamp = timestamp ,
916- complete = complete ,
893+ last_frame .split_size + buf .length ,
894+ timestamp =
895+ # Time cannot go backwards, so if we've got an unknown pts
896+ # simply repeat the last one
897+ last_frame .timestamp
898+ if buf .pts in (0 , mmal .MMAL_TIME_UNKNOWN ) else
899+ buf .pts ,
900+ complete =
901+ bool (buf .flags & mmal .MMAL_BUFFER_HEADER_FLAG_FRAME_END )
917902 )
918903 if self ._intra_period == 1 or (buf .flags & mmal .MMAL_BUFFER_HEADER_FLAG_CONFIG ):
919904 with self .outputs_lock :
@@ -926,21 +911,20 @@ def _callback_write(self, buf, key=PiVideoFrameType.frame):
926911 self ._close_output (new_key )
927912 self ._open_output (new_output , new_key )
928913 if new_key == PiVideoFrameType .frame :
929- self . frame = PiVideoFrame (
930- index = self . frame .index ,
931- frame_type = self . frame .frame_type ,
932- frame_size = self . frame .frame_size ,
933- video_size = self . frame .video_size ,
914+ this_frame = PiVideoFrame (
915+ index = this_frame .index ,
916+ frame_type = this_frame .frame_type ,
917+ frame_size = this_frame .frame_size ,
918+ video_size = this_frame .video_size ,
934919 split_size = 0 ,
935- timestamp = self . frame .timestamp ,
936- complete = self . frame .complete ,
920+ timestamp = this_frame .timestamp ,
921+ complete = this_frame .complete ,
937922 )
938- self .split_pts = self . last_pts
923+ self ._split_frame = this_frame
939924 self .event .set ()
940925 if buf .flags & mmal .MMAL_BUFFER_HEADER_FLAG_CODECSIDEINFO :
941926 key = PiVideoFrameType .motion_data
942- if self .frame .timestamp :
943- self .last_pts = self .frame .timestamp
927+ self .frame = this_frame
944928 return super (PiVideoEncoder , self )._callback_write (buf , key )
945929
946930
0 commit comments