Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(314)

Unified Diff: webrtc/modules/video_coding/codecs/vp9/vp9_impl.cc

Issue 1328113004: Work on flexible mode and screen sharing. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Undo renaming Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: webrtc/modules/video_coding/codecs/vp9/vp9_impl.cc
diff --git a/webrtc/modules/video_coding/codecs/vp9/vp9_impl.cc b/webrtc/modules/video_coding/codecs/vp9/vp9_impl.cc
index 73beab37b0627c44f065a784afd7e8f601281894..e59ddc302389ed375b73a6fde6830030567b28a4 100644
--- a/webrtc/modules/video_coding/codecs/vp9/vp9_impl.cc
+++ b/webrtc/modules/video_coding/codecs/vp9/vp9_impl.cc
@@ -76,9 +76,10 @@ VP9EncoderImpl::VP9EncoderImpl()
raw_(NULL),
input_image_(NULL),
tl0_pic_idx_(0),
- gof_idx_(0),
+ frames_since_kf_(0),
num_temporal_layers_(0),
- num_spatial_layers_(0) {
+ num_spatial_layers_(0),
+ frames_encoded_(0) {
memset(&codec_, 0, sizeof(codec_));
uint32_t seed = static_cast<uint32_t>(TickTime::MillisecondTimestamp());
srand(seed);
@@ -292,7 +293,26 @@ int VP9EncoderImpl::InitEncode(const VideoCodec* inst,
// TODO(asapersson): Check configuration of temporal switch up and increase
// pattern length.
- if (num_temporal_layers_ == 1) {
+ is_flexible_mode_ = inst->codecSpecific.VP9.flexibleMode;
+ if (is_flexible_mode_) {
+ config_->temporal_layering_mode = VP9E_TEMPORAL_LAYERING_MODE_BYPASS;
+ config_->ts_number_layers = num_temporal_layers_;
+
+ if (codec_.mode == kScreensharing) {
+ // TODO(philipel): Using VP8 style screen sharing. Change conditions
+ // when flexible mode + spatial layers become available.
+ assert(inst->codecSpecific.VP9.numberOfTemporalLayers == 2);
sprang_webrtc 2015/09/07 14:39:05 CHECK_EQ(2, ...)
philipel 2015/09/10 14:47:02 Code removed, now use spatial layers instead. Hurr
+ config_->ts_number_layers = 2;
+ config_->ts_rate_decimator[0] = 2;
+ config_->ts_rate_decimator[1] = 1;
+ config_->ts_periodicity = 2;
+ config_->ts_layer_id[0] = 0;
+ config_->ts_layer_id[1] = 1;
+
+ // TODO(philipel): The following should be configurable, not fixed:
+ temporal_layer_.ConfigureBitrate(1000);
sprang_webrtc 2015/09/07 14:39:05 Why not set to start bitrate from VideoCodec param
philipel 2015/09/10 14:47:02 Done.
+ }
+ } else if (num_temporal_layers_ == 1) {
gof_.SetGofInfoVP9(kTemporalStructureMode1);
config_->temporal_layering_mode = VP9E_TEMPORAL_LAYERING_MODE_NOLAYERING;
config_->ts_number_layers = 1;
@@ -458,12 +478,64 @@ int VP9EncoderImpl::Encode(const VideoFrame& input_image,
raw_->stride[VPX_PLANE_U] = input_image.stride(kUPlane);
raw_->stride[VPX_PLANE_V] = input_image.stride(kVPlane);
- int flags = 0;
+ vpx_enc_frame_flags_t flags = 0;
bool send_keyframe = (frame_type == kKeyFrame);
if (send_keyframe) {
// Key frame request from caller.
flags = VPX_EFLAG_FORCE_KF;
}
+
+ if (is_flexible_mode_) {
+ vpx_svc_layer_id_t svc_layer;
+ svc_layer.spatial_layer_id = 0;
+ if (send_keyframe) {
+ flags = GenerateRefsAndFlags();
+ } else if (codec_.mode == kRealtimeVideo) {
+ // TODO(philipel): For now produce the 0-2-1-2 mod 8 pattern
+ switch ((frames_since_kf_ - 1) % 8) {
+ case 0: {
+ flags = GenerateRefsAndFlags(0, 0);
+ break;
+ }
+ case 1: {
+ flags = GenerateRefsAndFlags(2, 0);
+ break;
+ }
+ case 2: {
+ flags = GenerateRefsAndFlags(1, 0);
+ break;
+ }
+ case 3: {
+ flags = GenerateRefsAndFlags(2, 0, 1, 2);
+ break;
+ }
+ case 4: {
+ flags = GenerateRefsAndFlags(0, 0);
+ break;
+ }
+ case 5: {
+ flags = GenerateRefsAndFlags(2, 0, 1, 2);
+ break;
+ }
+ case 6: {
+ flags = GenerateRefsAndFlags(1, 0, 1);
+ break;
+ }
+ case 7: {
+ flags = GenerateRefsAndFlags(2, 0, 1, 2);
+ break;
+ }
+ }
+ static const int temporal_layers[4] = {0, 2, 1, 2};
+ svc_layer.temporal_layer_id = temporal_layers[(frames_since_kf_ - 1) % 4];
+ } else {
+ flags = GenerateRefsAndFlags(
+ temporal_layer_.BufferArguments(input_image.timestamp()));
+ svc_layer.temporal_layer_id = temporal_layer_.CurrentLayer();
+ }
+ vpx_codec_control(encoder_, VP9E_SET_SVC_LAYER_ID, &svc_layer);
+ }
+
assert(codec_.maxFramerate > 0);
uint32_t duration = 90000 / codec_.maxFramerate;
if (vpx_codec_encode(encoder_, raw_, timestamp_, duration, flags,
@@ -489,9 +561,8 @@ void VP9EncoderImpl::PopulateCodecSpecific(CodecSpecificInfo* codec_specific,
!codec_.codecSpecific.VP9.flexibleMode)
? true
: false;
- if (pkt.data.frame.flags & VPX_FRAME_IS_KEY) {
- gof_idx_ = 0;
- }
+ if (pkt.data.frame.flags & VPX_FRAME_IS_KEY)
+ frames_since_kf_ = 0;
vpx_svc_layer_id_t layer_id = {0};
vpx_codec_control(encoder_, VP9E_GET_SVC_LAYER_ID, &layer_id);
@@ -514,13 +585,6 @@ void VP9EncoderImpl::PopulateCodecSpecific(CodecSpecificInfo* codec_specific,
vp9_info->ss_data_available = false;
}
- if (vp9_info->flexible_mode) {
- vp9_info->gof_idx = kNoGofIdx;
- } else {
- vp9_info->gof_idx =
- static_cast<uint8_t>(gof_idx_++ % gof_.num_frames_in_gof);
- }
-
// TODO(asapersson): this info has to be obtained from the encoder.
vp9_info->temporal_up_switch = true;
@@ -542,6 +606,21 @@ void VP9EncoderImpl::PopulateCodecSpecific(CodecSpecificInfo* codec_specific,
vp9_info->tl0_pic_idx = tl0_pic_idx_;
}
+ vp9_info->num_ref_pics = 0;
+ if (vp9_info->flexible_mode) {
+ vp9_info->gof_idx = kNoGofIdx;
+ if (!(pkt.data.frame.flags & VPX_FRAME_IS_KEY)) {
+ vp9_info->num_ref_pics = num_refs_pics_;
+ for (int i = 0; i < num_refs_pics_; ++i) {
+ vp9_info->p_diff[i] = p_diff_[i];
+ }
+ }
+ } else {
+ vp9_info->gof_idx =
+ static_cast<uint8_t>(frames_since_kf_ % gof_.num_frames_in_gof);
+ }
+ ++frames_since_kf_;
+
if (vp9_info->ss_data_available) {
vp9_info->num_spatial_layers = num_spatial_layers_;
vp9_info->spatial_layer_resolution_present = true;
@@ -578,6 +657,9 @@ int VP9EncoderImpl::GetEncodedLayerFrame(const vpx_codec_cx_pkt* pkt) {
frag_info.fragmentationPlType[part_idx] = 0;
frag_info.fragmentationTimeDiff[part_idx] = 0;
encoded_image_._length += static_cast<uint32_t>(pkt->data.frame.sz);
+ if (is_flexible_mode_ && codec_.mode == kScreensharing) {
+ temporal_layer_.FrameEncoded(encoded_image_._length);
+ }
sprang_webrtc 2015/09/07 14:39:05 Remove {}
philipel 2015/09/10 14:47:02 Done.
assert(encoded_image_._length <= encoded_image_._size);
// End of frame.
@@ -599,6 +681,94 @@ int VP9EncoderImpl::GetEncodedLayerFrame(const vpx_codec_cx_pkt* pkt) {
return WEBRTC_VIDEO_CODEC_OK;
}
+vpx_enc_frame_flags_t VP9EncoderImpl::GenerateRefsAndFlags(int8_t upd_buffer,
+ int8_t ref_buf1,
+ int8_t ref_buf2,
+ int8_t ref_buf3) {
+ // For now we only use 3 out of the 8 buffers available
+ DCHECK(upd_buffer < 3);
sprang_webrtc 2015/09/07 14:39:05 DCHECK_LT
philipel 2015/09/10 14:47:02 Code removed.
+
+ // BUF0 = LAST
+ // BUF1 = GF
+ // BUF2 = ARF
+ num_refs_pics_ = 0;
+ vpx_enc_frame_flags_t flags = VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_REF_LAST |
+ VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_ARF |
+ VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_LAST;
+ if (upd_buffer == -2) {
sprang_webrtc 2015/09/07 14:39:05 Have a named constant for -2?
philipel 2015/09/10 14:47:02 Code removed.
+#ifdef NDEBUG
sprang_webrtc 2015/09/07 14:39:05 Can't just always do this? memset it?
philipel 2015/09/10 14:47:02 Done.
+ // Used later on to make sure we don't make any invalid references.
+ for (int i = 0; i < 8; ++i)
+ buf_upd_at_frame_[i] = -1;
+#endif
+
+ // Keyframe, always stored in BUF0. Why? Because of line 161 in
sprang_webrtc 2015/09/07 14:39:05 This comment may grow stale quickly :) "Keyframe a
philipel 2015/09/10 14:47:02 Changed so that the keyframes are stored in the bu
+ // vpx_temporal_svc_encoder.c. I'm not sure if that comment applies here
+ buf_upd_at_frame_[0] = frames_encoded_;
+ flags = VPX_EFLAG_FORCE_KF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
+ } else {
+ int8_t refs[3] = {ref_buf1, ref_buf2, ref_buf3};
sprang_webrtc 2015/09/07 14:39:05 I'd probably add a named constant for 3 and use he
philipel 2015/09/10 14:47:01 Now use the kMaxVp9RefPics instead of '3'.
+ for (int i = 0; i < 3; ++i) {
+ switch (refs[i]) {
+ case -1:
+ goto done;
sprang_webrtc 2015/09/07 14:39:05 Ugh! How bout: i = kNumReferences; continue; Per
philipel 2015/09/10 14:47:02 Code removed.
+ case 0: {
+ flags ^= VP8_EFLAG_NO_REF_LAST;
+ break;
+ }
+ case 1: {
+ flags ^= VP8_EFLAG_NO_REF_GF;
+ break;
+ }
+ case 2: {
+ flags ^= VP8_EFLAG_NO_REF_ARF;
+ break;
+ }
+ default:
+ DCHECK(false);
sprang_webrtc 2015/09/07 14:39:05 RTC_NOTREACHED();
philipel 2015/09/10 14:47:02 Code removed.
+ }
+
+ // Make sure this frame doesn't reference to an unavailable
+ // buffer, either because it has not yet been used or
+ // because a KF has occurred since it was used.
+ DCHECK(buf_upd_at_frame_[refs[i]] != -1);
+
+ p_diff_[i] = frames_encoded_ - buf_upd_at_frame_[refs[i]];
+ num_refs_pics_++;
+ }
+ // Everybody love gotos!
sprang_webrtc 2015/09/07 14:39:05 No. :)
philipel 2015/09/10 14:47:02 Yes!
+ done:
+
+ buf_upd_at_frame_[upd_buffer] = frames_encoded_;
+ switch (upd_buffer) {
+ case -1:
+ break;
+ case 0: {
+ flags ^= VP8_EFLAG_NO_UPD_LAST;
+ break;
+ }
+ case 1: {
+ flags ^= VP8_EFLAG_NO_UPD_GF;
+ break;
+ }
+ case 2: {
+ flags ^= VP8_EFLAG_NO_UPD_ARF;
+ break;
+ }
+ default:
+ DCHECK(false);
sprang_webrtc 2015/09/07 14:39:05 RTC_NOTREACHED();
philipel 2015/09/10 14:47:01 Code removed.
+ }
+ }
+
+ frames_encoded_++;
+ return flags;
+}
+
+vpx_enc_frame_flags_t VP9EncoderImpl::GenerateRefsAndFlags(
+ std::array<int8_t, 4> args) {
+ return GenerateRefsAndFlags(args[0], args[1], args[2], args[3]);
+}
+
int VP9EncoderImpl::SetChannelParameters(uint32_t packet_loss, int64_t rtt) {
return WEBRTC_VIDEO_CODEC_OK;
}

Powered by Google App Engine
This is Rietveld 408576698