1ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu/*
2ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu * Copyright (C) Texas Instruments - http://www.ti.com/
3ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu *
4ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu * Licensed under the Apache License, Version 2.0 (the "License");
5ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu * you may not use this file except in compliance with the License.
6ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu * You may obtain a copy of the License at
7ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu *
8ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu *      http://www.apache.org/licenses/LICENSE-2.0
9ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu *
10ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu * Unless required by applicable law or agreed to in writing, software
11ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu * distributed under the License is distributed on an "AS IS" BASIS,
12ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu * See the License for the specific language governing permissions and
14ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu * limitations under the License.
15ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu */
16ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu
17ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu/**
18ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu* @file Encoder_libjpeg.cpp
19ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu*
20ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu* This file encodes a YUV422I buffer to a jpeg
21ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu* TODO(XXX): Need to support formats other than yuv422i
22ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu*            Change interface to pre/post-proc algo framework
23ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu*
24ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu*/
25ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu
26ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu#define LOG_TAG "CameraHAL"
27ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu
28ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu#include "CameraHal.h"
29ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu#include "Encoder_libjpeg.h"
30c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu#include "NV12_resize.h"
31ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu
32ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu#include <stdlib.h>
33ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu#include <unistd.h>
34ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu#include <sys/types.h>
35ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu#include <sys/stat.h>
36ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu#include <fcntl.h>
37ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu#include <stdio.h>
38ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu#include <errno.h>
39c11c07d676f130e6e28ab1611f4862a01a160389Tyler Luu#include <math.h>
40ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu
41ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luuextern "C" {
42ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu    #include "jpeglib.h"
43ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu    #include "jerror.h"
44ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu}
45ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu
4636e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu#define ARRAY_SIZE(array) (sizeof((array)) / sizeof((array)[0]))
47ef73bec8a83a2fd7fbb072d009382c64eb2da0eeTyler Luu#define MIN(x,y) ((x < y) ? x : y)
4836e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu
49ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luunamespace android {
50c78626b15e9f29a5bcf85447ceafb17dcbf58b69Emilian Peevstruct integer_string_pair {
51c78626b15e9f29a5bcf85447ceafb17dcbf58b69Emilian Peev    unsigned int integer;
52c78626b15e9f29a5bcf85447ceafb17dcbf58b69Emilian Peev    const char* string;
5336e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu};
54ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu
55c78626b15e9f29a5bcf85447ceafb17dcbf58b69Emilian Peevstatic integer_string_pair degress_to_exif_lut [] = {
5636e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu    // degrees, exif_orientation
57c78626b15e9f29a5bcf85447ceafb17dcbf58b69Emilian Peev    {0,   "1"},
58c78626b15e9f29a5bcf85447ceafb17dcbf58b69Emilian Peev    {90,  "6"},
59c78626b15e9f29a5bcf85447ceafb17dcbf58b69Emilian Peev    {180, "3"},
60c78626b15e9f29a5bcf85447ceafb17dcbf58b69Emilian Peev    {270, "8"},
6136e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu};
62ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luustruct libjpeg_destination_mgr : jpeg_destination_mgr {
63ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu    libjpeg_destination_mgr(uint8_t* input, int size);
64ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu
65ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu    uint8_t* buf;
66ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu    int bufsize;
67ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu    size_t jpegsize;
68ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu};
69ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu
70ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luustatic void libjpeg_init_destination (j_compress_ptr cinfo) {
71ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu    libjpeg_destination_mgr* dest = (libjpeg_destination_mgr*)cinfo->dest;
72ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu
73ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu    dest->next_output_byte = dest->buf;
74ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu    dest->free_in_buffer = dest->bufsize;
75ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu    dest->jpegsize = 0;
76ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu}
77ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu
78ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luustatic boolean libjpeg_empty_output_buffer(j_compress_ptr cinfo) {
79ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu    libjpeg_destination_mgr* dest = (libjpeg_destination_mgr*)cinfo->dest;
80ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu
81ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu    dest->next_output_byte = dest->buf;
82ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu    dest->free_in_buffer = dest->bufsize;
83ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu    return TRUE; // ?
84ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu}
85ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu
86ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luustatic void libjpeg_term_destination (j_compress_ptr cinfo) {
87ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu    libjpeg_destination_mgr* dest = (libjpeg_destination_mgr*)cinfo->dest;
88ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu    dest->jpegsize = dest->bufsize - dest->free_in_buffer;
89ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu}
90ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu
91ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luulibjpeg_destination_mgr::libjpeg_destination_mgr(uint8_t* input, int size) {
92ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu    this->init_destination = libjpeg_init_destination;
93ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu    this->empty_output_buffer = libjpeg_empty_output_buffer;
94ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu    this->term_destination = libjpeg_term_destination;
95ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu
96ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu    this->buf = input;
97ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu    this->bufsize = size;
98c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu
99c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu    jpegsize = 0;
100ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu}
101ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu
102ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu/* private static functions */
103c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luustatic void nv21_to_yuv(uint8_t* dst, uint8_t* y, uint8_t* uv, int width) {
104c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu    if (!dst || !y || !uv) {
105c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu        return;
106c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu    }
107c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu
108cb1183d6c3c8894fa09ad3ff7952388f6e7bec94Akwasi Boateng    while ((width--) > 0) {
109c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu        uint8_t y0 = y[0];
110c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu        uint8_t v0 = uv[0];
111c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu        uint8_t u0 = *(uv+1);
112c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu        dst[0] = y0;
113c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu        dst[1] = u0;
114c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu        dst[2] = v0;
115c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu        dst += 3;
116c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu        y++;
117c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu        if(!(width % 2)) uv+=2;
118c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu    }
119c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu}
120ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu
121ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luustatic void uyvy_to_yuv(uint8_t* dst, uint32_t* src, int width) {
12276f0345d0475def0f0c6fd2da7c2b35ed8a1bb2aTyler Luu    if (!dst || !src) {
12376f0345d0475def0f0c6fd2da7c2b35ed8a1bb2aTyler Luu        return;
12476f0345d0475def0f0c6fd2da7c2b35ed8a1bb2aTyler Luu    }
12576f0345d0475def0f0c6fd2da7c2b35ed8a1bb2aTyler Luu
12676f0345d0475def0f0c6fd2da7c2b35ed8a1bb2aTyler Luu    if (width % 2) {
12776f0345d0475def0f0c6fd2da7c2b35ed8a1bb2aTyler Luu        return; // not supporting odd widths
12876f0345d0475def0f0c6fd2da7c2b35ed8a1bb2aTyler Luu    }
12976f0345d0475def0f0c6fd2da7c2b35ed8a1bb2aTyler Luu
13076f0345d0475def0f0c6fd2da7c2b35ed8a1bb2aTyler Luu    // currently, neon routine only supports multiple of 16 width
13176f0345d0475def0f0c6fd2da7c2b35ed8a1bb2aTyler Luu    if (width % 16) {
13276f0345d0475def0f0c6fd2da7c2b35ed8a1bb2aTyler Luu        while ((width-=2) >= 0) {
13376f0345d0475def0f0c6fd2da7c2b35ed8a1bb2aTyler Luu            uint8_t u0 = (src[0] >> 0) & 0xFF;
13476f0345d0475def0f0c6fd2da7c2b35ed8a1bb2aTyler Luu            uint8_t y0 = (src[0] >> 8) & 0xFF;
13576f0345d0475def0f0c6fd2da7c2b35ed8a1bb2aTyler Luu            uint8_t v0 = (src[0] >> 16) & 0xFF;
13676f0345d0475def0f0c6fd2da7c2b35ed8a1bb2aTyler Luu            uint8_t y1 = (src[0] >> 24) & 0xFF;
13776f0345d0475def0f0c6fd2da7c2b35ed8a1bb2aTyler Luu            dst[0] = y0;
13876f0345d0475def0f0c6fd2da7c2b35ed8a1bb2aTyler Luu            dst[1] = u0;
13976f0345d0475def0f0c6fd2da7c2b35ed8a1bb2aTyler Luu            dst[2] = v0;
14076f0345d0475def0f0c6fd2da7c2b35ed8a1bb2aTyler Luu            dst[3] = y1;
14176f0345d0475def0f0c6fd2da7c2b35ed8a1bb2aTyler Luu            dst[4] = u0;
14276f0345d0475def0f0c6fd2da7c2b35ed8a1bb2aTyler Luu            dst[5] = v0;
14376f0345d0475def0f0c6fd2da7c2b35ed8a1bb2aTyler Luu            dst += 6;
14476f0345d0475def0f0c6fd2da7c2b35ed8a1bb2aTyler Luu            src++;
14576f0345d0475def0f0c6fd2da7c2b35ed8a1bb2aTyler Luu        }
14676f0345d0475def0f0c6fd2da7c2b35ed8a1bb2aTyler Luu    } else {
14776f0345d0475def0f0c6fd2da7c2b35ed8a1bb2aTyler Luu        int n = width;
14876f0345d0475def0f0c6fd2da7c2b35ed8a1bb2aTyler Luu        asm volatile (
14976f0345d0475def0f0c6fd2da7c2b35ed8a1bb2aTyler Luu        "   pld [%[src], %[src_stride], lsl #2]                         \n\t"
15076f0345d0475def0f0c6fd2da7c2b35ed8a1bb2aTyler Luu        "   cmp %[n], #16                                               \n\t"
15176f0345d0475def0f0c6fd2da7c2b35ed8a1bb2aTyler Luu        "   blt 5f                                                      \n\t"
15276f0345d0475def0f0c6fd2da7c2b35ed8a1bb2aTyler Luu        "0: @ 16 pixel swap                                             \n\t"
15376f0345d0475def0f0c6fd2da7c2b35ed8a1bb2aTyler Luu        "   vld2.8  {q0, q1} , [%[src]]! @ q0 = uv q1 = y               \n\t"
15476f0345d0475def0f0c6fd2da7c2b35ed8a1bb2aTyler Luu        "   vuzp.8 q0, q2                @ d1 = u d5 = v                \n\t"
15576f0345d0475def0f0c6fd2da7c2b35ed8a1bb2aTyler Luu        "   vmov d1, d0                  @ q0 = u0u1u2..u0u1u2...       \n\t"
15676f0345d0475def0f0c6fd2da7c2b35ed8a1bb2aTyler Luu        "   vmov d5, d4                  @ q2 = v0v1v2..v0v1v2...       \n\t"
15776f0345d0475def0f0c6fd2da7c2b35ed8a1bb2aTyler Luu        "   vzip.8 d0, d1                @ q0 = u0u0u1u1u2u2...         \n\t"
15876f0345d0475def0f0c6fd2da7c2b35ed8a1bb2aTyler Luu        "   vzip.8 d4, d5                @ q2 = v0v0v1v1v2v2...         \n\t"
15976f0345d0475def0f0c6fd2da7c2b35ed8a1bb2aTyler Luu        "   vswp q0, q1                  @ now q0 = y q1 = u q2 = v     \n\t"
16076f0345d0475def0f0c6fd2da7c2b35ed8a1bb2aTyler Luu        "   vst3.8  {d0,d2,d4},[%[dst]]!                                \n\t"
16176f0345d0475def0f0c6fd2da7c2b35ed8a1bb2aTyler Luu        "   vst3.8  {d1,d3,d5},[%[dst]]!                                \n\t"
16276f0345d0475def0f0c6fd2da7c2b35ed8a1bb2aTyler Luu        "   sub %[n], %[n], #16                                         \n\t"
16376f0345d0475def0f0c6fd2da7c2b35ed8a1bb2aTyler Luu        "   cmp %[n], #16                                               \n\t"
16476f0345d0475def0f0c6fd2da7c2b35ed8a1bb2aTyler Luu        "   bge 0b                                                      \n\t"
16576f0345d0475def0f0c6fd2da7c2b35ed8a1bb2aTyler Luu        "5: @ end                                                       \n\t"
16676f0345d0475def0f0c6fd2da7c2b35ed8a1bb2aTyler Luu#ifdef NEEDS_ARM_ERRATA_754319_754320
16776f0345d0475def0f0c6fd2da7c2b35ed8a1bb2aTyler Luu        "   vmov s0,s0  @ add noop for errata item                      \n\t"
16876f0345d0475def0f0c6fd2da7c2b35ed8a1bb2aTyler Luu#endif
16976f0345d0475def0f0c6fd2da7c2b35ed8a1bb2aTyler Luu        : [dst] "+r" (dst), [src] "+r" (src), [n] "+r" (n)
17076f0345d0475def0f0c6fd2da7c2b35ed8a1bb2aTyler Luu        : [src_stride] "r" (width)
17176f0345d0475def0f0c6fd2da7c2b35ed8a1bb2aTyler Luu        : "cc", "memory", "q0", "q1", "q2"
17276f0345d0475def0f0c6fd2da7c2b35ed8a1bb2aTyler Luu        );
173ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu    }
174ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu}
175ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu
176c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luustatic void resize_nv12(Encoder_libjpeg::params* params, uint8_t* dst_buffer) {
177c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu    structConvImage o_img_ptr, i_img_ptr;
178c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu
179c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu    if (!params || !dst_buffer) {
180c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu        return;
181c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu    }
182c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu
183c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu    //input
184c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu    i_img_ptr.uWidth =  params->in_width;
185c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu    i_img_ptr.uStride =  i_img_ptr.uWidth;
186c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu    i_img_ptr.uHeight =  params->in_height;
187c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu    i_img_ptr.eFormat = IC_FORMAT_YCbCr420_lp;
188c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu    i_img_ptr.imgPtr = (uint8_t*) params->src;
189c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu    i_img_ptr.clrPtr = i_img_ptr.imgPtr + (i_img_ptr.uWidth * i_img_ptr.uHeight);
190c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu
191c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu    //ouput
192c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu    o_img_ptr.uWidth = params->out_width;
193c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu    o_img_ptr.uStride = o_img_ptr.uWidth;
194c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu    o_img_ptr.uHeight = params->out_height;
195c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu    o_img_ptr.eFormat = IC_FORMAT_YCbCr420_lp;
196c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu    o_img_ptr.imgPtr = dst_buffer;
197c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu    o_img_ptr.clrPtr = o_img_ptr.imgPtr + (o_img_ptr.uWidth * o_img_ptr.uHeight);
198c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu
199c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu    VT_resizeFrame_Video_opt2_lp(&i_img_ptr, &o_img_ptr, NULL, 0);
200c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu}
201c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu
20236e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu/* public static functions */
203c78626b15e9f29a5bcf85447ceafb17dcbf58b69Emilian Peevconst char* ExifElementsTable::degreesToExifOrientation(unsigned int degrees) {
20476f0345d0475def0f0c6fd2da7c2b35ed8a1bb2aTyler Luu    for (unsigned int i = 0; i < ARRAY_SIZE(degress_to_exif_lut); i++) {
205c78626b15e9f29a5bcf85447ceafb17dcbf58b69Emilian Peev        if (degrees == degress_to_exif_lut[i].integer) {
206c78626b15e9f29a5bcf85447ceafb17dcbf58b69Emilian Peev            return degress_to_exif_lut[i].string;
20736e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu        }
20836e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu    }
20936e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu    return NULL;
21036e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu}
21136e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu
212c11c07d676f130e6e28ab1611f4862a01a160389Tyler Luuvoid ExifElementsTable::stringToRational(const char* str, unsigned int* num, unsigned int* den) {
213c11c07d676f130e6e28ab1611f4862a01a160389Tyler Luu    int len;
214c11c07d676f130e6e28ab1611f4862a01a160389Tyler Luu    char * tempVal = NULL;
215c11c07d676f130e6e28ab1611f4862a01a160389Tyler Luu
216c11c07d676f130e6e28ab1611f4862a01a160389Tyler Luu    if (str != NULL) {
217c11c07d676f130e6e28ab1611f4862a01a160389Tyler Luu        len = strlen(str);
218c11c07d676f130e6e28ab1611f4862a01a160389Tyler Luu        tempVal = (char*) malloc( sizeof(char) * (len + 1));
219c11c07d676f130e6e28ab1611f4862a01a160389Tyler Luu    }
220c11c07d676f130e6e28ab1611f4862a01a160389Tyler Luu
221c11c07d676f130e6e28ab1611f4862a01a160389Tyler Luu    if (tempVal != NULL) {
222c11c07d676f130e6e28ab1611f4862a01a160389Tyler Luu        // convert the decimal string into a rational
223c11c07d676f130e6e28ab1611f4862a01a160389Tyler Luu        size_t den_len;
224c11c07d676f130e6e28ab1611f4862a01a160389Tyler Luu        char *ctx;
225c11c07d676f130e6e28ab1611f4862a01a160389Tyler Luu        unsigned int numerator = 0;
226c11c07d676f130e6e28ab1611f4862a01a160389Tyler Luu        unsigned int denominator = 0;
227c11c07d676f130e6e28ab1611f4862a01a160389Tyler Luu        char* temp = NULL;
228c11c07d676f130e6e28ab1611f4862a01a160389Tyler Luu
229c11c07d676f130e6e28ab1611f4862a01a160389Tyler Luu        memset(tempVal, '\0', len + 1);
230c11c07d676f130e6e28ab1611f4862a01a160389Tyler Luu        strncpy(tempVal, str, len);
231c11c07d676f130e6e28ab1611f4862a01a160389Tyler Luu        temp = strtok_r(tempVal, ".", &ctx);
232c11c07d676f130e6e28ab1611f4862a01a160389Tyler Luu
233c11c07d676f130e6e28ab1611f4862a01a160389Tyler Luu        if (temp != NULL)
234c11c07d676f130e6e28ab1611f4862a01a160389Tyler Luu            numerator = atoi(temp);
235c11c07d676f130e6e28ab1611f4862a01a160389Tyler Luu
236c11c07d676f130e6e28ab1611f4862a01a160389Tyler Luu        if (!numerator)
237c11c07d676f130e6e28ab1611f4862a01a160389Tyler Luu            numerator = 1;
238c11c07d676f130e6e28ab1611f4862a01a160389Tyler Luu
239c11c07d676f130e6e28ab1611f4862a01a160389Tyler Luu        temp = strtok_r(NULL, ".", &ctx);
240c11c07d676f130e6e28ab1611f4862a01a160389Tyler Luu        if (temp != NULL) {
241c11c07d676f130e6e28ab1611f4862a01a160389Tyler Luu            den_len = strlen(temp);
242c11c07d676f130e6e28ab1611f4862a01a160389Tyler Luu            if(HUGE_VAL == den_len ) {
243c11c07d676f130e6e28ab1611f4862a01a160389Tyler Luu                den_len = 0;
244c11c07d676f130e6e28ab1611f4862a01a160389Tyler Luu            }
245c11c07d676f130e6e28ab1611f4862a01a160389Tyler Luu
246c11c07d676f130e6e28ab1611f4862a01a160389Tyler Luu            denominator = static_cast<unsigned int>(pow(10, den_len));
247c11c07d676f130e6e28ab1611f4862a01a160389Tyler Luu            numerator = numerator * denominator + atoi(temp);
248c11c07d676f130e6e28ab1611f4862a01a160389Tyler Luu        } else {
249c11c07d676f130e6e28ab1611f4862a01a160389Tyler Luu            denominator = 1;
250c11c07d676f130e6e28ab1611f4862a01a160389Tyler Luu        }
251c11c07d676f130e6e28ab1611f4862a01a160389Tyler Luu
252c11c07d676f130e6e28ab1611f4862a01a160389Tyler Luu        free(tempVal);
253c11c07d676f130e6e28ab1611f4862a01a160389Tyler Luu
254c11c07d676f130e6e28ab1611f4862a01a160389Tyler Luu        *num = numerator;
255c11c07d676f130e6e28ab1611f4862a01a160389Tyler Luu        *den = denominator;
256c11c07d676f130e6e28ab1611f4862a01a160389Tyler Luu    }
257c11c07d676f130e6e28ab1611f4862a01a160389Tyler Luu}
258c11c07d676f130e6e28ab1611f4862a01a160389Tyler Luu
259c11c07d676f130e6e28ab1611f4862a01a160389Tyler Luubool ExifElementsTable::isAsciiTag(const char* tag) {
260c11c07d676f130e6e28ab1611f4862a01a160389Tyler Luu    // TODO(XXX): Add tags as necessary
261c11c07d676f130e6e28ab1611f4862a01a160389Tyler Luu    return (strcmp(tag, TAG_GPS_PROCESSING_METHOD) == 0);
262c11c07d676f130e6e28ab1611f4862a01a160389Tyler Luu}
263c11c07d676f130e6e28ab1611f4862a01a160389Tyler Luu
26436e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luuvoid ExifElementsTable::insertExifToJpeg(unsigned char* jpeg, size_t jpeg_size) {
26536e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu    ReadMode_t read_mode = (ReadMode_t)(READ_METADATA | READ_IMAGE);
26636e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu
26736e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu    ResetJpgfile();
26836e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu    if (ReadJpegSectionsFromBuffer(jpeg, jpeg_size, read_mode)) {
26936e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu        jpeg_opened = true;
2701e3a7ee3fced4b9723f65147ae856bba7d4e2342Angus Kong        create_EXIF(table, exif_tag_count, gps_tag_count, has_datetime_tag);
27136e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu    }
27236e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu}
27336e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu
274c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luustatus_t ExifElementsTable::insertExifThumbnailImage(const char* thumb, int len) {
275c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu    status_t ret = NO_ERROR;
276c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu
277c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu    if ((len > 0) && jpeg_opened) {
278c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu        ret = ReplaceThumbnailFromBuffer(thumb, len);
279c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu        CAMHAL_LOGDB("insertExifThumbnailImage. ReplaceThumbnail(). ret=%d", ret);
280c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu    }
281c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu
282c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu    return ret;
283c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu}
284c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu
28536e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luuvoid ExifElementsTable::saveJpeg(unsigned char* jpeg, size_t jpeg_size) {
28636e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu    if (jpeg_opened) {
28736e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu       WriteJpegToBuffer(jpeg, jpeg_size);
28836e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu       DiscardData();
28936e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu       jpeg_opened = false;
29036e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu    }
29136e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu}
29236e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu
29336e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu/* public functions */
29436e9bdd56757ff8048e08f6e52f234480c44f122Tyler LuuExifElementsTable::~ExifElementsTable() {
29536e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu    int num_elements = gps_tag_count + exif_tag_count;
29636e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu
29736e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu    for (int i = 0; i < num_elements; i++) {
29836e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu        if (table[i].Value) {
29936e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu            free(table[i].Value);
30036e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu        }
30136e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu    }
30236e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu
30336e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu    if (jpeg_opened) {
30436e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu        DiscardData();
30536e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu    }
30636e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu}
30736e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu
30836e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luustatus_t ExifElementsTable::insertElement(const char* tag, const char* value) {
309ef73bec8a83a2fd7fbb072d009382c64eb2da0eeTyler Luu    unsigned int value_length = 0;
31036e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu    status_t ret = NO_ERROR;
31136e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu
31236e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu    if (!value || !tag) {
31336e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu        return -EINVAL;
31436e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu    }
31536e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu
31636e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu    if (position >= MAX_EXIF_TAGS_SUPPORTED) {
31736e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu        CAMHAL_LOGEA("Max number of EXIF elements already inserted");
31836e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu        return NO_MEMORY;
31936e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu    }
32036e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu
321c11c07d676f130e6e28ab1611f4862a01a160389Tyler Luu    if (isAsciiTag(tag)) {
322c11c07d676f130e6e28ab1611f4862a01a160389Tyler Luu        value_length = sizeof(ExifAsciiPrefix) + strlen(value + sizeof(ExifAsciiPrefix));
323c11c07d676f130e6e28ab1611f4862a01a160389Tyler Luu    } else {
324c11c07d676f130e6e28ab1611f4862a01a160389Tyler Luu        value_length = strlen(value);
325c11c07d676f130e6e28ab1611f4862a01a160389Tyler Luu    }
32636e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu
32736e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu    if (IsGpsTag(tag)) {
32836e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu        table[position].GpsTag = TRUE;
32936e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu        table[position].Tag = GpsTagNameToValue(tag);
33036e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu        gps_tag_count++;
33136e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu    } else {
33236e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu        table[position].GpsTag = FALSE;
33336e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu        table[position].Tag = TagNameToValue(tag);
33436e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu        exif_tag_count++;
335ef73bec8a83a2fd7fbb072d009382c64eb2da0eeTyler Luu
336ef73bec8a83a2fd7fbb072d009382c64eb2da0eeTyler Luu        if (strcmp(tag, TAG_DATETIME) == 0) {
3371e3a7ee3fced4b9723f65147ae856bba7d4e2342Angus Kong            has_datetime_tag = true;
338ef73bec8a83a2fd7fbb072d009382c64eb2da0eeTyler Luu        }
33936e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu    }
34036e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu
34136e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu    table[position].DataLength = 0;
34236e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu    table[position].Value = (char*) malloc(sizeof(char) * (value_length + 1));
34336e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu
34436e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu    if (table[position].Value) {
345c11c07d676f130e6e28ab1611f4862a01a160389Tyler Luu        memcpy(table[position].Value, value, value_length + 1);
34636e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu        table[position].DataLength = value_length + 1;
34736e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu    }
34836e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu
34936e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu    position++;
35036e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu    return ret;
35136e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu}
35236e9bdd56757ff8048e08f6e52f234480c44f122Tyler Luu
353ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu/* private member functions */
354c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luusize_t Encoder_libjpeg::encode(params* input) {
355ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu    jpeg_compress_struct    cinfo;
356ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu    jpeg_error_mgr jerr;
357ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu    jpeg_destination_mgr jdest;
358c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu    uint8_t* src = NULL, *resize_src = NULL;
359ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu    uint8_t* row_tmp = NULL;
360ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu    uint8_t* row_src = NULL;
361c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu    uint8_t* row_uv = NULL; // used only for NV12
362c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu    int out_width = 0, in_width = 0;
363c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu    int out_height = 0, in_height = 0;
364c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu    int bpp = 2; // for uyvy
365d9520b9de06f01b9411307040cf245e6fc7fe361Milen Mitkov    int right_crop = 0, start_offset = 0;
366c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu
367c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu    if (!input) {
368c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu        return 0;
369c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu    }
370c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu
371c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu    out_width = input->out_width;
372c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu    in_width = input->in_width;
373c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu    out_height = input->out_height;
374c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu    in_height = input->in_height;
375d9520b9de06f01b9411307040cf245e6fc7fe361Milen Mitkov    right_crop = input->right_crop;
376d9520b9de06f01b9411307040cf245e6fc7fe361Milen Mitkov    start_offset = input->start_offset;
377c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu    src = input->src;
378c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu    input->jpeg_size = 0;
379c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu
380c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu    libjpeg_destination_mgr dest_mgr(input->dst, input->dst_size);
381c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu
382c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu    // param check...
383c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu    if ((in_width < 2) || (out_width < 2) || (in_height < 2) || (out_height < 2) ||
384c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu         (src == NULL) || (input->dst == NULL) || (input->quality < 1) || (input->src_size < 1) ||
385c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu         (input->dst_size < 1) || (input->format == NULL)) {
386c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu        goto exit;
387c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu    }
388c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu
389c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu    if (strcmp(input->format, CameraParameters::PIXEL_FORMAT_YUV420SP) == 0) {
390c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu        bpp = 1;
391c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu        if ((in_width != out_width) || (in_height != out_height)) {
392c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu            resize_src = (uint8_t*) malloc(input->dst_size);
393c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu            resize_nv12(input, resize_src);
394c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu            if (resize_src) src = resize_src;
395c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu        }
396c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu    } else if ((in_width != out_width) || (in_height != out_height)) {
397c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu        CAMHAL_LOGEB("Encoder: resizing is not supported for this format: %s", input->format);
398c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu        goto exit;
399c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu    } else if (strcmp(input->format, CameraParameters::PIXEL_FORMAT_YUV422I)) {
400c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu        // we currently only support yuv422i and yuv420sp
401c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu        CAMHAL_LOGEB("Encoder: format not supported: %s", input->format);
402c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu        goto exit;
403c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu    }
404ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu
405ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu    cinfo.err = jpeg_std_error(&jerr);
406ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu
407ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu    jpeg_create_compress(&cinfo);
408ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu
409ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu    CAMHAL_LOGDB("encoding...  \n\t"
410ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu                 "width: %d    \n\t"
411ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu                 "height:%d    \n\t"
412ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu                 "dest %p      \n\t"
413ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu                 "dest size:%d \n\t"
414ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu                 "mSrc %p",
415c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu                 out_width, out_height, input->dst,
416c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu                 input->dst_size, src);
417ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu
418ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu    cinfo.dest = &dest_mgr;
419d9520b9de06f01b9411307040cf245e6fc7fe361Milen Mitkov    cinfo.image_width = out_width - right_crop;
420c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu    cinfo.image_height = out_height;
421ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu    cinfo.input_components = 3;
422ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu    cinfo.in_color_space = JCS_YCbCr;
423ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu    cinfo.input_gamma = 1;
424ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu
425ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu    jpeg_set_defaults(&cinfo);
426c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu    jpeg_set_quality(&cinfo, input->quality, TRUE);
427ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu    cinfo.dct_method = JDCT_IFAST;
428ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu
429ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu    jpeg_start_compress(&cinfo, TRUE);
430ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu
431c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu    row_tmp = (uint8_t*)malloc(out_width * 3);
432d9520b9de06f01b9411307040cf245e6fc7fe361Milen Mitkov    row_src = src + start_offset;
433c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu    row_uv = src + out_width * out_height * bpp;
434ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu
4358e52e3bcc31f65a699c25557cf3026d324e631b4Tyler Luu    while ((cinfo.next_scanline < cinfo.image_height) && !mCancelEncoding) {
436ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu        JSAMPROW row[1];    /* pointer to JSAMPLE row[s] */
437ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu
438c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu        // convert input yuv format to yuv444
439c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu        if (strcmp(input->format, CameraParameters::PIXEL_FORMAT_YUV420SP) == 0) {
440d9520b9de06f01b9411307040cf245e6fc7fe361Milen Mitkov            nv21_to_yuv(row_tmp, row_src, row_uv, out_width - right_crop);
441c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu        } else {
442d9520b9de06f01b9411307040cf245e6fc7fe361Milen Mitkov            uyvy_to_yuv(row_tmp, (uint32_t*)row_src, out_width - right_crop);
443c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu        }
444c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu
445ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu        row[0] = row_tmp;
446ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu        jpeg_write_scanlines(&cinfo, row, 1);
447c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu        row_src = row_src + out_width*bpp;
448c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu
449c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu        // move uv row if input format needs it
450c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu        if (strcmp(input->format, CameraParameters::PIXEL_FORMAT_YUV420SP) == 0) {
451c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu            if (!(cinfo.next_scanline % 2))
452c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu                row_uv = row_uv +  out_width * bpp;
453c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu        }
454ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu    }
455ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu
4568e52e3bcc31f65a699c25557cf3026d324e631b4Tyler Luu    // no need to finish encoding routine if we are prematurely stopping
4578e52e3bcc31f65a699c25557cf3026d324e631b4Tyler Luu    // we will end up crashing in dest_mgr since data is incomplete
4588e52e3bcc31f65a699c25557cf3026d324e631b4Tyler Luu    if (!mCancelEncoding)
4598e52e3bcc31f65a699c25557cf3026d324e631b4Tyler Luu        jpeg_finish_compress(&cinfo);
460ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu    jpeg_destroy_compress(&cinfo);
461ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu
462c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu    if (resize_src) free(resize_src);
463cb1183d6c3c8894fa09ad3ff7952388f6e7bec94Akwasi Boateng    if (row_tmp) free(row_tmp);
464c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu
465c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu exit:
466c160a1f85c70e49a7613d774e2d99035f3cb4851Tyler Luu    input->jpeg_size = dest_mgr.jpegsize;
467ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu    return dest_mgr.jpegsize;
468ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu}
469ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu
470ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cfTyler Luu} // namespace android
471