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:
parent
3417eb49f6
commit
2eaf98b38b
@ -10,302 +10,251 @@
|
||||
|
||||
#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/jitter_buffer_common.h"
|
||||
#include "webrtc/modules/video_coding/main/source/timestamp_extrapolator.h"
|
||||
#include "webrtc/system_wrappers/interface/clock.h"
|
||||
#include "webrtc/system_wrappers/interface/trace.h"
|
||||
|
||||
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
VCMTiming::VCMTiming(Clock* clock,
|
||||
int32_t vcmId,
|
||||
int32_t timingId,
|
||||
VCMTiming* masterTiming)
|
||||
:
|
||||
_critSect(CriticalSectionWrapper::CreateCriticalSection()),
|
||||
_vcmId(vcmId),
|
||||
_clock(clock),
|
||||
_timingId(timingId),
|
||||
_master(false),
|
||||
_tsExtrapolator(),
|
||||
_codecTimer(),
|
||||
_renderDelayMs(kDefaultRenderDelayMs),
|
||||
_minTotalDelayMs(0),
|
||||
_requiredDelayMs(0),
|
||||
_currentDelayMs(0),
|
||||
_prevFrameTimestamp(0)
|
||||
{
|
||||
if (masterTiming == NULL)
|
||||
{
|
||||
_master = true;
|
||||
_tsExtrapolator = new VCMTimestampExtrapolator(_clock, vcmId, timingId);
|
||||
}
|
||||
else
|
||||
{
|
||||
_tsExtrapolator = masterTiming->_tsExtrapolator;
|
||||
}
|
||||
int32_t vcm_id,
|
||||
int32_t timing_id,
|
||||
VCMTiming* master_timing)
|
||||
: crit_sect_(CriticalSectionWrapper::CreateCriticalSection()),
|
||||
vcm_id_(vcm_id),
|
||||
clock_(clock),
|
||||
timing_id_(timing_id),
|
||||
master_(false),
|
||||
ts_extrapolator_(),
|
||||
codec_timer_(),
|
||||
render_delay_ms_(kDefaultRenderDelayMs),
|
||||
min_total_delay_ms_(0),
|
||||
required_delay_ms_(0),
|
||||
current_delay_ms_(0),
|
||||
prev_frame_timestamp_(0) {
|
||||
if (master_timing == NULL) {
|
||||
master_ = true;
|
||||
ts_extrapolator_ = new VCMTimestampExtrapolator(clock_, vcm_id, timing_id);
|
||||
} else {
|
||||
ts_extrapolator_ = master_timing->ts_extrapolator_;
|
||||
}
|
||||
}
|
||||
|
||||
VCMTiming::~VCMTiming()
|
||||
{
|
||||
if (_master)
|
||||
{
|
||||
delete _tsExtrapolator;
|
||||
}
|
||||
delete _critSect;
|
||||
VCMTiming::~VCMTiming() {
|
||||
if (master_) {
|
||||
delete ts_extrapolator_;
|
||||
}
|
||||
delete crit_sect_;
|
||||
}
|
||||
|
||||
void
|
||||
VCMTiming::Reset()
|
||||
{
|
||||
CriticalSectionScoped cs(_critSect);
|
||||
|
||||
_tsExtrapolator->Reset();
|
||||
_codecTimer.Reset();
|
||||
_renderDelayMs = kDefaultRenderDelayMs;
|
||||
_minTotalDelayMs = 0;
|
||||
_requiredDelayMs = 0;
|
||||
_currentDelayMs = 0;
|
||||
_prevFrameTimestamp = 0;
|
||||
void VCMTiming::Reset() {
|
||||
CriticalSectionScoped cs(crit_sect_);
|
||||
ts_extrapolator_->Reset();
|
||||
codec_timer_.Reset();
|
||||
render_delay_ms_ = kDefaultRenderDelayMs;
|
||||
min_total_delay_ms_ = 0;
|
||||
required_delay_ms_ = 0;
|
||||
current_delay_ms_ = 0;
|
||||
prev_frame_timestamp_ = 0;
|
||||
}
|
||||
|
||||
void VCMTiming::ResetDecodeTime()
|
||||
{
|
||||
_codecTimer.Reset();
|
||||
void VCMTiming::ResetDecodeTime() {
|
||||
codec_timer_.Reset();
|
||||
}
|
||||
|
||||
void
|
||||
VCMTiming::SetRenderDelay(uint32_t renderDelayMs)
|
||||
{
|
||||
CriticalSectionScoped cs(_critSect);
|
||||
_renderDelayMs = renderDelayMs;
|
||||
void VCMTiming::SetRenderDelay(uint32_t render_delay_ms) {
|
||||
CriticalSectionScoped cs(crit_sect_);
|
||||
render_delay_ms_ = render_delay_ms;
|
||||
}
|
||||
|
||||
void
|
||||
VCMTiming::SetMinimumTotalDelay(uint32_t minTotalDelayMs)
|
||||
{
|
||||
CriticalSectionScoped cs(_critSect);
|
||||
_minTotalDelayMs = minTotalDelayMs;
|
||||
void VCMTiming::SetMinimumTotalDelay(uint32_t min_total_delay_ms) {
|
||||
CriticalSectionScoped cs(crit_sect_);
|
||||
min_total_delay_ms_ = min_total_delay_ms;
|
||||
}
|
||||
|
||||
void
|
||||
VCMTiming::SetRequiredDelay(uint32_t requiredDelayMs)
|
||||
{
|
||||
CriticalSectionScoped cs(_critSect);
|
||||
if (requiredDelayMs != _requiredDelayMs)
|
||||
{
|
||||
if (_master)
|
||||
{
|
||||
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;
|
||||
}
|
||||
void VCMTiming::SetRequiredDelay(uint32_t required_delay_ms) {
|
||||
CriticalSectionScoped cs(crit_sect_);
|
||||
if (required_delay_ms != required_delay_ms_) {
|
||||
if (master_) {
|
||||
WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCoding,
|
||||
VCMId(vcm_id_, timing_id_),
|
||||
"Desired jitter buffer level: %u ms", required_delay_ms);
|
||||
}
|
||||
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)
|
||||
{
|
||||
CriticalSectionScoped cs(_critSect);
|
||||
uint32_t targetDelayMs = TargetDelayInternal();
|
||||
void VCMTiming::UpdateCurrentDelay(uint32_t frame_timestamp) {
|
||||
CriticalSectionScoped cs(crit_sect_);
|
||||
uint32_t target_delay_ms = TargetDelayInternal();
|
||||
|
||||
if (_currentDelayMs == 0)
|
||||
{
|
||||
// Not initialized, set current delay to target.
|
||||
_currentDelayMs = targetDelayMs;
|
||||
if (current_delay_ms_ == 0) {
|
||||
// Not initialized, set current delay to target.
|
||||
current_delay_ms_ = target_delay_ms;
|
||||
} 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)
|
||||
{
|
||||
int64_t delayDiffMs = static_cast<int64_t>(targetDelayMs) -
|
||||
_currentDelayMs;
|
||||
// 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 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);
|
||||
if (max_change_ms <= 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;
|
||||
}
|
||||
delay_diff_ms = std::max(delay_diff_ms, -max_change_ms);
|
||||
delay_diff_ms = std::min(delay_diff_ms, max_change_ms);
|
||||
|
||||
_currentDelayMs = _currentDelayMs + static_cast<int32_t>(delayDiffMs);
|
||||
}
|
||||
_prevFrameTimestamp = frameTimestamp;
|
||||
current_delay_ms_ = current_delay_ms_ + static_cast<int32_t>(delay_diff_ms);
|
||||
}
|
||||
prev_frame_timestamp_ = frame_timestamp;
|
||||
}
|
||||
|
||||
void VCMTiming::UpdateCurrentDelay(int64_t renderTimeMs,
|
||||
int64_t actualDecodeTimeMs)
|
||||
{
|
||||
CriticalSectionScoped cs(_critSect);
|
||||
uint32_t targetDelayMs = TargetDelayInternal();
|
||||
|
||||
int64_t delayedMs = actualDecodeTimeMs -
|
||||
(renderTimeMs - MaxDecodeTimeMs() - _renderDelayMs);
|
||||
if (delayedMs < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (_currentDelayMs + delayedMs <= targetDelayMs)
|
||||
{
|
||||
_currentDelayMs += static_cast<uint32_t>(delayedMs);
|
||||
}
|
||||
else
|
||||
{
|
||||
_currentDelayMs = targetDelayMs;
|
||||
}
|
||||
void VCMTiming::UpdateCurrentDelay(int64_t render_time_ms,
|
||||
int64_t actual_decode_time_ms) {
|
||||
CriticalSectionScoped cs(crit_sect_);
|
||||
uint32_t target_delay_ms = TargetDelayInternal();
|
||||
int64_t delayed_ms = actual_decode_time_ms -
|
||||
(render_time_ms - MaxDecodeTimeMs() - render_delay_ms_);
|
||||
if (delayed_ms < 0) {
|
||||
return;
|
||||
}
|
||||
if (current_delay_ms_ + delayed_ms <= target_delay_ms) {
|
||||
current_delay_ms_ += static_cast<uint32_t>(delayed_ms);
|
||||
} else {
|
||||
current_delay_ms_ = target_delay_ms;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t
|
||||
VCMTiming::StopDecodeTimer(uint32_t timeStamp,
|
||||
int64_t startTimeMs,
|
||||
int64_t nowMs)
|
||||
{
|
||||
CriticalSectionScoped cs(_critSect);
|
||||
const int32_t maxDecTime = MaxDecodeTimeMs();
|
||||
int32_t timeDiffMs = _codecTimer.StopTimer(startTimeMs, nowMs);
|
||||
if (timeDiffMs < 0)
|
||||
{
|
||||
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCoding, VCMId(_vcmId, _timingId),
|
||||
"Codec timer error: %d", timeDiffMs);
|
||||
assert(false);
|
||||
}
|
||||
int32_t VCMTiming::StopDecodeTimer(uint32_t time_stamp,
|
||||
int64_t start_time_ms,
|
||||
int64_t now_ms) {
|
||||
CriticalSectionScoped cs(crit_sect_);
|
||||
const int32_t max_dec_time = MaxDecodeTimeMs();
|
||||
int32_t time_diff_ms = codec_timer_.StopTimer(start_time_ms, now_ms);
|
||||
if (time_diff_ms < 0) {
|
||||
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCoding, VCMId(vcm_id_,
|
||||
timing_id_), "Codec timer error: %d", time_diff_ms);
|
||||
assert(false);
|
||||
}
|
||||
|
||||
if (_master)
|
||||
{
|
||||
WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCoding, VCMId(_vcmId, _timingId),
|
||||
"Frame decoded: timeStamp=%u decTime=%d maxDecTime=%u, at %u",
|
||||
timeStamp, timeDiffMs, maxDecTime, MaskWord64ToUWord32(nowMs));
|
||||
}
|
||||
return 0;
|
||||
if (master_) {
|
||||
WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCoding, VCMId(vcm_id_,
|
||||
timing_id_),
|
||||
"Frame decoded: time_stamp=%u dec_time=%d max_dec_time=%u, at %u",
|
||||
time_stamp, time_diff_ms, max_dec_time, MaskWord64ToUWord32(now_ms));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
VCMTiming::IncomingTimestamp(uint32_t timeStamp, int64_t nowMs)
|
||||
{
|
||||
CriticalSectionScoped cs(_critSect);
|
||||
_tsExtrapolator->Update(nowMs, timeStamp, _master);
|
||||
void VCMTiming::IncomingTimestamp(uint32_t time_stamp, int64_t now_ms) {
|
||||
CriticalSectionScoped cs(crit_sect_);
|
||||
ts_extrapolator_->Update(now_ms, time_stamp, master_);
|
||||
}
|
||||
|
||||
int64_t
|
||||
VCMTiming::RenderTimeMs(uint32_t frameTimestamp, int64_t nowMs) const
|
||||
{
|
||||
CriticalSectionScoped cs(_critSect);
|
||||
const int64_t renderTimeMs = RenderTimeMsInternal(frameTimestamp, nowMs);
|
||||
if (_master)
|
||||
{
|
||||
WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCoding, VCMId(_vcmId, _timingId),
|
||||
"Render frame %u at %u. Render delay %u, required delay %u,"
|
||||
" max decode time %u, min total delay %u",
|
||||
frameTimestamp, MaskWord64ToUWord32(renderTimeMs), _renderDelayMs,
|
||||
_requiredDelayMs, MaxDecodeTimeMs(),_minTotalDelayMs);
|
||||
}
|
||||
return renderTimeMs;
|
||||
int64_t VCMTiming::RenderTimeMs(uint32_t frame_timestamp, int64_t now_ms)
|
||||
const {
|
||||
CriticalSectionScoped cs(crit_sect_);
|
||||
const int64_t render_time_ms = RenderTimeMsInternal(frame_timestamp, now_ms);
|
||||
if (master_) {
|
||||
WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCoding, VCMId(vcm_id_,
|
||||
timing_id_), "Render frame %u at %u. Render delay %u",
|
||||
"required delay %u, max decode time %u, min total delay %u",
|
||||
frame_timestamp, MaskWord64ToUWord32(render_time_ms), render_delay_ms_,
|
||||
required_delay_ms_, MaxDecodeTimeMs(), min_total_delay_ms_);
|
||||
}
|
||||
return render_time_ms;
|
||||
}
|
||||
|
||||
int64_t
|
||||
VCMTiming::RenderTimeMsInternal(uint32_t frameTimestamp, int64_t nowMs) const
|
||||
{
|
||||
int64_t estimatedCompleteTimeMs =
|
||||
_tsExtrapolator->ExtrapolateLocalTime(frameTimestamp);
|
||||
if (_master)
|
||||
{
|
||||
WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCoding, VCMId(_vcmId, _timingId),
|
||||
"ExtrapolateLocalTime(%u)=%u ms",
|
||||
frameTimestamp, MaskWord64ToUWord32(estimatedCompleteTimeMs));
|
||||
}
|
||||
if (estimatedCompleteTimeMs == -1)
|
||||
{
|
||||
estimatedCompleteTimeMs = nowMs;
|
||||
}
|
||||
int64_t VCMTiming::RenderTimeMsInternal(uint32_t frame_timestamp,
|
||||
int64_t now_ms) const {
|
||||
int64_t estimated_complete_time_ms =
|
||||
ts_extrapolator_->ExtrapolateLocalTime(frame_timestamp);
|
||||
if (master_) {
|
||||
WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCoding,
|
||||
VCMId(vcm_id_, timing_id_), "ExtrapolateLocalTime(%u)=%u ms",
|
||||
frame_timestamp, MaskWord64ToUWord32(estimated_complete_time_ms));
|
||||
}
|
||||
if (estimated_complete_time_ms == -1) {
|
||||
estimated_complete_time_ms = now_ms;
|
||||
}
|
||||
|
||||
// Make sure that we have at least the total minimum delay.
|
||||
uint32_t actual_delay = std::max(_currentDelayMs, _minTotalDelayMs);
|
||||
return estimatedCompleteTimeMs + actual_delay;
|
||||
// Make sure that we have at least the total minimum delay.
|
||||
uint32_t actual_delay = std::max(current_delay_ms_, min_total_delay_ms_);
|
||||
return estimated_complete_time_ms + actual_delay;
|
||||
}
|
||||
|
||||
// Must be called from inside a critical section
|
||||
int32_t
|
||||
VCMTiming::MaxDecodeTimeMs(FrameType frameType /*= kVideoFrameDelta*/) const
|
||||
{
|
||||
const int32_t decodeTimeMs = _codecTimer.RequiredDecodeTimeMs(frameType);
|
||||
|
||||
if (decodeTimeMs < 0)
|
||||
{
|
||||
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCoding, VCMId(_vcmId, _timingId),
|
||||
"Negative maximum decode time: %d", decodeTimeMs);
|
||||
// Must be called from inside a critical section.
|
||||
int32_t VCMTiming::MaxDecodeTimeMs(FrameType frame_type /*= kVideoFrameDelta*/)
|
||||
const {
|
||||
const int32_t decode_time_ms = codec_timer_.RequiredDecodeTimeMs(frame_type);
|
||||
if (decode_time_ms < 0) {
|
||||
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCoding, VCMId(vcm_id_,
|
||||
timing_id_), "Negative maximum decode time: %d", decode_time_ms);
|
||||
return -1;
|
||||
}
|
||||
return decodeTimeMs;
|
||||
}
|
||||
return decode_time_ms;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
VCMTiming::MaxWaitingTime(int64_t renderTimeMs, int64_t nowMs) const
|
||||
{
|
||||
CriticalSectionScoped cs(_critSect);
|
||||
uint32_t VCMTiming::MaxWaitingTime(int64_t render_time_ms, int64_t now_ms)
|
||||
const {
|
||||
CriticalSectionScoped cs(crit_sect_);
|
||||
|
||||
const int64_t maxWaitTimeMs = renderTimeMs - nowMs -
|
||||
MaxDecodeTimeMs() - _renderDelayMs;
|
||||
const int64_t max_wait_time_ms = render_time_ms - now_ms -
|
||||
MaxDecodeTimeMs() - render_delay_ms_;
|
||||
|
||||
if (maxWaitTimeMs < 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return static_cast<uint32_t>(maxWaitTimeMs);
|
||||
if (max_wait_time_ms < 0) {
|
||||
return 0;
|
||||
}
|
||||
return static_cast<uint32_t>(max_wait_time_ms);
|
||||
}
|
||||
|
||||
bool
|
||||
VCMTiming::EnoughTimeToDecode(uint32_t availableProcessingTimeMs) const
|
||||
{
|
||||
CriticalSectionScoped cs(_critSect);
|
||||
int32_t maxDecodeTimeMs = MaxDecodeTimeMs();
|
||||
if (maxDecodeTimeMs < 0)
|
||||
{
|
||||
// Haven't decoded any frames yet, try decoding one to get an estimate
|
||||
// of the decode time.
|
||||
return true;
|
||||
}
|
||||
else if (maxDecodeTimeMs == 0)
|
||||
{
|
||||
// Decode time is less than 1, set to 1 for now since
|
||||
// we don't have any better precision. Count ticks later?
|
||||
maxDecodeTimeMs = 1;
|
||||
}
|
||||
return static_cast<int32_t>(availableProcessingTimeMs) - maxDecodeTimeMs > 0;
|
||||
bool VCMTiming::EnoughTimeToDecode(uint32_t available_processing_time_ms)
|
||||
const {
|
||||
CriticalSectionScoped cs(crit_sect_);
|
||||
int32_t max_decode_time_ms = MaxDecodeTimeMs();
|
||||
if (max_decode_time_ms < 0) {
|
||||
// Haven't decoded any frames yet, try decoding one to get an estimate
|
||||
// of the decode time.
|
||||
return true;
|
||||
} else if (max_decode_time_ms == 0) {
|
||||
// Decode time is less than 1, set to 1 for now since
|
||||
// we don't have any better precision. Count ticks later?
|
||||
max_decode_time_ms = 1;
|
||||
}
|
||||
return static_cast<int32_t>(available_processing_time_ms) -
|
||||
max_decode_time_ms > 0;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
VCMTiming::TargetVideoDelay() const
|
||||
{
|
||||
CriticalSectionScoped cs(_critSect);
|
||||
return TargetDelayInternal();
|
||||
uint32_t VCMTiming::TargetVideoDelay() const {
|
||||
CriticalSectionScoped cs(crit_sect_);
|
||||
return TargetDelayInternal();
|
||||
}
|
||||
|
||||
uint32_t
|
||||
VCMTiming::TargetDelayInternal() const
|
||||
{
|
||||
return std::max(_minTotalDelayMs,
|
||||
_requiredDelayMs + MaxDecodeTimeMs() + _renderDelayMs);
|
||||
uint32_t VCMTiming::TargetDelayInternal() const {
|
||||
return std::max(min_total_delay_ms_,
|
||||
required_delay_ms_ + MaxDecodeTimeMs() + render_delay_ms_);
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace webrtc
|
||||
|
@ -8,103 +8,102 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_MODULES_VIDEO_CODING_TIMING_H_
|
||||
#define WEBRTC_MODULES_VIDEO_CODING_TIMING_H_
|
||||
#ifndef WEBRTC_MODULES_VIDEO_CODING_MAIN_SOURCE_TIMING_H_
|
||||
#define WEBRTC_MODULES_VIDEO_CODING_MAIN_SOURCE_TIMING_H_
|
||||
|
||||
#include "typedefs.h"
|
||||
#include "critical_section_wrapper.h"
|
||||
#include "codec_timer.h"
|
||||
#include "webrtc/modules/video_coding/main/source/codec_timer.h"
|
||||
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
|
||||
#include "webrtc/typedefs.h"
|
||||
|
||||
namespace webrtc
|
||||
{
|
||||
namespace webrtc {
|
||||
|
||||
class Clock;
|
||||
class VCMTimestampExtrapolator;
|
||||
|
||||
class VCMTiming
|
||||
{
|
||||
public:
|
||||
// The primary timing component should be passed
|
||||
// if this is the dual timing component.
|
||||
VCMTiming(Clock* clock,
|
||||
int32_t vcmId = 0,
|
||||
int32_t timingId = 0,
|
||||
VCMTiming* masterTiming = NULL);
|
||||
~VCMTiming();
|
||||
class VCMTiming {
|
||||
public:
|
||||
// The primary timing component should be passed
|
||||
// if this is the dual timing component.
|
||||
VCMTiming(Clock* clock,
|
||||
int32_t vcm_id = 0,
|
||||
int32_t timing_id = 0,
|
||||
VCMTiming* master_timing = NULL);
|
||||
~VCMTiming();
|
||||
|
||||
// Resets the timing to the initial state.
|
||||
void Reset();
|
||||
void ResetDecodeTime();
|
||||
// Resets the timing to the initial state.
|
||||
void Reset();
|
||||
void ResetDecodeTime();
|
||||
|
||||
// The amount of time needed to render an image. Defaults to 10 ms.
|
||||
void SetRenderDelay(uint32_t renderDelayMs);
|
||||
// The amount of time needed to render an image. Defaults to 10 ms.
|
||||
void SetRenderDelay(uint32_t render_delay_ms);
|
||||
|
||||
// The minimum time the video must be delayed on the receiver to
|
||||
// get the desired jitter buffer level.
|
||||
void SetRequiredDelay(uint32_t requiredDelayMs);
|
||||
// The minimum time the video must be delayed on the receiver to
|
||||
// get the desired jitter buffer level.
|
||||
void SetRequiredDelay(uint32_t required_delay_ms);
|
||||
|
||||
// Minimum total delay required to sync video with audio.
|
||||
void SetMinimumTotalDelay(uint32_t minTotalDelayMs);
|
||||
// Minimum total delay required to sync video with audio.
|
||||
void SetMinimumTotalDelay(uint32_t min_total_delay_ms);
|
||||
|
||||
// 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,
|
||||
// and increases/decreases the delay in proportion to the time difference.
|
||||
void UpdateCurrentDelay(uint32_t frameTimestamp);
|
||||
// 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,
|
||||
// and increases/decreases the delay in proportion to the time difference.
|
||||
void UpdateCurrentDelay(uint32_t frame_timestamp);
|
||||
|
||||
// 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
|
||||
// function calculates how late the frame is and increases the delay accordingly.
|
||||
void UpdateCurrentDelay(int64_t renderTimeMs, int64_t actualDecodeTimeMs);
|
||||
// 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 function calculates how late the frame is and increases the delay
|
||||
// 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
|
||||
// or when the decoded frame callback is called.
|
||||
int32_t StopDecodeTimer(uint32_t timeStamp,
|
||||
int64_t startTimeMs,
|
||||
int64_t nowMs);
|
||||
// Stops the decoder timer, should be called when the decoder returns a frame
|
||||
// or when the decoded frame callback is called.
|
||||
int32_t StopDecodeTimer(uint32_t time_stamp,
|
||||
int64_t start_time_ms,
|
||||
int64_t now_ms);
|
||||
|
||||
// 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.
|
||||
void IncomingTimestamp(uint32_t timeStamp, int64_t lastPacketTimeMs);
|
||||
// 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.
|
||||
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
|
||||
// should be rendered, assuming that the system time currently is nowMs.
|
||||
int64_t RenderTimeMs(uint32_t frameTimestamp, int64_t nowMs) const;
|
||||
// Returns the maximum time in ms that we can wait for a frame to become
|
||||
// complete before we must pass it to the decoder.
|
||||
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
|
||||
// before we must pass it to the decoder.
|
||||
uint32_t MaxWaitingTime(int64_t renderTimeMs, int64_t nowMs) const;
|
||||
// Returns the current target delay which is required delay + decode time +
|
||||
// render delay.
|
||||
uint32_t TargetVideoDelay() const;
|
||||
|
||||
// Returns the current target delay which is required delay + decode time + render
|
||||
// delay.
|
||||
uint32_t TargetVideoDelay() const;
|
||||
// Calculates whether or not there is enough time to decode a frame given a
|
||||
// certain amount of processing time.
|
||||
bool EnoughTimeToDecode(uint32_t available_processing_time_ms) const;
|
||||
|
||||
// Calculates whether or not there is enough time to decode a frame given a
|
||||
// certain amount of processing time.
|
||||
bool EnoughTimeToDecode(uint32_t availableProcessingTimeMs) const;
|
||||
enum { kDefaultRenderDelayMs = 10 };
|
||||
enum { kDelayMaxChangeMsPerS = 100 };
|
||||
|
||||
enum { kDefaultRenderDelayMs = 10 };
|
||||
enum { kDelayMaxChangeMsPerS = 100 };
|
||||
protected:
|
||||
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:
|
||||
int32_t MaxDecodeTimeMs(FrameType frameType = kVideoFrameDelta) const;
|
||||
int64_t RenderTimeMsInternal(uint32_t frameTimestamp, int64_t nowMs) const;
|
||||
uint32_t TargetDelayInternal() const;
|
||||
|
||||
private:
|
||||
CriticalSectionWrapper* _critSect;
|
||||
int32_t _vcmId;
|
||||
Clock* _clock;
|
||||
int32_t _timingId;
|
||||
bool _master;
|
||||
VCMTimestampExtrapolator* _tsExtrapolator;
|
||||
VCMCodecTimer _codecTimer;
|
||||
uint32_t _renderDelayMs;
|
||||
uint32_t _minTotalDelayMs;
|
||||
uint32_t _requiredDelayMs;
|
||||
uint32_t _currentDelayMs;
|
||||
uint32_t _prevFrameTimestamp;
|
||||
private:
|
||||
CriticalSectionWrapper* crit_sect_;
|
||||
int32_t vcm_id_;
|
||||
Clock* clock_;
|
||||
int32_t timing_id_;
|
||||
bool master_;
|
||||
VCMTimestampExtrapolator* ts_extrapolator_;
|
||||
VCMCodecTimer codec_timer_;
|
||||
uint32_t render_delay_ms_;
|
||||
uint32_t min_total_delay_ms_;
|
||||
uint32_t required_delay_ms_;
|
||||
uint32_t current_delay_ms_;
|
||||
uint32_t prev_frame_timestamp_;
|
||||
};
|
||||
} // namespace webrtc
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_MODULES_VIDEO_CODING_TIMING_H_
|
||||
#endif // WEBRTC_MODULES_VIDEO_CODING_MAIN_SOURCE_TIMING_H_
|
||||
|
Loading…
x
Reference in New Issue
Block a user