summaryrefslogtreecommitdiffstats
path: root/libcamera
diff options
context:
space:
mode:
Diffstat (limited to 'libcamera')
-rw-r--r--libcamera/SecCameraHWInterface.cpp159
1 files changed, 45 insertions, 114 deletions
diff --git a/libcamera/SecCameraHWInterface.cpp b/libcamera/SecCameraHWInterface.cpp
index c316ea6..34f1009 100644
--- a/libcamera/SecCameraHWInterface.cpp
+++ b/libcamera/SecCameraHWInterface.cpp
@@ -39,22 +39,18 @@
#define BACK_CAMERA_INFINITY_FOCUS_DISTANCES_STR "0.10,1.20,Infinity"
#define FRONT_CAMERA_FOCUS_DISTANCES_STR "0.20,0.25,Infinity"
-// This hack does two things:
-// -- it sets preview to NV21 (YUV420SP)
-// -- it sets gralloc to YV12
+// FIXME:
+// -- The actual preview color is set to YV12. The preview frames
+// returned via preview callback must be generated by color
+// conversion if the requested preview color format for the
+// preview frames is _not_ YV12. The reason that YV12 is used
+// for actual preview is because that is the only color format
+// supported by gralloc. Matching the preview cor format with
+// gralloc color format improves performance since no color
+// conversion is needed for preview.
//
-// The reason being: the samsung encoder understands only yuv420sp, and gralloc
-// does yv12 and rgb565. So what we do is we break up the interleaved UV in
-// separate V and U planes, which makes preview look good, and enabled the
-// encoder as well.
-//
-// FIXME: Samsung needs to enable support for proper yv12 coming out of the
-// camera, and to fix their video encoder to work with yv12.
-// FIXME: It also seems like either Samsung's YUV420SP (NV21) or img's YV12 has
-// the color planes switched. We need to figure which side is doing it
-// wrong and have the respective party fix it.
-
-#define HACK 0
+// -- we only support two preview color formats that client
+// applications can set: NV21 and YUV420/YV12.
namespace android {
@@ -181,20 +177,13 @@ void CameraHardwareSec::initDefaultParameters(int cameraId)
&snapshot_max_height) < 0)
LOGE("getSnapshotMaxSize fail (%d / %d) \n",
snapshot_max_width, snapshot_max_height);
-
-// p.setPreviewFormat(CameraParameters::PIXEL_FORMAT_RGB565);
-// p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FORMATS, CameraParameters::PIXEL_FORMAT_RGB565);
-// p.set(CameraParameters::KEY_VIDEO_FRAME_FORMAT, CameraParameters::PIXEL_FORMAT_RGB565);
-#if HACK
+ String8 previewColorString;
+ previewColorString = CameraParameters::PIXEL_FORMAT_YUV420SP;
+ previewColorString.append(",");
+ previewColorString.append(CameraParameters::PIXEL_FORMAT_YUV420P);
p.setPreviewFormat(CameraParameters::PIXEL_FORMAT_YUV420SP); mFrameSizeDelta = 16;
- p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FORMATS, CameraParameters::PIXEL_FORMAT_YUV420SP);
- p.set(CameraParameters::KEY_VIDEO_FRAME_FORMAT, CameraParameters::PIXEL_FORMAT_YUV420SP);
-#else
- p.setPreviewFormat(CameraParameters::PIXEL_FORMAT_YUV420P); mFrameSizeDelta = 16;
- p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FORMATS, CameraParameters::PIXEL_FORMAT_YUV420P);
+ p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FORMATS, previewColorString.string());
p.set(CameraParameters::KEY_VIDEO_FRAME_FORMAT, CameraParameters::PIXEL_FORMAT_YUV420P);
-#endif
-// p.setPreviewFormat(CameraParameters::PIXEL_FORMAT_YUV420P); mFrameSizeDelta = 16;
p.setPreviewSize(preview_max_width, preview_max_height);
p.setPictureFormat(CameraParameters::PIXEL_FORMAT_JPEG);
@@ -411,36 +400,12 @@ status_t CameraHardwareSec::setPreviewWindow(preview_stream_ops *w)
int preview_width;
int preview_height;
mParameters.getPreviewSize(&preview_width, &preview_height);
-
- int hal_pixel_format;
+ int hal_pixel_format = HAL_PIXEL_FORMAT_YV12;
const char *str_preview_format = mParameters.getPreviewFormat();
LOGV("%s: preview format %s", __func__, str_preview_format);
mFrameSizeDelta = 16;
- hal_pixel_format = HAL_PIXEL_FORMAT_YV12; // default
-
- if (!strcmp(str_preview_format,
- CameraParameters::PIXEL_FORMAT_RGB565)) {
- hal_pixel_format = HAL_PIXEL_FORMAT_RGB_565;
- mFrameSizeDelta = 0;
- }
- else if (!strcmp(str_preview_format,
- CameraParameters::PIXEL_FORMAT_RGBA8888)) {
- hal_pixel_format = HAL_PIXEL_FORMAT_RGBA_8888;
- mFrameSizeDelta = 0;
- }
- else if (!strcmp(str_preview_format,
- CameraParameters::PIXEL_FORMAT_YUV420SP)) {
-#if HACK
- hal_pixel_format = HAL_PIXEL_FORMAT_YV12;
-#else
- hal_pixel_format = HAL_PIXEL_FORMAT_YCrCb_420_SP;
-#endif
- } else if (!strcmp(str_preview_format,
- CameraParameters::PIXEL_FORMAT_YUV420P))
- hal_pixel_format = HAL_PIXEL_FORMAT_YV12; // HACK
-
if (w->set_usage(w, GRALLOC_USAGE_SW_WRITE_OFTEN)) {
LOGE("%s: could not set usage on gralloc buffer", __func__);
return INVALID_OPERATION;
@@ -601,7 +566,7 @@ int CameraHardwareSec::previewThread()
char *frame = ((char *)mPreviewHeap->data) + offset;
int total = frame_size + mFrameSizeDelta;
-// HACK or no HACK, the code below assumes YUV, not RGB
+ // the code below assumes YUV, not RGB
{
int h;
char *src = frame;
@@ -614,40 +579,7 @@ int CameraHardwareSec::previewThread()
src += width;
}
- if (HACK) {
- // The incoming data is in NV21 format, and we need to
- // convert it to YV12 for the gralloc buffer.
-
- char *uv = src;
- const int uv_size = width * height / 2;
- char saved_uv[uv_size];
- memcpy(saved_uv, src, uv_size);
-
- // first, collapse the V chroma pixels into their own plane
- // following the Y plane.
- h = 0;
- while (h < width * height / 4) {
- *ptr++ = *src;
- src += 2;
- h++;
- if (!(h % (width / 2)))
- ptr += (stride - width) / 2;
- }
-
- // next, use the saved_uv plane and collapse the U chroma
- // pixels into their own plane following the newly-created
- // V plane.
- h = 0;
- src = saved_uv + 1;
- while (h < width * height / 4) {
- *ptr++ = *src;
- src += 2;
- h++;
- if (!(h % (width / 2)))
- ptr += (stride - width) / 2;
- }
- }
- else {
+ {
// U
char *v = ptr;
ptr += stride * height / 4;
@@ -679,8 +611,26 @@ int CameraHardwareSec::previewThread()
callbacks:
// Notify the client of a new frame.
- if (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME)
+ if (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME) {
+ const char * preview_format = mParameters.getPreviewFormat();
+ if (!strcmp(preview_format, CameraParameters::PIXEL_FORMAT_YUV420SP)) {
+ // Color conversion from YUV420 to NV21
+ char *vu = ((char *)mPreviewHeap->data) + offset + width * height;
+ const int uv_size = (width * height) >> 1;
+ char saved_uv[uv_size];
+ memcpy(saved_uv, vu, uv_size);
+ char *u = saved_uv;
+ char *v = u + (uv_size >> 1);
+
+ int h = 0;
+ while (h < width * height / 4) {
+ *vu++ = *v++;
+ *vu++ = *u++;
+ ++h;
+ }
+ }
mDataCb(CAMERA_MSG_PREVIEW_FRAME, mPreviewHeap, index, NULL, mCallbackCookie);
+ }
Mutex::Autolock lock(mRecordLock);
if (mRecordRunning == true) {
@@ -1615,36 +1565,17 @@ status_t CameraHardwareSec::setParameters(const CameraParameters& params)
LOGV("%s : new_preview_width x new_preview_height = %dx%d, format = %s",
__func__, new_preview_width, new_preview_height, new_str_preview_format);
+ if (strcmp(new_str_preview_format, CameraParameters::PIXEL_FORMAT_YUV420SP) &&
+ strcmp(new_str_preview_format, CameraParameters::PIXEL_FORMAT_YUV420P)) {
+ LOGE("Unsupported preview color format: %s", new_str_preview_format);
+ return BAD_VALUE;
+ }
+
if (0 < new_preview_width && 0 < new_preview_height &&
new_str_preview_format != NULL &&
isSupportedPreviewSize(new_preview_width, new_preview_height)) {
- int new_preview_format = 0;
-
+ int new_preview_format = V4L2_PIX_FMT_YUV420;
mFrameSizeDelta = 16;
- if (!strcmp(new_str_preview_format,
- CameraParameters::PIXEL_FORMAT_RGB565)) {
- new_preview_format = V4L2_PIX_FMT_RGB565;
- mFrameSizeDelta = 0;
- }
- else if (!strcmp(new_str_preview_format,
- CameraParameters::PIXEL_FORMAT_RGBA8888)) {
- new_preview_format = V4L2_PIX_FMT_RGB32;
- mFrameSizeDelta = 0;
- }
- else if (!strcmp(new_str_preview_format,
- CameraParameters::PIXEL_FORMAT_YUV420SP))
- new_preview_format = V4L2_PIX_FMT_NV21;
- else if (!strcmp(new_str_preview_format,
- CameraParameters::PIXEL_FORMAT_YUV420P))
- new_preview_format = V4L2_PIX_FMT_YUV420;
- else if (!strcmp(new_str_preview_format, "yuv420sp_custom"))
- new_preview_format = V4L2_PIX_FMT_NV12T;
- else if (!strcmp(new_str_preview_format, "yuv422i"))
- new_preview_format = V4L2_PIX_FMT_YUYV;
- else if (!strcmp(new_str_preview_format, "yuv422p"))
- new_preview_format = V4L2_PIX_FMT_YUV422P;
- else
- new_preview_format = V4L2_PIX_FMT_NV21; //for 3rd party
int current_preview_width, current_preview_height, current_frame_size;
mSecCamera->getPreviewSize(&current_preview_width,