o
    diR                     @   s  d dl Z d dlZd dlZd dlZd dlZd dlZd dlmZmZm	Z	m
Z
 d dlZd dlZd dlmZmZ d dlmZ d dlmZ d dlmZ d dlmZ dd	lmZmZmZ eeZg d
Ze	eef ZdeddfddZ G dd dZ!de j"dej#j$de%e dddddej&de'de'ddfddZ(de j"dej#j$de%e dddddej&de'de'ddfddZ)G dd deZ*G dd  d Z+G d!d" d"Z,G d#d$ d$Z-G d%d& d&eZ.G d'd( d(Z/dS ))    N)AnyOptionalUnioncast)
AudioFrame
VideoFrame)AudioStream)Frame)Packet)VideoStream   )AUDIO_PTIMEMediaStreamErrorMediaStreamTrack)alsaandroid_cameraavfoundationbktrdecklinkdshowfbdevgdigrabiec61883jackkmsgrabopenalosspulsesndiortspv4l2vfwcapx11grabtrackreturnc                    s.   	 z	|   I d H  W n
 ty   Y d S w qN)recvr   )r#    r'   H/home/ubuntu/.local/lib/python3.10/site-packages/aiortc/contrib/media.pyblackhole_consume.   s   r)   c                   @   s@   e Zd ZdZdddZdeddfddZdd	d
ZdddZdS )MediaBlackholez<
    A media sink that consumes and discards all media.
    r$   Nc                 C   s
   i | _ d S r%   _MediaBlackhole__tracksselfr'   r'   r(   __init__;   s   
zMediaBlackhole.__init__r#   c                 C   s   || j vrd| j |< dS dS )zy
        Add a track whose media should be discarded.

        :param track: A :class:`aiortc.MediaStreamTrack`.
        Nr+   r.   r#   r'   r'   r(   addTrack>   s   
zMediaBlackhole.addTrackc                    s6   | j  D ]\}}|du rtt|| j |< qdS )z)
        Start discarding media.
        N)r,   itemsasyncioensure_futurer)   )r.   r#   taskr'   r'   r(   startG   s   zMediaBlackhole.startc                    s,   | j  D ]
}|dur|  qi | _ dS )z(
        Stop discarding media.
        N)r,   valuescancel)r.   r5   r'   r'   r(   stopO   s   
zMediaBlackhole.stopr$   N)	__name__
__module____qualname____doc__r/   r   r1   r6   r9   r'   r'   r'   r(   r*   6   s    

	r*   loop	containerstreamsaudio_trackPlayerStreamTrackvideo_track
quit_eventthrottle_playbackloop_playbackc              
   C   s  d}d}	t d|}
tjdd|t|t d}d }d }t }| sz	t|j	| }W nT t
y } zHt|tjrK|jtjkrKtd W Y d }~qt|tr]|r]|d W Y d }~q|rit|jd |  |rut|jd |  W Y d }~d S d }~ww |rt | }|r||d krtd t|tr|r||D ]}|	|_|
|_|	|j7 }	|j}t|j||  qn/t|tr|r|jd u rtd	|j q|d u r|j}| j|8  _|j}t|j||  | r#d S d S )
Ni  r      s16stereo)formatlayoutrate
frame_size{Gz?皙?z0MediaPlayer(%s) Skipping video frame with no pts)	fractionsFractionavAudioResamplerintr   timeis_setnextdecode	Exception
isinstanceFFmpegErrorerrnoEAGAINsleepStopIterationseekr3   run_coroutine_threadsafe_queueputr   resamplepts	time_basesamplesr   loggerwarningname)r?   r@   rA   rB   rD   rE   rF   rG   audio_sample_rateaudio_samplesaudio_time_baseaudio_resamplervideo_first_pts
frame_time
start_timeframeexcelapsed_timer'   r'   r(   player_worker_decodeY   sj   






rv   c              
   C   s  d }d }	t   }
| szt|j| }|jstW nT tyn } zHt|tj	r9|j
t
jkr9t d W Y d }~qt|trK|rK|d W Y d }~q|rWt|jd |  |rct|jd |  W Y d }~d S d }~ww |rt   |
 }|	r|	|d krt d d }t|jtr|r|}n%t|jtr|r|jd u rtd|j q|}|d u r|j}| j|8  _|d ur|jd ur|jd urt|j|j }	t|j||  | rd S d S )NrO   r   rH   rP   z1MediaPlayer(%s) Skipping video packet with no pts)rV   rW   rX   demuxsizer`   rZ   r[   rS   r\   r]   r^   r_   ra   r3   rb   rc   rd   streamr   r   rf   ri   rj   rk   rg   rU   )r?   r@   rA   rB   rD   rE   rF   rG   rp   rq   rr   packetrt   ru   r#   r'   r'   r(   player_worker_demux   s\   






r{   c                       sN   e Zd Zdddeddf fddZdeeef fdd	Zd fd
dZ	  Z
S )rC   playerMediaPlayerkindr$   Nc                    s*   t    || _|| _t | _d | _d S r%   )superr/   r~   _playerr3   Queuerc   _start)r.   r|   r~   	__class__r'   r(   r/      s
   


zPlayerStreamTrack.__init__c                    s   | j dkrt| j|  | j I d H }|d u r |   tt|tr)|j	}nt|t
r6t|j|j }| jd urb| jjrb|d urb| jd u rQt		 | | _|S | j| t		  }t|I d H  |S Nlive)
readyStater   r   r   rc   getr9   r[   r	   rV   r
   floatrf   rg   _throttle_playbackr3   r_   )r.   data	data_timewaitr'   r'   r(   r&      s,   




zPlayerStreamTrack.recvc                    s.   t    | jd ur| j|  d | _d S d S r%   )r   r9   r   _stopr-   r   r'   r(   r9     s
   


zPlayerStreamTrack.stopr:   )r;   r<   r=   strr/   r   r	   r
   r&   r9   __classcell__r'   r'   r   r(   rC      s    c                   @   s   e Zd ZdZ					ddedee deeeef  dee d	e	d
e	ddfddZ
edee fddZedee fddZdeddfddZdeddfddZdededdfddZdS )r}   u  
    A media source that reads audio and/or video from a file.

    Examples:

    .. code-block:: python

        # Open a video file.
        player = MediaPlayer('/path/to/some.mp4')

        # Open an HTTP stream.
        player = MediaPlayer(
            'http://download.tsi.telecom-paristech.fr/'
            'gpac/dataset/dash/uhd/mux_sources/hevcds_720p30_2M.mp4')

        # Open webcam on Linux.
        player = MediaPlayer('/dev/video0', format='v4l2', options={
            'video_size': '640x480'
        })

        # Open webcam on OS X.
        player = MediaPlayer('default:none', format='avfoundation', options={
            'video_size': '640x480'
        })

        # Open webcam on Windows.
        player = MediaPlayer('video=Integrated Camera', format='dshow', options={
            'video_size': '640x480'
        })

    :param file: The path to a file, or a file-like object.
    :param format: The format to use, defaults to autodect.
    :param options: Additional options to pass to FFmpeg.
    :param timeout: Open/read timeout to pass to FFmpeg.
    :param loop: Whether to repeat playback indefinitely (requires a seekable file).
    NFTfilerK   optionstimeoutr?   rY   r$   c           	      C   sF  t j||d||d| _d | _d | _t | _g | _|| _d | _	d | _
| jjD ][}|jdkrT| j	sT| jr@t| dd| _	| j| q%|jjdv rSt| dd| _	| j| q%|jdkr| j
s| jrmt| dd| _
| j| q%|jjdv rt| dd| _
| j| q%t| jjjd}|t | _|r| jjd usJ d	|| _d S )
Nr)r   rK   moder   r   audio)r~   )opuspcm_alaw	pcm_mulawvideo)h264vp8,z,The `loop` argument requires a seekable file)rS   open_MediaPlayer__container_MediaPlayer__thread_MediaPlayer__thread_quitset_MediaPlayer__started_MediaPlayer__streams_MediaPlayer__decode_MediaPlayer__audio_MediaPlayer__videorA   typerC   appendcodec_contextrk   rK   splitintersectionREAL_TIME_FORMATSr   duration_loop_playback)	r.   r   rK   r   r   r?   rY   ry   container_formatr'   r'   r(   r/   1  sB   	

zMediaPlayer.__init__c                 C      | j S )zY
        A :class:`aiortc.MediaStreamTrack` instance if the file contains audio.
        )r   r-   r'   r'   r(   r   `     zMediaPlayer.audioc                 C   r   )zY
        A :class:`aiortc.MediaStreamTrack` instance if the file contains video.
        )r   r-   r'   r'   r(   r   g  r   zMediaPlayer.videor#   c                 C   sz   | j | | jd u r;| d t | _tjd| jrt	nt
t | j| j| j| j| j| j| jfd| _| j  d S d S )NzStarting worker threadzmedia-player)rk   targetargs)r   addr   _MediaPlayer__log_debug	threadingEventr   Threadr   rv   r{   r3   get_event_loopr   r   r   r   r   r   r6   r0   r'   r'   r(   r   n  s&   


zMediaPlayer._startc                 C   sl   | j | | j s | jd ur | d | j  | j  d | _| j s2| jd ur4| j  d | _d S d S d S )NzStopping worker thread)	r   discardr   r   r   r   joinr   closer0   r'   r'   r(   r     s   




zMediaPlayer._stopmsgr   c                 G   s"   t jd| | jjg|R   d S )NzMediaPlayer(%s) )ri   debugr   rk   r.   r   r   r'   r'   r(   __log_debug     "zMediaPlayer.__log_debug)NNNFT)r;   r<   r=   r>   r   r   r   dictrU   boolr/   propertyr   r   r   rC   r   r   objectr   r'   r'   r'   r(   r}     s:    (
/r}   c                   @   s   e Zd ZdeddfddZdS )MediaRecorderContextry   r$   Nc                 C   s   d| _ || _d | _d S )NF)startedry   r5   )r.   ry   r'   r'   r(   r/     s   
zMediaRecorderContext.__init__)r;   r<   r=   _AudioOrVideoStreamr/   r'   r'   r'   r(   r     s    r   c                
   @   s|   e Zd ZdZ		ddedee deeeef  ddfddZd	e	ddfd
dZ
dddZdddZd	e	deddfddZdS )MediaRecordera  
    A media sink that writes audio and/or video to a file.

    Examples:

    .. code-block:: python

        # Write to a video file.
        player = MediaRecorder('/path/to/file.mp4')

        # Write to a set of images.
        player = MediaRecorder('/path/to/file-%3d.png')

    :param file: The path to a file, or a file-like object.
    :param format: The format to use, defaults to autodect.
    :param options: Additional options to pass to FFmpeg.
    Nr   rK   r   r$   c                 C   s   t j||d|d| _i | _d S )Nw)r   rK   r   r   )rS   r   _MediaRecorder__container_MediaRecorder__tracks)r.   r   rK   r   r'   r'   r(   r/     s   
zMediaRecorder.__init__r#   c                 C   s   |j dkr/| jjjdv rd}n| jjjdkrd}n| jjjdv r#d}nd}tt| j|}n1| jjjdkrB| jjd	d
d}d|_n| jjjdkrU| jjdd
d}d|_n| jjdd
d}d|_t|| j	|< dS )zh
        Add a track to be recorded.

        :param track: A :class:`aiortc.MediaStreamTrack`.
        r   )wavr   r   	pcm_s16lemp3)oggr   webmlibopusaacimage2png   )rM   rgb24r   libvpxyuv420plibx264N)
r~   r   rK   rk   r   r   
add_streampix_fmtr   r   )r.   r#   
codec_namery   r'   r'   r(   r1     s$   
zMediaRecorder.addTrackc                    s8   | j  D ]\}}|jdu rt| |||_qdS )z"
        Start recording.
        N)r   r2   r5   r3   r4   _MediaRecorder__run_track)r.   r#   contextr'   r'   r(   r6     s   
zMediaRecorder.startc                    sv   | j dur9| j D ] \}}|jdur+|j  d|_|jdD ]}| j | q"qi | _| j   d| _ dS dS )z!
        Stop recording.
        N)	r   r   r2   r5   r8   ry   encodemuxr   )r.   r#   r   rz   r'   r'   r(   r9     s   




zMediaRecorder.stopr   c                    s   	 z	|  I d H }W n
 ty   Y d S w t|ttfs!J d|js<t|jtr9t|tr9|j|j_|j	|j_	d|_|j
|D ]}| j| qBq)NTz*Only audio or video frames can be recorded)r&   r   r[   r   r   r   ry   r   widthheightr   r   r   )r.   r#   r   rs   rz   r'   r'   r(   __run_track  s(   

zMediaRecorder.__run_track)NNr:   )r;   r<   r=   r>   r   r   r   r   r/   r   r1   r6   r9   r   r   r'   r'   r'   r(   r     s.    


r   c                       sR   e Zd Zdddededdf fddZdeeef fd	d
Z	d fddZ
  ZS )RelayStreamTrackrelay
MediaRelaysourcebufferedr$   Nc                    sX   t    |j| _|| _|| _|| _d | _d | _d | _| jr%t	
 | _d S t	 | _d S r%   )r   r/   r~   _relay_source	_buffered_framerc   _new_frame_eventr3   r   r   )r.   r   r   r   r   r'   r(   r/     s   
zRelayStreamTrack.__init__c                    sl   | j dkrt| j|  | jr| j I d H | _n| j	 I d H  | j
  | jd u r3|   t| jS r   )r   r   r   r   r   rc   r   r   r   r   clearr9   r-   r'   r'   r(   r&     s   


zRelayStreamTrack.recvc                    s4   t    | jd ur| j|  d | _d | _d S d S r%   )r   r9   r   r   r   r-   r   r'   r(   r9   .  s   


zRelayStreamTrack.stopr:   )r;   r<   r=   r   r   r/   r   r	   r
   r&   r9   r   r'   r'   r   r(   r     s    r   c                   @   s   e Zd ZdZdddZ	ddededefd	d
ZdeddfddZ	deddfddZ
dededdfddZdeddfddZdS )r   z
    A media source that relays one or more tracks to multiple consumers.

    This is especially useful for live tracks such as webcams or media received
    over the network.
    r$   Nc                 C   s   i | _ i | _d S r%   )_MediaRelay__proxies_MediaRelay__tasksr-   r'   r'   r(   r/   >  s   
zMediaRelay.__init__Tr#   r   c                 C   s<   t | ||}| dt|t| || jvrt | j|< |S )a.  
        Create a proxy around the given `track` for a new consumer.

        :param track: Source :class:`MediaStreamTrack` which is relayed.
        :param buffered: Whether there need a buffer between the source track and
            relayed track.

        :rtype: :class: MediaStreamTrack
        zCreate proxy %s for source %s)r   _MediaRelay__log_debugidr   r   )r.   r#   r   proxyr'   r'   r(   	subscribeB  s
   
zMediaRelay.subscriber   c                 C   sv   |j }|d ur5|| jv r7|| j| vr#| dt| | j| | || jvr9t| || j|< d S d S d S d S )NzStart proxy %s)	r   r   r   r   r   r   r3   r4   _MediaRelay__run_trackr.   r   r#   r'   r'   r(   r   T  s   
zMediaRelay._startc                 C   sD   |j }|d ur|| jv r | dt| | j| | d S d S d S )NzStop proxy %s)r   r   r   r   r   r   r'   r'   r(   r   `  s
   zMediaRelay._stopr   r   c                 G   s"   t jd| t| g|R   d S )NzMediaRelay(%s) )ri   r   r   r   r'   r'   r(   r   g  r   zMediaRelay.__log_debugc                    s   |  dt|  	 z	| I d H }W n ty   d }Y nw | j| D ]}|jr1|j| q%||_|j	
  q%|d u r?nq|  dt| | j|= | j|= d S )NzStart reading source %sTzStop reading source %s)r   r   r&   r   r   r   rc   
put_nowaitr   r   r   r   )r.   r#   rs   r   r'   r'   r(   r   j  s&   zMediaRelay.__run_trackr:   )T)r;   r<   r=   r>   r/   r   r   r   r   r   r   r   r   r   r   r'   r'   r'   r(   r   6  s    

r   )0r3   r]   rQ   loggingr   rV   typingr   r   r   r   rS   av.containerr   r   av.audior   av.framer	   	av.packetr
   av.video.streamr   mediastreamsr   r   r   	getLoggerr;   ri   r   r   r)   r*   AbstractEventLoopr@   InputContainerlistr   r   rv   r{   rC   r}   r   r   r   r   r'   r'   r'   r(   <module>   s    
#	
H	
?+ 
l/