h.264 FMO
在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 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | /*! ?************************************************************************ ?* \brief ?*??? Generate interleaved slice group map type MapUnit map (type 0) ?* ?* \param img ?*??? Image Parameter to be used for map generation ?* \param pps ?*??? Picture Parameter set to be used for map generation ?************************************************************************ ?*/ static?void?FmoGenerateType0MapUnitMap (ImageParameters * img, pic_parameter_set_rbsp_t * pps ) { ??unsigned iGroup, j; ??unsigned i = 0; ??do ??{ ????for( iGroup = 0; ????(iGroup <= pps->num_slice_groups_minus1) && (i < PicSizeInMapUnits); ????i += pps->run_length_minus1[iGroup++] + 1) ????{ ??????for( j = 0; j <= pps->run_length_minus1[ iGroup ] && i + j < PicSizeInMapUnits; j++ ) ????????MapUnitToSliceGroupMap[i+j] = iGroup; ????} ??} ??while( i < PicSizeInMapUnits ); } |
?
?
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 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | /*! ?************************************************************************ ?* \brief ?*??? Generate dispersed slice group map type MapUnit map (type 1) ?* ?* \param img ?*??? Image Parameter to be used for map generation ?* \param pps ?*??? Picture Parameter set to be used for map generation ?************************************************************************ ?*/ static?void?FmoGenerateType1MapUnitMap (ImageParameters * img, pic_parameter_set_rbsp_t * pps ) { ??unsigned i; ??for( i = 0; i < PicSizeInMapUnits; i++ ) ??{ ????MapUnitToSliceGroupMap[i] = ((i%img->PicWidthInMbs)+(((i/img->PicWidthInMbs)*(pps->num_slice_groups_minus1+1))/2)) ??????%(pps->num_slice_groups_minus1+1); ??} } |
?
?
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 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | /*! ?************************************************************************ ?* \brief ?*??? Generate foreground with left-over slice group map type MapUnit map (type 2) ?* ?* \param img ?*??? Image Parameter to be used for map generation ?* \param pps ?*??? Picture Parameter set to be used for map generation ?************************************************************************ ?*/ static?void?FmoGenerateType2MapUnitMap (ImageParameters * img, pic_parameter_set_rbsp_t * pps ) { ??int?iGroup; ??unsigned i, x, y; ??unsigned yTopLeft, xTopLeft, yBottomRight, xBottomRight; ??? ??for( i = 0; i < PicSizeInMapUnits; i++ ) ????MapUnitToSliceGroupMap[ i ] = pps->num_slice_groups_minus1; ??? ??for( iGroup = pps->num_slice_groups_minus1 - 1 ; iGroup >= 0; iGroup-- ) ??{ ????yTopLeft = pps->top_left[ iGroup ] / img->PicWidthInMbs; ????xTopLeft = pps->top_left[ iGroup ] % img->PicWidthInMbs; ????yBottomRight = pps->bottom_right[ iGroup ] / img->PicWidthInMbs; ????xBottomRight = pps->bottom_right[ iGroup ] % img->PicWidthInMbs; ????for( y = yTopLeft; y <= yBottomRight; y++ ) ??????for( x = xTopLeft; x <= xBottomRight; x++ ) ????????MapUnitToSliceGroupMap[ y * img->PicWidthInMbs + x ] = iGroup; ??} } |
?
?
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 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | /*! ?************************************************************************ ?* \brief ?*??? Generate box-out slice group map type MapUnit map (type 3) ?* ?* \param img ?*??? Image Parameter to be used for map generation ?* \param pps ?*??? Picture Parameter set to be used for map generation ?************************************************************************ ?*/ static?void?FmoGenerateType3MapUnitMap (ImageParameters * img, pic_parameter_set_rbsp_t * pps ) { ??unsigned i, k; ??int?leftBound, topBound, rightBound, bottomBound; ??int?x, y, xDir, yDir; ??int?mapUnitVacant; ??? ??unsigned mapUnitsInSliceGroup0 = min((pps->slice_group_change_rate_minus1 + 1) * img->slice_group_change_cycle, PicSizeInMapUnits); ??? ??for( i = 0; i < PicSizeInMapUnits; i++ ) ????MapUnitToSliceGroupMap[ i ] = 2; ??? ??x = ( img->PicWidthInMbs - pps->slice_group_change_direction_flag ) / 2; ??y = ( img->PicHeightInMapUnits - pps->slice_group_change_direction_flag ) / 2; ??? ??leftBound?? = x; ??topBound??? = y; ??rightBound? = x; ??bottomBound = y; ??? ??xDir =? pps->slice_group_change_direction_flag - 1; ??yDir =? pps->slice_group_change_direction_flag; ??? ??for( k = 0; k < PicSizeInMapUnits; k += mapUnitVacant ) ??{ ????mapUnitVacant = ( MapUnitToSliceGroupMap[ y * img->PicWidthInMbs + x ]? ==? 2 ); ????if( mapUnitVacant ) ??????MapUnitToSliceGroupMap[ y * img->PicWidthInMbs + x ] = ( k >= mapUnitsInSliceGroup0 ); ????? ????if( xDir? ==? -1? &&? x? ==? leftBound ) ????{ ??????leftBound = max( leftBound - 1, 0 ); ??????x = leftBound; ??????xDir = 0; ??????yDir = 2 * pps->slice_group_change_direction_flag - 1; ????} ????else ??????if( xDir? ==? 1? &&? x? ==? rightBound ) ??????{ ????????rightBound = min( rightBound + 1, (int)img->PicWidthInMbs - 1 ); ????????x = rightBound; ????????xDir = 0; ????????yDir = 1 - 2 * pps->slice_group_change_direction_flag; ??????} ??????else ????????if( yDir? ==? -1? &&? y? ==? topBound ) ????????{ ??????????topBound = max( topBound - 1, 0 ); ??????????y = topBound; ??????????xDir = 1 - 2 * pps->slice_group_change_direction_flag; ??????????yDir = 0; ????????} ????????else ??????????if( yDir? ==? 1? &&? y? ==? bottomBound ) ??????????{ ????????????bottomBound = min( bottomBound + 1, (int)img->PicHeightInMapUnits - 1 ); ????????????y = bottomBound; ????????????xDir = 2 * pps->slice_group_change_direction_flag - 1; ????????????yDir = 0; ??????????} ??????????else ??????????{ ????????????x = x + xDir; ????????????y = y + yDir; ??????????} ??} ??? } |
?
?
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 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | /*! ?************************************************************************ ?* \brief ?*??? Generate raster scan slice group map type MapUnit map (type 4) ?* ?* \param img ?*??? Image Parameter to be used for map generation ?* \param pps ?*??? Picture Parameter set to be used for map generation ?************************************************************************ ?*/ static?void?FmoGenerateType4MapUnitMap (ImageParameters * img, pic_parameter_set_rbsp_t * pps ) { ??? ??unsigned mapUnitsInSliceGroup0 = min((pps->slice_group_change_rate_minus1 + 1) * img->slice_group_change_cycle, PicSizeInMapUnits); ??unsigned sizeOfUpperLeftGroup = pps->slice_group_change_direction_flag ? ( PicSizeInMapUnits - mapUnitsInSliceGroup0 ) : mapUnitsInSliceGroup0; ??? ??unsigned i; ??? ??for( i = 0; i < PicSizeInMapUnits; i++ ) ????if( i < sizeOfUpperLeftGroup ) ??????MapUnitToSliceGroupMap[ i ] = pps->slice_group_change_direction_flag; ????else ??????MapUnitToSliceGroupMap[ i ] = 1 - pps->slice_group_change_direction_flag; ????? } |
?
?
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 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | /*! ?************************************************************************ ?* \brief ?*??? Generate wipe slice group map type MapUnit map (type 5) ?* ?* \param img ?*??? Image Parameter to be used for map generation ?* \param pps ?*??? Picture Parameter set to be used for map generation ?************************************************************************ */ static?void?FmoGenerateType5MapUnitMap (ImageParameters * img, pic_parameter_set_rbsp_t * pps ) { ??? ??unsigned mapUnitsInSliceGroup0 = min((pps->slice_group_change_rate_minus1 + 1) * img->slice_group_change_cycle, PicSizeInMapUnits); ??unsigned sizeOfUpperLeftGroup = pps->slice_group_change_direction_flag ? ( PicSizeInMapUnits - mapUnitsInSliceGroup0 ) : mapUnitsInSliceGroup0; ??? ??unsigned i,j, k = 0; ??? ??for( j = 0; j < img->PicWidthInMbs; j++ ) ????for( i = 0; i < img->PicHeightInMapUnits; i++ ) ??????if( k++ < sizeOfUpperLeftGroup ) ????????MapUnitToSliceGroupMap[ i * img->PicWidthInMbs + j ] = 1 - pps->slice_group_change_direction_flag; ??????else ????????MapUnitToSliceGroupMap[ i * img->PicWidthInMbs + j ] = pps->slice_group_change_direction_flag; ??????? } |
?
?
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 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | /*! ?************************************************************************ ?* \brief ?*??? Generate explicit slice group map type MapUnit map (type 6) ?* ?* \param img ?*??? Image Parameter to be used for map generation ?* \param pps ?*??? Picture Parameter set to be used for map generation ?************************************************************************ ?*/ static?void?FmoGenerateType6MapUnitMap (ImageParameters * img, pic_parameter_set_rbsp_t * pps ) { ??unsigned i; ??for?(i=0; i<PicSizeInMapUnits; i++) ??{ ????MapUnitToSliceGroupMap[i] = pps->slice_group_id[i]; ??} }
|
轉載于:https://www.cnblogs.com/xumaojun/p/8523516.html
總結
- 上一篇: 外国影片这部叫啥
- 下一篇: jmeter实现多并发