Refactor VCM/Timing.

No changes in functionality.

R=marpan@google.com

Review URL: https://webrtc-codereview.appspot.com/1514004

git-svn-id: http://webrtc.googlecode.com/svn/trunk@4081 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
mikhal@webrtc.org 2013-05-21 17:58:43 +00:00
parent 3417eb49f6
commit 2eaf98b38b
2 changed files with 271 additions and 323 deletions

View File

@ -10,302 +10,251 @@
#include "webrtc/modules/video_coding/main/source/timing.h" #include "webrtc/modules/video_coding/main/source/timing.h"
#include "webrtc/modules/video_coding/main/source/internal_defines.h" #include "webrtc/modules/video_coding/main/source/internal_defines.h"
#include "webrtc/modules/video_coding/main/source/jitter_buffer_common.h" #include "webrtc/modules/video_coding/main/source/jitter_buffer_common.h"
#include "webrtc/modules/video_coding/main/source/timestamp_extrapolator.h" #include "webrtc/modules/video_coding/main/source/timestamp_extrapolator.h"
#include "webrtc/system_wrappers/interface/clock.h" #include "webrtc/system_wrappers/interface/clock.h"
#include "webrtc/system_wrappers/interface/trace.h" #include "webrtc/system_wrappers/interface/trace.h"
namespace webrtc { namespace webrtc {
VCMTiming::VCMTiming(Clock* clock, VCMTiming::VCMTiming(Clock* clock,
int32_t vcmId, int32_t vcm_id,
int32_t timingId, int32_t timing_id,
VCMTiming* masterTiming) VCMTiming* master_timing)
: : crit_sect_(CriticalSectionWrapper::CreateCriticalSection()),
_critSect(CriticalSectionWrapper::CreateCriticalSection()), vcm_id_(vcm_id),
_vcmId(vcmId), clock_(clock),
_clock(clock), timing_id_(timing_id),
_timingId(timingId), master_(false),
_master(false), ts_extrapolator_(),
_tsExtrapolator(), codec_timer_(),
_codecTimer(), render_delay_ms_(kDefaultRenderDelayMs),
_renderDelayMs(kDefaultRenderDelayMs), min_total_delay_ms_(0),
_minTotalDelayMs(0), required_delay_ms_(0),
_requiredDelayMs(0), current_delay_ms_(0),
_currentDelayMs(0), prev_frame_timestamp_(0) {
_prevFrameTimestamp(0) if (master_timing == NULL) {
{ master_ = true;
if (masterTiming == NULL) ts_extrapolator_ = new VCMTimestampExtrapolator(clock_, vcm_id, timing_id);
{ } else {
_master = true; ts_extrapolator_ = master_timing->ts_extrapolator_;
_tsExtrapolator = new VCMTimestampExtrapolator(_clock, vcmId, timingId); }
}
else
{
_tsExtrapolator = masterTiming->_tsExtrapolator;
}
} }
VCMTiming::~VCMTiming() VCMTiming::~VCMTiming() {
{ if (master_) {
if (_master) delete ts_extrapolator_;
{ }
delete _tsExtrapolator; delete crit_sect_;
}
delete _critSect;
} }
void void VCMTiming::Reset() {
VCMTiming::Reset() CriticalSectionScoped cs(crit_sect_);
{ ts_extrapolator_->Reset();
CriticalSectionScoped cs(_critSect); codec_timer_.Reset();
render_delay_ms_ = kDefaultRenderDelayMs;
_tsExtrapolator->Reset(); min_total_delay_ms_ = 0;
_codecTimer.Reset(); required_delay_ms_ = 0;
_renderDelayMs = kDefaultRenderDelayMs; current_delay_ms_ = 0;
_minTotalDelayMs = 0; prev_frame_timestamp_ = 0;
_requiredDelayMs = 0;
_currentDelayMs = 0;
_prevFrameTimestamp = 0;
} }
void VCMTiming::ResetDecodeTime() void VCMTiming::ResetDecodeTime() {
{ codec_timer_.Reset();
_codecTimer.Reset();
} }
void void VCMTiming::SetRenderDelay(uint32_t render_delay_ms) {
VCMTiming::SetRenderDelay(uint32_t renderDelayMs) CriticalSectionScoped cs(crit_sect_);
{ render_delay_ms_ = render_delay_ms;
CriticalSectionScoped cs(_critSect);
_renderDelayMs = renderDelayMs;
} }
void void VCMTiming::SetMinimumTotalDelay(uint32_t min_total_delay_ms) {
VCMTiming::SetMinimumTotalDelay(uint32_t minTotalDelayMs) CriticalSectionScoped cs(crit_sect_);
{ min_total_delay_ms_ = min_total_delay_ms;
CriticalSectionScoped cs(_critSect);
_minTotalDelayMs = minTotalDelayMs;
} }
void void VCMTiming::SetRequiredDelay(uint32_t required_delay_ms) {
VCMTiming::SetRequiredDelay(uint32_t requiredDelayMs) CriticalSectionScoped cs(crit_sect_);
{ if (required_delay_ms != required_delay_ms_) {
CriticalSectionScoped cs(_critSect); if (master_) {
if (requiredDelayMs != _requiredDelayMs) WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCoding,
{ VCMId(vcm_id_, timing_id_),
if (_master) "Desired jitter buffer level: %u ms", required_delay_ms);
{
WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCoding, VCMId(_vcmId, _timingId),
"Desired jitter buffer level: %u ms", requiredDelayMs);
}
_requiredDelayMs = requiredDelayMs;
// When in initial state, set current delay to minimum delay.
if (_currentDelayMs == 0) {
_currentDelayMs = _requiredDelayMs;
}
} }
required_delay_ms_ = required_delay_ms;
// When in initial state, set current delay to minimum delay.
if (current_delay_ms_ == 0) {
current_delay_ms_ = required_delay_ms_;
}
}
} }
void VCMTiming::UpdateCurrentDelay(uint32_t frameTimestamp) void VCMTiming::UpdateCurrentDelay(uint32_t frame_timestamp) {
{ CriticalSectionScoped cs(crit_sect_);
CriticalSectionScoped cs(_critSect); uint32_t target_delay_ms = TargetDelayInternal();
uint32_t targetDelayMs = TargetDelayInternal();
if (_currentDelayMs == 0) if (current_delay_ms_ == 0) {
{ // Not initialized, set current delay to target.
// Not initialized, set current delay to target. current_delay_ms_ = target_delay_ms;
_currentDelayMs = targetDelayMs; } else if (target_delay_ms != current_delay_ms_) {
int64_t delay_diff_ms = static_cast<int64_t>(target_delay_ms) -
current_delay_ms_;
// Never change the delay with more than 100 ms every second. If we're
// changing the delay in too large steps we will get noticeable freezes. By
// limiting the change we can increase the delay in smaller steps, which
// will be experienced as the video is played in slow motion. When lowering
// the delay the video will be played at a faster pace.
int64_t max_change_ms = 0;
if (frame_timestamp < 0x0000ffff && prev_frame_timestamp_ > 0xffff0000) {
// wrap
max_change_ms = kDelayMaxChangeMsPerS * (frame_timestamp +
(static_cast<int64_t>(1) << 32) - prev_frame_timestamp_) / 90000;
} else {
max_change_ms = kDelayMaxChangeMsPerS *
(frame_timestamp - prev_frame_timestamp_) / 90000;
} }
else if (targetDelayMs != _currentDelayMs) if (max_change_ms <= 0) {
{ // Any changes less than 1 ms are truncated and
int64_t delayDiffMs = static_cast<int64_t>(targetDelayMs) - // will be postponed. Negative change will be due
_currentDelayMs; // to reordering and should be ignored.
// Never change the delay with more than 100 ms every second. If we're changing the return;
// delay in too large steps we will get noticeable freezes. By limiting the change we }
// can increase the delay in smaller steps, which will be experienced as the video is delay_diff_ms = std::max(delay_diff_ms, -max_change_ms);
// played in slow motion. When lowering the delay the video will be played at a faster delay_diff_ms = std::min(delay_diff_ms, max_change_ms);
// pace.
int64_t maxChangeMs = 0;
if (frameTimestamp < 0x0000ffff && _prevFrameTimestamp > 0xffff0000)
{
// wrap
maxChangeMs = kDelayMaxChangeMsPerS * (frameTimestamp +
(static_cast<int64_t>(1)<<32) - _prevFrameTimestamp) / 90000;
}
else
{
maxChangeMs = kDelayMaxChangeMsPerS *
(frameTimestamp - _prevFrameTimestamp) / 90000;
}
if (maxChangeMs <= 0)
{
// Any changes less than 1 ms are truncated and
// will be postponed. Negative change will be due
// to reordering and should be ignored.
return;
}
delayDiffMs = std::max(delayDiffMs, -maxChangeMs);
delayDiffMs = std::min(delayDiffMs, maxChangeMs);
_currentDelayMs = _currentDelayMs + static_cast<int32_t>(delayDiffMs); current_delay_ms_ = current_delay_ms_ + static_cast<int32_t>(delay_diff_ms);
} }
_prevFrameTimestamp = frameTimestamp; prev_frame_timestamp_ = frame_timestamp;
} }
void VCMTiming::UpdateCurrentDelay(int64_t renderTimeMs, void VCMTiming::UpdateCurrentDelay(int64_t render_time_ms,
int64_t actualDecodeTimeMs) int64_t actual_decode_time_ms) {
{ CriticalSectionScoped cs(crit_sect_);
CriticalSectionScoped cs(_critSect); uint32_t target_delay_ms = TargetDelayInternal();
uint32_t targetDelayMs = TargetDelayInternal(); int64_t delayed_ms = actual_decode_time_ms -
(render_time_ms - MaxDecodeTimeMs() - render_delay_ms_);
int64_t delayedMs = actualDecodeTimeMs - if (delayed_ms < 0) {
(renderTimeMs - MaxDecodeTimeMs() - _renderDelayMs); return;
if (delayedMs < 0) }
{ if (current_delay_ms_ + delayed_ms <= target_delay_ms) {
return; current_delay_ms_ += static_cast<uint32_t>(delayed_ms);
} } else {
if (_currentDelayMs + delayedMs <= targetDelayMs) current_delay_ms_ = target_delay_ms;
{ }
_currentDelayMs += static_cast<uint32_t>(delayedMs);
}
else
{
_currentDelayMs = targetDelayMs;
}
} }
int32_t int32_t VCMTiming::StopDecodeTimer(uint32_t time_stamp,
VCMTiming::StopDecodeTimer(uint32_t timeStamp, int64_t start_time_ms,
int64_t startTimeMs, int64_t now_ms) {
int64_t nowMs) CriticalSectionScoped cs(crit_sect_);
{ const int32_t max_dec_time = MaxDecodeTimeMs();
CriticalSectionScoped cs(_critSect); int32_t time_diff_ms = codec_timer_.StopTimer(start_time_ms, now_ms);
const int32_t maxDecTime = MaxDecodeTimeMs(); if (time_diff_ms < 0) {
int32_t timeDiffMs = _codecTimer.StopTimer(startTimeMs, nowMs); WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCoding, VCMId(vcm_id_,
if (timeDiffMs < 0) timing_id_), "Codec timer error: %d", time_diff_ms);
{ assert(false);
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCoding, VCMId(_vcmId, _timingId), }
"Codec timer error: %d", timeDiffMs);
assert(false);
}
if (_master) if (master_) {
{ WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCoding, VCMId(vcm_id_,
WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCoding, VCMId(_vcmId, _timingId), timing_id_),
"Frame decoded: timeStamp=%u decTime=%d maxDecTime=%u, at %u", "Frame decoded: time_stamp=%u dec_time=%d max_dec_time=%u, at %u",
timeStamp, timeDiffMs, maxDecTime, MaskWord64ToUWord32(nowMs)); time_stamp, time_diff_ms, max_dec_time, MaskWord64ToUWord32(now_ms));
} }
return 0; return 0;
} }
void void VCMTiming::IncomingTimestamp(uint32_t time_stamp, int64_t now_ms) {
VCMTiming::IncomingTimestamp(uint32_t timeStamp, int64_t nowMs) CriticalSectionScoped cs(crit_sect_);
{ ts_extrapolator_->Update(now_ms, time_stamp, master_);
CriticalSectionScoped cs(_critSect);
_tsExtrapolator->Update(nowMs, timeStamp, _master);
} }
int64_t int64_t VCMTiming::RenderTimeMs(uint32_t frame_timestamp, int64_t now_ms)
VCMTiming::RenderTimeMs(uint32_t frameTimestamp, int64_t nowMs) const const {
{ CriticalSectionScoped cs(crit_sect_);
CriticalSectionScoped cs(_critSect); const int64_t render_time_ms = RenderTimeMsInternal(frame_timestamp, now_ms);
const int64_t renderTimeMs = RenderTimeMsInternal(frameTimestamp, nowMs); if (master_) {
if (_master) WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCoding, VCMId(vcm_id_,
{ timing_id_), "Render frame %u at %u. Render delay %u",
WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCoding, VCMId(_vcmId, _timingId), "required delay %u, max decode time %u, min total delay %u",
"Render frame %u at %u. Render delay %u, required delay %u," frame_timestamp, MaskWord64ToUWord32(render_time_ms), render_delay_ms_,
" max decode time %u, min total delay %u", required_delay_ms_, MaxDecodeTimeMs(), min_total_delay_ms_);
frameTimestamp, MaskWord64ToUWord32(renderTimeMs), _renderDelayMs, }
_requiredDelayMs, MaxDecodeTimeMs(),_minTotalDelayMs); return render_time_ms;
}
return renderTimeMs;
} }
int64_t int64_t VCMTiming::RenderTimeMsInternal(uint32_t frame_timestamp,
VCMTiming::RenderTimeMsInternal(uint32_t frameTimestamp, int64_t nowMs) const int64_t now_ms) const {
{ int64_t estimated_complete_time_ms =
int64_t estimatedCompleteTimeMs = ts_extrapolator_->ExtrapolateLocalTime(frame_timestamp);
_tsExtrapolator->ExtrapolateLocalTime(frameTimestamp); if (master_) {
if (_master) WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCoding,
{ VCMId(vcm_id_, timing_id_), "ExtrapolateLocalTime(%u)=%u ms",
WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCoding, VCMId(_vcmId, _timingId), frame_timestamp, MaskWord64ToUWord32(estimated_complete_time_ms));
"ExtrapolateLocalTime(%u)=%u ms", }
frameTimestamp, MaskWord64ToUWord32(estimatedCompleteTimeMs)); if (estimated_complete_time_ms == -1) {
} estimated_complete_time_ms = now_ms;
if (estimatedCompleteTimeMs == -1) }
{
estimatedCompleteTimeMs = nowMs;
}
// Make sure that we have at least the total minimum delay. // Make sure that we have at least the total minimum delay.
uint32_t actual_delay = std::max(_currentDelayMs, _minTotalDelayMs); uint32_t actual_delay = std::max(current_delay_ms_, min_total_delay_ms_);
return estimatedCompleteTimeMs + actual_delay; return estimated_complete_time_ms + actual_delay;
} }
// Must be called from inside a critical section // Must be called from inside a critical section.
int32_t int32_t VCMTiming::MaxDecodeTimeMs(FrameType frame_type /*= kVideoFrameDelta*/)
VCMTiming::MaxDecodeTimeMs(FrameType frameType /*= kVideoFrameDelta*/) const const {
{ const int32_t decode_time_ms = codec_timer_.RequiredDecodeTimeMs(frame_type);
const int32_t decodeTimeMs = _codecTimer.RequiredDecodeTimeMs(frameType); if (decode_time_ms < 0) {
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCoding, VCMId(vcm_id_,
if (decodeTimeMs < 0) timing_id_), "Negative maximum decode time: %d", decode_time_ms);
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCoding, VCMId(_vcmId, _timingId),
"Negative maximum decode time: %d", decodeTimeMs);
return -1; return -1;
} }
return decodeTimeMs; return decode_time_ms;
} }
uint32_t uint32_t VCMTiming::MaxWaitingTime(int64_t render_time_ms, int64_t now_ms)
VCMTiming::MaxWaitingTime(int64_t renderTimeMs, int64_t nowMs) const const {
{ CriticalSectionScoped cs(crit_sect_);
CriticalSectionScoped cs(_critSect);
const int64_t maxWaitTimeMs = renderTimeMs - nowMs - const int64_t max_wait_time_ms = render_time_ms - now_ms -
MaxDecodeTimeMs() - _renderDelayMs; MaxDecodeTimeMs() - render_delay_ms_;
if (maxWaitTimeMs < 0) if (max_wait_time_ms < 0) {
{ return 0;
return 0; }
} return static_cast<uint32_t>(max_wait_time_ms);
return static_cast<uint32_t>(maxWaitTimeMs);
} }
bool bool VCMTiming::EnoughTimeToDecode(uint32_t available_processing_time_ms)
VCMTiming::EnoughTimeToDecode(uint32_t availableProcessingTimeMs) const const {
{ CriticalSectionScoped cs(crit_sect_);
CriticalSectionScoped cs(_critSect); int32_t max_decode_time_ms = MaxDecodeTimeMs();
int32_t maxDecodeTimeMs = MaxDecodeTimeMs(); if (max_decode_time_ms < 0) {
if (maxDecodeTimeMs < 0) // Haven't decoded any frames yet, try decoding one to get an estimate
{ // of the decode time.
// Haven't decoded any frames yet, try decoding one to get an estimate return true;
// of the decode time. } else if (max_decode_time_ms == 0) {
return true; // Decode time is less than 1, set to 1 for now since
} // we don't have any better precision. Count ticks later?
else if (maxDecodeTimeMs == 0) max_decode_time_ms = 1;
{ }
// Decode time is less than 1, set to 1 for now since return static_cast<int32_t>(available_processing_time_ms) -
// we don't have any better precision. Count ticks later? max_decode_time_ms > 0;
maxDecodeTimeMs = 1;
}
return static_cast<int32_t>(availableProcessingTimeMs) - maxDecodeTimeMs > 0;
} }
uint32_t uint32_t VCMTiming::TargetVideoDelay() const {
VCMTiming::TargetVideoDelay() const CriticalSectionScoped cs(crit_sect_);
{ return TargetDelayInternal();
CriticalSectionScoped cs(_critSect);
return TargetDelayInternal();
} }
uint32_t uint32_t VCMTiming::TargetDelayInternal() const {
VCMTiming::TargetDelayInternal() const return std::max(min_total_delay_ms_,
{ required_delay_ms_ + MaxDecodeTimeMs() + render_delay_ms_);
return std::max(_minTotalDelayMs,
_requiredDelayMs + MaxDecodeTimeMs() + _renderDelayMs);
} }
} } // namespace webrtc

View File

@ -8,103 +8,102 @@
* be found in the AUTHORS file in the root of the source tree. * be found in the AUTHORS file in the root of the source tree.
*/ */
#ifndef WEBRTC_MODULES_VIDEO_CODING_TIMING_H_ #ifndef WEBRTC_MODULES_VIDEO_CODING_MAIN_SOURCE_TIMING_H_
#define WEBRTC_MODULES_VIDEO_CODING_TIMING_H_ #define WEBRTC_MODULES_VIDEO_CODING_MAIN_SOURCE_TIMING_H_
#include "typedefs.h" #include "webrtc/modules/video_coding/main/source/codec_timer.h"
#include "critical_section_wrapper.h" #include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
#include "codec_timer.h" #include "webrtc/typedefs.h"
namespace webrtc namespace webrtc {
{
class Clock; class Clock;
class VCMTimestampExtrapolator; class VCMTimestampExtrapolator;
class VCMTiming class VCMTiming {
{ public:
public: // The primary timing component should be passed
// The primary timing component should be passed // if this is the dual timing component.
// if this is the dual timing component. VCMTiming(Clock* clock,
VCMTiming(Clock* clock, int32_t vcm_id = 0,
int32_t vcmId = 0, int32_t timing_id = 0,
int32_t timingId = 0, VCMTiming* master_timing = NULL);
VCMTiming* masterTiming = NULL); ~VCMTiming();
~VCMTiming();
// Resets the timing to the initial state. // Resets the timing to the initial state.
void Reset(); void Reset();
void ResetDecodeTime(); void ResetDecodeTime();
// The amount of time needed to render an image. Defaults to 10 ms. // The amount of time needed to render an image. Defaults to 10 ms.
void SetRenderDelay(uint32_t renderDelayMs); void SetRenderDelay(uint32_t render_delay_ms);
// The minimum time the video must be delayed on the receiver to // The minimum time the video must be delayed on the receiver to
// get the desired jitter buffer level. // get the desired jitter buffer level.
void SetRequiredDelay(uint32_t requiredDelayMs); void SetRequiredDelay(uint32_t required_delay_ms);
// Minimum total delay required to sync video with audio. // Minimum total delay required to sync video with audio.
void SetMinimumTotalDelay(uint32_t minTotalDelayMs); void SetMinimumTotalDelay(uint32_t min_total_delay_ms);
// Increases or decreases the current delay to get closer to the target delay. // Increases or decreases the current delay to get closer to the target delay.
// Calculates how long it has been since the previous call to this function, // Calculates how long it has been since the previous call to this function,
// and increases/decreases the delay in proportion to the time difference. // and increases/decreases the delay in proportion to the time difference.
void UpdateCurrentDelay(uint32_t frameTimestamp); void UpdateCurrentDelay(uint32_t frame_timestamp);
// Increases or decreases the current delay to get closer to the target delay. // Increases or decreases the current delay to get closer to the target delay.
// Given the actual decode time in ms and the render time in ms for a frame, this // Given the actual decode time in ms and the render time in ms for a frame,
// function calculates how late the frame is and increases the delay accordingly. // this function calculates how late the frame is and increases the delay
void UpdateCurrentDelay(int64_t renderTimeMs, int64_t actualDecodeTimeMs); // accordingly.
void UpdateCurrentDelay(int64_t render_time_ms,
int64_t actual_decode_time_ms);
// Stops the decoder timer, should be called when the decoder returns a frame // Stops the decoder timer, should be called when the decoder returns a frame
// or when the decoded frame callback is called. // or when the decoded frame callback is called.
int32_t StopDecodeTimer(uint32_t timeStamp, int32_t StopDecodeTimer(uint32_t time_stamp,
int64_t startTimeMs, int64_t start_time_ms,
int64_t nowMs); int64_t now_ms);
// Used to report that a frame is passed to decoding. Updates the timestamp // Used to report that a frame is passed to decoding. Updates the timestamp
// filter which is used to map between timestamps and receiver system time. // filter which is used to map between timestamps and receiver system time.
void IncomingTimestamp(uint32_t timeStamp, int64_t lastPacketTimeMs); void IncomingTimestamp(uint32_t time_stamp, int64_t last_packet_time_ms);
// Returns the receiver system time when the frame with timestamp
// frame_timestamp should be rendered, assuming that the system time currently
// is now_ms.
int64_t RenderTimeMs(uint32_t frame_timestamp, int64_t now_ms) const;
// Returns the receiver system time when the frame with timestamp frameTimestamp // Returns the maximum time in ms that we can wait for a frame to become
// should be rendered, assuming that the system time currently is nowMs. // complete before we must pass it to the decoder.
int64_t RenderTimeMs(uint32_t frameTimestamp, int64_t nowMs) const; uint32_t MaxWaitingTime(int64_t render_time_ms, int64_t now_ms) const;
// Returns the maximum time in ms that we can wait for a frame to become complete // Returns the current target delay which is required delay + decode time +
// before we must pass it to the decoder. // render delay.
uint32_t MaxWaitingTime(int64_t renderTimeMs, int64_t nowMs) const; uint32_t TargetVideoDelay() const;
// Returns the current target delay which is required delay + decode time + render // Calculates whether or not there is enough time to decode a frame given a
// delay. // certain amount of processing time.
uint32_t TargetVideoDelay() const; bool EnoughTimeToDecode(uint32_t available_processing_time_ms) const;
// Calculates whether or not there is enough time to decode a frame given a enum { kDefaultRenderDelayMs = 10 };
// certain amount of processing time. enum { kDelayMaxChangeMsPerS = 100 };
bool EnoughTimeToDecode(uint32_t availableProcessingTimeMs) const;
enum { kDefaultRenderDelayMs = 10 }; protected:
enum { kDelayMaxChangeMsPerS = 100 }; int32_t MaxDecodeTimeMs(FrameType frame_type = kVideoFrameDelta) const;
int64_t RenderTimeMsInternal(uint32_t frame_timestamp, int64_t now_ms) const;
uint32_t TargetDelayInternal() const;
protected: private:
int32_t MaxDecodeTimeMs(FrameType frameType = kVideoFrameDelta) const; CriticalSectionWrapper* crit_sect_;
int64_t RenderTimeMsInternal(uint32_t frameTimestamp, int64_t nowMs) const; int32_t vcm_id_;
uint32_t TargetDelayInternal() const; Clock* clock_;
int32_t timing_id_;
private: bool master_;
CriticalSectionWrapper* _critSect; VCMTimestampExtrapolator* ts_extrapolator_;
int32_t _vcmId; VCMCodecTimer codec_timer_;
Clock* _clock; uint32_t render_delay_ms_;
int32_t _timingId; uint32_t min_total_delay_ms_;
bool _master; uint32_t required_delay_ms_;
VCMTimestampExtrapolator* _tsExtrapolator; uint32_t current_delay_ms_;
VCMCodecTimer _codecTimer; uint32_t prev_frame_timestamp_;
uint32_t _renderDelayMs;
uint32_t _minTotalDelayMs;
uint32_t _requiredDelayMs;
uint32_t _currentDelayMs;
uint32_t _prevFrameTimestamp;
}; };
} // namespace webrtc
} // namespace webrtc #endif // WEBRTC_MODULES_VIDEO_CODING_MAIN_SOURCE_TIMING_H_
#endif // WEBRTC_MODULES_VIDEO_CODING_TIMING_H_