diff options
author | Tyler Luu <tluu@ti.com> | 2011-10-07 11:57:42 -0500 |
---|---|---|
committer | Iliyan Malchev <malchev@google.com> | 2011-10-07 11:10:18 -0700 |
commit | b0f698a6430c3a9478bd476af7189849a1fb1a9d (patch) | |
tree | 80d08c481415e2b9a84c920ae2e32b8253f312bf /camera | |
parent | 058603f11e5d4355440c4289ac24e4bcd0b82db7 (diff) | |
download | hardware_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.cpp | 24 | ||||
-rw-r--r-- | camera/Encoder_libjpeg.cpp | 7 | ||||
-rwxr-xr-x | camera/inc/Encoder_libjpeg.h | 24 |
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*); }; |