gpt4 book ai didi

colors - QOMX_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka 颜色格式

转载 作者:行者123 更新时间:2023-12-04 17:25:51 26 4
gpt4 key购买 nike

全部

有谁知道详情 QOMX_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka 格式,这是qcom 7x30 h/w解码器的输出格式,数据是如何以这种颜色格式存储的?谢谢

最佳答案

这是我对此的研究,关于 QOMX_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka 转换为 YUV420Planar (I420) .至于 QOMX_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka格式方面,可以引用($your_android_native_sdk_dir)/WORKING_DIRECTORY/hardware/qcom/media/mm-core/inc/QOMX_IVCommonExtensions.h源代码。这个函数可能理想地支持通用分辨率,但是我只测试 CIF 大小,因为给定的源输入不可用。当然,您可以将其他大小的数据伪造为给定的输入。如果您正在处理此问题,希望对您有所帮助。
根据我的 CIF 测试,我看到颜色是正确的。代码很长,大约有 390 行,很重。包括步骤:构造yTileToMb、uvTileToMb,然后按如下转换y和u/v。

///////////////////////////////////////////////////////////////////////
/**
* Enumeration defining the extended uncompressed image/video
* formats.
*
* ENUMS:
* YVU420PackedSemiPlanar : Buffer containing all Y, and then V and U
* interleaved.
* YVU420PackedSemiPlanar32m4ka : YUV planar format, similar to the
* YVU420PackedSemiPlanar format, but with the
* following restrictions:
*
* 1. The width and height of both plane must
* be a multiple of 32 texels.
*
* 2. The base address of both planes must be
* aligned to a 4kB boundary.
*
* YUV420PackedSemiPlanar16m2ka : YUV planar format, similar to the
* YUV420PackedSemiPlanar format, but with the
* following restrictions:
*
* 1. The width of the luma plane must be a
* multiple of 16 pixels.
*
* 2. The address of both planes must be
* aligned to a 2kB boundary.
*
* YUV420PackedSemiPlanar64x32Tile2m8ka : YUV planar format, similar to the
* YUV420PackedSemiPlanar format, but with the
* following restrictions:
*
* 1. The data is laid out in a 4x2 MB tiling
* memory structure
*
* 2. The width of each plane is a multiple of
* 2 4x2 MB tiles.
*
* 3. The height of each plan is a multiple of
* a 4x2 MB tile.
*
* 4. The base address of both planes must be
* aligned to an 8kB boundary.
*
* 5. The tiles are scanned in the order
* defined in the MFCV5.1 User's Manual.
*
* i.e, CIF size in pysical location
*
* Luma order(4x2 MB = 64x32 pix): 54 tiles:
* 0 1 6 7 8 9
* 2 3 4 5 10 11
* 12 13 18 19 20 21
* 14 15 16 17 22 23
* 24 25 30 31 32 33
* 26 27 28 29 34 35
* 36 37 42 43 44 45
* 38 39 40 41 46 47
* 48 49 50 51 52 53
* MBs in a y tile:
* 0 1 2 3
* 22 23 24 25
* Chromas order(64x32 pix):
* 0 1 6 7 8 9
* 2 3 4 5 10 11
* 12 13 18 19 20 21
* 14 15 16 17 22 23
* 24 25 26 27 28 29
* MBs in a uv tile:
* 0 1 2 3
* 22 23 24 25
* 44 45 46 47
* 66 67 68 69
*
*/

// YUV420PackedSemiPlanar64x32Tile2m8ka, // 12 bit, yyyyyyyy vuvu
// YUV420Planar, 12 bit, yyyyyyyy uu vv
#pragma pack(1)
typedef enum {
Scan_Init = 0,
Scan_Hor,
Scan_VerDown,
Scan_VerUp
} ScanMode;
typedef struct{
uint16_t startMbIndex;
uint8_t numMBs;
// bool lastTileInHor;
bool lastTileInVer;
} MbGroup;
#pragma pack()

#define ALIGN_B(x,a) (((x)+(a)-1) &(~((a)-1)))
#define MAX_RESOLUTION_X 1920 // 4096
#define MAX_RESOLUTION_Y 1088 // 3072
#define MAX_TILES_NUM (((MAX_RESOLUTION_X+63)>>6) * ((MAX_RESOLUTION_Y+31)>>5))

int32_t ToI420::YUV420PackedSemiPlanar64x32Tile2m8kaToYUV420Planar( uint8_t* src, uint8_t* dst_y, uint8_t* dst_u, uint8_t* dst_v,
const int32_t width, const int32_t height,
const int32_t stride_y, const int32_t stride_u, const int32_t stride_v )
{
const int32_t srcStrideY = ALIGN_B( width, 128 );
const int32_t srcHeightY = ALIGN_B( height, 32 );
const int32_t srcStrideUV = srcStrideY; // v/u interlaced
const int32_t srcHeightUV = ALIGN_B( (height>>1), 32 );
const int32_t srcSizeY = ALIGN_B( (srcStrideY * srcHeightY), 8192 );
const int32_t srcSizeUV = ALIGN_B( (srcStrideUV * srcHeightUV), 8192 );
uint8_t* src_y = src;
uint8_t* src_uv = src_y + srcSizeY;

const int32_t wTiles = (width+63)>>6;
const int32_t hTilesY = (height+31)>>5;
const int32_t hTilesUV = (height/2+31)>>5;
const int32_t numTilesY = wTiles*hTilesY;
const int32_t numTilesUV = wTiles*hTilesUV;
const int32_t wMacroblocks = (width+15)>>4;
const int32_t hMacroblocks = (height+15)>>4;
int32_t numMbInTile = 4*2; // y: 4*2; uv: 4*4
const int32_t mbOffsetTileHor = 4;
int32_t mbOffsetTileVer = (wMacroblocks<<1); // y: (wMacroblocks<<1); uv: (wMacroblocks<<2)
MbGroup yTileToMb[MAX_TILES_NUM] = {0}; // each Tile index storing according MB index
MbGroup uvTileToMb[MAX_TILES_NUM] = {0}; // each Tile index storing according MB index
assert( numTilesY <= MAX_TILES_NUM && numTilesUV <= MAX_TILES_NUM );
int32_t availableTilesY = numTilesY;
int32_t availableTilesUV = numTilesUV;
const int32_t numTilesYPerScanUnit = (wTiles<<1);
int32_t tileIndex = 0;
ScanMode preMode = Scan_Init;
ScanMode curMode = Scan_Hor;
int32_t scanedTiles = 0;
int32_t hMbMultiple = 0;
int32_t cntScanTimesInPeriod = 0; // maximal scan times is up to 4
int32_t cnt1stLineTiles = 0;
int32_t cnt2ndLineTiles = 0;
uint16_t mbPosition = 0;
uint16_t lastMbIdx = mbPosition;
uint16_t firstMbIdxUnit = mbPosition;
bool noEnoughMbInTile = false;

// construct yTileToMb table
while( availableTilesY > 0 ){
if ( availableTilesY >= numTilesYPerScanUnit ){
preMode = Scan_Init;
curMode = Scan_Hor;
lastMbIdx = mbPosition;
firstMbIdxUnit = mbPosition;
cntScanTimesInPeriod = 0; // maximal scan times is up to 4
cnt1stLineTiles = 0;
cnt2ndLineTiles = 0;
noEnoughMbInTile = false;
scanedTiles = 0;

while ( scanedTiles < numTilesYPerScanUnit ){
if ( (tileIndex & 3) == 0 ){
firstMbIdxUnit = mbPosition;
}
noEnoughMbInTile = false;
if ( curMode == Scan_Hor ){
if ( (preMode == Scan_VerUp && cnt1stLineTiles+1>= wTiles) ||
(preMode == Scan_VerDown && cnt2ndLineTiles+1>= wTiles) ){
noEnoughMbInTile = (ALIGN_B(width, 16) < srcStrideY);
// yTileToMb[tileIndex].lastTileInHor = true;
}
yTileToMb[tileIndex].startMbIndex = mbPosition;
yTileToMb[tileIndex].numMBs = noEnoughMbInTile ? ((4-((srcStrideY-ALIGN_B(width,16))>>4))<<1) : numMbInTile;
++ tileIndex;
++ cntScanTimesInPeriod;
if ( noEnoughMbInTile && cntScanTimesInPeriod == 1){
if ( preMode == Scan_VerDown ){
preMode = curMode; // scan mode change need upate preMode
curMode = Scan_VerUp;
++ cnt2ndLineTiles;
mbPosition = firstMbIdxUnit - mbOffsetTileVer;
}else if ( preMode == Scan_VerUp ){
preMode = curMode; // scan mode change need upate preMode
curMode = Scan_VerDown;
++ cnt1stLineTiles;
mbPosition = firstMbIdxUnit + mbOffsetTileVer;
}
}else if ( cntScanTimesInPeriod == 2 ){
if ( preMode == Scan_Init || preMode == Scan_VerUp ){
preMode = curMode; // scan mode change need upate preMode
curMode = Scan_VerDown;
++ cnt1stLineTiles;
mbPosition = firstMbIdxUnit + mbOffsetTileVer;
}else if ( preMode == Scan_VerDown ){
preMode = curMode; // scan mode change need upate preMode
curMode = Scan_VerUp;
++ cnt2ndLineTiles;
mbPosition = firstMbIdxUnit - mbOffsetTileVer;
}
}else if ( cntScanTimesInPeriod == 4 ){
if ( preMode == Scan_VerDown ){
++ cnt2ndLineTiles;
mbPosition += mbOffsetTileHor;
}else if ( preMode == Scan_VerUp ){
++ cnt1stLineTiles;
mbPosition += mbOffsetTileHor;
}
}else{
if ( preMode == Scan_Init ){
++ cnt1stLineTiles;
}else if ( preMode == Scan_VerDown ){
++ cnt2ndLineTiles;
}else if ( preMode == Scan_VerUp ){
++ cnt1stLineTiles;
}
if ( cnt2ndLineTiles >= wTiles && preMode == Scan_VerDown ){
preMode = curMode; // scan mode change need upate preMode
curMode = Scan_VerUp;
mbPosition = firstMbIdxUnit - mbOffsetTileVer;
}else if ( cnt1stLineTiles >= wTiles && preMode == Scan_VerUp ){
preMode = curMode; // scan mode change need upate preMode
curMode = Scan_VerDown;
mbPosition = firstMbIdxUnit + mbOffsetTileVer;
}else{
mbPosition += mbOffsetTileHor;
}
}
}else if ( curMode == Scan_VerUp ){
if ( cnt1stLineTiles+1 >= wTiles ){
noEnoughMbInTile = (ALIGN_B(width, 16) < srcStrideY);
// yTileToMb[tileIndex].lastTileInHor = true;
}
yTileToMb[tileIndex].startMbIndex= mbPosition;
yTileToMb[tileIndex].numMBs = noEnoughMbInTile ? ((4-((srcStrideY-ALIGN_B(width,16))>>4))<<1) : numMbInTile;
++ tileIndex;
mbPosition += mbOffsetTileHor;
++ cntScanTimesInPeriod;
++ cnt1stLineTiles;
preMode = curMode; // scan mode change need upate preMode
curMode = Scan_Hor;
}else if ( curMode == Scan_VerDown ){
if ( cnt2ndLineTiles+1 >= wTiles ){
noEnoughMbInTile = (ALIGN_B(width, 16) < srcStrideY);
// yTileToMb[tileIndex].lastTileInHor = true;
}
yTileToMb[tileIndex].startMbIndex= mbPosition;
yTileToMb[tileIndex].numMBs = noEnoughMbInTile ? ((4-((srcStrideY-ALIGN_B(width,16))>>4))<<1) : numMbInTile;
++ tileIndex;
mbPosition += mbOffsetTileHor;
++ cntScanTimesInPeriod;
++ cnt2ndLineTiles;
preMode = curMode; // scan mode change need upate preMode
curMode = Scan_Hor;
}
cntScanTimesInPeriod &= 0x03;
++ scanedTiles;
}
mbPosition = lastMbIdx + (mbOffsetTileVer<<1);
availableTilesY -= numTilesYPerScanUnit;
}else{
scanedTiles = 0;
hMbMultiple = hMacroblocks - (tileIndex/wTiles)*2;
noEnoughMbInTile = false;
while ( scanedTiles < wTiles ){
yTileToMb[tileIndex].startMbIndex = mbPosition;
yTileToMb[tileIndex].lastTileInVer= true;
if ( scanedTiles+1 == wTiles ){
noEnoughMbInTile = (ALIGN_B(width, 16) < srcStrideY);
// yTileToMb[tileIndex].lastTileInHor = true;
}
yTileToMb[tileIndex].numMBs = noEnoughMbInTile ? ((4-((srcStrideY-ALIGN_B(width,16))>>4))*hMbMultiple) : (4*hMbMultiple);
++ tileIndex;
mbPosition += mbOffsetTileHor;
++ scanedTiles;
}
availableTilesY -= wTiles;
}
}

numMbInTile = 4*4;
mbOffsetTileVer = (wMacroblocks<<2);
mbPosition = 0;
tileIndex = 0;
// construct uvTileToMb table
while( availableTilesUV > 0 ){
if ( availableTilesUV >= numTilesYPerScanUnit ){
preMode = Scan_Init;
curMode = Scan_Hor;
lastMbIdx = mbPosition;
firstMbIdxUnit = mbPosition;
cntScanTimesInPeriod= 0; // maximal scan times is up to 4
cnt1stLineTiles = 0;
cnt2ndLineTiles = 0;
noEnoughMbInTile = false;
scanedTiles = 0;

while ( scanedTiles < numTilesYPerScanUnit ){
if ( (tileIndex & 3) == 0 ){
firstMbIdxUnit = mbPosition;
}
noEnoughMbInTile = false;
if ( curMode == Scan_Hor ){
if ( (preMode == Scan_VerUp && cnt1stLineTiles+1>= wTiles) ||
(preMode == Scan_VerDown && cnt2ndLineTiles+1>= wTiles) ){
noEnoughMbInTile = (ALIGN_B(width, 16) < srcStrideY);
// uvTileToMb[tileIndex].lastTileInHor = true;
}
uvTileToMb[tileIndex].startMbIndex = mbPosition;
uvTileToMb[tileIndex].numMBs = noEnoughMbInTile ? ((4-((srcStrideY-ALIGN_B(width,16))>>4))<<2) : numMbInTile;
++ tileIndex;
++ cntScanTimesInPeriod;
if ( noEnoughMbInTile && cntScanTimesInPeriod == 1){
if ( preMode == Scan_VerDown ){
preMode = curMode; // scan mode change need upate preMode
curMode = Scan_VerUp;
++ cnt2ndLineTiles;
mbPosition = firstMbIdxUnit - mbOffsetTileVer;
}else if ( preMode == Scan_VerUp ){
preMode = curMode; // scan mode change need upate preMode
curMode = Scan_VerDown;
++ cnt1stLineTiles;
mbPosition = firstMbIdxUnit + mbOffsetTileVer;
}
}else if ( cntScanTimesInPeriod == 2 ){
if ( preMode == Scan_Init || preMode == Scan_VerUp ){
preMode = curMode; // scan mode change need upate preMode
curMode = Scan_VerDown;
++ cnt1stLineTiles;
mbPosition = firstMbIdxUnit + mbOffsetTileVer;
}else if ( preMode == Scan_VerDown ){
preMode = curMode; // scan mode change need upate preMode
curMode = Scan_VerUp;
++ cnt2ndLineTiles;
mbPosition = firstMbIdxUnit - mbOffsetTileVer;
}
}else if ( cntScanTimesInPeriod == 4 ){
if ( preMode == Scan_VerDown ){
++ cnt2ndLineTiles;
mbPosition += mbOffsetTileHor;
}else if ( preMode == Scan_VerUp ){
++ cnt1stLineTiles;
mbPosition += mbOffsetTileHor;
}
}else{
if ( preMode == Scan_Init ){
++ cnt1stLineTiles;
}else if ( preMode == Scan_VerDown ){
++ cnt2ndLineTiles;
}else if ( preMode == Scan_VerUp ){
++ cnt1stLineTiles;
}
if ( cnt2ndLineTiles >= wTiles && preMode == Scan_VerDown ){
preMode = curMode; // scan mode change need upate preMode
curMode = Scan_VerUp;
mbPosition = firstMbIdxUnit - mbOffsetTileVer;
}else if ( cnt1stLineTiles >= wTiles && preMode == Scan_VerUp ){
preMode = curMode; // scan mode change need upate preMode
curMode = Scan_VerDown;
mbPosition = firstMbIdxUnit + mbOffsetTileVer;
}else{
mbPosition += mbOffsetTileHor;
}
}
}else if ( curMode == Scan_VerUp ){
if ( cnt1stLineTiles+1 >= wTiles ){
noEnoughMbInTile = (ALIGN_B(width, 16) < srcStrideY);
// uvTileToMb[tileIndex].lastTileInHor = true;
}
uvTileToMb[tileIndex].startMbIndex = mbPosition;
uvTileToMb[tileIndex].numMBs = noEnoughMbInTile ? ((4-((srcStrideY-ALIGN_B(width,16))>>4))<<2) : numMbInTile;
++ tileIndex;
mbPosition += mbOffsetTileHor;
++ cntScanTimesInPeriod;
++ cnt1stLineTiles;
preMode = curMode; // scan mode change need upate preMode
curMode = Scan_Hor;
}else if ( curMode == Scan_VerDown ){
if ( cnt2ndLineTiles+1 >= wTiles ){
noEnoughMbInTile = (ALIGN_B(width, 16) < srcStrideY);
// uvTileToMb[tileIndex].lastTileInHor = true;
}
uvTileToMb[tileIndex].startMbIndex = mbPosition;
uvTileToMb[tileIndex].numMBs = noEnoughMbInTile ? ((4-((srcStrideY-ALIGN_B(width,16))>>4))<<2) : numMbInTile;
++ tileIndex;
mbPosition += mbOffsetTileHor;
++ cntScanTimesInPeriod;
++ cnt2ndLineTiles;
preMode = curMode; // scan mode change need upate preMode
curMode = Scan_Hor;
}
cntScanTimesInPeriod &= 0x03;
++ scanedTiles;
}
mbPosition = lastMbIdx + (mbOffsetTileVer<<1);
availableTilesUV -= numTilesYPerScanUnit;
}else{
scanedTiles = 0;
hMbMultiple = hMacroblocks - (tileIndex/wTiles)*4;
noEnoughMbInTile = false;
while ( scanedTiles < wTiles ){
uvTileToMb[tileIndex].startMbIndex = mbPosition;
uvTileToMb[tileIndex].lastTileInVer = true;
if ( scanedTiles+1 == wTiles ){
noEnoughMbInTile = (ALIGN_B(width, 16) < srcStrideY);
// uvTileToMb[tileIndex].lastTileInHor = true;
}
uvTileToMb[tileIndex].numMBs = noEnoughMbInTile ? ((4-((srcStrideY-ALIGN_B(width,16))>>4))*hMbMultiple) : (4*hMbMultiple);
++ tileIndex;
mbPosition += mbOffsetTileHor;
++ scanedTiles;
}
availableTilesUV -= wTiles;
}
}

uint8_t* py = src_y;
tileIndex = 0;
// converting luma componet with yTileToMb
while ( tileIndex < numTilesY ){
uint16_t startMbIndex = yTileToMb[tileIndex].startMbIndex;
const int32_t startMbX = (startMbIndex % wMacroblocks);
const int32_t startMbY = (startMbIndex / wMacroblocks);

int32_t mb_x = startMbX;
int32_t mb_y = startMbY;
const int32_t cntMbLines = yTileToMb[tileIndex].lastTileInVer ? (hMacroblocks - (tileIndex/wTiles)*2) : 2;
const int32_t numMbPerLine = yTileToMb[tileIndex].numMBs / cntMbLines;
const int32_t sizePixelLine = (numMbPerLine << 4);
int32_t mbLine = 0;
while ( mbLine < cntMbLines ){
assert( mb_y < hMacroblocks && mb_x < wMacroblocks );
const int32_t dstOffsetY = (mb_y * stride_y + mb_x)<<4;
int32_t _l = 0;
// luma
while( _l < 16 ){
memcpy( dst_y + dstOffsetY + _l * stride_y, py, sizePixelLine );
py += 64; // eliminate padding (64-sizePixelLine)
++ _l;
}
mb_x = startMbX;
++ mb_y;
++ mbLine;
}
++ tileIndex;
}

uint8_t* puv = src_uv;
tileIndex = 0;
// convering cb/cr componets with uvTileToMb
while ( tileIndex < numTilesUV ){
uint16_t startMbIndex = uvTileToMb[tileIndex].startMbIndex;
const int32_t startMbX = (startMbIndex % wMacroblocks);
const int32_t startMbY = (startMbIndex / wMacroblocks);

int32_t mb_x = startMbX;
int32_t mb_y = startMbY;
const int32_t cntMbLines = uvTileToMb[tileIndex].lastTileInVer ? (hMacroblocks - (tileIndex/wTiles)*4) : 4;
const int32_t numMbPerLine = uvTileToMb[tileIndex].numMBs / cntMbLines;
int32_t mbLine = 0;
while ( mbLine < cntMbLines ){
assert( mb_y < hMacroblocks && mb_x < wMacroblocks );
// cb/cr
int32_t mbIndex = 0;
while ( mbIndex < numMbPerLine ){
assert( mb_y < hMacroblocks && mb_x < wMacroblocks );
const int32_t dstOffsetUV = (mb_y * stride_u + mb_x)<<3;
int32_t _l = 0;
while( _l < 8 ){
const int32_t _offset = dstOffsetUV + _l * stride_u;
uint8_t* _u = dst_u + _offset;
uint8_t* _v = dst_v + _offset;
uint8_t* _src_vu = puv+(mbIndex<<4)+(_l<<6);
int32_t _interlace = 0;
for ( int32_t ichroma = 0; ichroma < 8; ++ichroma ){
_u[ichroma] = _src_vu[_interlace++];
_v[ichroma] = _src_vu[_interlace++];
}
++ _l;
}
++ mb_x;
++ mbIndex;
}
puv += 64*8;
mb_x = startMbX;
++ mb_y;
++ mbLine;
}
if ( cntMbLines < 4 ){
puv += 64*(4-cntMbLines)*8;
}
++ tileIndex;
}

return 0;
}

///////////////////////////////////////////////////////////////////////

关于colors - QOMX_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka 颜色格式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10059738/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com