o
    e                     @  s   d dl mZ d dlZd dlmZ d dlmZ d dlmZm	Z	m
Z
mZ d dlZd dlZeG dd dZG dd	 d	Zd ddZ	d!d"ddZd#ddZG dd dZdS )$    )annotationsN)deque)	dataclass)Callable	GeneratorOptionalTuplec                   @  sR   e Zd ZU dZded< ded< ded< dZded< edddZedddZ	dS )	VideoInfoa  
    A class to store video information, including width, height, fps and
        total number of frames.

    Attributes:
        width (int): width of the video in pixels
        height (int): height of the video in pixels
        fps (int): frames per second of the video
        total_frames (int, optional): total number of frames in the video,
            default is None

    Examples:
        ```python
        >>> import supervision as sv

        >>> video_info = sv.VideoInfo.from_video_path(video_path='video.mp4')

        >>> video_info
        VideoInfo(width=3840, height=2160, fps=25, total_frames=538)

        >>> video_info.resolution_wh
        (3840, 2160)
        ```
    intwidthheightfpsNOptional[int]total_frames
video_pathstrreturnc                 C  sv   t |}| std| t|t j}t|t j}t|t j}t|t j	}|
  t||||S )NCould not open video at )cv2VideoCaptureisOpened	Exceptionr
   getCAP_PROP_FRAME_WIDTHCAP_PROP_FRAME_HEIGHTCAP_PROP_FPSCAP_PROP_FRAME_COUNTreleaser	   )clsr   videor   r   r   r    r    F/var/www/myenv/lib/python3.10/site-packages/supervision/utils/video.pyfrom_video_path,   s   
zVideoInfo.from_video_pathTuple[int, int]c                 C  s   | j | jfS N)r   r   selfr    r    r!   resolution_wh9   s   zVideoInfo.resolution_wh)r   r   r   r	   )r   r#   )
__name__
__module____qualname____doc____annotations__r   classmethodr"   propertyr'   r    r    r    r!   r	      s   
 r	   c                   @  s6   e Zd ZdZdddd	Zd
d ZdddZdd ZdS )	VideoSinka  
    Context manager that saves video frames to a file using OpenCV.

    Attributes:
        target_path (str): The path to the output file where the video will be saved.
        video_info (VideoInfo): Information about the video resolution, fps,
            and total frame count.
        codec (str): FOURCC code for video format

    Example:
        ```python
        >>> import supervision as sv

        >>> video_info = sv.VideoInfo.from_video_path('source.mp4')
        >>> frames_generator = get_video_frames_generator('source.mp4')

        >>> with sv.VideoSink(target_path='target.mp4', video_info=video_info) as sink:
        ...     for frame in frames_generator:
        ...         sink.write_frame(frame=frame)
        ```
    mp4vtarget_pathr   
video_infor	   codecc                 C  s   || _ || _|| _d | _d S r$   )r1   r2   _VideoSink__codec_VideoSink__writer)r&   r1   r2   r3   r    r    r!   __init__U   s   
zVideoSink.__init__c              
   C  sv   z	t j| j | _W n  ty) } ztt|d  t jd | _W Y d }~nd }~ww t | j| j| j	j
| j	j| _| S )Nz. Defaulting to mp4v...r0   )r   VideoWriter_fourccr4   _VideoSink__fourcc	TypeErrorprintr   VideoWriterr1   r2   r   r'   r5   )r&   er    r    r!   	__enter__[   s   zVideoSink.__enter__frame
np.ndarrayc                 C  s   | j | d S r$   )r5   write)r&   r>   r    r    r!   write_framei   s   zVideoSink.write_framec                 C  s   | j   d S r$   )r5   r   )r&   exc_type	exc_valueexc_tracebackr    r    r!   __exit__l   s   zVideoSink.__exit__N)r0   )r1   r   r2   r	   r3   r   )r>   r?   )r(   r)   r*   r+   r6   r=   rA   rE   r    r    r    r!   r/   >   s    
r/   source_pathr   startr
   endr   c                 C  s   t | }| std|  t|t j}|d ur$||kr$tdt|d}|d ur2t||n|}|	t j
| |||fS )Nr   zRequested frames are outboundr   )r   r   r   r   r
   r   r   maxminsetCAP_PROP_POS_FRAMES)rF   rG   rH   r   r   r    r    r!   _validate_and_setup_videop   s   


rM      strider   !Generator[np.ndarray, None, None]c           	      c  sr    t | ||\}}}|}	 | \}}|r||krn|V  t|d D ]
}| }|s- nq#||7 }q|  dS )a=  
    Get a generator that yields the frames of the video.

    Args:
        source_path (str): The path of the video file.
        stride (int): Indicates the interval at which frames are returned,
            skipping stride - 1 frames between each.
        start (int): Indicates the starting position from which
            video should generate frames
        end (Optional[int]): Indicates the ending position at which video
            should stop generating frames. If None, video will be read to the end.

    Returns:
        (Generator[np.ndarray, None, None]): A generator that yields the
            frames of the video.

    Examples:
        ```python
        >>> import supervision as sv

        >>> for frame in sv.get_video_frames_generator(source_path='source_video.mp4'):
        ...     ...
        ```
    TrN   N)rM   readrangegrabr   )	rF   rO   rG   rH   r   frame_positionsuccessr>   _r    r    r!   get_video_frames_generator}   s    
rW   r1   callback'Callable[[np.ndarray, int], np.ndarray]Nonec                 C  sl   t j| d}t||d }tt| dD ]\}}|||}|j|d qW d   dS 1 s/w   Y  dS )aS  
    Process a video file by applying a callback function on each frame
        and saving the result to a target video file.

    Args:
        source_path (str): The path to the source video file.
        target_path (str): The path to the target video file.
        callback (Callable[[np.ndarray, int], np.ndarray]): A function that takes in
            a numpy ndarray representation of a video frame and an
            int index of the frame and returns a processed numpy ndarray
            representation of the frame.

    Examples:
        ```python
        >>> import supervision as sv

        >>> def callback(scene: np.ndarray, index: int) -> np.ndarray:
        ...     ...

        >>> process_video(
        ...     source_path='...',
        ...     target_path='...',
        ...     callback=callback
        ... )
        ```
    )r   )r1   r2   )rF   )r>   N)r	   r"   r/   	enumeraterW   rA   )rF   r1   rX   source_video_infosinkindexr>   result_framer    r    r!   process_video   s   
"r`   c                   @  s:   e Zd ZdZddddZdd	d
ZdddZdddZdS )
FPSMonitorzN
    A class for monitoring frames per second (FPS) to benchmark latency.
       sample_sizer
   c                 C  s   t |d| _dS )a  
        Args:
            sample_size (int): The maximum number of observations for latency
                benchmarking.

        Examples:
            ```python
            >>> import supervision as sv

            >>> frames_generator = sv.get_video_frames_generator('source.mp4')
            >>> fps_monitor = sv.FPSMonitor()

            >>> for frame in frames_generator:
            ...     # your processing code here
            ...     fps_monitor.tick()
            ...     fps = fps_monitor()
            ```
        )maxlenN)r   all_timestamps)r&   rc   r    r    r!   r6      s   zFPSMonitor.__init__r   floatc                 C  s8   | j sdS | j d | j d  }|dkrt| j | S dS )z
        Computes and returns the average FPS based on the stored time stamps.

        Returns:
            float: The average FPS. Returns 0.0 if no time stamps are stored.
        g        r   )re   len)r&   
taken_timer    r    r!   __call__   s   zFPSMonitor.__call__rZ   c                 C  s   | j t  dS )zI
        Adds a new time stamp to the deque for FPS calculation.
        N)re   appendtime	monotonicr%   r    r    r!   tick   s   zFPSMonitor.tickc                 C  s   | j   dS )z<
        Clears all the time stamps from the deque.
        N)re   clearr%   r    r    r!   reset   s   zFPSMonitor.resetN)rb   )rc   r
   )r   rf   )r   rZ   )r(   r)   r*   r+   r6   rj   rn   rp   r    r    r    r!   ra      s    

ra   )rF   r   rG   r
   rH   r   )rN   r   N)
rF   r   rO   r
   rG   r
   rH   r   r   rP   )rF   r   r1   r   rX   rY   r   rZ   )
__future__r   rl   collectionsr   dataclassesr   typingr   r   r   r   r   numpynpr	   r/   rM   rW   r`   ra   r    r    r    r!   <module>   s    1
2
*(