在H.264之前的标准中,比如H.263,其比特流中的数据是按照一个宏块接一个宏块的方式排列的,一旦发生丢包,很多相邻宏块信息都会丢失,很难进行错误隐藏处理。在H.264中加入了一项新特性:把宏块在比特流中的数据按照一定的映射规则进行排列,而不一定按照原本的光栅扫描顺序排列,这种方称为灵活的宏块重拍FMO(Flexible Macroblock Ordering)。

FMO是基于组的方式将宏块集合起来,把一帧内的宏块划分到不同的条带组(slice group)。当然在最后也需要对条带组按光栅扫描顺序划分条带(slice)。在h.264中,当slice group被设为大于1时才使用FMO。在代码端看来,FMO时,主要是对映射表(数组)的设置,如下第一个表:

对一帧进行FMO:

0 1 2 0 1 2 0 1 2 0 1
1 2 0 1 2 0 1 2 0 1 2
0 1 2 0 1 2 0 1 2 0 1
1 2 0 1 2 0 1 2 0 1 2
0 1 2 0 1 2 0 1 2 0 1
1 2 0 1 2 0 1 2 0 1 2
0 1 2 0 1 2 0 1 2 0 1
1 2 0 1 2 0 1 2 0 1 2
0 1 2 0 1 2 0 1 2 0 1

得到slice group有三个:

0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0        
1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1
2 2 2 2 2 2 2 2 2
2 2 2 2 2 2 2 2 2
2 2 2 2 2 2 2 2 2
2 2 2 2          

然后再对每个slice group按照光栅扫描顺序进行排序,分割出slice,下面为分割slice group 0(假设slice长度为16)

slice 1 in slice group 0:

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

slice 2 in slice group 0:

16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31

FMO在h.264中有7种(FMO0 ~ FMO6)

FMO0

FMO0,交织映射。交织映射是指不同的slice group交替出现。

如下设置了slice group 0 = 10,slice group 1 = 15,slice group 2 = 18

0 0 0 0 0 0 0 0 0 0 1
1 1 1 1 1 1 1 1 1 1 1
1 1 1 2 2 2 2 2 2 2 2
2 2 2 2 2 2 2 2 2 2 0
0 0 0 0 0 0 0 0 0 1 1
1 1 1 1 1 1 1 1 1 1 1
1 1 2 2 2 2 2 2 2 2 2
2 2 2 2 2 2 2 2 2 0 0
0 0 0 0 0 0 0 0 1 1 1

JM code如下:

  1. /*!
  2. ************************************************************************
  3. * \brief
  4. * Generate interleaved slice group map type MapUnit map (type 0)
  5. *
  6. * \param img
  7. * Image Parameter to be used for map generation
  8. * \param pps
  9. * Picture Parameter set to be used for map generation
  10. ************************************************************************
  11. */
  12. static void FmoGenerateType0MapUnitMap (ImageParameters * img, pic_parameter_set_rbsp_t * pps )
  13. {
  14. unsigned iGroup, j;
  15. unsigned i = 0;
  16. do
  17. {
  18. for( iGroup = 0;
  19. (iGroup <= pps->num_slice_groups_minus1) && (i < PicSizeInMapUnits);
  20. i += pps->run_length_minus1[iGroup++] + 1)
  21. {
  22. for( j = 0; j <= pps->run_length_minus1[ iGroup ] && i + j < PicSizeInMapUnits; j++ )
  23. MapUnitToSliceGroupMap[i+j] = iGroup;
  24. }
  25. }
  26. while( i < PicSizeInMapUnits );
  27. }

FMO1

FMO1,分散映射。每个宏块相邻的宏块都不在同一组。x方向上的宏块按照slice group序号递增分配,y方向第一个宏块按照0,slice group numbers/2交替分配。

0 1 2 0 1 2 0 1 2 0 1
1 2 0 1 2 0 1 2 0 1 2
0 1 2 0 1 2 0 1 2 0 1
1 2 0 1 2 0 1 2 0 1 2
0 1 2 0 1 2 0 1 2 0 1
1 2 0 1 2 0 1 2 0 1 2
0 1 2 0 1 2 0 1 2 0 1
1 2 0 1 2 0 1 2 0 1 2
0 1 2 0 1 2 0 1 2 0 1

JM code 如下:

  1. /*!
  2. ************************************************************************
  3. * \brief
  4. * Generate dispersed slice group map type MapUnit map (type 1)
  5. *
  6. * \param img
  7. * Image Parameter to be used for map generation
  8. * \param pps
  9. * Picture Parameter set to be used for map generation
  10. ************************************************************************
  11. */
  12. static void FmoGenerateType1MapUnitMap (ImageParameters * img, pic_parameter_set_rbsp_t * pps )
  13. {
  14. unsigned i;
  15. for( i = 0; i < PicSizeInMapUnits; i++ )
  16. {
  17. MapUnitToSliceGroupMap[i] = ((i%img->PicWidthInMbs)+(((i/img->PicWidthInMbs)*(pps->num_slice_groups_minus1+1))/2))
  18. %(pps->num_slice_groups_minus1+1);
  19. }
  20. }

FMO2

FMO2,前后景映射。以整个帧作为背景,该模式可以通过(左上角坐标,右下角坐标)的方式指定前景,每个前景都为一个slice group,最先指定的前景可以覆盖后来指定的前景。

假设有

slice group 0(3,4)(8,8)

slice group 1(1,2)(6,6)

2 2 2 2 2 2 2 2 2 2 2
2 2 2 2 2 2 2 2 2 2 2
2 1 1 1 1 1 1 2 2 2 2
2 1 1 1 1 1 1 2 2 2 2
2 1 1 0 0 0 0 0 0 2 2
2 1 1 0 0 0 0 0 0 2 2
2 1 1 0 0 0 0 0 0 2 2
2 2 2 0 0 0 0 0 0 2 2
2 2 2 0 0 0 0 0 0 2 2

JM code如下:

  1. /*!
  2. ************************************************************************
  3. * \brief
  4. * Generate foreground with left-over slice group map type MapUnit map (type 2)
  5. *
  6. * \param img
  7. * Image Parameter to be used for map generation
  8. * \param pps
  9. * Picture Parameter set to be used for map generation
  10. ************************************************************************
  11. */
  12. static void FmoGenerateType2MapUnitMap (ImageParameters * img, pic_parameter_set_rbsp_t * pps )
  13. {
  14. int iGroup;
  15. unsigned i, x, y;
  16. unsigned yTopLeft, xTopLeft, yBottomRight, xBottomRight;
  17.  
  18. for( i = 0; i < PicSizeInMapUnits; i++ )
  19. MapUnitToSliceGroupMap[ i ] = pps->num_slice_groups_minus1;
  20.  
  21. for( iGroup = pps->num_slice_groups_minus1 - 1 ; iGroup >= 0; iGroup-- )
  22. {
  23. yTopLeft = pps->top_left[ iGroup ] / img->PicWidthInMbs;
  24. xTopLeft = pps->top_left[ iGroup ] % img->PicWidthInMbs;
  25. yBottomRight = pps->bottom_right[ iGroup ] / img->PicWidthInMbs;
  26. xBottomRight = pps->bottom_right[ iGroup ] % img->PicWidthInMbs;
  27. for( y = yTopLeft; y <= yBottomRight; y++ )
  28. for( x = xTopLeft; x <= xBottomRight; x++ )
  29. MapUnitToSliceGroupMap[ y * img->PicWidthInMbs + x ] = iGroup;
  30. }
  31. }

FMO3

FMO3,环形扫描映射。在JM中,环形扫描映射把一帧分为两个slice group,一个是以一帧为背景,另一个是以环作为的前景(其实环可以扩展到更多的group)。环的起点是帧的中心位置,通过指定环的运动方向(顺时针或逆时针)以及环的长度即可得到前景。

以下为顺时针,环长度为32

1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1
1 1 1 20 21 22 23 24 25 1 1
1 1 1 19 6 7 8 9 26 1 1
1 1 1 18 5 0 1 10 27 1 1
1 1 1 17 4 3 2 11 28 1 1
1 1 1 16 15 14 13 12 29 1 1
1 1 1 1 1 1 1 31 30 1 1
1 1 1 1 1 1 1 1 1 1 1

JM code 如下:

  1. /*!
  2. ************************************************************************
  3. * \brief
  4. * Generate box-out slice group map type MapUnit map (type 3)
  5. *
  6. * \param img
  7. * Image Parameter to be used for map generation
  8. * \param pps
  9. * Picture Parameter set to be used for map generation
  10. ************************************************************************
  11. */
  12. static void FmoGenerateType3MapUnitMap (ImageParameters * img, pic_parameter_set_rbsp_t * pps )
  13. {
  14. unsigned i, k;
  15. int leftBound, topBound, rightBound, bottomBound;
  16. int x, y, xDir, yDir;
  17. int mapUnitVacant;
  18.  
  19. unsigned mapUnitsInSliceGroup0 = min((pps->slice_group_change_rate_minus1 + 1) * img->slice_group_change_cycle, PicSizeInMapUnits);
  20.  
  21. for( i = 0; i < PicSizeInMapUnits; i++ )
  22. MapUnitToSliceGroupMap[ i ] = 2;
  23.  
  24. x = ( img->PicWidthInMbs - pps->slice_group_change_direction_flag ) / 2;
  25. y = ( img->PicHeightInMapUnits - pps->slice_group_change_direction_flag ) / 2;
  26.  
  27. leftBound = x;
  28. topBound = y;
  29. rightBound = x;
  30. bottomBound = y;
  31.  
  32. xDir = pps->slice_group_change_direction_flag - 1;
  33. yDir = pps->slice_group_change_direction_flag;
  34.  
  35. for( k = 0; k < PicSizeInMapUnits; k += mapUnitVacant )
  36. {
  37. mapUnitVacant = ( MapUnitToSliceGroupMap[ y * img->PicWidthInMbs + x ] == 2 );
  38. if( mapUnitVacant )
  39. MapUnitToSliceGroupMap[ y * img->PicWidthInMbs + x ] = ( k >= mapUnitsInSliceGroup0 );
  40.  
  41. if( xDir == -1 && x == leftBound )
  42. {
  43. leftBound = max( leftBound - 1, 0 );
  44. x = leftBound;
  45. xDir = 0;
  46. yDir = 2 * pps->slice_group_change_direction_flag - 1;
  47. }
  48. else
  49. if( xDir == 1 && x == rightBound )
  50. {
  51. rightBound = min( rightBound + 1, (int)img->PicWidthInMbs - 1 );
  52. x = rightBound;
  53. xDir = 0;
  54. yDir = 1 - 2 * pps->slice_group_change_direction_flag;
  55. }
  56. else
  57. if( yDir == -1 && y == topBound )
  58. {
  59. topBound = max( topBound - 1, 0 );
  60. y = topBound;
  61. xDir = 1 - 2 * pps->slice_group_change_direction_flag;
  62. yDir = 0;
  63. }
  64. else
  65. if( yDir == 1 && y == bottomBound )
  66. {
  67. bottomBound = min( bottomBound + 1, (int)img->PicHeightInMapUnits - 1 );
  68. y = bottomBound;
  69. xDir = 2 * pps->slice_group_change_direction_flag - 1;
  70. yDir = 0;
  71. }
  72. else
  73. {
  74. x = x + xDir;
  75. y = y + yDir;
  76. }
  77. }
  78.  
  79. }

FMO4

FMO4,光栅扫描映射。该模式只支持两个slice group,按照光栅扫描顺序来分组,方向有正向与反向之分。

如下为反向FMO4(始于右下角):

1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0

JM code 如下:

  1. /*!
  2. ************************************************************************
  3. * \brief
  4. * Generate raster scan slice group map type MapUnit map (type 4)
  5. *
  6. * \param img
  7. * Image Parameter to be used for map generation
  8. * \param pps
  9. * Picture Parameter set to be used for map generation
  10. ************************************************************************
  11. */
  12. static void FmoGenerateType4MapUnitMap (ImageParameters * img, pic_parameter_set_rbsp_t * pps )
  13. {
  14.  
  15. unsigned mapUnitsInSliceGroup0 = min((pps->slice_group_change_rate_minus1 + 1) * img->slice_group_change_cycle, PicSizeInMapUnits);
  16. unsigned sizeOfUpperLeftGroup = pps->slice_group_change_direction_flag ? ( PicSizeInMapUnits - mapUnitsInSliceGroup0 ) : mapUnitsInSliceGroup0;
  17.  
  18. unsigned i;
  19.  
  20. for( i = 0; i < PicSizeInMapUnits; i++ )
  21. if( i < sizeOfUpperLeftGroup )
  22. MapUnitToSliceGroupMap[ i ] = pps->slice_group_change_direction_flag;
  23. else
  24. MapUnitToSliceGroupMap[ i ] = 1 - pps->slice_group_change_direction_flag;
  25.  
  26. }

FMO5

FMO5,擦式扫描映射。仅支持两个slice group,扫描方式为纵向,也有正反两个方向

如下为正向FMO5(始于左上角):

0 0 0 1 1 1 1 1 1 1 1
0 0 0 1 1 1 1 1 1 1 1
0 0 1 1 1 1 1 1 1 1 1
0 0 1 1 1 1 1 1 1 1 1
0 0 1 1 1 1 1 1 1 1 1
0 0 1 1 1 1 1 1 1 1 1
0 0 1 1 1 1 1 1 1 1 1
0 0 1 1 1 1 1 1 1 1 1
0 0 1 1 1 1 1 1 1 1 1

JM code 如下:

  1. /*!
  2. ************************************************************************
  3. * \brief
  4. * Generate wipe slice group map type MapUnit map (type 5)
  5. *
  6. * \param img
  7. * Image Parameter to be used for map generation
  8. * \param pps
  9. * Picture Parameter set to be used for map generation
  10. ************************************************************************
  11. */
  12. static void FmoGenerateType5MapUnitMap (ImageParameters * img, pic_parameter_set_rbsp_t * pps )
  13. {
  14.  
  15. unsigned mapUnitsInSliceGroup0 = min((pps->slice_group_change_rate_minus1 + 1) * img->slice_group_change_cycle, PicSizeInMapUnits);
  16. unsigned sizeOfUpperLeftGroup = pps->slice_group_change_direction_flag ? ( PicSizeInMapUnits - mapUnitsInSliceGroup0 ) : mapUnitsInSliceGroup0;
  17.  
  18. unsigned i,j, k = 0;
  19.  
  20. for( j = 0; j < img->PicWidthInMbs; j++ )
  21. for( i = 0; i < img->PicHeightInMapUnits; i++ )
  22. if( k++ < sizeOfUpperLeftGroup )
  23. MapUnitToSliceGroupMap[ i * img->PicWidthInMbs + j ] = 1 - pps->slice_group_change_direction_flag;
  24. else
  25. MapUnitToSliceGroupMap[ i * img->PicWidthInMbs + j ] = pps->slice_group_change_direction_flag;
  26.  
  27. }

FMO6

FMO6,显示控制映射。可以在配置文件中自由地指定每个宏块所属的slice group。

0 1 0 2 1 1 0 2 1 1 1
1 2 0 0 0 1 0 2 0 1 0
3 5 4 1 0 0 3 5 4 0 1
0 0 5 5 3 1 0 2 5 0 1
4 1 0 0 1 1 1 1 4 4 2
0 2 2 3 2 3 2 1 5 2 3
0 1 2 0 1 1 2 0 5 5 5
3 2 1 4 1 4 4 0 3 3 2
4 2 3 5 0 0 1 4 1 2 3

顺带一提JM支持一帧中最多为8个slice group

JM code 如下:

  1. /*!
  2. ************************************************************************
  3. * \brief
  4. * Generate explicit slice group map type MapUnit map (type 6)
  5. *
  6. * \param img
  7. * Image Parameter to be used for map generation
  8. * \param pps
  9. * Picture Parameter set to be used for map generation
  10. ************************************************************************
  11. */
  12. static void FmoGenerateType6MapUnitMap (ImageParameters * img, pic_parameter_set_rbsp_t * pps )
  13. {
  14. unsigned i;
  15. for (i=0; i<PicSizeInMapUnits; i++)
  16. {
  17. MapUnitToSliceGroupMap[i] = pps->slice_group_id[i];
  18. }
  19. }

h.264 FMO的更多相关文章

  1. h.264语法结构分析

    NAL Unit Stream Network Abstraction Layer,简称NAL. h.264把原始的yuv文件编码成码流文件,生成的码流文件就是NAL单元流(NAL unit Stre ...

  2. H.264视频的RTP荷载格式

    Status of This Memo This document specifies an Internet standards track protocol for the   Internet ...

  3. FFmpeg的H.264解码器源代码简单分析:熵解码(Entropy Decoding)部分

    ===================================================== H.264源代码分析文章列表: [编码 - x264] x264源代码简单分析:概述 x26 ...

  4. FFmpeg的H.264解码器源代码简单分析:解析器(Parser)部分

    ===================================================== H.264源代码分析文章列表: [编码 - x264] x264源代码简单分析:概述 x26 ...

  5. 6. H.264/AVC编码器原理

    1. H.264/AVC的应用 H.264 不仅具有优异的压缩性能,而且具有良好的网络亲和性,这对实时的视频通信是十分重要的.和 MPEG-4 中的重点是灵活性不同,H.264 着重在压缩的高效率和传 ...

  6. H.264 Profile

    提到High Profile H.264解码许多人并不了解,那么到底什么是High Profile H.264解码?其应用效果又是如何呢?  作为行业标准,H.264编码体系定义了4种不同的Profi ...

  7. (转载)H.264码流的RTP封包说明

    H.264的NALU,RTP封包说明(转自牛人) 2010-06-30 16:28 H.264 RTP payload 格式 H.264 视频 RTP 负载格式 1. 网络抽象层单元类型 (NALU) ...

  8. H.264的优势和主要特点

    H.264,同时也是MPEG-4第十部分,是由ITU-T视频编码专家组(VCEG)和ISO/IEC动态图像专家组(MPEG)联合组成的联合视频组(JVT,Joint Video Team)提出的高度压 ...

  9. Android IOS WebRTC 音视频开发总结(七九)-- WebRTC选择H.264的四大理由

    本文主要介绍WebRTC选择H.264的理由(我们翻译和整理的,译者:weizhenwei,校验:blacker),最早发表在[编风网] 支持原创,转载必须注明出处,欢迎关注我的微信公众号blacke ...

随机推荐

  1. [转]Android实现计时与倒计时(限时抢购)的几种方法

    在购物网站的促销活动中一般都有倒计时限制购物时间或者折扣的时间,这些都是如何实现的呢? 在一个安卓客户端项目中恰好遇到了类似的问题,一开始使用的是Timer与 TimerTask, 虽然此方法通用,但 ...

  2. 基于MyBatis的数据库切分框架,可实现数据的水平切分和垂直切分。 http://www.makersoft.org

    https://github.com/makersoft/mybatis-shards MyBatis-Shards 专业的MyBatis数据库切分框架 MyBatis Shards简介 MyBati ...

  3. Java基础知识强化之集合框架笔记09:Collection集合迭代器使用的问题探讨

    1.Collection集合迭代器使用的问题探讨: (1)问题1:能用while循环写这个程序,我能不能用for循环呢?                  可以使用for循环替代. (2)问题2:不要 ...

  4. Android(java)学习笔记248:ContentProvider使用之虚拟短信

    1.虚拟短信应用场景:   急着脱身?应付老婆(老公.男女朋友查岗)?   使用虚拟通话短信吧.您只需通过简单设置,软件就会在指定时间会模拟一个“真实”来电或短信来迷惑对方,通过“真实”的证据让对方相 ...

  5. Centos6.3 配置yum 163源

    1. 下载repo文件    下载地址:http://mirrors.163.com/.help/CentOS6-Base-163.repo 2. 备份并替换系统的repo文件[root@localh ...

  6. Python 代码实现模糊查询

    Python 代码实现模糊查询 1.导语: 模糊匹配可以算是现代编辑器(如 Eclipse 等各种 IDE)的一个必备特性了,它所做的就是根据用户输入的部分内容,猜测用户想要的文件名,并提供一个推荐列 ...

  7. PID38 串的记数(codevs2077)

    /* 假设当前有a个A b个B c个C 用 f[a][b][c]来表示 那么如果这个串以A结尾 那就是 f[a-1][b][c]转移来的 所以构成 f[a][b][c]的串一定有一部分是 f[a-1] ...

  8. IDisposable 接口2

    定义一种释放分配的资源的方法. 命名空间:  System程序集:  mscorlib(在 mscorlib.dll 中) 语法 C# C++ F# VB [ComVisibleAttribute(t ...

  9. mac 查找当前目录下所有同一类型文件,并执行命令行

    以TexturePacker举例 MAC下用TexturePacker命令行打包当前目录下所有的 *.tps文件 1.配置好tps文件需要配置好路径.参数等.(也可不配置,用命令行实现.具体参考:ht ...

  10. Linux 网络配置(固定IP)

    通常linux作为服务器系统时,是不推荐安装图形界面的,因此我们需要掌握非图形界面下如何配置网络,主要两种方式,如下: 一.使用SETUP工具(redhat系列才可以,推荐此修改方式) 1.在命令行直 ...