x264_scan8分析

先上代码及注释

    
    
  1. #define X264_SCAN8_SIZE (6*8) //!< 扫描表的尺寸
  2. #define X264_SCAN8_0 (4+1*8) //!< 扫描表第一个扫描序(即亮度的首扫描序)
  3. static const int x264_scan8[ 16+ 2* 4+ 3] =
  4. {
  5. /* Luma */
  6. 4+ 1* 8, 5+ 1* 8, 4+ 2* 8, 5+ 2* 8,
  7. 6+ 1* 8, 7+ 1* 8, 6+ 2* 8, 7+ 2* 8,
  8. 4+ 3* 8, 5+ 3* 8, 4+ 4* 8, 5+ 4* 8,
  9. 6+ 3* 8, 7+ 3* 8, 6+ 4* 8, 7+ 4* 8,
  10. /* Cb */
  11. 1+ 1* 8, 2+ 1* 8,
  12. 1+ 2* 8, 2+ 2* 8,
  13. /* Cr */
  14. 1+ 4* 8, 2+ 4* 8,
  15. 1+ 5* 8, 2+ 5* 8,
  16. /* Luma DC */
  17. 4+ 5* 8,
  18. /* Chroma DC */
  19. 5+ 5* 8, 6+ 5* 8
  20. };
  21. /*
  22. 0 1 2 3 4 5 6 7
  23. 0
  24. 1 B B L L L L
  25. 2 B B L L L L
  26. 3 L L L L
  27. 4 R R L L L L
  28. 5 R R DyDuDv
  29. */ // B – Cb; R – Cr; L – Luma; Dy – Luma DC; Du – Cb DC; Dv – Cr DC

x264_scan8是一个存放着4x4亮度块及色度块扫描序的数组,其内存存储方式如下所示:

其中,每一个小方格代表着一个4x4块,方格中的数字则是对应块的序号。

根据代码中对x264_scan8这个数组的赋值不难得到上图,其中,红色方块代表的是亮度块,绿色块和蓝色块分别代表两个色度块,而三个橙色块则依次代表亮度、两个色度的DC块。

为什么要这么做呢?我们知道,在进行帧内预测,帧间运动矢量预测的时候,需要使用到当前块的left块和top块,在CAVLC编码过程中,也需要知道当前块的left块和top块的non_zero_count,故由上图可以看到,空出来的部分可以用于存储前述所需的left块和top块的相关参数,起到便于访问和节省内存的作用。

看下面这个例子:


    
    
  1. void x264_mb_predict_mv_16x16( x264_t *h, int i_list, int i_ref, int16_t mvp[2] )
  2. {
  3. int i_refa = h->mb.cache.ref[i_list][X264_SCAN8_0 - 1]; //!< a块参考帧序号
  4. int16_t *mv_a = h->mb.cache.mv[i_list][X264_SCAN8_0 - 1]; //!< a块的运动矢量
  5. int i_refb = h->mb.cache.ref[i_list][X264_SCAN8_0 - 8]; //!< b块参考帧序号
  6. int16_t *mv_b = h->mb.cache.mv[i_list][X264_SCAN8_0 - 8]; //!< b块的运动矢量
  7. int i_refc = h->mb.cache.ref[i_list][X264_SCAN8_0 - 8 + 4]; //!< c块参考帧序号
  8. int16_t *mv_c = h->mb.cache.mv[i_list][X264_SCAN8_0 - 8 + 4]; //!< c块的运动矢量
  9. int i_count;
  10. if( i_refc == -2 )
  11. {
  12. i_refc = h->mb.cache.ref[i_list][X264_SCAN8_0 - 8 - 1];
  13. mv_c = h->mb.cache.mv[i_list][X264_SCAN8_0 - 8 - 1];
  14. }
  15. i_count = 0;
  16. if( i_refa == i_ref ) i_count++;
  17. if( i_refb == i_ref ) i_count++;
  18. if( i_refc == i_ref ) i_count++;
  19. if( i_count > 1 )
  20. x264_median_mv( mvp, mv_a, mv_b, mv_c );
  21. else if( i_count == 1 )
  22. {
  23. if( i_refa == i_ref )
  24. *( uint32_t*)mvp = *( uint32_t*)mv_a;
  25. else if( i_refb == i_ref )
  26. *( uint32_t*)mvp = *( uint32_t*)mv_b;
  27. else
  28. *( uint32_t*)mvp = *( uint32_t*)mv_c;
  29. }
  30. else if( i_refb == -2 && i_refc == -2 && i_refa != -2 )
  31. *( uint32_t*)mvp = *( uint32_t*)mv_a;
  32. else
  33. x264_median_mv( mvp, mv_a, mv_b, mv_c );
  34. }


其中,a块,b块,c块分别是当前宏块左、上、右上邻块,结合x264_scan8的赋值及上图不难分析出上述结论。

 

(转载请注明出处。)

转载自:https://blog.csdn.net/hevc_cjl/article/details/8273533

先上代码及注释

  
  
  1. #define X264_SCAN8_SIZE (6*8) //!< 扫描表的尺寸
  2. #define X264_SCAN8_0 (4+1*8) //!< 扫描表第一个扫描序(即亮度的首扫描序)
  3. static const int x264_scan8[ 16+ 2* 4+ 3] =
  4. {
  5. /* Luma */
  6. 4+ 1* 8, 5+ 1* 8, 4+ 2* 8, 5+ 2* 8,
  7. 6+ 1* 8, 7+ 1* 8, 6+ 2* 8, 7+ 2* 8,
  8. 4+ 3* 8, 5+ 3* 8, 4+ 4* 8, 5+ 4* 8,
  9. 6+ 3* 8, 7+ 3* 8, 6+ 4* 8, 7+ 4* 8,
  10. /* Cb */
  11. 1+ 1* 8, 2+ 1* 8,
  12. 1+ 2* 8, 2+ 2* 8,
  13. /* Cr */
  14. 1+ 4* 8, 2+ 4* 8,
  15. 1+ 5* 8, 2+ 5* 8,
  16. /* Luma DC */
  17. 4+ 5* 8,
  18. /* Chroma DC */
  19. 5+ 5* 8, 6+ 5* 8
  20. };
  21. /*
  22. 0 1 2 3 4 5 6 7
  23. 0
  24. 1 B B L L L L
  25. 2 B B L L L L
  26. 3 L L L L
  27. 4 R R L L L L
  28. 5 R R DyDuDv
  29. */ // B – Cb; R – Cr; L – Luma; Dy – Luma DC; Du – Cb DC; Dv – Cr DC

x264_scan8是一个存放着4x4亮度块及色度块扫描序的数组,其内存存储方式如下所示:

其中,每一个小方格代表着一个4x4块,方格中的数字则是对应块的序号。

根据代码中对x264_scan8这个数组的赋值不难得到上图,其中,红色方块代表的是亮度块,绿色块和蓝色块分别代表两个色度块,而三个橙色块则依次代表亮度、两个色度的DC块。

为什么要这么做呢?我们知道,在进行帧内预测,帧间运动矢量预测的时候,需要使用到当前块的left块和top块,在CAVLC编码过程中,也需要知道当前块的left块和top块的non_zero_count,故由上图可以看到,空出来的部分可以用于存储前述所需的left块和top块的相关参数,起到便于访问和节省内存的作用。

看下面这个例子:


  
  
  1. void x264_mb_predict_mv_16x16( x264_t *h, int i_list, int i_ref, int16_t mvp[2] )
  2. {
  3. int i_refa = h->mb.cache.ref[i_list][X264_SCAN8_0 - 1]; //!< a块参考帧序号
  4. int16_t *mv_a = h->mb.cache.mv[i_list][X264_SCAN8_0 - 1]; //!< a块的运动矢量
  5. int i_refb = h->mb.cache.ref[i_list][X264_SCAN8_0 - 8]; //!< b块参考帧序号
  6. int16_t *mv_b = h->mb.cache.mv[i_list][X264_SCAN8_0 - 8]; //!< b块的运动矢量
  7. int i_refc = h->mb.cache.ref[i_list][X264_SCAN8_0 - 8 + 4]; //!< c块参考帧序号
  8. int16_t *mv_c = h->mb.cache.mv[i_list][X264_SCAN8_0 - 8 + 4]; //!< c块的运动矢量
  9. int i_count;
  10. if( i_refc == -2 )
  11. {
  12. i_refc = h->mb.cache.ref[i_list][X264_SCAN8_0 - 8 - 1];
  13. mv_c = h->mb.cache.mv[i_list][X264_SCAN8_0 - 8 - 1];
  14. }
  15. i_count = 0;
  16. if( i_refa == i_ref ) i_count++;
  17. if( i_refb == i_ref ) i_count++;
  18. if( i_refc == i_ref ) i_count++;
  19. if( i_count > 1 )
  20. x264_median_mv( mvp, mv_a, mv_b, mv_c );
  21. else if( i_count == 1 )
  22. {
  23. if( i_refa == i_ref )
  24. *( uint32_t*)mvp = *( uint32_t*)mv_a;
  25. else if( i_refb == i_ref )
  26. *( uint32_t*)mvp = *( uint32_t*)mv_b;
  27. else
  28. *( uint32_t*)mvp = *( uint32_t*)mv_c;
  29. }
  30. else if( i_refb == -2 && i_refc == -2 && i_refa != -2 )
  31. *( uint32_t*)mvp = *( uint32_t*)mv_a;
  32. else
  33. x264_median_mv( mvp, mv_a, mv_b, mv_c );
  34. }


其中,a块,b块,c块分别是当前宏块左、上、右上邻块,结合x264_scan8的赋值及上图不难分析出上述结论。

 

(转载请注明出处。)

转载自:https://blog.csdn.net/hevc_cjl/article/details/8273533

猜你喜欢

转载自blog.csdn.net/baidu_38172402/article/details/81132520