diff --git a/tools/emulator/system/camera/EmulatedCamera.cpp b/tools/emulator/system/camera/EmulatedCamera.cpp index 02b4683f6..f7f6eea56 100755 --- a/tools/emulator/system/camera/EmulatedCamera.cpp +++ b/tools/emulator/system/camera/EmulatedCamera.cpp @@ -28,7 +28,7 @@ #include #include #include "EmulatedCamera.h" -#include "EmulatedFakeCameraDevice.h" +//#include "EmulatedFakeCameraDevice.h" #include "Converters.h" /* Defines whether we should trace parameter changes. */ @@ -99,12 +99,8 @@ status_t EmulatedCamera::Initialize() * Fake required parameters. */ - mParameters.set(CameraParameters::KEY_SUPPORTED_JPEG_THUMBNAIL_SIZES, - "320x240,0x0"); - mParameters.set(CameraParameters::KEY_MAX_EXPOSURE_COMPENSATION, "6"); - mParameters.set(CameraParameters::KEY_MIN_EXPOSURE_COMPENSATION, "-6"); - mParameters.set(CameraParameters::KEY_EXPOSURE_COMPENSATION_STEP, "0.5"); - mParameters.set(CameraParameters::KEY_EXPOSURE_COMPENSATION, "0"); + mParameters.set(CameraParameters::KEY_SUPPORTED_JPEG_THUMBNAIL_SIZES, "320x240,0x0"); + mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH, "512"); mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT, "384"); mParameters.set(CameraParameters::KEY_JPEG_QUALITY, "90"); @@ -137,10 +133,22 @@ status_t EmulatedCamera::Initialize() CameraParameters::PIXEL_FORMAT_JPEG); mParameters.setPictureFormat(CameraParameters::PIXEL_FORMAT_JPEG); - /* - * Not supported features - */ + /* Sets the default exposure compensation support to be disabled. */ + mParameters.set(CameraParameters::KEY_MAX_EXPOSURE_COMPENSATION, "0"); + mParameters.set(CameraParameters::KEY_MIN_EXPOSURE_COMPENSATION, "0"); + /* Sets auto white balance as default. */ + getCameraDevice()->initializeWhiteBalanceModes( + CameraParameters::WHITE_BALANCE_AUTO, 1.0f, 1.0f); + mParameters.set(CameraParameters::KEY_SUPPORTED_WHITE_BALANCE, + CameraParameters::WHITE_BALANCE_AUTO); + mParameters.set(CameraParameters::KEY_WHITE_BALANCE, + CameraParameters::WHITE_BALANCE_AUTO); + getCameraDevice()->setWhiteBalanceMode( + mParameters.get(CameraParameters::KEY_WHITE_BALANCE)); + + /* Not supported features + */ mParameters.set(CameraParameters::KEY_SUPPORTED_FOCUS_MODES, CameraParameters::FOCUS_MODE_FIXED); mParameters.set(CameraParameters::KEY_FOCUS_MODE, @@ -408,6 +416,9 @@ status_t EmulatedCamera::setParameters(const char* parms) String8 str8_param(parms); new_param.unflatten(str8_param); + /* + * Check for new exposure compensation parameter. + */ int new_exposure_compensation = new_param.getInt( CameraParameters::KEY_EXPOSURE_COMPENSATION); const int min_exposure_compensation = new_param.getInt( @@ -435,6 +446,24 @@ status_t EmulatedCamera::setParameters(const char* parms) exposure_value); } } + + const char* new_white_balance = new_param.get( + CameraParameters::KEY_WHITE_BALANCE); + const char* supported_white_balance = new_param.get( + CameraParameters::KEY_SUPPORTED_WHITE_BALANCE); + + if ((supported_white_balance != NULL) && (new_white_balance != NULL) && + (strstr(supported_white_balance, new_white_balance) != NULL)) { + + const char* current_white_balance = mParameters.get( + CameraParameters::KEY_WHITE_BALANCE); + if ((current_white_balance == NULL) || + (strcmp(current_white_balance, new_white_balance) != 0)) { + LOGV("Setting white balance to %s", new_white_balance); + getCameraDevice()->setWhiteBalanceMode(new_white_balance); + } + } + mParameters = new_param; return NO_ERROR; diff --git a/tools/emulator/system/camera/EmulatedCameraDevice.cpp b/tools/emulator/system/camera/EmulatedCameraDevice.cpp index 71464d201..eab169c67 100755 --- a/tools/emulator/system/camera/EmulatedCameraDevice.cpp +++ b/tools/emulator/system/camera/EmulatedCameraDevice.cpp @@ -29,25 +29,33 @@ #include #include #include "EmulatedCameraDevice.h" -#include "Converters.h" namespace android { +const float GAMMA_CORRECTION = 2.2f; EmulatedCameraDevice::EmulatedCameraDevice(EmulatedCamera* camera_hal) : mObjectLock(), mCurFrameTimestamp(0), mCameraHAL(camera_hal), mCurrentFrame(NULL), mExposureCompensation(1.0f), + mWhiteBalanceScale(NULL), + mSupportedWhiteBalanceScale(), mState(ECDS_CONSTRUCTED) { } EmulatedCameraDevice::~EmulatedCameraDevice() { + LOGV("EmulatedCameraDevice destructor"); if (mCurrentFrame != NULL) { delete[] mCurrentFrame; } + for (int i = 0; i < mSupportedWhiteBalanceScale.size(); ++i) { + if (mSupportedWhiteBalanceScale.valueAt(i) != NULL) { + delete[] mSupportedWhiteBalanceScale.valueAt(i); + } + } } /**************************************************************************** @@ -110,10 +118,43 @@ void EmulatedCameraDevice::setExposureCompensation(const float ev) { LOGW("%s: Fake camera device is not started.", __FUNCTION__); } - mExposureCompensation = std::pow(2.0f, ev); + mExposureCompensation = std::pow(2.0f, ev / GAMMA_CORRECTION); LOGV("New exposure compensation is %f", mExposureCompensation); } +void EmulatedCameraDevice::initializeWhiteBalanceModes(const char* mode, + const float r_scale, + const float b_scale) { + LOGV("%s with %s, %f, %f", __FUNCTION__, mode, r_scale, b_scale); + float* value = new float[3]; + value[0] = r_scale; value[1] = 1.0f; value[2] = b_scale; + mSupportedWhiteBalanceScale.add(String8(mode), value); +} + +void EmulatedCameraDevice::setWhiteBalanceMode(const char* mode) { + LOGV("%s with white balance %s", __FUNCTION__, mode); + mWhiteBalanceScale = + mSupportedWhiteBalanceScale.valueFor(String8(mode)); +} + +/* Computes the pixel value after adjusting the white balance to the current + * one. The input the y, u, v channel of the pixel and the adjusted value will + * be stored in place. The adjustment is done in RGB space. + */ +void EmulatedCameraDevice::changeWhiteBalance(uint8_t& y, + uint8_t& u, + uint8_t& v) const { + float r_scale = mWhiteBalanceScale[0]; + float b_scale = mWhiteBalanceScale[2]; + int r = static_cast(YUV2R(y, u, v)) / r_scale; + int g = YUV2G(y, u, v); + int b = static_cast(YUV2B(y, u, v)) / b_scale; + + y = RGB2Y(r, g, b); + u = RGB2U(r, g, b); + v = RGB2V(r, g, b); +} + status_t EmulatedCameraDevice::getCurrentPreviewFrame(void* buffer) { if (!isStarted()) { diff --git a/tools/emulator/system/camera/EmulatedCameraDevice.h b/tools/emulator/system/camera/EmulatedCameraDevice.h index 357c9e6dd..b0999063b 100755 --- a/tools/emulator/system/camera/EmulatedCameraDevice.h +++ b/tools/emulator/system/camera/EmulatedCameraDevice.h @@ -27,7 +27,10 @@ */ #include +#include +#include #include "EmulatedCameraCommon.h" +#include "Converters.h" namespace android { @@ -116,6 +119,21 @@ public: */ virtual status_t Initialize(); + /* Initializes the white balance modes parameters. + * The parameters are passed by each individual derived camera API to + * represent that different camera manufacturers may have different + * preferences on the white balance parameters. Green channel in the RGB + * color space is fixed to keep the luminance to be reasonably constant. + * + * Param: + * mode the text describing the current white balance mode + * r_scale the scale factor for the R channel in RGB space + * b_scale the scale factor for the B channel in RGB space. + */ + void initializeWhiteBalanceModes(const char* mode, + const float r_scale, + const float b_scale); + /* Starts delivering frames captured from the camera device. * This method will start the worker thread that would be pulling frames from * the camera device, and will deliver the pulled frames back to the emulated @@ -145,7 +163,11 @@ public: /* Sets the exposure compensation for the camera device. */ - virtual void setExposureCompensation(const float ev); + void setExposureCompensation(const float ev); + + /* Sets the white balance mode for the device. + */ + void setWhiteBalanceMode(const char* mode); /* Gets current framebuffer, converted into preview frame format. * This method must be called on a connected instance of this class with a @@ -269,6 +291,24 @@ protected: */ virtual void commonStopDevice(); + /** Computes a luminance value after taking the exposure compensation. + * value into account. + * + * Param: + * inputY - The input luminance value. + * Return: + * The luminance value after adjusting the exposure compensation. + */ + inline uint8_t changeExposure(const uint8_t& inputY) const { + return static_cast(clamp(static_cast(inputY) * + mExposureCompensation)); + } + + /** Computes the pixel value in YUV space after adjusting to the current + * white balance mode. + */ + void changeWhiteBalance(uint8_t& y, uint8_t& u, uint8_t& v) const; + /**************************************************************************** * Worker thread management. * Typicaly when emulated camera device starts capturing frames from the @@ -478,6 +518,10 @@ protected: /* Exposure compensation value */ float mExposureCompensation; + float* mWhiteBalanceScale; + + DefaultKeyedVector mSupportedWhiteBalanceScale; + /* Defines possible states of the emulated camera device object. */ enum EmulatedCameraDeviceState { diff --git a/tools/emulator/system/camera/EmulatedFakeCamera.cpp b/tools/emulator/system/camera/EmulatedFakeCamera.cpp index d82fd787f..9d54f3884 100755 --- a/tools/emulator/system/camera/EmulatedFakeCamera.cpp +++ b/tools/emulator/system/camera/EmulatedFakeCamera.cpp @@ -61,6 +61,33 @@ status_t EmulatedFakeCamera::Initialize() gEmulatedCameraFactory.getFakeCameraOrientation()); res = EmulatedCamera::Initialize(); + + mParameters.set(CameraParameters::KEY_MAX_EXPOSURE_COMPENSATION, "6"); + mParameters.set(CameraParameters::KEY_MIN_EXPOSURE_COMPENSATION, "-6"); + mParameters.set(CameraParameters::KEY_EXPOSURE_COMPENSATION_STEP, "0.5"); + mParameters.set(CameraParameters::KEY_EXPOSURE_COMPENSATION, "0"); + LOGV("Set camera supported exposure values"); + + // Sets the white balance modes and the device-dependent scale factors. + mFakeCameraDevice.initializeWhiteBalanceModes( + CameraParameters::WHITE_BALANCE_INCANDESCENT, 1.38f, 0.60f); + mFakeCameraDevice.initializeWhiteBalanceModes( + CameraParameters::WHITE_BALANCE_DAYLIGHT, 1.09f, 0.92f); + mFakeCameraDevice.initializeWhiteBalanceModes( + CameraParameters::WHITE_BALANCE_TWILIGHT, 0.92f, 1.22f); + + char supported_white_balance[1024]; + snprintf(supported_white_balance, sizeof(supported_white_balance), + "%s,%s,%s,%s", + mParameters.get(CameraParameters::KEY_SUPPORTED_WHITE_BALANCE), + CameraParameters::WHITE_BALANCE_INCANDESCENT, + CameraParameters::WHITE_BALANCE_DAYLIGHT, + CameraParameters::WHITE_BALANCE_TWILIGHT); + mParameters.set(CameraParameters::KEY_SUPPORTED_WHITE_BALANCE, + supported_white_balance); + + LOGV("Set camera supported white balance modes"); + if (res != NO_ERROR) { return res; } diff --git a/tools/emulator/system/camera/EmulatedFakeCameraDevice.cpp b/tools/emulator/system/camera/EmulatedFakeCameraDevice.cpp index 36668272e..1e1a01210 100755 --- a/tools/emulator/system/camera/EmulatedFakeCameraDevice.cpp +++ b/tools/emulator/system/camera/EmulatedFakeCameraDevice.cpp @@ -46,11 +46,11 @@ EmulatedFakeCameraDevice::EmulatedFakeCameraDevice(EmulatedFakeCamera* camera_ha { // Makes the image with the original exposure compensation darker. // So the effects of changing the exposure compensation can be seen. - mBlackYUV.Y = mBlackYUV.Y / 4; - mWhiteYUV.Y = mWhiteYUV.Y / 4; - mRedYUV.Y = mRedYUV.Y / 4; - mGreenYUV.Y = mGreenYUV.Y / 4; - mBlueYUV.Y = mBlueYUV.Y / 4; + mBlackYUV.Y = mBlackYUV.Y / 2; + mWhiteYUV.Y = mWhiteYUV.Y / 2; + mRedYUV.Y = mRedYUV.Y / 2; + mGreenYUV.Y = mGreenYUV.Y / 2; + mBlueYUV.Y = mBlueYUV.Y / 2; } EmulatedFakeCameraDevice::~EmulatedFakeCameraDevice() @@ -256,6 +256,9 @@ void EmulatedFakeCameraDevice::drawCheckerboard() uint8_t* U = U_pos; uint8_t* V = V_pos; + YUVPixel adjustedWhite = YUVPixel(mWhiteYUV); + changeWhiteBalance(adjustedWhite.Y, adjustedWhite.U, adjustedWhite.V); + for(int y = 0; y < mFrameHeight; y++) { int countx = checkxremainder; bool current = black; @@ -263,7 +266,7 @@ void EmulatedFakeCameraDevice::drawCheckerboard() if (current) { mBlackYUV.get(Y, U, V); } else { - mWhiteYUV.get(Y, U, V); + adjustedWhite.get(Y, U, V); } *Y = changeExposure(*Y); Y[1] = *Y; @@ -407,7 +410,7 @@ int EmulatedFakeCameraDevice::rotateFrame() } } else if (mCurrentFrameType == 0) { LOGD("********** Rotated to the CHECKERBOARD frame **********"); - } else { + } else if (mCurrentFrameType == 1) { LOGD("********** Rotated to the STRIPED frame **********"); } } diff --git a/tools/emulator/system/camera/EmulatedFakeCameraDevice.h b/tools/emulator/system/camera/EmulatedFakeCameraDevice.h index 0920be7a2..6f6d4f715 100755 --- a/tools/emulator/system/camera/EmulatedFakeCameraDevice.h +++ b/tools/emulator/system/camera/EmulatedFakeCameraDevice.h @@ -99,6 +99,7 @@ protected: ***************************************************************************/ private: + /* Draws a black and white checker board in the current frame buffer. */ void drawCheckerboard(); @@ -110,10 +111,6 @@ private: */ void drawSquare(int x, int y, int size, const YUVPixel* color); - inline uint8_t changeExposure(uint8_t inputY) { - return static_cast(static_cast(inputY) * - mExposureCompensation); - } #if EFCD_ROTATE_FRAME void drawSolid(YUVPixel* color); void drawStripes();