U
    a¨+dIi  ã                   @   sî   d dl Z d dlZd dlZd dlZd dlmZ d dlmZ ddlm	Z	m
Z
mZ ddlmZmZmZ e j d¡Zedd	„ ƒZd
ed< ded< ded< ded< ded< ded< ded< dd„ Zdd„ Zeƒ dd„ ƒZdd„ Zd'dd „Zd(d%d&„ZdS ))é    N)Ú	lru_cache)Údefaultdicté   )Úget_ffmpeg_exeÚ_popen_kwargsÚlogger)Ú
LogCatcherÚparse_ffmpeg_headerÚcvsecsÚwinc                   C   s   dS )Néÿÿÿÿ© r   r   r   ú6/tmp/pip-unpacked-wheel-hya5gyls/imageio_ffmpeg/_io.pyÚ<lambda>   ó    r   éd   Úlibx264éZ   Ú
h264_nvencÚ
nvenc_h264ÚnvencéP   Z
h264_vaapiéF   Zlibopenh264é2   Z
libx264rgbc                 C   s>   t ƒ dddddd| dddg}tj|tjtjtjd	}|jd
kS )Nú-hide_bannerú-fZlavfiú-iznullsrc=s=256x256:d=8ú-vcodecÚnullú-©ÚstdinÚstdoutÚstderrr   )r   Ú
subprocessÚrunÚPIPEÚ
returncode)ÚencoderÚcmdÚpr   r   r   Úffmpeg_test_encoder!   s&    õür+   c                  C   sè   t ƒ ddg} tj| tjtjtjd}|j ¡  dd¡}| d¡}|d  d¡}g }| d¡D ]L}| ¡ }| d	¡d }|t	krŠ| 
|¡ q\|d
 dkr\d|kr\| 
|¡ q\|jddd„ d d|kràdD ]}||krÈ| |¡ qÈt|ƒS )Nr   z	-encodersr    úÚ z------r   Ú
ú r   ÚVzH.264Tc                 S   s   t |  S )N)Úh264_encoder_preference)Úxr   r   r   r   q   r   z,get_compiled_h264_encoders.<locals>.<lambda>)ÚreverseÚkeyr   )r   r   )r   r$   r%   r&   r"   ÚdecodeÚreplaceÚsplitÚstripr1   ÚappendÚsortÚremoveÚtuple)r)   r*   r"   Zheader_footerÚfooterÚencodersÚliner(   r   r   r   Úget_compiled_h264_encoders:   s0    ü
r@   c                  C   s,   t ƒ } | D ]}t|ƒr
|  S q
tdƒ‚d S )Nz=No valid H.264 encoder was found with the ffmpeg installation)r@   r+   ÚRuntimeError)Zcompiled_encodersr(   r   r   r   Ú get_first_available_h264_encoder{   s    
ÿrB   c           	   
   C   s‚  t | tjƒrt| ƒ} t | tƒs&tdƒ‚tƒ d| ddddddd	g
}ztj|fd
tjit	ƒ —Ž}W nD tj
k
r¢ } z$|jjdd}td |j|¡ƒ‚W 5 d}~X Y nX d }}t| ¡ ƒD ]¼}| d¡r¸|jdd}| d¡}|dkr||d…  dd¡d  ¡  dd¡d  ¡ }t|ƒ}| d¡}|dkrh||d…  dd¡d  ¡  dd¡d  ¡ }t| d¡Ž }||f  S q¸tdƒ‚dS )ap  
    Get the number of frames and number of seconds for the given video
    file. Note that this operation can be quite slow for large files.

    Disclaimer: I've seen this produce different results from actually reading
    the frames with older versions of ffmpeg (2.x). Therefore I cannot say
    with 100% certainty that the returned values are always exact.
    ú,Video path must be a string or pathlib.Path.r   ú-mapú0:v:0z-cÚcopyr   r   r   r#   Úignore)ÚerrorszFFMEG call failed with {}:
{}Ns   frame=zframe=r   ú=r   r   r/   ztime=ú:zCould not get number of frames)Ú
isinstanceÚpathlibÚPurePathÚstrÚ	TypeErrorr   r$   Úcheck_outputÚSTDOUTr   ÚCalledProcessErrorÚoutputr5   rA   Úformatr'   ÚreversedÚ
splitlinesÚ
startswithÚfindr7   Úlstripr8   Úintr
   )	Úpathr)   ÚoutÚerrÚnframesZnsecsr?   ÚiÚsr   r   r   Úcount_frames_and_secs‡   sD    
ö$


,

,ra   Úrgb24c                 c   sÄ  t | tjƒrt| ƒ} t | tƒs&tdƒ‚|p,d}|p4d}|p@|d }|pHg }|pPg }t |tƒsdtdƒ‚t |tƒsvtdƒ‚t |tƒsˆtdƒ‚t |tƒsštdƒ‚d	|d
dddg}tƒ g}||d| g 7 }||| dg 7 }t	j
|ft	jt	jt	jdœtdd—Ž}t|jƒ}	d}
zÚzŒt ¡ d }|	 ¡ rJ|	jsJt ¡ |k rJt d¡ q|	jsp|	 d¡}d}t| |¡ƒ‚nd|	jkrŠtd | ¡ƒ‚t|	jƒ}|V  |d \}}|| | }|d }|  ¡ sÌtdƒ‚t|ƒ}d }|d!7 }zft!ƒ }t"|ƒ|k r>|j #|t"|ƒ ¡}|s2t"|ƒd kr*W W W ¢ÀdS t$d"ƒ‚||7 }qè|V  W nL tk
r’ } z,t|ƒ}|	 d#¡}d$}t$| |||¡ƒ‚W 5 d}~X Y nX qØW nF t%k
r°   Y n2 tk
rÆ   ‚ Y n t&k
rà   d%}
‚ Y nX W 5 |	 ¡  | ¡ dkr¾z|j ¡  |j ¡  W n6 tk
rJ } zt dt|ƒ ¡ W 5 d}~X Y nX |
dkr¶z:t ¡ d }t ¡ |k rŽ| ¡ dkrŽt d¡ qdW 5 | ¡ dkr²t d¡ | ¡  X n| ¡  X dS )&a:  
    Create a generator to iterate over the frames in a video file.

    It first yields a small metadata dictionary that contains:

    * ffmpeg_version: the ffmpeg version in use (as a string).
    * codec: a hint about the codec used to encode the video, e.g. "h264".
    * source_size: the width and height of the encoded video frames.
    * size: the width and height of the frames that will be produced.
    * fps: the frames per second. Can be zero if it could not be detected.
    * duration: duration in seconds. Can be zero if it could not be detected.

    After that, it yields frames until the end of the video is reached. Each
    frame is a bytes object.

    This function makes no assumptions about the number of frames in
    the data. For one because this is hard to predict exactly, but also
    because it may depend on the provided output_params. If you want
    to know the number of frames in a video file, use count_frames_and_secs().
    It is also possible to estimate the number of frames from the fps and
    duration, but note that even if both numbers are present, the resulting
    value is not always correct.

    Example:

        gen = read_frames(path)
        meta = gen.__next__()
        for frame in gen:
            print(len(frame))

    Parameters:
        path (str): the filename of the file to read from.
        pix_fmt (str): the pixel format of the frames to be read.
            The default is "rgb24" (frames are uint8 RGB images).
        input_params (list): Additional ffmpeg input command line parameters.
        output_params (list): Additional ffmpeg output command line parameters.
        bits_per_pixel (int): The number of bits per pixel in the output frames.
            This depends on the given pix_fmt. Default is 24 (RGB)
        bpp (int): DEPRECATED, USE bits_per_pixel INSTEAD. The number of bytes per pixel in the output frames.
            This depends on the given pix_fmt. Some pixel formats like yuv420p have 12 bits per pixel
            and cannot be set in bytes as integer. For this reason the bpp argument is deprecated.
    rC   rb   é   é   zpix_fmt must be a stringz%bpp and bits_per_pixel must be an intúinput_params must be a listúoutput_params must be a listú-pix_fmtr   Úrawvideor   Z
image2piper   r   r    T©Zprevent_sigintÚtimeoutNz(Error while attempting stop ffmpeg (r): z!We had to kill ffmpeg to stop it.g      ø?ç{®Gáz„?ç      $@gš™™™™™É?z1Could not load meta information
=== stderr ===
{}zNo such file or directoryz{} not found! Wrong path?Úsizez;incorrect bits_per_pixel, framesize in bytes must be an intr   r   z4End of file reached before full frame could be read.gš™™™™™Ù?z-Could not read frame {}:
{}
=== stderr ===
{}Úkill)'rK   rL   rM   rN   rO   ÚAssertionErrorrZ   Úlistr   r$   ÚPopenr&   r   r   r#   Zstop_meÚpollr"   Úcloser!   Ú	Exceptionr   Úwarningrn   ÚtimeÚsleepÚis_aliveÚheaderZget_textÚIOErrorrT   r	   Ú
is_integerÚbytesÚlenÚreadrA   ÚGeneratorExitÚBaseException)r[   Zpix_fmtZbppÚinput_paramsÚoutput_paramsZbits_per_pixelZpre_output_paramsr)   r*   Zlog_catcherÚstop_policyr]   ÚetimeZerr2ÚfmtÚmetaÚwÚhZframesize_bitsZframesize_bytesZframenrÚbbZextra_bytesZerr1r   r   r   Úread_frames½   s´    5
ÿüû
 

ÿþÿ

,
$

rŠ   Úyuv420pé   é   ru   c                 #   s  t | tjƒrt| ƒ} t | tƒs&tdƒ‚|p,d}|p4d}|p<d}|pDd}ˆ pLd‰ |pTg }|p\g }|
pdd}
ttf}t |ttfƒrÀt	|ƒdkst
dƒ‚t |d tƒr¬t |d	 tƒs´t
d
ƒ‚dj|Ž }ndsÌt
dƒ‚t |tƒsÞt
dƒ‚t |tƒsðt
dƒ‚t ||ƒst
dƒ‚|dk	rDt ||ƒs"t
dƒ‚d	|  kr:dksDn t
dƒ‚t |tƒsXt
dƒ‚t ˆ tƒslt
dƒ‚t |
|ƒs€t
dƒ‚t |tƒs”t
dƒ‚t |tƒs¨t
dƒ‚|sÊ|  ¡  d¡rÄd}ntƒ }dg}|dk	r|  ¡  d¡sd|g}|dk	r|d|g7 }|d d!d d"g7 }tƒ d#d$d%d&d%d'|g}|d(|d)d* |¡g| 7 }|dd+g| 7 }|d&|d(|g7 }|dk	r„|d,t|ƒg7 }n^|dk	râd	|d-  }|d.krÂt|d/ ƒ}|d0t|ƒg7 }n t|d1 ƒd	 }|d2t|ƒg7 }|d	kr |d | dks|d	 | dkr |d }|d	 }|d | dkrF|||d |  7 }|d	 | dkrl|||d	 |  7 }|d3d4 ||¡g7 }t d5 ||dd… ||f¡¡ |d6ˆ g7 }||7 }| | ¡ d7 |¡}t‡ fd8d9„d:D ƒƒrît d;| ¡ tj|ftjtjdd<œtd=d>—Ž}d?}|
s d@}zÄzdd}dV }z|j "|¡ W n8 tk
rv } zdD ||¡}t#|ƒ‚W 5 d}~X Y nX |d	7 }q(W nZ t$k
r°   |dkr¬t dE¡ Y n2 tk
rÆ   ‚ Y n t%k
rà   dF}‚ Y nX W 5 | ¡ dkròz|j ¡  W n6 tk
r8 } zt dAt|ƒ ¡ W 5 d}~X Y nX |d?kr¤z:t ¡ |
 }t ¡ |k r|| ¡ dkr|t  dC¡ qRW 5 | ¡ dkr t dB¡ | ¡  X nN|d@krêz | ¡ dkrÌt  dC¡ q°W 5 | ¡ dkræ| ¡  X n| ¡  z|j! ¡  W n tk
r   Y nX X dS )GaÔ  
    Create a generator to write frames (bytes objects) into a video file.

    The frames are written by using the generator's `send()` method. Frames
    can be anything that can be written to a file. Typically these are
    bytes objects, but c-contiguous Numpy arrays also work.

    Example:

        gen = write_frames(path, size)
        gen.send(None)  # seed the generator
        for frame in frames:
            gen.send(frame)
        gen.close()  # don't forget this

    Parameters:
        path (str): the filename to write to.
        size (tuple): the width and height of the frames.
        pix_fmt_in (str): the pixel format of incoming frames.
            E.g. "gray", "gray8a", "rgb24", or "rgba". Default "rgb24".
        pix_fmt_out (str): the pixel format to store frames. Default yuv420p".
        fps (float): The frames per second. Default 16.
        quality (float): A measure for quality between 0 and 10. Default 5.
            Ignored if bitrate is given.
        bitrate (str): The bitrate, e.g. "192k". The defaults are pretty good.
        codec (str): The codec. Default "libx264" for .mp4 (if available from
            the ffmpeg executable) or "msmpeg4" for .wmv.
        macro_block_size (int): You probably want to align the size of frames
            to this value to avoid image resizing. Default 16. Can be set
            to 1 to avoid block alignment, though this is not recommended.
        ffmpeg_log_level (str): The ffmpeg logging level. Default "warning".
        ffmpeg_timeout (float): Timeout in seconds to wait for ffmpeg process
            to finish. Value of 0 or None will wait forever (default). The time that
            ffmpeg needs depends on CPU speed, compression, and frame size.
        input_params (list): Additional ffmpeg input command line parameters.
        output_params (list): Additional ffmpeg output command line parameters.
        audio_path (str): A input file path for encoding with an audio stream.
            Default None, no audio.
        audio_codec (str): The audio codec to use if audio_path is provided.
            "copy" will try to use audio_path's audio codec without re-encoding.
            Default None, but some formats must have certain codecs specified.
    rC   rb   r‹   rŒ   ru   r   é   zsize must be a 2-tupler   zsize must be intsz	{:d}x{:d}Fzsize must be str or tuplezpix_fmt_in must be strzpix_fmt_out must be strzfps must be floatNzquality must be floaté
   z*quality must be between 1 and 10 inclusivezmacro_block_size must be intzffmpeg_log_level must be strzffmpeg_timeout must be floatre   rf   z.wmvZmsmpeg4z-anz.gifr   z-acodecrD   rE   z1:a:0z-yr   rh   r   z-srg   z-rz{:.02f}r   z-b:vrl   r   é3   z-crfé   z	-qscale:vz-vfzscale={}:{}a/  IMAGEIO FFMPEG_WRITER WARNING: input image is not divisible by macro_block_size={}, resizing from {} to {} to ensure video compatibility with most codecs and players. To prevent resizing, make your input image divisible by the macro_block_size or set the macro_block_size to 1 (risking incompatibility).z-vr/   c                    s   g | ]}|ˆ k‘qS r   r   )Ú.0Úlevel©Úffmpeg_log_levelr   r   Ú
<listcomp>E  s     z write_frames.<locals>.<listcomp>)ÚinfoÚverboseÚdebugÚtracezRUNNING FFMPEG COMMAND: r    Tri   rj   Úwaitz(Error while attempting stop ffmpeg (w): ziWe had to kill ffmpeg to stop it. Consider increasing ffmpeg_timeout, or setting it to zero (no timeout).rk   z2{0:}

FFMPEG COMMAND:
{1:}

FFMPEG STDERR OUTPUT:
z:No frames have been written; the written video is invalid.rn   )&rK   rL   rM   rN   rO   ÚfloatrZ   r<   rp   r}   ro   rT   ÚlowerÚendswithrB   r   r   ru   r9   ÚjoinÚanyr—   r$   rq   r&   r   rr   r!   rs   rt   rn   rv   rw   r"   Úwriterz   r   r€   )r[   rm   Z
pix_fmt_inZpix_fmt_outZfpsZqualityZbitrateÚcodecZmacro_block_sizer•   Zffmpeg_timeoutr   r‚   Z
audio_pathZaudio_codecZfloatishZsizestrZaudio_paramsr)   Zout_wZout_hZcmd_strr*   rƒ   r]   r„   r^   r‰   Úmsgr   r”   r   Úwrite_frames‡  s(   >
	 ÿþ
"
ø




$ 
 úÿ

ÿÿüû	 ÿÿ
$
ÿ
r¤   )rb   NNNN)rb   r‹   rŒ   r   NNrŒ   ru   NNNNN)Úsysrv   rL   r$   Ú	functoolsr   Úcollectionsr   Ú_utilsr   r   r   Z_parsingr   r	   r
   ÚplatformrW   ZISWINr1   r+   r@   rB   ra   rŠ   r¤   r   r   r   r   Ú<module>   sT   A
8     ú
 N             ñ