Set first_frame_in_picture on first encoded frame of picture.
Set the flag based on coded length of buffered frame which is reset
after picture is encoded and, thus, is equal to zero when encoder
delivers first frame of next picture.
Before this change first_frame_in_picture was set based on index of
spatial layer of encoded frame. This is not right anymore since encoder
can drop base layer but deliver upper layers.
Bug: chromium:828350
Change-Id: I12c7534240de8bc4905f04ff368cc3704720a70b
Reviewed-on: https://webrtc-review.googlesource.com/68561
Reviewed-by: Rasmus Brandt <brandtr@webrtc.org>
Commit-Queue: Sergey Silkin <ssilkin@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#22805}
diff --git a/modules/video_coding/codecs/vp9/vp9_impl.cc b/modules/video_coding/codecs/vp9/vp9_impl.cc
index 348a0df..5ae44ed 100644
--- a/modules/video_coding/codecs/vp9/vp9_impl.cc
+++ b/modules/video_coding/codecs/vp9/vp9_impl.cc
@@ -585,11 +585,14 @@
void VP9EncoderImpl::PopulateCodecSpecific(CodecSpecificInfo* codec_specific,
const vpx_codec_cx_pkt& pkt,
- uint32_t timestamp) {
+ uint32_t timestamp,
+ bool first_frame_in_picture) {
RTC_CHECK(codec_specific != nullptr);
codec_specific->codecType = kVideoCodecVP9;
codec_specific->codec_name = ImplementationName();
CodecSpecificInfoVP9* vp9_info = &(codec_specific->codecSpecific.VP9);
+
+ vp9_info->first_frame_in_picture = first_frame_in_picture;
// TODO(asapersson): Set correct value.
vp9_info->inter_pic_predicted =
(pkt.data.frame.flags & VPX_FRAME_IS_KEY) ? false : true;
@@ -623,15 +626,7 @@
// TODO(asapersson): this info has to be obtained from the encoder.
vp9_info->temporal_up_switch = false;
- bool is_first_frame = false;
- if (is_flexible_mode_) {
- is_first_frame =
- layer_id.spatial_layer_id == spatial_layer_->GetStartLayer();
- } else {
- is_first_frame = layer_id.spatial_layer_id == 0;
- }
-
- if (is_first_frame) {
+ if (first_frame_in_picture) {
// TODO(asapersson): this info has to be obtained from the encoder.
vp9_info->inter_layer_predicted = false;
++frames_since_kf_;
@@ -640,8 +635,6 @@
vp9_info->inter_layer_predicted = true;
}
- vp9_info->first_frame_in_picture = is_first_frame;
-
if (pkt.data.frame.flags & VPX_FRAME_IS_KEY) {
frames_since_kf_ = 0;
}
@@ -687,6 +680,13 @@
return WEBRTC_VIDEO_CODEC_OK;
}
+ vpx_svc_layer_id_t layer_id = {0};
+ vpx_codec_control(encoder_, VP9E_GET_SVC_LAYER_ID, &layer_id);
+
+ const bool first_frame_in_picture = encoded_image_._length == 0;
+ // Ensure we don't buffer layers of previous picture (superframe).
+ RTC_DCHECK(first_frame_in_picture || layer_id.spatial_layer_id > 0);
+
const bool end_of_superframe = false;
DeliverBufferedFrame(end_of_superframe);
@@ -698,14 +698,12 @@
memcpy(encoded_image_._buffer, pkt->data.frame.buf, pkt->data.frame.sz);
encoded_image_._length = pkt->data.frame.sz;
- vpx_svc_layer_id_t layer_id = {0};
- vpx_codec_control(encoder_, VP9E_GET_SVC_LAYER_ID, &layer_id);
- if (is_flexible_mode_ && codec_.mode == kScreensharing)
+ if (is_flexible_mode_ && codec_.mode == kScreensharing) {
spatial_layer_->LayerFrameEncoded(
static_cast<unsigned int>(encoded_image_._length),
layer_id.spatial_layer_id);
+ }
- // End of frame.
// Check if encoded frame is a key frame.
encoded_image_._frameType = kVideoFrameDelta;
if (pkt->data.frame.flags & VPX_FRAME_IS_KEY) {
@@ -714,7 +712,8 @@
RTC_DCHECK_LE(encoded_image_._length, encoded_image_._size);
memset(&codec_specific_, 0, sizeof(codec_specific_));
- PopulateCodecSpecific(&codec_specific_, *pkt, input_image_->timestamp());
+ PopulateCodecSpecific(&codec_specific_, *pkt, input_image_->timestamp(),
+ first_frame_in_picture);
TRACE_COUNTER1("webrtc", "EncodedFrameSize", encoded_image_._length);
encoded_image_._timeStamp = input_image_->timestamp();
diff --git a/modules/video_coding/codecs/vp9/vp9_impl.h b/modules/video_coding/codecs/vp9/vp9_impl.h
index 3f10d26..b158523 100644
--- a/modules/video_coding/codecs/vp9/vp9_impl.h
+++ b/modules/video_coding/codecs/vp9/vp9_impl.h
@@ -74,7 +74,8 @@
void PopulateCodecSpecific(CodecSpecificInfo* codec_specific,
const vpx_codec_cx_pkt& pkt,
- uint32_t timestamp);
+ uint32_t timestamp,
+ bool first_frame_in_picture);
bool ExplicitlyConfiguredSpatialLayers() const;
bool SetSvcRates(const BitrateAllocation& bitrate_allocation);