author | shanghai engineers <yuxi.sun@droid09.amlogic.com> | 2014-11-05 02:21:40 (GMT) |
---|---|---|
committer | shanghai engineers <yuxi.sun@droid09.amlogic.com> | 2014-11-05 02:34:20 (GMT) |
commit | 39bf8d9b342cc6c955b6b2510d0cd4d33d5510db (patch) | |
tree | bcb936562e84df3439ad50944769010558aaac67 | |
parent | 88e27cb1b6b4a4412d82bd142836090864300365 (diff) | |
download | camera-39bf8d9b342cc6c955b6b2510d0cd4d33d5510db.zip camera-39bf8d9b342cc6c955b6b2510d0cd4d33d5510db.tar.gz camera-39bf8d9b342cc6c955b6b2510d0cd4d33d5510db.tar.bz2 |
Add sensor format function and set right format based on it
Change-Id: I4f9aec1a415a8abfcac3c21cbe771febad80c4bf
Signed-off-by: shanghai engineers <yuxi.sun@droid09.amlogic.com>
-rwxr-xr-x | v3/EmulatedFakeCamera3.cpp | 2 | ||||
-rwxr-xr-x | v3/fake-pipeline2/Sensor.cpp | 187 | ||||
-rwxr-xr-x | v3/fake-pipeline2/Sensor.h | 4 |
3 files changed, 180 insertions, 13 deletions
diff --git a/v3/EmulatedFakeCamera3.cpp b/v3/EmulatedFakeCamera3.cpp index da0a1ce..f7228ae 100755 --- a/v3/EmulatedFakeCamera3.cpp +++ b/v3/EmulatedFakeCamera3.cpp @@ -403,7 +403,7 @@ status_t EmulatedFakeCamera3::configureStreams( if (isRestart) { mSensor->streamOff(); - pixelfmt = mSensor->getOutputFormat(pixelfmt); + pixelfmt = mSensor->halFormatToSensorFormat(pixelfmt); mSensor->setOutputFormat(width, height, pixelfmt); mSensor->streamOn(); DBG_LOGB("width=%d, height=%d, pixelfmt=%.4s\n", diff --git a/v3/fake-pipeline2/Sensor.cpp b/v3/fake-pipeline2/Sensor.cpp index f8f6f9f..dcc9082 100755 --- a/v3/fake-pipeline2/Sensor.cpp +++ b/v3/fake-pipeline2/Sensor.cpp @@ -215,7 +215,43 @@ status_t Sensor::streamOff() { return stop_capturing(vinfo); } -int Sensor::getOutputFormat(int pixelfmt) +int Sensor::getOutputFormat() +{ + struct v4l2_fmtdesc fmt; + int ret; + memset(&fmt,0,sizeof(fmt)); + fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + fmt.index = 0; + while ((ret = ioctl(vinfo->fd, VIDIOC_ENUM_FMT, &fmt)) == 0){ + if (fmt.pixelformat == V4L2_PIX_FMT_MJPEG) + return V4L2_PIX_FMT_MJPEG; + fmt.index++; + } + + fmt.index = 0; + while ((ret = ioctl(vinfo->fd, VIDIOC_ENUM_FMT, &fmt)) == 0){ + if (fmt.pixelformat == V4L2_PIX_FMT_NV21) + return V4L2_PIX_FMT_NV21; + fmt.index++; + } + + fmt.index = 0; + while ((ret = ioctl(vinfo->fd, VIDIOC_ENUM_FMT, &fmt)) == 0){ + if (fmt.pixelformat == V4L2_PIX_FMT_YUYV) + return V4L2_PIX_FMT_YUYV; + fmt.index++; + } + + ALOGE("Unable to find a supported sensor format!"); + return BAD_VALUE; +} + +/* if sensor supports MJPEG, return it first, otherwise + * trasform HAL format to v4l2 format then check whether + * it is supported. + */ +int Sensor::halFormatToSensorFormat(int pixelfmt) { struct v4l2_fmtdesc fmt; int ret; @@ -238,14 +274,14 @@ int Sensor::getOutputFormat(int pixelfmt) return V4L2_PIX_FMT_MJPEG; fmt.index++; } - + fmt.index = 0; while ((ret = ioctl(vinfo->fd, VIDIOC_ENUM_FMT, &fmt)) == 0){ if (fmt.pixelformat == pixelfmt) return pixelfmt; fmt.index++; } - + ALOGE("Unable to find a supported sensor format!"); return BAD_VALUE; } @@ -930,6 +966,9 @@ bool Sensor::threadLoop() { case HAL_PIXEL_FORMAT_YV12: captureYV12(b.img, gain, b.stride); break; + case HAL_PIXEL_FORMAT_YCbCr_422_I: + captureYUYV(b.img, gain, b.stride); + break; default: ALOGE("%s: Unknown format %x, no output", __FUNCTION__, b.format); @@ -980,13 +1019,8 @@ int Sensor::getStreamConfigurations(int32_t picSizes[], const int32_t kAvailable } } - memset(&frmsize,0,sizeof(frmsize)); - for (size_t f = 0;f < sizeof(kAvailableFormats)/sizeof(kAvailableFormats[0]);f++) { - frmsize.pixel_format = getOutputFormat(kAvailableFormats[f]); - if (frmsize.pixel_format == V4L2_PIX_FMT_MJPEG) - break; //USB camera must be MJPEG - } + frmsize.pixel_format = getOutputFormat(); START = 0; for(i=0;;i++, count+=4){ @@ -1081,6 +1115,55 @@ int Sensor::getStreamConfigurations(int32_t picSizes[], const int32_t kAvailable } + if (frmsize.pixel_format == V4L2_PIX_FMT_YUYV) { + START = count; + for(i=0;;i++, count+=4){ + frmsize.index = i; + res = ioctl(vinfo->fd, VIDIOC_ENUM_FRAMESIZES, &frmsize); + if (res < 0){ + DBG_LOGB("index=%d, break\n", i); + break; + } + + if(frmsize.type == V4L2_FRMSIZE_TYPE_DISCRETE){ //only support this type + + if (0 != (frmsize.discrete.width%16)) + continue; + + if((frmsize.discrete.width > support_w) && (frmsize.discrete.height >support_h)) + continue; + + if (count >= size) + break; + + picSizes[count+0] = HAL_PIXEL_FORMAT_YCbCr_422_I; + picSizes[count+1] = frmsize.discrete.width; + picSizes[count+2] = frmsize.discrete.height; + picSizes[count+3] = ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT; + + DBG_LOGB("get output width=%d, height=%d, format =\ + HAL_PIXEL_FORMAT_YCbCr_420_888\n", frmsize.discrete.width, + frmsize.discrete.height); + if (0 == i) + continue; + + for (k = count; k > START; k -= 4) { + if (frmsize.discrete.width * frmsize.discrete.height > + picSizes[k - 3] * picSizes[k - 2]) { + picSizes[k + 1] = picSizes[k - 3]; + picSizes[k + 2] = picSizes[k - 2]; + + } else { + break; + } + } + picSizes[k + 1] = frmsize.discrete.width; + picSizes[k + 2] = frmsize.discrete.height; + } + + } + } + uint32_t jpgSrcfmt[] = { V4L2_PIX_FMT_RGB24, V4L2_PIX_FMT_YUYV, @@ -1147,7 +1230,6 @@ int Sensor::getStreamConfigurations(int32_t picSizes[], const int32_t kAvailable } - int Sensor::getStreamConfigurationDurations(int32_t picSizes[], int64_t duration[], int size) { int ret=0; int framerate=0; int temp_rate=0; @@ -1161,7 +1243,7 @@ int Sensor::getStreamConfigurationDurations(int32_t picSizes[], int64_t duration V4L2_PIX_FMT_NV21, V4L2_PIX_FMT_RGB24, V4L2_PIX_FMT_MJPEG, - // V4L2_PIX_FMT_YUYV, + V4L2_PIX_FMT_YUYV, // V4L2_PIX_FMT_YVU420 }; @@ -1716,5 +1798,88 @@ void Sensor::captureYV12(uint8_t *img, uint32_t gain, uint32_t stride) { ALOGVV("YV12 sensor image captured"); } +void Sensor::captureYUYV(uint8_t *img, uint32_t gain, uint32_t stride) { +#if 0 + float totalGain = gain/100.0 * kBaseGainFactor; + // Using fixed-point math with 6 bits of fractional precision. + // In fixed-point math, calculate total scaling from electrons to 8bpp + const int scale64x = 64 * totalGain * 255 / kMaxRawValue; + // In fixed-point math, saturation point of sensor after gain + const int saturationPoint = 64 * 255; + // Fixed-point coefficients for RGB-YUV transform + // Based on JFIF RGB->YUV transform. + // Cb/Cr offset scaled by 64x twice since they're applied post-multiply + const int rgbToY[] = {19, 37, 7}; + const int rgbToCb[] = {-10,-21, 32, 524288}; + const int rgbToCr[] = {32,-26, -5, 524288}; + // Scale back to 8bpp non-fixed-point + const int scaleOut = 64; + const int scaleOutSq = scaleOut * scaleOut; // after multiplies + + uint32_t inc = kResolution[0] / stride; + uint32_t outH = kResolution[1] / inc; + for (unsigned int y = 0, outY = 0; + y < kResolution[1]; y+=inc, outY++) { + uint8_t *pxY = img + outY * stride; + uint8_t *pxVU = img + (outH + outY / 2) * stride; + mScene.setReadoutPixel(0,y); + for (unsigned int outX = 0; outX < stride; outX++) { + int32_t rCount, gCount, bCount; + // TODO: Perfect demosaicing is a cheat + const uint32_t *pixel = mScene.getPixelElectrons(); + rCount = pixel[Scene::R] * scale64x; + rCount = rCount < saturationPoint ? rCount : saturationPoint; + gCount = pixel[Scene::Gr] * scale64x; + gCount = gCount < saturationPoint ? gCount : saturationPoint; + bCount = pixel[Scene::B] * scale64x; + bCount = bCount < saturationPoint ? bCount : saturationPoint; + + *pxY++ = (rgbToY[0] * rCount + + rgbToY[1] * gCount + + rgbToY[2] * bCount) / scaleOutSq; + if (outY % 2 == 0 && outX % 2 == 0) { + *pxVU++ = (rgbToCr[0] * rCount + + rgbToCr[1] * gCount + + rgbToCr[2] * bCount + + rgbToCr[3]) / scaleOutSq; + *pxVU++ = (rgbToCb[0] * rCount + + rgbToCb[1] * gCount + + rgbToCb[2] * bCount + + rgbToCb[3]) / scaleOutSq; + } + for (unsigned int j = 1; j < inc; j++) + mScene.getPixelElectrons(); + } + } +#else + uint8_t *src; + if (mKernelBuffer) { + src = mKernelBuffer; + if (vinfo->preview.format.fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) + memcpy(img, src, vinfo->preview.buf.length); + else + ALOGE("Unable known sensor format: %d", vinfo->preview.format.fmt.pix.pixelformat); + + return ; + } + + while(1) { + src = (uint8_t *)get_frame(vinfo); + usleep(30000); + if (NULL == src) + continue; + if (vinfo->preview.format.fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) { + memcpy(img, src, vinfo->preview.buf.length); + } else { + ALOGE("Unable known sensor format: %d", vinfo->preview.format.fmt.pix.pixelformat); + } + + break; + } +#endif + mKernelBuffer = src; + ALOGVV("YUYV sensor image captured"); +} + } // namespace android diff --git a/v3/fake-pipeline2/Sensor.h b/v3/fake-pipeline2/Sensor.h index 7d1c1d9..7a9f474 100755 --- a/v3/fake-pipeline2/Sensor.h +++ b/v3/fake-pipeline2/Sensor.h @@ -163,7 +163,8 @@ class Sensor: private Thread, public virtual RefBase { status_t startUp(int idx); status_t shutDown(); - int getOutputFormat(int pixelformat); + int getOutputFormat(); + int halFormatToSensorFormat(int pixelfmt); status_t setOutputFormat(int width, int height, int pixelformat); void setPictureRotate(int rotate); int getPictureRotate(); @@ -330,6 +331,7 @@ class Sensor: private Thread, public virtual RefBase { void captureRGB(uint8_t *img, uint32_t gain, uint32_t stride); void captureNV21(uint8_t *img, uint32_t gain, uint32_t stride); void captureYV12(uint8_t *img, uint32_t gain, uint32_t stride); + void captureYUYV(uint8_t *img, uint32_t gain, uint32_t stride); void YUYVToNV21(uint8_t *src, uint8_t *dst, int width, int height); void YUYVToYV12(uint8_t *src, uint8_t *dst, int width, int height); }; |