[Xiaomi Mi Note 2  ROMs, Kernels, Recoveries, & Oth] Mimi Mix:
tl;dr

I opened the blobs in a hex editor and changed two numbers

Magic!

Preface

This is my attempt at an explanation of what I think is wrong with the Mi Note 2 camera. My overall knowledge of all subjects involved is pretty limited and i may be downright wrong.

But, as wrong as I may be, what I found seems to actually fix something.

This development was motivated by the lack of working Google Camera mods on the Mi Note 2.

And I was, fortunately, somewhat successful!

If this is what you are looking for, go ahead and visit the Google Camera thread here https://xdaforums.com/mi-note-2/how-to/fix-camera-sensor-gcam-mod-t3782495

My goal with this thread is to share what I did, not only the files, but also the thought process behind the changes. You are free to do with them as you wish.

I am also opening discussion on the topic, if anyone more knowledgeable then me wants to chime in and help, I'd be extremely thankful.

I'll keep updating and editing this post with new information and any developments.

Intro

Let's start with what we know about our phone.

The Xiaomi Mi Note 2 has a 22,5MP Sony IMX318 CMOS image sensor.

This sensor has:

an Active Resolution of 5488 x 4112.

an Unit Cell Size of 1µm

a 6,31x Crop Factor.

What's wrong

With this information in mind, let's take a look at the libmmcamera_imx318.so file:

Snippet of file opened in Hex Workshop:

This is wrong.

Why it is wrong

Although I have no definitive answer as to why, I can make a few conjectures.

Only one Sony sensor has a 5344 x 4016 active resolution, a 1,12µm unit cell size and a 5,78x crop factor.

That's the Sony IMX230. Released in April 2015. Found inside a dozen phones and predecessor to the IMX318.

Maybe Xiaomi was planning to use this sensor inside the Mi Note 2 and on a last minute decision chose to go with the IMX318.

This change was hastily implemented and some leftover crumbs remained in the code.

The Fix

The only thing I changed was the active array size. I changed it from 5344 x 4016 to 5488 x 4112.

I'm currently testing the consequences of fixing the other incorrect values and further exploring the file for more inaccuracies.

Why it works

For this we need to take a look at the code for our Camera HAL3:

[B]Snippet from file: /QCamera2/HAL3/QCamera3CropRegionMapper.cpp[/B]

/*===========================================================================
* FUNCTION : update
*
* DESCRIPTION: update sensor active array size and sensor output size
*
* PARAMETERS :
* [MENTION=285871]active[/MENTION]_array_w : active array width
* [MENTION=285871]active[/MENTION]_array_h : active array height
* [MENTION=8139033]sensor_[/MENTION]w : sensor output width
* [MENTION=8139033]sensor_[/MENTION]h : sensor output height
*
* RETURN : none
*==========================================================================*/
void QCamera3CropRegionMapper::update(uint32_t active_array_w,
uint32_t active_array_h, uint32_t sensor_w,
uint32_t sensor_h)
{
// Sanity check
if (active_array_w == 0 || active_array_h == 0 ||
sensor_w == 0 || sensor_h == 0) {
ALOGE("%s: active_array size and sensor output size must be non zero",
__func__);
return;
}
if (active_array_w < sensor_w || active_array_h < sensor_h) {
ALOGE("%s: invalid input: active_array [%d, %d], sensor size [%d, %d]",
__func__, active_array_w, active_array_h, sensor_w, sensor_h);
return;
}
mSensorW = sensor_w;
mSensorH = sensor_h;
mActiveArrayW = active_array_w;
mActiveArrayH = active_array_h;

// Derive mapping from active array to sensor output size
// Assume the sensor first crops top/bottom, or left/right, (not both),
// before doing downscaling.
// sensor_w = (active_array_w - 2 * crop_w) / scale;
// sensor_h = (active_array_h - 2 * crop_y) / scale;
float scale_w = 1.0 * active_array_w / sensor_w;
float scale_h = 1.0 * active_array_h / sensor_h;
float scale = MIN(scale_w, scale_h);
uint32_t crop_w = 0, crop_h = 0;
if (scale_w > scale_h) {
crop_w = (active_array_w - sensor_w * active_array_h / sensor_h)/2;
} else {
crop_h = (active_array_h - sensor_h * active_array_w / sensor_w)/2;
}
mSensorCropW = crop_w;
mSensorCropH = crop_h;
mSensorScale = scale;

ALOGI("%s: active_array: %d x %d, sensor size %d x %d", __func__,
mActiveArrayW, mActiveArrayH, mSensorW, mSensorH);
ALOGI("%s: mSensorCrop is [%d, %d], and scale is %f", __func__,
mSensorCropW, mSensorCropH, mSensorScale);
}

This sanity check in particular

if (active_array_w < sensor_w || active_array_h < sensor_h) {
ALOGE("%s: invalid input: active_array [%d, %d], sensor size [%d, %d]", __func__, active_array_w, active_array_h, sensor_w, sensor_h);
return;
}

The active array size can never be smaller than the sensor output size.

The sensor output size is our desired output resolution. The resolution in which we want to take photos or capture videos.

The camera HAL then takes our active array size and crops it to the desired output size. It can't do the opposite. The active array size is the highest possible image size the CMOS is capable of outputting.

So what happens when the driver file is telling the camera HAL the active array size is 5344 x 4016 and the sensor output size is 5488 x 4112? It returns an exception.

Some software don't catch this exception and crash. The google camera for example.

Other software catch the exception and assume the 5488 x 4112 sensor output resolution isn't supported. That is what the Camera Hal is telling it. So they try capturing the photo with a lower resolution. This is why we get cropped photos in apps like WhatsApp.

And although I have only looked at the Camera HAL3 code. We can assume the Camera HAL1 code is affected by the same issue.

The other files

On my device the libmmcamera_imx318_primax.so file is the only I need to edit.

I can safely delete both libmmcamera_imx318.so and libmmcamera_imx318_semco.so files from my Mi Note 2 with no consequence.

But not every smartphone is built the same. For example, the Redmi Note 4 can have a Sony, Samsung or Omnivision camera sensor.

The Mi Note 2 isn't as drastic, every Mi Note 2 has a Sony IMX318. But it can come from a few different camera model vendors.

So, I'm assuming the different blobs are for camera models built and sold by Sony, Semco and Primax, all using the Sony IMX318 CMOS.

All these files have the incorrect active array size. The change was the same.

What about the front camera?

I'll edit this bit with info about the change to the front camera blobs. The change was similar but the reasoning was different.

Latest blobs

All these files are located inside /vendor/lib/

Original blobs were taken from MIUI 8.4.12. Edited on 03-05-2018.

https://mega.nz/#!JWoVBCTR!VrThENYfBBO4GMs31obnn4Z8QkBhEASEdNP3FBSOOjw

Hex Workshop Bookmark Files

libmmcamera_imx318_primax.so https://mega.nz/#!sfh2jSRK!pZJQ0dJIyJxv_yXeFMrkt3OkGyD7I0vPrxRobCQjBlw

Some sources

gmsarena page for the Mi Note 2 https://www.gsmarena.com/xiaomi_mi_note_2-8014.php

Sony IMX318 product brief https://www.sony-semicon.co.jp/products_en/IS/sensor1/img/products/ProductBrief_IMX318_20161122.pdf

Sony IMX230 product brief https://www.sony-semicon.co.jp/products_en/IS/sensor1/img/products/ProductBrief_IMX230_20150427.pdf

QCamera3 Crop Region Mapper source code https://source.codeaurora.org/quic/...ee/QCamera2/HAL3/QCamera3CropRegionMapper.cpp

Thanks

Thank you to everyone who participated on the Google Camera thread and helped get it to work.

Thank you [MENTION=5736124]Psy_Man[/MENTION] for the chat about this issue.

Thank you [MENTION=377973]defcomg[/MENTION]. Your work on the OP3 sent me in the right direction. https://www.celsoazevedo.com/files/android/google-camera/op3fix/