o
    i]-                     @  s   d dl m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	 d dl
mZ d dlZd dlZd dlmZ ddlmZ d	d
lmZ d	dlmZ dddZG dd dZG dd dZdS )    )annotationsN)AsyncIterator)ThreadPoolExecutor)cast)rtc   )logger   )aio)AudioByteStreammime
str | Nonereturnc                 C  s<   | sdS |   } ddddddddddddddd	}|| S )
u   Return the libav *container* short‑name for a given MIME‑type.

    If *mime* is *None* or not recognised, return *None* so that PyAV will
    fall back to auto‑detection.
    Nmp3aacflacwavoggwebmmp4)z
audio/mpegz	audio/mp3zaudio/x-mpegz	audio/aaczaudio/x-aacz
audio/flaczaudio/x-flacz	audio/wavz
audio/wavezaudio/x-wavz
audio/opusz	audio/oggz
audio/webmz	audio/mp4)lowerget)r   _TABLE r   e/var/www/html/livekit_bhavya/venv/lib/python3.10/site-packages/livekit/agents/utils/codecs/decoder.py_mime_to_av_format#   s&   
r   c                   @  sD   e Zd ZdZdddZddd	ZddddZdddZdddZdS )StreamBufferz{
    A thread-safe buffer that behaves like an IO stream.
    Allows writing from one thread and reading from another.
    r   Nonec                 C  s,   t  | _t | _t| j| _d| _d S )NF)	ioBytesIO_buffer	threadingLock_lock	Condition_data_available_eofselfr   r   r   __init__G   s   


zStreamBuffer.__init__databytesc                 C  sR   | j  | jdtj | j| | j   W d   dS 1 s"w   Y  dS )z.Write data to the buffer from a writer thread.r   N)r%   r    seekr   SEEK_ENDwrite
notify_all)r(   r*   r   r   r   r.   M   s
   "zStreamBuffer.writesizeintc                 C  s   | j jrdS | jC 	 | j jr	 W d   dS | j d | j |}|r:| j  }t|| _ |W  d   S | jrF	 W d   dS | j  q1 sOw   Y  dS )z-Read data from the buffer in a reader thread.    TNr   )	r    closedr%   r,   readr   r   r&   wait)r(   r1   r*   	remainingr   r   r   r5   T   s(   

zStreamBuffer.readc                 C  s<   | j  d| _| j   W d   dS 1 sw   Y  dS )z)Signal that no more data will be written.TN)r%   r&   r/   r'   r   r   r   	end_inputm   s   "zStreamBuffer.end_inputc                 C  s   | j   d S N)r    closer'   r   r   r   r:   s   s   zStreamBuffer.closeNr   r   )r*   r+   r   r   )r0   )r1   r2   r   r+   )	__name__
__module____qualname____doc__r)   r.   r5   r8   r:   r   r   r   r   r   A   s    


r   c                   @  sj   e Zd ZdZddddd!ddZd"ddZd#ddZd#ddZd#ddZd$ddZ	d%ddZ
d#dd ZdS )&AudioStreamDecoderzA class that can be used to decode audio stream into PCM AudioFrames.

    Decoders are stateful, and it should not be reused across multiple streams. Each decoder
    is designed to decode a single stream.
    i     N)sample_ratenum_channelsformatrB   
int | NonerC   rD   r   c                C  sx   || _ d| _|dkrd| _|r| nd | _t| j| _tjtj	  | _
d| _d| _t | _t | _tddd| _d S )Nmonor	   stereoFrA   AudioDecoder)max_workersthread_name_prefix)_sample_rate_layoutr   
_mime_typer   
_av_formatr
   Chanr   
AudioFrame
_output_ch_closed_startedr   
_input_bufasyncioget_event_loop_loopr   	_executor)r(   rB   rC   rD   r   r   r   r)   ~   s   
zAudioStreamDecoder.__init__chunkr+   r   r   c                 C  sF   | j | | js!d| _| jdkr| jn| j}| j| j| d S d S )NTr   )	rT   r.   rS   rN   _decode_wav_loop_decode_looprW   run_in_executorrX   )r(   rY   targetr   r   r   push   s   zAudioStreamDecoder.pushc                 C  s"   | j   | js| j  d S d S r9   )rT   r8   rS   rQ   r:   r'   r   r   r   r8      s   
zAudioStreamDecoder.end_inputc                 C  s  d }d }zzt j| jd| jdddddddddd	}| jttt jjj	j
t jjjj
B O  _t|jjd
kr:td|jjd
 }| jd usJ| jd urTt jd| j| jd}||D ]L}| jrs W W | j| jj |rq|  d S d S |r{||}n|g}|D ]$}t|jj}| j| jjtj|   |t|j!t|j"| d qqYW n t#y   t$%d Y nw W | j| jj |r|  d S d S | j| jj |r|  w w )Nr   320znobuffer+flush_packets	low_delaydirect)	probesizeanalyzedurationfflagsflagsreorder_queue_size	max_delay	avioflags)moderD   buffer_sizeoptionsr   zno audio stream founds16)rD   layoutrate)r*   rC   rB   samples_per_channelzerror decoding audio)&avopenrT   rN   rh   r   r2   	containerFlags	no_buffervalueflush_packetslenstreamsaudio
ValueErrorrK   rL   AudioResamplerdecoderR   rW   call_soon_threadsaferQ   r:   resamplerp   channelssend_nowaitr   rP   
to_ndarraytobytesrB   samples	Exceptionr   	exception)r(   ru   	resampleraudio_streamframeframesf	nchannelsr   r   r   r[      s|   


zAudioStreamDecoder._decode_loopc              	     s  zDzd}t |dk r&jdt | }|std||7 }t |dk s|dd dks6|dd dkr=td	|	 jd}t |dk rNtdtd|\}}d}|}|dkr{jtd|}|smtd||7 }|t |8 }|dks^|dkrtd|dd \}	}
}}}}|	dkrtd|	 nq>	 jd}t |dk rtdtd|\}}|dkrn |}|dkrوjtd|}|std|t |8 }|dksqt||
d}jdurt	j
|j|
dnd d! fdd}	 jd}|sn||}|D ]}|| q
q| D ]}|| qW n ty/   td  Y nw W jjj dS W jjj dS jjj w )"zDecode wav data from the buffer without ffmpeg, parse header and emit PCM frames.

        This can be much faster than using ffmpeg, as we are emitting frames as quickly as possible.
        r3      z#Invalid WAV file: incomplete headerN   s   RIFF   s   WAVEz%Invalid WAV file: missing RIFF/WAVE: Tz-Invalid WAV file: incomplete fmt chunk headerz<4sIr   i   z+Invalid WAV file: incomplete fmt chunk datas   fmt z<HHIIHH   rA   zUnsupported WAV audio format: z.Invalid WAV file: incomplete data chunk headers   dataz5Invalid WAV file: incomplete chunk while seeking data)rB   rC   )
input_rateoutput_raterC   r   rtc.AudioFramer   r   c                   s@    sj jj|  d S  | D ]}j jj| qd S r9   )rW   r   rQ   r   r^   )r   resampled_framer   r(   r   r   resample_and_push%  s   z>AudioStreamDecoder._decode_wav_loop.<locals>.resample_and_pushzerror decoding wav)r   r   r   r   )rz   rT   r5   r}   structunpackminr   rK   r   r~   r^   flushr   r   r   rW   r   rQ   r:   )r(   headerrY   
sub_headerchunk_id
chunk_sizer*   r7   partaudio_formatwave_channels	wave_rate_bits_per_sampleto_skipskippedbstreamr   r   	rtc_framer   r   r   rZ      s    

&z#AudioStreamDecoder._decode_wav_loopAsyncIterator[rtc.AudioFrame]c                 C  s   | S r9   r   r'   r   r   r   	__aiter__?  s   zAudioStreamDecoder.__aiter__r   c                   s   | j  I d H S r9   )rQ   	__anext__r'   r   r   r   r   B  s   zAudioStreamDecoder.__anext__c                   sX   | j rd S |   d| _ | j  | jsd S | j2 z3 d H W }q6 | jjddd d S )NTF)r6   cancel_futures)rR   r8   rT   r:   rS   rQ   rX   shutdown)r(   r   r   r   r   acloseE  s   
zAudioStreamDecoder.aclose)rB   rE   rC   rE   rD   r   )rY   r+   r   r   r;   )r   r   )r   r   )r<   r=   r>   r?   r)   r^   r8   r[   rZ   r   r   r   r   r   r   r   r@   w   s    	



@
\
r@   )r   r   r   r   )
__future__r   rU   r   r   r!   collections.abcr   concurrent.futuresr   typingr   rs   av.containerlivekitr   logr    r
   r|   r   r   r   r@   r   r   r   r   <module>   s"   
6