summaryrefslogtreecommitdiffstats
path: root/camera
diff options
context:
space:
mode:
authorTyler Luu <tluu@ti.com>2011-10-04 22:27:50 +0530
committerIliyan Malchev <malchev@google.com>2011-10-07 11:07:28 -0700
commitc160a1f85c70e49a7613d774e2d99035f3cb4851 (patch)
tree25953e9a7e2d1a34218f0eaa681df501549ff8ae /camera
parent72b0d2814165e633385bd87a838fc9c3a8250113 (diff)
downloadhardware_ti_omap4xxx-c160a1f85c70e49a7613d774e2d99035f3cb4851.zip
hardware_ti_omap4xxx-c160a1f85c70e49a7613d774e2d99035f3cb4851.tar.gz
hardware_ti_omap4xxx-c160a1f85c70e49a7613d774e2d99035f3cb4851.tar.bz2
omap4xxx: camera: EXIF thumbnail for video snapshot
Fixes b/5370657 1) Extend NV12 resizer to take stride insteadof hardcoding stride 2) Change Encoder class interface to support encoding a thumbnail and main jpeg image. Encoder will resize/encodethumbnail in parallel while encoding the main jpeg. Only NV21/NV12 resizing is supported. Thumbnail is created withpost view frame. 3) Add interface in Encoder class to replace thumbnail with jhead. 4) Height and width fields of EXIF are not proper. Fixed. Change-Id: I5d0063357e4e9e327d22805c2dddf8f630d22e7b Signed-off-by: Raji Reddy Kandi<rajireddy.k@samsung.com> Signed-off-by: Tyler Luu <tluu@ti.com> Signed-off-by: Iliyan Malchev <malchev@google.com>
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;