Encoder_libjpeg.cpp revision ee6bb64f60c228d711dc1d6875d8f4b0ed88b6cf
1/*
2 * Copyright (C) Texas Instruments - http://www.ti.com/
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17/**
18* @file Encoder_libjpeg.cpp
19*
20* This file encodes a YUV422I buffer to a jpeg
21* TODO(XXX): Need to support formats other than yuv422i
22*            Change interface to pre/post-proc algo framework
23*
24*/
25
26#define LOG_TAG "CameraHAL"
27
28#include "CameraHal.h"
29#include "Encoder_libjpeg.h"
30
31#include <stdlib.h>
32#include <unistd.h>
33#include <sys/types.h>
34#include <sys/stat.h>
35#include <fcntl.h>
36#include <stdio.h>
37#include <errno.h>
38
39extern "C" {
40    #include "jpeglib.h"
41    #include "jerror.h"
42}
43
44namespace android {
45
46struct libjpeg_destination_mgr : jpeg_destination_mgr {
47    libjpeg_destination_mgr(uint8_t* input, int size);
48
49    uint8_t* buf;
50    int bufsize;
51    size_t jpegsize;
52};
53
54static void libjpeg_init_destination (j_compress_ptr cinfo) {
55    libjpeg_destination_mgr* dest = (libjpeg_destination_mgr*)cinfo->dest;
56
57    dest->next_output_byte = dest->buf;
58    dest->free_in_buffer = dest->bufsize;
59    dest->jpegsize = 0;
60}
61
62static boolean libjpeg_empty_output_buffer(j_compress_ptr cinfo) {
63    libjpeg_destination_mgr* dest = (libjpeg_destination_mgr*)cinfo->dest;
64
65    dest->next_output_byte = dest->buf;
66    dest->free_in_buffer = dest->bufsize;
67    return TRUE; // ?
68}
69
70static void libjpeg_term_destination (j_compress_ptr cinfo) {
71    libjpeg_destination_mgr* dest = (libjpeg_destination_mgr*)cinfo->dest;
72    dest->jpegsize = dest->bufsize - dest->free_in_buffer;
73}
74
75libjpeg_destination_mgr::libjpeg_destination_mgr(uint8_t* input, int size) {
76    this->init_destination = libjpeg_init_destination;
77    this->empty_output_buffer = libjpeg_empty_output_buffer;
78    this->term_destination = libjpeg_term_destination;
79
80    this->buf = input;
81    this->bufsize = size;
82}
83
84/* private static functions */
85
86static void uyvy_to_yuv(uint8_t* dst, uint32_t* src, int width) {
87    // TODO(XXX): optimize later
88    while ((width-=2) >= 0) {
89        uint8_t u0 = (src[0] >> 0) & 0xFF;
90        uint8_t y0 = (src[0] >> 8) & 0xFF;
91        uint8_t v0 = (src[0] >> 16) & 0xFF;
92        uint8_t y1 = (src[0] >> 24) & 0xFF;
93        dst[0] = y0;
94        dst[1] = u0;
95        dst[2] = v0;
96        dst[3] = y1;
97        dst[4] = u0;
98        dst[5] = v0;
99        dst += 6;
100        src++;
101    }
102}
103
104/* private member functions */
105size_t Encoder_libjpeg::encode() {
106    jpeg_compress_struct    cinfo;
107    jpeg_error_mgr jerr;
108    jpeg_destination_mgr jdest;
109    uint8_t* row_tmp = NULL;
110    uint8_t* row_src = NULL;
111    int bpp = 2; // TODO(XXX): hardcoded for uyvy
112
113    cinfo.err = jpeg_std_error(&jerr);
114
115    jpeg_create_compress(&cinfo);
116
117    libjpeg_destination_mgr dest_mgr(mDest, mDestSize);
118
119    CAMHAL_LOGDB("encoding...  \n\t"
120                 "width: %d    \n\t"
121                 "height:%d    \n\t"
122                 "dest %p      \n\t"
123                 "dest size:%d \n\t"
124                 "mSrc %p",
125                 mWidth, mHeight, mDest, mDestSize, mSrc);
126
127    cinfo.dest = &dest_mgr;
128    cinfo.image_width = mWidth;
129    cinfo.image_height = mHeight;
130    cinfo.input_components = 3;
131    cinfo.in_color_space = JCS_YCbCr;
132    cinfo.input_gamma = 1;
133
134    jpeg_set_defaults(&cinfo);
135    jpeg_set_quality(&cinfo, mQuality, TRUE);
136    cinfo.dct_method = JDCT_IFAST;
137
138    jpeg_start_compress(&cinfo, TRUE);
139
140    row_tmp = (uint8_t*)malloc(mWidth * 3);
141    row_src = mSrc;
142
143    while (cinfo.next_scanline < cinfo.image_height) {
144        JSAMPROW row[1];    /* pointer to JSAMPLE row[s] */
145
146        uyvy_to_yuv(row_tmp, (uint32_t*)row_src, mWidth);
147        row[0] = row_tmp;
148        jpeg_write_scanlines(&cinfo, row, 1);
149        row_src = row_src + mWidth*bpp;
150    }
151
152    jpeg_finish_compress(&cinfo);
153    jpeg_destroy_compress(&cinfo);
154
155    return dest_mgr.jpegsize;
156}
157
158} // namespace android
159