summaryrefslogtreecommitdiffstats
path: root/camera
diff options
context:
space:
mode:
Diffstat (limited to 'camera')
-rw-r--r--camera/AppCallbackNotifier.cpp152
-rw-r--r--camera/CameraHal.cpp13
-rw-r--r--camera/Encoder_libjpeg.cpp139
-rw-r--r--camera/NV12_resize.c22
-rwxr-xr-x[-rw-r--r--]camera/OMXCameraAdapter/OMXExif.cpp4
-rw-r--r--camera/inc/CameraHal.h2
-rwxr-xr-x[-rw-r--r--]camera/inc/Encoder_libjpeg.h76
-rw-r--r--camera/inc/NV12_resize.h1
8 files changed, 308 insertions, 101 deletions
diff --git a/camera/AppCallbackNotifier.cpp b/camera/AppCallbackNotifier.cpp
index 3ff28a8..f88cc3f 100644
--- a/camera/AppCallbackNotifier.cpp
+++ b/camera/AppCallbackNotifier.cpp
@@ -26,15 +26,14 @@
#include <MetadataBufferType.h>
#include <ui/GraphicBuffer.h>
#include <ui/GraphicBufferMapper.h>
-
#include "NV12_resize.h"
namespace android {
const int AppCallbackNotifier::NOTIFIER_TIMEOUT = -1;
-void AppCallbackNotifierEncoderCallback(size_t jpeg_size,
- uint8_t* src,
+void AppCallbackNotifierEncoderCallback(void* main_jpeg,
+ void* thumb_jpeg,
CameraFrame::FrameType type,
void* cookie1,
void* cookie2,
@@ -42,15 +41,18 @@ void AppCallbackNotifierEncoderCallback(size_t jpeg_size,
{
if (cookie1) {
AppCallbackNotifier* cb = (AppCallbackNotifier*) cookie1;
- cb->EncoderDoneCb(jpeg_size, src, type, cookie2, cookie3);
+ cb->EncoderDoneCb(main_jpeg, thumb_jpeg, type, cookie2, cookie3);
}
}
/*--------------------NotificationHandler Class STARTS here-----------------------------*/
-void AppCallbackNotifier::EncoderDoneCb(size_t jpeg_size, uint8_t* src, CameraFrame::FrameType type, void* cookie1, void* cookie2)
+void AppCallbackNotifier::EncoderDoneCb(void* main_jpeg, void* thumb_jpeg, CameraFrame::FrameType type, void* cookie1, void* cookie2)
{
camera_memory_t* encoded_mem = NULL;
+ Encoder_libjpeg::params *main_param = NULL, *thumb_param = NULL;
+ size_t jpeg_size;
+ uint8_t* src = NULL;
LOG_FUNCTION_NAME;
@@ -59,18 +61,28 @@ void AppCallbackNotifier::EncoderDoneCb(size_t jpeg_size, uint8_t* src, CameraFr
{
Mutex::Autolock lock(mLock);
- encoded_mem = (camera_memory_t*) cookie1;
+ if (!main_jpeg) {
+ goto exit;
+ }
- // TODO(XXX): Need to temporarily allocate another chunk of memory and then memcpy
- // encoded buffer since MemoryHeapBase and MemoryBase are passed as
- // one camera_memory_t structure. How fix this?
+ encoded_mem = (camera_memory_t*) cookie1;
+ main_param = (Encoder_libjpeg::params *) main_jpeg;
+ jpeg_size = main_param->jpeg_size;
+ src = main_param->src;
- if(encoded_mem && encoded_mem->data) {
+ if(encoded_mem && encoded_mem->data && (jpeg_size > 0)) {
if (cookie2) {
ExifElementsTable* exif = (ExifElementsTable*) cookie2;
Section_t* exif_section = NULL;
exif->insertExifToJpeg((unsigned char*) encoded_mem->data, jpeg_size);
+
+ if(thumb_jpeg) {
+ thumb_param = (Encoder_libjpeg::params *) thumb_jpeg;
+ exif->insertExifThumbnailImage((const char*)thumb_param->dst,
+ (int)thumb_param->jpeg_size);
+ }
+
exif_section = FindSection(M_EXIF);
if (exif_section) {
@@ -88,11 +100,11 @@ void AppCallbackNotifier::EncoderDoneCb(size_t jpeg_size, uint8_t* src, CameraFr
}
}
}
- }
+ } // scope for mutex lock
// Send the callback to the application only if the notifier is started and the message is enabled
- if((mNotifierState==AppCallbackNotifier::NOTIFIER_STARTED)
- && (mCameraHal->msgTypeEnabled(CAMERA_MSG_COMPRESSED_IMAGE)))
+ if(picture && (mNotifierState==AppCallbackNotifier::NOTIFIER_STARTED) &&
+ (mCameraHal->msgTypeEnabled(CAMERA_MSG_COMPRESSED_IMAGE)))
{
Mutex::Autolock lock(mBurstLock);
#if 0 //TODO: enable burst mode later
@@ -107,6 +119,19 @@ void AppCallbackNotifier::EncoderDoneCb(size_t jpeg_size, uint8_t* src, CameraFr
}
}
+ exit:
+
+ if (main_jpeg) {
+ free(main_jpeg);
+ }
+
+ if (thumb_jpeg) {
+ if (((Encoder_libjpeg::params *) thumb_jpeg)->dst) {
+ free(((Encoder_libjpeg::params *) thumb_jpeg)->dst);
+ }
+ free(thumb_jpeg);
+ }
+
if (encoded_mem) {
encoded_mem->release(encoded_mem);
}
@@ -767,8 +792,10 @@ void AppCallbackNotifier::notifyFrame()
(CameraFrame::ENCODE_RAW_YUV422I_TO_JPEG & frame->mQuirks) )
{
- int encode_quality = 100;
- const char* valstr = NULL;
+ int encode_quality = 100, tn_quality = 100;
+ int tn_width, tn_height;
+ unsigned int current_snapshot = 0;
+ Encoder_libjpeg::params *main_jpeg = NULL, *tn_jpeg = NULL;
void* exif_data = NULL;
camera_memory_t* raw_picture = mRequestMemory(-1, frame->mLength, 1, NULL);
@@ -776,47 +803,72 @@ void AppCallbackNotifier::notifyFrame()
buf = raw_picture->data;
}
- valstr = mParameters.get(CameraParameters::KEY_JPEG_QUALITY);
- if (valstr) {
- encode_quality = atoi(valstr);
- if (encode_quality < 0 || encode_quality > 100) {
- encode_quality = 100;
- }
+ encode_quality = mParameters.getInt(CameraParameters::KEY_JPEG_QUALITY);
+ if (encode_quality < 0 || encode_quality > 100) {
+ encode_quality = 100;
+ }
+
+ tn_quality = mParameters.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY);
+ if (tn_quality < 0 || tn_quality > 100) {
+ tn_quality = 100;
}
if (CameraFrame::HAS_EXIF_DATA & frame->mQuirks) {
exif_data = frame->mCookie2;
}
- CAMHAL_LOGVB("encoder(%p, %d, %p, %d, %d, %d, %d,%p,%d,%p,%p,%p)",
- (uint8_t*)frame->mBuffer,
- frame->mLength,
- (uint8_t*)buf,
- frame->mLength,
- encode_quality,
- frame->mWidth,
- frame->mHeight,
- AppCallbackNotifierEncoderCallback,
- frame->mFrameType,
- this,
- raw_picture,
- exif_data);
-
- sp<Encoder_libjpeg> encoder = new Encoder_libjpeg((uint8_t*)frame->mBuffer,
- frame->mLength,
- (uint8_t*)buf,
- frame->mLength,
- encode_quality,
- frame->mWidth,
- frame->mHeight,
- AppCallbackNotifierEncoderCallback,
- (CameraFrame::FrameType)frame->mFrameType,
- this,
- raw_picture,
- exif_data);
+ main_jpeg = (Encoder_libjpeg::params*)
+ malloc(sizeof(Encoder_libjpeg::params));
+ if (main_jpeg) {
+ main_jpeg->src = (uint8_t*) frame->mBuffer;
+ main_jpeg->src_size = frame->mLength;
+ main_jpeg->dst = (uint8_t*) buf;
+ main_jpeg->dst_size = frame->mLength;
+ main_jpeg->quality = encode_quality;
+ main_jpeg->in_width = frame->mWidth;
+ main_jpeg->in_height = frame->mHeight;
+ main_jpeg->out_width = frame->mWidth;
+ main_jpeg->out_height = frame->mHeight;
+ main_jpeg->format = CameraParameters::PIXEL_FORMAT_YUV422I;
+ }
+
+ tn_width = mParameters.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH);
+ tn_height = mParameters.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;
+ mParameters.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;;
+ }
+
+ sp<Encoder_libjpeg> encoder = new Encoder_libjpeg(main_jpeg,
+ tn_jpeg,
+ AppCallbackNotifierEncoderCallback,
+ (CameraFrame::FrameType)frame->mFrameType,
+ this,
+ raw_picture,
+ exif_data);
encoder->run();
encoder.clear();
-
}
else if ( ( CameraFrame::IMAGE_FRAME == frame->mFrameType ) &&
( NULL != mCameraHal ) &&
@@ -886,6 +938,7 @@ void AppCallbackNotifier::notifyFrame()
structConvImage input = {frame->mWidth,
frame->mHeight,
+ 4096,
IC_FORMAT_YCbCr420_lp,
(mmByte *)frame->mYuv[0],
(mmByte *)frame->mYuv[1],
@@ -893,6 +946,7 @@ void AppCallbackNotifier::notifyFrame()
structConvImage output = {mVideoWidth,
mVideoHeight,
+ 4096,
IC_FORMAT_YCbCr420_lp,
(mmByte *)y_uv[0],
(mmByte *)y_uv[1],
@@ -1346,7 +1400,7 @@ int AppCallbackNotifier::setParameters(const CameraParameters& params)
{
LOG_FUNCTION_NAME;
- mParameters = params
+ mParameters = params;
LOG_FUNCTION_NAME_EXIT;
return NO_ERROR;
diff --git a/camera/CameraHal.cpp b/camera/CameraHal.cpp
index 448ba80..257c2a8 100644
--- a/camera/CameraHal.cpp
+++ b/camera/CameraHal.cpp
@@ -982,6 +982,10 @@ int CameraHal::setParameters(const CameraParameters& params)
mParameters.unflatten(oldParams.flatten());
}
+ if ( NULL != mAppCallbackNotifier.get() ) {
+ mAppCallbackNotifier->setParameters(mParameters);
+ }
+
// Restart Preview if needed by KEY_RECODING_HINT only if preview is already running.
// If preview is not started yet, Video Mode parameters will take effect on next startPreview()
if(restartPreviewRequired && previewEnabled())
@@ -2479,6 +2483,15 @@ status_t CameraHal::takePicture( )
#endif
}
+ // if we taking video snapshot...
+ if ((NO_ERROR == ret) && (mCameraAdapter->getState() == CameraAdapter::VIDEO_STATE)) {
+ // enable post view frames if not already enabled so we can internally
+ // save snapshot frames for generating thumbnail
+ if((mMsgEnabled & CAMERA_MSG_POSTVIEW_FRAME) == 0) {
+ mAppCallbackNotifier->enableMsgType(CAMERA_MSG_POSTVIEW_FRAME);
+ }
+ }
+
if ( (NO_ERROR == ret) && (NULL != mCameraAdapter) )
{
if ( NO_ERROR == ret )
diff --git a/camera/Encoder_libjpeg.cpp b/camera/Encoder_libjpeg.cpp
index 5ae4fdf..23058d3 100644
--- a/camera/Encoder_libjpeg.cpp
+++ b/camera/Encoder_libjpeg.cpp
@@ -27,6 +27,7 @@
#include "CameraHal.h"
#include "Encoder_libjpeg.h"
+#include "NV12_resize.h"
#include <stdlib.h>
#include <unistd.h>
@@ -92,9 +93,28 @@ libjpeg_destination_mgr::libjpeg_destination_mgr(uint8_t* input, int size) {
this->buf = input;
this->bufsize = size;
+
+ jpegsize = 0;
}
/* private static functions */
+static void nv21_to_yuv(uint8_t* dst, uint8_t* y, uint8_t* uv, int width) {
+ if (!dst || !y || !uv) {
+ return;
+ }
+
+ while ((width--) >= 0) {
+ uint8_t y0 = y[0];
+ uint8_t v0 = uv[0];
+ uint8_t u0 = *(uv+1);
+ dst[0] = y0;
+ dst[1] = u0;
+ dst[2] = v0;
+ dst += 3;
+ y++;
+ if(!(width % 2)) uv+=2;
+ }
+}
static void uyvy_to_yuv(uint8_t* dst, uint32_t* src, int width) {
if (!dst || !src) {
@@ -151,6 +171,32 @@ static void uyvy_to_yuv(uint8_t* dst, uint32_t* src, int width) {
}
}
+static void resize_nv12(Encoder_libjpeg::params* params, uint8_t* dst_buffer) {
+ structConvImage o_img_ptr, i_img_ptr;
+
+ if (!params || !dst_buffer) {
+ return;
+ }
+
+ //input
+ i_img_ptr.uWidth = params->in_width;
+ i_img_ptr.uStride = i_img_ptr.uWidth;
+ i_img_ptr.uHeight = params->in_height;
+ i_img_ptr.eFormat = IC_FORMAT_YCbCr420_lp;
+ i_img_ptr.imgPtr = (uint8_t*) params->src;
+ i_img_ptr.clrPtr = i_img_ptr.imgPtr + (i_img_ptr.uWidth * i_img_ptr.uHeight);
+
+ //ouput
+ o_img_ptr.uWidth = params->out_width;
+ o_img_ptr.uStride = o_img_ptr.uWidth;
+ o_img_ptr.uHeight = params->out_height;
+ o_img_ptr.eFormat = IC_FORMAT_YCbCr420_lp;
+ o_img_ptr.imgPtr = dst_buffer;
+ o_img_ptr.clrPtr = o_img_ptr.imgPtr + (o_img_ptr.uWidth * o_img_ptr.uHeight);
+
+ VT_resizeFrame_Video_opt2_lp(&i_img_ptr, &o_img_ptr, NULL, 0);
+}
+
/* public static functions */
const char* ExifElementsTable::degreesToExifOrientation(const char* degrees) {
for (unsigned int i = 0; i < ARRAY_SIZE(degress_to_exif_lut); i++) {
@@ -171,6 +217,17 @@ void ExifElementsTable::insertExifToJpeg(unsigned char* jpeg, size_t jpeg_size)
}
}
+status_t ExifElementsTable::insertExifThumbnailImage(const char* thumb, int len) {
+ status_t ret = NO_ERROR;
+
+ if ((len > 0) && jpeg_opened) {
+ ret = ReplaceThumbnailFromBuffer(thumb, len);
+ CAMHAL_LOGDB("insertExifThumbnailImage. ReplaceThumbnail(). ret=%d", ret);
+ }
+
+ return ret;
+}
+
void ExifElementsTable::saveJpeg(unsigned char* jpeg, size_t jpeg_size) {
if (jpeg_opened) {
WriteJpegToBuffer(jpeg, jpeg_size);
@@ -223,7 +280,7 @@ status_t ExifElementsTable::insertElement(const char* tag, const char* value) {
table[position].Value = (char*) malloc(sizeof(char) * (value_length + 1));
if (table[position].Value) {
- strncpy(table[position].Value, value, value_length);
+ strcpy(table[position].Value, value);
table[position].DataLength = value_length + 1;
}
@@ -232,56 +289,112 @@ status_t ExifElementsTable::insertElement(const char* tag, const char* value) {
}
/* private member functions */
-size_t Encoder_libjpeg::encode() {
+size_t Encoder_libjpeg::encode(params* input) {
jpeg_compress_struct cinfo;
jpeg_error_mgr jerr;
jpeg_destination_mgr jdest;
+ uint8_t* src = NULL, *resize_src = NULL;
uint8_t* row_tmp = NULL;
uint8_t* row_src = NULL;
- int bpp = 2; // TODO(XXX): hardcoded for uyvy
+ uint8_t* row_uv = NULL; // used only for NV12
+ int out_width = 0, in_width = 0;
+ int out_height = 0, in_height = 0;
+ int bpp = 2; // for uyvy
+
+ if (!input) {
+ return 0;
+ }
+
+ out_width = input->out_width;
+ in_width = input->in_width;
+ out_height = input->out_height;
+ in_height = input->in_height;
+ src = input->src;
+ input->jpeg_size = 0;
+
+ libjpeg_destination_mgr dest_mgr(input->dst, input->dst_size);
+
+ // 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) ||
+ (input->dst_size < 1) || (input->format == NULL)) {
+ goto exit;
+ }
+
+ if (strcmp(input->format, CameraParameters::PIXEL_FORMAT_YUV420SP) == 0) {
+ bpp = 1;
+ if ((in_width != out_width) || (in_height != out_height)) {
+ resize_src = (uint8_t*) malloc(input->dst_size);
+ resize_nv12(input, resize_src);
+ if (resize_src) src = resize_src;
+ }
+ } else if ((in_width != out_width) || (in_height != out_height)) {
+ CAMHAL_LOGEB("Encoder: resizing is not supported for this format: %s", input->format);
+ goto exit;
+ } else if (strcmp(input->format, CameraParameters::PIXEL_FORMAT_YUV422I)) {
+ // we currently only support yuv422i and yuv420sp
+ CAMHAL_LOGEB("Encoder: format not supported: %s", input->format);
+ goto exit;
+ }
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_compress(&cinfo);
- libjpeg_destination_mgr dest_mgr(mDest, mDestSize);
-
CAMHAL_LOGDB("encoding... \n\t"
"width: %d \n\t"
"height:%d \n\t"
"dest %p \n\t"
"dest size:%d \n\t"
"mSrc %p",
- mWidth, mHeight, mDest, mDestSize, mSrc);
+ out_width, out_height, input->dst,
+ input->dst_size, src);
cinfo.dest = &dest_mgr;
- cinfo.image_width = mWidth;
- cinfo.image_height = mHeight;
+ cinfo.image_width = out_width;
+ cinfo.image_height = out_height;
cinfo.input_components = 3;
cinfo.in_color_space = JCS_YCbCr;
cinfo.input_gamma = 1;
jpeg_set_defaults(&cinfo);
- jpeg_set_quality(&cinfo, mQuality, TRUE);
+ jpeg_set_quality(&cinfo, input->quality, TRUE);
cinfo.dct_method = JDCT_IFAST;
jpeg_start_compress(&cinfo, TRUE);
- row_tmp = (uint8_t*)malloc(mWidth * 3);
- row_src = mSrc;
+ row_tmp = (uint8_t*)malloc(out_width * 3);
+ row_src = src;
+ row_uv = src + out_width * out_height * bpp;
while (cinfo.next_scanline < cinfo.image_height) {
JSAMPROW row[1]; /* pointer to JSAMPLE row[s] */
- uyvy_to_yuv(row_tmp, (uint32_t*)row_src, mWidth);
+ // convert input yuv format to yuv444
+ if (strcmp(input->format, CameraParameters::PIXEL_FORMAT_YUV420SP) == 0) {
+ nv21_to_yuv(row_tmp, row_src, row_uv, out_width);
+ } else {
+ uyvy_to_yuv(row_tmp, (uint32_t*)row_src, out_width);
+ }
+
row[0] = row_tmp;
jpeg_write_scanlines(&cinfo, row, 1);
- row_src = row_src + mWidth*bpp;
+ row_src = row_src + out_width*bpp;
+
+ // move uv row if input format needs it
+ if (strcmp(input->format, CameraParameters::PIXEL_FORMAT_YUV420SP) == 0) {
+ if (!(cinfo.next_scanline % 2))
+ row_uv = row_uv + out_width * bpp;
+ }
}
jpeg_finish_compress(&cinfo);
jpeg_destroy_compress(&cinfo);
+ if (resize_src) free(resize_src);
+
+ exit:
+ input->jpeg_size = dest_mgr.jpegsize;
return dest_mgr.jpegsize;
}
diff --git a/camera/NV12_resize.c b/camera/NV12_resize.c
index 0d9377e..03c049e 100644
--- a/camera/NV12_resize.c
+++ b/camera/NV12_resize.c
@@ -93,9 +93,9 @@ VT_resizeFrame_Video_opt2_lp
idy = i_img_ptr->uHeight;
/* make sure valid input size */
- if (idx < 1 || idy < 1)
+ if (idx < 1 || idy < 1 || i_img_ptr->uStride < 1)
{
- LOGE("idx or idy less then 1");
+ LOGE("idx or idy less then 1 idx = %d idy = %d stride = %d", idx, idy, i_img_ptr->uStride);
LOGV("VT_resizeFrame_Video_opt2_lp-");
return FALSE;
}
@@ -116,8 +116,8 @@ VT_resizeFrame_Video_opt2_lp
mmUchar *pu8Yrow2 = NULL;
y = (mmUint16) ((mmUint32) (row*resizeFactorY) >> 9);
yf = (mmUchar) ((mmUint32)((row*resizeFactorY) >> 6) & 0x7);
- pu8Yrow1 = inImgPtrY + (y)*STRIDE;
- pu8Yrow2 = pu8Yrow1 + STRIDE;
+ pu8Yrow1 = inImgPtrY + (y) * i_img_ptr->uStride;
+ pu8Yrow2 = pu8Yrow1 + i_img_ptr->uStride;
for (col=0; col < codx; col++)
{
@@ -178,7 +178,7 @@ VT_resizeFrame_Video_opt2_lp
ptr8++;
}
- ptr8 = ptr8 + (STRIDE-codx);
+ ptr8 = ptr8 + (o_img_ptr->uStride - codx);
}
////////////////////////////for Y//////////////////////////
@@ -199,10 +199,10 @@ VT_resizeFrame_Video_opt2_lp
y = (mmUint16) ((mmUint32) (row*resizeFactorY) >> 9);
yf = (mmUchar) ((mmUint32)((row*resizeFactorY) >> 6) & 0x7);
- pu8Cbr1 = inImgPtrU + (y)*STRIDE;
- pu8Cbr2 = pu8Cbr1 + STRIDE;
- pu8Crr1 = inImgPtrV + (y)*STRIDE;
- pu8Crr2 = pu8Crr1 + STRIDE;
+ pu8Cbr1 = inImgPtrU + (y) * i_img_ptr->uStride;
+ pu8Cbr2 = pu8Cbr1 + i_img_ptr->uStride;
+ pu8Crr1 = inImgPtrV + (y) * i_img_ptr->uStride;
+ pu8Crr2 = pu8Crr1 + i_img_ptr->uStride;
for (col=0; col < (((codx)>>1)); col++)
{
@@ -290,8 +290,8 @@ VT_resizeFrame_Video_opt2_lp
ptr8Cb++;
ptr8Cr++;
}
- ptr8Cb = ptr8Cb + (STRIDE-codx);
- ptr8Cr = ptr8Cr + (STRIDE-codx);
+ ptr8Cb = ptr8Cb + (o_img_ptr->uStride-codx);
+ ptr8Cr = ptr8Cr + (o_img_ptr->uStride-codx);
}
///////////////////For Cb- Cr////////////////////////////////////////
}
diff --git a/camera/OMXCameraAdapter/OMXExif.cpp b/camera/OMXCameraAdapter/OMXExif.cpp
index af50a39..e13d145 100644..100755
--- a/camera/OMXCameraAdapter/OMXExif.cpp
+++ b/camera/OMXCameraAdapter/OMXExif.cpp
@@ -580,13 +580,13 @@ status_t OMXCameraAdapter::setupEXIF_libjpeg(ExifElementsTable* exifTable)
if ((NO_ERROR == ret)) {
char temp_value[5];
- snprintf(temp_value, sizeof(temp_value)/sizeof(char) - 1, "%lu", capData->mWidth);
+ snprintf(temp_value, sizeof(temp_value)/sizeof(char), "%lu", capData->mWidth);
ret = exifTable->insertElement(TAG_IMAGE_WIDTH, temp_value);
}
if ((NO_ERROR == ret)) {
char temp_value[5];
- snprintf(temp_value, sizeof(temp_value)/sizeof(char) - 1, "%lu", capData->mHeight);
+ snprintf(temp_value, sizeof(temp_value)/sizeof(char), "%lu", capData->mHeight);
ret = exifTable->insertElement(TAG_IMAGE_LENGTH, temp_value);
}
diff --git a/camera/inc/CameraHal.h b/camera/inc/CameraHal.h
index 07f084f..3ca9ed7 100644
--- a/camera/inc/CameraHal.h
+++ b/camera/inc/CameraHal.h
@@ -574,7 +574,7 @@ public:
status_t useMetaDataBufferMode(bool enable);
- void EncoderDoneCb(size_t jpeg_size, uint8_t* src, CameraFrame::FrameType type, void* cookie1, void* cookie2);
+ void EncoderDoneCb(void*, void*, CameraFrame::FrameType type, void* cookie1, void* cookie2);
void useVideoBuffers(bool useVideoBuffers);
diff --git a/camera/inc/Encoder_libjpeg.h b/camera/inc/Encoder_libjpeg.h
index 8aaae02..62c534a 100644..100755
--- a/camera/inc/Encoder_libjpeg.h
+++ b/camera/inc/Encoder_libjpeg.h
@@ -37,9 +37,8 @@ namespace android {
*/
#define MAX_EXIF_TAGS_SUPPORTED 30
-
-typedef void (*encoder_libjpeg_callback_t) (size_t jpeg_size,
- uint8_t* src,
+typedef void (*encoder_libjpeg_callback_t) (void* main_jpeg,
+ void* thumb_jpeg,
CameraFrame::FrameType type,
void* cookie1,
void* cookie2,
@@ -73,6 +72,7 @@ class ExifElementsTable {
status_t insertElement(const char* tag, const char* value);
void insertExifToJpeg(unsigned char* jpeg, size_t jpeg_size);
+ status_t insertExifThumbnailImage(const char*, int);
void saveJpeg(unsigned char* picture, size_t jpeg_size);
static const char* degreesToExifOrientation(const char*);
private:
@@ -84,22 +84,32 @@ class ExifElementsTable {
};
class Encoder_libjpeg : public Thread {
+ /* public member types and variables */
+ public:
+ struct params {
+ uint8_t* src;
+ int src_size;
+ uint8_t* dst;
+ int dst_size;
+ int quality;
+ int in_width;
+ int in_height;
+ int out_width;
+ int out_height;
+ const char* format;
+ size_t jpeg_size;
+ };
+ /* public member functions */
public:
- Encoder_libjpeg(uint8_t* src,
- int src_size,
- uint8_t* dst,
- int dst_size,
- int quality,
- int width,
- int height,
- encoder_libjpeg_callback_t cb,
- CameraFrame::FrameType type,
- void* cookie1,
- void* cookie2,
- void* cookie3)
- : Thread(false), mSrc(src), mDest(dst), mSrcSize(src_size), mDestSize(dst_size),
- mQuality(quality), mWidth(width), mHeight(height), mCb(cb), mCookie1(cookie1),
- mCookie2(cookie2), mCookie3(cookie3), mType(type) {
+ Encoder_libjpeg(params* main_jpeg,
+ params* tn_jpeg,
+ encoder_libjpeg_callback_t cb,
+ CameraFrame::FrameType type,
+ void* cookie1,
+ void* cookie2,
+ void* cookie3)
+ : Thread(false), mMainInput(main_jpeg), mThumbnailInput(tn_jpeg), mCb(cb),
+ mCookie1(cookie1), mCookie2(cookie2), mCookie3(cookie3), mType(type) {
this->incStrong(this);
}
@@ -107,25 +117,41 @@ class Encoder_libjpeg : public Thread {
}
virtual bool threadLoop() {
- size_t size = encode();
- mCb(size, mSrc, mType, mCookie1, mCookie2, mCookie3);
+ size_t size = 0;
+ sp<Encoder_libjpeg> tn = NULL;
+ if (mThumbnailInput) {
+ // start thread to encode thumbnail
+ tn = new Encoder_libjpeg(mThumbnailInput, NULL, NULL, mType, NULL, NULL, NULL);
+ tn->run();
+ }
+
+ // encode our main image
+ size = encode(mMainInput);
+
+ // check if it is main jpeg thread
+ if(tn.get()) {
+ // wait until tn jpeg thread exits.
+ tn->join();
+ tn.clear();
+ if(mCb) {
+ mCb(mMainInput, mThumbnailInput, mType, mCookie1, mCookie2, mCookie3);
+ }
+ }
// encoder thread runs, self-destructs, and then exits
this->decStrong(this);
return false;
}
private:
- uint8_t* mSrc;
- uint8_t* mDest;
- int mSrcSize, mDestSize;
- int mQuality, mWidth, mHeight;
+ params* mMainInput;
+ params* mThumbnailInput;
encoder_libjpeg_callback_t mCb;
void* mCookie1;
void* mCookie2;
void* mCookie3;
CameraFrame::FrameType mType;
- size_t encode();
+ size_t encode(params*);
};
}
diff --git a/camera/inc/NV12_resize.h b/camera/inc/NV12_resize.h
index 64afcea..927faf8 100644
--- a/camera/inc/NV12_resize.h
+++ b/camera/inc/NV12_resize.h
@@ -103,6 +103,7 @@ typedef struct
{
mmInt32 uWidth;
mmInt32 uHeight;
+ mmInt32 uStride;
enumImageFormat eFormat;
mmByte *imgPtr;
mmByte *clrPtr;