文档章节

x264 x264_slicetype_analyse 函数分析

貌似高手
 貌似高手
发布于 2017/05/01 11:52
字数 2005
阅读 28
收藏 0
点赞 0
评论 0

 x264_slicetype_annlyse 方法是确定待编码slice在率失真限制下slicetype 的选择:

       1,已经确定slicetype 的最近的一个非Bslice为参照帧和待编码的slices组成一个slices 数

作为分析slicestype 的基础数据结构.

       2,针对qp初始化对应的各种cost table https://my.oschina.net/u/269082/blog/886661

       3,check 是否是一个gop 的开始(需要插入IDR) 或者是否视频内容有场景切换没有向前参考的价值(需要插入Islice),此时只检查一个none_B 之后的第一个未确定类型的帧.注意GOP的最后一个帧一定要是P帧(B帧的话需要下一个GOP的帧做p1参考帧,场景都切换了做参考帧没有意义)

                         4,如果不是Islice 则具体计算分别是P,B片时的cost.

                            以X264_B_ADAPT_FAST为例计算第i帧是P帧即P_OR_I(last_none_B_slice)P(i)P(i+1)的代价,以及第i帧是B帧即P_OR_I(last_none_B_slice)B(i)P(i+1)的代价 来确定当前slice 的类型是选择P还是选择B具体参见后续x264_slicetype_frame_cost函数:

   int cost2p1 = x264_slicetype_frame_cost( h, &a, frames, last_nonb+0, j+1, j+1, 1 ); //last_nonb+0 为p0参考帧,j+1 为P 帧的代价

        int cost1b1 = x264_slicetype_frame_cost( h, &a, frames, last_nonb+0, j+1, j+0, 0 );// last_nonb+0为p0参考帧,j为B帧j+1为P帧作为p1参考的代价

        int cost1p0 = x264_slicetype_frame_cost( h, &a, frames, last_nonb+0, j+0, j+0, 0 ); //ast_nonb+0为p0参考,j为P帧的代价

        int cost2p0 = x264_slicetype_frame_cost( h, &a, frames, last_nonb+1, j+1, j+1, 0 );//ast_nonb+1为p0参考,j+1为P帧的代价

      选定第j帧为P 还是为 B的标准如下last_nonb+0,j,j+1 三帧确定第j帧的类型:cost(P,P,P) < cost(P,B,P)?P:B

1639                      if( cost1p0 + cost2p0 < cost1b1 + cost2p1 )
1640                      {// cost(P,P,P) < cost(p,b,p)?P:B 
1641                          frames[j]->i_type = X264_TYPE_P;
1642                          continue;
1643                      }
1644                      frames[j]->i_type = X264_TYPE_B;
1645                      continue;

       5, check 是否超过最大的连续Bslice 限制,如果超过最大连续Bslices 限制则下一片的类型为改为P帧(避免量化误差在时间上的蔓延)

    6,猜测:检查minigop 已经确定的连续B帧中是不是有场景切换,如果有则把B帧换成P帧编码//TODO fixed me.

    7,如果有具体RC算法,需要遵循具体的RC 算法限制,微调类型选择,详见VBV 算法分析.

1770      if( vbv_lookahead )
1771          x264_vbv_lookahead( h, &a, frames, num_frames, keyframe );

 

整个方法的源代码如下/x264/encoder/slicetype.c

void x264_slicetype_analyse( x264_t *h, int intra_minigop )
1478  {
1479      x264_mb_analysis_t a;
1480      x264_frame_t *frames[X264_LOOKAHEAD_MAX+3] = { NULL, };
1481      int num_frames, orig_num_frames, keyint_limit, framecnt;
1482      int i_mb_count = NUM_MBS;
1483      int i_max_search = X264_MIN( h->lookahead->next.i_size, X264_LOOKAHEAD_MAX );
1484      int vbv_lookahead = h->param.rc.i_vbv_buffer_size && h->param.rc.i_lookahead;
1485      /* For determinism we should limit the search to the number of frames lookahead has for sure
1486       * in h->lookahead->next.list buffer, except at the end of stream.
1487       * For normal calls with (intra_minigop == 0) that is h->lookahead->i_slicetype_length + 1 frames.
1488       * And for I-frame calls (intra_minigop != 0) we already removed intra_minigop frames from there. */
1489      if( h->param.b_deterministic )
1490          i_max_search = X264_MIN( i_max_search, h->lookahead->i_slicetype_length + 1 - intra_minigop );
1491      int keyframe = !!intra_minigop;
1492  
1493      assert( h->frames.b_have_lowres );
1494  
1495      if( !h->lookahead->last_nonb )
1496          return;

1

1497      frames[0] = h->lookahead->last_nonb;
1498      for( framecnt = 0; framecnt < i_max_search; framecnt++ )
1499          frames[framecnt+1] = h->lookahead->next.list[framecnt];
1500  

2

1501      x264_lowres_context_init( h, &a );
1502  
1503      if( !framecnt )
1504      {
1505          if( h->param.rc.b_mb_tree )
1506              x264_macroblock_tree( h, &a, frames, 0, keyframe );
1507          return;
1508      }
1509  
1510      keyint_limit = h->param.i_keyint_max - frames[0]->i_frame + h->lookahead->i_last_keyframe - 1;
1511      orig_num_frames = num_frames = h->param.b_intra_refresh ? framecnt : X264_MIN( framecnt, keyint_limit );
1512  
1513      /* This is important psy-wise: if we have a non-scenecut keyframe,
1514       * there will be significant visual artifacts if the frames just before
1515       * go down in quality due to being referenced less, despite it being
1516       * more RD-optimal. */
1517      if( (h->param.analyse.b_psy && h->param.rc.b_mb_tree) || vbv_lookahead )
1518          num_frames = framecnt;
1519      else if( h->param.b_open_gop && num_frames < framecnt )
1520          num_frames++;
1521      else if( num_frames == 0 )
1522      {
1523          frames[1]->i_type = X264_TYPE_I;
1524          return;
1525      }
1526  

3

1527      if( IS_X264_TYPE_AUTO_OR_I( frames[1]->i_type ) &&
1528          h->param.i_scenecut_threshold && scenecut( h, &a, frames, 0, 1, 1, orig_num_frames, i_max_search ) )
1529      {
1530          if( frames[1]->i_type == X264_TYPE_AUTO )
1531              frames[1]->i_type = X264_TYPE_I;
1532          return;
1533      }
1534  
1535  #if HAVE_OPENCL
1536      x264_opencl_slicetype_prep( h, frames, num_frames, a.i_lambda );
1537  #endif
1538  
1539      /* Replace forced keyframes with I/IDR-frames */
1540      for( int j = 1; j <= num_frames; j++ )
1541      {
1542          if( frames[j]->i_type == X264_TYPE_KEYFRAME )
1543              frames[j]->i_type = h->param.b_open_gop ? X264_TYPE_I : X264_TYPE_IDR;
1544      }
1545  
1546      /* Close GOP at IDR-frames */
1547      for( int j = 2; j <= num_frames; j++ )
1548      {
1549          if( frames[j]->i_type == X264_TYPE_IDR && IS_X264_TYPE_AUTO_OR_B( frames[j-1]->i_type ) )
1550              frames[j-1]->i_type = X264_TYPE_P;
1551      }
1552  
1553      int num_analysed_frames = num_frames;
1554      int reset_start;
1555  
1556      if( h->param.i_bframe )
1557      {
1558          if( h->param.i_bframe_adaptive == X264_B_ADAPT_TRELLIS )
1559          {
1560              if( num_frames > 1 )
1561              {
1562                  char best_paths[X264_BFRAME_MAX+1][X264_LOOKAHEAD_MAX+1] = {"","P"};
1563                  int best_path_index = num_frames % (X264_BFRAME_MAX+1);
1564  
1565                  /* Perform the frametype analysis. */
1566                  for( int j = 2; j <= num_frames; j++ )
1567                      x264_slicetype_path( h, &a, frames, j, best_paths );
1568  
1569                  /* Load the results of the analysis into the frame types. */
1570                  for( int j = 1; j < num_frames; j++ )
1571                  {
1572                      if( best_paths[best_path_index][j-1] != 'B' )
1573                      {
1574                          if( IS_X264_TYPE_AUTO_OR_B( frames[j]->i_type ) )
1575                              frames[j]->i_type = X264_TYPE_P;
1576                      }
1577                      else
1578                      {
1579                          if( frames[j]->i_type == X264_TYPE_AUTO )
1580                              frames[j]->i_type = X264_TYPE_B;
1581                      }
1582                  }
1583              }
1584          }

4

1585          else if( h->param.i_bframe_adaptive == X264_B_ADAPT_FAST )
1586          {
1587              int last_nonb = 0;
1588              int num_bframes = h->param.i_bframe;
1589              for( int j = 1; j < num_frames; j++ )
1590              {
1591                  if( j-1 > 0 && IS_X264_TYPE_B( frames[j-1]->i_type ) )
1592                      num_bframes--;
1593                  else
1594                  {
1595                      last_nonb = j-1;
1596                      num_bframes = h->param.i_bframe;
1597                  }
1598                  if( !num_bframes )
1599                  {
1600                      if( IS_X264_TYPE_AUTO_OR_B( frames[j]->i_type ) )
1601                          frames[j]->i_type = X264_TYPE_P;
1602                      continue;
1603                  }
1604  
1605                  if( frames[j]->i_type != X264_TYPE_AUTO )
1606                      continue;
1607  
1608                  if( IS_X264_TYPE_B( frames[j+1]->i_type ) )
1609                  {
1610                      frames[j]->i_type = X264_TYPE_P;
1611                      continue;
1612                  }
1613  
1614                  if( j - last_nonb <= 1 )
1615                  {
1616                      int cost2p1 = x264_slicetype_frame_cost( h, &a, frames, last_nonb+0, j+1, j+1, 1 );
1617                      if( frames[j+1]->i_intra_mbs[2] > i_mb_count / 2 )
1618                      {
1619                          frames[j]->i_type = X264_TYPE_P;
1620                          continue;
1621                      }
1622  
1623  #if HAVE_OPENCL
1624                      if( h->param.b_opencl )
1625                      {
1626                          int b_work_done = 0;
1627                          b_work_done |= x264_opencl_precalculate_frame_cost(h, frames, a.i_lambda, last_nonb+0, j+1, j+0 );
1628                          b_work_done |= x264_opencl_precalculate_frame_cost(h, frames, a.i_lambda, last_nonb+0, j+0, j+0 );
1629                          b_work_done |= x264_opencl_precalculate_frame_cost(h, frames, a.i_lambda, last_nonb+1, j+1, j+1 );
1630                          if( b_work_done )
1631                              x264_opencl_flush( h );
1632                      }
1633  #endif
1634  
1635                      int cost1b1 = x264_slicetype_frame_cost( h, &a, frames, last_nonb+0, j+1, j+0, 0 );
1636                      int cost1p0 = x264_slicetype_frame_cost( h, &a, frames, last_nonb+0, j+0, j+0, 0 );
1637                      int cost2p0 = x264_slicetype_frame_cost( h, &a, frames, last_nonb+1, j+1, j+1, 0 );
1638  
1639                      if( cost1p0 + cost2p0 < cost1b1 + cost2p1 )
1640                      {
1641                          frames[j]->i_type = X264_TYPE_P;
1642                          continue;
1643                      }
1644                      frames[j]->i_type = X264_TYPE_B;
1645                      continue;
1646                  }
1647  
1648                  // arbitrary and untuned
1649                  #define INTER_THRESH 300
1650                  #define P_SENS_BIAS (50 - h->param.i_bframe_bias)
1651  
1652                  int pthresh = X264_MAX(INTER_THRESH - P_SENS_BIAS * (j-last_nonb-1), INTER_THRESH/10);
1653                  int pcost = x264_slicetype_frame_cost( h, &a, frames, last_nonb, j+1, j+1, 1 );
1654                  if( pcost > pthresh*i_mb_count || frames[j+1]->i_intra_mbs[j-last_nonb+1] > i_mb_count/3 )
1655                      frames[j]->i_type = X264_TYPE_P;
1656                  else
1657                      frames[j]->i_type = X264_TYPE_B;
1658              }
1659          }
1660          else
1661          {
1662              int num_bframes = h->param.i_bframe;
1663              for( int j = 1; j < num_frames; j++ )
1664              {
1665                  if( !num_bframes )
1666                  {
1667                      if( IS_X264_TYPE_AUTO_OR_B( frames[j]->i_type ) )
1668                          frames[j]->i_type = X264_TYPE_P;
1669                  }
1670                  else if( frames[j]->i_type == X264_TYPE_AUTO )
1671                  {
1672                      if( IS_X264_TYPE_B( frames[j+1]->i_type ) )
1673                          frames[j]->i_type = X264_TYPE_P;
1674                      else
1675                          frames[j]->i_type = X264_TYPE_B;
1676                  }
1677                  if( IS_X264_TYPE_B( frames[j]->i_type ) )
1678                      num_bframes--;
1679                  else
1680                      num_bframes = h->param.i_bframe;
1681              }
1682          }

1683          if( IS_X264_TYPE_AUTO_OR_B( frames[num_frames]->i_type ) )
1684              frames[num_frames]->i_type = X264_TYPE_P;
1685  
1686          int num_bframes = 0;
1687          while( num_bframes < num_frames && IS_X264_TYPE_B( frames[num_bframes+1]->i_type ) )
1688              num_bframes++;
1689 

 
1690          /* Check scenecut on the first minigop. */
1691          for( int j = 1; j < num_bframes+1; j++ )
1692          {
1693              if( frames[j]->i_forced_type == X264_TYPE_AUTO && IS_X264_TYPE_AUTO_OR_I( frames[j+1]->i_forced_type ) &&
1694                  h->param.i_scenecut_threshold && scenecut( h, &a, frames, j, j+1, 0, orig_num_frames, i_max_search ) )
1695              {
1696                  frames[j]->i_type = X264_TYPE_P;
1697                  num_analysed_frames = j;
1698                  break;
1699              }
1700          }
1701  
1702          reset_start = keyframe ? 1 : X264_MIN( num_bframes+2, num_analysed_frames+1 );
1703      }
1704      else
1705      {
1706          for( int j = 1; j <= num_frames; j++ )
1707              if( IS_X264_TYPE_AUTO_OR_B( frames[j]->i_type ) )
1708                  frames[j]->i_type = X264_TYPE_P;
1709          reset_start = !keyframe + 1;
1710      }
1711  
1712      /* Perform the actual macroblock tree analysis.
1713       * Don't go farther than the maximum keyframe interval; this helps in short GOPs. */
1714      if( h->param.rc.b_mb_tree )
1715          x264_macroblock_tree( h, &a, frames, X264_MIN(num_frames, h->param.i_keyint_max), keyframe );
1716  
1717      /* Enforce keyframe limit. */
1718      if( !h->param.b_intra_refresh )
1719      {
1720          int last_keyframe = h->lookahead->i_last_keyframe;
1721          int last_possible = 0;
1722          for( int j = 1; j <= num_frames; j++ )
1723          {
1724              x264_frame_t *frm = frames[j];
1725              int keyframe_dist = frm->i_frame - last_keyframe;
1726  
1727              if( IS_X264_TYPE_AUTO_OR_I( frm->i_forced_type ) )
1728              {
1729                  if( h->param.b_open_gop || !IS_X264_TYPE_B( frames[j-1]->i_forced_type ) )
1730                      last_possible = j;
1731              }
1732              if( keyframe_dist >= h->param.i_keyint_max )
1733              {
1734                  if( last_possible != 0 && last_possible != j )
1735                  {
1736                      j = last_possible;
1737                      frm = frames[j];
1738                      keyframe_dist = frm->i_frame - last_keyframe;
1739                  }
1740                  last_possible = 0;
1741                  if( frm->i_type != X264_TYPE_IDR )
1742                      frm->i_type = h->param.b_open_gop ? X264_TYPE_I : X264_TYPE_IDR;
1743              }
1744              if( frm->i_type == X264_TYPE_I && keyframe_dist >= h->param.i_keyint_min )
1745              {
1746                  if( h->param.b_open_gop )
1747                  {
1748                      last_keyframe = frm->i_frame;
1749                      if( h->param.b_bluray_compat )
1750                      {
1751                          // Use bluray order
1752                          int bframes = 0;
1753                          while( bframes < j-1 && IS_X264_TYPE_B( frames[j-1-bframes]->i_type ) )
1754                              bframes++;
1755                          last_keyframe -= bframes;
1756                      }
1757                  }
1758                  else if( frm->i_forced_type != X264_TYPE_I )
1759                      frm->i_type = X264_TYPE_IDR;
1760              }
1761              if( frm->i_type == X264_TYPE_IDR )
1762              {
1763                  last_keyframe = frm->i_frame;
1764                  if( j > 1 && IS_X264_TYPE_B( frames[j-1]->i_type ) )
1765                      frames[j-1]->i_type = X264_TYPE_P;
1766              }
1767          }
1768      }
1769

  
1770      if( vbv_lookahead )
1771          x264_vbv_lookahead( h, &a, frames, num_frames, keyframe );
1772  
1773      /* Restore frametypes for all frames that haven't actually been decided yet. */
1774      for( int j = reset_start; j <= num_frames; j++ )
1775          frames[j]->i_type = frames[j]->i_forced_type;
1776  
1777  #if HAVE_OPENCL
1778      x264_opencl_slicetype_end( h );
1779  #endif
1780  }

 

 

© 著作权归作者所有

共有 人打赏支持
貌似高手
粉丝 8
博文 60
码字总数 59033
作品 0
海淀
高级程序员
x264源代码简单分析:编码器主干部分-2

===================================================== H.264源代码分析文章列表: 【编码 - x264】 x264源代码简单分析:概述 x264源代码简单分析:x264命令行工具(x264.exe) x264源代码...

leixiaohua1020 ⋅ 2015/05/14 ⋅ 0

x264源代码简单分析:概述

===================================================== H.264源代码分析文章列表: 【编码 - x264】 x264源代码简单分析:概述 x264源代码简单分析:x264命令行工具(x264.exe) x264源代码...

leixiaohua1020 ⋅ 2015/05/06 ⋅ 0

音视频技术--H.264代码与标准如何对应

总是有人说自己把代码和标准对应不起来。其实是因为你要么不知道标准各个章节讲的什么,要么不知道代码中各个函数的功能,或者两者都不知道。今天再以 X264 的帧内编码为例让大家体会一下读代...

技术小阿哥 ⋅ 2017/11/27 ⋅ 0

x264源代码简单分析:宏块分析(Analysis)部分-帧间宏块(Inter)

===================================================== H.264源代码分析文章列表: 【编码 - x264】 x264源代码简单分析:概述 x264源代码简单分析:x264命令行工具(x264.exe) x264源代码...

leixiaohua1020 ⋅ 2015/05/23 ⋅ 0

x264源代码简单分析:宏块分析(Analysis)部分-帧内宏块(Intra)

===================================================== H.264源代码分析文章列表: 【编码 - x264】 x264源代码简单分析:概述 x264源代码简单分析:x264命令行工具(x264.exe) x264源代码...

leixiaohua1020 ⋅ 2015/05/22 ⋅ 0

x264源代码简单分析:编码器主干部分-1

===================================================== H.264源代码分析文章列表: 【编码 - x264】 x264源代码简单分析:概述 x264源代码简单分析:x264命令行工具(x264.exe) x264源代码...

leixiaohua1020 ⋅ 2015/05/11 ⋅ 0

x264源代码简单分析:x264_slice_write()

===================================================== H.264源代码分析文章列表: 【编码 - x264】 x264源代码简单分析:概述 x264源代码简单分析:x264命令行工具(x264.exe) x264源代码...

leixiaohua1020 ⋅ 2015/05/17 ⋅ 0

[直播一揽子]x264参数的解释

x264paramdefault(¶m);//设置默认参数具体见common/common.c int yuvsize=mheightmwidth3/2; param.i_width=m_width; param.i_height=m_height; param.i_keyint_min=5;//关键帧最小间隔 ......

拉风的道长 ⋅ 2016/07/15 ⋅ 0

x264源代码简单分析:熵编码(Entropy Encoding)部分

===================================================== H.264源代码分析文章列表: 【编码 - x264】 x264源代码简单分析:概述 x264源代码简单分析:x264命令行工具(x264.exe) x264源代码...

leixiaohua1020 ⋅ 2015/05/24 ⋅ 0

x264 码率控制:mb-tree

本文是关于x264中mb-tree算法的介绍,有不准确的地方欢迎指正 在新版本的x264中,mb-tree是默认开启的,和自适应量化(adaptive quantization )一起控制MB级的QP mb-tree的具体作用原理是:...

zhoudegui88 ⋅ 05/07 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

收集自网络的wordpress 分页导航的代码教程(全网最全版)

wordpress 分页导航是用来切换文章的一个功能,添加了 wordpress 分页导航后,用户即可自由到达指定的页面数浏览分类文章,而这样的一个很简单功能却有很多朋友在用插件:WP-PageNavi,插件的...

Rhymo-Wu ⋅ 36分钟前 ⋅ 0

微服务 WildFly Swarm 入门

Hello World 就像前面章节中的其他框架一样,我们希望添加一些基本的 Hello-world 功能,然后在其上逐步添加更多的功能。让我们从在我们的项目中创建一个 HolaResources 开始。您可以使用您的...

woshixin ⋅ 43分钟前 ⋅ 0

Maven的安装和Eclipse的配置

1. 下载Maven 下载地址 2. 解压压缩包,放到自己习惯的硬盘中 此处我将其放到了 D:\Tools 目录下。 3. 配置环境变量 右键此电脑 -> 属性 -> 高级系统设置 -> 环境变量。 在系统变量中新建,变...

影狼 ⋅ 50分钟前 ⋅ 0

python pip使用国内镜像的方法

国内源 清华:https://pypi.tuna.tsinghua.edu.cn/simple 阿里云:http://mirrors.aliyun.com/pypi/simple/ 中国科技大学 https://pypi.mirrors.ustc.edu.cn/simple/ 华中理工大学:http://......

良言 ⋅ 51分钟前 ⋅ 0

对于url变化的spa应该如何使用微信jssdk

使用vue单页面碰上微信jssdk config验证失败的坑。第一次成功 之后切换页面全部失败,找到了解决方法,第一次验证成功后保存验证信息 切换页面时验证信息直接拿来用,加一个wx.error() 失败时...

孙冠峰 ⋅ 55分钟前 ⋅ 0

Spring Cloud Gateway 一般集成

SCF发布,带来很多新东西,不过少了点教程,打开方式又和以前的不一样,比如这个SCG,压根就没有入门指导,所以这里写一个,以备后用。 一、集成 pom.xml <dependency> <groupI...

kut ⋅ 59分钟前 ⋅ 0

建造模式

《JAVA与模式》之建造模式

Cobbage ⋅ 今天 ⋅ 0

WePY框架开发的小程序如何在微信web开发者工具中运行起来

一、首先需要安装node.js,安装步骤如下: 首先下载安装包 https://nodejs.org/en/download/ 点击下载相应的zip版本 然后将文件夹解压到任意目录 比如我这里解压到了:C:\Program Files\node...

Helios51 ⋅ 今天 ⋅ 0

使用EnumSet 代替位域(32)

1、位域(Bit field):使用or 运算将几个常量合并到一个集合中 位操作,可以有效地执行 AND 、OR 这样的位操作 但是 位域比int 常量枚举缺点更多 2、java.util 包里面的EnumSet 类是有效的替...

职业搬砖20年 ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部