int CameraHal::CapturePicture()
	{
		int image_width, image_height, preview_width, preview_height;
		unsigned long base, offset;
		
		struct v4l2_buffer buffer; // for VIDIOC_QUERYBUF and VIDIOC_QBUF
		struct v4l2_format format;
		struct v4l2_buffer cfilledbuffer; // for VIDIOC_DQBUF
		struct v4l2_requestbuffers creqbuf; // for VIDIOC_REQBUFS and VIDIOC_STREAMON and VIDIOC_STREAMOFF

		sp<MemoryBase> 		mPictureBuffer;
		sp<MemoryBase> 		mFinalPictureBuffer;
		sp<MemoryHeapBase>  mJPEGPictureHeap;
		sp<MemoryBase>		mJPEGPictureMemBase;
#if OMAP_SCALE
		sp<MemoryHeapBase> 	TempHeapBase;
		sp<MemoryBase>	 	TempBase;
		sp<IMemoryHeap> 	TempHeap;
#endif

		ssize_t newoffset;
		size_t newsize;

		mCaptureFlag = true;
		int jpegSize;
		void* outBuffer;
		int err, i;
		int err_cnt = 0;

		int EXIF_Data_Size = 0;
		int ThumbNail_Data_Size = 0;
		unsigned char* pExifBuf = new unsigned char[65536];	//64*1024

		int twoSecondReviewMode = getTwoSecondReviewMode();
		int orientation = getOrientation();

		LOG_FUNCTION_NAME

		if (CameraSetFrameRate())
		{
			LOGE("Error in setting Camera frame rate\n");
			return -1;
		}

		HAL_PRINT("\n\n\n PICTURE NUMBER =%d\n\n\n",++pictureNumber);

		mParameters.getPictureSize(&image_width, &image_height);
		mParameters.getPreviewSize(&preview_width, &preview_height);	
		HAL_PRINT("Picture Size: Width = %d \t Height = %d\n", image_width, image_height);
		HAL_PRINT("Preview Size: Width = %d \t Height = %d\n", preview_width, preview_height);

#if OPEN_CLOSE_WORKAROUND
		close(camera_device);
		camera_device = open(VIDEO_DEVICE, O_RDWR);
		if (camera_device < 0) 
		{
			LOGE ("!!!!!!!!!FATAL Error: Could not open the camera device: %s!!!!!!!!!\n",
					strerror(errno) );
		}
#endif

		if(mCamera_Mode == CAMERA_MODE_JPEG)
		{
			int jpeg_width = GetJPEG_Capture_Width();
			int jpeg_height = GetJPEG_Capture_Height();
			capture_len = jpeg_width * jpeg_height * 2;
		}
		else
		{
			capture_len = image_width * image_height * 2;
		}

		if (capture_len & 0xfff)
		{
			capture_len = (capture_len & 0xfffff000) + 0x1000;
		}

		HAL_PRINT("pictureFrameSize = 0x%x = %d\n", capture_len, capture_len);

		mPictureHeap = new MemoryHeapBase(capture_len);

		base = (unsigned long)mPictureHeap->getBase();
		base = (base + 0xfff) & 0xfffff000;
		offset = base - (unsigned long)mPictureHeap->getBase();

		/* set size & format of the video image */
		format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
		format.fmt.pix.width = image_width;
		format.fmt.pix.height = image_height;
		
		if(mCamera_Mode == CAMERA_MODE_JPEG)
			format.fmt.pix.pixelformat = PIXEL_FORMAT_JPEG;
		else
			format.fmt.pix.pixelformat = PIXEL_FORMAT;

		if (ioctl(camera_device, VIDIOC_S_FMT, &format) < 0)
		{
			LOGE ("Failed to set VIDIOC_S_FMT.\n");
			return -1;
		}
		
#if OMAP_SCALE
        if(mCameraIndex == VGA_CAMERA && mCamMode != VT_MODE) {
            if(orientation == 0 || orientation == 180) {
                struct v4l2_control vc;            
                CLEAR(vc);
                vc.id = V4L2_CID_FLIP;                
                vc.value = CAMERA_FLIP_MIRROR;
                if (ioctl (camera_device, VIDIOC_S_CTRL, &vc) < 0) {
                    LOGE("V4L2_CID_FLIP fail!\n");
                    return UNKNOWN_ERROR;  
                }
            }
        }
#endif  

		/* Shutter CallBack */
		if(mMsgEnabled & CAMERA_MSG_SHUTTER)
		{
			mNotifyCb(CAMERA_MSG_SHUTTER,0,0,mCallbackCookie);
		} 

		/* Check if the camera driver can accept 1 buffer */
		creqbuf.type   = V4L2_BUF_TYPE_VIDEO_CAPTURE;
		creqbuf.memory = V4L2_MEMORY_USERPTR;
		creqbuf.count  = 1;
		if (ioctl(camera_device, VIDIOC_REQBUFS, &creqbuf) < 0)
		{
			LOGE ("VIDIOC_REQBUFS Failed. errno = %d\n", errno);
			return -1;
		}

		buffer.type = creqbuf.type;
		buffer.memory = creqbuf.memory;
		buffer.index = 0;
		if (ioctl(camera_device, VIDIOC_QUERYBUF, &buffer) < 0) {
			LOGE("VIDIOC_QUERYBUF Failed");
			return -1;
		}

		buffer.m.userptr = base;
		mPictureBuffer = new MemoryBase(mPictureHeap, offset, buffer.length);
		LOGD("Picture Buffer: Base = %p Offset = 0x%x\n", (void *)base, (unsigned int)offset);

		if (ioctl(camera_device, VIDIOC_QBUF, &buffer) < 0) {
			LOGE("CAMERA VIDIOC_QBUF Failed");
			return -1;
		}

		/* turn on streaming */
		creqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
		if (ioctl(camera_device, VIDIOC_STREAMON, &creqbuf.type) < 0)
		{
			LOGE("VIDIOC_STREAMON Failed\n");
			return -1;
		}

		HAL_PRINT("De-queue the next avaliable buffer\n");

		/* De-queue the next avaliable buffer */
		cfilledbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
		cfilledbuffer.memory = creqbuf.memory;

		while (ioctl(camera_device, VIDIOC_DQBUF, &cfilledbuffer) < 0) 
		{
			LOGE("VIDIOC_DQBUF Failed cnt = %d\n", err_cnt);
			if(err_cnt++ > 10)
			{
				mNotifyCb(CAMERA_MSG_ERROR,CAMERA_DEVICE_ERROR_FOR_RESTART,0,mCallbackCookie);

				mPictureBuffer.clear();
				mPictureHeap.clear();

				return NO_ERROR;           
			}
		}
#if TIMECHECK
		PPM("AFTER CAPTURE YUV IMAGE\n");
#endif
		/* turn off streaming */
		creqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
		if (ioctl(camera_device, VIDIOC_STREAMOFF, &creqbuf.type) < 0) 
		{
			LOGE("VIDIOC_STREAMON Failed\n");
			return -1;
		}

#if OMAP_SCALE
        if(mCameraIndex == VGA_CAMERA && mCamMode != VT_MODE) {
            if(orientation == 0 || orientation == 180) {
                struct v4l2_control vc;            
                CLEAR(vc);
                vc.id = V4L2_CID_FLIP;                
                vc.value = CAMERA_FLIP_NONE;
                if (ioctl (camera_device, VIDIOC_S_CTRL, &vc) < 0) {
                    LOGE("V4L2_CID_FLIP fail!\n");
                    return UNKNOWN_ERROR;  
                }
            }
        }
#endif  

		if(mCamera_Mode == CAMERA_MODE_JPEG)
		{
			int JPEG_Image_Size = GetJpegImageSize();
			int thumbNailOffset = GetThumbNailOffset();
			int yuvOffset = GetYUVOffset();
			ThumbNail_Data_Size = GetThumbNailDataSize();
			sp<IMemoryHeap> heap = mPictureBuffer->getMemory(&newoffset, &newsize);
			uint8_t* pInJPEGDataBUuf = (uint8_t *)heap->base() + newoffset ;
			uint8_t* pInThumbNailDataBuf = (uint8_t *)heap->base() + thumbNailOffset;
			uint8_t* pYUVDataBuf = (uint8_t *)heap->base() + yuvOffset;

			CreateExif(pInThumbNailDataBuf,ThumbNail_Data_Size,pExifBuf,EXIF_Data_Size,1);

			//create a new binder object 
			mFinalPictureHeap = new MemoryHeapBase(EXIF_Data_Size+JPEG_Image_Size);
			mFinalPictureBuffer = new MemoryBase(mFinalPictureHeap,0,EXIF_Data_Size+JPEG_Image_Size);
			heap = mFinalPictureBuffer->getMemory(&newoffset, &newsize);
			uint8_t* pOutFinalJpegDataBuf = (uint8_t *)heap->base();

			//create a new binder obj to send yuv data
			if(yuvOffset)
			{
				int mFrameSizeConvert = (preview_width*preview_height*3/2) ;

				mYUVPictureHeap = new MemoryHeapBase(mFrameSizeConvert);
				mYUVPictureBuffer = new MemoryBase(mYUVPictureHeap,0,mFrameSizeConvert);
				sp<IMemoryHeap> newheap = mYUVPictureBuffer->getMemory(&newoffset, &newsize);
#if TIMECHECK
				PPM("YUV COLOR CONVERSION STARTED\n");
#endif
				Neon_Convert_yuv422_to_NV21((uint8_t *)pYUVDataBuf, (uint8_t *)newheap->base(), mPreviewWidth, mPreviewHeight);
#if TIMECHECK
				PPM("YUV COLOR CONVERSION ENDED\n");
#endif
			}
			//create final JPEG with EXIF into that
			int OutJpegSize = 0;
			err = CreateJpegWithExif(pInJPEGDataBUuf,JPEG_Image_Size,pExifBuf,EXIF_Data_Size,pOutFinalJpegDataBuf,OutJpegSize);
			if(err==false) return -1;
			
			if(yuvOffset)
			{
#ifdef HARDWARE_OMX
				if(twoSecondReviewMode == 1)
				{
					DrawOverlay(pYUVDataBuf, true);
				}
#endif //HARDWARE_OMX
				if(mMsgEnabled & CAMERA_MSG_RAW_IMAGE)
				{
					mDataCb(CAMERA_MSG_RAW_IMAGE, mYUVPictureBuffer, mCallbackCookie);
				}	
			}

			if (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)
			{
				mDataCb(CAMERA_MSG_COMPRESSED_IMAGE, mFinalPictureBuffer, mCallbackCookie);
			}

#if OPEN_CLOSE_WORKAROUND
			close(camera_device);
			camera_device = open(VIDEO_DEVICE, O_RDWR);
			if (camera_device < 0) 
			{
				LOGE ("!!!!!!!!!FATAL Error: Could not open the camera device: %s!!!!!!!!!\n", strerror(errno) );
			}
#endif
		}

		if(mCamera_Mode == CAMERA_MODE_YUV)
		{
#ifdef HARDWARE_OMX
			int mFrameSizeConvert = (image_width*image_height*2) ;
			mVGAYUVPictureHeap = new MemoryHeapBase(mFrameSizeConvert);
			mVGAYUVPictureBuffer = new MemoryBase(mVGAYUVPictureHeap,0,mFrameSizeConvert);
			mVGANewheap = mVGAYUVPictureBuffer->getMemory(&newoffset, &newsize);

			sp<IMemoryHeap> heap = mPictureBuffer->getMemory(&newoffset, &newsize);
			uint8_t* pYUVDataBuf = (uint8_t *)heap->base() + newoffset ;
			LOGD("PictureThread: generated a picture, yuv_buffer=%p yuv_len=%d\n",pYUVDataBuf,capture_len);
#if OMAP_SCALE
			TempHeapBase = new MemoryHeapBase(mFrameSizeConvert);
			TempBase = new MemoryBase(TempHeapBase,0,mFrameSizeConvert);
			TempHeap = TempBase->getMemory(&newoffset, &newsize);
			if(scale_process((void*)pYUVDataBuf, mPreviewWidth, mPreviewHeight,(void*)TempHeap->base(), mPreviewHeight, mPreviewWidth, 0, PIX_YUV422I, 1))
			{
				LOGE("scale_process() failed\n");
			}
#endif

#if TIMECHECK
			PPM("YUV COLOR ROTATION STARTED\n");
#endif                   

#if 0	//YUV dump code for testing
			FILE* fIn = NULL;	
			fIn = fopen("/data/output.yuv", "w");
			if ( fIn == NULL ) 	  
			{ 		 
				LOGE("Error: failed to open the file for writing\n");		 
			}		
			fwrite((uint8_t*)mVGANewheap->base(), 1, mPreviewWidth*mPreviewHeight*2, fIn);	   
			fclose(fIn);
#endif

			/*
			   	for VGA capture case
				pYUVDataBuf : Input buffer from Camera Driver YUV422.
				mVGANewheap->base() : 90 or 270 degree rotated YUV422 format.
			 */
			{
				int error = 0;
#if OMAP_SCALE
				neon_args->pIn 		= (uint8_t*)TempHeap->base();
#else
				neon_args->pIn 		= (uint8_t*)pYUVDataBuf;
#endif
				neon_args->pOut 	= (uint8_t*)mVGANewheap->base();
				neon_args->height 	= mPreviewWidth; 
				neon_args->width 	= mPreviewHeight;
#if OMAP_SCALE
				neon_args->rotate 	= NEON_ROT90;
#else
				neon_args->rotate 	= NEON_ROT270;
#endif
				if (Neon_Rotate != NULL)
					error = (*Neon_Rotate)(neon_args);
				else
					LOGE("Rotate Fucntion pointer Null");

				if (error < 0) {
					LOGE("Error in Rotation 90");

				}							    					
			}
#if OMAP_SCALE
			TempHeapBase.clear();
			TempBase.clear();
			TempHeap.clear();
#endif
#if TIMECHECK
			PPM("YUV COLOR ROTATION Done\n");
#endif
#endif //HARDWARE_OMX

			if (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)
			{
#ifdef HARDWARE_OMX  
				int jpegSize = image_width * image_height*2;
				capture_len = (image_width*image_height*2) ;
				CreateExif(NULL, 0, pExifBuf, EXIF_Data_Size, 0);
				HAL_PRINT("VGA EXIF size : %d\n", EXIF_Data_Size);
				mJPEGPictureHeap = new MemoryHeapBase(jpegSize + 256);
				outBuffer = (void *)((unsigned long)(mJPEGPictureHeap->getBase()) + 128);
#if TIMECHECK
				PPM("BEFORE JPEG Encode Image\n");
#endif
				HAL_PRINT("VGA capture : outbuffer = 0x%x, jpegSize = %d, yuv_buffer = 0x%x, yuv_len = %d, image_width = %d, image_height = %d, quality = %d, mippMode =%d\n", 
							outBuffer, jpegSize, yuv_buffer, capture_len, image_width, image_height, mYcbcrQuality, mippMode); 

				if(isStart_JPEG)
				{
					int jpegFormat = PIX_YUV422I;
#ifdef OMAP_ENHANCEMENT
#if OMAP_SCALE

					err = jpegEncoder->encodeImage(outBuffer, 
											jpegSize, 
											(uint8_t*)mVGANewheap->base(), 
											capture_len, 
											pExifBuf,
											EXIF_Data_Size,
											image_width,	//
											image_height,	//
											mThumbnailWidth,
											mThumbnailHeight,
											mYcbcrQuality,
											jpegFormat);
#else
					err = jpegEncoder->encodeImage(outBuffer, 
											jpegSize, 
											(uint8_t*)mVGANewheap->base(), 
											capture_len, 
											pExifBuf,
											EXIF_Data_Size,
											image_height,	//
											image_width,	//
											mThumbnailWidth,
											mThumbnailHeight,
											mYcbcrQuality,
											jpegFormat);
#endif        	
					LOGD("JPEG ENCODE END\n");

					if(err != true) {
						LOGE("Jpeg encode failed!!\n");
						return -1;
					} else {
						LOGD("Jpeg encode success!!\n");
					}
#endif
				}
#if TIMECHECK
				PPM("AFTER JPEG Encode Image\n");
#endif
#ifdef OMAP_ENHANCEMENT
				mJPEGPictureMemBase = new MemoryBase(mJPEGPictureHeap, 128, jpegEncoder->jpegSize);
#endif
				if (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)
				{
					mDataCb(CAMERA_MSG_COMPRESSED_IMAGE,mJPEGPictureMemBase,mCallbackCookie);
				}

				mJPEGPictureMemBase.clear();
				mJPEGPictureHeap.clear();
#endif //HARDWARE_OMX
			}//END of CAMERA_MSG_COMPRESSED_IMAGE

			yuv_buffer = (uint8_t*)cfilledbuffer.m.userptr;		           

			if(twoSecondReviewMode == 1)
			{ 	
				DrawOverlay(yuv_buffer, true);
			}  
			//yuv_buffer: [Reused]Output buffer with YUV 420P 270 degree rotated.             
			if(mMsgEnabled & CAMERA_MSG_RAW_IMAGE)
			{
				Neon_Convert_yuv422_to_YUV420P((uint8_t *)mVGANewheap->base(), (uint8_t *)yuv_buffer, mPreviewHeight, mPreviewWidth);         	
				mDataCb(CAMERA_MSG_RAW_IMAGE, mPictureBuffer, mCallbackCookie);
			}        
		}
		//END of CAMERA_MODE_YUV

		mPictureBuffer.clear();
		mPictureHeap.clear();
		if(mCamera_Mode == CAMERA_MODE_JPEG)
		{
			mFinalPictureBuffer.clear();
			mFinalPictureHeap.clear();
			mYUVPictureBuffer.clear();
			mYUVPictureHeap.clear();
		}

		if(mCamera_Mode == CAMERA_MODE_YUV)
		{
			if(mCameraIndex == VGA_CAMERA)
			{
				mVGAYUVPictureBuffer.clear();
				mVGAYUVPictureHeap.clear();
			}
		}

		delete []pExifBuf;
		mCaptureFlag = false;
		LOG_FUNCTION_NAME_EXIT

		return NO_ERROR;

	}
	int CameraHal::CapturePicture()
	{
		int image_width, image_height, preview_width, preview_height;
        int capture_len;
		unsigned long base, offset;
      
#ifdef R3D4_CONVERT     
        CColorConvert* pConvert;    //class for image processing
#endif		
		struct v4l2_buffer buffer; // for VIDIOC_QUERYBUF and VIDIOC_QBUF
		struct v4l2_format format;
		//struct v4l2_buffer cfilledbuffer; // for VIDIOC_DQBUF
		struct v4l2_requestbuffers creqbuf; // for VIDIOC_REQBUFS and VIDIOC_STREAMON and VIDIOC_STREAMOFF

		sp<MemoryBase> 		mPictureBuffer;
		sp<MemoryBase> 		mFinalPictureBuffer;
		sp<MemoryHeapBase>  mJPEGPictureHeap;
		sp<MemoryBase>		mJPEGPictureMemBase;


		ssize_t newoffset;
		size_t newsize;

		mCaptureFlag = true;
		int jpegSize;
		void* outBuffer;
		int err, i;
		int err_cnt = 0;


		int exifDataSize = 0;
		int thumbnaiDataSize = 0;
		unsigned char* pExifBuf = new unsigned char[64*1024];

		int twoSecondReviewMode = getTwoSecondReviewMode();
		int orientation = getOrientation();

		LOG_FUNCTION_NAME
		
		                           
		if (CameraSetFrameRate())
		{
			LOGE("Error in setting Camera frame rate\n");
			return -1;
		}
        
		LOGD("\n\n\n PICTURE NUMBER =%d\n\n\n",++pictureNumber);
       
        mParameters.getPictureSize(&image_width, &image_height);
		mParameters.getPreviewSize(&preview_width, &preview_height);	
		LOGV("mCameraIndex = %d\n", mCameraIndex);
		LOGD("Picture Size: Width = %d \t Height = %d\n", image_width, image_height);

        /* set size & format of the video image */
		format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
		format.fmt.pix.width = image_width;
		format.fmt.pix.height = image_height;
        
		if(mCamera_Mode == CAMERA_MODE_JPEG)
		{
            format.fmt.pix.pixelformat = PIXEL_FORMAT_JPEG;
			capture_len =  GetJPEG_Capture_Width() * GetJPEG_Capture_Height() * JPG_BYTES_PER_PIXEL;
		}
		else
		{
            format.fmt.pix.pixelformat = PIXEL_FORMAT;
			capture_len = image_width * image_height * UYV_BYTES_PER_PIXEL;   
		}

         // round up to 4096 bytes
		if (capture_len & 0xfff)   
			capture_len = (capture_len & 0xfffff000) + 0x1000;

		LOGV("capture: %s mode, pictureFrameSize = 0x%x = %d\n", 
            (mCamera_Mode == CAMERA_MODE_JPEG)?"jpeg":"yuv", capture_len, capture_len);

            
		mPictureHeap = new MemoryHeapBase(capture_len);
		base = (unsigned long)mPictureHeap->getBase();
		base = (base + 0xfff) & 0xfffff000;
		offset = base - (unsigned long)mPictureHeap->getBase();


        // set capture format
		if (ioctl(camera_device, VIDIOC_S_FMT, &format) < 0)
		{
			LOGE ("Failed to set VIDIOC_S_FMT.\n");
			return -1;
		}
#if OMAP_SCALE       
        if(mCameraIndex == VGA_CAMERA && mCamMode != VT_MODE)
            if(orientation == 0 || orientation == 180)
                setFlip(CAMERA_FLIP_MIRROR);
#endif
		/* Shutter CallBack */
		if(mMsgEnabled & CAMERA_MSG_SHUTTER)
		{
			mNotifyCb(CAMERA_MSG_SHUTTER, 0, 0, mCallbackCookie);
		} 
		
		/* Check if the camera driver can accept 1 buffer */
		creqbuf.type   = V4L2_BUF_TYPE_VIDEO_CAPTURE;
		creqbuf.memory = V4L2_MEMORY_USERPTR;
		creqbuf.count  = 1;
		if (ioctl(camera_device, VIDIOC_REQBUFS, &creqbuf) < 0)
		{
			LOGE ("VIDIOC_REQBUFS Failed. errno = %d\n", errno);
			return -1;
		}

		buffer.type = creqbuf.type;
		buffer.memory = creqbuf.memory;
		buffer.index = 0;
		if (ioctl(camera_device, VIDIOC_QUERYBUF, &buffer) < 0) {
			LOGE("VIDIOC_QUERYBUF Failed");
			return -1;
		}

		buffer.m.userptr = base;
		mPictureBuffer = new MemoryBase(mPictureHeap, offset, buffer.length);
		LOGD("Picture Buffer: Base = %p Offset = 0x%x\n", (void *)base, (unsigned int)offset);

		if (ioctl(camera_device, VIDIOC_QBUF, &buffer) < 0) {
			LOGE("CAMERA VIDIOC_QBUF Failed");
			return -1;
		}

		/* turn on streaming */
		if (ioctl(camera_device, VIDIOC_STREAMON, &creqbuf.type) < 0)
		{
			LOGE("VIDIOC_STREAMON Failed\n");
			return -1;
		}

		LOGD("De-queue the next avaliable buffer\n");

		/* De-queue the next avaliable buffer */       
        //try to get buffer from camearo for 10 times
		while (ioctl(camera_device, VIDIOC_DQBUF, &buffer) < 0) 
		{
			LOGE("VIDIOC_DQBUF Failed cnt = %d\n", err_cnt);
			if(err_cnt++ > 10)
			{
				mNotifyCb(CAMERA_MSG_ERROR, CAMERA_DEVICE_ERROR_FOR_RESTART, 0, mCallbackCookie);

				mPictureBuffer.clear();
				mPictureHeap.clear();

				return NO_ERROR;           
			}
		}
		PPM("AFTER CAPTURE YUV IMAGE\n");
		/* turn off streaming */
        
		if (ioctl(camera_device, VIDIOC_STREAMOFF, &creqbuf.type) < 0) 
		{
			LOGE("VIDIOC_STREAMON Failed\n");
			return -1;
		}
#if OMAP_SCALE          
        if(mCameraIndex == VGA_CAMERA && mCamMode != VT_MODE)
            if(orientation == 0 || orientation == 180)
                setFlip(CAMERA_FLIP_NONE);
#endif                
        // camera returns processed jpeg image
		if(mCamera_Mode == CAMERA_MODE_JPEG)
		{
			int JPEG_Image_Size = GetJpegImageSize();
			int thumbNailOffset = 0;	//m4mo doesnt store offset ?
			int yuvOffset =0;			//m4mo doesnt store yuv image ?
			// int thumbNailOffset = GetThumbNailOffset();
			// int yuvOffset = GetYUVOffset();
			thumbnaiDataSize = GetThumbNailDataSize();
			sp<IMemoryHeap> heap = mPictureBuffer->getMemory(&newoffset, &newsize);
			uint8_t* pInJPEGDataBUuf = (uint8_t *)heap->base() + newoffset ;			//ptr to jpeg data
			uint8_t* pInThumbNailDataBuf = (uint8_t *)heap->base() + thumbNailOffset;	//ptr to thmubnail
			uint8_t* pYUVDataBuf = (uint8_t *)heap->base() + yuvOffset;

			// FILE* fOut = NULL;
			// fOut = fopen("/dump/dump.jpg", "w");
			// fwrite(pInJPEGDataBUuf, 1, JPEG_Image_Size, fOut);
			// fclose(fOut);
			
			CreateExif(pInThumbNailDataBuf, thumbnaiDataSize, pExifBuf, exifDataSize, EXIF_SET_JPEG_LENGTH);

			//create a new binder object 
			mFinalPictureHeap = new MemoryHeapBase(exifDataSize+JPEG_Image_Size);
			mFinalPictureBuffer = new MemoryBase(mFinalPictureHeap,0,exifDataSize+JPEG_Image_Size);
			heap = mFinalPictureBuffer->getMemory(&newoffset, &newsize);
			uint8_t* pOutFinalJpegDataBuf = (uint8_t *)heap->base();

			
			//create a new binder obj to send yuv data
			if(yuvOffset)
			{
				int mFrameSizeConvert = (preview_width*preview_height*3/2) ;

				mYUVPictureHeap = new MemoryHeapBase(mFrameSizeConvert);
				mYUVPictureBuffer = new MemoryBase(mYUVPictureHeap,0,mFrameSizeConvert);
				mYUVNewheap = mYUVPictureBuffer->getMemory(&newoffset, &newsize);

				PPM("YUV COLOR CONVERSION STARTED\n");
#ifdef NEON

				Neon_Convert_yuv422_to_NV21((uint8_t *)pYUVDataBuf, 
                    (uint8_t *)mYUVNewheap->base(), mPreviewWidth, mPreviewHeight);

				PPM("YUV COLOR CONVERSION ENDED\n");

				if(mMsgEnabled & CAMERA_MSG_RAW_IMAGE)
				{
					mDataCb(CAMERA_MSG_RAW_IMAGE, mYUVPictureBuffer, mCallbackCookie);
				}	
#else
                if(mMsgEnabled & CAMERA_MSG_RAW_IMAGE)
                    mDataCb(CAMERA_MSG_RAW_IMAGE, pYUVDataBuf, mCallbackCookie);

#endif
			}
			//create final JPEG with EXIF into that
			int OutJpegSize = 0;
			if(!CreateJpegWithExif( pInJPEGDataBUuf, JPEG_Image_Size, pExifBuf, exifDataSize, pOutFinalJpegDataBuf, OutJpegSize))
            {
                LOGE("createJpegWithExif fail!!\n");
                return -1;
            }

            if (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)
            {
                mDataCb(CAMERA_MSG_COMPRESSED_IMAGE, mFinalPictureBuffer, mCallbackCookie);
             }

		}   //CAMERA_MODE_JPEG
        
        // camera returns 16 bit uyv image
        // -> needs to process (rotate/flip) 
        // -> and compess to jpeg (with dsp)
		if(mCamera_Mode == CAMERA_MODE_YUV)
		{
#ifdef HARDWARE_OMX
            // create new buffer for image processing
			int mFrameSizeConvert = (image_width*image_height*2) ;
			mYUVPictureHeap = new MemoryHeapBase(mFrameSizeConvert);
			mYUVPictureBuffer = new MemoryBase(mYUVPictureHeap,0,mFrameSizeConvert);
			mYUVNewheap = mYUVPictureBuffer->getMemory(&newoffset, &newsize);
            
            // buffer from v4l holding the actual image
            uint8_t *pYuvBuffer = (uint8_t*)buffer.m.userptr;    
            
			LOGD("PictureThread: generated a picture, pYuvBuffer=%p yuv_len=%d\n", 
                pYuvBuffer, capture_len);
                     
              
			PPM("YUV COLOR ROTATION STARTED\n");
    
#ifdef R3D4_CONVERT     
            if(mCameraIndex == VGA_CAMERA)
            {
				LOGV("use rotation");
                 // color converter and image processing (flip/rotate)
                 // neon lib doesnt seem to work, jpeg was corrupted?
                 // so use own stuff
                pConvert = new CColorConvert(pYuvBuffer, image_width, image_height, UYV2);
                
                //pConvert->writeFile(DUMP_PATH "before_rotate.uyv", SOURCE);  
                //pConvert->writeFile(DUMP_PATH "before_rotate.bmp", BMP);      
               
                if(mCameraIndex == VGA_CAMERA )
                    pConvert->rotateImage(ROTATE_270);
                // else
                   // pConvert->flipImage(FLIP_VERTICAL);
                
                // write rotatet image back to input buffer
                //pConvert->writeFile(DUMP_PATH "after_rotate.bmp", BMP);   
                pConvert->makeUYV2(NULL, INPLACE);  //INPLACE: no new buffer, write to input buffer   
                image_width = pConvert->getWidth();
                image_height = pConvert->geHeight();
            }
#else

#endif            
			PPM("YUV COLOR ROTATION Done\n");           
         
             //pYuvBuffer: [Reused]Output buffer with YUV 420P 270 degree rotated.             
			if(mMsgEnabled & CAMERA_MSG_RAW_IMAGE)
			{   
                // convert pYuvBuffer(YUV422I) to mYUVPictureBuffer(YUV420P)
				Neon_Convert_yuv422_to_YUV420P(pYuvBuffer, (uint8_t *)mYUVNewheap->base(), image_width, image_height);         	
				mDataCb(CAMERA_MSG_RAW_IMAGE, mYUVPictureBuffer, mCallbackCookie);
			}

#endif //HARDWARE_OMX

			if (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)
			{
#ifdef HARDWARE_OMX  
                // int inputFormat = PIX_YUV420P;
                // int imputSize = image_width * image_height * PIX_YUV420P_BYTES_PER_PIXEL; 

                int inputFormat = PIX_YUV422I;
                int inputSize = image_width * image_height * PIX_YUV422I_BYTES_PER_PIXEL;
				int jpegSize = image_width * image_height * JPG_BYTES_PER_PIXEL;
                
				CreateExif(NULL, 0, pExifBuf, exifDataSize, EXIF_NOTSET_JPEG_LENGTH);
				HAL_PRINT("VGA EXIF size : %d\n", exifDataSize);
                
				mJPEGPictureHeap = new MemoryHeapBase(jpegSize + 256);
				outBuffer = (void *)((unsigned long)(mJPEGPictureHeap->getBase()) + 128);


      
				HAL_PRINT("YUV capture : outbuffer = 0x%x, jpegSize = %d, pYuvBuffer = 0x%x, yuv_len = %d, image_width = %d, image_height = %d, quality = %d, mippMode =%d\n", 
							outBuffer, jpegSize, pYuvBuffer, capture_len, image_width, image_height, mYcbcrQuality, mippMode); 

				if(jpegEncoder)
				{
                	PPM("BEFORE JPEG Encode Image\n");
					err = jpegEncoder->encodeImage(
                            outBuffer,                          // void* outputBuffer, 
                            jpegSize,                           // int outBuffSize, 
                            pYuvBuffer,                         // void *inputBuffer, 
                            inputSize,                          // int inBuffSize, 
                            pExifBuf,                           // unsigned char* pExifBuf,
                            exifDataSize,                       // int ExifSize,
                            image_width,	                    // int width, 
                            image_height,	                    // int height, 
                            mThumbnailWidth,                    // int ThumbWidth, 
                            mThumbnailHeight,                   // int ThumbHeight, 
                            mYcbcrQuality,                      // int quality,
                            inputFormat);                       // int isPixelFmt420p)
                    PPM("AFTER JPEG Encode Image\n");
					LOGD("JPEG ENCODE END\n");

					if(err != true) 
                    {
						LOGE("Jpeg encode failed!!\n");
						return -1;
					} 
                    else 
						LOGD("Jpeg encode success!!\n");
				}

				mJPEGPictureMemBase = new MemoryBase(mJPEGPictureHeap, 128, jpegEncoder->jpegSize);

				if (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)
				{
					mDataCb(CAMERA_MSG_COMPRESSED_IMAGE, mJPEGPictureMemBase, mCallbackCookie);
				}

				mJPEGPictureMemBase.clear();
				mJPEGPictureHeap.clear();
#endif //HARDWARE_OMX
			}//END of CAMERA_MSG_COMPRESSED_IMAGE
       

 
#ifdef R3D4_CONVERT 
            delete pConvert;  
#endif            

            
		}//END of CAMERA_MODE_YUV
        
		mPictureBuffer.clear();
		mPictureHeap.clear();
        
		if(mCamera_Mode == CAMERA_MODE_JPEG)
		{
			mFinalPictureBuffer.clear();
			mFinalPictureHeap.clear();

		}
         
        mYUVPictureBuffer.clear();
        mYUVPictureHeap.clear();
        
		delete []pExifBuf;
		mCaptureFlag = false;
                
		LOG_FUNCTION_NAME_EXIT

		return NO_ERROR;

	}