doc:appunti:hardware:ambarella_custom_firmware
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
doc:appunti:hardware:ambarella_custom_firmware [2022/02/26 17:54] – niccolo | doc:appunti:hardware:ambarella_custom_firmware [2022/05/05 08:26] (current) – created niccolo | ||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== SJCAM SJ8 Pro Custom Firmware | + | ====== SJCAM SJ8 Pro Action Camera |
- | **How to customize the Ambarella firmware using BitrateEditor** | + | Content was moved into the following |
- | + | ||
- | In this page there are some notes about customizing the firmware of the **[[sjcam-8pro|SJCAM SJ8 Pro]]** action camera, using the **[[https:// | + | |
- | + | ||
- | On many cameras based on the **Ambarella** SoC (but also **Novatek** based cameras have this opportunity) it is possible to **tweak the firmware** changing specific values and tables, to customize several parameters: bitrates, YUV settings, gamma correction, chroma correction, 3D-LUT tables, etc. There is an active community of hackers which produces //modded// firmwares that you can flash on the camera, generally using the official upgrade procedure. Each firmware is specific for a make/model, it is based on a specific released official version and it contains the necessary //poke(s)// directly into the binary file. Generally the source code of the firmware is not available, either documentation about features and data structure is missing, so the big work is done by **reverse engeneering** and countless trials. | + | |
- | + | ||
- | Unfortunately it seems that the hackers community is very jealous of their findings, hardly anyone writes complete documentation and it seems that the main interest is to prove our own supremacy by publishing as many //mod//s as possible, without documenting exactly what was done inside. A notable exception is the **BitrateEditor** software by **V_Max** hacker; being released as open source it is a source of very useful information on the internal structure of firmware files. | + | |
- | + | ||
- | ===== My Custom firmware ===== | + | |
- | + | ||
- | This is my list for firmware customizations: | + | |
- | + | ||
- | * Increased **bitrates**, | + | |
- | * Increased **keyframes** rates (reducing GOP-N): one keyframe every 1/4 second instead of 1 per second. | + | |
- | * Changed **YUV color profiles**: less contrast for **SJCAM - Vivid**, more contrast for **Flat** | + | |
- | * Fixed **exposition** profiles: **Center**, **Spot** and **Average**. | + | |
- | * Changed **gamma curves**: reducing blue sky and contrast. | + | |
- | * Changed power-on, power-off and photo shutter **sounds** with louder ones. | + | |
- | * Disabled **LRV** (low resolution videos) recording. | + | |
- | + | ||
- | === Bitrates === | + | |
- | + | ||
- | The SJ8 Pro camera has by default very low bitrates compared with other 4K action cameras. In the following table you can compare three cameras in various video modes. My custom settings are geared to always keep the standard quality and to film mainly at 1920x1080, to save space and battery. | + | |
- | + | ||
- | ^ Bitrates | + | |
- | ^ | + | |
- | ^ Video Mode ^ Eco ^ Std ^ Fine ^ Default | + | |
- | ^ 4K@60 | + | |
- | ^ 4K@30 | + | |
- | | ||||||| | + | |
- | ^ 2.7K@60 | + | |
- | ^ 2.7K@30 | + | |
- | | ||||||| | + | |
- | ^ 1440@60 | + | |
- | ^ 1440@30 | + | |
- | | ||||||| | + | |
- | ^ 1080@120 | + | |
- | ^ 1080@60 | + | |
- | ^ 1080@30 | + | |
- | | ||||||| | + | |
- | ^ 720@240 | + | |
- | + | ||
- | * **[[https:// | + | |
- | * **[[https:// | + | |
- | + | ||
- | **NOTICE**: For bitrates of **100 Mbit/s** or above you have to consider the micro SD card performances. Recording a stream of 100 Mbit/s means writing a **sustained stream of 12 Mb/s** (megabytes/ | + | |
- | + | ||
- | === Bitrates GOP === | + | |
- | + | ||
- | I want at least 4 keyframes per second, so I can cut scenes without re-encoding with the precision of about 0.25 seconds. The original firmware instead put only a keyframe every second. | + | |
- | + | ||
- | ^ GOP-N Values | + | |
- | ^ FPS ^ 24 ^ 25 ^ 30 ^ 60 ^ 120 ^ 240 ^ | + | |
- | ^ SJ8Pro Default | + | |
- | ^ My Custom SJ8Pro | + | |
- | + | ||
- | === YUV Profiles === | + | |
- | + | ||
- | For my taste the two YUV profiles are both too exagerated. The **Vivid - SJCAM** profile has **too much contrast** and colors are **too much saturated**, | + | |
- | + | ||
- | For the **default** and **vivid** profile I reduced the multipliers by about 6% on the luminance channel and by about 14% on the colors channels. Then I decreased the luminance offset (2%) to recover a bit of the black. For the **flat** profile I reduced the luminance multiplier by about 19%, on both the color channels the multiplier was reduced by about 21%; then I added about 2.5% to the luminance offset, to get some more white. | + | |
- | + | ||
- | The resulting two profiles are not so different from each other, may be you cannot tell them apart looking at the touch screen. This may be a problem, because of the firmware bug which does not properly show the selected profile name and which does not remember the selected profile on power-off/ | + | |
- | + | ||
- | ^ | + | |
- | ^ ^ Default | + | |
- | ^ Y | + | |
- | ^ U | + | |
- | ^ V | + | |
- | ^ Y-offset | + | |
- | ^ U-offset | + | |
- | ^ V-offset | + | |
- | + | ||
- | === Exposition === | + | |
- | + | ||
- | Metering tables were fixed, this simply means swapping profiles **Spot** and **Average**. | + | |
- | + | ||
- | === Gamma curves === | + | |
- | + | ||
- | After countless experiments with the gamma curves, I decided to replace the original ones with **ascending linear lines**, i.e. **no actual gamma transformation**. There is no documentation on how the **%%*/ | + | |
- | + | ||
- | * Group **%%*/0%%** is not used at all. | + | |
- | * Groups **%%*/ | + | |
- | * It seems that in some **particular circumstances** (some color component of */255 is **very dark**) the gamma curve is replaced automatically with something different, may be a **negative** (descending) curve. | + | |
- | + | ||
- | For all that reasons, I decided to replace the curves with linear ones. It may be that I will intervene in the future if I notice any problems in the footages. | + | |
- | + | ||
- | === Sounds === | + | |
- | + | ||
- | I changed the original sounds for **power-on**, | + | |
- | + | ||
- | === autoexec.ash === | + | |
- | + | ||
- | I suggest to add a single line **autoexec.ash** to disable the recording of the **.LRV** (low resolution video) files into the SD card. I don't use them at all, so it is a waste of space and CPU/battery to create them. | + | |
- | + | ||
- | ===== Anatomy of the Ambarella firmware ===== | + | |
- | + | ||
- | We used firmware **1.3.2** released in date **2020-06-08**. Using a Python script which I wrote (see [[https:// | + | |
- | + | ||
- | ^ SJ8 Pro 1.3.2 Firmware File Header - Sections Table | + | |
- | ^ Len (+header) ^ ~CRC32 | + | |
- | | 26095616 | 0xE1744B4A | 0xE1744B4A | + | |
- | | | + | |
- | | | + | |
- | | | + | |
- | | 10699008 | 0x8CC124AC | 0x8CC124AC | + | |
- | + | ||
- | ^ Ambarella Firmware Sections found by Magic 90EB24A3 | + | |
- | ^ Header | + | |
- | | 0x00000230 | 0x00000330 | 26095360 | 0xF42BD26A OK | + | |
- | | 0x018E3230 | 0x018E3330 | 3540992 | 0xCB683D41 OK | + | |
- | | 0x01C43B30 | 0x01C43C30 | 5365760 | 0x45520C76 OK | + | |
- | | 0x02161C30 | 0x02161D30 | 6590472 | 0xEB6ACD7A OK | + | |
- | | 0x027AAD38 | 0x027AAE38 | 10698752 | 0x5686EF50 OK | + | |
- | + | ||
- | Refer to the comments contained into the **ambarella-h22-firmware-unpack** script for a first analysis of file structure. | + | |
- | + | ||
- | ===== Bitrate and GOP ===== | + | |
- | + | ||
- | It is possible to customize bitrates and GOP values for all video modes. Launch the '' | + | |
- | + | ||
- | {{.: | + | |
- | + | ||
- | The SJCAM SJ8 Pro camera has very high default values for the **[[wp> | + | |
- | + | ||
- | Changes will be written into firmware section #1 (the RTOS image). The GOP table is found using a magic string at offset **0x0188A880**, | + | |
- | + | ||
- | ^ Offset | + | |
- | ^ 0x0188A880 | + | |
- | ^ ... | + | |
- | ^ 0x0188A8C0 | + | |
- | ^ ... | + | |
- | ^ 0x0188AE10 | + | |
- | + | ||
- | ===== YUV profiles ===== | + | |
- | + | ||
- | YUV profiles are applied probably very early into the video processing pipeline by the Ambarella processor. They can **alter the color space** of the images by acting on the **luma** (the overall brightness) and the **chrominance** (the colors); a YUV profile defines some mathematic rules to alter luma and chrominance to satisfy particular needs. | + | |
- | + | ||
- | The SJ8 Pro firmware contains **28 YUV prfiles**, they are stored inside the files **de_default_still_Imx377** and **de_default_video_Imx377** contained into section #3 (the ROMFS section at firmware file offset **0x01C43C30**). BitrateEditor can show all of them launching the '' | + | |
- | + | ||
- | {{.: | + | |
- | + | ||
- | Only **four profiles** from the above are actually used: **Video VIVID**, **Video FLAT**, **Photo VIVID** and **Photo FLAT**. There are also **two additional profiles** hard coded into the section #1 (the RTOS image), which are used by default at power-on: **Video default** and **Photo default**. You can launch the '' | + | |
- | + | ||
- | {{.: | + | |
- | + | ||
- | {{.: | + | |
- | + | ||
- | Each profile consists of six values because there are **two parameters for each component** Y, U and V. The numbers define a linear transformation: | + | |
- | + | ||
- | ^ Value ^ Range ^ Notes ^ | + | |
- | ^ Y | 0 ÷ 2048 | Multiplier for the **luma** signal, i.e. the brightness of the image. | + | |
- | ^ U | 0 ÷ 2048 | Multiplier for the **blue projection** (blue - luma). | + | |
- | ^ V | 0 ÷ 2048 | Multiplier for the **red projection** (red - luma). | + | |
- | ^ Y-offset | + | |
- | ^ U-offset | + | |
- | ^ V-offset | + | |
- | + | ||
- | + | ||
- | Values for **Y**, **U** and **V** are unsigned integers in the range **0 ÷ 2048**, values for **Y-offset**, | + | |
- | + | ||
- | ^ File de_default_video_Imx377 | + | |
- | | ||| | + | |
- | ^ Profile Video VIVID ^^^ | + | |
- | ^ Offset | + | |
- | | 0x26 | Y | 2 bytes unsigned integer | + | |
- | | 0x28 | ??? | 6 bytes * 0x00 | | + | |
- | | 0x2E | U | 2 bytes unsigned integer | + | |
- | | 0x30 | ??? | 6 bytes * 0x00 | | + | |
- | | 0x36 | V | 2 bytes unsigned integer | + | |
- | | 0x38 | Y-offset | + | |
- | | 0x3A | U-offset | + | |
- | | 0x3C | V-offset | + | |
- | | ||| | + | |
- | ^ Profile Video FLAT ^^^ | + | |
- | ^ Offset | + | |
- | | 0xA2 | Y | 2 bytes unsigned integer | + | |
- | | 0xA4 | ??? | 6 bytes * 0x00 | | + | |
- | | 0xAA | U | 2 bytes unsigned integer | + | |
- | | 0xAC | ??? | 6 bytes * 0x00 | | + | |
- | | 0xB2 | V | 2 bytes unsigned integer | + | |
- | | 0xB4 | Y-offset | + | |
- | | 0xB6 | U-offset | + | |
- | | 0xB8 | V-offset | + | |
- | + | ||
- | As stated above, changes will be written by BitrateEditor into sections #3 (the ROMFS section at offset 0x01C43C30), | + | |
- | + | ||
- | ==== Using ImageMagick to preview a YUV profile ==== | + | |
- | + | ||
- | You may want to **experiment with YUV values** to obtain a specific image result, but surely you don't want to flash a new firmware on each try! You can use **[[https:// | + | |
- | + | ||
- | With the following **shell script** (tested with ImageMagick 6.9 on GNU/Linux) it is possible to preview a new YUV from an image acquired with neutral settings. Input values are in the range [0, 2048] for the multipliers and in the range [-128, 127] for the offsets, as expected by BitrateEditor. Such values will be converted for use by ImageMagick to the ranges [0, 2.0] and [-0.5, 0.5] respectively. | + | |
- | + | ||
- | <code bash> | + | |
- | #!/bin/sh | + | |
- | # Get filename from command line. | + | |
- | FILENAME=" | + | |
- | # Range: [0, 2048] | + | |
- | cY=' | + | |
- | cU=' | + | |
- | cV=' | + | |
- | # Range [-128, 127] | + | |
- | oY=' | + | |
- | oU=' | + | |
- | oV=' | + | |
- | # Remove extension from filename. | + | |
- | BASENAME=" | + | |
- | # Function to do floating point calculations. | + | |
- | calc() { awk " | + | |
- | # Convert YUV coefficients to the range [0.0, 2.0] | + | |
- | cY=" | + | |
- | cU=" | + | |
- | cV=" | + | |
- | # Convert YUV offsets to the range [-0.5, 0.5] | + | |
- | oY=" | + | |
- | oU=" | + | |
- | oV=" | + | |
- | + | ||
- | # Use ImageMagick internal conversion from/to YCbCr and sRGB. | + | |
- | convert " | + | |
- | -colorspace ' | + | |
- | \( -clone 0 -fx " | + | |
- | \( -clone 1 -fx "0.5 + $oU + $cU * (u[0] - 0.5)" -clamp \) \ | + | |
- | \( -clone 2 -fx "0.5 + $oV + $cV * (u[0] - 0.5)" -clamp \) \ | + | |
- | -delete 0-2 \ | + | |
- | -set colorspace ' | + | |
- | </ | + | |
- | + | ||
- | The ImageMagick incantation is explained here: | + | |
- | - The first line does the conversion from **sRGB** to the **YCbCr** colorspace (when dealing with digital images, if you read YUV, it is actually YCbCr). The result are three separated channels: **Y**, **Cb** and **Cr**, numbered **#0**, **#1** and **#2**. | + | |
- | - The second line makes a clone of the **Y** channel and applies the multiplier and the offset. A new channel will be created, with number **#3**. | + | |
- | - The third and fourth lines will create the modified versions of channels **Cb** and **Cr**, applying the corrections. Two new channels will be created: **#4** and **#5**. | + | |
- | - Using the //delete// command, the first three channels will be deleted, so **only the modified ones remain**. | + | |
- | - The three modified Y, Cb and Cr channels are combined together and **converted back to sRGB**. | + | |
- | + | ||
- | **NOTICE**: BitrateEditor shows a preview of an image simulating the selected YUV profile. The program uses some hard-coded coefficients to perform the conversion from/to **YCbCr** and **RGB**. There is not a single formula for such a conversion, but **there are many standards** (BT.601, BT.709, JPEG) adopted in various circumstances (analog, digital, HDTV, etc.). In the script above we did not use any of that formulas, but instead we relayed on the internal method used by ImageMagick, | + | |
- | + | ||
- | + | ||
- | ===== Exposition (Metering Mode) ===== | + | |
- | + | ||
- | The SJ8Pro contains **three metering tables** used for the three metering modes: **Center**, **Spot** and **Average**. Each table is a matrix of 12x8 integers; each number indicates the weight of that portion of the image in calculating the correct auto exposure. | + | |
- | + | ||
- | By inspecting the exposition matrices with BitrateEditor, | + | |
- | + | ||
- | {{.: | + | |
- | + | ||
- | {{.: | + | |
- | + | ||
- | {{.: | + | |
- | + | ||
- | The tables are contained into the **aaa_default_00_Imx377** file (inside the ROMFS section #3), at offsets **0x285**, **0x2E5** and **0x345** respectively. Each exposition table is a matrix of 12x8 bytes; each number represents the exposition weight of a portion of the image, being the image divided in 8 rows and 12 columns. | + | |
- | + | ||
- | ===== Gamma correction ===== | + | |
- | + | ||
- | Simply speaking, gamma can make the image **lighter** or **darker** in a **selective** manner, i.e. acting differently on shadows and highlights. By acting differently on the red, green and blue channels, gamma can also do **color balancing**. | + | |
- | + | ||
- | Gamma correction is probably applied in a later stage of the Ambarella video processing pipeline. Gamma is a function that transforms brightness or luminance values, it is usually nonlinear and affects the highlights, midtones, and shadows separately. In our case there are different gamma curves for the three color channles: red, green and blue. Different video formats (4K, 1080, etc) use different gamma correction tables. | + | |
- | + | ||
- | BitrateEditor exposes and allow the modification of several look-up tables (**LUT**) contained into the files **adj_video_default_0[0-5]_Imx377** and **adj_still_default_0[0-1]_Imx377** (file are contained into firmware section #3). The tables are shown grouped by three, i.e. we work actually on a **3** x **1D-LUT**, one for each color channel: Red, Green and Blue. In the following picture we see the editing of the group called **4K30/ | + | |
- | + | ||
- | {{.: | + | |
- | + | ||
- | The LUTs are used to transform each color component, mapping 254 input values into a 10-bits integer. For example, following the table above, a **red input value** of **0** is mapped to **0** (first entry of the red table), a red input value of **16** is mapped to **37** (seventeenth entry of the red table), and so on. The 256 values will be used probably with spline interpolation to calculate the transformation on each color component. | + | |
- | + | ||
- | Instead of writing down the raw numeric values, BitrateEditor allow you to draw the gamma curves just dragging nodes over a graph (select the **Graphs** menu). In real time you will see how the curves will impact over the image colors. Once you are satisfied with the curves. select the **Update table from spline** from the menu, this will update numeric values into the table. Otherwise select **Recalculate spline** to re-draw the curves from table numbers. Use **right click on the nodes** to view the useful context menu. | + | |
- | + | ||
- | {{.: | + | |
- | + | ||
- | ==== What gamma curves are applied on each video mode ==== | + | |
- | + | ||
- | In the image processing pipeline, the SJ8 Pro actually uses **two groups** of **three LUTs**. For example, if you are filming at **4K30 FPS**, the groups used are **4K30/ | + | |
- | + | ||
- | The following table shows what group of LUT tables are used for each **video mode**. Also the tables used for **photo modes** are listed: | + | |
- | + | ||
- | ^ Group ^ Contained in file ^ Used for video modes ^ | + | |
- | | 4K30/ | + | |
- | | 4K60/ | + | |
- | | FHD60/ | + | |
- | | FHD120/ | + | |
- | | 720@240/ | + | |
- | | ||| | + | |
- | ^ Group ^ Contained in file ^ Used for photo mode/ | + | |
- | | Photo/ | + | |
- | | Photo-Hi-ISO/ | + | |
- | + | ||
- | I have not found any video mode which is affected by tables contained into the file **adj_video_default_05_Imx377**, | + | |
- | + | ||
- | ==== How gamma curves are mixed together ==== | + | |
- | + | ||
- | I tried to understand how the gamma curves are mixed together to produce the final result. As far I know, there is not official documentation from Ambarella and there is no exhaustive treatment of the subject. I proceeded by uploading some gamma curves with a very specific pattern, then I filmed with the camera a **reference image** displayed on a computer display, trying to keep always the same lighting conditions and changing the **ISO** and **EV** (exposition) settings. | + | |
- | + | ||
- | [{{.: | + | |
- | + | ||
- | The fixed **ISO** modes work in a quite predictable manner, whereas **ISO MAX** modes are rather hard to understand. | + | |
- | + | ||
- | * Using **fixed ISO modes** (from **ISO 100** to **ISO 1600**) it seems that only the **%%*/ | + | |
- | * Using **dynamic ISO modes** (from **ISO MAX 100** to ISO **MAX 6400**) it seems that **%%*/ | + | |
- | + | ||
- | ==== Fixed ISO 1600: test only one color per LUTs group ==== | + | |
- | + | ||
- | In the following two tests I set only **one color channel for each LUTs group**: | + | |
- | + | ||
- | [{{.: | + | |
- | [{{.: | + | |
- | + | ||
- | The following images were captured at **ISO 1600** (using other fixed ISO modes produces similar results). The resulting frames show only the color enabled in the **%%*/ | + | |
- | + | ||
- | [{{.: | + | |
- | [{{.: | + | |
- | + | ||
- | ==== Fixed ISO 1600: only the */255 group matters ==== | + | |
- | + | ||
- | We made four other tests, mixing different slopes on LUT tables **%%*/ | + | |
- | + | ||
- | [{{.: | + | |
- | [{{.: | + | |
- | + | ||
- | [{{.: | + | |
- | [{{.: | + | |
- | + | ||
- | Even in these cases only the tables **%%*/ | + | |
- | + | ||
- | [{{.: | + | |
- | [{{.: | + | |
- | + | ||
- | [{{.: | + | |
- | [{{.: | + | |
- | + | ||
- | ==== ISO MAX 6400: test only one color per LUTs group ==== | + | |
- | + | ||
- | Using **ISO MAX ** modes, both the **%%*/ | + | |
- | + | ||
- | The first two tests use gamma curves with only one different color component for each LUTs group (the same gamma graphs seen above): | + | |
- | + | ||
- | * Test #28: **blue** for **%%*/ | + | |
- | * Test #29: **green** for **%%*/ | + | |
- | + | ||
- | It is rather clear that the **%%*/ | + | |
- | + | ||
- | [{{.: | + | |
- | [{{.: | + | |
- | + | ||
- | Separating the **blue** and the **green** components of the first test (produced by gamma curves **%%*/ | + | |
- | + | ||
- | [{{.: | + | |
- | [{{.: | + | |
- | + | ||
- | Separating the **green** and the **red** components of the second test (produced by gamma curves **%%*/ | + | |
- | + | ||
- | [{{.: | + | |
- | [{{.: | + | |
- | + | ||
- | ==== ISO MAX 6400: how does LUTs groups mixes ==== | + | |
- | + | ||
- | With the other four tests I tried to guess how the **%%*/ | + | |
- | + | ||
- | [{{.: | + | |
- | [{{.: | + | |
- | + | ||
- | [{{.: | + | |
- | [{{.: | + | |
- | + | ||
- | + | ||
- | ==== How does group */255 interpolate with */128? ==== | + | |
- | + | ||
- | [{{.: | + | |
- | [{{.: | + | |
- | [{{.: | + | |
- | + | ||
- | [{{.: | + | |
- | [{{.: | + | |
- | [{{.: | + | |
- | + | ||
- | - Below some brightness threshold, group */128 and */255 are used in combination. You can see the central part of the leftmost column, that is light blue, it is not rendered properly untill the */255 gives its contribute in blue channel. | + | |
- | - It seems that above some brightness threshold, there is a drastic change in gamma correction and group */255 becomes prevalent, if not exclusive. | + | |
- | + | ||
- | The following actual scene filmed wit test #38, shows that the **brightest parts** get a totally **different gamma correction**. However, it is not possible to explain why the color blue does not prevail in the brightest areas, as it should be the only color channel contributed by the */255 group. It seems that **some other correction mechanism** is applied when a color channel is too dark. I suppose that a **negative linear green** channel | + | |
- | + | ||
- | [{{: | + | |
- | + | ||
- | + | ||
- | ==== Anomalies if */255 is too dark ==== | + | |
- | + | ||
- | Finally I tried another border case, where the **%%*/ | + | |
- | + | ||
- | [{{.: | + | |
- | [{{.: | + | |
- | + | ||
- | We will have expected that the brightest part of the image become almost black, but instead we got a strange effect, where colors become somewhat negative: you can see the green part at the center of the image (red on the original image) and the red stripe at the top (which is white on the original image, but it can be actually be sensed as light cyan by the camera). | + | |
- | + | ||
- | [{{.: | + | |
- | [{{.: | + | |
- | + | ||
- | + | ||
- | ==== Gamma curves */0 are not used ==== | + | |
- | + | ||
- | It was supposed that the three groups **4K30/ | + | |
- | + | ||
- | We tried also groups **%%720@240/ | + | |
- | + | ||
- | In the following frames you can see how the 4K30/255 and 4K30/128 groups produces the expected results, whereas the 4K30/0 does not have any effect. The definitive proof should be that zeroing groups 4K30/255 and 4K30/128 and leaving at default values the group 4K30/0, produces a perfect black frame. | + | |
- | + | ||
- | {{.: | + | |
- | + | ||
- | {{.: | + | |
- | + | ||
- | {{.: | + | |
- | + | ||
- | {{.: | + | |
- | + | ||
- | ===== Chroma ===== | + | |
- | + | ||
- | It is possibile to apply a transformation to the **[[wp> | + | |
- | + | ||
- | BitrateEditor exposes three chroma tables: **4K30/ | + | |
- | + | ||
- | Also **photos** have their chroma tables contained into **adj_still_default_00_Imx377** and **adj_hiso_still_default_00_Imx377**. | + | |
- | + | ||
- | + | ||
- | ^ Tables | + | |
- | | 4K30/ | + | |
- | | 4K60/ | + | |
- | | 1080/ | + | |
- | | FHD120/ | + | |
- | | 720/* | adj_video_default_04_Imx377, | + | |
- | | ||| | + | |
- | ^ Tables | + | |
- | | Photo/ | + | |
- | | Photo-Hi-ISO/ | + | |
- | + | ||
- | Each chroma curve is **defined by 128 points** that map to a chrominance value ranging from 0 to 2048. On the X axis there is the brightness of the image pixels, on the Y axis there is the chroma correction factor to be applied. A value of **zero** means to **remove all the chroma** information, | + | |
- | + | ||
- | {{.: | + | |
- | + | ||
- | The three curves are applied by stretching the full range **over the full brightness range** of the image, i.e. the leftmost point of the curve applies to the darkest points of the image, the rightmost point of the curve applies to the brightest points of the image. The three curves are combined together, probably each one is **weighed upon the overall exposition of the image**. It seems that the **4K30/ | + | |
- | + | ||
- | Changes made on tables **%%4K30/ | + | |
- | + | ||
- | ==== Chroma curves examples ==== | + | |
- | + | ||
- | In the following | + | |
- | Then we filmed a reference image using different exposition values. | + | |
- | + | ||
- | Here you are the **reference image**; a gradient of the full RGB palette created with a [[https:// | + | |
- | + | ||
- | {{.: | + | |
- | + | ||
- | === Curve 4K30/255 === | + | |
- | + | ||
- | We tried to understand when the **4K30/ | + | |
- | + | ||
- | {{.: | + | |
- | + | ||
- | {{.: | + | |
- | + | ||
- | {{.: | + | |
- | + | ||
- | Using an exposition of **EV -1.0** or higher, no chrominance is added at all. Some mild effect is visible at **EV -2.0**, despite the chroma graph teeth were set to the maximum value of 2048. In the darker part of the image the effect is not noticeable; the first tooth on the left produces almost no effect. Also the third tooth on the right does not produces any noticeable effect. Only the central **narrow tooth** produces a **narrow band of color**. If the tooth instead expands from the center to the right (last image), the colored area expands from the center towards the brightest part. | + | |
- | + | ||
- | So the maximum effect of the **4K30/ | + | |
- | + | ||
- | {{.: | + | |
- | + | ||
- | === Curve 4K30/128 === | + | |
- | + | ||
- | The curve **4K30/ | + | |
- | + | ||
- | {{.: | + | |
- | + | ||
- | {{.: | + | |
- | + | ||
- | {{.: | + | |
- | + | ||
- | === Curve 4K30/0 === | + | |
- | + | ||
- | The curve **4K30/0** is effective, using the maximum value of 2048, starting from **EV 0.0** and above: | + | |
- | + | ||
- | {{.: | + | |
- | + | ||
- | {{.: | + | |
- | + | ||
- | {{.: | + | |
- | + | ||
- | === Mixing the curves === | + | |
- | + | ||
- | The first example shows the effect of creating some **disjointed theet on the three curves**; each tooth is set at the maximum value of 2048. Actually the single tooth of the curve 4k30/255 produces almos no visble effect, you can see **only three narrow bands of colors** corresponding to teeth on curves **4k30/ | + | |
- | + | ||
- | {{.: | + | |
- | + | ||
- | The last example is used to show how curves are **mixed together**. In this case a **wide teeth** on curve **4K30/ | + | |
- | + | ||
- | {{.: | + | |
- | + | ||
- | ===== AGC and digital gain ===== | + | |
- | + | ||
- | {{.: | + | |
- | + | ||
- | Automatic Gain Control | + | |
- | + | ||
- | ===== White balance presets ===== | + | |
- | + | ||
- | {{.: | + | |
- | + | ||
- | ===== 3D LUT tables ===== | + | |
- | + | ||
- | There are some 16x16x16 **3D LUTs** tables for color grading inside the files **VideoCc[0-4]_Imx377** and **StillCc[0-4]_Imx377** (contained in section #3 of the firmware file). See this **[[https:// | + | |
- | + | ||
- | Using a **[[https:// | + | |
- | + | ||
- | {{.: | + | |
- | {{.: | + | |
- | {{.: | + | |
- | {{.: | + | |
- | {{.: | + | |
- | + | ||
- | It remains to be seen when such tables are used. The files **%%StillCc*%%** contain the same LUT tables. | + | |
- | + | ||
- | + | ||
- | ===== Scenes ===== | + | |
- | + | ||
- | {{.: | + | |
- | + | ||
- | ===== Sharpness ===== | + | |
- | + | ||
- | The author is adding support for editing sharpness tables in BitrateEditor: | + | |
- | + | ||
- | ===== Audio files ===== | + | |
- | + | ||
- | Partition #3 contains some **.pcm audio files** which are used at power-on, power-off, etc. The following files exist: | + | |
- | + | ||
- | * **img_48k.pcm** - Photo shutter noise. | + | |
- | * **optone_48k.pcm** - Bell. | + | |
- | * **power_off_48k.pcm** - Power-on sound. | + | |
- | * **power_on_48k.pcm** - Power-off sound. | + | |
- | + | ||
- | They are headerless audio files, but you can convert them to wav using **[[http:// | + | |
- | + | ||
- | < | + | |
- | sox -r 48k -e signed-integer -b 16 -L -c 1 -t raw power_off_48k.pcm power_off_48k.wav | + | |
- | </ | + | |
- | + | ||
- | The following table explains the SoX command line options used: | + | |
- | + | ||
- | ^ -r, --rate RATE[k] | + | |
- | ^ -e ENCODING, --encoding ENCODING | + | |
- | ^ -b BITS, --bits BITS | The number of bits in each encoded sample. | + | |
- | ^ -L, --endian little | + | |
- | ^ -c CHANNELS, --channels CHANNELS | + | |
- | ^ -t, --type FILE-TYPE | + | |
- | ===== Ambarella imaging pipeline ===== | + | |
- | + | ||
- | The following image is leaked from the Ambarella A12 SDK: | + | |
- | + | ||
- | {{.: | + | |
- | + | ||
- | + | ||
- | ===== Web References ===== | + | |
- | + | ||
- | * **[[http:// | + | |
- | * **[[http:// | + | |
- | * **[[wp> | + | |
- | * **[[https:// | + | |
- | * **[[https:// | + | |
- | * **[[https:// | + | |
- | * **{{.: | + | |
- | * **[[https:// | + | |
+ | * **[[sjcam-8pro]]** | ||
+ | * **[[sjcam-8pro-ambarella-firmware-modding]]** | ||
+ | * **[[sjcam-8pro-custom-firmware]]** | ||
+ | * **[[sjcam-8pro-ambarella-wifi-api]]** | ||
doc/appunti/hardware/ambarella_custom_firmware.txt · Last modified: 2022/05/05 08:26 by niccolo