o
    diD                     @   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 d dlm	Z	m
Z
 d dlmZ d dlmZ ddlmZmZ ddlmZmZmZ dd	lmZ dd
lmZ ddlmZ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%m&Z&m'Z'm(Z(m)Z)m*Z*m+Z+m,Z,m-Z-m.Z.m/Z/m0Z0m1Z1m2Z2m3Z3 ddl4m5Z5m6Z6m7Z7 ddl8m9Z9m:Z:m;Z;m<Z< e=e>Z?dZ@deAfddZBG dd dZCG dd dZDdS )    N)Callable)OptionalUnion)
AudioFrame)Frame   )clockrtp)get_capabilitiesget_encoderis_rtx)Encoder)InvalidStateError)MediaStreamErrorMediaStreamTrack)RTCDtlsTransport)RTCRtpCapabilitiesRTCRtpCodecParametersRTCRtpSendParameters)RTCP_PSFB_APPRTCP_PSFB_FIRRTCP_PSFB_PLIRTCP_RTPFB_NACKRTP_HISTORY_SIZEAnyRtcpPacketRtcpByePacketRtcpPsfbPacketRtcpRrPacketRtcpRtpfbPacketRtcpSdesPacketRtcpSenderInfoRtcpSourceInfoRtcpSrPacket	RtpPacketunpack_remb_fciwrap_rtx)RTCOutboundRtpStreamStatsRTCRemoteInboundRtpStreamStatsRTCStatsReport)random16random32
uint16_add
uint32_addg333333?returnc                   C   s
   t  d S )a  
    Generate a random RTP sequence number.

    The sequence number is chosen in the lower half of the allowed range in
    order to avoid wraparounds which break SRTP decryption.

    See:
    https://chromiumdash.appspot.com/commit/13b327b05fa3788b4daa9c3463e13282824cb320
    i   )r)    r.   r.   G/home/ubuntu/.local/lib/python3.10/site-packages/aiortc/rtcrtpsender.pyrandom_sequence_number7   s   

r0   c                   @   s&   e Zd Zdee dedefddZdS )RTCEncodedFramepayloads	timestampaudio_levelc                 C   s   || _ || _|| _d S N)r2   r3   r4   )selfr2   r3   r4   r.   r.   r/   __init__E   s   
zRTCEncodedFrame.__init__N)__name__
__module____qualname__listbytesintr7   r.   r.   r.   r/   r1   D   s    r1   c                   @   sX  e Zd ZdZdeeef deddfddZe	defdd	Z
e	defd
dZe	defddZededefddZdefddZdee ddfddZdeddfddZdeddfddZd3ddZdeddfddZd edee fd!d"Zd#eddfd$d%Zd3d&d'Zd eddfd(d)Z d3d*d+Z!d,e"e ddfd-d.Z#d/ed0e$ddfd1d2Z%dS )4RTCRtpSendera{  
    The :class:`RTCRtpSender` interface provides the ability to control and
    obtain details about how a particular :class:`MediaStreamTrack` is encoded
    and sent to a remote peer.

    :param trackOrKind: Either a :class:`MediaStreamTrack` instance or a
                         media kind (`'audio'` or `'video'`).
    :param transport: An :class:`RTCDtlsTransport`.
    trackOrKind	transportr-   Nc                    s>  |j dkrtt|tr|j _ | n| _ d  d  _t  _	t  _
tt  _d _d  _d _t  _d  _t  _t  _t  _d  _i  _t  _t  _d  _ d  _!t"  _#d _$t%  _&| _'d  _(d  _)d _*d _+d _,d _-d  _.dd  _/t01t2j3r fdd _/d S d S )NclosedTFr   c                  W   s   d S r5   r.   )argsr.   r.   r/   <lambda>   s    z'RTCRtpSender.__init__.<locals>.<lambda>c                    s   t jd|   jg|R  S )NzRTCRtpSender(%s) )loggerdebug_RTCRtpSender__kind)msgrB   r6   r.   r/   rC      s
    )4stater   
isinstancer   kindrF   replaceTrack_RTCRtpSender__cnamer*   _ssrc	_rtx_ssrcstruuiduuid4
_stream_id_enabled_RTCRtpSender__encoder_RTCRtpSender__force_keyframeasyncioget_event_loop_RTCRtpSender__loop_RTCRtpSender__midEvent_RTCRtpSender__rtp_exitedr	   HeaderExtensionsMap(_RTCRtpSender__rtp_header_extensions_map_RTCRtpSender__rtp_started_RTCRtpSender__rtp_task_RTCRtpSender__rtp_history_RTCRtpSender__rtcp_exited_RTCRtpSender__rtcp_started_RTCRtpSender__rtcp_task_RTCRtpSender__rtx_payload_typer0   "_RTCRtpSender__rtx_sequence_number_RTCRtpSender__startedr(   _RTCRtpSender__stats_RTCRtpSender__transport_RTCRtpSender__lsr_RTCRtpSender__lsr_time_RTCRtpSender__ntp_timestamp_RTCRtpSender__rtp_timestamp_RTCRtpSender__octet_count_RTCRtpSender__packet_count_RTCRtpSender__rtt_RTCRtpSender__log_debugrD   isEnabledForloggingDEBUG)r6   r?   r@   r.   rH   r/   r7   V   sP   









zRTCRtpSender.__init__c                 C      | j S r5   )rF   rH   r.   r.   r/   rK      s   zRTCRtpSender.kindc                 C   ru   )zU
        The :class:`MediaStreamTrack` which is being handled by the sender.
        )_RTCRtpSender__trackrH   r.   r.   r/   track   s   zRTCRtpSender.trackc                 C   ru   )zk
        The :class:`RTCDtlsTransport` over which media data for the track is
        transmitted.
        ri   rH   r.   r.   r/   r@      s   zRTCRtpSender.transportrK   c                 C   s   t |S )z
        Returns the most optimistic view of the system's capabilities for
        sending media of the given `kind`.

        :rtype: :class:`RTCRtpCapabilities`
        )r
   )r6   rK   r.   r.   r/   getCapabilities   s   zRTCRtpSender.getCapabilitiesc                    sb   | j tt ddtt|  | j| j| j	j
| j| jtt| jd	 | j | j	  | j S )zc
        Returns statistics about the RTP sender.

        :rtype: :class:`RTCStatsReport`
        zoutbound-rtpzoutbound-rtp_)	r3   typeidssrcrK   transportIdpacketsSent	bytesSenttrackId)rh   addr&   r   current_datetimerP   r{   rN   rF   r@   	_stats_idro   rn   rw   update
_get_statsrH   r.   r.   r/   getStats   s    zRTCRtpSender.getStatsrw   c                 C   s,   || _ |d ur|j| _d S tt | _d S r5   )rv   r{   	_track_idrP   rQ   rR   )r6   rw   r.   r.   r/   rL      s   zRTCRtpSender.replaceTrackc                 C   s
   || _ d S r5   rx   )r6   r@   r.   r.   r/   setTransport   s   
zRTCRtpSender.setTransport
parametersc                    s   | j sN|jj| _|j| _| j| | | j	| |j
D ]}t|r4|jd |j
d jkr4|j| _ nqt| |j
d | _t|  | _d| _ dS dS )z
        Attempt to set the parameters controlling the sending of media.

        :param parameters: The :class:`RTCRtpSendParameters` for the sender.
        aptr   TN)rg   rtcpcnamerM   muxIdrZ   ri   _register_rtp_senderr^   	configurecodecsr   r   payloadTypere   rW   ensure_future_run_rtpr`   	_run_rtcprd   )r6   r   codecr.   r.   r/   send   s"   


zRTCRtpSender.sendc                    sl   | j r4| j|  t| j | j I dH  | j	  | j
	  t| j | j I dH  dS dS )z/
        Irreversibly stop the sender.
        N)rg   ri   _unregister_rtp_senderrW   gatherr_   waitrc   r`   cancelrd   r\   rb   rH   r.   r.   r/   stop   s   

"zRTCRtpSender.stoppacketc                    s  t |ttfrht fdd|jD ]S} j|jkr>|jr>t  j	 |jd  } j
d u r2| _
nt j
 dt |   _
 jtt ddtt  |j j jj j|j |j|j j
|jd qd S t |tr|jtkr|jD ]
} |I d H  qud S t |t r|jt!t"fv r #  d S t |t r|jt$krz+t%|j&\}} j'|v r (d|  j)rt* j)d	r| j)_+W d S W d S W d S W d S  t,y   Y d S w d S d S )
Nc                    s   | j  jkS r5   )r|   rN   )xrH   r.   r/   rC      s    z2RTCRtpSender._handle_rtcp_packet.<locals>.<lambda>i   r   zremote-inbound-rtpzremote-inbound-rtp_)r3   rz   r{   r|   rK   r}   packetsReceivedpacketsLostjitterroundTripTimefractionLostz+- receiver estimated maximum bitrate %d bpstarget_bitrate)-rJ   r   r"   filterreportsrj   lsrdlsrtimerk   rp   	RTT_ALPHArh   r   r'   r   r   rP   r{   r|   rF   r@   r   ro   packets_lostr   fraction_lostr   fmtr   lost_retransmitr   r   r   _send_keyframer   r$   fcirN   rq   rU   hasattrr   
ValueError)r6   r   reportrttseqbitratessrcsr.   rH   r/   _handle_rtcp_packet   s`   



z RTCRtpSender._handle_rtcp_packetr   c                    s   | j  I d H }| jsd S d }| jd u rt|| _t|tr@t|tr)t	|}| j
}d| _
| jd | jj||I d H \}}n| j|\}}|sLd S t|||S )NF)rv   recvrT   rU   r   rJ   r   r   r	   compute_audio_level_dbovrV   rY   run_in_executorencodepackr1   )r6   r   datar4   force_keyframer2   r3   r.   r.   r/   _next_encoded_frame&  s&   




z RTCRtpSender._next_encoded_framesequence_numberc                    s   | j |t }|r>|j|kr@| jdur't|| j| j| jd}t| jd| _| 	d| |
| j}| j|I dH  dS dS dS )zF
        Retransmit an RTP packet which was reported as lost.
        N)payload_typer   r|   r   > %s)ra   getr   r   re   r%   rf   rO   r+   rq   	serializer^   r@   	_send_rtp)r6   r   r   packet_bytesr.   r.   r/   r   L  s   
zRTCRtpSender._retransmitc                 C   s
   d| _ dS )z:
        Request the next frame to be a keyframe.
        TN)rV   rH   r.   r.   r/   r   _  s   
zRTCRtpSender._send_keyframec           
   
      s  |  d | j  t }t }z	 | jstdI d H  q| |I d H }|d u r,qt	||j
}t|jD ]x\}}t|j||d}| j|_||_|t|jd krUdpVd|_t d? d@ |j_| j|j_|jd urtd	|j f|j_|  d
| || j|jt < || j}	| j !|	I d H  t | _"|j
| _#|  j$t|7  _$|  j%d7  _%t&|d}q7q tj't(t)fy   Y n t*y   | +t,-  Y nw | jr| j.  d | _d | _/|  d | j0  d S )Nz- RTP startedTg{Gz?)r   r   r3   r   r      i Fr   z- RTP finished)1rq   r_   setr0   r*   rv   rW   sleepr   r,   r3   	enumerater2   r#   r   rN   r|   payloadlenmarkerr   current_ntp_time
extensionsabs_send_timerZ   midr4   ra   r   r   r   r^   r@   r   rl   rm   rn   ro   r+   CancelledErrorConnectionErrorr   	Exception_RTCRtpSender__log_warning	traceback
format_excr   rU   r\   )
r6   r   r   timestamp_origin	enc_framer3   ir   r   r   r.   r.   r/   r   e  sf   





,

zRTCRtpSender._run_rtpc              	      s
  |  d | j  zS	 tdt  I d H  t| jt| j	| j
| jd@ | jd@ ddg}| j	d? d@ | _t | _| jd urV|tt| jd| jd	fgd
gd | |I d H  q tjyh   Y nw t| jgd}| |gI d H  |  d | j  d S )Nz- RTCP startedTg      ?l    )ntp_timestamprtp_timestamppacket_countoctet_count)r|   sender_info   r   utf8)r|   items)chunks)sourcesz- RTCP finished)rq   rc   r   rW   r   randomr"   rN   r    rl   rm   ro   rn   rj   r   rk   rM   appendr   r!   r   
_send_rtcpr   r   rb   )r6   packetsr   r.   r.   r/   r     sJ   



"
zRTCRtpSender._run_rtcpr   c                    sV   d}|D ]}|  d| |t|7 }qz| j|I d H  W d S  ty*   Y d S w )N    r   )rq   r<   r@   r   r   )r6   r   r   r   r.   r.   r/   r     s   zRTCRtpSender._send_rtcprG   rB   c                 G   s    t jd| | jg|R   d S )NzRTCRtpsender(%s) )rD   warningrF   )r6   rG   rB   r.   r.   r/   __log_warning  s    zRTCRtpSender.__log_warning)r-   N)&r8   r9   r:   __doc__r   r   rP   r   r7   propertyrK   rw   r@   classmethodr   ry   r(   r   r   rL   r   r   r   r   r   r   r   r1   r   r=   r   r   r   r   r;   r   objectr   r.   r.   r.   r/   r>   K   sD    


4	
2
&

E1r>   )ErW   rs   r   r   r   rQ   collections.abcr   typingr   r   avr   av.framer    r   r	   r   r
   r   r   codecs.baser   
exceptionsr   mediastreamsr   r   rtcdtlstransportr   rtcrtpparametersr   r   r   r   r   r   r   r   r   r   r   r   r   r   r    r!   r"   r#   r$   r%   statsr&   r'   r(   utilsr)   r*   r+   r,   	getLoggerr8   rD   r   r=   r0   r1   r>   r.   r.   r.   r/   <module>   s2    L
