YuvToJpegEncoder.cpp revision 8f2423e8f394ae0666f1b61f83df4c0c7a4782d9
1bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen#include "CreateJavaOutputStreamAdaptor.h"
2bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen#include "SkJpegUtility.h"
3bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen#include "YuvToJpegEncoder.h"
48f2423e8f394ae0666f1b61f83df4c0c7a4782d9Mathias Agopian#include <ui/PixelFormat.h>
58f2423e8f394ae0666f1b61f83df4c0c7a4782d9Mathias Agopian#include <hardware/hardware.h>
6bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen
7bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen#include <jni.h>
8bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen
9bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta ChenYuvToJpegEncoder* YuvToJpegEncoder::create(int format, int* strides) {
10bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    // Only PIXEL_FORMAT_YCbCr_420_SP and PIXEl_FOMAT_YCbCr_422_I are supported
11bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    // for now.
128f2423e8f394ae0666f1b61f83df4c0c7a4782d9Mathias Agopian    if (format == HAL_PIXEL_FORMAT_YCbCr_420_SP) {
13bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen        return new Yuv420SpToJpegEncoder(strides);
148f2423e8f394ae0666f1b61f83df4c0c7a4782d9Mathias Agopian    } else if (format == HAL_PIXEL_FORMAT_YCbCr_422_I) {
15bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen        return new Yuv422IToJpegEncoder(strides);
16bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    } else {
17bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen      return NULL;
18bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    }
19bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen}
20bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen
21bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta ChenYuvToJpegEncoder::YuvToJpegEncoder(int* strides) : fStrides(strides) {
22bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen}
23bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen
24bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chenbool YuvToJpegEncoder::encode(SkWStream* stream, void* inYuv, int width,
25bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen        int height, int* offsets, int jpegQuality) {
26bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    jpeg_compress_struct    cinfo;
27bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    skjpeg_error_mgr        sk_err;
28bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    skjpeg_destination_mgr  sk_wstream(stream);
29bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen
30bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    cinfo.err = jpeg_std_error(&sk_err);
31bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    sk_err.error_exit = skjpeg_error_exit;
32bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    if (setjmp(sk_err.fJmpBuf)) {
33bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen        return false;
34bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    }
35bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    jpeg_create_compress(&cinfo);
36bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen
37bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    cinfo.dest = &sk_wstream;
38bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen
39bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    setJpegCompressStruct(&cinfo, width, height, jpegQuality);
40bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen
41bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    jpeg_start_compress(&cinfo, TRUE);
42bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen
43bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    compress(&cinfo, (uint8_t*) inYuv, offsets);
44bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen
45bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    jpeg_finish_compress(&cinfo);
46bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen
47bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    return true;
48bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen}
49bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen
50bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chenvoid YuvToJpegEncoder::setJpegCompressStruct(jpeg_compress_struct* cinfo,
51bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen        int width, int height, int quality) {
52bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    jpeg_set_quality(cinfo, quality, TRUE);
53bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen
54bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    cinfo->image_width = width;
55bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    cinfo->image_height = height;
56bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen
57bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    cinfo->input_components = 3;
58bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    cinfo->in_color_space = JCS_YCbCr;
59bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    jpeg_set_defaults(cinfo);
60bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    jpeg_set_colorspace(cinfo, JCS_YCbCr);
61bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    cinfo->raw_data_in = TRUE;
62bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen
63bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    cinfo->dct_method = JDCT_IFAST;
64bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen
65bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    configSamplingFactors(cinfo);
66bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen}
67bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen
68bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen///////////////////////////////////////////////////////////////////
69bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta ChenYuv420SpToJpegEncoder::Yuv420SpToJpegEncoder(int* strides) :
70bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen        YuvToJpegEncoder(strides) {
71bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    fNumPlanes = 2;
72bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen}
73bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen
74bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chenvoid Yuv420SpToJpegEncoder::compress(jpeg_compress_struct* cinfo,
75bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen        uint8_t* yuv, int* offsets) {
76bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    SkDebugf("onFlyCompress");
77bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    JSAMPROW y[16];
78bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    JSAMPROW cb[8];
79bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    JSAMPROW cr[8];
80bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    JSAMPARRAY planes[3];
81bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    planes[0] = y;
82bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    planes[1] = cb;
83bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    planes[2] = cr;
84bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen
85bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    int width = cinfo->image_width;
86bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    int height = cinfo->image_height;
87bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    uint8_t* yPlanar = yuv + offsets[0];
88bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    uint8_t* vuPlanar = yuv + offsets[1]; //width * height;
89bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    uint8_t* uRows = new uint8_t [8 * (width >> 1)];
90bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    uint8_t* vRows = new uint8_t [8 * (width >> 1)];
91bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen
92bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen
93bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    // process 16 lines of Y and 8 lines of U/V each time.
94bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    while (cinfo->next_scanline < cinfo->image_height) {
95bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen        //deitnerleave u and v
96bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen        deinterleave(vuPlanar, uRows, vRows, cinfo->next_scanline, width);
97bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen
98bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen        for (int i = 0; i < 16; i++) {
99bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen            // y row
100bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen            y[i] = yPlanar + (cinfo->next_scanline + i) * fStrides[0];
101bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen
102bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen            // construct u row and v row
103bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen            if ((i & 1) == 0) {
104bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen                // height and width are both halved because of downsampling
105bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen                int offset = (i >> 1) * (width >> 1);
106bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen                cb[i/2] = uRows + offset;
107bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen                cr[i/2] = vRows + offset;
108bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen            }
109bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen          }
110bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen        jpeg_write_raw_data(cinfo, planes, 16);
111bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    }
112bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    delete [] uRows;
113bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    delete [] vRows;
114bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen
115bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen}
116bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen
117bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chenvoid Yuv420SpToJpegEncoder::deinterleave(uint8_t* vuPlanar, uint8_t* uRows,
118bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen        uint8_t* vRows, int rowIndex, int width) {
119bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    for (int row = 0; row < 8; ++row) {
120bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen        int offset = ((rowIndex >> 1) + row) * fStrides[1];
121bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen        uint8_t* vu = vuPlanar + offset;
122bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen        for (int i = 0; i < (width >> 1); ++i) {
123bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen            int index = row * (width >> 1) + i;
124bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen            uRows[index] = vu[1];
125bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen            vRows[index] = vu[0];
126bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen            vu += 2;
127bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen        }
128bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    }
129bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen}
130bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen
131bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chenvoid Yuv420SpToJpegEncoder::configSamplingFactors(jpeg_compress_struct* cinfo) {
132bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    // cb and cr are horizontally downsampled and vertically downsampled as well.
133bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    cinfo->comp_info[0].h_samp_factor = 2;
134bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    cinfo->comp_info[0].v_samp_factor = 2;
135bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    cinfo->comp_info[1].h_samp_factor = 1;
136bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    cinfo->comp_info[1].v_samp_factor = 1;
137bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    cinfo->comp_info[2].h_samp_factor = 1;
138bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    cinfo->comp_info[2].v_samp_factor = 1;
139bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen}
140bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen
141bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen///////////////////////////////////////////////////////////////////////////////
142bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta ChenYuv422IToJpegEncoder::Yuv422IToJpegEncoder(int* strides) :
143bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen        YuvToJpegEncoder(strides) {
144bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    fNumPlanes = 1;
145bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen}
146bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen
147bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chenvoid Yuv422IToJpegEncoder::compress(jpeg_compress_struct* cinfo,
148bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen        uint8_t* yuv, int* offsets) {
149bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    SkDebugf("onFlyCompress_422");
150bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    JSAMPROW y[16];
151bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    JSAMPROW cb[16];
152bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    JSAMPROW cr[16];
153bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    JSAMPARRAY planes[3];
154bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    planes[0] = y;
155bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    planes[1] = cb;
156bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    planes[2] = cr;
157bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen
158bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    int width = cinfo->image_width;
159bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    int height = cinfo->image_height;
160bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    uint8_t* yRows = new uint8_t [16 * width];
161bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    uint8_t* uRows = new uint8_t [16 * (width >> 1)];
162bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    uint8_t* vRows = new uint8_t [16 * (width >> 1)];
163bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen
164bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    uint8_t* yuvOffset = yuv + offsets[0];
165bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen
166bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    // process 16 lines of Y and 16 lines of U/V each time.
167bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    while (cinfo->next_scanline < cinfo->image_height) {
168bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen        deinterleave(yuvOffset, yRows, uRows, vRows, cinfo->next_scanline, width, height);
169bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen
170bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen        for (int i = 0; i < 16; i++) {
171bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen            // y row
172bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen            y[i] = yRows + i * width;
173bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen
174bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen            // construct u row and v row
175bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen            // width is halved because of downsampling
176bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen            int offset = i * (width >> 1);
177bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen            cb[i] = uRows + offset;
178bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen            cr[i] = vRows + offset;
179bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen        }
180bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen
181bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen        jpeg_write_raw_data(cinfo, planes, 16);
182bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    }
183bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    delete [] yRows;
184bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    delete [] uRows;
185bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    delete [] vRows;
186bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen}
187bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen
188bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen
189bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chenvoid Yuv422IToJpegEncoder::deinterleave(uint8_t* yuv, uint8_t* yRows, uint8_t* uRows,
190bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen        uint8_t* vRows, int rowIndex, int width, int height) {
191bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    for (int row = 0; row < 16; ++row) {
192bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen        uint8_t* yuvSeg = yuv + (rowIndex + row) * fStrides[0];
193bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen        for (int i = 0; i < (width >> 1); ++i) {
194bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen            int indexY = row * width + (i << 1);
195bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen            int indexU = row * (width >> 1) + i;
196bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen            yRows[indexY] = yuvSeg[0];
197bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen            yRows[indexY + 1] = yuvSeg[2];
198bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen            uRows[indexU] = yuvSeg[1];
199bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen            vRows[indexU] = yuvSeg[3];
200bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen            yuvSeg += 4;
201bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen        }
202bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    }
203bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen}
204bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen
205bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chenvoid Yuv422IToJpegEncoder::configSamplingFactors(jpeg_compress_struct* cinfo) {
206bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    // cb and cr are horizontally downsampled and vertically downsampled as well.
207bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    cinfo->comp_info[0].h_samp_factor = 2;
208bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    cinfo->comp_info[0].v_samp_factor = 2;
209bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    cinfo->comp_info[1].h_samp_factor = 1;
210bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    cinfo->comp_info[1].v_samp_factor = 2;
211bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    cinfo->comp_info[2].h_samp_factor = 1;
212bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    cinfo->comp_info[2].v_samp_factor = 2;
213bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen}
214bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen///////////////////////////////////////////////////////////////////////////////
215bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen
216bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chenstatic jboolean YuvImage_compressToJpeg(JNIEnv* env, jobject, jbyteArray inYuv,
217bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen        int format, int width, int height, jintArray offsets,
218bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen        jintArray strides, int jpegQuality, jobject jstream,
219bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen        jbyteArray jstorage) {
220bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    jbyte* yuv = env->GetByteArrayElements(inYuv, NULL);
221bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    SkWStream* strm = CreateJavaOutputStreamAdaptor(env, jstream, jstorage);
222bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen
223bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    jint* imgOffsets = env->GetIntArrayElements(offsets, NULL);
224bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    jint* imgStrides = env->GetIntArrayElements(strides, NULL);
225bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    YuvToJpegEncoder* encoder = YuvToJpegEncoder::create(format, imgStrides);
226bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    if (encoder == NULL) {
227bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen        return false;
228bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    }
229bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    encoder->encode(strm, yuv, width, height, imgOffsets, jpegQuality);
230bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen
231bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    delete encoder;
232bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    env->ReleaseByteArrayElements(inYuv, yuv, 0);
233bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    env->ReleaseIntArrayElements(offsets, imgOffsets, 0);
234bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    env->ReleaseIntArrayElements(strides, imgStrides, 0);
235bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    return true;
236bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen}
237bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen///////////////////////////////////////////////////////////////////////////////
238bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen
239bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen#include <android_runtime/AndroidRuntime.h>
240bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen
241bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chenstatic JNINativeMethod gYuvImageMethods[] = {
242bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    {   "nativeCompressToJpeg",  "([BIII[I[IILjava/io/OutputStream;[B)Z",
243bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen        (void*)YuvImage_compressToJpeg }
244bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen};
245bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen
246bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen#define kClassPathName  "android/graphics/YuvImage"
247bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen
248bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chenint register_android_graphics_YuvImage(JNIEnv* env);
249bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chenint register_android_graphics_YuvImage(JNIEnv* env)
250bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen{
251bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen    return android::AndroidRuntime::registerNativeMethods(env, kClassPathName,
252bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen            gYuvImageMethods, SK_ARRAY_COUNT(gYuvImageMethods));
253bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen}
254