Allow for 1 layer case to be set in temporal_layers.

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

git-svn-id: http://webrtc.googlecode.com/svn/trunk@3188 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
marpan@webrtc.org
2012-11-28 22:06:21 +00:00
parent 7d5dacc985
commit c09e779766
3 changed files with 70 additions and 56 deletions

View File

@ -40,7 +40,17 @@ bool TemporalLayers::ConfigureBitrates(int bitrateKbit,
switch (number_of_temporal_layers_) {
case 0:
case 1:
// Do nothing.
temporal_ids_length_ = 1;
temporal_ids_[0] = 0;
cfg->ts_number_layers = number_of_temporal_layers_;
cfg->ts_periodicity = temporal_ids_length_;
cfg->ts_target_bitrate[0] = bitrateKbit;
cfg->ts_rate_decimator[0] = 1;
memcpy(cfg->ts_layer_id,
temporal_ids_,
sizeof(unsigned int) * temporal_ids_length_);
temporal_pattern_length_ = 1;
temporal_pattern_[0] = kTemporalUpdateLastRefAll;
break;
case 2:
temporal_ids_length_ = 2;
@ -147,10 +157,9 @@ bool TemporalLayers::ConfigureBitrates(int bitrateKbit,
}
int TemporalLayers::EncodeFlags() {
assert(number_of_temporal_layers_ > 1);
assert(number_of_temporal_layers_ > 0);
assert(kMaxTemporalPattern >= temporal_pattern_length_);
assert(0 < temporal_pattern_length_);
int flags = 0;
int patternIdx = ++pattern_idx_ % temporal_pattern_length_;
assert(kMaxTemporalPattern >= patternIdx);
@ -211,6 +220,10 @@ int TemporalLayers::EncodeFlags() {
flags |= VP8_EFLAG_NO_UPD_ARF;
flags |= VP8_EFLAG_NO_REF_GF;
break;
case kTemporalUpdateLastRefAll:
flags |= VP8_EFLAG_NO_UPD_ARF;
flags |= VP8_EFLAG_NO_UPD_GF;
break;
}
return flags;
}
@ -218,39 +231,47 @@ int TemporalLayers::EncodeFlags() {
void TemporalLayers::PopulateCodecSpecific(bool base_layer_sync,
CodecSpecificInfoVP8 *vp8_info,
uint32_t timestamp) {
assert(number_of_temporal_layers_ > 1);
assert(number_of_temporal_layers_ > 0);
assert(0 < temporal_ids_length_);
if (base_layer_sync) {
if (number_of_temporal_layers_ == 1) {
vp8_info->temporalIdx = kNoTemporalIdx;
vp8_info->layerSync = false;
vp8_info->tl0PicIdx = kNoTl0PicIdx;
} else {
if (base_layer_sync) {
vp8_info->temporalIdx = 0;
vp8_info->layerSync = true;
} else {
vp8_info->temporalIdx = temporal_ids_[pattern_idx_ % temporal_ids_length_];
TemporalReferences temporal_reference =
temporal_pattern_[pattern_idx_ % temporal_pattern_length_];
if (temporal_reference == kTemporalUpdateAltrefWithoutDependency ||
temporal_reference == kTemporalUpdateGoldenWithoutDependency ||
temporal_reference == kTemporalUpdateGoldenWithoutDependencyRefAltRef ||
temporal_reference == kTemporalUpdateNoneNoRefGoldenRefAltRef ||
(temporal_reference == kTemporalUpdateNone &&
number_of_temporal_layers_ == 4)) {
vp8_info->layerSync = true;
} else {
vp8_info->layerSync = false;
vp8_info->temporalIdx = temporal_ids_
[pattern_idx_ % temporal_ids_length_];
TemporalReferences temporal_reference =
temporal_pattern_[pattern_idx_ % temporal_pattern_length_];
if (temporal_reference == kTemporalUpdateAltrefWithoutDependency ||
temporal_reference == kTemporalUpdateGoldenWithoutDependency ||
temporal_reference ==
kTemporalUpdateGoldenWithoutDependencyRefAltRef ||
temporal_reference == kTemporalUpdateNoneNoRefGoldenRefAltRef ||
(temporal_reference == kTemporalUpdateNone &&
number_of_temporal_layers_ == 4)) {
vp8_info->layerSync = true;
} else {
vp8_info->layerSync = false;
}
}
if (last_base_layer_sync_ && vp8_info->temporalIdx != 0) {
// Regardless of pattern the frame after a base layer sync will always
// be a layer sync.
vp8_info->layerSync = true;
}
if (vp8_info->temporalIdx == 0 && timestamp != timestamp_) {
timestamp_ = timestamp;
tl0_pic_idx_++;
}
last_base_layer_sync_ = base_layer_sync;
vp8_info->tl0PicIdx = tl0_pic_idx_;
}
if (last_base_layer_sync_ && vp8_info->temporalIdx != 0) {
// Regardless of pattern the frame after a base layer sync will always
// be a layer sync.
vp8_info->layerSync = true;
}
if (vp8_info->temporalIdx == 0 && timestamp != timestamp_) {
timestamp_ = timestamp;
tl0_pic_idx_++;
}
last_base_layer_sync_ = base_layer_sync;
vp8_info->tl0PicIdx = tl0_pic_idx_;
}
} // namespace webrtc

View File

@ -37,6 +37,9 @@ class TemporalLayers {
private:
enum TemporalReferences {
// For 1 layer case: reference all (last, golden, and alt ref), but only
// update last.
kTemporalUpdateLastRefAll = 12,
// First base layer frame for 3 temporal layers, which updates last and
// golden with alt ref dependency.
kTemporalUpdateLastAndGoldenRefAltRef = 11,

View File

@ -111,9 +111,7 @@ int VP8EncoderImpl::SetRates(uint32_t new_bitrate_kbit,
config_->rc_target_bitrate = new_bitrate_kbit; // in kbit/s
#if WEBRTC_LIBVPX_VERSION >= 971
if (temporal_layers_) {
temporal_layers_->ConfigureBitrates(new_bitrate_kbit, config_);
}
temporal_layers_->ConfigureBitrates(new_bitrate_kbit, config_);
#endif
codec_.maxFramerate = new_framerate;
@ -159,12 +157,12 @@ int VP8EncoderImpl::InitEncode(const VideoCodec* inst,
codec_ = *inst;
int num_temporal_layers = inst->codecSpecific.VP8.numberOfTemporalLayers > 1 ?
inst->codecSpecific.VP8.numberOfTemporalLayers : 1;
#if WEBRTC_LIBVPX_VERSION >= 971
if (inst->codecSpecific.VP8.numberOfTemporalLayers > 1) {
assert(temporal_layers_ == NULL);
temporal_layers_ =
new TemporalLayers(inst->codecSpecific.VP8.numberOfTemporalLayers);
}
assert(temporal_layers_ == NULL);
temporal_layers_ = new TemporalLayers(num_temporal_layers);
#endif
// random start 16 bits is enough.
picture_id_ = static_cast<uint16_t>(rand()) & 0x7FFF;
@ -191,9 +189,7 @@ int VP8EncoderImpl::InitEncode(const VideoCodec* inst,
config_->rc_target_bitrate = inst->startBitrate; // in kbit/s
#if WEBRTC_LIBVPX_VERSION >= 971
if (temporal_layers_) {
temporal_layers_->ConfigureBitrates(inst->startBitrate, config_);
}
temporal_layers_->ConfigureBitrates(inst->startBitrate, config_);
#endif
// setting the time base of the codec
config_->g_timebase.num = 1;
@ -204,8 +200,8 @@ int VP8EncoderImpl::InitEncode(const VideoCodec* inst,
case kResilienceOff:
config_->g_error_resilient = 0;
#if WEBRTC_LIBVPX_VERSION >= 971
if (temporal_layers_) {
// Must be on for temporal layers.
if (num_temporal_layers > 1) {
// Must be on for temporal layers (i.e., |num_temporal_layers| > 1).
config_->g_error_resilient = 1;
}
#endif
@ -363,9 +359,7 @@ int VP8EncoderImpl::Encode(const I420VideoFrame& input_image,
int flags = 0;
#if WEBRTC_LIBVPX_VERSION >= 971
if (temporal_layers_) {
flags |= temporal_layers_->EncodeFlags();
}
flags |= temporal_layers_->EncodeFlags();
#endif
bool send_keyframe = (frame_type == kKeyFrame);
if (send_keyframe) {
@ -442,17 +436,13 @@ void VP8EncoderImpl::PopulateCodecSpecific(CodecSpecificInfo* codec_specific,
vp8Info->keyIdx = kNoKeyIdx; // TODO(hlundin) populate this
vp8Info->nonReference = (pkt.data.frame.flags & VPX_FRAME_IS_DROPPABLE) != 0;
#if WEBRTC_LIBVPX_VERSION >= 971
if (temporal_layers_) {
temporal_layers_->PopulateCodecSpecific(
(pkt.data.frame.flags & VPX_FRAME_IS_KEY) ? true : false, vp8Info,
timestamp);
} else {
#endif
vp8Info->temporalIdx = kNoTemporalIdx;
vp8Info->layerSync = false;
vp8Info->tl0PicIdx = kNoTl0PicIdx;
#if WEBRTC_LIBVPX_VERSION >= 971
}
temporal_layers_->PopulateCodecSpecific(
(pkt.data.frame.flags & VPX_FRAME_IS_KEY) ? true : false, vp8Info,
timestamp);
#else
vp8Info->temporalIdx = kNoTemporalIdx;
vp8Info->layerSync = false;
vp8Info->tl0PicIdx = kNoTl0PicIdx;
#endif
picture_id_ = (picture_id_ + 1) & 0x7FFF; // prepare next
}