Skip to content

Commit e068fe9

Browse files
tempoTempoTian
authored andcommitted
bugfix(esp_capture): Fixed bitrate setting not work
Closes #29
1 parent 076a0d6 commit e068fe9

File tree

12 files changed

+187
-42
lines changed

12 files changed

+187
-42
lines changed

elements/gmf_video/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Changelog
22

3+
## v0.7.1
4+
5+
### Features
6+
7+
- Add QP and GOP setting support for video encoder element
8+
39
## v0.7.0
410

511
### Features

elements/gmf_video/esp_gmf_video_enc.c

Lines changed: 65 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -38,16 +38,38 @@
3838

3939
static const char *TAG = "VENC_EL";
4040

41+
/**
42+
* @brief Video encoder extra setting mask
43+
*/
44+
typedef enum {
45+
VENC_EXTRA_SET_MASK_NONE = 0,
46+
VENC_EXTRA_SET_MASK_BITRATE = (1 << 0),
47+
VENC_EXTRA_SET_MASK_QP = (1 << 1),
48+
VENC_EXTRA_SET_MASK_GOP = (1 << 2),
49+
VENC_EXTRA_SET_MASK_ALL = (0xFF),
50+
} venc_extra_set_mask_t;
51+
52+
/**
53+
* @brief Video encoder extra setting
54+
*/
55+
typedef struct {
56+
uint32_t bitrate;
57+
uint32_t min_qp;
58+
uint32_t max_qp;
59+
uint32_t gop;
60+
venc_extra_set_mask_t mask;
61+
} venc_extra_set_t;
62+
4163
/**
4264
* @brief Video encoder definition
4365
*/
4466
typedef struct {
4567
esp_gmf_video_element_t parent; /*!< Video element parent */
4668
esp_video_codec_type_t dst_codec; /*!< Video encoder destination codec */
4769
bool venc_bypass; /*!< Whether video encoder is bypassed or not */
48-
uint32_t bitrate; /*!< Output bitrate setting */
4970
uint32_t codec_cc; /*!< FourCC used to find encoder if set */
5071
esp_video_enc_handle_t enc_handle; /*!< Video encoder handle */
72+
venc_extra_set_t extra_set; /*!< Video encoder extra setting */
5173
} venc_t;
5274

5375
static int venc_get_input_codecs(venc_t *venc, uint32_t dst_codec, const uint32_t **codecs, uint8_t *num)
@@ -106,11 +128,24 @@ static int venc_get_frame_size(venc_t *venc, int *in_frame_size, int *out_frame_
106128
return ESP_GMF_ERR_OK;
107129
}
108130

109-
static void venc_el_apply_settings(venc_t *venc)
131+
static esp_gmf_err_t venc_el_apply_settings(venc_t *venc, venc_extra_set_mask_t mask)
110132
{
111-
if (venc->bitrate) {
112-
esp_video_enc_set_bitrate(venc->enc_handle, venc->bitrate);
133+
venc_extra_set_t *extra_set = &venc->extra_set;
134+
if (venc->enc_handle == NULL ||
135+
extra_set->mask == VENC_EXTRA_SET_MASK_NONE) {
136+
return ESP_GMF_ERR_OK;
137+
}
138+
esp_vc_err_t ret = ESP_VC_ERR_OK;
139+
if (extra_set->mask & (mask & VENC_EXTRA_SET_MASK_BITRATE)) {
140+
ret |= esp_video_enc_set_bitrate(venc->enc_handle, extra_set->bitrate);
141+
}
142+
if (extra_set->mask & (mask & VENC_EXTRA_SET_MASK_QP)) {
143+
ret |= esp_video_enc_set_qp(venc->enc_handle, extra_set->min_qp, extra_set->max_qp);
113144
}
145+
if (extra_set->mask & (mask & VENC_EXTRA_SET_MASK_GOP)) {
146+
ret |= esp_video_enc_set_gop(venc->enc_handle, extra_set->gop);
147+
}
148+
return ret == ESP_VC_ERR_OK ? ESP_GMF_ERR_OK : ESP_GMF_ERR_NOT_SUPPORT;
114149
}
115150

116151
static esp_gmf_job_err_t venc_el_open(esp_gmf_video_element_handle_t self, void *para)
@@ -143,7 +178,7 @@ static esp_gmf_job_err_t venc_el_open(esp_gmf_video_element_handle_t self, void
143178
venc_get_frame_size(venc, &in_frame_size, &out_frame_size);
144179
ESP_GMF_ELEMENT_GET(venc)->in_attr.data_size = in_frame_size;
145180
ESP_GMF_ELEMENT_GET(venc)->out_attr.data_size = out_frame_size;
146-
venc_el_apply_settings(venc);
181+
venc_el_apply_settings(venc, VENC_EXTRA_SET_MASK_ALL);
147182
}
148183
// Report info to next element
149184
esp_gmf_info_video_t out_info = venc->parent.src_info;
@@ -276,12 +311,9 @@ static esp_gmf_err_t set_bitrate(esp_gmf_element_handle_t handle, esp_gmf_args_d
276311
ESP_GMF_NULL_CHECK(TAG, arg_desc, return ESP_GMF_ERR_INVALID_ARG);
277312
venc_t *venc = (venc_t *)handle;
278313
int offset = 0;
279-
COPY_ARG(&venc->bitrate, buf, offset, sizeof(uint32_t), buf_len)
280-
// TODO allow set bitrate before running?
281-
if (venc->enc_handle) {
282-
return esp_video_enc_set_bitrate(venc->enc_handle, venc->bitrate);
283-
}
284-
return ESP_GMF_ERR_OK;
314+
COPY_ARG(&venc->extra_set.bitrate, buf, offset, sizeof(uint32_t), buf_len);
315+
venc->extra_set.mask |= VENC_EXTRA_SET_MASK_BITRATE;
316+
return venc_el_apply_settings(venc, VENC_EXTRA_SET_MASK_BITRATE);
285317
}
286318

287319
static esp_gmf_err_t get_in_formats(esp_gmf_element_handle_t handle, esp_gmf_args_desc_t *arg_desc,
@@ -440,11 +472,28 @@ esp_gmf_err_t esp_gmf_video_enc_set_bitrate(esp_gmf_element_handle_t self, uint3
440472
{
441473
ESP_GMF_NULL_CHECK(TAG, self, return ESP_GMF_ERR_INVALID_ARG);
442474
venc_t *venc = (venc_t *)self;
443-
venc->bitrate = bitrate;
444-
// TODO allow set bitrate before running?
445-
if (venc->enc_handle) {
446-
return esp_video_enc_set_bitrate(venc->enc_handle, bitrate);
447-
}
475+
venc->extra_set.bitrate = bitrate;
476+
venc->extra_set.mask |= VENC_EXTRA_SET_MASK_BITRATE;
477+
return venc_el_apply_settings(venc, VENC_EXTRA_SET_MASK_BITRATE);
478+
}
479+
480+
esp_gmf_err_t esp_gmf_video_enc_set_gop(esp_gmf_element_handle_t self, uint32_t gop)
481+
{
482+
ESP_GMF_NULL_CHECK(TAG, self, return ESP_GMF_ERR_INVALID_ARG);
483+
venc_t *venc = (venc_t *)self;
484+
venc->extra_set.gop = gop;
485+
venc->extra_set.mask |= VENC_EXTRA_SET_MASK_GOP;
486+
return venc_el_apply_settings(venc, VENC_EXTRA_SET_MASK_GOP);
487+
}
488+
489+
esp_gmf_err_t esp_gmf_video_enc_set_qp(esp_gmf_element_handle_t self, uint32_t min_qp, uint32_t max_qp)
490+
{
491+
ESP_GMF_NULL_CHECK(TAG, self, return ESP_GMF_ERR_INVALID_ARG);
492+
venc_t *venc = (venc_t *)self;
493+
venc->extra_set.min_qp = min_qp;
494+
venc->extra_set.max_qp = max_qp;
495+
venc->extra_set.mask |= VENC_EXTRA_SET_MASK_QP;
496+
venc_el_apply_settings(venc, VENC_EXTRA_SET_MASK_QP);
448497
return ESP_GMF_ERR_OK;
449498
}
450499

elements/gmf_video/idf_component.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
version: "0.7.0"
1+
version: "0.7.1"
22
description: Espressif GMF Video Elements Module
33
url: https://github.com/espressif/esp-gmf/tree/main/elements/gmf_video
44
documentation: "https://github.com/espressif/esp-gmf/blob/main/elements/gmf_video/README.md"

elements/gmf_video/include/esp_gmf_video_enc.h

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,39 @@ esp_gmf_err_t esp_gmf_video_enc_get_src_formats(esp_gmf_element_handle_t handle,
115115
*/
116116
esp_gmf_err_t esp_gmf_video_enc_set_bitrate(esp_gmf_element_handle_t handle, uint32_t bitrate);
117117

118+
/**
119+
* @brief Set the GOP (Group of Pictures) for video encoder.
120+
*
121+
* @note This setting applies specifically to the H.264 encoder
122+
* The H.264 encoder generates an I-frame at the start of each GOP
123+
* Can be configured both before and after the encoder element is running
124+
*
125+
* @param[in] handle Handle to the video encoder element
126+
* @param[in] gop GOP size for H.264 (in number of frames)
127+
*
128+
* @return
129+
* - ESP_GMF_ERR_OK On success
130+
* - ESP_GMF_ERR_INVALID_ARG Invalid configuration provided
131+
*/
132+
esp_gmf_err_t esp_gmf_video_enc_set_gop(esp_gmf_element_handle_t handle, uint32_t gop);
133+
134+
/**
135+
* @brief Set the QP (Quantization Parameter) range for video encoder
136+
*
137+
* @note This setting applies specifically to the H.264 encoder
138+
* Higher QP values generally result in lower image quality
139+
* Can be configured both before and after the encoder element is running
140+
*
141+
* @param[in] handle Handle to the video encoder element
142+
* @param[in] min_qp Minimum QP value
143+
* @param[in] max_qp Maximum QP value
144+
*
145+
* @return
146+
* - ESP_GMF_ERR_OK On success
147+
* - ESP_GMF_ERR_INVALID_ARG Invalid configuration provided
148+
*/
149+
esp_gmf_err_t esp_gmf_video_enc_set_qp(esp_gmf_element_handle_t handle, uint32_t min_qp, uint32_t max_qp);
150+
118151
#ifdef __cplusplus
119152
}
120153
#endif /* __cplusplus */

packages/esp_capture/CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,17 @@
11
# Changelog
22

3+
## v0.7.7
4+
5+
### Features
6+
7+
- Fixed failed to set bitrate
8+
- Added QP and GOP setting for H264
9+
10+
### Bug Fixes
11+
12+
- Fixed share queue release possible issue
13+
- Fixed wrong received muxer data when audio/video path has error
14+
315
## v0.7.6
416

517
### Features

packages/esp_capture/idf_component.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
version: "0.7.6"
1+
version: "0.7.7"
22
description: Espressif Capture is a module for capture media stream from camera and microphone
33
url: https://github.com/espressif/esp-gmf/tree/main/packages/esp_capture
44
documentation: "https://github.com/espressif/esp-gmf/blob/main/packages/esp_capture/README.md"

packages/esp_capture/impl/capture_gmf_path/src/gmf_capture_audio_path.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,7 @@ esp_capture_err_t gmf_audio_path_set(esp_capture_path_mngr_if_t *p, uint8_t path
252252
res->sync_handle = *(esp_capture_sync_handle_t *)cfg;
253253
} else if (type == ESP_CAPTURE_PATH_SET_TYPE_AUDIO_BITRATE) {
254254
res->bitrate = *(uint32_t *)cfg;
255+
ret = ESP_CAPTURE_ERR_OK;
255256
if (res->aenc_el && cfg_size == sizeof(uint32_t)) {
256257
ret = esp_gmf_audio_enc_set_bitrate(res->aenc_el, res->bitrate);
257258
}

packages/esp_capture/impl/capture_gmf_path/src/gmf_capture_video_path.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ static esp_capture_err_t video_path_apply_setting(gmf_capture_path_mngr_t *mngr,
145145
}
146146
esp_gmf_video_overlay_enable(res->overlay_el, res->overlay_enable);
147147
}
148-
if (res->venc_el) {
148+
if (res->venc_el && res->bitrate) {
149149
esp_gmf_video_enc_set_bitrate(res->venc_el, res->bitrate);
150150
}
151151
if (res->sync_handle) {
@@ -401,7 +401,8 @@ esp_capture_err_t gmf_video_path_set(esp_capture_path_mngr_if_t *p, uint8_t path
401401
res->sync_handle = *(esp_capture_sync_handle_t *)cfg;
402402
} else if (type == ESP_CAPTURE_PATH_SET_TYPE_VIDEO_BITRATE) {
403403
res->bitrate = *(uint32_t *)cfg;
404-
if (res->venc_el) {
404+
ret = ESP_CAPTURE_ERR_OK;
405+
if (res->venc_el && res->bitrate) {
405406
ret = esp_gmf_video_enc_set_bitrate(res->venc_el, res->bitrate);
406407
}
407408
} else if (type == ESP_CAPTURE_PATH_SET_TYPE_REGISTER_ELEMENT) {

packages/esp_capture/src/esp_capture.c

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ static int capture_frame_avail(void *src, uint8_t sel, esp_capture_stream_frame_
100100
return ESP_CAPTURE_ERR_NOT_FOUND;
101101
}
102102
// When path disable drop input data directly
103-
if (path->sink_disabled) {
103+
if (path->sink_disabled || path->parent->started == false) {
104104
// Can not release it here, callback to user to handle it
105105
return ESP_CAPTURE_ERR_NOT_SUPPORTED;
106106
}
@@ -1110,15 +1110,15 @@ esp_capture_err_t esp_capture_sink_set_bitrate(esp_capture_sink_handle_t h, esp_
11101110
int ret = ESP_CAPTURE_ERR_NOT_SUPPORTED;
11111111
if (stream_type == ESP_CAPTURE_STREAM_TYPE_VIDEO) {
11121112
type = ESP_CAPTURE_PATH_SET_TYPE_VIDEO_BITRATE;
1113-
esp_capture_path_mngr_if_t *audio_path = &capture->cfg.audio_path->base;
1114-
if (audio_path) {
1115-
audio_path->set(audio_path, path->path_type, type, &bitrate, sizeof(uint32_t));
1113+
esp_capture_path_mngr_if_t *video_path = &capture->cfg.video_path->base;
1114+
if (video_path) {
1115+
ret = video_path->set(video_path, path->path_type, type, &bitrate, sizeof(uint32_t));
11161116
}
11171117
} else if (stream_type == ESP_CAPTURE_STREAM_TYPE_AUDIO) {
11181118
type = ESP_CAPTURE_PATH_SET_TYPE_AUDIO_BITRATE;
1119-
esp_capture_path_mngr_if_t *video_path = &capture->cfg.video_path->base;
1120-
if (video_path) {
1121-
video_path->set(video_path, path->path_type, type, &bitrate, sizeof(uint32_t));
1119+
esp_capture_path_mngr_if_t *audio_path = &capture->cfg.audio_path->base;
1120+
if (audio_path) {
1121+
ret = audio_path->set(audio_path, path->path_type, type, &bitrate, sizeof(uint32_t));
11221122
}
11231123
}
11241124
capture_mutex_unlock(capture->api_lock);
@@ -1139,8 +1139,9 @@ esp_capture_err_t esp_capture_sink_acquire_frame(esp_capture_sink_handle_t h, es
11391139
switch (frame->stream_type) {
11401140
case ESP_CAPTURE_STREAM_TYPE_VIDEO:
11411141
if (path->video_path_disabled) {
1142-
if (path->video_share_q) {
1143-
share_q_recv_all(path->video_share_q, frame);
1142+
// Only receive all of share q port data
1143+
while (msg_q_recv(path->video_q, frame, sizeof(esp_capture_stream_frame_t), true) == 0) {
1144+
share_q_release(path->video_share_q, frame);
11441145
}
11451146
return ESP_CAPTURE_ERR_NOT_FOUND;
11461147
}
@@ -1152,8 +1153,8 @@ esp_capture_err_t esp_capture_sink_acquire_frame(esp_capture_sink_handle_t h, es
11521153
break;
11531154
case ESP_CAPTURE_STREAM_TYPE_AUDIO:
11541155
if (path->audio_path_disabled) {
1155-
if (path->audio_share_q) {
1156-
share_q_recv_all(path->audio_share_q, frame);
1156+
while (msg_q_recv(path->audio_q, frame, sizeof(esp_capture_stream_frame_t), true) == 0) {
1157+
share_q_release(path->audio_share_q, frame);
11571158
}
11581159
return ESP_CAPTURE_ERR_NOT_FOUND;
11591160
}

packages/esp_capture/src/utils/share_q.c

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,11 @@ int share_q_recv_all(share_q_handle_t q, void *frame)
179179
for (int i = 0; i < q->cfg.user_count; i++) {
180180
if (q->user_q[i].enable) {
181181
while (msg_q_recv(q->user_q[i].q, frame, q->cfg.item_size, true) == 0) {
182-
share_q_release(q, frame);
182+
if (q->user_q[i].release_frame) {
183+
q->user_q[i].release_frame(frame, q->user_q[i].ctx);
184+
} else {
185+
share_q_release(q, frame);
186+
}
183187
}
184188
}
185189
}
@@ -262,21 +266,24 @@ int share_q_release(share_q_t *q, void *item)
262266
int rp = q->rp;
263267
int wp = q->wp;
264268
void *frame_data = q->cfg.get_frame_data(item);
265-
269+
bool need_notify = false;
270+
share_item_t *head = &q->items[rp];
266271
while (rp != wp) {
267272
share_item_t *q_item = &q->items[rp];
268273
if (q_item->frame_data == frame_data) {
269274
q_item->ref_count--;
270275
if (q_item->ref_count == 0) {
276+
need_notify = true;
271277
q->cfg.release_frame(item, q->cfg.ctx);
272-
q->rp = (q->rp + 1) % q->cfg.q_count;
273-
pthread_cond_signal(&q->cond);
278+
q->rp = (rp + 1) % q->cfg.q_count;
274279
}
275-
pthread_mutex_unlock(&q->lock);
276-
return 0;
280+
break;
277281
}
278282
rp = (rp + 1) % (q->cfg.q_count);
279283
}
284+
if (need_notify) {
285+
pthread_cond_signal(&q->cond);
286+
}
280287
pthread_mutex_unlock(&q->lock);
281288
// Maybe flushed for disabled, here return 0 directly
282289
return 0;

0 commit comments

Comments
 (0)