x264代码剖析(七):encode()函数之x264_encoder_encode()函数

来源:互联网 发布:apache开启rewrite 编辑:程序博客网 时间:2024/05/17 00:09

转自:http://blog.csdn.net/frd2009041510      

encode()函数是x264的主干函数,主要包括x264_encoder_open()函数、x264_encoder_headers()函数、x264_encoder_encode()函数与x264_encoder_close()函数四大部分,其中x264_encoder_encode()函数是其核心部分,具体的H.264视频编码算法均在此模块。上两篇博文主要分析了x264_encoder_open()函数与x264_encoder_headers()函数,本文主要学习x264_encoder_encode()函数。

 

        在《x264代码剖析(三):主函数main()、解析函数parse()与编码函数encode()》的介绍中,我们知道x264_encoder_encode()函数被encode_frame()函数调用,而encode_frame()函数被encode()函数调用,encode()函数又被main()函数调用。由于main()函数、encode()函数与encode_frame()函数对应的代码已经分析完毕,本文主要分析x264_encoder_encode()函数。x264_encoder_encode()函数编码一帧YUVH.264码流,对应的函数关系图如下,主要调用了下面的函数:

        x264_frame_pop_unused():获取1x264_frame_t类型结构体fenc。如果frames.unused[]队列不为空,就调用x264_frame_pop()unused[]队列取1个现成的;否则就调用x264_frame_new()创建一个新的。

        x264_frame_copy_picture():将输入的图像数据拷贝至fenc

        x264_lookahead_put_frame():将fenc放入lookahead.next.list[]队列,等待确定帧类型。

        x264_lookahead_get_frames():通过lookahead分析帧类型。该函数调用了x264_slicetype_decide()x264_slicetype_analyse()x264_slicetype_frame_cost()等函数。经过一些列分析之后,最终确定了帧类型信息,并且将帧放入frames.current[]队列。

        x264_frame_shift():从frames.current[]队列取出1帧用于编码。

        x264_reference_update():更新参考帧队列。

        x264_reference_reset():如果为IDR帧,调用该函数清空参考帧列表。

        x264_reference_hierarchy_reset():如果是非IDRI帧、P帧、B帧(可做为参考帧),调用该函数。

        x264_reference_build_list():创建参考帧列表list0list1

        x264_ratecontrol_start():开启码率控制。

        x264_slice_init():创建 Slice Header

        x264_slices_write():编码数据(最关键的步骤)。其中调用了x264_slice_write()完成了编码的工作(注意“x264_slices_write()”和“x264_slice_write()”名字差了一个“s”)。

        x264_encoder_frame_end():编码结束后做一些后续处理,例如记录一些统计信息。其中调用了x264_encoder_encapsulate_nals()封装NALU(添加起始码),调用x264_frame_push_unused()fenc重新放回frames.unused[]队列,并且调用x264_ratecontrol_end()结束码率控制。




 

        下面对x264_encoder_encode()函数源码进行分析,如下:

 

[cpp] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. /******************************************************************/  
  2. /******************************************************************/  
  3. /* 
  4. ======Analysed by RuiDong Fang 
  5. ======Csdn Blog:http://blog.csdn.net/frd2009041510 
  6. ======Date:2016.03.10 
  7.  */  
  8. /******************************************************************/  
  9. /******************************************************************/  
  10.   
  11. /************====== x264_encoder_encode()函数 ======************/  
  12. /* 
  13. 功能:编码一帧数据 
  14. */  
  15. /**************************************************************************** 
  16.  * x264_encoder_encode: 
  17.  *  XXX: i_poc   : is the poc of the current given picture 
  18.  *       i_frame : is the number of the frame being coded 
  19.  *  ex:  type frame poc 
  20.  *       I      0   2*0 
  21.  *       P      1   2*3 
  22.  *       B      2   2*1 
  23.  *       B      3   2*2 
  24.  *       P      4   2*6 
  25.  *       B      5   2*4 
  26.  *       B      6   2*5 
  27.  ****************************************************************************/  
  28. int     x264_encoder_encode( x264_t *h,  
  29.                              x264_nal_t **pp_nal, int *pi_nal,  
  30.                              x264_picture_t *pic_in,  
  31.                              x264_picture_t *pic_out )  
  32. {  
  33.     x264_t *thread_current, *thread_prev, *thread_oldest;  
  34.     int i_nal_type, i_nal_ref_idc, i_global_qp;  
  35.     int overhead = NALU_OVERHEAD;  
  36.   
  37. #if HAVE_OPENCL  
  38.     if( h->opencl.b_fatal_error )  
  39.         return -1;  
  40. #endif  
  41.   
  42.     if( h->i_thread_frames > 1 )  
  43.     {  
  44.         thread_prev    = h->thread[ h->i_thread_phase ];  
  45.         h->i_thread_phase = (h->i_thread_phase + 1) % h->i_thread_frames;  
  46.         thread_current = h->thread[ h->i_thread_phase ];  
  47.         thread_oldest  = h->thread[ (h->i_thread_phase + 1) % h->i_thread_frames ];  
  48.         x264_thread_sync_context( thread_current, thread_prev );  
  49.         x264_thread_sync_ratecontrol( thread_current, thread_prev, thread_oldest );  
  50.         h = thread_current;  
  51.     }  
  52.     else  
  53.     {  
  54.         thread_current =  
  55.         thread_oldest  = h;  
  56.     }  
  57.     h->i_cpb_delay_pir_offset = h->i_cpb_delay_pir_offset_next;  
  58.   
  59.     /* no data out */  
  60.     *pi_nal = 0;  
  61.     *pp_nal = NULL;  
  62.   
  63.     /* ------------------- Setup new frame from picture -------------------- */  
  64.     if( pic_in != NULL )  
  65.     {  
  66.         if( h->lookahead->b_exit_thread )  
  67.         {  
  68.             x264_log( h, X264_LOG_ERROR, "lookahead thread is already stopped\n" );  
  69.             return -1;  
  70.         }  
  71.   
  72.         /* 1: Copy the picture to a frame and move it to a buffer */  
  73.         x264_frame_t *fenc = x264_frame_pop_unused( h, 0 );//////////////////步骤1:fenc存储了编码帧(获取一帧的空间fenc,用来存放待编码的帧)  
  74.         if( !fenc )  
  75.             return -1;  
  76.   
  77.         if( x264_frame_copy_picture( h, fenc, pic_in ) < 0 ));//////////////////外部像素数据传递到内部系统,pic_in(外部结构体x264_picture_t)到fenc(内部结构体x264_frame_t)  
  78.             return -1;  
  79.   
  80.         //宽和高都确保是16的整数倍(宏块宽度的整数倍)  
  81.         if( h->param.i_width != 16 * h->mb.i_mb_width ||  
  82.             h->param.i_height != 16 * h->mb.i_mb_height )  
  83.             x264_frame_expand_border_mod16( h, fenc );//扩展至16整数倍  
  84.   
  85.         fenc->i_frame = h->frames.i_input++;  
  86.   
  87.         if( fenc->i_frame == 0 )  
  88.             h->frames.i_first_pts = fenc->i_pts;  
  89.         if( h->frames.i_bframe_delay && fenc->i_frame == h->frames.i_bframe_delay )  
  90.             h->frames.i_bframe_delay_time = fenc->i_pts - h->frames.i_first_pts;  
  91.   
  92.         if( h->param.b_vfr_input && fenc->i_pts <= h->frames.i_largest_pts )  
  93.             x264_log( h, X264_LOG_WARNING, "non-strictly-monotonic PTS\n" );  
  94.   
  95.         h->frames.i_second_largest_pts = h->frames.i_largest_pts;  
  96.         h->frames.i_largest_pts = fenc->i_pts;  
  97.   
  98.         if( (fenc->i_pic_struct < PIC_STRUCT_AUTO) || (fenc->i_pic_struct > PIC_STRUCT_TRIPLE) )  
  99.             fenc->i_pic_struct = PIC_STRUCT_AUTO;  
  100.   
  101.         if( fenc->i_pic_struct == PIC_STRUCT_AUTO )  
  102.         {  
  103. #if HAVE_INTERLACED  
  104.             int b_interlaced = fenc->param ? fenc->param->b_interlaced : h->param.b_interlaced;  
  105. #else  
  106.             int b_interlaced = 0;  
  107. #endif  
  108.             if( b_interlaced )  
  109.             {  
  110.                 int b_tff = fenc->param ? fenc->param->b_tff : h->param.b_tff;  
  111.                 fenc->i_pic_struct = b_tff ? PIC_STRUCT_TOP_BOTTOM : PIC_STRUCT_BOTTOM_TOP;  
  112.             }  
  113.             else  
  114.                 fenc->i_pic_struct = PIC_STRUCT_PROGRESSIVE;  
  115.         }  
  116.   
  117.         if( h->param.rc.b_mb_tree && h->param.rc.b_stat_read )  
  118.         {  
  119.             if( x264_macroblock_tree_read( h, fenc, pic_in->prop.quant_offsets ) )  
  120.                 return -1;  
  121.         }  
  122.         else  
  123.             x264_stack_align( x264_adaptive_quant_frame, h, fenc, pic_in->prop.quant_offsets );  
  124.   
  125.         if( pic_in->prop.quant_offsets_free )  
  126.             pic_in->prop.quant_offsets_free( pic_in->prop.quant_offsets );  
  127.   
  128.         //降低分辨率处理(原来的一半),线性内插    
  129.         //注意这里并不是6抽头滤波器的半像素内插  
  130.         if( h->frames.b_have_lowres )  
  131.             x264_frame_init_lowres( h, fenc );  
  132.   
  133.         /* 2: Place the frame into the queue for its slice type decision */  
  134.         x264_lookahead_put_frame( h, fenc );));//////////////////步骤2:fenc放入lookahead.next.list[]队列,等待确定帧类型  
  135.   
  136.         if( h->frames.i_input <= h->frames.i_delay + 1 - h->i_thread_frames )  
  137.         {  
  138.             /* Nothing yet to encode, waiting for filling of buffers */  
  139.             pic_out->i_type = X264_TYPE_AUTO;  
  140.             return 0;  
  141.         }  
  142.     }  
  143.     else  
  144.     {  
  145.         /* signal kills for lookahead thread */  
  146.         x264_pthread_mutex_lock( &h->lookahead->ifbuf.mutex );  
  147.         h->lookahead->b_exit_thread = 1;  
  148.         x264_pthread_cond_broadcast( &h->lookahead->ifbuf.cv_fill );  
  149.         x264_pthread_mutex_unlock( &h->lookahead->ifbuf.mutex );  
  150.     }  
  151.   
  152.     h->i_frame++;  
  153.     /* 3: The picture is analyzed in the lookahead */  
  154.     if( !h->frames.current[0] )  
  155.         x264_lookahead_get_frames( h );//////////////////步骤3:通过lookahead分析帧类型  
  156.   
  157.     if( !h->frames.current[0] && x264_lookahead_is_empty( h ) )  
  158.         return x264_encoder_frame_end( thread_oldest, thread_current, pp_nal, pi_nal, pic_out );  
  159.   
  160.     /* ------------------- Get frame to be encoded ------------------------- */  
  161.     /* 4: get picture to encode */  
  162.     h->fenc = x264_frame_shift( h->frames.current );//////////////////步骤4:从frames.current[]队列取出1帧[0]用于编码  
  163.   
  164.     /* If applicable, wait for previous frame reconstruction to finish */  
  165.     if( h->param.b_sliced_threads )  
  166.         if( x264_threadpool_wait_all( h ) < 0 )  
  167.             return -1;  
  168.   
  169.     if( h->i_frame == 0 )  
  170.         h->i_reordered_pts_delay = h->fenc->i_reordered_pts;  
  171.     if( h->reconfig )  
  172.     {  
  173.         x264_encoder_reconfig_apply( h, &h->reconfig_h->param );  
  174.         h->reconfig = 0;  
  175.     }  
  176.     if( h->fenc->param )  
  177.     {  
  178.         x264_encoder_reconfig_apply( h, h->fenc->param );  
  179.         if( h->fenc->param->param_free )  
  180.         {  
  181.             h->fenc->param->param_free( h->fenc->param );  
  182.             h->fenc->param = NULL;  
  183.         }  
  184.     }  
  185.   
  186.     // ok to call this before encoding any frames, since the initial values of fdec have b_kept_as_ref=0  
  187.     //更新参考帧队列frames.reference[].若为B帧则不更新    
  188.     //重建帧fdec移植参考帧列表,新建一个fdec  
  189.     if( x264_reference_update( h ) ));//////////////////更新参考帧队列  
  190.         return -1;  
  191.     h->fdec->i_lines_completed = -1;  
  192.   
  193.     if( !IS_X264_TYPE_I( h->fenc->i_type ) )  
  194.     {  
  195.         int valid_refs_left = 0;  
  196.         forint i = 0; h->frames.reference[i]; i++ )  
  197.             if( !h->frames.reference[i]->b_corrupt )  
  198.                 valid_refs_left++;  
  199.         /* No valid reference frames left: force an IDR. */  
  200.         if( !valid_refs_left )  
  201.         {  
  202.             h->fenc->b_keyframe = 1;  
  203.             h->fenc->i_type = X264_TYPE_IDR;  
  204.         }  
  205.     }  
  206.   
  207.     if( h->fenc->b_keyframe )  
  208.     {  
  209.         h->frames.i_last_keyframe = h->fenc->i_frame;  
  210.         if( h->fenc->i_type == X264_TYPE_IDR )  
  211.         {  
  212.             h->i_frame_num = 0;  
  213.             h->frames.i_last_idr = h->fenc->i_frame;  
  214.         }  
  215.     }  
  216.     h->sh.i_mmco_command_count =  
  217.     h->sh.i_mmco_remove_from_end = 0;  
  218.     h->b_ref_reorder[0] =  
  219.     h->b_ref_reorder[1] = 0;  
  220.     h->fdec->i_poc =  
  221.     h->fenc->i_poc = 2 * ( h->fenc->i_frame - X264_MAX( h->frames.i_last_idr, 0 ) );  
  222.   
  223.     /* ------------------- Setup frame context ----------------------------- */  
  224.     /* 5: Init data dependent of frame type */  
  225.     //步骤5:确定帧类型  
  226.     if( h->fenc->i_type == X264_TYPE_IDR )  
  227.     {  
  228.         //I与IDR区别    
  229.         //注意IDR会导致参考帧列清空,而I不会    
  230.         //I图像之后的图像可以引用I图像之间的图像做运动参考  
  231.         /* reset ref pictures */  
  232.         i_nal_type    = NAL_SLICE_IDR;  
  233.         i_nal_ref_idc = NAL_PRIORITY_HIGHEST;  
  234.         h->sh.i_type = SLICE_TYPE_I;  
  235.         x264_reference_reset( h );//////////////////若是IDR帧,则清空所有参考帧  
  236.         h->frames.i_poc_last_open_gop = -1;  
  237.     }  
  238.     else if( h->fenc->i_type == X264_TYPE_I )  
  239.     {  
  240.         //I与IDR区别    
  241.         //注意IDR会导致参考帧列清空,而I不会    
  242.         //I图像之后的图像可以引用I图像之间的图像做运动参考  
  243.         i_nal_type    = NAL_SLICE;  
  244.         i_nal_ref_idc = NAL_PRIORITY_HIGH; /* Not completely true but for now it is (as all I/P are kept as ref)*/  
  245.         h->sh.i_type = SLICE_TYPE_I;  
  246.         x264_reference_hierarchy_reset( h );//////////////////如果是非IDR的I帧,调用该函数  
  247.         if( h->param.b_open_gop )  
  248.             h->frames.i_poc_last_open_gop = h->fenc->b_keyframe ? h->fenc->i_poc : -1;  
  249.     }  
  250.     else if( h->fenc->i_type == X264_TYPE_P )  
  251.     {  
  252.         i_nal_type    = NAL_SLICE;  
  253.         i_nal_ref_idc = NAL_PRIORITY_HIGH; /* Not completely true but for now it is (as all I/P are kept as ref)*/  
  254.         h->sh.i_type = SLICE_TYPE_P;  
  255.         x264_reference_hierarchy_reset( h ););//////////////////如果是非IDR的P帧,调用该函数  
  256.         h->frames.i_poc_last_open_gop = -1;  
  257.     }  
  258.     else if( h->fenc->i_type == X264_TYPE_BREF )  
  259.     {  
  260.         //可以作为参考帧的B帧,这是个特色  
  261.         i_nal_type    = NAL_SLICE;  
  262.         i_nal_ref_idc = h->param.i_bframe_pyramid == X264_B_PYRAMID_STRICT ? NAL_PRIORITY_LOW : NAL_PRIORITY_HIGH;  
  263.         h->sh.i_type = SLICE_TYPE_B;  
  264.         x264_reference_hierarchy_reset( h ););//////////////////如果是非IDR的B帧(可做为参考帧),调用该函数  
  265.     }  
  266.     else    /* B frame */  
  267.     {  
  268.         //最普通  
  269.         i_nal_type    = NAL_SLICE;  
  270.         i_nal_ref_idc = NAL_PRIORITY_DISPOSABLE;  
  271.         h->sh.i_type = SLICE_TYPE_B;  
  272.     }  
  273.   
  274.     //重建帧与编码帧的赋值  
  275.     h->fdec->i_type = h->fenc->i_type;  
  276.     h->fdec->i_frame = h->fenc->i_frame;  
  277.     h->fenc->b_kept_as_ref =  
  278.     h->fdec->b_kept_as_ref = i_nal_ref_idc != NAL_PRIORITY_DISPOSABLE && h->param.i_keyint_max > 1;  
  279.   
  280.     h->fdec->mb_info = h->fenc->mb_info;  
  281.     h->fdec->mb_info_free = h->fenc->mb_info_free;  
  282.     h->fenc->mb_info = NULL;  
  283.     h->fenc->mb_info_free = NULL;  
  284.   
  285.     h->fdec->i_pts = h->fenc->i_pts;  
  286.     if( h->frames.i_bframe_delay )  
  287.     {  
  288.         int64_t *prev_reordered_pts = thread_current->frames.i_prev_reordered_pts;  
  289.         h->fdec->i_dts = h->i_frame > h->frames.i_bframe_delay  
  290.                        ? prev_reordered_pts[ (h->i_frame - h->frames.i_bframe_delay) % h->frames.i_bframe_delay ]  
  291.                        : h->fenc->i_reordered_pts - h->frames.i_bframe_delay_time;  
  292.         prev_reordered_pts[ h->i_frame % h->frames.i_bframe_delay ] = h->fenc->i_reordered_pts;  
  293.     }  
  294.     else  
  295.         h->fdec->i_dts = h->fenc->i_reordered_pts;  
  296.     if( h->fenc->i_type == X264_TYPE_IDR )  
  297.         h->i_last_idr_pts = h->fdec->i_pts;  
  298.   
  299.     /* ------------------- Init                ----------------------------- */  
  300.     /* build ref list 0/1 */  
  301.     x264_reference_build_list( h, h->fdec->i_poc );//////////////////创建参考帧列表list0和list1  
  302.   
  303.     /* ---------------------- Write the bitstream -------------------------- */  
  304.     /* Init bitstream context */  
  305.     //用于输出  
  306.     if( h->param.b_sliced_threads )  
  307.     {  
  308.         forint i = 0; i < h->param.i_threads; i++ )  
  309.         {  
  310.             bs_init( &h->thread[i]->out.bs, h->thread[i]->out.p_bitstream, h->thread[i]->out.i_bitstream );  
  311.             h->thread[i]->out.i_nal = 0;  
  312.         }  
  313.     }  
  314.     else  
  315.     {  
  316.         bs_init( &h->out.bs, h->out.p_bitstream, h->out.i_bitstream );  
  317.         h->out.i_nal = 0;  
  318.     }  
  319.   
  320.     if( h->param.b_aud )  
  321.     {  
  322.         int pic_type;  
  323.   
  324.         if( h->sh.i_type == SLICE_TYPE_I )  
  325.             pic_type = 0;  
  326.         else if( h->sh.i_type == SLICE_TYPE_P )  
  327.             pic_type = 1;  
  328.         else if( h->sh.i_type == SLICE_TYPE_B )  
  329.             pic_type = 2;  
  330.         else  
  331.             pic_type = 7;  
  332.   
  333.         x264_nal_start( h, NAL_AUD, NAL_PRIORITY_DISPOSABLE );  
  334.         bs_write( &h->out.bs, 3, pic_type );  
  335.         bs_rbsp_trailing( &h->out.bs );  
  336.         if( x264_nal_end( h ) )  
  337.             return -1;  
  338.         overhead += h->out.nal[h->out.i_nal-1].i_payload + NALU_OVERHEAD;  
  339.     }  
  340.   
  341.     h->i_nal_type = i_nal_type;  
  342.     h->i_nal_ref_idc = i_nal_ref_idc;  
  343.   
  344.     if( h->param.b_intra_refresh )  
  345.     {  
  346.         if( IS_X264_TYPE_I( h->fenc->i_type ) )  
  347.         {  
  348.             h->fdec->i_frames_since_pir = 0;  
  349.             h->b_queued_intra_refresh = 0;  
  350.             /* PIR is currently only supported with ref == 1, so any intra frame effectively refreshes 
  351.              * the whole frame and counts as an intra refresh. */  
  352.             h->fdec->f_pir_position = h->mb.i_mb_width;  
  353.         }  
  354.         else if( h->fenc->i_type == X264_TYPE_P )  
  355.         {  
  356.             int pocdiff = (h->fdec->i_poc - h->fref[0][0]->i_poc)/2;  
  357.             float increment = X264_MAX( ((float)h->mb.i_mb_width-1) / h->param.i_keyint_max, 1 );  
  358.             h->fdec->f_pir_position = h->fref[0][0]->f_pir_position;  
  359.             h->fdec->i_frames_since_pir = h->fref[0][0]->i_frames_since_pir + pocdiff;  
  360.             if( h->fdec->i_frames_since_pir >= h->param.i_keyint_max ||  
  361.                 (h->b_queued_intra_refresh && h->fdec->f_pir_position + 0.5 >= h->mb.i_mb_width) )  
  362.             {  
  363.                 h->fdec->f_pir_position = 0;  
  364.                 h->fdec->i_frames_since_pir = 0;  
  365.                 h->b_queued_intra_refresh = 0;  
  366.                 h->fenc->b_keyframe = 1;  
  367.             }  
  368.             h->fdec->i_pir_start_col = h->fdec->f_pir_position+0.5;  
  369.             h->fdec->f_pir_position += increment * pocdiff;  
  370.             h->fdec->i_pir_end_col = h->fdec->f_pir_position+0.5;  
  371.             /* If our intra refresh has reached the right side of the frame, we're done. */  
  372.             if( h->fdec->i_pir_end_col >= h->mb.i_mb_width - 1 )  
  373.             {  
  374.                 h->fdec->f_pir_position = h->mb.i_mb_width;  
  375.                 h->fdec->i_pir_end_col = h->mb.i_mb_width - 1;  
  376.             }  
  377.         }  
  378.     }  
  379.   
  380.     if( h->fenc->b_keyframe )  
  381.     {  
  382.         //每个关键帧前面重复加上SPS和PPS  
  383.         /* Write SPS and PPS */  
  384.         if( h->param.b_repeat_headers )  
  385.         {  
  386.             /* generate sequence parameters */  
  387.             x264_nal_start( h, NAL_SPS, NAL_PRIORITY_HIGHEST );  
  388.             x264_sps_write( &h->out.bs, h->sps );  
  389.             if( x264_nal_end( h ) )  
  390.                 return -1;  
  391.             /* Pad AUD/SPS to 256 bytes like Panasonic */  
  392.             if( h->param.i_avcintra_class )  
  393.                 h->out.nal[h->out.i_nal-1].i_padding = 256 - bs_pos( &h->out.bs ) / 8 - 2*NALU_OVERHEAD;  
  394.             overhead += h->out.nal[h->out.i_nal-1].i_payload + h->out.nal[h->out.i_nal-1].i_padding + NALU_OVERHEAD;  
  395.   
  396.             /* generate picture parameters */  
  397.             x264_nal_start( h, NAL_PPS, NAL_PRIORITY_HIGHEST );  
  398.             x264_pps_write( &h->out.bs, h->sps, h->pps );  
  399.             if( x264_nal_end( h ) )  
  400.                 return -1;  
  401.             if( h->param.i_avcintra_class )  
  402.                 h->out.nal[h->out.i_nal-1].i_padding = 256 - h->out.nal[h->out.i_nal-1].i_payload - NALU_OVERHEAD;  
  403.             overhead += h->out.nal[h->out.i_nal-1].i_payload + h->out.nal[h->out.i_nal-1].i_padding + NALU_OVERHEAD;  
  404.         }  
  405.   
  406.         /* when frame threading is used, buffering period sei is written in x264_encoder_frame_end */  
  407.         if( h->i_thread_frames == 1 && h->sps->vui.b_nal_hrd_parameters_present )  
  408.         {  
  409.             x264_hrd_fullness( h );  
  410.             x264_nal_start( h, NAL_SEI, NAL_PRIORITY_DISPOSABLE );  
  411.             x264_sei_buffering_period_write( h, &h->out.bs );  
  412.             if( x264_nal_end( h ) )  
  413.                return -1;  
  414.             overhead += h->out.nal[h->out.i_nal-1].i_payload + SEI_OVERHEAD;  
  415.         }  
  416.     }  
  417.   
  418.     /* write extra sei */  
  419.     //下面很大一段代码用于写入SEI(一部分是为了适配其他的解码器)  
  420.     forint i = 0; i < h->fenc->extra_sei.num_payloads; i++ )  
  421.     {  
  422.         x264_nal_start( h, NAL_SEI, NAL_PRIORITY_DISPOSABLE );  
  423.         x264_sei_write( &h->out.bs, h->fenc->extra_sei.payloads[i].payload, h->fenc->extra_sei.payloads[i].payload_size,  
  424.                         h->fenc->extra_sei.payloads[i].payload_type );  
  425.         if( x264_nal_end( h ) )  
  426.             return -1;  
  427.         overhead += h->out.nal[h->out.i_nal-1].i_payload + SEI_OVERHEAD;  
  428.         if( h->fenc->extra_sei.sei_free )  
  429.         {  
  430.             h->fenc->extra_sei.sei_free( h->fenc->extra_sei.payloads[i].payload );  
  431.             h->fenc->extra_sei.payloads[i].payload = NULL;  
  432.         }  
  433.     }  
  434.   
  435.     if( h->fenc->extra_sei.sei_free )  
  436.     {  
  437.         h->fenc->extra_sei.sei_free( h->fenc->extra_sei.payloads );  
  438.         h->fenc->extra_sei.payloads = NULL;  
  439.         h->fenc->extra_sei.sei_free = NULL;  
  440.     }  
  441.   
  442.     //特殊的SEI信息(Avid等解码器需要)  
  443.     if( h->fenc->b_keyframe )  
  444.     {  
  445.         /* Avid's decoder strictly wants two SEIs for AVC-Intra so we can't insert the x264 SEI */  
  446.         if( h->param.b_repeat_headers && h->fenc->i_frame == 0 && !h->param.i_avcintra_class )  
  447.         {  
  448.             /* identify ourself */  
  449.             x264_nal_start( h, NAL_SEI, NAL_PRIORITY_DISPOSABLE );  
  450.             if( x264_sei_version_write( h, &h->out.bs ) )  
  451.                 return -1;  
  452.             if( x264_nal_end( h ) )  
  453.                 return -1;  
  454.             overhead += h->out.nal[h->out.i_nal-1].i_payload + SEI_OVERHEAD;  
  455.         }  
  456.   
  457.         if( h->fenc->i_type != X264_TYPE_IDR )  
  458.         {  
  459.             int time_to_recovery = h->param.b_open_gop ? 0 : X264_MIN( h->mb.i_mb_width - 1, h->param.i_keyint_max ) + h->param.i_bframe - 1;  
  460.             x264_nal_start( h, NAL_SEI, NAL_PRIORITY_DISPOSABLE );  
  461.             x264_sei_recovery_point_write( h, &h->out.bs, time_to_recovery );  
  462.             if( x264_nal_end( h ) )  
  463.                 return -1;  
  464.             overhead += h->out.nal[h->out.i_nal-1].i_payload + SEI_OVERHEAD;  
  465.         }  
  466.     }  
  467.   
  468.     if( h->param.i_frame_packing >= 0 && (h->fenc->b_keyframe || h->param.i_frame_packing == 5) )  
  469.     {  
  470.         x264_nal_start( h, NAL_SEI, NAL_PRIORITY_DISPOSABLE );  
  471.         x264_sei_frame_packing_write( h, &h->out.bs );  
  472.         if( x264_nal_end( h ) )  
  473.             return -1;  
  474.         overhead += h->out.nal[h->out.i_nal-1].i_payload + SEI_OVERHEAD;  
  475.     }  
  476.   
  477.     /* generate sei pic timing */  
  478.     if( h->sps->vui.b_pic_struct_present || h->sps->vui.b_nal_hrd_parameters_present )  
  479.     {  
  480.         x264_nal_start( h, NAL_SEI, NAL_PRIORITY_DISPOSABLE );  
  481.         x264_sei_pic_timing_write( h, &h->out.bs );  
  482.         if( x264_nal_end( h ) )  
  483.             return -1;  
  484.         overhead += h->out.nal[h->out.i_nal-1].i_payload + SEI_OVERHEAD;  
  485.     }  
  486.   
  487.     /* As required by Blu-ray. */  
  488.     if( !IS_X264_TYPE_B( h->fenc->i_type ) && h->b_sh_backup )  
  489.     {  
  490.         h->b_sh_backup = 0;  
  491.         x264_nal_start( h, NAL_SEI, NAL_PRIORITY_DISPOSABLE );  
  492.         x264_sei_dec_ref_pic_marking_write( h, &h->out.bs );  
  493.         if( x264_nal_end( h ) )  
  494.             return -1;  
  495.         overhead += h->out.nal[h->out.i_nal-1].i_payload + SEI_OVERHEAD;  
  496.     }  
  497.   
  498.     if( h->fenc->b_keyframe && h->param.b_intra_refresh )  
  499.         h->i_cpb_delay_pir_offset_next = h->fenc->i_cpb_delay;  
  500.   
  501.     /* Filler space: 10 or 18 SEIs' worth of space, depending on resolution */  
  502.     if( h->param.i_avcintra_class )  
  503.     {  
  504.         /* Write an empty filler NAL to mimic the AUD in the P2 format*/  
  505.         x264_nal_start( h, NAL_FILLER, NAL_PRIORITY_DISPOSABLE );  
  506.         x264_filler_write( h, &h->out.bs, 0 );  
  507.         if( x264_nal_end( h ) )  
  508.             return -1;  
  509.         overhead += h->out.nal[h->out.i_nal-1].i_payload + NALU_OVERHEAD;  
  510.   
  511.         /* All lengths are magic lengths that decoders expect to see */  
  512.         /* "UMID" SEI */  
  513.         x264_nal_start( h, NAL_SEI, NAL_PRIORITY_DISPOSABLE );  
  514.         if( x264_sei_avcintra_umid_write( h, &h->out.bs ) < 0 )  
  515.             return -1;  
  516.         if( x264_nal_end( h ) )  
  517.             return -1;  
  518.         overhead += h->out.nal[h->out.i_nal-1].i_payload + SEI_OVERHEAD;  
  519.   
  520.         int unpadded_len;  
  521.         int total_len;  
  522.         if( h->param.i_height == 1080 )  
  523.         {  
  524.             unpadded_len = 5780;  
  525.             total_len = 17*512;  
  526.         }  
  527.         else  
  528.         {  
  529.             unpadded_len = 2900;  
  530.             total_len = 9*512;  
  531.         }  
  532.         /* "VANC" SEI */  
  533.         x264_nal_start( h, NAL_SEI, NAL_PRIORITY_DISPOSABLE );  
  534.         if( x264_sei_avcintra_vanc_write( h, &h->out.bs, unpadded_len ) < 0 )  
  535.             return -1;  
  536.         if( x264_nal_end( h ) )  
  537.             return -1;  
  538.   
  539.         h->out.nal[h->out.i_nal-1].i_padding = total_len - h->out.nal[h->out.i_nal-1].i_payload - SEI_OVERHEAD;  
  540.         overhead += h->out.nal[h->out.i_nal-1].i_payload + h->out.nal[h->out.i_nal-1].i_padding + SEI_OVERHEAD;  
  541.     }//写入SEI代码结束  
  542.   
  543.     /* Init the rate control */  
  544.     /* FIXME: Include slice header bit cost. */  
  545.     x264_ratecontrol_start( h, h->fenc->i_qpplus1, overhead*8 );////////////////////////码率控制单元开始  
  546.     i_global_qp = x264_ratecontrol_qp( h );  
  547.   
  548.     pic_out->i_qpplus1 =  
  549.     h->fdec->i_qpplus1 = i_global_qp + 1;  
  550.   
  551.     if( h->param.rc.b_stat_read && h->sh.i_type != SLICE_TYPE_I )  
  552.     {  
  553.         x264_reference_build_list_optimal( h );  
  554.         x264_reference_check_reorder( h );  
  555.     }  
  556.   
  557.     if( h->i_ref[0] )  
  558.         h->fdec->i_poc_l0ref0 = h->fref[0][0]->i_poc;  
  559.   
  560.     /* ------------------------ Create slice header  ----------------------- */  
  561.     x264_slice_init( h, i_nal_type, i_global_qp );//////////////////////////创建Slice Header  
  562.   
  563.     /*------------------------- Weights -------------------------------------*/  
  564.     //加权预测  
  565.     if( h->sh.i_type == SLICE_TYPE_B )  
  566.         x264_macroblock_bipred_init( h );  
  567.   
  568.     x264_weighted_pred_init( h );  
  569.   
  570.     if( i_nal_ref_idc != NAL_PRIORITY_DISPOSABLE )  
  571.         h->i_frame_num++;  
  572.   
  573.     /* Write frame */  
  574.     h->i_threadslice_start = 0;  
  575.     h->i_threadslice_end = h->mb.i_mb_height;  
  576.     if( h->i_thread_frames > 1 )  
  577.     {  
  578.         x264_threadpool_run( h->threadpool, (void*)x264_slices_write, h );  
  579.         h->b_thread_active = 1;  
  580.     }  
  581.     else if( h->param.b_sliced_threads )  
  582.     {  
  583.         if( x264_threaded_slices_write( h ) )  
  584.             return -1;  
  585.     }  
  586.     else  
  587.         if( (intptr_t)x264_slices_write( h ) )////////////////////////真正的编码——编码1个图像帧(注意这里“slices”后面有“s”)  
  588.             return -1;  
  589.   
  590.     return x264_encoder_frame_end( thread_oldest, thread_current, pp_nal, pi_nal, pic_out );//////////////////结束的时候做一些处理,记录一些统计信息:输出NALU、输出重建帧  
  591. }  


        从源代码可以看出,x264_encoder_encode()的流程大致如下:

1)调用x264_frame_pop_unused获取一个空的fencx264_frame_t类型)用于存储一帧编码像素数据。

2)调用x264_frame_copy_picture()将外部结构体的pic_inx264_picture_t类型)的数据拷贝给内部结构体的fencx264_frame_t类型)。

3)调用x264_lookahead_put_frame()fenc放入Lookahead模块的队列中,等待确定帧类型。

4)调用x264_lookahead_get_frames()分析Lookahead模块中一个帧的帧类型。分析后的帧保存在frames.current[]中。

5)调用x264_frame_shift()frames.current[]中取出分析帧类型之后的fenc

6)调用x264_reference_update()更新参考帧队列frames.reference[]

7)如果编码帧fencIDR帧,调用x264_reference_reset()清空参考帧队列frames.reference[]

8)调用x264_reference_build_list()创建参考帧列表List0List1

9)根据选项做一些配置:

          a)、如果b_aud不为0,输出AUD类型NALU

          b)、在当前帧是关键帧的情况下,如果b_repeat_headers不为0,调用x264_sps_write()x264_pps_write()输出SPSPPS

          c)、输出一些特殊的SEI信息,用于适配各种解码器。

10)调用x264_slice_init()初始化Slice Header信息。

11)调用x264_slices_write()进行编码。该部分是libx264的核心,在后续文章中会详细分析。

12)调用x264_encoder_frame_end()做一些编码后的后续处理。

0 0
原创粉丝点击