yuv convert demo
以前测试hisi解码器数据时候写的demo
1 #include <string.h> 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <sys/types.h> 5 #include <sys/stat.h> 6 #include <fcntl.h> 7 8 #define ERR_OK 0 9 #define ERR_FAIL 1 10 #define ERR_INVAL_PARAM 2 11 #define ERR_MEMORY 3 12 13 #define ALIGN_DOWN(data, align) (data & ~(align - 1)) 14 #define ALIGN_UP(data, align) ALIGN_DOWN((data + (align - 1)), align) 15 #define DEFAULT_ALIGN 16 16 17 #define MAX_WIDTH 3840 18 #define MAX_HEIGHT 2160 19 #define MAX_STRIDE ALIGN_UP(MAX_WIDTH, DEFAULT_ALIGN) 20 #define MAX_FILE_LEN 128 21 22 #if 1 23 #define DBG(Err, fmt, args...) do { \ 24 printf("==================== %s[%u] ret = 0x%08x\n" \ 25 "%s" fmt "\n", __func__, __LINE__, Err, \ 26 (ERR_OK == Err) ? "msg: " : "error: ", ##args);} while (0); 27 #else 28 #define DBG(...) 29 #endif 30 31 #define BIT(off) (1 << off) 32 #define TST(data, off) (data & BIT(off)) 33 34 #define BIT_UV_ORDER 0 35 #define BIT_PLANE 1 36 #define BIT_YUV422 2 37 38 typedef enum tagPixelFormat 39 { 40 PF_DEFAULT = 0, 41 PF_NV12 = PF_DEFAULT, 42 PF_NV21, 43 PF_YU12, 44 PF_YV12, 45 PF_420_BUTT, 46 PF_NV16 = PF_420_BUTT, 47 PF_NV61, 48 PF_YUYV, 49 PF_YVYU, 50 PF_422_BUTT, 51 PF_BUTT = PF_422_BUTT 52 } PIXEL_FORMAT_E; 53 54 typedef enum tagDataFormat 55 { 56 DF_LINER = 0, 57 DF_TILE, 58 DF_BUTT 59 } DATA_FORMAT_E; 60 61 typedef struct tagDataInfo 62 { 63 PIXEL_FORMAT_E enInPixelFormat; 64 PIXEL_FORMAT_E enOutPixelFormat; 65 DATA_FORMAT_E enDataFormat; 66 unsigned int uiWidth; 67 unsigned int uiHeight; 68 unsigned int uiStride; 69 unsigned char astSrcFile[MAX_FILE_LEN]; 70 unsigned char astDstFile[MAX_FILE_LEN]; 71 } CMD_INFO_S; 72 73 typedef struct tagPicBufInfo 74 { 75 int Handle; 76 PIXEL_FORMAT_E enPixelFormat; 77 unsigned char *pucData; 78 unsigned int uiLen; 79 } PIC_BUF_INFO_S; 80 81 static char gaststring[PF_BUTT][8] = 82 { 83 "NV12", 84 "NV21", 85 "YU12", 86 "YV12", 87 88 "NV16", 89 "NV61", 90 "YUYV", 91 "YVYU", 92 }; 93 94 static CMD_INFO_S *g_pstDataInfo = NULL; 95 static PIC_BUF_INFO_S stSrcPic; 96 static PIC_BUF_INFO_S stDstPic; 97 98 static void usage(void) 99 { 100 int i; 101 102 printf("yuv format convert tool used to convert yuv format\n"); 103 printf("only support yuv420p yuv420sp yuv422p yuv422sp for now\n"); 104 printf("2012.12.5 add tile / liner convert to support hixxxx decoder data\n"); 105 printf("================================================================\n"); 106 printf("usage: ./yuv_convert src=[file] dst=[file] I [type] O [type] F [format] W [width] H [height] S [stride]\n\n"); 107 108 for (i = 0; i < PF_BUTT; i++) 109 { 110 if (0 == i) 111 { 112 printf("[type]: %u for %s\n", i, gaststring[i]); 113 } 114 else 115 { 116 printf(" %u for %s\n", i, gaststring[i]); 117 } 118 } 119 120 printf("\n[format]: 0 for liner and 1 for tile(256 pixel * 16 lines)\n"); 121 printf("TODO: add more format\n\n"); 122 } 123 124 static int prase_args(int argc, char **argv) 125 { 126 int i = 0; 127 char **pcStr = argv; 128 129 g_pstDataInfo = malloc(sizeof(CMD_INFO_S)); 130 if (NULL == g_pstDataInfo) 131 { 132 DBG(ERR_MEMORY, "malloc CMD_INFO_S failed\n"); 133 return ERR_MEMORY; 134 } 135 136 memset((void *)g_pstDataInfo, 0, sizeof(CMD_INFO_S)); 137 g_pstDataInfo->enInPixelFormat = PF_BUTT; 138 g_pstDataInfo->enOutPixelFormat = PF_BUTT; 139 140 if (0 == argc) 141 { 142 usage(); 143 return ERR_FAIL; 144 } 145 146 for (i = 0; i < argc; i++) 147 { 148 if (strncasecmp(pcStr[i], "-h", 2) == 0) 149 { 150 usage(); 151 return ERR_FAIL; 152 } 153 else if (strncasecmp(pcStr[i], "--help", 6) == 0) 154 { 155 usage(); 156 return ERR_FAIL; 157 } 158 else if (strncasecmp(pcStr[i], "src=", 4) == 0) 159 { 160 memcpy(g_pstDataInfo->astSrcFile, (pcStr[i] + 4), (strlen(pcStr[i]) - 4)); 161 } 162 else if (strncasecmp(pcStr[i], "dst=", 4) == 0) 163 { 164 memcpy(g_pstDataInfo->astDstFile, (pcStr[i] + 4), (strlen(pcStr[i]) - 4)); 165 } 166 else if (strncasecmp(pcStr[i], "I", 1) == 0) 167 { 168 i++; 169 if (i< argc) 170 { 171 g_pstDataInfo->enInPixelFormat = strtoul(pcStr[i], NULL, 10); 172 if (g_pstDataInfo->enInPixelFormat >= PF_DEFAULT && 173 g_pstDataInfo->enInPixelFormat< PF_BUTT) 174 { 175 continue; 176 } 177 } 178 179 goto ERR; 180 } 181 else if (strncasecmp(pcStr[i], "O", 1) == 0) 182 { 183 i++; 184 if (i< argc) 185 { 186 g_pstDataInfo->enOutPixelFormat = strtoul(pcStr[i], NULL, 10); 187 if (g_pstDataInfo->enOutPixelFormat >= PF_DEFAULT && 188 g_pstDataInfo->enOutPixelFormat< PF_BUTT) 189 { 190 continue; 191 } 192 } 193 194 goto ERR; 195 } 196 else if (strncasecmp(pcStr[i], "F", 1) == 0) 197 { 198 i++; 199 if (i< argc) 200 { 201 g_pstDataInfo->enDataFormat = strtoul(pcStr[i], NULL, 10); 202 if (g_pstDataInfo->enDataFormat >= DF_LINER&& 203 g_pstDataInfo->enDataFormat< DF_BUTT) 204 { 205 continue; 206 } 207 } 208 209 goto ERR; 210 } 211 else if (strncasecmp(pcStr[i], "W", 1) == 0) 212 { 213 i++; 214 if (i< argc) 215 { 216 g_pstDataInfo->uiWidth = strtoul(pcStr[i], NULL, 10); 217 if (g_pstDataInfo->uiWidth > 0 && 218 g_pstDataInfo->uiWidth< = MAX_WIDTH) 219 { 220 continue; 221 } 222 } 223 224 goto ERR; 225 } 226 else if (strncasecmp(pcStr[i], "H", 1) == 0) 227 { 228 i++; 229 if (i< argc) 230 { 231 g_pstDataInfo->uiHeight = strtoul(pcStr[i], NULL, 10); 232 if (g_pstDataInfo->uiHeight > 0 && 233 g_pstDataInfo->uiHeight< = MAX_HEIGHT) 234 { 235 continue; 236 } 237 } 238 239 goto ERR; 240 } 241 else if (strncasecmp(pcStr[i], "S", 1) == 0) 242 { 243 i++; 244 if (i< argc) 245 { 246 g_pstDataInfo->uiStride = strtoul(pcStr[i], NULL, 10); 247 if (g_pstDataInfo->uiStride > 0 && 248 g_pstDataInfo->uiStride< = MAX_STRIDE) 249 { 250 continue; 251 } 252 } 253 254 goto ERR; 255 } 256 } 257 258 //adjust param 259 if ( (g_pstDataInfo->enInPixelFormat >= PF_BUTT) || 260 (0 == g_pstDataInfo->astSrcFile[0]) || 261 (0 == g_pstDataInfo->uiWidth) || 262 (0 == g_pstDataInfo->uiHeight) ) 263 { 264 DBG(ERR_INVAL_PARAM, "uncomplete init param need file %s format %u width %u height %u\n", \ 265 g_pstDataInfo->astSrcFile, g_pstDataInfo->enInPixelFormat, \ 266 g_pstDataInfo->uiWidth, g_pstDataInfo->uiHeight); 267 return ERR_INVAL_PARAM; 268 } 269 270 if (PF_BUTT == g_pstDataInfo->enOutPixelFormat) 271 { 272 g_pstDataInfo->enOutPixelFormat = PF_NV12; 273 } 274 275 if (0 == g_pstDataInfo->uiStride) 276 { 277 g_pstDataInfo->uiStride = ALIGN_UP(g_pstDataInfo->uiWidth, DEFAULT_ALIGN); 278 } 279 280 if (0 == g_pstDataInfo->astDstFile[0]) 281 { 282 sprintf(g_pstDataInfo->astDstFile, "default_out_" "%u" "x" "%u" "_" "%s" ".yuv", \ 283 g_pstDataInfo->uiStride, g_pstDataInfo->uiHeight, \ 284 gaststring[g_pstDataInfo->enOutPixelFormat]); 285 } 286 287 return ERR_OK; 288 289 ERR: 290 DBG(ERR_INVAL_PARAM, "wrong format at param %u\n", i); 291 return ERR_INVAL_PARAM; 292 } 293 294 //ugly: in order to compatible hixxxx cpu 295 static int tile2liner(void) 296 { 297 unsigned char *pucTmpBuf = NULL; 298 unsigned char *pucSrc = NULL; 299 unsigned char *pucDst = NULL; 300 int i = 0, j = 0, k = 0; 301 unsigned int uiBlockLen = 0, uiBlockCnt = 0, uiBlockOneLine = 0; 302 303 if ( (DF_TILE == g_pstDataInfo->enDataFormat) && 304 ((PF_NV12 == g_pstDataInfo->enInPixelFormat) || (PF_NV21 == g_pstDataInfo->enInPixelFormat)) ) 305 306 { 307 DBG(ERR_OK, "get src data with tile format need convert to liner\n"); 308 309 pucTmpBuf = malloc(stSrcPic.uiLen); 310 if (NULL == pucTmpBuf) 311 { 312 DBG(ERR_MEMORY, "malloc temp buf %u fail\n", stSrcPic.uiLen); 313 } 314 315 memset(pucTmpBuf, 0, stSrcPic.uiLen); 316 317 uiBlockLen = (256 * 16) * 3 / 2; 318 uiBlockCnt = stSrcPic.uiLen / uiBlockLen; 319 uiBlockOneLine = g_pstDataInfo->uiStride / 256; 320 321 pucSrc = stSrcPic.pucData; 322 for (i = 0; i < uiBlockCnt; i++) 323 { 324 pucDst = pucTmpBuf + (i % uiBlockOneLine) * 256 + (i / uiBlockOneLine) * g_pstDataInfo->uiStride * 16; 325 326 for (j = 0; j < 16; j++) 327 { 328 memcpy(pucDst, pucSrc, 256); 329 pucSrc += 256; 330 pucDst += g_pstDataInfo->uiStride; 331 } 332 333 } 334 335 //fixme: during debugging fisheye i find out that Y / UV data from hixxxx decoder is not constant 336 //bewteen Y and UV contains stride * n lines useless data while leak same length data at end of file 337 //here just ignore it as a result the correct data has green slice at the top of picture 338 unsigned int uiBlockOffset = 0; 339 int iOffLine = 0; 340 if (2560 == g_pstDataInfo->uiWidth && 1440 == g_pstDataInfo->uiHeight) 341 { 342 iOffLine = 64; 343 } 344 else if (1280 == g_pstDataInfo->uiWidth&& 720 == g_pstDataInfo->uiHeight) 345 { 346 iOffLine = 96; 347 } 348 349 pucSrc += g_pstDataInfo->uiStride * iOffLine / 2; 350 uiBlockOffset = g_pstDataInfo->uiStride / 256 * iOffLine / 16; 351 352 for (i = 0; i < uiBlockCnt - uiBlockOffset; i++) 353 { 354 pucDst = pucTmpBuf + g_pstDataInfo->uiStride * g_pstDataInfo->uiHeight + (i % uiBlockOneLine) * 256 + (i / uiBlockOneLine) * g_pstDataInfo->uiStride * 8; 355 for (j = 0; j < 8; j++) 356 { 357 memcpy(pucDst, pucSrc, 256); 358 pucSrc += 256; 359 pucDst += g_pstDataInfo->uiStride; 360 } 361 } 362 363 memcpy(stSrcPic.pucData, pucTmpBuf, stSrcPic.uiLen); 364 free(pucTmpBuf); 365 pucTmpBuf = NULL; 366 } 367 368 return ERR_OK; 369 370 unsigned int uiSwitchFlag = g_pstDataInfo->enInPixelFormat ^ g_pstDataInfo->enOutPixelFormat; 371 unsigned int uiLenY = 0; 372 unsigned int uiLenC = 0; 373 unsigned int uiCopyOneLine = 0; 374 unsigned int uiCopyLines = 0; 375 unsigned char *pucData = NULL; 376 unsigned char *pucSrcTmp; 377 unsigned char *pucDstTmp; 378 int i, j; 379 380 uiLenY = g_pstDataInfo->uiStride * g_pstDataInfo->uiHeight; 381 uiLenC = ((g_pstDataInfo->enInPixelFormat < PF_420_BUTT) ? 1 : 2) * uiLenY / 2; 382 383 if (0 == uiSwitchFlag) 384 { 385 DBG(ERR_OK, "same format data no need convert\n"); 386 memcpy(stDstPic.pucData, stSrcPic.pucData, (uiLenY + uiLenC)); 387 return ERR_OK; 388 } 389 390 pucData = malloc((uiLenY * 3)); // extend memory for YUV444 391 if (NULL == pucData) 392 { 393 DBG(ERR_MEMORY, "malloc memory %u fail\n", (uiLenY + uiLenC)); 394 return ERR_MEMORY; 395 } 396 397 if (TST(uiSwitchFlag, BIT_UV_ORDER)) 398 { 399 DBG(ERR_OK, "detect in %u out %u need reverse UV\n", \ 400 g_pstDataInfo->enInPixelFormat, g_pstDataInfo->enOutPixelFormat); 401 402 pucSrcTmp = stSrcPic.pucData + uiLenY; 403 pucDstTmp = pucData; 404 if (TST(uiSwitchFlag, BIT_PLANE)) 405 { 406 memcpy(pucDstTmp, pucSrcTmp, (uiLenC / 2)); 407 memcpy(pucSrcTmp, (pucSrcTmp + uiLenC / 2), (uiLenC / 2)); 408 memcpy((pucSrcTmp + uiLenC / 2), pucDstTmp, (uiLenC / 2)); 409 } 410 else 411 { 412 for (i = 0; i < uiLenC; i += 2) 413 { 414 pucDstTmp[0] = pucSrcTmp[i]; 415 pucSrcTmp[i] = pucSrcTmp[i + 1]; 416 pucSrcTmp[i + 1] = pucDstTmp[0]; 417 } 418 } 419 } 420 421 if (TST(uiSwitchFlag, BIT_PLANE)) 422 { 423 DBG(ERR_OK, "detect in %u out %u need convert plane\n", \ 424 g_pstDataInfo->enInPixelFormat, g_pstDataInfo->enOutPixelFormat); 425 426 pucSrcTmp = stSrcPic.pucData + uiLenY; 427 pucDstTmp = pucData; 428 if (TST(g_pstDataInfo->enInPixelFormat, BIT_PLANE)) 429 { 430 for (i = 0, j = 0; i < uiLenC; i += 2, j++) 431 { 432 pucDstTmp[i] = pucSrcTmp[j]; 433 pucDstTmp[i + 1] = pucSrcTmp[uiLenC / 2 + j]; 434 } 435 } 436 else 437 { 438 for (i = 0, j = 0; i < uiLenC; i += 2, j++) 439 { 440 pucDstTmp[j] = pucSrcTmp[i]; 441 pucDstTmp[uiLenC / 2 + j] = pucSrcTmp[i + 1]; 442 } 443 } 444 445 memcpy(pucSrcTmp, pucData, uiLenC); 446 } 447 448 if (TST(uiSwitchFlag, BIT_YUV422)) 449 { 450 DBG(ERR_OK, "detect in %u out %u need convert YUV\n", \ 451 g_pstDataInfo->enInPixelFormat, g_pstDataInfo->enOutPixelFormat); 452 453 pucSrcTmp = stSrcPic.pucData + uiLenY; 454 pucDstTmp = pucData; 455 if (TST(g_pstDataInfo->enInPixelFormat, BIT_YUV422)) 456 { 457 if (TST(g_pstDataInfo->enOutPixelFormat, BIT_PLANE)) 458 { 459 uiCopyOneLine = g_pstDataInfo->uiStride / 2; 460 uiCopyLines = g_pstDataInfo->uiHeight; 461 } 462 else 463 { 464 uiCopyOneLine = g_pstDataInfo->uiStride; 465 uiCopyLines = g_pstDataInfo->uiHeight / 2; 466 } 467 468 for (i = 0; i < uiCopyLines; i++) 469 { 470 memcpy(pucDstTmp, pucSrcTmp, uiCopyOneLine); 471 pucDstTmp += uiCopyOneLine; 472 pucSrcTmp += uiCopyOneLine * 2; 473 } 474 475 memcpy(stDstPic.pucData, stSrcPic.pucData, uiLenY); 476 memcpy((stDstPic.pucData + uiLenY), pucData, (uiLenC / 2)); 477 } 478 else 479 { 480 if (TST(g_pstDataInfo->enOutPixelFormat, BIT_PLANE)) 481 { 482 uiCopyOneLine = g_pstDataInfo->uiStride / 2; 483 uiCopyLines = g_pstDataInfo->uiHeight; 484 } 485 else 486 { 487 uiCopyOneLine = g_pstDataInfo->uiStride; 488 uiCopyLines = g_pstDataInfo->uiHeight / 2; 489 } 490 491 for (i = 0; i < uiCopyLines; i++) 492 { 493 memcpy(pucDstTmp, pucSrcTmp, uiCopyOneLine); 494 memcpy((pucDstTmp + uiCopyOneLine), pucSrcTmp, uiCopyOneLine); 495 pucDstTmp += uiCopyOneLine * 2; 496 pucSrcTmp += uiCopyOneLine; 497 } 498 499 printf("aaaaaaaaaaa\n"); 500 501 memcpy(stDstPic.pucData, stSrcPic.pucData, uiLenY); 502 memcpy((stDstPic.pucData + uiLenY), pucData, (uiLenC * 2)); 503 } 504 } 505 else 506 { 507 memcpy(stDstPic.pucData, stSrcPic.pucData, (uiLenY + uiLenC)); 508 } 509 510 free(pucData); 511 pucData = NULL; 512 return ERR_OK; 513 } 514 515 int main(int argc, char *argv[]) 516 { 517 int uiReadLen = 0; 518 int iRet = prase_args((argc - 1), &argv[1]); 519 520 if (ERR_OK != iRet) 521 { 522 goto ERR0; 523 } 524 525 DBG(ERR_OK, "get in type %u out type %u data format %u " \ 526 "width %u height %u stride %u src file %s dst file %s\n", \ 527 g_pstDataInfo->enInPixelFormat, g_pstDataInfo->enOutPixelFormat, \ 528 g_pstDataInfo->enDataFormat, g_pstDataInfo->uiWidth, \ 529 g_pstDataInfo->uiHeight, g_pstDataInfo->uiStride, \ 530 g_pstDataInfo->astSrcFile, g_pstDataInfo->astDstFile); 531 532 #if 0 533 return 0; 534 #endif 535 536 stSrcPic.Handle = open(g_pstDataInfo->astSrcFile, O_RDONLY, 0555); 537 if (stSrcPic.Handle <= 0) 538 { 539 DBG(ERR_FAIL, "open src yuv %s fail\n", g_pstDataInfo->astSrcFile); 540 goto ERR1; 541 } 542 543 stSrcPic.enPixelFormat = g_pstDataInfo->enInPixelFormat; 544 if (stSrcPic.enPixelFormat < PF_420_BUTT) 545 { 546 stSrcPic.uiLen = g_pstDataInfo->uiStride * g_pstDataInfo->uiHeight * 3 / 2; 547 } 548 else if (stSrcPic.enPixelFormat < PF_422_BUTT) 549 { 550 stSrcPic.uiLen = g_pstDataInfo->uiStride * g_pstDataInfo->uiHeight * 2; 551 } 552 else 553 { 554 DBG(ERR_INVAL_PARAM, "unsupport pixel format %u\n", stSrcPic.enPixelFormat); 555 goto ERR2; 556 } 557 558 stSrcPic.pucData = malloc(stSrcPic.uiLen); 559 if (NULL ==stSrcPic.pucData) 560 { 561 DBG(ERR_MEMORY, "malloc picture buf %u fail\n", stSrcPic.uiLen); 562 goto ERR2; 563 } 564 565 uiReadLen = read(stSrcPic.Handle, stSrcPic.pucData, stSrcPic.uiLen); 566 if (uiReadLen != stSrcPic.uiLen) 567 { 568 DBG(ERR_FAIL, "read len %u request %u\n", uiReadLen, stSrcPic.uiLen); 569 goto ERR3; 570 } 571 572 stDstPic.Handle = open(g_pstDataInfo->astDstFile, O_RDWR | O_CREAT, 0755); 573 if (stDstPic.Handle <= 0) 574 { 575 DBG(ERR_FAIL, "open dst yuv %s fail\n", g_pstDataInfo->astDstFile); 576 goto ERR3; 577 } 578 579 stDstPic.enPixelFormat = g_pstDataInfo->enOutPixelFormat; 580 if (stDstPic.enPixelFormat < PF_420_BUTT) 581 { 582 stDstPic.uiLen = g_pstDataInfo->uiStride * g_pstDataInfo->uiHeight * 3 / 2; 583 } 584 else if (stDstPic.enPixelFormat < PF_422_BUTT) 585 { 586 stDstPic.uiLen = g_pstDataInfo->uiStride * g_pstDataInfo->uiHeight * 2; 587 } 588 else 589 { 590 DBG(ERR_INVAL_PARAM, "unsupport pixel format %u\n", stDstPic.enPixelFormat); 591 goto ERR4; 592 } 593 594 stDstPic.pucData = malloc(stDstPic.uiLen); 595 if (NULL ==stDstPic.pucData) 596 { 597 DBG(ERR_MEMORY, "malloc picture buf %u fail\n", stDstPic.uiLen); 598 goto ERR4; 599 } 600 601 DBG(ERR_OK, "check variable complete start convert\n"); 602 603 #if 1 604 iRet = tile2liner(); 605 if (ERR_OK != iRet) 606 { 607 goto ERR5; 608 } 609 610 DBG(ERR_OK, "convert tile 2 liner ok\n"); 611 #endif 612 613 iRet = yuv_convert(); 614 if (ERR_OK != iRet) 615 { 616 goto ERR5; 617 } 618 619 write(stDstPic.Handle, stDstPic.pucData, stDstPic.uiLen); 620 621 DBG(ERR_OK, "convert complete src type %u dst type %u\n", \ 622 g_pstDataInfo->enInPixelFormat, g_pstDataInfo->enOutPixelFormat); 623 624 ERR5: 625 free(stDstPic.pucData); 626 stDstPic.pucData = NULL; 627 ERR4: 628 close(stDstPic.Handle); 629 stDstPic.Handle = -1; 630 ERR3: 631 free(stSrcPic.pucData); 632 stSrcPic.pucData = NULL; 633 ERR2: 634 close(stSrcPic.Handle); 635 stSrcPic.Handle = -1; 636 ERR1: 637 free(g_pstDataInfo); 638 g_pstDataInfo = NULL; 639 ERR0: 640 return -iRet;