frameworks/base
Révision | 74908804ca31b4392c3ccb5ccc284889b1e71e92 (tree) |
---|---|
l'heure | 2015-12-22 13:13:49 |
Auteur | Zhao Liang <leo.zhao@inte...> |
Commiter | Chih-Wei Huang |
import YuvToEncoder R3 patches, BZ 18528, 19092, 19696
BZ: 47824
Please refer http://umgbugzilla.sh.intel.com:41006/show_bug.cgi?id=19092 and
external/jpeg/libjpeg.doc
The MCU height is max_v_samp_factor = 2 DCT rows so you must pass at least 16
scanlines on each call to jpeg_write_raw_data(), which is to say 16 actual
sample rows of Y and 8 each of Cb and Cr.
The original implement of Yuv420SpToJpegEncoder::compress didn't add padding to the frame buffer
when height and width aren't aligned with 16 pixel. It will cause illegal memory violation and core dump.
Category: aosp improvement
Domain: Video.Media-jpeg
Origin: Internal
Upstream: Yes
Change-Id: Ibcf14230d616e2d440ace244bb420723b5c01dc2
Orig-Change-Id: Ic1b7494b98ee9c1997b226d58abd034b1dcb18f6
Signed-off-by: Tong, Bo <box.tong@intel.com>
Signed-off-by: Zhao Liang <leo.zhao@intel.com>
@@ -43,6 +43,7 @@ bool YuvToJpegEncoder::encode(SkWStream* stream, void* inYuv, int width, | ||
43 | 43 | compress(&cinfo, (uint8_t*) inYuv, offsets); |
44 | 44 | |
45 | 45 | jpeg_finish_compress(&cinfo); |
46 | + jpeg_destroy_compress(&cinfo); | |
46 | 47 | |
47 | 48 | return true; |
48 | 49 | } |
@@ -83,9 +84,15 @@ void Yuv420SpToJpegEncoder::compress(jpeg_compress_struct* cinfo, | ||
83 | 84 | int height = cinfo->image_height; |
84 | 85 | uint8_t* yPlanar = yuv + offsets[0]; |
85 | 86 | uint8_t* vuPlanar = yuv + offsets[1]; //width * height; |
86 | - uint8_t* uRows = new uint8_t [8 * (width >> 1)]; | |
87 | - uint8_t* vRows = new uint8_t [8 * (width >> 1)]; | |
88 | - | |
87 | + uint8_t* uRows = new uint8_t [8 * (((width + 15) & ~15) >> 1)]; | |
88 | + uint8_t* vRows = new uint8_t [8 * (((width + 15) & ~15) >> 1)]; | |
89 | + uint8_t* yRows; | |
90 | + int lastLines; | |
91 | + | |
92 | + if ((height & 0xf) != 0) { | |
93 | + lastLines = height & 0xf; | |
94 | + yRows = new uint8_t [16 * ((width + 15) & ~15)]; | |
95 | + } | |
89 | 96 | |
90 | 97 | // process 16 lines of Y and 8 lines of U/V each time. |
91 | 98 | while (cinfo->next_scanline < cinfo->image_height) { |
@@ -94,8 +101,11 @@ void Yuv420SpToJpegEncoder::compress(jpeg_compress_struct* cinfo, | ||
94 | 101 | |
95 | 102 | // Jpeg library ignores the rows whose indices are greater than height. |
96 | 103 | for (int i = 0; i < 16; i++) { |
97 | - // y row | |
98 | - y[i] = yPlanar + (cinfo->next_scanline + i) * fStrides[0]; | |
104 | + // y row. Add padding if height isn't aligned to 16 pixels. | |
105 | + if ((height & 0xf) != 0 && (cinfo->next_scanline + i) > height) | |
106 | + y[i] = &yRows[(i - lastLines) * ((width + 15) & ~15)]; | |
107 | + else | |
108 | + y[i] = yPlanar + (cinfo->next_scanline + i) * fStrides[0]; | |
99 | 109 | |
100 | 110 | // construct u row and v row |
101 | 111 | if ((i & 1) == 0) { |
@@ -107,6 +117,8 @@ void Yuv420SpToJpegEncoder::compress(jpeg_compress_struct* cinfo, | ||
107 | 117 | } |
108 | 118 | jpeg_write_raw_data(cinfo, planes, 16); |
109 | 119 | } |
120 | + if ((height & 0xf) != 0) | |
121 | + delete [] yRows; | |
110 | 122 | delete [] uRows; |
111 | 123 | delete [] vRows; |
112 | 124 |
@@ -114,9 +126,12 @@ void Yuv420SpToJpegEncoder::compress(jpeg_compress_struct* cinfo, | ||
114 | 126 | |
115 | 127 | void Yuv420SpToJpegEncoder::deinterleave(uint8_t* vuPlanar, uint8_t* uRows, |
116 | 128 | uint8_t* vRows, int rowIndex, int width, int height) { |
117 | - int numRows = (height - rowIndex) / 2; | |
118 | - if (numRows > 8) numRows = 8; | |
119 | - for (int row = 0; row < numRows; ++row) { | |
129 | + int lines = 16; | |
130 | + //In case there isn't enough lines to process | |
131 | + if ((rowIndex + lines) > height) | |
132 | + lines = (height - rowIndex); | |
133 | + | |
134 | + for (int row = 0; row < (lines >> 1); ++row) { | |
120 | 135 | int offset = ((rowIndex >> 1) + row) * fStrides[1]; |
121 | 136 | uint8_t* vu = vuPlanar + offset; |
122 | 137 | for (int i = 0; i < (width >> 1); ++i) { |