-
Notifications
You must be signed in to change notification settings - Fork 17
Description
Checklist
- Checked the issue tracker for similar issues to ensure this is not a duplicate
- Read the documentation to confirm the issue is not addressed there and your configuration is set correctly
- Tested with the latest version to ensure the issue hasn't been fixed
How often does this bug occurs?
always
Expected behavior
esp_capture_sink_set_bitrate() always returned ESP_CAPTURE_ERR_NOT_SUPPORTED and mixed up audio/video routing. This prevents bitrate changes from reaching the active video encoder.
Calling esp_capture_sink_set_bitrate(h, ESP_CAPTURE_STREAM_TYPE_VIDEO, bps) should:
-
Route to the video path manager’s .set with ESP_CAPTURE_PATH_SET_TYPE_VIDEO_BITRATE
-
Update video_path_res_t.bitrate
-
If venc_el is present, call
esp_gmf_video_enc_set_bitrate(venc_el, bitrate) immediately; otherwise apply on prepare/start
Actual behavior (suspected bug)
-
Function returned
ESP_CAPTURE_ERR_NOT_SUPPORTED -
Audio/video handling was inverted, so video bitrate never propagated
Error logs or terminal output
W (53288) webrtc: Failed to set video bitrate: -3Steps to reproduce the behavior
- Context
App is built on espressif/esp-webrtc-solution, which provides the WebRTC layer and plugs into esp_capture for media (capture/encode). The repo’s README states that esp_capture is used to capture media (now provided as a Component Registry package), and the solution bundles several demo apps (Doorbell, Video Call, WHIP Publisher, etc.). However, the WebRTC library itself does not expose a public API to adjust encoder bitrate at runtime, so I added a small wrapper that calls esp_capture_sink_set_bitrate(...) under the hood to test runtime bitrate changes
- Environment
ESP-IDF: latest
Repo: espressif/esp-webrtc-solution (cloned at main)
Board: ESP32-P4
Video: H.264
Notes: ESP-GMF includes the esp_capture package and the GMF video encoder element used by esp-webrtc-solution.
GitHub
- Add a public bitrate setter to
esp_webrtc(temporary test hook)
Because esp-webrtc-solution doesn’t expose bitrate control, add a thin wrapper in your app that ultimately invokes esp_capture_sink_set_bitrate on the capture path:
int esp_webrtc_set_video_bitrate(esp_webrtc_handle_t handle, uint32_t bps) {
if (handle == NULL) return ESP_PEER_ERR_INVALID_ARG;
webrtc_t *rtc = (webrtc_t *)handle;
if (rtc->capture_path) {
// Call into esp_capture sink bitrate setter for VIDEO
int ret = esp_capture_sink_set_bitrate(rtc->capture_path, ESP_CAPTURE_STREAM_TYPE_VIDEO, bps);
return ret; // IMPORTANT: propagate the underlying return code
}
// If not started yet, cache and apply on start
rtc->pending_video_bitrate_bps = bps;
rtc->video_bitrate_pending = true;
return 0;
}
- Build & flash a demo
Use any of the bundled demos (e.g., Doorbell, Video Call, or WHIP Publisher). They all set up a WebRTC call and send video via GMF:
- Start a WebRTC session
Bring the device online and establish a call with the browser/peer using one of the solution demos from the repo’s Solutions section (Doorbell/Video Call/WHIP).
GitHub
- While streaming, attempt to lower bitrate
From an app task (or via your control UI/CLI), invoke the new method:
// e.g., drop to ~300 kbps while running
int ret = esp_webrtc_set_video_bitrate(rtc, 300000);
ESP_LOGI("TEST", "set bitrate ret=%d", ret);
Project release version
latest
System architecture
ARM 64-bit (Apple M1/M2, Raspberry Pi 4/5)
Operating system
MacOS
Operating system version
Sequoia 15.6
Shell
ZSH
Additional context
Proposed fix (function)
esp_capture_err_t esp_capture_sink_set_bitrate(esp_capture_sink_handle_t h,
esp_capture_stream_type_t stream_type,
uint32_t bitrate)
{
capture_path_t *path = (capture_path_t *)h;
if (path == NULL || path->parent == NULL) {
return ESP_CAPTURE_ERR_INVALID_ARG;
}
capture_t *capture = path->parent;
capture_mutex_lock(capture->api_lock, CAPTURE_MAX_LOCK_TIME);
esp_capture_err_t ret = ESP_CAPTURE_ERR_NOT_SUPPORTED;
if (stream_type == ESP_CAPTURE_STREAM_TYPE_VIDEO) {
esp_capture_path_mngr_if_t *video_path =
(capture->cfg.video_path ? &capture->cfg.video_path->base : NULL);
if (video_path && video_path->set) {
ret = video_path->set(video_path,
path->path_type,
ESP_CAPTURE_PATH_SET_TYPE_VIDEO_BITRATE,
&bitrate,
sizeof(uint32_t));
}
} else if (stream_type == ESP_CAPTURE_STREAM_TYPE_AUDIO) {
esp_capture_path_mngr_if_t *audio_path =
(capture->cfg.audio_path ? &capture->cfg.audio_path->base : NULL);
if (audio_path && audio_path->set) {
ret = audio_path->set(audio_path,
path->path_type,
ESP_CAPTURE_PATH_SET_TYPE_AUDIO_BITRATE,
&bitrate,
sizeof(uint32_t));
}
}
capture_mutex_unlock(capture->api_lock);
return ret;
}