author | brian.zhu <brian.zhu@amlogic.com> | 2014-01-27 09:28:54 (GMT) |
---|---|---|
committer | Sandy lUo <sandy.luo@amlogic.com> | 2014-02-17 11:48:40 (GMT) |
commit | a63700c49b6dd9aada1fa6d6460d2dd8e1e59634 (patch) | |
tree | 31eb3cf03f35eab3982a96c100c2863f7127ddcb | |
parent | 66e38b28cd5abccf7cd62fa5d8b0eb6be1d40f67 (diff) | |
download | camera-a63700c49b6dd9aada1fa6d6460d2dd8e1e59634.zip camera-a63700c49b6dd9aada1fa6d6460d2dd8e1e59634.tar.gz camera-a63700c49b6dd9aada1fa6d6460d2dd8e1e59634.tar.bz2 |
PD #86949 add hw jpeg encode
-rwxr-xr-x | Android.mk | 16 | ||||
-rwxr-xr-x | AppCallbackNotifier.cpp | 32 | ||||
-rwxr-xr-x | Encoder_libjpeg.cpp | 53 | ||||
-rwxr-xr-x | inc/Encoder_libjpeg.h | 7 | ||||
-rwxr-xr-x | inc/jpegenc_hw/jpegenc.h | 88 | ||||
-rwxr-xr-x | jpegenc_hw/jpegenc.cpp | 374 |
6 files changed, 535 insertions, 35 deletions
@@ -35,6 +35,9 @@ CAMERA_HAL_VERTURAL_CAMERA_SRC:= \ CAMERA_HAL_JPEG_SRC:=\ mjpeg/jpegdec.c \ mjpeg/colorspaces.c + +CAMERA_HAL_HW_JPEGENC_SRC:=\ + jpegenc_hw/jpegenc.cpp include $(CLEAR_VARS) @@ -45,6 +48,10 @@ LOCAL_SRC_FILES:= \ $(CAMERA_UTILS_SRC) \ $(CAMERA_HAL_JPEG_SRC) +ifeq ($(BOARD_HAVE_HW_JPEGENC),true) +LOCAL_SRC_FILES += $(CAMERA_HAL_HW_JPEGENC_SRC) +endif + ifneq (,$(wildcard hardware/amlogic/gralloc)) GRALLOC_DIR := hardware/amlogic/gralloc else @@ -65,6 +72,11 @@ LOCAL_C_INCLUDES += \ $(GRALLOC_DIR) \ system/core/include/utils +ifeq ($(BOARD_HAVE_HW_JPEGENC),true) +LOCAL_C_INCLUDES += \ + $(LOCAL_PATH)/inc/jpegenc_hw/ +endif + LOCAL_C_INCLUDES_VIRCAM := \ $(LOCAL_PATH)/vircam/inc @@ -153,6 +165,10 @@ ifeq ($(BOARD_HAVE_VIRTUAL_CAMERA),true) $(LOCAL_C_INCLUDES_VIRCAM) endif +ifeq ($(BOARD_HAVE_HW_JPEGENC),true) + LOCAL_CFLAGS += -DAMLOGIC_HW_JPEGENC +endif + LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw LOCAL_MODULE:= camera.amlogic LOCAL_MODULE_TAGS:= optional diff --git a/AppCallbackNotifier.cpp b/AppCallbackNotifier.cpp index 197c604..886fa1c 100755 --- a/AppCallbackNotifier.cpp +++ b/AppCallbackNotifier.cpp @@ -921,37 +921,6 @@ void AppCallbackNotifier::notifyFrame() main_jpeg->format = CameraParameters::PIXEL_FORMAT_YUV420SP; } -// disable thumbnail for now. preview was stopped and mPreviewBufs was -// cleared, so this won't work. -#if 0 - tn_width = parameters.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH); - tn_height = parameters.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT); - - if ((tn_width > 0) && (tn_height > 0)) { - tn_jpeg = (Encoder_libjpeg::params*) - malloc(sizeof(Encoder_libjpeg::params)); - // if malloc fails just keep going and encode main jpeg - if (!tn_jpeg) { - tn_jpeg = NULL; - } - } - - if (tn_jpeg) { - int width, height; - parameters.getPreviewSize(&width,&height); - current_snapshot = (mPreviewBufCount + MAX_BUFFERS - 1) % MAX_BUFFERS; - tn_jpeg->src = (uint8_t*) mPreviewBufs[current_snapshot]; - tn_jpeg->src_size = mPreviewMemory->size / MAX_BUFFERS; - tn_jpeg->dst = (uint8_t*) malloc(tn_jpeg->src_size); - tn_jpeg->dst_size = tn_jpeg->src_size; - tn_jpeg->quality = tn_quality; - tn_jpeg->in_width = width; - tn_jpeg->in_height = height; - tn_jpeg->out_width = tn_width; - tn_jpeg->out_height = tn_height; - tn_jpeg->format = CameraParameters::PIXEL_FORMAT_YUV420SP;; - } -#else tn_width = parameters.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH); tn_height = parameters.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT); @@ -993,7 +962,6 @@ void AppCallbackNotifier::notifyFrame() CAMHAL_LOGEA("Error! Thumbnail Jpeg encoder malloc memory fail!"); } } -#endif CAMHAL_LOGDA("IMAGE_FRAME ENCODE_RAW.."); sp<Encoder_libjpeg> encoder = new Encoder_libjpeg(main_jpeg, diff --git a/Encoder_libjpeg.cpp b/Encoder_libjpeg.cpp index 8eaf885..8b57aca 100755 --- a/Encoder_libjpeg.cpp +++ b/Encoder_libjpeg.cpp @@ -43,6 +43,7 @@ extern "C" { #include "jerror.h" } + #define ARRAY_SIZE(array) (sizeof((array)) / sizeof((array)[0])) namespace android { @@ -50,7 +51,6 @@ struct string_pair { const char* string1; const char* string2; }; - static string_pair degress_to_exif_lut [] = { // degrees, exif_orientation {"0", "1"}, @@ -443,6 +443,7 @@ size_t Encoder_libjpeg::encode(params* input) { int out_width = 0, in_width = 0; int out_height = 0, in_height = 0; int bpp = 2; // for uyvy + Encoder_libjpeg::format informat = Encoder_libjpeg::YUV422I; if (!input) { @@ -455,9 +456,16 @@ size_t Encoder_libjpeg::encode(params* input) { in_height = input->in_height; src = input->src; input->jpeg_size = 0; - libjpeg_destination_mgr dest_mgr(input->dst, input->dst_size); +#ifdef AMLOGIC_HW_JPEGENC + if((out_width == in_width)&&(out_height == in_height) + &&(out_height%16 == 0)&&(out_width%16 == 0)){ + goto HW_CASE; + } +SOFTWARE_ENC: +#endif + // param check... if ((in_width < 2) || (out_width < 2) || (in_height < 2) || (out_height < 2) || (src == NULL) || (input->dst == NULL) || (input->quality < 1) || (input->src_size < 1) || @@ -500,7 +508,7 @@ size_t Encoder_libjpeg::encode(params* input) { jpeg_create_compress(&cinfo); - CAMHAL_LOGDB("encoding... \n\t" + CAMHAL_LOGDB("software encoding... \n\t" "width: %d \n\t" "height:%d \n\t" "dest %p \n\t" @@ -569,6 +577,45 @@ size_t Encoder_libjpeg::encode(params* input) { exit: input->jpeg_size = dest_mgr.jpegsize; return dest_mgr.jpegsize; + +#ifdef AMLOGIC_HW_JPEGENC +HW_CASE: + size_t jpeg_size = 0; + memset(&hw_info,0, sizeof(hw_info)); + if (strcmp(input->format, CameraParameters::PIXEL_FORMAT_YUV420SP) == 0) { + hw_info.in_format = FMT_NV21; + } else if (strcmp(input->format, CameraProperties::PIXEL_FORMAT_RGB24) == 0) { + hw_info.in_format = FMT_RGB888; + } else if(strcmp(input->format, CameraParameters::PIXEL_FORMAT_YUV422I)== 0){ + hw_info.in_format = FMT_YUV422_SINGLE; + } else{ + hw_info.in_format = FMT_NV21; + } + hw_info.fd = -1; + hw_info.width = out_width; + hw_info.height = out_height; + hw_info.src = input->src; + hw_info.src_size= input->src_size; + hw_info.dst= input->dst; + hw_info.dst_size= input->dst_size; + hw_info.quality = input->quality; + + CAMHAL_LOGDB("hardware encoding... \n\t" + "width: %d \n\t" + "height:%d \n\t" + "dest %p \n\t" + "dest size:%d \n\t" + "mSrc %p", + out_width, out_height, input->dst, + input->dst_size, input->src); + jpeg_size = hw_encode(&hw_info); + if(jpeg_size<=0){ + CAMHAL_LOGEA("HW Encode fail, re-encode with software."); + goto SOFTWARE_ENC; + } + input->jpeg_size = jpeg_size; + return jpeg_size; +#endif } } // namespace android diff --git a/inc/Encoder_libjpeg.h b/inc/Encoder_libjpeg.h index 5075f41..42780e5 100755 --- a/inc/Encoder_libjpeg.h +++ b/inc/Encoder_libjpeg.h @@ -27,6 +27,10 @@ #include <utils/threads.h> #include <utils/RefBase.h> +#ifdef AMLOGIC_HW_JPEGENC +#include "jpegenc.h" +#endif + extern "C" { #include "jhead.h" } @@ -174,6 +178,9 @@ class Encoder_libjpeg : public Thread { sp<Encoder_libjpeg> mThumb; size_t encode(params*); +#ifdef AMLOGIC_HW_JPEGENC + hw_jpegenc_t hw_info; +#endif }; } diff --git a/inc/jpegenc_hw/jpegenc.h b/inc/jpegenc_hw/jpegenc.h new file mode 100755 index 0000000..f408a1f --- a/dev/null +++ b/inc/jpegenc_hw/jpegenc.h @@ -0,0 +1,88 @@ +#ifndef AML_JPEG_ENCODER_M8_
+#define AML_JPEG_ENCODER_M8_
+
+#define JPEGENC_IOC_MAGIC 'E'
+
+#define JPEGENC_IOC_GET_DEVINFO _IOW(JPEGENC_IOC_MAGIC, 0xf0, unsigned int)
+
+#define JPEGENC_IOC_GET_ADDR _IOW(JPEGENC_IOC_MAGIC, 0x00, unsigned int)
+#define JPEGENC_IOC_INPUT_UPDATE _IOW(JPEGENC_IOC_MAGIC, 0x01, unsigned int)
+#define JPEGENC_IOC_GET_STATUS _IOW(JPEGENC_IOC_MAGIC, 0x02, unsigned int)
+#define JPEGENC_IOC_NEW_CMD _IOW(JPEGENC_IOC_MAGIC, 0x03, unsigned int)
+#define JPEGENC_IOC_GET_STAGE _IOW(JPEGENC_IOC_MAGIC, 0x04, unsigned int)
+#define JPEGENC_IOC_GET_OUTPUT_SIZE _IOW(JPEGENC_IOC_MAGIC, 0x05, unsigned int)
+#define JPEGENC_IOC_SET_QUALITY _IOW(JPEGENC_IOC_MAGIC, 0x06, unsigned int)
+#define JPEGENC_IOC_SET_ENCODER_WIDTH _IOW(JPEGENC_IOC_MAGIC, 0x07, unsigned int)
+#define JPEGENC_IOC_SET_ENCODER_HEIGHT _IOW(JPEGENC_IOC_MAGIC, 0x08, unsigned int)
+#define JPEGENC_IOC_CONFIG_INIT _IOW(JPEGENC_IOC_MAGIC, 0x09, unsigned int)
+#define JPEGENC_IOC_FLUSH_CACHE _IOW(JPEGENC_IOC_MAGIC, 0x0a, unsigned int)
+#define JPEGENC_IOC_FLUSH_DMA _IOW(JPEGENC_IOC_MAGIC, 0x0b, unsigned int)
+#define JPEGENC_IOC_GET_BUFFINFO _IOW(JPEGENC_IOC_MAGIC, 0x0c, unsigned int)
+#define JPEGENC_IOC_INPUT_FORMAT _IOW(JPEGENC_IOC_MAGIC, 0x0d, unsigned int)
+#define JPEGENC_IOC_SEL_QUANT_TABLE _IOW(JPEGENC_IOC_MAGIC, 0x0e, unsigned int)
+#define JPEGENC_IOC_SET_EXT_QUANT_TABLE _IOW(JPEGENC_IOC_MAGIC, 0x0f, unsigned int)
+
+//---------------------------------------------------
+// ENCODER_STATUS define
+//---------------------------------------------------
+#define ENCODER_IDLE 0
+#define ENCODER_START 1
+//#define ENCODER_SOS_HEADER 2
+#define ENCODER_MCU 3
+#define ENCODER_DONE 4
+
+
+#define JPEGENC_BUFFER_INPUT 0
+#define JPEGENC_BUFFER_OUTPUT 1
+
+typedef enum{
+ LOCAL_BUFF = 0,
+ CANVAS_BUFF,
+ PHYSICAL_BUFF,
+ MAX_BUFF_TYPE
+}jpegenc_mem_type;
+
+typedef enum{
+ FMT_YUV422_SINGLE = 0,
+ FMT_YUV444_SINGLE,
+ FMT_NV21,
+ FMT_NV12,
+ FMT_YUV420,
+ FMT_YUV444_PLANE,
+ FMT_RGB888,
+ FMT_RGB888_PLANE,
+ FMT_RGB565,
+ FMT_RGBA8888,
+ MAX_FRAME_FMT
+}jpegenc_frame_fmt;
+
+#define ENCODER_PATH "/dev/jpegenc"
+
+typedef struct{
+ unsigned char* addr;
+ unsigned size;
+}jpegenc_buff_t;
+
+typedef struct hw_jpegenc_s {
+ uint8_t* src;
+ unsigned src_size;
+ uint8_t* dst;
+ unsigned dst_size;
+ int quality;
+ int qtbl_id;
+ unsigned width;
+ unsigned height;
+ int bpp;
+ jpegenc_mem_type type;
+ jpegenc_frame_fmt in_format;
+ jpegenc_frame_fmt out_format;
+ size_t jpeg_size;
+
+ int fd;
+ jpegenc_buff_t mmap_buff;
+ jpegenc_buff_t input_buf;
+ jpegenc_buff_t output_buf;
+ }hw_jpegenc_t;
+
+extern size_t hw_encode(hw_jpegenc_t* hw_info);
+#endif
\ No newline at end of file diff --git a/jpegenc_hw/jpegenc.cpp b/jpegenc_hw/jpegenc.cpp new file mode 100755 index 0000000..e9bb535 --- a/dev/null +++ b/jpegenc_hw/jpegenc.cpp @@ -0,0 +1,374 @@ +/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+ #define LOG_TAG "HW_JPEGENC"
+
+#include "CameraHal.h"
+
+#include <signal.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/mman.h>
+
+#include <stdio.h>
+#include <assert.h>
+#include <limits.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sched.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/poll.h>
+
+#include "jpegenc.h"
+
+#define ENCODE_DONE_TIMEOUT 5000
+
+//#define DEBUG_TIME
+#ifdef DEBUG_TIME
+static struct timeval start_test, end_test;
+#endif
+
+static int RGBX32_To_RGB24Plane_NEON(unsigned char *src, unsigned char *dest, int width, int height)
+{
+ unsigned char *R;
+ unsigned char *G;
+ unsigned char *B;
+ int canvas_w = ((width+31)>>5)<<5;
+ int i, j;
+ int aligned = canvas_w - width;
+
+ if( !src || !dest )
+ return -1;
+
+ R = dest;
+ G = R + canvas_w * height;
+ B = G + canvas_w * height;
+
+ for( i = 0; i < height; i += 1 ){
+ for( j = 0; j < width; j += 8 ){
+ asm volatile (
+ "vld4.8 {d0, d1, d2, d3}, [%[src]]! \n" // load 8 more ABGR pixels.
+ "vst1.8 {d0}, [%[R]]! \n" // store R.
+ "vst1.8 {d1}, [%[G]]! \n" // store G.
+ "vst1.8 {d2}, [%[B]]! \n" // store B.
+
+ : [src] "+r" (src), [R] "+r" (R),
+ [G] "+r" (G), [B] "+r" (B)
+ :
+ : "cc", "memory", "d0", "d1", "d2", "d3"
+ );
+ }
+ if(aligned){
+ R+=aligned;
+ G+=aligned;
+ B+=aligned;
+ }
+ }
+ return canvas_w*height*3;
+}
+
+static int RGB24_To_RGB24Plane_NEON(unsigned char *src, unsigned char *dest, int width, int height)
+{
+ unsigned char *R;
+ unsigned char *G;
+ unsigned char *B;
+ int i, j;
+ int canvas_w = ((width+31)>>5)<<5;
+ int aligned = canvas_w - width;
+
+ if( !src || !dest )
+ return -1;
+
+#ifdef DEBUG_TIME
+ unsigned total_time = 0;
+ struct timeval start_test1, end_test1;
+ gettimeofday(&start_test1, NULL);
+#endif
+ R = dest;
+ G = R + canvas_w * height;
+ B = G + canvas_w * height;
+
+ for( i = 0; i < height; i += 1 ){
+ for( j = 0; j < width; j += 8 ){
+ asm volatile (
+ "vld3.8 {d0, d1, d2}, [%[src]]! \n" // load 8 more BGR pixels.
+ "vst1.8 {d0}, [%[R]]! \n" // store R.
+ "vst1.8 {d1}, [%[G]]! \n" // store G.
+ "vst1.8 {d2}, [%[B]]! \n" // store B.
+
+ : [src] "+r" (src), [R] "+r" (R),
+ [G] "+r" (G), [B] "+r" (B)
+ :
+ : "cc", "memory", "d0", "d1", "d2"
+ );
+ }
+ if(aligned){
+ R+=aligned;
+ G+=aligned;
+ B+=aligned;
+ }
+ }
+#ifdef DEBUG_TIME
+ gettimeofday(&end_test1, NULL);
+ total_time = (end_test1.tv_sec - start_test1.tv_sec)*1000000 + end_test1.tv_usec -start_test1.tv_usec;
+ ALOGD("RGB24_To_RGB24Plane_NEON: need time: %d us",total_time);
+#endif
+ return canvas_w*height*3;
+}
+
+static int encode_poll(int fd, int timeout)
+{
+ struct pollfd poll_fd[1];
+ poll_fd[0].fd = fd;
+ poll_fd[0].events = POLLIN |POLLERR;
+ return poll(poll_fd, 1, timeout);
+}
+
+static unsigned copy_to_local(hw_jpegenc_t* hw_info)
+{
+ unsigned offset = 0;
+ int bytes_per_line = 0, active = 0;;
+ unsigned i = 0;
+ unsigned total_size = 0;
+ unsigned char* src = NULL;
+ unsigned char* dst = NULL;
+ int plane_num = 1;
+
+ if((hw_info->bpp !=12)&&(hw_info->in_format != FMT_YUV444_PLANE)&&(hw_info->in_format != FMT_RGB888_PLANE))
+ bytes_per_line = hw_info->width*hw_info->bpp/8;
+ else
+ bytes_per_line = hw_info->width;
+
+ if((hw_info->in_format == FMT_YUV420)||(hw_info->in_format == FMT_YUV444_PLANE)||(hw_info->in_format == FMT_RGB888_PLANE))
+ plane_num = 3;
+ else if ((hw_info->in_format == FMT_NV12)||(hw_info->in_format == FMT_NV21))
+ plane_num = 2;
+
+ active = bytes_per_line;
+
+ if(hw_info->in_format == FMT_YUV420)
+ bytes_per_line = ((bytes_per_line+63)>>6)<<6;
+ else if((hw_info->in_format == FMT_NV12)||(hw_info->in_format == FMT_NV21)||(hw_info->in_format == FMT_RGB888)
+ ||(hw_info->in_format == FMT_YUV422_SINGLE)||(hw_info->in_format == FMT_YUV444_SINGLE)||(hw_info->in_format == FMT_YUV444_PLANE)
+ ||(hw_info->in_format == FMT_RGB888_PLANE))
+ bytes_per_line = ((bytes_per_line+31)>>5)<<5;
+
+ src = (unsigned char*)hw_info->src;
+ dst = hw_info->input_buf.addr;
+ if(bytes_per_line != active){
+ for(i =0; i<hw_info->height; i++){
+ memcpy(dst, src,active);
+ dst+=bytes_per_line;
+ src+=active;
+ }
+ }else{
+ memcpy(dst, src,hw_info->height*bytes_per_line);
+ }
+
+ if(plane_num == 2){
+ offset = hw_info->height*bytes_per_line;
+ src = (unsigned char*)(hw_info->src + hw_info->height*active);
+ dst = (unsigned char*)(hw_info->input_buf.addr+offset);
+ if(bytes_per_line != active){
+ for(i =0; i<hw_info->height/2; i++){
+ memcpy(dst, src,active);
+ dst+=bytes_per_line;
+ src+=active;
+ }
+ }else{
+ memcpy(dst, src,hw_info->height*bytes_per_line/2);
+ }
+ }else if(plane_num == 3){
+ unsigned temp_active = ((hw_info->in_format == FMT_YUV444_PLANE)||(hw_info->in_format == FMT_RGB888_PLANE))?active:active/2;
+ unsigned temp_h = ((hw_info->in_format == FMT_YUV444_PLANE)||(hw_info->in_format == FMT_RGB888_PLANE))?hw_info->height:hw_info->height/2;
+ unsigned temp_bytes = ((hw_info->in_format == FMT_YUV444_PLANE)||(hw_info->in_format == FMT_RGB888_PLANE))?bytes_per_line:bytes_per_line/2;
+ offset = hw_info->height*bytes_per_line;
+ src = (unsigned char*)(hw_info->src + hw_info->height*active);
+ dst = (unsigned char*)(hw_info->input_buf.addr+offset);
+ if(bytes_per_line != active){
+ for(i =0; i<temp_h; i++){
+ memcpy(dst, src,temp_active);
+ dst+=temp_bytes;
+ src+=temp_active;
+ }
+ }else{
+ memcpy(dst, src,temp_bytes*temp_h);
+ }
+ offset = temp_h*temp_bytes+hw_info->height*bytes_per_line;
+ src = (unsigned char*)(hw_info->src + hw_info->height*active +temp_h*temp_active);
+ dst = (unsigned char*)(hw_info->input_buf.addr+offset);
+ if(bytes_per_line != active){
+ for(i =0; i<temp_h; i++){
+ memcpy(dst, src,temp_active);
+ dst+=temp_bytes;
+ src+=temp_active;
+ }
+ }else{
+ memcpy(dst, src,temp_bytes*temp_h);
+ }
+ }
+ if((hw_info->bpp !=12)&&(hw_info->in_format != FMT_YUV444_PLANE)&&(hw_info->in_format != FMT_RGB888_PLANE))
+ total_size = bytes_per_line*hw_info->height;
+ else
+ total_size = bytes_per_line*hw_info->height*hw_info->bpp/8;
+ return total_size;
+}
+
+static size_t start_encoder(hw_jpegenc_t* hw_info)
+{
+ int i;
+ int bpp;
+ unsigned size = 0;
+ unsigned cmd[7] , status;
+ unsigned in_format = hw_info->in_format;
+ if(hw_info->type == LOCAL_BUFF){
+ if((hw_info->in_format != FMT_RGB888)&&(hw_info->in_format != FMT_RGBA8888)){
+ cmd[5] = copy_to_local(hw_info);
+ }else if(hw_info->in_format == FMT_RGB888){
+ cmd[5] = RGB24_To_RGB24Plane_NEON(hw_info->src, hw_info->input_buf.addr, hw_info->width, hw_info->height);
+ in_format = FMT_RGB888_PLANE;
+ }else{
+ cmd[5] = RGBX32_To_RGB24Plane_NEON(hw_info->src, hw_info->input_buf.addr, hw_info->width, hw_info->height);
+ in_format = FMT_RGB888_PLANE;
+ }
+ }else{
+ cmd[5] = hw_info->width*hw_info->height*hw_info->bpp/8;
+ }
+
+ cmd[0] = hw_info->type; //input buffer type
+ cmd[1] = in_format;
+ cmd[2] = hw_info->out_format;
+ cmd[3] = (unsigned)hw_info->input_buf.addr;
+ cmd[4] = 0;
+ //cmd[5] = hw_info->width*hw_info->height*bpp/8;
+ cmd[6] = 1;
+
+ ioctl(hw_info->fd, JPEGENC_IOC_NEW_CMD, cmd);
+ if(encode_poll(hw_info->fd, ENCODE_DONE_TIMEOUT)<=0){
+ ALOGE("hw_encode: poll fail");
+ return 0;
+ }
+
+ ioctl(hw_info->fd, JPEGENC_IOC_GET_STAGE, &status);
+ if(status == ENCODER_DONE){
+ ioctl(hw_info->fd, JPEGENC_IOC_GET_OUTPUT_SIZE, &size);
+ if((size < hw_info->output_buf.size)&&(size>0)&&(size<=hw_info->dst_size)){
+ cmd[0] = JPEGENC_BUFFER_OUTPUT;
+ cmd[1] = 0 ;
+ cmd[2] = size ;
+ ioctl(hw_info->fd, JPEGENC_IOC_FLUSH_DMA ,cmd);
+ memcpy(hw_info->dst,hw_info->output_buf.addr,size);
+ ALOGV("hw_encode: done size: %d ",size);
+ }else{
+ ALOGE("hw_encode: output buffer size error: bitstream buffer size: %d, jpeg size: %d, output buffer size: %d",hw_info->output_buf.size, size, hw_info->dst_size);
+ size = 0;
+ }
+ }
+ return size;
+}
+
+size_t hw_encode(hw_jpegenc_t* hw_info)
+{
+ unsigned buff_info[5];
+ int ret;
+ unsigned encoder_width = hw_info->width;
+ unsigned encoder_height = hw_info->height;
+
+#ifdef DEBUG_TIME
+ unsigned total_time = 0;
+ gettimeofday(&start_test, NULL);
+#endif
+ hw_info->jpeg_size = 0;
+ hw_info->fd = open(ENCODER_PATH, O_RDWR);
+ if(hw_info->fd < 0){
+ ALOGD("hw_encode open device fail");
+ goto EXIT;
+ }
+
+ memset(buff_info,0,sizeof(buff_info));
+ ret = ioctl(hw_info->fd, JPEGENC_IOC_GET_BUFFINFO,&buff_info[0]);
+ if((ret)||(buff_info[0]==0)){
+ ALOGE("hw_encode -- no buffer information!");
+ goto EXIT;
+ }
+ hw_info->mmap_buff.addr = (unsigned char*)mmap(0,buff_info[0], PROT_READ|PROT_WRITE , MAP_SHARED ,hw_info->fd, 0);
+ if (hw_info->mmap_buff.addr == MAP_FAILED) {
+ ALOGE("hw_encode Error: failed to map framebuffer device to memory.\n");
+ goto EXIT;
+ }
+
+ hw_info->mmap_buff.size = buff_info[0];
+ hw_info->input_buf.addr = hw_info->mmap_buff.addr+buff_info[1];
+ hw_info->input_buf.size = buff_info[3]-buff_info[1];
+ hw_info->output_buf.addr = hw_info->mmap_buff.addr +buff_info[3];
+ hw_info->output_buf.size = buff_info[4];
+
+ hw_info->qtbl_id = 0;
+
+ switch(hw_info->in_format){
+ case FMT_NV21:
+ hw_info->bpp = 12;
+ break;
+ case FMT_RGB888:
+ hw_info->bpp = 24;
+ break;
+ case FMT_YUV422_SINGLE:
+ hw_info->bpp = 16;
+ break;
+ case FMT_YUV444_PLANE:
+ case FMT_RGB888_PLANE:
+ hw_info->bpp = 24;
+ break;
+ default:
+ hw_info->bpp = 12;
+ }
+
+ ioctl(hw_info->fd, JPEGENC_IOC_SET_ENCODER_WIDTH ,&encoder_width);
+ ioctl(hw_info->fd, JPEGENC_IOC_SET_ENCODER_HEIGHT ,&encoder_height);
+
+ if((hw_info->width!= encoder_width)||(hw_info->height!= encoder_height)){
+ ALOGE("hw_encode: set encode size fail. set as %dx%d, but max size is %dx%d.",hw_info->width,hw_info->height,encoder_width,encoder_height);
+ goto EXIT;
+ }
+
+ ioctl(hw_info->fd, JPEGENC_IOC_SET_QUALITY ,&hw_info->quality);
+ ioctl(hw_info->fd, JPEGENC_IOC_SEL_QUANT_TABLE ,&hw_info->qtbl_id);
+ //ioctl(hw_info->fd, JPEGENC_IOC_SET_EXT_QUANT_TABLE ,NULL);
+
+ ioctl(hw_info->fd, JPEGENC_IOC_CONFIG_INIT,NULL);
+
+ hw_info->type = LOCAL_BUFF;
+ hw_info->out_format = FMT_YUV420; //FMT_YUV422_SINGLE
+ hw_info->jpeg_size = start_encoder(hw_info);
+EXIT:
+ if(hw_info->mmap_buff.addr){
+ munmap(hw_info->mmap_buff.addr ,hw_info->mmap_buff.size);
+ }
+ close(hw_info->fd);
+ hw_info->fd = -1;
+#ifdef DEBUG_TIME
+ gettimeofday(&end_test, NULL);
+ total_time = (end_test.tv_sec - start_test.tv_sec)*1000000 + end_test.tv_usec -start_test.tv_usec;
+ ALOGD("hw_encode: need time: %d us, jpeg size:%d",total_time,hw_info->jpeg_size);
+#endif
+ return hw_info->jpeg_size;
+}
+
|