content_views"
c lass="markdown_views prism-atom-one-dark">
cap="round" d="M5,0 0,2.5 5,5z" id="raphael-marker-bloc k" style="-webkit-tap-highlight-c olor: rgba(0, 0, 0, 0);">
avc odec _send_pac ket和avc odec _rec eive_frame是一对孪生兄弟c ;avc odec _send_pac ket把需要解码的AVPac ket送到解码器中c ;avc odec _rec eive_frame则是得到解码完成后的frame。 这两个函数都是通过调用dec ode_rec eive_frame_internal来实现的。
c odec _send_pac ket__4">avc odec _send_pac ket 作用
把未经过解码的AVPac ket送到AVCodec Context中解码。 FFmpeg的说明如下:
<c ode c lass="prism language-c ">class="token c omment">/**
* Supply raw pac ket data as input to a dec oder.
*
* Internally, this c all will c opy relevant AVCodec Context fields, whic h c an
* influenc e dec oding per-pac ket, and apply them when the pac ket is ac tually
* dec oded. (For example AVCodec Context.skip_frame, whic h might direc t the
* dec oder to drop the frame c ontained by the pac ket sent with this func tion.)
*
* @return 0 on suc c ess, otherwise negative error c ode:
* AVERROR(EAGAIN): input is not ac c epted in the c urrent state - user
* must read output with avc odec _rec eive_frame() (onc e
* all output is read, the pac ket should be resent, and
* the c all will not fail with EAGAIN).
* AVERROR_EOF: the dec oder has been flushed, and no new pac kets c an
* be sent to it (also returned if more than 1 flush
* pac ket is sent)
* AVERROR(EINVAL): c odec not opened, it is an enc oder, or requires flush
* AVERROR(ENOMEM): failed to add pac ket to internal queue, or similar
* other errors: legitimate dec oding errors
*/
class="token keyword">int class="token func tion">avc odec _send_pac ket class="token punc tuation">( AVCodec Context class="token operator">* avc txclass="token punc tuation">, class="token keyword">c onst AVPac ket class="token operator">* avpktclass="token punc tuation">) class="token punc tuation">;
class="token c omment">/**
* Supply a raw video or audio frame to the enc oder. Use avc odec _rec eive_pac ket()
* to retrieve buffered output pac kets.
* @return 0 on suc c ess, otherwise negative error c ode:
* AVERROR(EAGAIN): input is not ac c epted in the c urrent state - user
* must read output with avc odec _rec eive_pac ket() (onc e
* all output is read, the pac ket should be resent, and
* the c all will not fail with EAGAIN).
* AVERROR_EOF: the enc oder has been flushed, and no new frames c an
* be sent to it
* AVERROR(EINVAL): c odec not opened, refc ounted_frames not set, it is a
* dec oder, or requires flush
* AVERROR(ENOMEM): failed to add pac ket to internal queue, or similar
* other errors: legitimate enc oding errors
*/
class="token keyword">int class="token func tion">avc odec _send_frame class="token punc tuation">( AVCodec Context class="token operator">* avc txclass="token punc tuation">, class="token keyword">c onst AVFrame class="token operator">* frameclass="token punc tuation">) class="token punc tuation">;
c ode>
简而言之c ;avc odec _send_pac ket就是把AVPac ket送到AVCodec Contextc ;然后让AVCodec Context解码。avc odec _rec eive_frame获得解码后的AVFrame。 需要注意的是c ;AVCodec Context必须经过avc odec _open2函数打开c ;输入的AVPac ket会在内部增加一个refc ;所以如果要freec ;外部也应该调用av_pac ket_unref。
c odec _send_pac ket__50">avc odec _send_pac ket 源码
把avpk送到avc i->bsf中c ;等待解码。然后通过判断avc i->buffer_frame->buf[0]是否null来决定是否调用dec ode_rec eive_frame_internal来接受解码后的frame。
<c ode c lass="prism language-c ">class="token keyword">int attribute_align_arg class="token func tion">avc odec _send_pac ket class="token punc tuation">( AVCodec Context class="token operator">* avc txclass="token punc tuation">, class="token keyword">c onst AVPac ket class="token operator">* avpktclass="token punc tuation">)
class="token punc tuation">{
AVCodec Internal class="token operator">* avc i class="token operator">= avc txclass="token operator">-> internalclass="token punc tuation">;
class="token keyword">int retclass="token punc tuation">;
class="token c omment">// 未open和编码器都不行
class="token keyword">if class="token punc tuation">( class="token operator">! class="token func tion">avc odec _is_open class="token punc tuation">( avc txclass="token punc tuation">) class="token operator">|| class="token operator">! class="token func tion">av_c odec _is_dec oder class="token punc tuation">( avc txclass="token operator">-> c odec class="token punc tuation">) class="token punc tuation">)
class="token keyword">return class="token func tion">AVERROR class="token punc tuation">( EINVALclass="token punc tuation">) class="token punc tuation">;
class="token c omment">// 检测是否应该先flush
class="token keyword">if class="token punc tuation">( avc txclass="token operator">-> internalclass="token operator">-> drainingclass="token punc tuation">)
class="token keyword">return AVERROR_EOFclass="token punc tuation">;
class="token keyword">if class="token punc tuation">( avpkt class="token operator">&& class="token operator">! avpktclass="token operator">-> size class="token operator">&& avpktclass="token operator">-> dataclass="token punc tuation">)
class="token keyword">return class="token func tion">AVERROR class="token punc tuation">( EINVALclass="token punc tuation">) class="token punc tuation">;
class="token func tion">av_pac ket_unref class="token punc tuation">( avc iclass="token operator">-> buffer_pktclass="token punc tuation">) class="token punc tuation">;
class="token c omment">// avc i->buffer_pkt也referenc e输入的avpkt
class="token c omment">// 相当于一次c opy (不一定是深c opy)
class="token keyword">if class="token punc tuation">( avpkt class="token operator">&& class="token punc tuation">( avpktclass="token operator">-> data class="token operator">|| avpktclass="token operator">-> side_data_elemsclass="token punc tuation">) class="token punc tuation">) class="token punc tuation">{
ret class="token operator">= class="token func tion">av_pac ket_ref class="token punc tuation">( avc iclass="token operator">-> buffer_pktclass="token punc tuation">, avpktclass="token punc tuation">) class="token punc tuation">;
class="token keyword">if class="token punc tuation">( ret class="token operator">< class="token number">0 class="token punc tuation">)
class="token keyword">return retclass="token punc tuation">;
class="token punc tuation">}
class="token c omment">// 把avc i->buffer_pkt送到avc i->bsf中
class="token c omment">// 即将avc i->buffer_pkt c opy到avc i->bsf->internal->buffer_pktc ;然后可以经过bsf。
class="token c omment">// AVBSFContext一般是对AVPac ket进行某些格式上的转换c ;比如对h264来说c ;存在AVCC和ANNEXB两种格式c ;这里就是把AVCC格式转换成为ANNEXB
ret class="token operator">= class="token func tion">av_bsf_send_pac ket class="token punc tuation">( avc iclass="token operator">-> bsfclass="token punc tuation">, avc iclass="token operator">-> buffer_pktclass="token punc tuation">) class="token punc tuation">;
class="token keyword">if class="token punc tuation">( ret class="token operator">< class="token number">0 class="token punc tuation">) class="token punc tuation">{
class="token func tion">av_pac ket_unref class="token punc tuation">( avc iclass="token operator">-> buffer_pktclass="token punc tuation">) class="token punc tuation">;
class="token keyword">return retclass="token punc tuation">;
class="token punc tuation">}
class="token keyword">if class="token punc tuation">( class="token operator">! avc iclass="token operator">-> buffer_frameclass="token operator">-> bufclass="token punc tuation">[ class="token number">0 class="token punc tuation">] class="token punc tuation">) class="token punc tuation">{
class="token c omment">//这个函数会在avc odec _send_pac ket或者avc odec _rec eive_frame中调用
class="token c omment">//avc i->buffer_frame->buf[0]为nullc ;就在avc odec _send_pac ket中调用
class="token c omment">//avc i->buffer_frame->buf[0]不为nullc ;就在avc odec _rec eive_frame中调用
class="token c omment">//dec ode_rec eive_frame_internal中
ret class="token operator">= class="token func tion">dec ode_rec eive_frame_internal class="token punc tuation">( avc txclass="token punc tuation">, avc iclass="token operator">-> buffer_frameclass="token punc tuation">) class="token punc tuation">;
class="token keyword">if class="token punc tuation">( ret class="token operator">< class="token number">0 class="token operator">&& ret class="token operator">!= class="token func tion">AVERROR class="token punc tuation">( EAGAINclass="token punc tuation">) class="token operator">&& ret class="token operator">!= AVERROR_EOFclass="token punc tuation">)
class="token keyword">return retclass="token punc tuation">;
class="token punc tuation">}
class="token keyword">return class="token number">0 class="token punc tuation">;
class="token punc tuation">}
c ode>
c odec _rec eive_frame__100">avc odec _rec eive_frame 源码
<c ode c lass="prism language-c ">class="token keyword">int attribute_align_arg class="token func tion">avc odec _rec eive_frame class="token punc tuation">( AVCodec Context class="token operator">* avc txclass="token punc tuation">, AVFrame class="token operator">* frameclass="token punc tuation">)
class="token punc tuation">{
AVCodec Internal class="token operator">* avc i class="token operator">= avc txclass="token operator">-> internalclass="token punc tuation">;
class="token keyword">int retclass="token punc tuation">, c hangedclass="token punc tuation">;
class="token func tion">av_frame_unref class="token punc tuation">( frameclass="token punc tuation">) class="token punc tuation">;
class="token c omment">// 判断是否调用过avc odec _open2函数c ;是否为解码器
class="token keyword">if class="token punc tuation">( class="token operator">! class="token func tion">avc odec _is_open class="token punc tuation">( avc txclass="token punc tuation">) class="token operator">|| class="token operator">! class="token func tion">av_c odec _is_dec oder class="token punc tuation">( avc txclass="token operator">-> c odec class="token punc tuation">) class="token punc tuation">)
class="token keyword">return class="token func tion">AVERROR class="token punc tuation">( EINVALclass="token punc tuation">) class="token punc tuation">;
class="token c omment">// 根据avc i->buffer_frame->buf[0]判断是否存在解码完成的帧c ;如果存在就直接move到frame中。
class="token c omment">// 如果没有就调用dec ode_rec eive_frame_internal把AVPac ket送去解码线程c ;然后获得解码之后的AVFrame。
class="token keyword">if class="token punc tuation">( avc iclass="token operator">-> buffer_frameclass="token operator">-> bufclass="token punc tuation">[ class="token number">0 class="token punc tuation">] class="token punc tuation">) class="token punc tuation">{
class="token func tion">av_frame_move_ref class="token punc tuation">( frameclass="token punc tuation">, avc iclass="token operator">-> buffer_frameclass="token punc tuation">) class="token punc tuation">;
class="token punc tuation">} class="token keyword">else class="token punc tuation">{
ret class="token operator">= class="token func tion">dec ode_rec eive_frame_internal class="token punc tuation">( avc txclass="token punc tuation">, frameclass="token punc tuation">) class="token punc tuation">;
class="token keyword">if class="token punc tuation">( ret class="token operator">< class="token number">0 class="token punc tuation">)
class="token keyword">return retclass="token punc tuation">;
class="token punc tuation">}
class="token keyword">if class="token punc tuation">( avc txclass="token operator">-> c odec _type class="token operator">== AVMEDIA_TYPE_VIDEOclass="token punc tuation">) class="token punc tuation">{
ret class="token operator">= class="token func tion">apply_c ropping class="token punc tuation">( avc txclass="token punc tuation">, frameclass="token punc tuation">) class="token punc tuation">;
class="token keyword">if class="token punc tuation">( ret class="token operator">< class="token number">0 class="token punc tuation">) class="token punc tuation">{
class="token func tion">av_frame_unref class="token punc tuation">( frameclass="token punc tuation">) class="token punc tuation">;
class="token keyword">return retclass="token punc tuation">;
class="token punc tuation">}
class="token punc tuation">}
avc txclass="token operator">-> frame_numberclass="token operator">++ class="token punc tuation">;
class="token keyword">if class="token punc tuation">( avc txclass="token operator">-> flags class="token operator">& AV_CODEC_FLAG_DROPCHANGEDclass="token punc tuation">) class="token punc tuation">{
class="token keyword">if class="token punc tuation">( avc txclass="token operator">-> frame_number class="token operator">== class="token number">1 class="token punc tuation">) class="token punc tuation">{
avc iclass="token operator">-> initial_format class="token operator">= frameclass="token operator">-> formatclass="token punc tuation">;
class="token keyword">switc h class="token punc tuation">( avc txclass="token operator">-> c odec _typeclass="token punc tuation">) class="token punc tuation">{
class="token keyword">c ase AVMEDIA_TYPE_VIDEOclass="token operator">:
avc iclass="token operator">-> initial_width class="token operator">= frameclass="token operator">-> widthclass="token punc tuation">;
avc iclass="token operator">-> initial_height class="token operator">= frameclass="token operator">-> heightclass="token punc tuation">;
class="token keyword">break class="token punc tuation">;
class="token keyword">c ase AVMEDIA_TYPE_AUDIOclass="token operator">:
avc iclass="token operator">-> initial_sample_rate class="token operator">= frameclass="token operator">-> sample_rate class="token operator">? frameclass="token operator">-> sample_rate class="token operator">:
avc txclass="token operator">-> sample_rateclass="token punc tuation">;
avc iclass="token operator">-> initial_c hannels class="token operator">= frameclass="token operator">-> c hannelsclass="token punc tuation">;
avc iclass="token operator">-> initial_c hannel_layout class="token operator">= frameclass="token operator">-> c hannel_layoutclass="token punc tuation">;
class="token keyword">break class="token punc tuation">;
class="token punc tuation">}
class="token punc tuation">}
class="token keyword">if class="token punc tuation">( avc txclass="token operator">-> frame_number class="token operator">> class="token number">1 class="token punc tuation">) class="token punc tuation">{
c hanged class="token operator">= avc iclass="token operator">-> initial_format class="token operator">!= frameclass="token operator">-> formatclass="token punc tuation">;
class="token keyword">switc h class="token punc tuation">( avc txclass="token operator">-> c odec _typeclass="token punc tuation">) class="token punc tuation">{
class="token keyword">c ase AVMEDIA_TYPE_VIDEOclass="token operator">:
c hanged class="token operator">|= avc iclass="token operator">-> initial_width class="token operator">!= frameclass="token operator">-> width class="token operator">||
avc iclass="token operator">-> initial_height class="token operator">!= frameclass="token operator">-> heightclass="token punc tuation">;
class="token keyword">break class="token punc tuation">;
class="token keyword">c ase AVMEDIA_TYPE_AUDIOclass="token operator">:
c hanged class="token operator">|= avc iclass="token operator">-> initial_sample_rate class="token operator">!= frameclass="token operator">-> sample_rate class="token operator">||
avc iclass="token operator">-> initial_sample_rate class="token operator">!= avc txclass="token operator">-> sample_rate class="token operator">||
avc iclass="token operator">-> initial_c hannels class="token operator">!= frameclass="token operator">-> c hannels class="token operator">||
avc iclass="token operator">-> initial_c hannel_layout class="token operator">!= frameclass="token operator">-> c hannel_layoutclass="token punc tuation">;
class="token keyword">break class="token punc tuation">;
class="token punc tuation">}
class="token keyword">if class="token punc tuation">( c hangedclass="token punc tuation">) class="token punc tuation">{
avc iclass="token operator">-> c hanged_frames_droppedclass="token operator">++ class="token punc tuation">;
class="token func tion">av_log class="token punc tuation">( avc txclass="token punc tuation">, AV_LOG_INFOclass="token punc tuation">, class="token string">"dropped c hanged frame #%d pts %" PRId64
class="token string">" drop c ount: %d \n" class="token punc tuation">,
avc txclass="token operator">-> frame_numberclass="token punc tuation">, frameclass="token operator">-> ptsclass="token punc tuation">,
avc iclass="token operator">-> c hanged_frames_droppedclass="token punc tuation">) class="token punc tuation">;
class="token func tion">av_frame_unref class="token punc tuation">( frameclass="token punc tuation">) class="token punc tuation">;
class="token keyword">return AVERROR_INPUT_CHANGEDclass="token punc tuation">;
class="token punc tuation">}
class="token punc tuation">}
class="token punc tuation">}
class="token keyword">return class="token number">0 class="token punc tuation">;
class="token punc tuation">}
c ode>
c ode_rec eive_frame_internal__181">dec ode_rec eive_frame_internal 源码
获取解码后的frame。
<c ode c lass="prism language-c ">class="token keyword">static class="token keyword">int class="token func tion">dec ode_rec eive_frame_internal class="token punc tuation">( AVCodec Context class="token operator">* avc txclass="token punc tuation">, AVFrame class="token operator">* frameclass="token punc tuation">)
class="token punc tuation">{
AVCodec Internal class="token operator">* avc i class="token operator">= avc txclass="token operator">-> internalclass="token punc tuation">;
class="token keyword">int retclass="token punc tuation">;
class="token func tion">av_assert0 class="token punc tuation">( class="token operator">! frameclass="token operator">-> bufclass="token punc tuation">[ class="token number">0 class="token punc tuation">] class="token punc tuation">) class="token punc tuation">;
class="token c omment">// 只有少部分解码器会实现这个函数c ;实现这个函数的解码器不会实现多线程解码c ;比如mjpeg
class="token keyword">if class="token punc tuation">( avc txclass="token operator">-> c odec class="token operator">-> rec eive_frameclass="token punc tuation">) class="token punc tuation">{
ret class="token operator">= avc txclass="token operator">-> c odec class="token operator">-> class="token func tion">rec eive_frame class="token punc tuation">( avc txclass="token punc tuation">, frameclass="token punc tuation">) class="token punc tuation">;
class="token keyword">if class="token punc tuation">( ret class="token operator">!= class="token func tion">AVERROR class="token punc tuation">( EAGAINclass="token punc tuation">) class="token punc tuation">)
class="token func tion">av_pac ket_unref class="token punc tuation">( avc iclass="token operator">-> last_pkt_propsclass="token punc tuation">) class="token punc tuation">;
class="token punc tuation">} class="token keyword">else
class="token c omment">//大部分都是调用这个函数
ret class="token operator">= class="token func tion">dec ode_simple_rec eive_frame class="token punc tuation">( avc txclass="token punc tuation">, frameclass="token punc tuation">) class="token punc tuation">;
class="token keyword">if class="token punc tuation">( ret class="token operator">== AVERROR_EOFclass="token punc tuation">)
avc iclass="token operator">-> draining_done class="token operator">= class="token number">1 class="token punc tuation">;
class="token keyword">if class="token punc tuation">( class="token operator">! retclass="token punc tuation">) class="token punc tuation">{
frameclass="token operator">-> best_effort_timestamp class="token operator">= class="token func tion">guess_c orrec t_pts class="token punc tuation">( avc txclass="token punc tuation">,
frameclass="token operator">-> ptsclass="token punc tuation">,
frameclass="token operator">-> pkt_dtsclass="token punc tuation">) class="token punc tuation">;
class="token c omment">/* the only c ase where dec ode data is not set should be dec oders
* that do not c all ff_get_buffer() */
class="token func tion">av_assert0 class="token punc tuation">( class="token punc tuation">( frameclass="token operator">-> private_ref class="token operator">&& frameclass="token operator">-> private_refclass="token operator">-> size class="token operator">== class="token keyword">sizeof class="token punc tuation">( FrameDec odeDataclass="token punc tuation">) class="token punc tuation">) class="token operator">||
class="token operator">! class="token punc tuation">( avc txclass="token operator">-> c odec class="token operator">-> c apabilities class="token operator">& AV_CODEC_CAP_DR1class="token punc tuation">) class="token punc tuation">) class="token punc tuation">;
class="token keyword">if class="token punc tuation">( frameclass="token operator">-> private_refclass="token punc tuation">) class="token punc tuation">{
FrameDec odeData class="token operator">* fdd class="token operator">= class="token punc tuation">( FrameDec odeDataclass="token operator">* class="token punc tuation">) frameclass="token operator">-> private_refclass="token operator">-> dataclass="token punc tuation">;
class="token keyword">if class="token punc tuation">( fddclass="token operator">-> post_proc essclass="token punc tuation">) class="token punc tuation">{
ret class="token operator">= fddclass="token operator">-> class="token func tion">post_proc ess class="token punc tuation">( avc txclass="token punc tuation">, frameclass="token punc tuation">) class="token punc tuation">;
class="token keyword">if class="token punc tuation">( ret class="token operator">< class="token number">0 class="token punc tuation">) class="token punc tuation">{
class="token func tion">av_frame_unref class="token punc tuation">( frameclass="token punc tuation">) class="token punc tuation">;
class="token keyword">return retclass="token punc tuation">;
class="token punc tuation">}
class="token punc tuation">}
class="token punc tuation">}
class="token punc tuation">}
class="token c omment">/* free the per-frame dec ode data */
class="token func tion">av_buffer_unref class="token punc tuation">( class="token operator">& frameclass="token operator">-> private_refclass="token punc tuation">) class="token punc tuation">;
class="token keyword">return retclass="token punc tuation">;
class="token punc tuation">}
c ode>
c ode_simple_rec eive_frame__234">dec ode_simple_rec eive_frame 源码
通过调用dec ode_simple_internal来实现解码AVPac ketc ;然后获取解码后的frame。
<c ode c lass="prism language-c ">class="token keyword">static class="token keyword">int class="token func tion">dec ode_simple_rec eive_frame class="token punc tuation">( AVCodec Context class="token operator">* avc txclass="token punc tuation">, AVFrame class="token operator">* frameclass="token punc tuation">)
class="token punc tuation">{
class="token keyword">int retclass="token punc tuation">;
class="token c lass-name">int64_t disc arded_samples class="token operator">= class="token number">0 class="token punc tuation">;
class="token keyword">while class="token punc tuation">( class="token operator">! frameclass="token operator">-> bufclass="token punc tuation">[ class="token number">0 class="token punc tuation">] class="token punc tuation">) class="token punc tuation">{
class="token keyword">if class="token punc tuation">( disc arded_samples class="token operator">> avc txclass="token operator">-> max_samplesclass="token punc tuation">)
class="token keyword">return class="token func tion">AVERROR class="token punc tuation">( EAGAINclass="token punc tuation">) class="token punc tuation">;
ret class="token operator">= class="token func tion">dec ode_simple_internal class="token punc tuation">( avc txclass="token punc tuation">, frameclass="token punc tuation">, class="token operator">& disc arded_samplesclass="token punc tuation">) class="token punc tuation">;
class="token keyword">if class="token punc tuation">( ret class="token operator">< class="token number">0 class="token punc tuation">)
class="token keyword">return retclass="token punc tuation">;
class="token punc tuation">}
class="token keyword">return class="token number">0 class="token punc tuation">;
class="token punc tuation">}
c ode>
c ode_simple_internal__254">dec ode_simple_internal 源码
avc odec _send_pac ket和avc odec _rec eive_frame中最核心的函数c ;大部分的编码格式都会调用到这里解码。
<c ode c lass="prism language-c ">class="token c omment">/*
* The c ore of the rec eive_frame_wrapper for the dec oders implementing
* the simple API. Certain dec oders might c onsume partial pac kets without
* returning any output, so this func tion needs to be c alled in a loop until it
* returns EAGAIN.
**/
class="token keyword">static class="token keyword">inline class="token keyword">int class="token func tion">dec ode_simple_internal class="token punc tuation">( AVCodec Context class="token operator">* avc txclass="token punc tuation">, AVFrame class="token operator">* frameclass="token punc tuation">, class="token c lass-name">int64_t class="token operator">* disc arded_samplesclass="token punc tuation">)
class="token punc tuation">{
AVCodec Internal class="token operator">* avc i class="token operator">= avc txclass="token operator">-> internalclass="token punc tuation">;
Dec odeSimpleContext class="token operator">* ds class="token operator">= class="token operator">& avc iclass="token operator">-> dsclass="token punc tuation">;
AVPac ket class="token operator">* pkt class="token operator">= dsclass="token operator">-> in_pktclass="token punc tuation">;
class="token keyword">int got_frameclass="token punc tuation">, ac tual_got_frameclass="token punc tuation">;
class="token keyword">int retclass="token punc tuation">;
class="token keyword">if class="token punc tuation">( class="token operator">! pktclass="token operator">-> data class="token operator">&& class="token operator">! avc iclass="token operator">-> drainingclass="token punc tuation">) class="token punc tuation">{
class="token func tion">av_pac ket_unref class="token punc tuation">( pktclass="token punc tuation">) class="token punc tuation">;
class="token c omment">// 从avc i->bsf中获得AVPac ketc ;然后设置到pkt中
ret class="token operator">= class="token func tion">ff_dec ode_get_pac ket class="token punc tuation">( avc txclass="token punc tuation">, pktclass="token punc tuation">) class="token punc tuation">;
class="token keyword">if class="token punc tuation">( ret class="token operator">< class="token number">0 class="token operator">&& ret class="token operator">!= AVERROR_EOFclass="token punc tuation">)
class="token keyword">return retclass="token punc tuation">;
class="token punc tuation">}
class="token c omment">// Some c odec s (at least wma lossless) will c rash when feeding drain pac kets
class="token c omment">// after EOF was signaled.
class="token keyword">if class="token punc tuation">( avc iclass="token operator">-> draining_doneclass="token punc tuation">)
class="token keyword">return AVERROR_EOFclass="token punc tuation">;
class="token keyword">if class="token punc tuation">( class="token operator">! pktclass="token operator">-> data class="token operator">&&
class="token operator">! class="token punc tuation">( avc txclass="token operator">-> c odec class="token operator">-> c apabilities class="token operator">& AV_CODEC_CAP_DELAY class="token operator">||
avc txclass="token operator">-> ac tive_thread_type class="token operator">& FF_THREAD_FRAMEclass="token punc tuation">) class="token punc tuation">)
class="token keyword">return AVERROR_EOFclass="token punc tuation">;
got_frame class="token operator">= class="token number">0 class="token punc tuation">;
class="token c omment">// 多线程解码 或者 单线程
class="token keyword">if class="token punc tuation">( HAVE_THREADS class="token operator">&& avc txclass="token operator">-> ac tive_thread_type class="token operator">& FF_THREAD_FRAMEclass="token punc tuation">) class="token punc tuation">{
class="token c omment">// 多线程解码
class="token c omment">// 先调用avc odec _open2打开多个解码线程c ;然后这里实现多线程解码
ret class="token operator">= class="token func tion">ff_thread_dec ode_frame class="token punc tuation">( avc txclass="token punc tuation">, frameclass="token punc tuation">, class="token operator">& got_frameclass="token punc tuation">, pktclass="token punc tuation">) class="token punc tuation">;
class="token punc tuation">} class="token keyword">else class="token punc tuation">{
class="token c omment">//调用对应AVCodec 的dec ode方法c ;h264默认解码器的话c ;就会调用c lass="tags" href="/tags/FFMPEG.html" title=ffmpeg>ffmpeg内置的h264解码器
ret class="token operator">= avc txclass="token operator">-> c odec class="token operator">-> class="token func tion">dec ode class="token punc tuation">( avc txclass="token punc tuation">, frameclass="token punc tuation">, class="token operator">& got_frameclass="token punc tuation">, pktclass="token punc tuation">) class="token punc tuation">;
class="token keyword">if class="token punc tuation">( class="token operator">! class="token punc tuation">( avc txclass="token operator">-> c odec class="token operator">-> c aps_internal class="token operator">& FF_CODEC_CAP_SETS_PKT_DTSclass="token punc tuation">) class="token punc tuation">)
frameclass="token operator">-> pkt_dts class="token operator">= pktclass="token operator">-> dtsclass="token punc tuation">;
class="token keyword">if class="token punc tuation">( avc txclass="token operator">-> c odec class="token operator">-> type class="token operator">== AVMEDIA_TYPE_VIDEOclass="token punc tuation">) class="token punc tuation">{
class="token keyword">if class="token punc tuation">( class="token operator">! avc txclass="token operator">-> has_b_framesclass="token punc tuation">)
frameclass="token operator">-> pkt_pos class="token operator">= pktclass="token operator">-> posclass="token punc tuation">;
class="token c omment">//FIXME these should be under if(!avc tx->has_b_frames)
class="token c omment">/* get_buffer is supposed to set frame parameters */
class="token keyword">if class="token punc tuation">( class="token operator">! class="token punc tuation">( avc txclass="token operator">-> c odec class="token operator">-> c apabilities class="token operator">& AV_CODEC_CAP_DR1class="token punc tuation">) class="token punc tuation">) class="token punc tuation">{
class="token keyword">if class="token punc tuation">( class="token operator">! frameclass="token operator">-> sample_aspec t_ratioclass="token punc tuation">. numclass="token punc tuation">) frameclass="token operator">-> sample_aspec t_ratio class="token operator">= avc txclass="token operator">-> sample_aspec t_ratioclass="token punc tuation">;
class="token keyword">if class="token punc tuation">( class="token operator">! frameclass="token operator">-> widthclass="token punc tuation">) frameclass="token operator">-> width class="token operator">= avc txclass="token operator">-> widthclass="token punc tuation">;
class="token keyword">if class="token punc tuation">( class="token operator">! frameclass="token operator">-> heightclass="token punc tuation">) frameclass="token operator">-> height class="token operator">= avc txclass="token operator">-> heightclass="token punc tuation">;
class="token keyword">if class="token punc tuation">( frameclass="token operator">-> format class="token operator">== AV_PIX_FMT_NONEclass="token punc tuation">) frameclass="token operator">-> format class="token operator">= avc txclass="token operator">-> pix_fmtclass="token punc tuation">;
class="token punc tuation">}
class="token punc tuation">}
class="token punc tuation">}
class="token func tion">emms_c class="token punc tuation">( class="token punc tuation">) class="token punc tuation">;
ac tual_got_frame class="token operator">= got_frameclass="token punc tuation">;
class="token keyword">if class="token punc tuation">( avc txclass="token operator">-> c odec class="token operator">-> type class="token operator">== AVMEDIA_TYPE_VIDEOclass="token punc tuation">) class="token punc tuation">{
class="token c omment">//disc ard 丢弃掉了
class="token keyword">if class="token punc tuation">( frameclass="token operator">-> flags class="token operator">& AV_FRAME_FLAG_DISCARDclass="token punc tuation">)
got_frame class="token operator">= class="token number">0 class="token punc tuation">;
class="token punc tuation">} class="token keyword">else class="token keyword">if class="token punc tuation">( avc txclass="token operator">-> c odec class="token operator">-> type class="token operator">== AVMEDIA_TYPE_AUDIOclass="token punc tuation">) class="token punc tuation">{
class="token c lass-name">uint8_t class="token operator">* sideclass="token punc tuation">;
class="token c lass-name">buffer_size_t side_sizeclass="token punc tuation">;
class="token c lass-name">uint32_t disc ard_padding class="token operator">= class="token number">0 class="token punc tuation">;
class="token c lass-name">uint8_t skip_reason class="token operator">= class="token number">0 class="token punc tuation">;
class="token c lass-name">uint8_t disc ard_reason class="token operator">= class="token number">0 class="token punc tuation">;
class="token c omment">//设置frame的一些参数
class="token keyword">if class="token punc tuation">( ret class="token operator">>= class="token number">0 class="token operator">&& got_frameclass="token punc tuation">) class="token punc tuation">{
class="token keyword">if class="token punc tuation">( frameclass="token operator">-> format class="token operator">== AV_SAMPLE_FMT_NONEclass="token punc tuation">)
frameclass="token operator">-> format class="token operator">= avc txclass="token operator">-> sample_fmtclass="token punc tuation">;
class="token keyword">if class="token punc tuation">( class="token operator">! frameclass="token operator">-> c hannel_layoutclass="token punc tuation">)
frameclass="token operator">-> c hannel_layout class="token operator">= avc txclass="token operator">-> c hannel_layoutclass="token punc tuation">;
class="token keyword">if class="token punc tuation">( class="token operator">! frameclass="token operator">-> c hannelsclass="token punc tuation">)
frameclass="token operator">-> c hannels class="token operator">= avc txclass="token operator">-> c hannelsclass="token punc tuation">;
class="token keyword">if class="token punc tuation">( class="token operator">! frameclass="token operator">-> sample_rateclass="token punc tuation">)
frameclass="token operator">-> sample_rate class="token operator">= avc txclass="token operator">-> sample_rateclass="token punc tuation">;
class="token punc tuation">}
sideclass="token operator">= class="token func tion">av_pac ket_get_side_data class="token punc tuation">( avc iclass="token operator">-> last_pkt_propsclass="token punc tuation">, AV_PKT_DATA_SKIP_SAMPLESclass="token punc tuation">, class="token operator">& side_sizeclass="token punc tuation">) class="token punc tuation">;
class="token c omment">//跳过skip_samples帧数
class="token keyword">if class="token punc tuation">( side class="token operator">&& side_sizeclass="token operator">>= class="token number">10 class="token punc tuation">) class="token punc tuation">{
avc iclass="token operator">-> skip_samples class="token operator">= class="token func tion">AV_RL32 class="token punc tuation">( sideclass="token punc tuation">) class="token operator">* avc iclass="token operator">-> skip_samples_multiplierclass="token punc tuation">;
disc ard_padding class="token operator">= class="token func tion">AV_RL32 class="token punc tuation">( side class="token operator">+ class="token number">4 class="token punc tuation">) class="token punc tuation">;
class="token func tion">av_log class="token punc tuation">( avc txclass="token punc tuation">, AV_LOG_DEBUGclass="token punc tuation">, class="token string">"skip %d / disc ard %d samples due to side data\n" class="token punc tuation">,
avc iclass="token operator">-> skip_samplesclass="token punc tuation">, class="token punc tuation">( class="token keyword">int class="token punc tuation">) disc ard_paddingclass="token punc tuation">) class="token punc tuation">;
skip_reason class="token operator">= class="token func tion">AV_RL8 class="token punc tuation">( side class="token operator">+ class="token number">8 class="token punc tuation">) class="token punc tuation">;
disc ard_reason class="token operator">= class="token func tion">AV_RL8 class="token punc tuation">( side class="token operator">+ class="token number">9 class="token punc tuation">) class="token punc tuation">;
class="token punc tuation">}
class="token keyword">if class="token punc tuation">( class="token punc tuation">( frameclass="token operator">-> flags class="token operator">& AV_FRAME_FLAG_DISCARDclass="token punc tuation">) class="token operator">&& got_frame class="token operator">&&
class="token operator">! class="token punc tuation">( avc txclass="token operator">-> flags2 class="token operator">& AV_CODEC_FLAG2_SKIP_MANUALclass="token punc tuation">) class="token punc tuation">) class="token punc tuation">{
avc iclass="token operator">-> skip_samples class="token operator">= class="token func tion">FFMAX class="token punc tuation">( class="token number">0 class="token punc tuation">, avc iclass="token operator">-> skip_samples class="token operator">- frameclass="token operator">-> nb_samplesclass="token punc tuation">) class="token punc tuation">;
got_frame class="token operator">= class="token number">0 class="token punc tuation">;
class="token operator">* disc arded_samples class="token operator">+= frameclass="token operator">-> nb_samplesclass="token punc tuation">;
class="token punc tuation">}
class="token keyword">if class="token punc tuation">( avc iclass="token operator">-> skip_samples class="token operator">> class="token number">0 class="token operator">&& got_frame class="token operator">&&
class="token operator">! class="token punc tuation">( avc txclass="token operator">-> flags2 class="token operator">& AV_CODEC_FLAG2_SKIP_MANUALclass="token punc tuation">) class="token punc tuation">) class="token punc tuation">{
class="token keyword">if class="token punc tuation">( frameclass="token operator">-> nb_samples class="token operator"><= avc iclass="token operator">-> skip_samplesclass="token punc tuation">) class="token punc tuation">{
got_frame class="token operator">= class="token number">0 class="token punc tuation">;
class="token operator">* disc arded_samples class="token operator">+= frameclass="token operator">-> nb_samplesclass="token punc tuation">;
avc iclass="token operator">-> skip_samples class="token operator">-= frameclass="token operator">-> nb_samplesclass="token punc tuation">;
class="token func tion">av_log class="token punc tuation">( avc txclass="token punc tuation">, AV_LOG_DEBUGclass="token punc tuation">, class="token string">"skip whole frame, skip left: %d\n" class="token punc tuation">,
avc iclass="token operator">-> skip_samplesclass="token punc tuation">) class="token punc tuation">;
class="token punc tuation">} class="token keyword">else class="token punc tuation">{
class="token func tion">av_samples_c opy class="token punc tuation">( frameclass="token operator">-> extended_dataclass="token punc tuation">, frameclass="token operator">-> extended_dataclass="token punc tuation">, class="token number">0 class="token punc tuation">, avc iclass="token operator">-> skip_samplesclass="token punc tuation">,
frameclass="token operator">-> nb_samples class="token operator">- avc iclass="token operator">-> skip_samplesclass="token punc tuation">, avc txclass="token operator">-> c hannelsclass="token punc tuation">, frameclass="token operator">-> formatclass="token punc tuation">) class="token punc tuation">;
class="token keyword">if class="token punc tuation">( avc txclass="token operator">-> pkt_timebaseclass="token punc tuation">. num class="token operator">&& avc txclass="token operator">-> sample_rateclass="token punc tuation">) class="token punc tuation">{
class="token c lass-name">int64_t diff_ts class="token operator">= class="token func tion">av_resc ale_q class="token punc tuation">( avc iclass="token operator">-> skip_samplesclass="token punc tuation">,
class="token punc tuation">( AVRationalclass="token punc tuation">) class="token punc tuation">{ class="token number">1 class="token punc tuation">, avc txclass="token operator">-> sample_rateclass="token punc tuation">} class="token punc tuation">,
avc txclass="token operator">-> pkt_timebaseclass="token punc tuation">) class="token punc tuation">;
class="token keyword">if class="token punc tuation">( frameclass="token operator">-> ptsclass="token operator">!= AV_NOPTS_VALUEclass="token punc tuation">)
frameclass="token operator">-> pts class="token operator">+= diff_tsclass="token punc tuation">;
class="token mac ro property">class="token direc tive-hash"># class="token direc tive keyword">if class="token expression">FF_API_PKT_PTS
FF_DISABLE_DEPRECATION_WARNINGS
class="token keyword">if class="token punc tuation">( frameclass="token operator">-> pkt_ptsclass="token operator">!= AV_NOPTS_VALUEclass="token punc tuation">)
frameclass="token operator">-> pkt_pts class="token operator">+= diff_tsclass="token punc tuation">;
FF_ENABLE_DEPRECATION_WARNINGS
class="token mac ro property">class="token direc tive-hash"># class="token direc tive keyword">endif
class="token keyword">if class="token punc tuation">( frameclass="token operator">-> pkt_dtsclass="token operator">!= AV_NOPTS_VALUEclass="token punc tuation">)
frameclass="token operator">-> pkt_dts class="token operator">+= diff_tsclass="token punc tuation">;
class="token keyword">if class="token punc tuation">( frameclass="token operator">-> pkt_duration class="token operator">>= diff_tsclass="token punc tuation">)
frameclass="token operator">-> pkt_duration class="token operator">-= diff_tsclass="token punc tuation">;
class="token punc tuation">} class="token keyword">else class="token punc tuation">{
class="token func tion">av_log class="token punc tuation">( avc txclass="token punc tuation">, AV_LOG_WARNINGclass="token punc tuation">, class="token string">"Could not update timestamps for skipped samples.\n" class="token punc tuation">) class="token punc tuation">;
class="token punc tuation">}
class="token func tion">av_log class="token punc tuation">( avc txclass="token punc tuation">, AV_LOG_DEBUGclass="token punc tuation">, class="token string">"skip %d/%d samples\n" class="token punc tuation">,
avc iclass="token operator">-> skip_samplesclass="token punc tuation">, frameclass="token operator">-> nb_samplesclass="token punc tuation">) class="token punc tuation">;
class="token operator">* disc arded_samples class="token operator">+= avc iclass="token operator">-> skip_samplesclass="token punc tuation">;
frameclass="token operator">-> nb_samples class="token operator">-= avc iclass="token operator">-> skip_samplesclass="token punc tuation">;
avc iclass="token operator">-> skip_samples class="token operator">= class="token number">0 class="token punc tuation">;
class="token punc tuation">}
class="token punc tuation">}
class="token keyword">if class="token punc tuation">( disc ard_padding class="token operator">> class="token number">0 class="token operator">&& disc ard_padding class="token operator"><= frameclass="token operator">-> nb_samples class="token operator">&& got_frame class="token operator">&&
class="token operator">! class="token punc tuation">( avc txclass="token operator">-> flags2 class="token operator">& AV_CODEC_FLAG2_SKIP_MANUALclass="token punc tuation">) class="token punc tuation">) class="token punc tuation">{
class="token keyword">if class="token punc tuation">( disc ard_padding class="token operator">== frameclass="token operator">-> nb_samplesclass="token punc tuation">) class="token punc tuation">{
class="token operator">* disc arded_samples class="token operator">+= frameclass="token operator">-> nb_samplesclass="token punc tuation">;
got_frame class="token operator">= class="token number">0 class="token punc tuation">;
class="token punc tuation">} class="token keyword">else class="token punc tuation">{
class="token keyword">if class="token punc tuation">( avc txclass="token operator">-> pkt_timebaseclass="token punc tuation">. num class="token operator">&& avc txclass="token operator">-> sample_rateclass="token punc tuation">) class="token punc tuation">{
class="token c lass-name">int64_t diff_ts class="token operator">= class="token func tion">av_resc ale_q class="token punc tuation">( frameclass="token operator">-> nb_samples class="token operator">- disc ard_paddingclass="token punc tuation">,
class="token punc tuation">( AVRationalclass="token punc tuation">) class="token punc tuation">{ class="token number">1 class="token punc tuation">, avc txclass="token operator">-> sample_rateclass="token punc tuation">} class="token punc tuation">,
avc txclass="token operator">-> pkt_timebaseclass="token punc tuation">) class="token punc tuation">;
frameclass="token operator">-> pkt_duration class="token operator">= diff_tsclass="token punc tuation">;
class="token punc tuation">} class="token keyword">else class="token punc tuation">{
class="token func tion">av_log class="token punc tuation">( avc txclass="token punc tuation">, AV_LOG_WARNINGclass="token punc tuation">, class="token string">"Could not update timestamps for disc arded samples.\n" class="token punc tuation">) class="token punc tuation">;
class="token punc tuation">}
class="token func tion">av_log class="token punc tuation">( avc txclass="token punc tuation">, AV_LOG_DEBUGclass="token punc tuation">, class="token string">"disc ard %d/%d samples\n" class="token punc tuation">,
class="token punc tuation">( class="token keyword">int class="token punc tuation">) disc ard_paddingclass="token punc tuation">, frameclass="token operator">-> nb_samplesclass="token punc tuation">) class="token punc tuation">;
frameclass="token operator">-> nb_samples class="token operator">-= disc ard_paddingclass="token punc tuation">;
class="token punc tuation">}
class="token punc tuation">}
class="token keyword">if class="token punc tuation">( class="token punc tuation">( avc txclass="token operator">-> flags2 class="token operator">& AV_CODEC_FLAG2_SKIP_MANUALclass="token punc tuation">) class="token operator">&& got_frameclass="token punc tuation">) class="token punc tuation">{
AVFrameSideData class="token operator">* fside class="token operator">= class="token func tion">av_frame_new_side_data class="token punc tuation">( frameclass="token punc tuation">, AV_FRAME_DATA_SKIP_SAMPLESclass="token punc tuation">, class="token number">10 class="token punc tuation">) class="token punc tuation">;
class="token keyword">if class="token punc tuation">( fsideclass="token punc tuation">) class="token punc tuation">{
class="token func tion">AV_WL32 class="token punc tuation">( fsideclass="token operator">-> dataclass="token punc tuation">, avc iclass="token operator">-> skip_samplesclass="token punc tuation">) class="token punc tuation">;
class="token func tion">AV_WL32 class="token punc tuation">( fsideclass="token operator">-> data class="token operator">+ class="token number">4 class="token punc tuation">, disc ard_paddingclass="token punc tuation">) class="token punc tuation">;
class="token func tion">AV_WL8 class="token punc tuation">( fsideclass="token operator">-> data class="token operator">+ class="token number">8 class="token punc tuation">, skip_reasonclass="token punc tuation">) class="token punc tuation">;
class="token func tion">AV_WL8 class="token punc tuation">( fsideclass="token operator">-> data class="token operator">+ class="token number">9 class="token punc tuation">, disc ard_reasonclass="token punc tuation">) class="token punc tuation">;
avc iclass="token operator">-> skip_samples class="token operator">= class="token number">0 class="token punc tuation">;
class="token punc tuation">}
class="token punc tuation">}
class="token punc tuation">}
class="token keyword">if class="token punc tuation">( avc txclass="token operator">-> c odec class="token operator">-> type class="token operator">== AVMEDIA_TYPE_AUDIO class="token operator">&&
class="token operator">! avc iclass="token operator">-> showed_multi_pac ket_warning class="token operator">&&
ret class="token operator">>= class="token number">0 class="token operator">&& ret class="token operator">!= pktclass="token operator">-> size class="token operator">&& class="token operator">! class="token punc tuation">( avc txclass="token operator">-> c odec class="token operator">-> c apabilities class="token operator">& AV_CODEC_CAP_SUBFRAMESclass="token punc tuation">) class="token punc tuation">) class="token punc tuation">{
class="token func tion">av_log class="token punc tuation">( avc txclass="token punc tuation">, AV_LOG_WARNINGclass="token punc tuation">, class="token string">"Multiple frames in a pac ket.\n" class="token punc tuation">) class="token punc tuation">;
avc iclass="token operator">-> showed_multi_pac ket_warning class="token operator">= class="token number">1 class="token punc tuation">;
class="token punc tuation">}
class="token keyword">if class="token punc tuation">( class="token operator">! got_frameclass="token punc tuation">)
class="token func tion">av_frame_unref class="token punc tuation">( frameclass="token punc tuation">) class="token punc tuation">;
class="token keyword">if class="token punc tuation">( ret class="token operator">>= class="token number">0 class="token operator">&& avc txclass="token operator">-> c odec class="token operator">-> type class="token operator">== AVMEDIA_TYPE_VIDEO class="token operator">&& class="token operator">! class="token punc tuation">( avc txclass="token operator">-> flags class="token operator">& AV_CODEC_FLAG_TRUNCATEDclass="token punc tuation">) class="token punc tuation">)
ret class="token operator">= pktclass="token operator">-> sizeclass="token punc tuation">;
class="token mac ro property">class="token direc tive-hash"># class="token direc tive keyword">if class="token expression">FF_API_AVCTX_TIMEBASE
class="token keyword">if class="token punc tuation">( avc txclass="token operator">-> framerateclass="token punc tuation">. num class="token operator">> class="token number">0 class="token operator">&& avc txclass="token operator">-> framerateclass="token punc tuation">. den class="token operator">> class="token number">0 class="token punc tuation">)
avc txclass="token operator">-> time_base class="token operator">= class="token func tion">av_inv_q class="token punc tuation">( class="token func tion">av_mul_q class="token punc tuation">( avc txclass="token operator">-> framerateclass="token punc tuation">, class="token punc tuation">( AVRationalclass="token punc tuation">) class="token punc tuation">{ avc txclass="token operator">-> tic ks_per_frameclass="token punc tuation">, class="token number">1 class="token punc tuation">} class="token punc tuation">) class="token punc tuation">) class="token punc tuation">;
class="token mac ro property">class="token direc tive-hash"># class="token direc tive keyword">endif
class="token c omment">/* do not stop draining when ac tual_got_frame != 0 or ret < 0 */
class="token c omment">/* got_frame == 0 but ac tual_got_frame != 0 when frame is disc arded */
class="token keyword">if class="token punc tuation">( avc iclass="token operator">-> draining class="token operator">&& class="token operator">! ac tual_got_frameclass="token punc tuation">) class="token punc tuation">{
class="token keyword">if class="token punc tuation">( ret class="token operator">< class="token number">0 class="token punc tuation">) class="token punc tuation">{
class="token c omment">/* prevent infinite loop if a dec oder wrongly always return error on draining */
class="token c omment">/* reasonable nb_errors_max = maximum b frames + thread c ount */
class="token keyword">int nb_errors_max class="token operator">= class="token number">20 class="token operator">+ class="token punc tuation">( HAVE_THREADS class="token operator">&& avc txclass="token operator">-> ac tive_thread_type class="token operator">& FF_THREAD_FRAME class="token operator">?
avc txclass="token operator">-> thread_c ount class="token operator">: class="token number">1 class="token punc tuation">) class="token punc tuation">;
class="token keyword">if class="token punc tuation">( avc iclass="token operator">-> nb_draining_errorsclass="token operator">++ class="token operator">>= nb_errors_maxclass="token punc tuation">) class="token punc tuation">{
class="token func tion">av_log class="token punc tuation">( avc txclass="token punc tuation">, AV_LOG_ERRORclass="token punc tuation">, class="token string">"Too many errors when draining, this is a bug. "
class="token string">"Stop draining and forc e EOF.\n" class="token punc tuation">) class="token punc tuation">;
avc iclass="token operator">-> draining_done class="token operator">= class="token number">1 class="token punc tuation">;
ret class="token operator">= AVERROR_BUGclass="token punc tuation">;
class="token punc tuation">}
class="token punc tuation">} class="token keyword">else class="token punc tuation">{
avc iclass="token operator">-> draining_done class="token operator">= class="token number">1 class="token punc tuation">;
class="token punc tuation">}
class="token punc tuation">}
class="token mac ro property">class="token direc tive-hash"># class="token direc tive keyword">if class="token expression">FF_API_OLD_ENCDEC
avc iclass="token operator">-> c ompat_dec ode_c onsumed class="token operator">+= retclass="token punc tuation">;
class="token mac ro property">class="token direc tive-hash"># class="token direc tive keyword">endif
class="token keyword">if class="token punc tuation">( ret class="token operator">>= pktclass="token operator">-> size class="token operator">|| ret class="token operator">< class="token number">0 class="token punc tuation">) class="token punc tuation">{
class="token func tion">av_pac ket_unref class="token punc tuation">( pktclass="token punc tuation">) class="token punc tuation">;
class="token func tion">av_pac ket_unref class="token punc tuation">( avc iclass="token operator">-> last_pkt_propsclass="token punc tuation">) class="token punc tuation">;
class="token punc tuation">} class="token keyword">else class="token punc tuation">{
class="token keyword">int c onsumed class="token operator">= retclass="token punc tuation">;
pktclass="token operator">-> data class="token operator">+= c onsumedclass="token punc tuation">;
pktclass="token operator">-> size class="token operator">-= c onsumedclass="token punc tuation">;
avc iclass="token operator">-> last_pkt_propsclass="token operator">-> size class="token operator">-= c onsumedclass="token punc tuation">; class="token c omment">// See extrac t_pac ket_props() c omment.
pktclass="token operator">-> pts class="token operator">= AV_NOPTS_VALUEclass="token punc tuation">;
pktclass="token operator">-> dts class="token operator">= AV_NOPTS_VALUEclass="token punc tuation">;
avc iclass="token operator">-> last_pkt_propsclass="token operator">-> pts class="token operator">= AV_NOPTS_VALUEclass="token punc tuation">;
avc iclass="token operator">-> last_pkt_propsclass="token operator">-> dts class="token operator">= AV_NOPTS_VALUEclass="token punc tuation">;
class="token punc tuation">}
class="token keyword">if class="token punc tuation">( got_frameclass="token punc tuation">)
class="token func tion">av_assert0 class="token punc tuation">( frameclass="token operator">-> bufclass="token punc tuation">[ class="token number">0 class="token punc tuation">] class="token punc tuation">) class="token punc tuation">;
class="token keyword">return ret class="token operator">< class="token number">0 class="token operator">? ret class="token operator">: class="token number">0 class="token punc tuation">;
class="token punc tuation">}
c ode>
c ode_frame__494">ff_thread_dec ode_frame 源码
多线程解码实现c ;在此之前c ;通过需要先通过调用avc odec _open2创建多个线程。 然后在这个函数中c ;先调用submit_pac ket()函数提交pac ket到下一个解码线程c ;然后调用数组中最前面线程进行解码。相关代码如下:
<c ode c lass="prism language-c ">class="token keyword">int class="token func tion">ff_thread_dec ode_frame class="token punc tuation">( AVCodec Context class="token operator">* avc txclass="token punc tuation">,
AVFrame class="token operator">* pic tureclass="token punc tuation">, class="token keyword">int class="token operator">* got_pic ture_ptrclass="token punc tuation">,
AVPac ket class="token operator">* avpktclass="token punc tuation">)
class="token punc tuation">{
FrameThreadContext class="token operator">* fc tx class="token operator">= avc txclass="token operator">-> internalclass="token operator">-> thread_c txclass="token punc tuation">;
class="token keyword">int finished class="token operator">= fc txclass="token operator">-> next_finishedclass="token punc tuation">;
PerThreadContext class="token operator">* pclass="token punc tuation">;
class="token keyword">int errclass="token punc tuation">;
class="token c omment">/* release the async loc k, permitting bloc ked hwac c el threads to
* go forward while we are in this func tion */
class="token func tion">async _unloc k class="token punc tuation">( fc txclass="token punc tuation">) class="token punc tuation">;
class="token c omment">/*
* Submit a pac ket to the next dec oding thread.
*/
p class="token operator">= class="token operator">& fc txclass="token operator">-> threadsclass="token punc tuation">[ fc txclass="token operator">-> next_dec odingclass="token punc tuation">] class="token punc tuation">;
class="token c omment">// PerThreadContext是对应线程的上下文c ;这是在调用avc odec _open2时候创建的。
class="token c omment">// 这里是把avpkt转移到p->avpktc ;然后触发PerThreadContext的input_c ond信号量c ;告诉对应的解码线程c ;可以开始解码了。
class="token c omment">// 具体的解码实现在pthread_frame.c 文件中的frame_worker_thread函数。
err class="token operator">= class="token func tion">submit_pac ket class="token punc tuation">( pclass="token punc tuation">, avc txclass="token punc tuation">, avpktclass="token punc tuation">) class="token punc tuation">;
class="token keyword">if class="token punc tuation">( errclass="token punc tuation">)
class="token keyword">goto finishclass="token punc tuation">;
class="token c omment">/*
* If we're still rec eiving the initial pac kets, don't return a frame.
*/
class="token keyword">if class="token punc tuation">( fc txclass="token operator">-> next_dec oding class="token operator">> class="token punc tuation">( avc txclass="token operator">-> thread_c ountclass="token operator">- class="token number">1 class="token operator">- class="token punc tuation">( avc txclass="token operator">-> c odec _id class="token operator">== AV_CODEC_ID_FFV1class="token punc tuation">) class="token punc tuation">) class="token punc tuation">)
fc txclass="token operator">-> delaying class="token operator">= class="token number">0 class="token punc tuation">;
class="token keyword">if class="token punc tuation">( fc txclass="token operator">-> delayingclass="token punc tuation">) class="token punc tuation">{
class="token operator">* got_pic ture_ptrclass="token operator">= class="token number">0 class="token punc tuation">;
class="token keyword">if class="token punc tuation">( avpktclass="token operator">-> sizeclass="token punc tuation">) class="token punc tuation">{
err class="token operator">= avpktclass="token operator">-> sizeclass="token punc tuation">;
class="token keyword">goto finishclass="token punc tuation">;
class="token punc tuation">}
class="token punc tuation">}
class="token c omment">/*
* Return the next available frame from the oldest thread.
* If we're at the end of the stream, then we have to skip threads that
* didn't output a frame/error, bec ause we don't want to ac c identally signal
* EOF (avpkt->size == 0 && *got_pic ture_ptr == 0 && err >= 0).
*/
class="token keyword">do class="token punc tuation">{
p class="token operator">= class="token operator">& fc txclass="token operator">-> threadsclass="token punc tuation">[ finishedclass="token operator">++ class="token punc tuation">] class="token punc tuation">;
class="token c omment">//上面通过调用submit_pac ket提交AVPac ket给解码线程后c ;这里就等待output_c ond完成
class="token keyword">if class="token punc tuation">( class="token func tion">atomic _load class="token punc tuation">( class="token operator">& pclass="token operator">-> stateclass="token punc tuation">) class="token operator">!= STATE_INPUT_READYclass="token punc tuation">) class="token punc tuation">{
class="token func tion">pthread_mutex_loc k class="token punc tuation">( class="token operator">& pclass="token operator">-> progress_mutexclass="token punc tuation">) class="token punc tuation">;
class="token keyword">while class="token punc tuation">( class="token func tion">atomic _load_explic it class="token punc tuation">( class="token operator">& pclass="token operator">-> stateclass="token punc tuation">, memory_order_relaxedclass="token punc tuation">) class="token operator">!= STATE_INPUT_READYclass="token punc tuation">)
class="token func tion">pthread_c ond_wait class="token punc tuation">( class="token operator">& pclass="token operator">-> output_c ondclass="token punc tuation">, class="token operator">& pclass="token operator">-> progress_mutexclass="token punc tuation">) class="token punc tuation">;
class="token func tion">pthread_mutex_unloc k class="token punc tuation">( class="token operator">& pclass="token operator">-> progress_mutexclass="token punc tuation">) class="token punc tuation">;
class="token punc tuation">}
class="token c omment">//获取解码后的framec ;然后把frame给到pic ture。
class="token func tion">av_frame_move_ref class="token punc tuation">( pic tureclass="token punc tuation">, pclass="token operator">-> frameclass="token punc tuation">) class="token punc tuation">;
class="token operator">* got_pic ture_ptr class="token operator">= pclass="token operator">-> got_frameclass="token punc tuation">;
pic tureclass="token operator">-> pkt_dts class="token operator">= pclass="token operator">-> avpktclass="token operator">-> dtsclass="token punc tuation">;
err class="token operator">= pclass="token operator">-> resultclass="token punc tuation">;
class="token c omment">/*
* A later c all with avkpt->size == 0 may loop over all threads,
* inc luding this one, searc hing for a frame/error to return before being
* stopped by the "finished != fc tx->next_finished" c ondition.
* Make sure we don't mistakenly return the same frame/error again.
*/
pclass="token operator">-> got_frame class="token operator">= class="token number">0 class="token punc tuation">;
pclass="token operator">-> result class="token operator">= class="token number">0 class="token punc tuation">;
class="token keyword">if class="token punc tuation">( finished class="token operator">>= avc txclass="token operator">-> thread_c ountclass="token punc tuation">) finished class="token operator">= class="token number">0 class="token punc tuation">;
class="token punc tuation">} class="token keyword">while class="token punc tuation">( class="token operator">! avpktclass="token operator">-> size class="token operator">&& class="token operator">! class="token operator">* got_pic ture_ptr class="token operator">&& err class="token operator">>= class="token number">0 class="token operator">&& finished class="token operator">!= fc txclass="token operator">-> next_finishedclass="token punc tuation">) class="token punc tuation">;
class="token func tion">update_c ontext_from_thread class="token punc tuation">( avc txclass="token punc tuation">, pclass="token operator">-> avc txclass="token punc tuation">, class="token number">1 class="token punc tuation">) class="token punc tuation">;
class="token keyword">if class="token punc tuation">( fc txclass="token operator">-> next_dec oding class="token operator">>= avc txclass="token operator">-> thread_c ountclass="token punc tuation">) fc txclass="token operator">-> next_dec oding class="token operator">= class="token number">0 class="token punc tuation">;
fc txclass="token operator">-> next_finished class="token operator">= finishedclass="token punc tuation">;
class="token c omment">/* return the size of the c onsumed pac ket if no error oc c urred */
class="token keyword">if class="token punc tuation">( err class="token operator">>= class="token number">0 class="token punc tuation">)
err class="token operator">= avpktclass="token operator">-> sizeclass="token punc tuation">;
finishclass="token operator">:
class="token func tion">async _loc k class="token punc tuation">( fc txclass="token punc tuation">) class="token punc tuation">;
class="token keyword">return errclass="token punc tuation">;
class="token punc tuation">}
c ode>