summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--branches/2.0/doubango/thirdparties/wince/lib/x86/libvpx.libbin2608822 -> 2677446 bytes
-rw-r--r--branches/2.0/doubango/tinyDAV/src/codecs/vpx/tdav_codec_vp8.c198
-rw-r--r--branches/2.0/doubango/tinyDAV/src/video/directx/tdav_producer_screencast_ddraw.cxx169
3 files changed, 218 insertions, 149 deletions
diff --git a/branches/2.0/doubango/thirdparties/wince/lib/x86/libvpx.lib b/branches/2.0/doubango/thirdparties/wince/lib/x86/libvpx.lib
index b01386c..7c0fee3 100644
--- a/branches/2.0/doubango/thirdparties/wince/lib/x86/libvpx.lib
+++ b/branches/2.0/doubango/thirdparties/wince/lib/x86/libvpx.lib
Binary files differ
diff --git a/branches/2.0/doubango/tinyDAV/src/codecs/vpx/tdav_codec_vp8.c b/branches/2.0/doubango/tinyDAV/src/codecs/vpx/tdav_codec_vp8.c
index f8e7f2f..bbda542 100644
--- a/branches/2.0/doubango/tinyDAV/src/codecs/vpx/tdav_codec_vp8.c
+++ b/branches/2.0/doubango/tinyDAV/src/codecs/vpx/tdav_codec_vp8.c
@@ -19,13 +19,13 @@
*/
/**@file tdav_codec_vp8.c
- * @brief VP8 codec
- * The RTP packetizer/depacketizer follows draft-ietf-payload-vp8 and draft-bankoski-vp8-bitstream-05
- * Google's VP8 (http://www.webmproject.org/) encoder/decoder
- *
- * We require v1.3.0 (2013-12-02 10:37:51) or later. For iOS, because of issue 423 (https://code.google.com/p/doubango/issues/detail?id=423) we require a version after "Mon, 28 Apr 2014 22:42:23 +0100 (14:42 -0700)" integrating fix in http://git.chromium.org/gitweb/?p=webm/libvpx.git;a=commit;h=33df6d1fc1d268b4901b74b4141f83594266f041
- *
- */
+* @brief VP8 codec
+* The RTP packetizer/depacketizer follows draft-ietf-payload-vp8 and draft-bankoski-vp8-bitstream-05
+* Google's VP8 (http://www.webmproject.org/) encoder/decoder
+*
+* We require v1.3.0 (2013-12-02 10:37:51) or later. For iOS, because of issue 423 (https://code.google.com/p/doubango/issues/detail?id=423) we require a version after "Mon, 28 Apr 2014 22:42:23 +0100 (14:42 -0700)" integrating fix in http://git.chromium.org/gitweb/?p=webm/libvpx.git;a=commit;h=33df6d1fc1d268b4901b74b4141f83594266f041
+*
+*/
#include "tinydav/codecs/vpx/tdav_codec_vp8.h"
#if HAVE_LIBVPX
@@ -134,24 +134,24 @@ static int tdav_codec_vp8_set(tmedia_codec_t* self, const tmedia_param_t* param)
tmedia_codec_action_t action = (tmedia_codec_action_t)TSK_TO_INT32((uint8_t*)param->value);
switch (action) {
case tmedia_codec_action_encode_idr:
- {
- vp8->encoder.force_idr = tsk_true;
- return 0;
- }
+ {
+ vp8->encoder.force_idr = tsk_true;
+ return 0;
+ }
case tmedia_codec_action_bw_down:
- {
- vp8->encoder.cfg.rc_target_bitrate = TSK_CLAMP(0, (int32_t)((vp8->encoder.cfg.rc_target_bitrate << 1) / 3), TMEDIA_CODEC(vp8)->bandwidth_max_upload);
- TSK_DEBUG_INFO("New target bitrate = %d kbps", vp8->encoder.cfg.rc_target_bitrate);
- reconf = tsk_true;
- break;
- }
+ {
+ vp8->encoder.cfg.rc_target_bitrate = TSK_CLAMP(0, (int32_t)((vp8->encoder.cfg.rc_target_bitrate << 1) / 3), TMEDIA_CODEC(vp8)->bandwidth_max_upload);
+ TSK_DEBUG_INFO("New target bitrate = %d kbps", vp8->encoder.cfg.rc_target_bitrate);
+ reconf = tsk_true;
+ break;
+ }
case tmedia_codec_action_bw_up:
- {
- vp8->encoder.cfg.rc_target_bitrate = TSK_CLAMP(0, (int32_t)((vp8->encoder.cfg.rc_target_bitrate * 3) >> 1), TMEDIA_CODEC(vp8)->bandwidth_max_upload);
- TSK_DEBUG_INFO("New target bitrate = %d kbps", vp8->encoder.cfg.rc_target_bitrate);
- reconf = tsk_true;
- break;
- }
+ {
+ vp8->encoder.cfg.rc_target_bitrate = TSK_CLAMP(0, (int32_t)((vp8->encoder.cfg.rc_target_bitrate * 3) >> 1), TMEDIA_CODEC(vp8)->bandwidth_max_upload);
+ TSK_DEBUG_INFO("New target bitrate = %d kbps", vp8->encoder.cfg.rc_target_bitrate);
+ reconf = tsk_true;
+ break;
+ }
}
}
else if (tsk_striequals(param->key, "bw_kbps")) { // both up and down (from the SDP)
@@ -287,18 +287,18 @@ static tsk_size_t tdav_codec_vp8_encode(tmedia_codec_t* self, const void* in_dat
while ((pkt = vpx_codec_get_cx_data(&vp8->encoder.context, &iter))) {
switch (pkt->kind) {
case VPX_CODEC_CX_FRAME_PKT:
- {
- tdav_codec_vp8_encap(vp8, pkt);
- break;
- }
+ {
+ tdav_codec_vp8_encap(vp8, pkt);
+ break;
+ }
default:
case VPX_CODEC_STATS_PKT: /**< Two-pass statistics for this frame */
case VPX_CODEC_PSNR_PKT: /**< PSNR statistics for this frame */
case VPX_CODEC_CUSTOM_PKT: /**< Algorithm extensions */
- {
- TSK_DEBUG_INFO("pkt->kind=%d not supported", (int)pkt->kind);
- break;
- }
+ {
+ TSK_DEBUG_INFO("pkt->kind=%d not supported", (int)pkt->kind);
+ break;
+ }
}
}
@@ -389,30 +389,30 @@ static tsk_size_t tdav_codec_vp8_decode(tmedia_codec_t* self, const void* in_dat
// New frame ?
if (vp8->decoder.last_timestamp != rtp_hdr->timestamp) {
/* 4.3. VP8 Payload Header
- Note that the header is present only in packets
- which have the S bit equal to one and the PartID equal to zero in the
- payload descriptor. Subsequent packets for the same frame do not
- carry the payload header.
- 0 1 2 3 4 5 6 7
- +-+-+-+-+-+-+-+-+
- |Size0|H| VER |P|
- +-+-+-+-+-+-+-+-+
- | Size1 |
- +-+-+-+-+-+-+-+-+
- | Size2 |
- +-+-+-+-+-+-+-+-+
- | Bytes 4..N of |
- | VP8 payload |
- : :
- +-+-+-+-+-+-+-+-+
- | OPTIONAL RTP |
- | padding |
- : :
- +-+-+-+-+-+-+-+-+
- P: Inverse key frame flag. When set to 0 the current frame is a key
- frame. When set to 1 the current frame is an interframe. Defined
- in [RFC6386]
- */
+ Note that the header is present only in packets
+ which have the S bit equal to one and the PartID equal to zero in the
+ payload descriptor. Subsequent packets for the same frame do not
+ carry the payload header.
+ 0 1 2 3 4 5 6 7
+ +-+-+-+-+-+-+-+-+
+ |Size0|H| VER |P|
+ +-+-+-+-+-+-+-+-+
+ | Size1 |
+ +-+-+-+-+-+-+-+-+
+ | Size2 |
+ +-+-+-+-+-+-+-+-+
+ | Bytes 4..N of |
+ | VP8 payload |
+ : :
+ +-+-+-+-+-+-+-+-+
+ | OPTIONAL RTP |
+ | padding |
+ : :
+ +-+-+-+-+-+-+-+-+
+ P: Inverse key frame flag. When set to 0 the current frame is a key
+ frame. When set to 1 the current frame is an interframe. Defined
+ in [RFC6386]
+ */
// Reset accumulator position
vp8->decoder.accumulator_pos = 0;
@@ -601,7 +601,7 @@ static tsk_bool_t tdav_codec_vp8_sdp_att_match(const tmedia_codec_t* codec, cons
TMEDIA_CODEC_VIDEO(codec)->out.height = out_height;
}
- return tsk_true;
+ return tsk_true;
}
static char* tdav_codec_vp8_sdp_att_get(const tmedia_codec_t* codec, const char* att_name)
@@ -616,7 +616,7 @@ static char* tdav_codec_vp8_sdp_att_get(const tmedia_codec_t* codec, const char*
return tmedia_get_video_imageattr(TMEDIA_CODEC_VIDEO(codec)->pref_size,
TMEDIA_CODEC_VIDEO(codec)->in.width, TMEDIA_CODEC_VIDEO(codec)->in.height, TMEDIA_CODEC_VIDEO(codec)->out.width, TMEDIA_CODEC_VIDEO(codec)->out.height);
}
- return tsk_null;
+ return tsk_null;
}
/* ============ VP8 object definition ================= */
@@ -752,8 +752,12 @@ int tdav_codec_vp8_open_encoder(tdav_codec_vp8_t* self)
/* vpx_codec_control(&self->encoder.context, VP8E_SET_STATIC_THRESHOLD, 800); */
#if !TDAV_UNDER_MOBILE /* must not remove: crash on Android for sure and probably on iOS also (all ARM devices ?) */
vpx_codec_control(&self->encoder.context, VP8E_SET_NOISE_SENSITIVITY, 2);
+#elif TDAV_UNDER_WINDOWS_CE
+ vpx_codec_control(&self->encoder.context, VP8E_SET_NOISE_SENSITIVITY, 16);
+ vpx_codec_control(&self->encoder.context, VP8E_SET_CPUUSED, 16);
+ vpx_codec_control(&self->encoder.context, VP8E_SET_STATIC_THRESHOLD, 16);
+ vpx_codec_control(&self->encoder.context, VP8E_SET_SHARPNESS, 16);
#endif
- /* vpx_codec_control(&self->encoder.context, VP8E_SET_CPUUSED, 0); */
// Set number of partitions
#if defined(VPX_CODEC_USE_OUTPUT_PARTITION)
@@ -780,8 +784,8 @@ int tdav_codec_vp8_open_encoder(tdav_codec_vp8_t* self)
TSK_DEBUG_ERROR("Failed to create mutex");
return -4;
}
-
- self->encoder.frame_count = 0;
+
+ self->encoder.frame_count = 0;
self->encoder.initialized = tsk_true;
@@ -936,9 +940,9 @@ static void tdav_codec_vp8_encap(tdav_codec_vp8_t* self, const vpx_codec_cx_pkt_
while (index<pkt_size) {
if (part_start) {
/* PartID SHOULD be incremented for each subsequent partition,
- but MAY be kept at 0 for all packets. PartID MUST NOT be larger
- than 8.
- */
+ but MAY be kept at 0 for all packets. PartID MUST NOT be larger
+ than 8.
+ */
part_ID++;
}
part_size = TSK_MIN(TDAV_VP8_RTP_PAYLOAD_MAX_SIZE, (pkt_size - index));
@@ -960,42 +964,42 @@ static void tdav_codec_vp8_rtp_callback(tdav_codec_vp8_t *self, const void *data
tsk_size_t paydesc_and_hdr_size = TDAV_VP8_PAY_DESC_SIZE;
tsk_bool_t has_hdr;
/* draft-ietf-payload-vp8-04 - 4.2. VP8 Payload Descriptor
- 0 1 2 3 4 5 6 7
- +-+-+-+-+-+-+-+-+
- |X|R|N|S|PartID | (REQUIRED)
- +-+-+-+-+-+-+-+-+
- X: |I|L|T|K| RSV | (OPTIONAL)
- +-+-+-+-+-+-+-+-+
- I: |M| PictureID | (OPTIONAL)
- +-+-+-+-+-+-+-+-+
- L: | TL0PICIDX | (OPTIONAL)
- +-+-+-+-+-+-+-+-+
- T/K: |TID|Y| KEYIDX | (OPTIONAL)
- +-+-+-+-+-+-+-+-+
-
- draft-ietf-payload-vp8-04 - 4.3. VP8 Payload Header
- 0 1 2 3 4 5 6 7
- +-+-+-+-+-+-+-+-+
- |Size0|H| VER |P|
- +-+-+-+-+-+-+-+-+
- | Size1 |
- +-+-+-+-+-+-+-+-+
- | Size2 |
- +-+-+-+-+-+-+-+-+
- | Bytes 4..N of |
- | VP8 payload |
- : :
- +-+-+-+-+-+-+-+-+
- | OPTIONAL RTP |
- | padding |
- : :
- +-+-+-+-+-+-+-+-+
- */
+ 0 1 2 3 4 5 6 7
+ +-+-+-+-+-+-+-+-+
+ |X|R|N|S|PartID | (REQUIRED)
+ +-+-+-+-+-+-+-+-+
+ X: |I|L|T|K| RSV | (OPTIONAL)
+ +-+-+-+-+-+-+-+-+
+ I: |M| PictureID | (OPTIONAL)
+ +-+-+-+-+-+-+-+-+
+ L: | TL0PICIDX | (OPTIONAL)
+ +-+-+-+-+-+-+-+-+
+ T/K: |TID|Y| KEYIDX | (OPTIONAL)
+ +-+-+-+-+-+-+-+-+
+
+ draft-ietf-payload-vp8-04 - 4.3. VP8 Payload Header
+ 0 1 2 3 4 5 6 7
+ +-+-+-+-+-+-+-+-+
+ |Size0|H| VER |P|
+ +-+-+-+-+-+-+-+-+
+ | Size1 |
+ +-+-+-+-+-+-+-+-+
+ | Size2 |
+ +-+-+-+-+-+-+-+-+
+ | Bytes 4..N of |
+ | VP8 payload |
+ : :
+ +-+-+-+-+-+-+-+-+
+ | OPTIONAL RTP |
+ | padding |
+ : :
+ +-+-+-+-+-+-+-+-+
+ */
/*
- Note that the header is present only in packets which have the S bit equal to one and the
- PartID equal to zero in the payload descriptor.
- */
+ Note that the header is present only in packets which have the S bit equal to one and the
+ PartID equal to zero in the payload descriptor.
+ */
if ((has_hdr = (part_start && partID == 0))) {
has_hdr = tsk_true;
paydesc_and_hdr_size += 0; // encoded data already contains payload header?
diff --git a/branches/2.0/doubango/tinyDAV/src/video/directx/tdav_producer_screencast_ddraw.cxx b/branches/2.0/doubango/tinyDAV/src/video/directx/tdav_producer_screencast_ddraw.cxx
index 7fdb078..3eba11c 100644
--- a/branches/2.0/doubango/tinyDAV/src/video/directx/tdav_producer_screencast_ddraw.cxx
+++ b/branches/2.0/doubango/tinyDAV/src/video/directx/tdav_producer_screencast_ddraw.cxx
@@ -51,33 +51,49 @@
#endif /* DDRAW_IS_ALIGNED */
#if !defined(DDRAW_HIGH_PRIO_MEMCPY)
-# define DDRAW_HIGH_PRIO_MEMCPY 0
+# define DDRAW_HIGH_PRIO_MEMCPY 0 // BOOL
#endif /* DDRAW_HIGH_PRIO_MEMCPY */
#if !defined(DDRAW_CPU_MONITOR)
-# define DDRAW_CPU_MONITOR 0
+# define DDRAW_CPU_MONITOR 0 // BOOL
#endif /* DDRAW_CPU_MONITOR */
-#if !defined(DDRAW_MEM_SURFACE_DIRECT_ACCESS)
-# define DDRAW_MEM_SURFACE_DIRECT_ACCESS 0 // direct access to "ddsd.lpSurface" is very slow even if the memory is correctly aligned: to be investigated
-#endif /* DDRAW_MEM_SURFACE_DIRECT_ACCESS */
+#if !defined(DDRAW_CPU_THROTTLING)
+# define DDRAW_CPU_THROTTLING 0 // BOOL
+#endif /* DDRAW_CPU_THROTTLING */
-#if DDRAW_CPU_MONITOR && !defined(DDRAW_CPU_MONITOR_TIME_OUT)
-# define DDRAW_CPU_MONITOR_TIME_OUT 1000
+#if (DDRAW_CPU_MONITOR || DDRAW_CPU_THROTTLING) && !defined(DDRAW_CPU_SCHEDULE_TIMEOUT)
+# define DDRAW_CPU_SCHEDULE_TIMEOUT 800 // millis
#endif /* DDRAW_CPU_MONITOR */
+#if defined(DDRAW_CPU_THROTTLING) && !defined(DDRAW_CPU_THROTTLING_FPS_MIN)
+# define DDRAW_CPU_THROTTLING_FPS_MIN 1 // frames per second
+#endif /* DDRAW_CPU_THROTTLING_FPS_MIN */
+
+#if defined(DDRAW_CPU_THROTTLING) && !defined(DDRAW_CPU_THROTTLING_THRESHOLD)
+# define DDRAW_CPU_THROTTLING_THRESHOLD 70 // percent
+#endif /* DDRAW_CPU_THROTTLING_THRESHOLD */
+
+#if defined(DDRAW_CPU_THROTTLING) && !defined(DDRAW_CPU_THROTTLING_THRESHOLD_MARGIN)
+# define DDRAW_CPU_THROTTLING_THRESHOLD_MARGIN 5 // percent
+#endif /* DDRAW_CPU_THROTTLING_THRESHOLD_MARGIN */
+
#if !defined(DDRAW_MT)
-# define DDRAW_MT 0 // Multi-threading
+# define DDRAW_MT 1 // BOOL: Multi-threading
#endif /* DDRAW_MT */
#if defined (DDRAW_MT) && !defined(DDRAW_MT_COUNT)
-# define DDRAW_MT_COUNT 4 // Number of buffers to use
+# define DDRAW_MT_COUNT 3 // Number of buffers to use
#endif /* DDRAW_MT_COUNT */
#if defined(DDRAW_MT_COUNT)
# define DDRAW_MT_EVENT_SHUTDOWN_INDEX DDRAW_MT_COUNT
#endif
+#if !defined(DDRAW_MEM_SURFACE_DIRECT_ACCESS)
+# define DDRAW_MEM_SURFACE_DIRECT_ACCESS 0 // direct access to "ddsd.lpSurface" is very slow even if the memory is correctly aligned: to be investigated
+#endif /* DDRAW_MEM_SURFACE_DIRECT_ACCESS */
+
#if !defined(DDRAW_PREVIEW)
# if TDAV_UNDER_WINDOWS_CE && (BUILD_TYPE_GE || SIN_CITY)
# define DDRAW_PREVIEW 0 // Do not waste time displaying the preview on "WEC7 + (GE | SINCITY)"
@@ -111,10 +127,13 @@ typedef struct tdav_producer_screencast_ddraw_s
BITMAPINFO bi_preview;
#endif /* DDRAW_PREVIEW */
-#if DDRAW_CPU_MONITOR
+#if DDRAW_CPU_MONITOR || DDRAW_CPU_THROTTLING
tsk_timer_manager_handle_t *p_timer_mgr;
- tsk_timer_id_t id_timer_cpu;
-#endif /* DDRAW_CPU_MONITOR */
+ struct {
+ tsk_timer_id_t id_timer;
+ int fps_target;
+ } cpu;
+#endif /* DDRAW_CPU_MONITOR || DDRAW_CPU_THROTTLING */
#if DDRAW_MT
struct{
@@ -740,11 +759,15 @@ static int _tdav_producer_screencast_ddraw_prepare(tmedia_producer_t* p_self, co
p_ddraw->bi_preview.bmiHeader.biSizeImage = (p_ddraw->bi_preview.bmiHeader.biWidth * p_ddraw->bi_preview.bmiHeader.biHeight * (p_ddraw->bi_preview.bmiHeader.biBitCount >> 3));
#endif /* DDRAW_PREVIEW */
-#if DDRAW_CPU_MONITOR
+#if DDRAW_CPU_MONITOR || DDRAW_CPU_THROTTLING
if (!p_ddraw->p_timer_mgr) {
p_ddraw->p_timer_mgr = tsk_timer_manager_create();
}
-#endif /* DDRAW_CPU_MONITOR */
+#endif /* DDRAW_CPU_MONITOR ||DDRAW_CPU_THROTTLING */
+
+#if DDRAW_CPU_THROTTLING
+ p_ddraw->cpu.fps_target = (TMEDIA_PRODUCER(p_ddraw)->video.fps + DDRAW_CPU_THROTTLING_FPS_MIN) >> 1; // start with minimum fps and increase the value based on the fps
+#endif /* DDRAW_CPU_THROTTLING */
bail:
tsk_safeobj_unlock(p_ddraw);
@@ -807,16 +830,16 @@ static int _tdav_producer_screencast_ddraw_start(tmedia_producer_t* p_self)
}
#endif /* DDRAW_MT */
#endif /* DDRAW_HIGH_PRIO_MEMCPY */
-#if DDRAW_CPU_MONITOR
+#if DDRAW_CPU_MONITOR || DDRAW_CPU_THROTTLING
ret = tsk_timer_manager_start(p_ddraw->p_timer_mgr);
if (ret == 0) {
- p_ddraw->id_timer_cpu = tsk_timer_manager_schedule(p_ddraw->p_timer_mgr, DDRAW_CPU_MONITOR_TIME_OUT, _tdav_producer_screencast_timer_cb, p_ddraw);
+ p_ddraw->cpu.id_timer = tsk_timer_manager_schedule(p_ddraw->p_timer_mgr, DDRAW_CPU_SCHEDULE_TIMEOUT, _tdav_producer_screencast_timer_cb, p_ddraw);
}
else {
ret = 0; // not fatal error
DDRAW_DEBUG_WARN("Failed to start CPU timer");
}
-#endif /* DDRAW_CPU_MONITOR */
+#endif /* DDRAW_CPU_MONITOR || DDRAW_CPU_THROTTLING */
bail:
if (ret) {
@@ -874,11 +897,11 @@ static int _tdav_producer_screencast_ddraw_stop(tmedia_producer_t* p_self)
p_ddraw->b_started = tsk_false;
p_ddraw->b_paused = tsk_false;
-#if DDRAW_CPU_MONITOR
+#if DDRAW_CPU_MONITOR || DDRAW_CPU_THROTTLING
if (p_ddraw->p_timer_mgr) {
tsk_timer_manager_stop(p_ddraw->p_timer_mgr);
}
-#endif /* DDRAW_CPU_MONITOR */
+#endif /* DDRAW_CPU_MONITOR ||DDRAW_CPU_THROTTLING */
// stop grabber thread
if (p_ddraw->tid[0]) {
@@ -934,6 +957,16 @@ static int _tdav_producer_screencast_grab(tdav_producer_screencast_ddraw_t* p_se
#endif
}
+#if DDRAW_MT
+ {
+ INT iIndex = 0;
+ for (; (iIndex < DDRAW_MT_COUNT) && (p_self->mt.b_flags_array[iIndex] == TRUE); ++iIndex);
+ if (iIndex == DDRAW_MT_COUNT) {
+ goto bail;
+ }
+ }
+#endif /* DDRAW_MT */
+
if (p_self->p_surf_primary->IsLost() == DDERR_SURFACELOST) {
DDRAW_CHECK_HR(hr = p_self->p_surf_primary->Restore());
}
@@ -1274,15 +1307,19 @@ bail:
static void* TSK_STDCALL _tdav_producer_screencast_grap_thread(void *arg)
{
tdav_producer_screencast_ddraw_t* p_ddraw = (tdav_producer_screencast_ddraw_t*)arg;
+ tmedia_producer_t* p_base = TMEDIA_PRODUCER(arg);
int ret = 0;
// FPS manager
uint64_t TimeNow, TimeLastFrame = 0;
- const uint64_t TimeFrameDuration = (1000 / TMEDIA_PRODUCER(p_ddraw)->video.fps);
+ uint64_t TimeFrameDuration = (1000 / p_base->video.fps);
DDRAW_DEBUG_INFO("Grab thread -- START");
while (ret == 0 && p_ddraw->b_started) {
+#if DDRAW_CPU_THROTTLING
+ TimeFrameDuration = (1000 / p_ddraw->cpu.fps_target);
+#endif /* DDRAW_CPU_THROTTLING */
TimeNow = tsk_time_now();
if ((TimeNow - TimeLastFrame) > TimeFrameDuration) {
if (!p_ddraw->b_muted && !p_ddraw->b_paused) {
@@ -1331,6 +1368,7 @@ static void* TSK_STDCALL _tdav_producer_screencast_mt_encode_thread(void *arg)
DDRAW_DEBUG_ERROR("Invalid b_flags_array(%d)", dwIndex);
break;
}
+
p_base->enc_cb.callback(p_base->enc_cb.callback_data, p_ddraw->mt.p_buff_yuv_aligned_array[dwIndex], p_ddraw->n_buff_yuv);
p_ddraw->mt.b_flags_array[dwIndex] = FALSE;
}
@@ -1339,10 +1377,43 @@ static void* TSK_STDCALL _tdav_producer_screencast_mt_encode_thread(void *arg)
}
#endif /* DDRAW_MT */
-#if DDRAW_CPU_MONITOR
-static unsigned long long FileTimeToInt64(const FILETIME & ft) {
+#if DDRAW_CPU_MONITOR || DDRAW_CPU_THROTTLING
+static unsigned long long FileTimeToInt64(const FILETIME & ft)
+{
return (((unsigned long long)(ft.dwHighDateTime))<<32) | ((unsigned long long)ft.dwLowDateTime);
}
+static BOOL GetCpuPercents(unsigned long long* PercentIdle, unsigned long long* PercentUsage)
+{
+ static unsigned long long _prevTicks = 0;
+ static unsigned long long _prevIdleTime = 0;
+ unsigned long long ticks, idleTime;
+ BOOL bSaveValues = FALSE, bSet = FALSE;
+#if TDAV_UNDER_WINDOWS_CE
+ bSaveValues = TRUE;
+ ticks = GetTickCount();
+ idleTime = GetIdleTime();
+#else
+ {
+ FILETIME _idleTime, _kernelTime, _userTime;
+ if (GetSystemTimes(&_idleTime, &_kernelTime, &_userTime)) {
+ idleTime = FileTimeToInt64(_idleTime);
+ ticks = FileTimeToInt64(_kernelTime) + FileTimeToInt64(_userTime);
+ bSaveValues = TRUE;
+ }
+ }
+#endif
+ if (_prevTicks > 0) {
+ *PercentIdle = ((100 * (idleTime - _prevIdleTime)) / (ticks - _prevTicks));
+ *PercentUsage = 100 - *PercentIdle;
+ bSet = TRUE;
+ }
+ if (bSaveValues) {
+ _prevTicks = ticks;
+ _prevIdleTime = idleTime;
+ }
+
+ return bSet;
+}
static int _tdav_producer_screencast_timer_cb(const void* arg, tsk_timer_id_t timer_id)
{
@@ -1353,43 +1424,37 @@ static int _tdav_producer_screencast_timer_cb(const void* arg, tsk_timer_id_t ti
return 0;
}
- if (p_ddraw->id_timer_cpu == timer_id) {
- static unsigned long long _prevTicks = 0;
- static unsigned long long _prevIdleTime = 0;
- unsigned long long ticks, idleTime, PercentIdle, PercentUsage;
- BOOL bSaveValues = FALSE;
-#if TDAV_UNDER_WINDOWS_CE
- bSaveValues = TRUE;
- ticks = GetTickCount();
- idleTime = GetIdleTime();
-#else
- {
- FILETIME _idleTime, _kernelTime, _userTime;
- if (GetSystemTimes(&_idleTime, &_kernelTime, &_userTime)) {
- idleTime = FileTimeToInt64(_idleTime);
- ticks = FileTimeToInt64(_kernelTime) + FileTimeToInt64(_userTime);
- bSaveValues = TRUE;
- }
- }
-#endif
- if (_prevTicks > 0) {
- PercentIdle = ((100 * (idleTime - _prevIdleTime)) / (ticks - _prevTicks));
- PercentUsage = 100 - PercentIdle;
+ if (p_ddraw->cpu.id_timer == timer_id) {
+ unsigned long long PercentIdle, PercentUsage;
+ if (GetCpuPercents(&PercentIdle, &PercentUsage) == TRUE) {
TSK_DEBUG_INFO("\n\n****\n\nCPU Usage = %lld\n\n***", PercentUsage);
- }
- if (bSaveValues) {
- _prevTicks = ticks;
- _prevIdleTime = idleTime;
+#if DDRAW_CPU_THROTTLING
+ {
+ if ((PercentUsage + DDRAW_CPU_THROTTLING_THRESHOLD_MARGIN) > DDRAW_CPU_THROTTLING_THRESHOLD) {
+ unsigned long long NewTargetPercentUsage = TSK_CLAMP(DDRAW_CPU_THROTTLING_THRESHOLD_MARGIN, DDRAW_CPU_THROTTLING_THRESHOLD - DDRAW_CPU_THROTTLING_THRESHOLD_MARGIN, INT_MAX);
+ int NewTargetFps = (int)((NewTargetPercentUsage * p_ddraw->cpu.fps_target) / PercentUsage);
+ NewTargetFps = TSK_CLAMP(DDRAW_CPU_THROTTLING_FPS_MIN, NewTargetFps, TMEDIA_PRODUCER(p_ddraw)->video.fps);
+ TSK_DEBUG_INFO("\n\n****\n\nCPU throttling = (%lld+%d)>%d, NewTargetPercentUsage=%lld, NewTargetFps=%d\n\n***",
+ PercentUsage, DDRAW_CPU_THROTTLING_THRESHOLD_MARGIN, DDRAW_CPU_THROTTLING_THRESHOLD, NewTargetPercentUsage, NewTargetFps);
+ p_ddraw->cpu.fps_target = NewTargetFps;
+ }
+ else if (PercentUsage < DDRAW_CPU_THROTTLING_THRESHOLD) {
+ if ((p_ddraw->cpu.fps_target + DDRAW_CPU_THROTTLING_THRESHOLD_MARGIN) < TMEDIA_PRODUCER(p_ddraw)->video.fps) { // not honoring the negotiated fps yet?
+ p_ddraw->cpu.fps_target += 1; // TODO: this is ok only if the timer timeout is set to 1s or less
+ }
+ }
+ }
+#endif /* DDRAW_CPU_THROTTLING */
}
if (p_ddraw->b_started) {
- p_ddraw->id_timer_cpu = tsk_timer_manager_schedule(p_ddraw->p_timer_mgr, DDRAW_CPU_MONITOR_TIME_OUT, _tdav_producer_screencast_timer_cb, p_ddraw);
+ p_ddraw->cpu.id_timer = tsk_timer_manager_schedule(p_ddraw->p_timer_mgr, DDRAW_CPU_SCHEDULE_TIMEOUT, _tdav_producer_screencast_timer_cb, p_ddraw);
}
}
return 0;
}
-#endif /* DDRAW_CPU_MONITOR */
+#endif /* DDRAW_CPU_MONITOR || DDRAW_CPU_THROTTLING */
//
// ddraw screencast producer object definition
@@ -1424,11 +1489,11 @@ static tsk_object_t* _tdav_producer_screencast_ddraw_dtor(tsk_object_t * self)
/* deinit base */
tmedia_producer_deinit(TMEDIA_PRODUCER(p_ddraw));
/* deinit self */
-#if DDRAW_CPU_MONITOR
+#if DDRAW_CPU_MONITOR || DDRAW_CPU_THROTTLING
if (p_ddraw->p_timer_mgr) {
tsk_timer_manager_destroy(&p_ddraw->p_timer_mgr);
}
-#endif /* DDRAW_CPU_MONITOR */
+#endif /* DDRAW_CPU_MONITOR || DDRAW_CPU_THROTTLING */
#if DDRAW_MT
for (int i = 0; i < sizeof(p_ddraw->mt.p_buff_yuv_aligned_array) / sizeof(p_ddraw->mt.p_buff_yuv_aligned_array[0]); ++i) {
TSK_FREE_ALIGNED(p_ddraw->mt.p_buff_yuv_aligned_array[i]);
OpenPOWER on IntegriCloud