diff --git a/webrtc/modules/video_coding/codecs/vp8/temporal_layers.cc b/webrtc/modules/video_coding/codecs/vp8/temporal_layers.cc index ad8a988251..2096eb5d9c 100644 --- a/webrtc/modules/video_coding/codecs/vp8/temporal_layers.cc +++ b/webrtc/modules/video_coding/codecs/vp8/temporal_layers.cc @@ -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 diff --git a/webrtc/modules/video_coding/codecs/vp8/temporal_layers.h b/webrtc/modules/video_coding/codecs/vp8/temporal_layers.h index c1366b59fb..463f95e4f1 100644 --- a/webrtc/modules/video_coding/codecs/vp8/temporal_layers.h +++ b/webrtc/modules/video_coding/codecs/vp8/temporal_layers.h @@ -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, diff --git a/webrtc/modules/video_coding/codecs/vp8/vp8_impl.cc b/webrtc/modules/video_coding/codecs/vp8/vp8_impl.cc index 9deb82c452..9d64ef19ee 100644 --- a/webrtc/modules/video_coding/codecs/vp8/vp8_impl.cc +++ b/webrtc/modules/video_coding/codecs/vp8/vp8_impl.cc @@ -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(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 }