1bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen#include "CreateJavaOutputStreamAdaptor.h" 279ad7bedcfaec8ccce22589eb62b342fd0de05afMatt Sarett#include "SkJPEGWriteUtility.h" 3bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen#include "YuvToJpegEncoder.h" 48f2423e8f394ae0666f1b61f83df4c0c7a4782d9Mathias Agopian#include <ui/PixelFormat.h> 58f2423e8f394ae0666f1b61f83df4c0c7a4782d9Mathias Agopian#include <hardware/hardware.h> 6bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 7ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe#include "core_jni_helpers.h" 8ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe 9bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen#include <jni.h> 10bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 11bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta ChenYuvToJpegEncoder* YuvToJpegEncoder::create(int format, int* strides) { 12a696f5d667227365da732481770767dcb330dd23Mathias Agopian // Only ImageFormat.NV21 and ImageFormat.YUY2 are supported 13bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen // for now. 14a696f5d667227365da732481770767dcb330dd23Mathias Agopian if (format == HAL_PIXEL_FORMAT_YCrCb_420_SP) { 15bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen return new Yuv420SpToJpegEncoder(strides); 168f2423e8f394ae0666f1b61f83df4c0c7a4782d9Mathias Agopian } else if (format == HAL_PIXEL_FORMAT_YCbCr_422_I) { 17bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen return new Yuv422IToJpegEncoder(strides); 18bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen } else { 19bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen return NULL; 20bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen } 21bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen} 22bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 23bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta ChenYuvToJpegEncoder::YuvToJpegEncoder(int* strides) : fStrides(strides) { 24bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen} 25bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 261c3ded39f2ebd57286577a648d5a906752046386Leon Scroggins IIIstruct ErrorMgr { 271c3ded39f2ebd57286577a648d5a906752046386Leon Scroggins III struct jpeg_error_mgr pub; 281c3ded39f2ebd57286577a648d5a906752046386Leon Scroggins III jmp_buf jmp; 291c3ded39f2ebd57286577a648d5a906752046386Leon Scroggins III}; 301c3ded39f2ebd57286577a648d5a906752046386Leon Scroggins III 311c3ded39f2ebd57286577a648d5a906752046386Leon Scroggins IIIvoid error_exit(j_common_ptr cinfo) { 321c3ded39f2ebd57286577a648d5a906752046386Leon Scroggins III ErrorMgr* err = (ErrorMgr*) cinfo->err; 331c3ded39f2ebd57286577a648d5a906752046386Leon Scroggins III (*cinfo->err->output_message) (cinfo); 341c3ded39f2ebd57286577a648d5a906752046386Leon Scroggins III longjmp(err->jmp, 1); 351c3ded39f2ebd57286577a648d5a906752046386Leon Scroggins III} 361c3ded39f2ebd57286577a648d5a906752046386Leon Scroggins III 37bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chenbool YuvToJpegEncoder::encode(SkWStream* stream, void* inYuv, int width, 38bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen int height, int* offsets, int jpegQuality) { 39bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen jpeg_compress_struct cinfo; 401c3ded39f2ebd57286577a648d5a906752046386Leon Scroggins III ErrorMgr err; 41bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen skjpeg_destination_mgr sk_wstream(stream); 42bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 431c3ded39f2ebd57286577a648d5a906752046386Leon Scroggins III cinfo.err = jpeg_std_error(&err.pub); 441c3ded39f2ebd57286577a648d5a906752046386Leon Scroggins III err.pub.error_exit = error_exit; 451c3ded39f2ebd57286577a648d5a906752046386Leon Scroggins III 461c3ded39f2ebd57286577a648d5a906752046386Leon Scroggins III if (setjmp(err.jmp)) { 471c3ded39f2ebd57286577a648d5a906752046386Leon Scroggins III jpeg_destroy_compress(&cinfo); 48bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen return false; 49bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen } 50bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen jpeg_create_compress(&cinfo); 51bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 52bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen cinfo.dest = &sk_wstream; 53bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 54bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen setJpegCompressStruct(&cinfo, width, height, jpegQuality); 55bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 56bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen jpeg_start_compress(&cinfo, TRUE); 57bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 58bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen compress(&cinfo, (uint8_t*) inYuv, offsets); 59bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 60bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen jpeg_finish_compress(&cinfo); 61bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 621c3ded39f2ebd57286577a648d5a906752046386Leon Scroggins III jpeg_destroy_compress(&cinfo); 631c3ded39f2ebd57286577a648d5a906752046386Leon Scroggins III 64bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen return true; 65bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen} 66bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 67bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chenvoid YuvToJpegEncoder::setJpegCompressStruct(jpeg_compress_struct* cinfo, 68bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen int width, int height, int quality) { 69bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen cinfo->image_width = width; 70bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen cinfo->image_height = height; 71bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen cinfo->input_components = 3; 72bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen cinfo->in_color_space = JCS_YCbCr; 73bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen jpeg_set_defaults(cinfo); 74aa86859b1035f865147b4f76ad2a9eed7ee098a5Chia-chi Yeh 75aa86859b1035f865147b4f76ad2a9eed7ee098a5Chia-chi Yeh jpeg_set_quality(cinfo, quality, TRUE); 76bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen jpeg_set_colorspace(cinfo, JCS_YCbCr); 77bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen cinfo->raw_data_in = TRUE; 78bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen cinfo->dct_method = JDCT_IFAST; 79bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen configSamplingFactors(cinfo); 80bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen} 81bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 82bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen/////////////////////////////////////////////////////////////////// 83bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta ChenYuv420SpToJpegEncoder::Yuv420SpToJpegEncoder(int* strides) : 84bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen YuvToJpegEncoder(strides) { 85bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen fNumPlanes = 2; 86bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen} 87bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 88bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chenvoid Yuv420SpToJpegEncoder::compress(jpeg_compress_struct* cinfo, 89bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen uint8_t* yuv, int* offsets) { 90bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen SkDebugf("onFlyCompress"); 91bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen JSAMPROW y[16]; 92bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen JSAMPROW cb[8]; 93bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen JSAMPROW cr[8]; 94bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen JSAMPARRAY planes[3]; 95bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen planes[0] = y; 96bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen planes[1] = cb; 97bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen planes[2] = cr; 98bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 99bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen int width = cinfo->image_width; 100bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen int height = cinfo->image_height; 101bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen uint8_t* yPlanar = yuv + offsets[0]; 102bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen uint8_t* vuPlanar = yuv + offsets[1]; //width * height; 103bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen uint8_t* uRows = new uint8_t [8 * (width >> 1)]; 104bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen uint8_t* vRows = new uint8_t [8 * (width >> 1)]; 105bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 106bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 107bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen // process 16 lines of Y and 8 lines of U/V each time. 108bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen while (cinfo->next_scanline < cinfo->image_height) { 109bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen //deitnerleave u and v 1104b63f14c96841d02b6bffce987f7705b6aa8e2a9Wu-cheng Li deinterleave(vuPlanar, uRows, vRows, cinfo->next_scanline, width, height); 111bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 1124b63f14c96841d02b6bffce987f7705b6aa8e2a9Wu-cheng Li // Jpeg library ignores the rows whose indices are greater than height. 113bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen for (int i = 0; i < 16; i++) { 114bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen // y row 115bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen y[i] = yPlanar + (cinfo->next_scanline + i) * fStrides[0]; 116bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 117bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen // construct u row and v row 118bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen if ((i & 1) == 0) { 119bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen // height and width are both halved because of downsampling 120bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen int offset = (i >> 1) * (width >> 1); 121bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen cb[i/2] = uRows + offset; 122bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen cr[i/2] = vRows + offset; 123bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen } 124bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen } 125bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen jpeg_write_raw_data(cinfo, planes, 16); 126bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen } 127bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen delete [] uRows; 128bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen delete [] vRows; 129bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 130bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen} 131bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 132bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chenvoid Yuv420SpToJpegEncoder::deinterleave(uint8_t* vuPlanar, uint8_t* uRows, 1334b63f14c96841d02b6bffce987f7705b6aa8e2a9Wu-cheng Li uint8_t* vRows, int rowIndex, int width, int height) { 1344b63f14c96841d02b6bffce987f7705b6aa8e2a9Wu-cheng Li int numRows = (height - rowIndex) / 2; 1354b63f14c96841d02b6bffce987f7705b6aa8e2a9Wu-cheng Li if (numRows > 8) numRows = 8; 1364b63f14c96841d02b6bffce987f7705b6aa8e2a9Wu-cheng Li for (int row = 0; row < numRows; ++row) { 137bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen int offset = ((rowIndex >> 1) + row) * fStrides[1]; 138bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen uint8_t* vu = vuPlanar + offset; 139bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen for (int i = 0; i < (width >> 1); ++i) { 140bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen int index = row * (width >> 1) + i; 141bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen uRows[index] = vu[1]; 142bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen vRows[index] = vu[0]; 143bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen vu += 2; 144bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen } 145bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen } 146bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen} 147bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 148bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chenvoid Yuv420SpToJpegEncoder::configSamplingFactors(jpeg_compress_struct* cinfo) { 149bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen // cb and cr are horizontally downsampled and vertically downsampled as well. 150bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen cinfo->comp_info[0].h_samp_factor = 2; 151bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen cinfo->comp_info[0].v_samp_factor = 2; 152bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen cinfo->comp_info[1].h_samp_factor = 1; 153bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen cinfo->comp_info[1].v_samp_factor = 1; 154bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen cinfo->comp_info[2].h_samp_factor = 1; 155bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen cinfo->comp_info[2].v_samp_factor = 1; 156bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen} 157bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 158bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen/////////////////////////////////////////////////////////////////////////////// 159bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta ChenYuv422IToJpegEncoder::Yuv422IToJpegEncoder(int* strides) : 160bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen YuvToJpegEncoder(strides) { 161bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen fNumPlanes = 1; 162bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen} 163bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 164bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chenvoid Yuv422IToJpegEncoder::compress(jpeg_compress_struct* cinfo, 165bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen uint8_t* yuv, int* offsets) { 166bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen SkDebugf("onFlyCompress_422"); 167bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen JSAMPROW y[16]; 168bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen JSAMPROW cb[16]; 169bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen JSAMPROW cr[16]; 170bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen JSAMPARRAY planes[3]; 171bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen planes[0] = y; 172bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen planes[1] = cb; 173bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen planes[2] = cr; 174bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 175bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen int width = cinfo->image_width; 176bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen int height = cinfo->image_height; 177bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen uint8_t* yRows = new uint8_t [16 * width]; 178bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen uint8_t* uRows = new uint8_t [16 * (width >> 1)]; 179bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen uint8_t* vRows = new uint8_t [16 * (width >> 1)]; 180bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 181bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen uint8_t* yuvOffset = yuv + offsets[0]; 182bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 183bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen // process 16 lines of Y and 16 lines of U/V each time. 184bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen while (cinfo->next_scanline < cinfo->image_height) { 185bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen deinterleave(yuvOffset, yRows, uRows, vRows, cinfo->next_scanline, width, height); 186bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 1874b63f14c96841d02b6bffce987f7705b6aa8e2a9Wu-cheng Li // Jpeg library ignores the rows whose indices are greater than height. 188bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen for (int i = 0; i < 16; i++) { 189bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen // y row 190bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen y[i] = yRows + i * width; 191bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 192bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen // construct u row and v row 193bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen // width is halved because of downsampling 194bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen int offset = i * (width >> 1); 195bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen cb[i] = uRows + offset; 196bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen cr[i] = vRows + offset; 197bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen } 198bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 199bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen jpeg_write_raw_data(cinfo, planes, 16); 200bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen } 201bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen delete [] yRows; 202bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen delete [] uRows; 203bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen delete [] vRows; 204bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen} 205bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 206bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 207bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chenvoid Yuv422IToJpegEncoder::deinterleave(uint8_t* yuv, uint8_t* yRows, uint8_t* uRows, 208bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen uint8_t* vRows, int rowIndex, int width, int height) { 2094b63f14c96841d02b6bffce987f7705b6aa8e2a9Wu-cheng Li int numRows = height - rowIndex; 2104b63f14c96841d02b6bffce987f7705b6aa8e2a9Wu-cheng Li if (numRows > 16) numRows = 16; 2114b63f14c96841d02b6bffce987f7705b6aa8e2a9Wu-cheng Li for (int row = 0; row < numRows; ++row) { 212bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen uint8_t* yuvSeg = yuv + (rowIndex + row) * fStrides[0]; 213bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen for (int i = 0; i < (width >> 1); ++i) { 214bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen int indexY = row * width + (i << 1); 215bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen int indexU = row * (width >> 1) + i; 216bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen yRows[indexY] = yuvSeg[0]; 217bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen yRows[indexY + 1] = yuvSeg[2]; 218bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen uRows[indexU] = yuvSeg[1]; 219bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen vRows[indexU] = yuvSeg[3]; 220bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen yuvSeg += 4; 221bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen } 222bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen } 223bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen} 224bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 225bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chenvoid Yuv422IToJpegEncoder::configSamplingFactors(jpeg_compress_struct* cinfo) { 226bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen // cb and cr are horizontally downsampled and vertically downsampled as well. 227bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen cinfo->comp_info[0].h_samp_factor = 2; 228bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen cinfo->comp_info[0].v_samp_factor = 2; 229bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen cinfo->comp_info[1].h_samp_factor = 1; 230bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen cinfo->comp_info[1].v_samp_factor = 2; 231bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen cinfo->comp_info[2].h_samp_factor = 1; 232bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen cinfo->comp_info[2].v_samp_factor = 2; 233bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen} 234bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen/////////////////////////////////////////////////////////////////////////////// 235bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 236bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chenstatic jboolean YuvImage_compressToJpeg(JNIEnv* env, jobject, jbyteArray inYuv, 23739029b29906fb064fc1e408983809b9b7ad74095Ashok Bhat jint format, jint width, jint height, jintArray offsets, 23839029b29906fb064fc1e408983809b9b7ad74095Ashok Bhat jintArray strides, jint jpegQuality, jobject jstream, 239bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen jbyteArray jstorage) { 240bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen jbyte* yuv = env->GetByteArrayElements(inYuv, NULL); 241bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen SkWStream* strm = CreateJavaOutputStreamAdaptor(env, jstream, jstorage); 242bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 243bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen jint* imgOffsets = env->GetIntArrayElements(offsets, NULL); 244bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen jint* imgStrides = env->GetIntArrayElements(strides, NULL); 245bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen YuvToJpegEncoder* encoder = YuvToJpegEncoder::create(format, imgStrides); 2467c68a4076e1ef141db5ac338d675646a278f0eb8Pawel Augustyn jboolean result = JNI_FALSE; 2477c68a4076e1ef141db5ac338d675646a278f0eb8Pawel Augustyn if (encoder != NULL) { 2487c68a4076e1ef141db5ac338d675646a278f0eb8Pawel Augustyn encoder->encode(strm, yuv, width, height, imgOffsets, jpegQuality); 2497c68a4076e1ef141db5ac338d675646a278f0eb8Pawel Augustyn delete encoder; 2507c68a4076e1ef141db5ac338d675646a278f0eb8Pawel Augustyn result = JNI_TRUE; 251bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen } 252bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 253bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen env->ReleaseByteArrayElements(inYuv, yuv, 0); 254bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen env->ReleaseIntArrayElements(offsets, imgOffsets, 0); 255bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen env->ReleaseIntArrayElements(strides, imgStrides, 0); 256d865900425d9593974aac640bc4deb93865dcfbeMartin Wallgren delete strm; 2577c68a4076e1ef141db5ac338d675646a278f0eb8Pawel Augustyn return result; 258bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen} 259bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen/////////////////////////////////////////////////////////////////////////////// 260bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 26176f6a86de25e1bf74717e047e55fd44b089673f3Daniel Micaystatic const JNINativeMethod gYuvImageMethods[] = { 262bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen { "nativeCompressToJpeg", "([BIII[I[IILjava/io/OutputStream;[B)Z", 263bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen (void*)YuvImage_compressToJpeg } 264bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen}; 265bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 266bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chenint register_android_graphics_YuvImage(JNIEnv* env) 267bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen{ 268ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe return android::RegisterMethodsOrDie(env, "android/graphics/YuvImage", gYuvImageMethods, 269ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe NELEM(gYuvImageMethods)); 270bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen} 271