Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(75)

Side by Side Diff: src/codec/SkJpegCodec.cpp

Issue 1716523002: Update Skia's YUV API (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Tweak the API to use arrays and named indices Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright 2015 Google Inc. 2 * Copyright 2015 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "SkCodec.h" 8 #include "SkCodec.h"
9 #include "SkMSAN.h" 9 #include "SkMSAN.h"
10 #include "SkJpegCodec.h" 10 #include "SkJpegCodec.h"
(...skipping 517 matching lines...) Expand 10 before | Expand all | Expand 10 after
528 int hSampY = dinfo->comp_info[0].h_samp_factor; 528 int hSampY = dinfo->comp_info[0].h_samp_factor;
529 int vSampY = dinfo->comp_info[0].v_samp_factor; 529 int vSampY = dinfo->comp_info[0].v_samp_factor;
530 return (1 == hSampY && 1 == vSampY) || 530 return (1 == hSampY && 1 == vSampY) ||
531 (2 == hSampY && 1 == vSampY) || 531 (2 == hSampY && 1 == vSampY) ||
532 (2 == hSampY && 2 == vSampY) || 532 (2 == hSampY && 2 == vSampY) ||
533 (1 == hSampY && 2 == vSampY) || 533 (1 == hSampY && 2 == vSampY) ||
534 (4 == hSampY && 1 == vSampY) || 534 (4 == hSampY && 1 == vSampY) ||
535 (4 == hSampY && 2 == vSampY); 535 (4 == hSampY && 2 == vSampY);
536 } 536 }
537 537
538 bool SkJpegCodec::onQueryYUV8(YUVSizeInfo* sizeInfo, SkYUVColorSpace* colorSpace ) const { 538 bool SkJpegCodec::onQueryYUV8(SkYUVSizeInfo* sizeInfo, SkYUVColorSpace* colorSpa ce) const {
539 jpeg_decompress_struct* dinfo = fDecoderMgr->dinfo(); 539 jpeg_decompress_struct* dinfo = fDecoderMgr->dinfo();
540 if (!is_yuv_supported(dinfo)) { 540 if (!is_yuv_supported(dinfo)) {
541 return false; 541 return false;
542 } 542 }
543 543
544 sizeInfo->fYSize.set(dinfo->comp_info[0].downsampled_width, 544 sizeInfo->fSizes[SkYUVSizeInfo::kY].set(dinfo->comp_info[0].downsampled_widt h,
545 dinfo->comp_info[0].downsampled_height); 545 dinfo->comp_info[0].downsampled_heigh t);
546 sizeInfo->fUSize.set(dinfo->comp_info[1].downsampled_width, 546 sizeInfo->fSizes[SkYUVSizeInfo::kU].set(dinfo->comp_info[1].downsampled_widt h,
547 dinfo->comp_info[1].downsampled_height); 547 dinfo->comp_info[1].downsampled_heigh t);
548 sizeInfo->fVSize.set(dinfo->comp_info[2].downsampled_width, 548 sizeInfo->fSizes[SkYUVSizeInfo::kV].set(dinfo->comp_info[2].downsampled_widt h,
549 dinfo->comp_info[2].downsampled_height); 549 dinfo->comp_info[2].downsampled_heigh t);
550 sizeInfo->fYWidthBytes = dinfo->comp_info[0].width_in_blocks * DCTSIZE; 550 sizeInfo->fWidthBytes[SkYUVSizeInfo::kY] = dinfo->comp_info[0].width_in_bloc ks * DCTSIZE;
551 sizeInfo->fUWidthBytes = dinfo->comp_info[1].width_in_blocks * DCTSIZE; 551 sizeInfo->fWidthBytes[SkYUVSizeInfo::kU] = dinfo->comp_info[1].width_in_bloc ks * DCTSIZE;
552 sizeInfo->fVWidthBytes = dinfo->comp_info[2].width_in_blocks * DCTSIZE; 552 sizeInfo->fWidthBytes[SkYUVSizeInfo::kV] = dinfo->comp_info[2].width_in_bloc ks * DCTSIZE;
553 553
554 if (colorSpace) { 554 if (colorSpace) {
555 *colorSpace = kJPEG_SkYUVColorSpace; 555 *colorSpace = kJPEG_SkYUVColorSpace;
556 } 556 }
557 557
558 return true; 558 return true;
559 } 559 }
560 560
561 SkCodec::Result SkJpegCodec::onGetYUV8Planes(const YUVSizeInfo& sizeInfo, void* pixels[3]) { 561 SkCodec::Result SkJpegCodec::onGetYUV8Planes(const SkYUVSizeInfo& sizeInfo,
562 YUVSizeInfo defaultInfo; 562 void* pixels[SkYUVSizeInfo::kPlaneCount]) {
563 SkYUVSizeInfo defaultInfo;
563 564
564 // This will check is_yuv_supported(), so we don't need to here. 565 // This will check is_yuv_supported(), so we don't need to here.
565 bool supportsYUV = this->onQueryYUV8(&defaultInfo, nullptr); 566 bool supportsYUV = this->onQueryYUV8(&defaultInfo, nullptr);
566 if (!supportsYUV || sizeInfo.fYSize != defaultInfo.fYSize || 567 if (!supportsYUV ||
567 sizeInfo.fUSize != defaultInfo.fUSize || 568 sizeInfo.fSizes[SkYUVSizeInfo::kY] != defaultInfo.fSizes[SkYUVSizeIn fo::kY] ||
568 sizeInfo.fVSize != defaultInfo.fVSize || 569 sizeInfo.fSizes[SkYUVSizeInfo::kU] != defaultInfo.fSizes[SkYUVSizeIn fo::kU] ||
569 sizeInfo.fYWidthBytes < defaultInfo.fYWidthBytes || 570 sizeInfo.fSizes[SkYUVSizeInfo::kV] != defaultInfo.fSizes[SkYUVSizeIn fo::kV] ||
570 sizeInfo.fUWidthBytes < defaultInfo.fUWidthBytes || 571 sizeInfo.fWidthBytes[SkYUVSizeInfo::kY] < defaultInfo.fWidthBytes[Sk YUVSizeInfo::kY] ||
571 sizeInfo.fVWidthBytes < defaultInfo.fVWidthBytes) { 572 sizeInfo.fWidthBytes[SkYUVSizeInfo::kU] < defaultInfo.fWidthBytes[Sk YUVSizeInfo::kU] ||
573 sizeInfo.fWidthBytes[SkYUVSizeInfo::kV] < defaultInfo.fWidthBytes[Sk YUVSizeInfo::kV]) {
572 return fDecoderMgr->returnFailure("onGetYUV8Planes", kInvalidInput); 574 return fDecoderMgr->returnFailure("onGetYUV8Planes", kInvalidInput);
573 } 575 }
574 576
575 // Set the jump location for libjpeg errors 577 // Set the jump location for libjpeg errors
576 if (setjmp(fDecoderMgr->getJmpBuf())) { 578 if (setjmp(fDecoderMgr->getJmpBuf())) {
577 return fDecoderMgr->returnFailure("setjmp", kInvalidInput); 579 return fDecoderMgr->returnFailure("setjmp", kInvalidInput);
578 } 580 }
579 581
580 // Get a pointer to the decompress info since we will use it quite frequentl y 582 // Get a pointer to the decompress info since we will use it quite frequentl y
581 jpeg_decompress_struct* dinfo = fDecoderMgr->dinfo(); 583 jpeg_decompress_struct* dinfo = fDecoderMgr->dinfo();
582 584
583 dinfo->raw_data_out = TRUE; 585 dinfo->raw_data_out = TRUE;
584 if (!jpeg_start_decompress(dinfo)) { 586 if (!jpeg_start_decompress(dinfo)) {
585 return fDecoderMgr->returnFailure("startDecompress", kInvalidInput); 587 return fDecoderMgr->returnFailure("startDecompress", kInvalidInput);
586 } 588 }
587 589
588 // A previous implementation claims that the return value of is_yuv_supporte d() 590 // A previous implementation claims that the return value of is_yuv_supporte d()
589 // may change after calling jpeg_start_decompress(). It looks to me like th is 591 // may change after calling jpeg_start_decompress(). It looks to me like th is
590 // was caused by a bug in the old code, but we'll be safe and check here. 592 // was caused by a bug in the old code, but we'll be safe and check here.
591 SkASSERT(is_yuv_supported(dinfo)); 593 SkASSERT(is_yuv_supported(dinfo));
592 594
593 // Currently, we require that the Y plane dimensions match the image dimensi ons 595 // Currently, we require that the Y plane dimensions match the image dimensi ons
594 // and that the U and V planes are the same dimensions. 596 // and that the U and V planes are the same dimensions.
595 SkASSERT(sizeInfo.fUSize == sizeInfo.fVSize); 597 SkASSERT(sizeInfo.fSizes[SkYUVSizeInfo::kU] == sizeInfo.fSizes[SkYUVSizeInfo ::kV]);
596 SkASSERT((uint32_t) sizeInfo.fYSize.width() == dinfo->output_width && 598 SkASSERT((uint32_t) sizeInfo.fSizes[SkYUVSizeInfo::kY].width() == dinfo->out put_width &&
597 (uint32_t) sizeInfo.fYSize.height() == dinfo->output_height); 599 (uint32_t) sizeInfo.fSizes[SkYUVSizeInfo::kY].height() == dinfo->out put_height);
598 600
599 // Build a JSAMPIMAGE to handle output from libjpeg-turbo. A JSAMPIMAGE has 601 // Build a JSAMPIMAGE to handle output from libjpeg-turbo. A JSAMPIMAGE has
600 // a 2-D array of pixels for each of the components (Y, U, V) in the image. 602 // a 2-D array of pixels for each of the components (Y, U, V) in the image.
601 // Cheat Sheet: 603 // Cheat Sheet:
602 // JSAMPIMAGE == JSAMPLEARRAY* == JSAMPROW** == JSAMPLE*** 604 // JSAMPIMAGE == JSAMPLEARRAY* == JSAMPROW** == JSAMPLE***
603 JSAMPARRAY yuv[3]; 605 JSAMPARRAY yuv[3];
604 606
605 // Set aside enough space for pointers to rows of Y, U, and V. 607 // Set aside enough space for pointers to rows of Y, U, and V.
606 JSAMPROW rowptrs[2 * DCTSIZE + DCTSIZE + DCTSIZE]; 608 JSAMPROW rowptrs[2 * DCTSIZE + DCTSIZE + DCTSIZE];
607 yuv[0] = &rowptrs[0]; // Y rows (DCTSIZE or 2 * DCTSIZE) 609 yuv[0] = &rowptrs[0]; // Y rows (DCTSIZE or 2 * DCTSIZE)
608 yuv[1] = &rowptrs[2 * DCTSIZE]; // U rows (DCTSIZE) 610 yuv[1] = &rowptrs[2 * DCTSIZE]; // U rows (DCTSIZE)
609 yuv[2] = &rowptrs[3 * DCTSIZE]; // V rows (DCTSIZE) 611 yuv[2] = &rowptrs[3 * DCTSIZE]; // V rows (DCTSIZE)
610 612
611 // Initialize rowptrs. 613 // Initialize rowptrs.
612 int numYRowsPerBlock = DCTSIZE * dinfo->comp_info[0].v_samp_factor; 614 int numYRowsPerBlock = DCTSIZE * dinfo->comp_info[0].v_samp_factor;
613 for (int i = 0; i < numYRowsPerBlock; i++) { 615 for (int i = 0; i < numYRowsPerBlock; i++) {
614 rowptrs[i] = SkTAddOffset<JSAMPLE>(pixels[0], i * sizeInfo.fYWidthBytes) ; 616 rowptrs[i] = SkTAddOffset<JSAMPLE>(pixels[SkYUVSizeInfo::kY],
617 i * sizeInfo.fWidthBytes[SkYUVSizeInfo::kY]);
615 } 618 }
616 for (int i = 0; i < DCTSIZE; i++) { 619 for (int i = 0; i < DCTSIZE; i++) {
617 rowptrs[i + 2 * DCTSIZE] = SkTAddOffset<JSAMPLE>(pixels[1], i * sizeInfo .fUWidthBytes); 620 rowptrs[i + 2 * DCTSIZE] = SkTAddOffset<JSAMPLE>(pixels[SkYUVSizeInfo::k U],
618 rowptrs[i + 3 * DCTSIZE] = SkTAddOffset<JSAMPLE>(pixels[2], i * sizeInfo .fVWidthBytes); 621 i * sizeInfo.fWidthBytes[SkYUVSizeInfo::kU]);
622 rowptrs[i + 3 * DCTSIZE] = SkTAddOffset<JSAMPLE>(pixels[SkYUVSizeInfo::k V],
623 i * sizeInfo.fWidthBytes[SkYUVSizeInfo::kV]);
619 } 624 }
620 625
621 // After each loop iteration, we will increment pointers to Y, U, and V. 626 // After each loop iteration, we will increment pointers to Y, U, and V.
622 size_t blockIncrementY = numYRowsPerBlock * sizeInfo.fYWidthBytes; 627 size_t blockIncrementY = numYRowsPerBlock * sizeInfo.fWidthBytes[SkYUVSizeIn fo::kY];
623 size_t blockIncrementU = DCTSIZE * sizeInfo.fUWidthBytes; 628 size_t blockIncrementU = DCTSIZE * sizeInfo.fWidthBytes[SkYUVSizeInfo::kU];
624 size_t blockIncrementV = DCTSIZE * sizeInfo.fVWidthBytes; 629 size_t blockIncrementV = DCTSIZE * sizeInfo.fWidthBytes[SkYUVSizeInfo::kV];
625 630
626 uint32_t numRowsPerBlock = numYRowsPerBlock; 631 uint32_t numRowsPerBlock = numYRowsPerBlock;
627 632
628 // We intentionally round down here, as this first loop will only handle 633 // We intentionally round down here, as this first loop will only handle
629 // full block rows. As a special case at the end, we will handle any 634 // full block rows. As a special case at the end, we will handle any
630 // remaining rows that do not make up a full block. 635 // remaining rows that do not make up a full block.
631 const int numIters = dinfo->output_height / numRowsPerBlock; 636 const int numIters = dinfo->output_height / numRowsPerBlock;
632 for (int i = 0; i < numIters; i++) { 637 for (int i = 0; i < numIters; i++) {
633 JDIMENSION linesRead = jpeg_read_raw_data(dinfo, yuv, numRowsPerBlock); 638 JDIMENSION linesRead = jpeg_read_raw_data(dinfo, yuv, numRowsPerBlock);
634 if (linesRead < numRowsPerBlock) { 639 if (linesRead < numRowsPerBlock) {
(...skipping 12 matching lines...) Expand all
647 } 652 }
648 653
649 uint32_t remainingRows = dinfo->output_height - dinfo->output_scanline; 654 uint32_t remainingRows = dinfo->output_height - dinfo->output_scanline;
650 SkASSERT(remainingRows == dinfo->output_height % numRowsPerBlock); 655 SkASSERT(remainingRows == dinfo->output_height % numRowsPerBlock);
651 SkASSERT(dinfo->output_scanline == numIters * numRowsPerBlock); 656 SkASSERT(dinfo->output_scanline == numIters * numRowsPerBlock);
652 if (remainingRows > 0) { 657 if (remainingRows > 0) {
653 // libjpeg-turbo needs memory to be padded by the block sizes. We will fulfill 658 // libjpeg-turbo needs memory to be padded by the block sizes. We will fulfill
654 // this requirement using a dummy row buffer. 659 // this requirement using a dummy row buffer.
655 // FIXME: Should SkCodec have an extra memory buffer that can be shared among 660 // FIXME: Should SkCodec have an extra memory buffer that can be shared among
656 // all of the implementations that use temporary/garbage memory? 661 // all of the implementations that use temporary/garbage memory?
657 SkAutoTMalloc<JSAMPLE> dummyRow(sizeInfo.fYWidthBytes); 662 SkAutoTMalloc<JSAMPLE> dummyRow(sizeInfo.fWidthBytes[SkYUVSizeInfo::kY]) ;
658 for (int i = remainingRows; i < numYRowsPerBlock; i++) { 663 for (int i = remainingRows; i < numYRowsPerBlock; i++) {
659 rowptrs[i] = dummyRow.get(); 664 rowptrs[i] = dummyRow.get();
660 } 665 }
661 int remainingUVRows = dinfo->comp_info[1].downsampled_height - DCTSIZE * numIters; 666 int remainingUVRows = dinfo->comp_info[1].downsampled_height - DCTSIZE * numIters;
662 for (int i = remainingUVRows; i < DCTSIZE; i++) { 667 for (int i = remainingUVRows; i < DCTSIZE; i++) {
663 rowptrs[i + 2 * DCTSIZE] = dummyRow.get(); 668 rowptrs[i + 2 * DCTSIZE] = dummyRow.get();
664 rowptrs[i + 3 * DCTSIZE] = dummyRow.get(); 669 rowptrs[i + 3 * DCTSIZE] = dummyRow.get();
665 } 670 }
666 671
667 JDIMENSION linesRead = jpeg_read_raw_data(dinfo, yuv, numRowsPerBlock); 672 JDIMENSION linesRead = jpeg_read_raw_data(dinfo, yuv, numRowsPerBlock);
668 if (linesRead < remainingRows) { 673 if (linesRead < remainingRows) {
669 // FIXME: Handle incomplete YUV decodes without signalling an error. 674 // FIXME: Handle incomplete YUV decodes without signalling an error.
670 return kInvalidInput; 675 return kInvalidInput;
671 } 676 }
672 } 677 }
673 678
674 return kSuccess; 679 return kSuccess;
675 } 680 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698