Use libvpx_fast code
Enable DDraw multi-threading
Adds support for CPU throttling (disabled by default)
This commit is contained in:
bossiel 2015-08-08 19:04:31 +00:00
parent 60b7f6d8f1
commit 3716e7f5d8
3 changed files with 217 additions and 148 deletions

View File

@ -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)
+-+-+-+-+-+-+-+-+
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 |
: :
+-+-+-+-+-+-+-+-+
*/
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?

View File

@ -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]);