summaryrefslogtreecommitdiffstats
path: root/camera
diff options
context:
space:
mode:
authorTyler Luu <tluu@ti.com>2011-10-07 11:57:42 -0500
committerIliyan Malchev <malchev@google.com>2011-10-07 11:10:18 -0700
commitb0f698a6430c3a9478bd476af7189849a1fb1a9d (patch)
tree80d08c481415e2b9a84c920ae2e32b8253f312bf /camera
parent058603f11e5d4355440c4289ac24e4bcd0b82db7 (diff)
downloadhardware_ti_omap4-b0f698a6430c3a9478bd476af7189849a1fb1a9d.zip
hardware_ti_omap4-b0f698a6430c3a9478bd476af7189849a1fb1a9d.tar.gz
hardware_ti_omap4-b0f698a6430c3a9478bd476af7189849a1fb1a9d.tar.bz2
omap4xxx: camera: cancel and flush for SW JPEG encoder
Fixes b/5378650 1. Add method to externally cancel Encoder class while in the middle of encoding. 2. Add queue in AppCallbackNotifier to track all the encoding sessions. When stopping AppCallbackNotifier if any encoding sessions are still ongoing, cancel and wait for the threads to return. Previously, it was possible for Encoder threads to still be running when the preview and images buffers were freed. Change-Id: Ib123d1644dfa7058a6f50f0001b4d05359853827 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.cpp24
-rw-r--r--camera/Encoder_libjpeg.cpp7
-rwxr-xr-xcamera/inc/Encoder_libjpeg.h24
3 files changed, 46 insertions, 9 deletions
diff --git a/camera/AppCallbackNotifier.cpp b/camera/AppCallbackNotifier.cpp
index f88cc3f..a69cfc0 100644
--- a/camera/AppCallbackNotifier.cpp
+++ b/camera/AppCallbackNotifier.cpp
@@ -31,6 +31,7 @@
namespace android {
const int AppCallbackNotifier::NOTIFIER_TIMEOUT = -1;
+KeyedVector<void*, sp<Encoder_libjpeg> > gEncoderQueue;
void AppCallbackNotifierEncoderCallback(void* main_jpeg,
void* thumb_jpeg,
@@ -53,6 +54,7 @@ void AppCallbackNotifier::EncoderDoneCb(void* main_jpeg, void* thumb_jpeg, Camer
Encoder_libjpeg::params *main_param = NULL, *thumb_param = NULL;
size_t jpeg_size;
uint8_t* src = NULL;
+ sp<Encoder_libjpeg> encoder = NULL;
LOG_FUNCTION_NAME;
@@ -144,7 +146,14 @@ void AppCallbackNotifier::EncoderDoneCb(void* main_jpeg, void* thumb_jpeg, Camer
delete (ExifElementsTable*) cookie2;
}
- mFrameProvider->returnFrame(src, type);
+ if (mNotifierState == AppCallbackNotifier::NOTIFIER_STARTED) {
+ encoder = gEncoderQueue.valueFor(src);
+ if (encoder.get()) {
+ gEncoderQueue.removeItem(src);
+ encoder.clear();
+ }
+ mFrameProvider->returnFrame(src, type);
+ }
LOG_FUNCTION_NAME_EXIT;
}
@@ -868,6 +877,7 @@ void AppCallbackNotifier::notifyFrame()
raw_picture,
exif_data);
encoder->run();
+ gEncoderQueue.add(frame->mBuffer, encoder);
encoder.clear();
}
else if ( ( CameraFrame::IMAGE_FRAME == frame->mFrameType ) &&
@@ -1668,6 +1678,8 @@ status_t AppCallbackNotifier::start()
mNotifierState = AppCallbackNotifier::NOTIFIER_STARTED;
CAMHAL_LOGDA(" --> AppCallbackNotifier NOTIFIER_STARTED \n");
+ gEncoderQueue.clear();
+
LOG_FUNCTION_NAME_EXIT;
return NO_ERROR;
@@ -1691,6 +1703,16 @@ status_t AppCallbackNotifier::stop()
CAMHAL_LOGDA(" --> AppCallbackNotifier NOTIFIER_STOPPED \n");
}
+ while(!gEncoderQueue.isEmpty()) {
+ sp<Encoder_libjpeg> encoder = gEncoderQueue.valueAt(0);
+ if(encoder.get()) {
+ encoder->cancel();
+ encoder->join();
+ encoder.clear();
+ }
+ gEncoderQueue.removeItemsAt(0);
+ }
+
LOG_FUNCTION_NAME_EXIT;
return NO_ERROR;
}
diff --git a/camera/Encoder_libjpeg.cpp b/camera/Encoder_libjpeg.cpp
index 23058d3..152e3cc 100644
--- a/camera/Encoder_libjpeg.cpp
+++ b/camera/Encoder_libjpeg.cpp
@@ -367,7 +367,7 @@ size_t Encoder_libjpeg::encode(params* input) {
row_src = src;
row_uv = src + out_width * out_height * bpp;
- while (cinfo.next_scanline < cinfo.image_height) {
+ while ((cinfo.next_scanline < cinfo.image_height) && !mCancelEncoding) {
JSAMPROW row[1]; /* pointer to JSAMPLE row[s] */
// convert input yuv format to yuv444
@@ -388,7 +388,10 @@ size_t Encoder_libjpeg::encode(params* input) {
}
}
- jpeg_finish_compress(&cinfo);
+ // no need to finish encoding routine if we are prematurely stopping
+ // we will end up crashing in dest_mgr since data is incomplete
+ if (!mCancelEncoding)
+ jpeg_finish_compress(&cinfo);
jpeg_destroy_compress(&cinfo);
if (resize_src) free(resize_src);
diff --git a/camera/inc/Encoder_libjpeg.h b/camera/inc/Encoder_libjpeg.h
index 62c534a..da6382e 100755
--- a/camera/inc/Encoder_libjpeg.h
+++ b/camera/inc/Encoder_libjpeg.h
@@ -109,11 +109,13 @@ class Encoder_libjpeg : public Thread {
void* cookie2,
void* cookie3)
: Thread(false), mMainInput(main_jpeg), mThumbnailInput(tn_jpeg), mCb(cb),
- mCookie1(cookie1), mCookie2(cookie2), mCookie3(cookie3), mType(type) {
+ mCancelEncoding(false), mCookie1(cookie1), mCookie2(cookie2), mCookie3(cookie3),
+ mType(type), mThumb(NULL) {
this->incStrong(this);
}
~Encoder_libjpeg() {
+ CAMHAL_LOGVB("~Encoder_libjpeg(%p)", this);
}
virtual bool threadLoop() {
@@ -121,18 +123,19 @@ class Encoder_libjpeg : public Thread {
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();
+ mThumb = new Encoder_libjpeg(mThumbnailInput, NULL, NULL, mType, NULL, NULL, NULL);
+ mThumb->run();
}
// encode our main image
size = encode(mMainInput);
// check if it is main jpeg thread
- if(tn.get()) {
+ if(mThumb.get()) {
// wait until tn jpeg thread exits.
- tn->join();
- tn.clear();
+ mThumb->join();
+ mThumb.clear();
+ mThumb = NULL;
if(mCb) {
mCb(mMainInput, mThumbnailInput, mType, mCookie1, mCookie2, mCookie3);
}
@@ -142,14 +145,23 @@ class Encoder_libjpeg : public Thread {
return false;
}
+ void cancel() {
+ if (mThumb.get()) {
+ mThumb->cancel();
+ }
+ mCancelEncoding = true;
+ }
+
private:
params* mMainInput;
params* mThumbnailInput;
encoder_libjpeg_callback_t mCb;
+ bool mCancelEncoding;
void* mCookie1;
void* mCookie2;
void* mCookie3;
CameraFrame::FrameType mType;
+ sp<Encoder_libjpeg> mThumb;
size_t encode(params*);
};