Skip to content

Select the GC4653 sensor mode and fix FH8852 rate control - #61

Open
carbofos wants to merge 1 commit into
OpenIPC:masterfrom
carbofos:cursor/fh8852-gc4653-stream-33d4
Open

carbofos wants to merge 1 commit into
OpenIPC:masterfrom
carbofos:cursor/fh8852-gc4653-stream-33d4

Conversation

@carbofos

@carbofos carbofos commented Oct 19, 2026 •

Copy link
Copy Markdown

Summary

This is the FH8852V200 stream work for a GC4653 camera.

  • GC4653 follows the requested picture size and frame rate. The sensor library accepts 1920×1080 at 25 or 30 fps (0x203, 0x204) and 2560×1440 at 20 or 25 fps (0x602, 0x603). An exact size selects that mode and the nearest listed rate. A smaller picture uses the smallest mode that covers it. Anything larger uses 2560×1440. The mode is chosen when the pipeline starts, so a resolution change needs a restart.
  • The other sensors in this HAL keep the single size and format 0x203 they already had. Their libraries were checked, not reflashed onto hardware. jxf32, mn34425, and ovos02k do accept 0x203. ovos04c10 and ovos08 do not list 0x203; that request is unchanged from the previous HAL. ovos05 lists 0x203 as 1080p, while the HAL size remains 2592×1944, also unchanged. gc5603 is still in the table and is not shipped in this firmware package.
  • FH8852 H.264 constant-bitrate control ignores the target and stays at the top of its quantizer window, so the bitrate is applied as a fixed quantizer: 38 at 1024 kbps, 36 at 2048, 34 at 4096, 32 at 8192, and never below 30. H.265 keeps the driver's constant-bitrate control. The rate is programmed with FH_VENC_SetRCAttr.
  • MJPEG uses a scaled VPSS channel at the requested size. Quality 1 selects encoder quantizer 98 and quality 99 selects quantizer 0, so a higher quality is a larger frame. The MJPEG encoder does not use the bitrate field. A snapshot whose size already matches an open channel still reuses that channel.

Test plan

Checked on an FH8852V200 with GC4653:

  • Pipeline log: Using gc4653_mipi 2560x1440 at 25 fps (format 0x603)
  • JPEG snapshot /image.jpg is 2560×1440
  • RTSP is H.264 2560×1440 at 25 fps. Four seconds at the 4096 kbps setting (quantizer 34) were 3,560,721 bytes, about 7.1 Mbps
  • MJPEG 640×360 at 15 fps, quality 30: 48 frames in 3.2 s, 640×360, average 26,784 bytes, driver quantizer 69
  • Same stream at quality 80: 48 frames in 3.2 s, 640×360, average 55,716 bytes, driver quantizer 19
  • Other sensor modules were not fitted to this board

GC4653 follows the requested picture size and frame rate. The library
accepts 1920x1080 at 25 or 30 fps and 2560x1440 at 20 or 25 fps. An
exact size uses that mode and the nearest listed rate. A smaller
picture uses the smallest mode that covers it. Anything larger uses
2560x1440. Other sensors in this HAL keep their previous single mode
and format.

The FH8852 H.264 constant-bitrate loop ignores its target, so the
requested bitrate is applied as a fixed quantizer: 38 at 1024 kbps,
36 at 2048, 34 at 4096, and 32 at 8192, and never below 30. H.265
keeps the driver's constant-bitrate control.

MJPEG uses its own scaled channel at the requested size. A higher
quality selects a lower encoder quantizer, from 98 at quality 1 down
to 0 at quality 99. The encoder does not use the MJPEG bitrate field.
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

Select GC4653 modes and correct FH8852 video controls

🐞 Bug fix ✨ Enhancement 🕐 40+ Minutes

Grey Divider

AI Description

• Select GC4653 sensor modes by requested size and nearest supported frame rate at pipeline startup.
• Replace ineffective FH8852 H.264 CBR with bitrate-derived quantizers while retaining H.265 CBR.
• Scale MJPEG to its requested size and map quality to encoder quantizer.
Diagram

graph TD
  A["Stream settings"] --> B["Mode selection"] --> D["Sensor ISP"] --> E["VPSS scaling"] --> F{"Codec choice"} --> G["VENC controls"] --> H["Video output"]
  C["Sensor modes"] --> B
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Application-level H.264 bitrate feedback
  • ➕ Could track a requested bitrate more closely than a fixed quantizer.
  • ➖ Requires ongoing stream measurement and quantizer adjustment, adding complexity and hardware-specific tuning.

Recommendation: Use the PR's fixed-quantizer mapping for the observed ineffective FH8852 controller, while retaining native H.265 CBR. Treat H.264 bitrate as a quality hint, not a guaranteed rate; consider feedback control only if enforcing a rate becomes necessary.

Files changed (6) +179 / -54

Enhancement (2) +158 / -44
f2_hal.cSelect sensor modes and configure FH8852 encoding +142/-32

Select sensor modes and configure FH8852 encoding

• Selects sensor format, dimensions, and nearest supported frame rate at pipeline startup. Allocates or reuses VPSS channels for JPEG/MJPEG output, applies MJPEG quality and frame timing, and programs codec-specific rate control through the encoder API.

src/hal/fhan/f2_hal.c

f2_isp.hDefine sensor dimensions, rates, and formats +16/-12

Define sensor dimensions, rates, and formats

• Replaces the sensor-size table with mode entries for GC4653's four supported combinations. Preserves the prior single size and format for other listed sensors.

src/hal/fhan/f2_isp.h

Bug fix (2) +14 / -9
media.cPass configured MJPEG quality to the HAL +5/-0

Pass configured MJPEG quality to the HAL

• Initializes the MJPEG video configuration and passes a bounded quality factor, defaulting to 50. This makes the configured quality available to the FH8852 encoder.

src/media.c

server.cValidate HTTP video bitrate and MJPEG quality inputs +9/-9

Validate HTTP video bitrate and MJPEG quality inputs

• Parses MJPEG and MP4 bitrates as positive long values before storing them. Restricts HTTP MJPEG quality updates to values from 1 through 99.

src/server.c

Documentation (2) +7 / -1
config.mdDocument FH8852 mode and encoder behavior +6/-0

Document FH8852 mode and encoder behavior

• Explains GC4653 mode selection and the restart required for resolution changes. Clarifies H.264 bitrate-to-quantizer mapping, H.265 CBR, and MJPEG quality behavior.

doc/config.md

f2_venc.hCorrect documented encoder rate-control layout +1/-1

Correct documented encoder rate-control layout

• Revises the CBR parameter-layout comment to identify the frame-rate field used by the encoder configuration.

src/hal/fhan/f2_venc.h

@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (3) 📘 Rule violations (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Snapshots can switch to video dimensions 🐞 Bug ≡ Correctness
Description
f2_channel_create assigns a JPEG encoder any free picture channel, but a later video encoder can
reconfigure that same channel by its index without checking whether the JPEG encoder uses it. When
JPEG starts first at a size different from the pipeline picture, enabling video on that index
changes the source used by subsequent snapshots.
Code

src/hal/fhan/f2_hal.c[R215-218]

+    for (char i = 0; i < _f2_vpss_count; i++) {
+        if (_f2_vpss_open[i]) continue;
+        _f2_vpss_src[index] = i;
+        return f2_vpss_setup(i, width, height, framerate);
Evidence
JPEG allocation can select a free VPSS index independently of its encoder index. The non-JPEG path
later claims its indexed VPSS source, and setup disables and reconfigures an open source when the
requested configuration differs. Snapshot binding uses the JPEG encoder’s retained source index.

src/hal/fhan/f2_hal.c[201-218]
src/hal/fhan/f2_hal.c[146-173]
src/hal/fhan/f2_hal.c[860-871]
src/media.c[380-391]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
A JPEG encoder can be assigned a free picture channel that a later video encoder reconfigures, changing the source of subsequent snapshots.
## Fix Focus Areas
- src/hal/fhan/f2_hal.c[201-223]
- src/hal/fhan/f2_hal.c[146-173]
## Recommended Fix
Track active users of each picture channel. Before assigning an indexed channel to a video encoder, preserve or relocate any active JPEG user; never reconfigure a source while another encoder depends on it.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. Repeated snapshots exhaust picture channels 🐞 Bug ☼ Reliability
Description
f2_channel_create opens a free picture channel for a new JPEG size, but f2_video_destroy never
releases that channel when the JPEG encoder is destroyed. After JPEG is disabled and recreated at
different sizes enough times, no free channel remains; creation falls back to the main picture,
whose dimensions can differ or exceed the encoder’s previously allocated size.
Code

src/hal/fhan/f2_hal.c[R215-220]

+    for (char i = 0; i < _f2_vpss_count; i++) {
+        if (_f2_vpss_open[i]) continue;
+        _f2_vpss_src[index] = i;
+        return f2_vpss_setup(i, width, height, framerate);
+    }
+    _f2_vpss_src[index] = -1;
Evidence
The new allocation opens a free VPSS channel, whereas encoder destruction only stops reception and
unbinds. Once channels are open, the source picker defaults to channel zero if none matches, and
encoder creation substitutes that channel’s dimensions.

src/hal/fhan/f2_hal.c[208-223]
src/hal/fhan/f2_hal.c[805-813]
src/hal/fhan/f2_hal.c[120-127]
src/hal/fhan/f2_hal.c[650-663]
src/jpeg.c[77-110]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
JPEG reconfiguration opens picture channels that remain allocated after the encoder is destroyed, eventually forcing a wrong-size fallback.
## Fix Focus Areas
- src/hal/fhan/f2_hal.c[208-223]
- src/hal/fhan/f2_hal.c[805-813]
## Recommended Fix
Track picture-channel ownership or users and disable a JPEG-allocated channel when its last encoder is destroyed. Reuse or reclaim unused channels on reconfiguration, and do not silently substitute the main picture when no matching channel is available.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Streams can advertise the wrong frame rate 🐞 Bug ≡ Correctness
Description
f2_pipeline_create selects the nearest supported sensor rate but retains the requested rate for
picture-channel setup and downstream stream configuration. A 2560×1440 request at 30 fps selects the
25-fps GC4653 mode while the encoder and MP4 configuration still use 30 fps, leaving the stream
timing and reported rate inconsistent with its source.
Code

src/hal/fhan/f2_hal.c[R381-385]

+    mode = f2_snr_match(f2_snr.name, (unsigned int)width, (unsigned int)height,
+        (unsigned int)(unsigned char)framerate);
+    snrFmt = mode ? mode->format : F2_SNR_FMT;
+    if (mode) {
+        _f2_snr_dim = mode->dim;
Evidence
The new table limits 2560×1440 to 20 or 25 fps, and matching chooses the closest entry to 30.
Pipeline setup passes the unchanged request to VPSS, while video configuration and MP4 metadata
continue to use the configured request.

src/hal/fhan/f2_isp.h[81-85]
src/hal/fhan/f2_hal.c[341-372]
src/hal/fhan/f2_hal.c[375-388]
src/hal/fhan/f2_hal.c[430-439]
src/media.c[748-797]
src/hal/fhan/f2_vpss.h[5-8]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Nearest-rate sensor selection does not update the frame rate used to configure picture channels, encoders, and stream metadata.
## Fix Focus Areas
- src/hal/fhan/f2_hal.c[375-392]
- src/hal/fhan/f2_hal.c[430-439]
- src/media.c[929-954]
- src/media.c[748-797]
## Recommended Fix
Expose the selected sensor frame rate to downstream setup. Configure picture-channel input timing from that actual rate, and set encoder and stream metadata rates to achievable output rates when a request is rounded to a supported sensor mode.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context sources
Review mode: Auto: ⚖️ Balanced: Downgraded extended -> standard: change is below the extended eligibility bar (hunks 17/18, lines 233/200; both must reach the floor). Router rationale: Multiple independent sensor, VPSS, encoder, and request-parsing logic changes create dense defect risk.

Grey Divider

Tip of the day
💡 Did you know, you can import rules and skills only from the repositories your team follows

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread src/hal/fhan/f2_hal.c
Comment on lines +215 to +218
for (char i = 0; i < _f2_vpss_count; i++) {
if (_f2_vpss_open[i]) continue;
_f2_vpss_src[index] = i;
return f2_vpss_setup(i, width, height, framerate);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. Snapshots can switch to video dimensions 🐞 Bug ≡ Correctness

f2_channel_create assigns a JPEG encoder any free picture channel, but a later video encoder can
reconfigure that same channel by its index without checking whether the JPEG encoder uses it. When
JPEG starts first at a size different from the pipeline picture, enabling video on that index
changes the source used by subsequent snapshots.
Agent Prompt
## Issue description
A JPEG encoder can be assigned a free picture channel that a later video encoder reconfigures, changing the source of subsequent snapshots.
## Fix Focus Areas
- src/hal/fhan/f2_hal.c[201-223]
- src/hal/fhan/f2_hal.c[146-173]
## Recommended Fix
Track active users of each picture channel. Before assigning an indexed channel to a video encoder, preserve or relocate any active JPEG user; never reconfigure a source while another encoder depends on it.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment thread src/hal/fhan/f2_hal.c
Comment on lines +215 to +220
for (char i = 0; i < _f2_vpss_count; i++) {
if (_f2_vpss_open[i]) continue;
_f2_vpss_src[index] = i;
return f2_vpss_setup(i, width, height, framerate);
}
_f2_vpss_src[index] = -1;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remediation recommended

2. Repeated snapshots exhaust picture channels 🐞 Bug ☼ Reliability

f2_channel_create opens a free picture channel for a new JPEG size, but f2_video_destroy never
releases that channel when the JPEG encoder is destroyed. After JPEG is disabled and recreated at
different sizes enough times, no free channel remains; creation falls back to the main picture,
whose dimensions can differ or exceed the encoder’s previously allocated size.
Agent Prompt
## Issue description
JPEG reconfiguration opens picture channels that remain allocated after the encoder is destroyed, eventually forcing a wrong-size fallback.
## Fix Focus Areas
- src/hal/fhan/f2_hal.c[208-223]
- src/hal/fhan/f2_hal.c[805-813]
## Recommended Fix
Track picture-channel ownership or users and disable a JPEG-allocated channel when its last encoder is destroyed. Reuse or reclaim unused channels on reconfiguration, and do not silently substitute the main picture when no matching channel is available.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment thread src/hal/fhan/f2_hal.c
Comment on lines +381 to +385
mode = f2_snr_match(f2_snr.name, (unsigned int)width, (unsigned int)height,
(unsigned int)(unsigned char)framerate);
snrFmt = mode ? mode->format : F2_SNR_FMT;
if (mode) {
_f2_snr_dim = mode->dim;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remediation recommended

3. Streams can advertise the wrong frame rate 🐞 Bug ≡ Correctness

f2_pipeline_create selects the nearest supported sensor rate but retains the requested rate for
picture-channel setup and downstream stream configuration. A 2560×1440 request at 30 fps selects the
25-fps GC4653 mode while the encoder and MP4 configuration still use 30 fps, leaving the stream
timing and reported rate inconsistent with its source.
Agent Prompt
## Issue description
Nearest-rate sensor selection does not update the frame rate used to configure picture channels, encoders, and stream metadata.
## Fix Focus Areas
- src/hal/fhan/f2_hal.c[375-392]
- src/hal/fhan/f2_hal.c[430-439]
- src/media.c[929-954]
- src/media.c[748-797]
## Recommended Fix
Expose the selected sensor frame rate to downstream setup. Configure picture-channel input timing from that actual rate, and set encoder and stream metadata rates to achievable output rates when a request is rounded to a supported sensor mode.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

@carbofos

Copy link
Copy Markdown
Author

Now the camera is on openwall:
https://openipc.org/open-wall/camera/0e6515a9d19e2c20

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant