summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xtinyDAV/src/video/tdav_session_video.c165
-rwxr-xr-xtinyMEDIA/include/tinymedia/tmedia_common.h1
-rwxr-xr-xtinyMEDIA/src/tmedia_common.c12
3 files changed, 120 insertions, 58 deletions
diff --git a/tinyDAV/src/video/tdav_session_video.c b/tinyDAV/src/video/tdav_session_video.c
index 920d005..d0d65f2 100755
--- a/tinyDAV/src/video/tdav_session_video.c
+++ b/tinyDAV/src/video/tdav_session_video.c
@@ -755,6 +755,9 @@ static int _tdav_session_video_codec_set_int32(tdav_session_video_t* self, const
ret = tmedia_producer_set(base->producer, param);
}
else {
+ if (tsk_strniequals(key, "out-size", 8)) {
+ self->encoder.size_changed = tsk_true;
+ }
ret = tmedia_codec_set((tmedia_codec_t*)(self)->encoder.codec, param);
}
}
@@ -1430,7 +1433,7 @@ static int _tdav_session_video_timer_cb(const void* arg, tsk_timer_id_t timer_id
uint64_t bw_est_kbps;
tsk_bool_t cavgneg, update_qavg = tsk_false, update_size = tsk_false;
unsigned enc_avg_time;
- int32_t bw_up_base_kbps, bw_up_ref_kbps;
+ int32_t bw_up_base_kbps, bw_up_ref_kbps, bw_up_new_kbps;
tsk_mutex_lock(video->h_mutex_qos);
q1 = video->q1_n ? session->qos_metrics.q1 : 1.f;
@@ -1469,60 +1472,6 @@ static int _tdav_session_video_timer_cb(const void* arg, tsk_timer_id_t timer_id
session->qos_metrics.last_update_time = tsk_time_now();
tsk_mutex_unlock(video->h_mutex_qos);
-#if BUILD_TYPE_TCH
- {
- unsigned best_enc_time;
- float vs_weight;
-
- // Check if encoding time is too high or low
- best_enc_time = 1000 / (codec->out.fps);
- if (enc_avg_time > (best_enc_time + (best_enc_time >> 2))) { /* Too slow */
- if (++video->num_enc_avg_time_high >= 2) {
- update_size = tsk_true;
- vs_weight = ((best_enc_time + (best_enc_time >> 2)) / (float)enc_avg_time);
- TSK_DEBUG_INFO("_tdav_session_video_timer_cb: upsample the video size: %f", vs_weight);
- video->num_enc_avg_time_high = 0;
- }
- }
- else { /* Too fast */
- if (enc_avg_time < (best_enc_time - (best_enc_time >> 1))) {
- if (--video->num_enc_avg_time_high <= -2) {
- if (enc_avg_time != 0.f && (codec->out.width * codec->out.height) < (video->neg_width * video->neg_height)) { // video size downsampled in the past?
- update_size = tsk_true;
- vs_weight = ((best_enc_time - (best_enc_time >> 1)) / (float)enc_avg_time);
- TSK_DEBUG_INFO("_tdav_session_video_timer_cb: downsample the video size: %f", vs_weight);
- }
- video->num_enc_avg_time_high = 0;
- }
- }
- }
-
- // Update video size
- if (update_size) {
- unsigned new_w, new_h, new_s;
- char size[128] = {'\0'};
- tmedia_param_t* param;
- new_w = (((unsigned)(codec->out.width * vs_weight)) + 16) & -16; // +16 instead of +15 to make sure the size will be >= 16
- new_h = (((unsigned)(codec->out.height * vs_weight)) + 16) & -16;
- new_s = (new_w & 0xFFFF) | (new_h << 16);
- TSK_DEBUG_INFO("_tdav_session_video_timer_cb: new video size: (%u, %u), neg size: (%u, %u)", new_w, new_h, video->neg_width, video->neg_height);
- param = tmedia_param_create(tmedia_pat_set,
- tmedia_video,
- tmedia_ppt_codec,
- tmedia_pvt_int32,
- "out-size",
- (void*)&new_s);
- if (param) {
- tsk_mutex_lock(video->encoder.h_mutex);
- tmedia_codec_set(TMEDIA_CODEC(codec), param);
- video->encoder.size_changed = tsk_true;
- tsk_mutex_unlock(video->encoder.h_mutex);
- TSK_OBJECT_SAFE_FREE(param);
- }
- }
- }
-#endif
-
// Compute the new qvag value
qavg = q1 * 0.1f + q2 * 0.4f + q3 * 0.1f + q4 * 0.0f + q5 * 0.4f;
cavg = (qavg - session->qos_metrics.qvag);
@@ -1549,11 +1498,14 @@ static int _tdav_session_video_timer_cb(const void* arg, tsk_timer_id_t timer_id
update_qavg = (cavg > 0.1f);
}
- bw_up_base_kbps = tmedia_get_video_bandwidth_kbps_2(codec->out.width, codec->out.height, codec->out.fps);
+ // Do not use "codec->out.width" and "codec->out.height" to compute "bw_up_base_kbps" as these values could be changed when
+ // adapt. resolution is enabled
+ bw_up_base_kbps = tmedia_get_video_bandwidth_kbps_2(video->neg_width, video->neg_height, codec->out.fps);
bw_up_ref_kbps = TMEDIA_CODEC(codec)->bandwidth_max_upload;
if (bw_up_ref_kbps < 0 || bw_up_ref_kbps == INT_MAX) {
- bw_up_ref_kbps = tmedia_get_video_bandwidth_kbps_2(codec->out.width, codec->out.height, codec->out.fps);
+ bw_up_ref_kbps = bw_up_base_kbps;
}
+ bw_up_new_kbps = bw_up_ref_kbps; // default value will be update depending on qavg
// Unconditionally decrease the bandwidth when the quality is < 90%
// bandwidth will decrease regardless qavg value as the ref. value is recursive
@@ -1563,7 +1515,7 @@ static int _tdav_session_video_timer_cb(const void* arg, tsk_timer_id_t timer_id
if (update_qavg) {
// Update the upload bandwidth
- int32_t bw_up_new_kbps, bw_up_max_kbps = base->bandwidth_max_upload_kbps; // user-defined maximum
+ int32_t bw_up_max_kbps = base->bandwidth_max_upload_kbps; // user-defined maximum
// When the qavg is within ]90-100]% we increase the ref. bw
if (qavg > 0.9f) {
@@ -1580,6 +1532,103 @@ static int _tdav_session_video_timer_cb(const void* arg, tsk_timer_id_t timer_id
session->qos_metrics.qvag = qavg;
}
//!\ update qavg only if condition "c" is true
+
+
+ /* Update size depending on bw */
+#if BUILD_TYPE_TCH
+ {
+ // A video quality is defined by MR (Motion Rank) like this:
+ // MR(#1)->poor, #2->acceptable, #4->good, #6->excellent ....
+ // Higher the MR is higher is the bandwidth and the quality
+ // The algorithm to change the video size depending on the bandwidth is straightforward:
+ // 1/ Compute the right bandwidth (bw_up_new_kbps) using Qavg as done above
+ // 2/ From the current video resolution (width, height), framerate(fps) and bandwidth(bw_up_new_kbps) compute the MR (a.k.a quality)
+ // 3/ If the computed MR is <=#1(poor) then, downsample the resolution to have MR=#2(acceptable)
+ // 4/ If the computed MR is >=#4 and the current resolution is lower than what was negotiated then, upsample the resolution to have MR=#2 (at most)
+ // In short: we want MR to stay within [2, %[
+ int32_t mr = tmedia_get_video_motion_rank(codec->out.width, codec->out.height, codec->out.fps, bw_up_new_kbps);
+ int32_t mr_diff = 0;
+ update_size = ((mr <= 1) || (mr >= 4 && (codec->out.width * codec->out.height) < (video->neg_width * video->neg_height)));
+ if (update_size) {
+ mr_diff = (mr - 2);
+ }
+ if (mr_diff != 0) {
+ unsigned new_w, new_h, min_w, min_h, max_w, max_h;
+ if (mr_diff > 0) {
+ new_w = ((codec->out.width << mr_diff) + 15) & -16;
+ new_h = ((codec->out.height << mr_diff) + 15) & -16;
+ }
+ else {
+ new_w = ((codec->out.width >> (-mr_diff)) + 15) & -16;
+ new_h = ((codec->out.height >> (-mr_diff)) + 15) & -16;
+ }
+ min_w = 16;
+ min_h = 16;
+ max_w = video->neg_width;
+ max_h = video->neg_height;
+ if (tmedia_defaults_get_adapt_video_size_range_enabled()) {
+ tmedia_pref_video_size_t min, max;
+ if (tmedia_defaults_get_pref_video_size_range(&min, &max) == 0) {
+ tmedia_video_get_size(min, &min_w, &min_h);
+ tmedia_video_get_size(max, &max_w, &max_h);
+ }
+ }
+ new_w = TSK_CLAMP(min_w, new_w, max_w);
+ new_h = TSK_CLAMP(min_h, new_h, max_h);
+ if ((new_w * new_h) < (codec->out.width * codec->out.height)) { // make sure we'll set lower resolution after clipping
+ TSK_DEBUG_INFO("_tdav_session_video_timer_cb: [[size change based on bandwidth]] new video size: (%u, %u), neg size: (%u, %u)", new_w, new_h, video->neg_width, video->neg_height);
+ tsk_mutex_lock(video->encoder.h_mutex);
+ _tdav_session_video_codec_set_int32(video, "out-size", (int32_t)((new_w & 0xFFFF) | (new_h << 16)));
+ tsk_mutex_unlock(video->encoder.h_mutex);
+ }
+ }
+ }
+#endif /* BUILD_TYPE_TCH */
+
+ /* Update size depending cpu usage */
+#if BUILD_TYPE_TCH
+ if (!update_size) {
+ unsigned best_enc_time;
+ float vs_weight;
+
+ // Check if encoding time is too high or low
+ best_enc_time = 1000 / (codec->out.fps);
+ if (enc_avg_time > (best_enc_time + (best_enc_time >> 2))) { /* Too slow */
+ if (++video->num_enc_avg_time_high >= 2) {
+ update_size = tsk_true;
+ vs_weight = ((best_enc_time + (best_enc_time >> 2)) / (float)enc_avg_time);
+ TSK_DEBUG_INFO("_tdav_session_video_timer_cb: upsample the video size: %f", vs_weight);
+ video->num_enc_avg_time_high = 0;
+ }
+ }
+ else { /* Too fast */
+ if (enc_avg_time < (best_enc_time - (best_enc_time >> 1))) {
+ if (--video->num_enc_avg_time_high <= -2) {
+ if (enc_avg_time != 0.f && (codec->out.width * codec->out.height) < (video->neg_width * video->neg_height)) { // video size downsampled in the past?
+ update_size = tsk_true;
+ vs_weight = ((best_enc_time - (best_enc_time >> 1)) / (float)enc_avg_time);
+ TSK_DEBUG_INFO("_tdav_session_video_timer_cb: downsample the video size: %f", vs_weight);
+ }
+ video->num_enc_avg_time_high = 0;
+ }
+ }
+ }
+
+ // Update video size
+ if (update_size) {
+ unsigned new_w, new_h, new_s;
+ char size[128] = {'\0'};
+ new_w = (((unsigned)(codec->out.width * vs_weight)) + 16) & -16; // +16 instead of +15 to make sure the size will be >= 16
+ new_h = (((unsigned)(codec->out.height * vs_weight)) + 16) & -16;
+ new_s = (new_w & 0xFFFF) | (new_h << 16);
+ TSK_DEBUG_INFO("_tdav_session_video_timer_cb: [[size change based on cpu]] new video size: (%u, %u), neg size: (%u, %u)", new_w, new_h, video->neg_width, video->neg_height);
+ tsk_mutex_lock(video->encoder.h_mutex);
+ _tdav_session_video_codec_set_int32(video, "out-size", (int32_t)new_s);
+ video->encoder.size_changed = tsk_true;
+ tsk_mutex_unlock(video->encoder.h_mutex);
+ }
+ }
+#endif /* BUILD_TYPE_TCH */
}
tsk_object_unref(TSK_OBJECT(codec));
}
diff --git a/tinyMEDIA/include/tinymedia/tmedia_common.h b/tinyMEDIA/include/tinymedia/tmedia_common.h
index e786146..5fc041e 100755
--- a/tinyMEDIA/include/tinymedia/tmedia_common.h
+++ b/tinyMEDIA/include/tinymedia/tmedia_common.h
@@ -263,6 +263,7 @@ TINYMEDIA_API int tmedia_get_video_quality(tmedia_bandwidth_level_t bl);
TINYMEDIA_API int32_t tmedia_get_video_bandwidth_kbps(unsigned width, unsigned height, unsigned fps, unsigned motion_rank);
TINYMEDIA_API int32_t tmedia_get_video_bandwidth_kbps_2(unsigned width, unsigned height, unsigned fps);
TINYMEDIA_API int32_t tmedia_get_video_bandwidth_kbps_3();
+TINYMEDIA_API int32_t tmedia_get_video_motion_rank(unsigned width, unsigned height, unsigned fps, int32_t bw_kbps);
#define tmedia_get_video_qscale tmedia_get_video_quality
TMEDIA_END_DECLS
diff --git a/tinyMEDIA/src/tmedia_common.c b/tinyMEDIA/src/tmedia_common.c
index 86832e1..1f20845 100755
--- a/tinyMEDIA/src/tmedia_common.c
+++ b/tinyMEDIA/src/tmedia_common.c
@@ -451,4 +451,16 @@ int32_t tmedia_get_video_bandwidth_kbps_3()
unsigned height = 2160;
tmedia_video_get_size(tmedia_defaults_get_pref_video_size(), &width, &height);
return tmedia_get_video_bandwidth_kbps(width, height, tmedia_defaults_get_video_fps(), tmedia_defaults_get_video_motion_rank());
+}
+
+int32_t tmedia_get_video_motion_rank(unsigned width, unsigned height, unsigned fps, int32_t bw_kbps)
+{
+ if (!width || !height || !fps || bw_kbps <= 0) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return 0;
+ }
+ else {
+ float mr = (bw_kbps * 1024.f) / (width * height * fps * 0.07f);
+ return (int32_t)(TSK_MAX(1.f, (mr + 0.5f)));
+ }
} \ No newline at end of file
OpenPOWER on IntegriCloud