2018-07-17 10:16:41 +02:00
|
|
|
/*
|
|
|
|
|
* Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
|
|
|
|
|
*
|
|
|
|
|
* Use of this source code is governed by a BSD-style license
|
|
|
|
|
* that can be found in the LICENSE file in the root of the source
|
|
|
|
|
* tree. An additional intellectual property rights grant can be found
|
|
|
|
|
* in the file PATENTS. All contributing project authors may
|
|
|
|
|
* be found in the AUTHORS file in the root of the source tree.
|
|
|
|
|
*/
|
|
|
|
|
|
2018-07-19 10:34:38 +02:00
|
|
|
#include "call/rtp_payload_params.h"
|
2019-07-05 19:08:33 +02:00
|
|
|
|
2018-11-28 16:47:49 +01:00
|
|
|
#include <string.h>
|
2019-07-05 19:08:33 +02:00
|
|
|
|
2018-11-28 16:47:49 +01:00
|
|
|
#include <map>
|
2018-08-27 14:33:18 +02:00
|
|
|
#include <set>
|
2018-07-17 10:16:41 +02:00
|
|
|
|
2018-11-28 16:47:49 +01:00
|
|
|
#include "absl/container/inlined_vector.h"
|
|
|
|
|
#include "absl/types/optional.h"
|
|
|
|
|
#include "absl/types/variant.h"
|
2020-04-18 14:36:59 +02:00
|
|
|
#include "api/transport/field_trial_based_config.h"
|
2018-11-28 16:47:49 +01:00
|
|
|
#include "api/video/video_content_type.h"
|
|
|
|
|
#include "api/video/video_rotation.h"
|
|
|
|
|
#include "modules/video_coding/codecs/h264/include/h264_globals.h"
|
|
|
|
|
#include "modules/video_coding/codecs/interface/common_constants.h"
|
|
|
|
|
#include "modules/video_coding/codecs/vp8/include/vp8_globals.h"
|
|
|
|
|
#include "modules/video_coding/codecs/vp9/include/vp9_globals.h"
|
2018-07-17 10:16:41 +02:00
|
|
|
#include "modules/video_coding/include/video_codec_interface.h"
|
2021-04-22 15:20:28 +02:00
|
|
|
#include "test/explicit_key_value_config.h"
|
2019-06-13 15:13:16 +02:00
|
|
|
#include "test/gmock.h"
|
2018-07-17 10:16:41 +02:00
|
|
|
#include "test/gtest.h"
|
2022-03-09 15:12:07 +01:00
|
|
|
#include "test/scoped_key_value_config.h"
|
2018-07-17 10:16:41 +02:00
|
|
|
|
2021-04-22 15:20:28 +02:00
|
|
|
using ::testing::Each;
|
2019-06-13 15:13:16 +02:00
|
|
|
using ::testing::ElementsAre;
|
2021-09-01 15:21:16 +02:00
|
|
|
using ::testing::Eq;
|
2019-06-13 15:13:16 +02:00
|
|
|
using ::testing::IsEmpty;
|
2020-05-19 14:48:19 +02:00
|
|
|
using ::testing::SizeIs;
|
2019-06-13 15:13:16 +02:00
|
|
|
|
2020-01-07 19:16:33 +00:00
|
|
|
namespace webrtc {
|
|
|
|
|
namespace {
|
2018-07-17 10:16:41 +02:00
|
|
|
const uint32_t kSsrc1 = 12345;
|
|
|
|
|
const uint32_t kSsrc2 = 23456;
|
|
|
|
|
const int16_t kPictureId = 123;
|
|
|
|
|
const int16_t kTl0PicIdx = 20;
|
|
|
|
|
const uint8_t kTemporalIdx = 1;
|
|
|
|
|
const int16_t kInitialPictureId1 = 222;
|
|
|
|
|
const int16_t kInitialTl0PicIdx1 = 99;
|
2018-08-27 14:33:18 +02:00
|
|
|
const int64_t kDontCare = 0;
|
2018-07-17 10:16:41 +02:00
|
|
|
} // namespace
|
|
|
|
|
|
|
|
|
|
TEST(RtpPayloadParamsTest, InfoMappedToRtpVideoHeader_Vp8) {
|
|
|
|
|
RtpPayloadState state2;
|
|
|
|
|
state2.picture_id = kPictureId;
|
|
|
|
|
state2.tl0_pic_idx = kTl0PicIdx;
|
|
|
|
|
std::map<uint32_t, RtpPayloadState> states = {{kSsrc2, state2}};
|
|
|
|
|
|
2020-04-18 14:36:59 +02:00
|
|
|
RtpPayloadParams params(kSsrc2, &state2, FieldTrialBasedConfig());
|
2018-07-17 10:16:41 +02:00
|
|
|
EncodedImage encoded_image;
|
|
|
|
|
encoded_image.rotation_ = kVideoRotation_90;
|
|
|
|
|
encoded_image.content_type_ = VideoContentType::SCREENSHARE;
|
2018-08-27 15:33:42 +02:00
|
|
|
encoded_image.SetSpatialIndex(1);
|
2018-07-17 10:16:41 +02:00
|
|
|
|
|
|
|
|
CodecSpecificInfo codec_info;
|
|
|
|
|
codec_info.codecType = kVideoCodecVP8;
|
2018-08-27 14:33:18 +02:00
|
|
|
codec_info.codecSpecific.VP8.temporalIdx = 0;
|
2018-07-17 10:16:41 +02:00
|
|
|
codec_info.codecSpecific.VP8.keyIdx = kNoKeyIdx;
|
2018-08-27 14:33:18 +02:00
|
|
|
codec_info.codecSpecific.VP8.layerSync = false;
|
2018-07-17 10:16:41 +02:00
|
|
|
codec_info.codecSpecific.VP8.nonReference = true;
|
|
|
|
|
|
2018-08-27 14:33:18 +02:00
|
|
|
RTPVideoHeader header =
|
|
|
|
|
params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
|
|
|
|
|
|
|
|
|
|
codec_info.codecType = kVideoCodecVP8;
|
|
|
|
|
codec_info.codecSpecific.VP8.temporalIdx = 1;
|
|
|
|
|
codec_info.codecSpecific.VP8.layerSync = true;
|
|
|
|
|
|
|
|
|
|
header = params.GetRtpVideoHeader(encoded_image, &codec_info, 1);
|
2018-07-17 10:16:41 +02:00
|
|
|
|
|
|
|
|
EXPECT_EQ(kVideoRotation_90, header.rotation);
|
|
|
|
|
EXPECT_EQ(VideoContentType::SCREENSHARE, header.content_type);
|
|
|
|
|
EXPECT_EQ(1, header.simulcastIdx);
|
|
|
|
|
EXPECT_EQ(kVideoCodecVP8, header.codec);
|
Reland "Remove RTPVideoHeader::vp8() accessors."
This reverts commit 1811c04f22a26da3ed2832373a5c92a9786420c3.
Reason for revert: Downstream projects fixed.
Original change's description:
> Revert "Remove RTPVideoHeader::vp8() accessors."
>
> This reverts commit af7afc66427b0e9109e7d492f2805d63d239b914.
>
> Reason for revert: Break downstream projects.
>
> Original change's description:
> > Remove RTPVideoHeader::vp8() accessors.
> >
> > Bug: none
> > Change-Id: Ia7d65148fb36a8f26647bee8a876ce7217ff8a68
> > Reviewed-on: https://webrtc-review.googlesource.com/93321
> > Reviewed-by: Niels Moller <nisse@webrtc.org>
> > Reviewed-by: Stefan Holmer <stefan@webrtc.org>
> > Reviewed-by: Danil Chapovalov <danilchap@webrtc.org>
> > Commit-Queue: Philip Eliasson <philipel@webrtc.org>
> > Cr-Commit-Position: refs/heads/master@{#24626}
>
> TBR=danilchap@webrtc.org,nisse@webrtc.org,sprang@webrtc.org,stefan@webrtc.org,philipel@webrtc.org,holmer@google.com
>
> Change-Id: I3f7f19c0ea810c0fd988c59e6556bbea9b756b33
> No-Presubmit: true
> No-Tree-Checks: true
> No-Try: true
> Bug: none
> Reviewed-on: https://webrtc-review.googlesource.com/98864
> Reviewed-by: Philip Eliasson <philipel@webrtc.org>
> Commit-Queue: Philip Eliasson <philipel@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#24628}
TBR=danilchap@webrtc.org,nisse@webrtc.org,sprang@webrtc.org,stefan@webrtc.org,philipel@webrtc.org,holmer@google.com
Change-Id: I9246f36e638108ae4fc46c1ae4559c8205d50fc1
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: none
Reviewed-on: https://webrtc-review.googlesource.com/98841
Reviewed-by: Philip Eliasson <philipel@webrtc.org>
Commit-Queue: Philip Eliasson <philipel@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#24629}
2018-09-07 13:03:55 +00:00
|
|
|
const auto& vp8_header =
|
|
|
|
|
absl::get<RTPVideoHeaderVP8>(header.video_type_header);
|
|
|
|
|
EXPECT_EQ(kPictureId + 2, vp8_header.pictureId);
|
|
|
|
|
EXPECT_EQ(kTemporalIdx, vp8_header.temporalIdx);
|
|
|
|
|
EXPECT_EQ(kTl0PicIdx + 1, vp8_header.tl0PicIdx);
|
|
|
|
|
EXPECT_EQ(kNoKeyIdx, vp8_header.keyIdx);
|
|
|
|
|
EXPECT_TRUE(vp8_header.layerSync);
|
|
|
|
|
EXPECT_TRUE(vp8_header.nonReference);
|
2018-07-17 10:16:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST(RtpPayloadParamsTest, InfoMappedToRtpVideoHeader_Vp9) {
|
|
|
|
|
RtpPayloadState state;
|
|
|
|
|
state.picture_id = kPictureId;
|
|
|
|
|
state.tl0_pic_idx = kTl0PicIdx;
|
2020-04-18 14:36:59 +02:00
|
|
|
RtpPayloadParams params(kSsrc1, &state, FieldTrialBasedConfig());
|
2018-07-17 10:16:41 +02:00
|
|
|
|
|
|
|
|
EncodedImage encoded_image;
|
|
|
|
|
encoded_image.rotation_ = kVideoRotation_90;
|
|
|
|
|
encoded_image.content_type_ = VideoContentType::SCREENSHARE;
|
2018-08-27 15:33:42 +02:00
|
|
|
encoded_image.SetSpatialIndex(0);
|
2018-07-17 10:16:41 +02:00
|
|
|
CodecSpecificInfo codec_info;
|
|
|
|
|
codec_info.codecType = kVideoCodecVP9;
|
|
|
|
|
codec_info.codecSpecific.VP9.num_spatial_layers = 3;
|
|
|
|
|
codec_info.codecSpecific.VP9.first_frame_in_picture = true;
|
|
|
|
|
codec_info.codecSpecific.VP9.temporal_idx = 2;
|
2020-11-11 12:42:56 +01:00
|
|
|
codec_info.end_of_picture = false;
|
2018-07-17 10:16:41 +02:00
|
|
|
|
2018-08-27 14:33:18 +02:00
|
|
|
RTPVideoHeader header =
|
|
|
|
|
params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
|
2018-07-17 10:16:41 +02:00
|
|
|
|
|
|
|
|
EXPECT_EQ(kVideoRotation_90, header.rotation);
|
|
|
|
|
EXPECT_EQ(VideoContentType::SCREENSHARE, header.content_type);
|
|
|
|
|
EXPECT_EQ(kVideoCodecVP9, header.codec);
|
2018-12-03 14:18:53 +01:00
|
|
|
EXPECT_FALSE(header.color_space);
|
2018-08-08 14:26:00 +02:00
|
|
|
const auto& vp9_header =
|
|
|
|
|
absl::get<RTPVideoHeaderVP9>(header.video_type_header);
|
|
|
|
|
EXPECT_EQ(kPictureId + 1, vp9_header.picture_id);
|
|
|
|
|
EXPECT_EQ(kTl0PicIdx, vp9_header.tl0_pic_idx);
|
|
|
|
|
EXPECT_EQ(vp9_header.temporal_idx, codec_info.codecSpecific.VP9.temporal_idx);
|
2018-08-27 15:33:42 +02:00
|
|
|
EXPECT_EQ(vp9_header.spatial_idx, encoded_image.SpatialIndex());
|
2018-08-08 14:26:00 +02:00
|
|
|
EXPECT_EQ(vp9_header.num_spatial_layers,
|
2018-07-17 10:16:41 +02:00
|
|
|
codec_info.codecSpecific.VP9.num_spatial_layers);
|
2020-11-11 12:42:56 +01:00
|
|
|
EXPECT_EQ(vp9_header.end_of_picture, codec_info.end_of_picture);
|
2018-07-17 10:16:41 +02:00
|
|
|
|
|
|
|
|
// Next spatial layer.
|
|
|
|
|
codec_info.codecSpecific.VP9.first_frame_in_picture = false;
|
2020-11-11 12:42:56 +01:00
|
|
|
codec_info.end_of_picture = true;
|
2018-07-17 10:16:41 +02:00
|
|
|
|
2018-08-27 15:33:42 +02:00
|
|
|
encoded_image.SetSpatialIndex(1);
|
2018-12-03 14:18:53 +01:00
|
|
|
ColorSpace color_space(
|
|
|
|
|
ColorSpace::PrimaryID::kSMPTE170M, ColorSpace::TransferID::kSMPTE170M,
|
|
|
|
|
ColorSpace::MatrixID::kSMPTE170M, ColorSpace::RangeID::kFull);
|
2019-02-05 11:32:19 +01:00
|
|
|
encoded_image.SetColorSpace(color_space);
|
2018-08-27 14:33:18 +02:00
|
|
|
header = params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
|
2018-07-17 10:16:41 +02:00
|
|
|
|
|
|
|
|
EXPECT_EQ(kVideoRotation_90, header.rotation);
|
|
|
|
|
EXPECT_EQ(VideoContentType::SCREENSHARE, header.content_type);
|
|
|
|
|
EXPECT_EQ(kVideoCodecVP9, header.codec);
|
2018-12-03 14:18:53 +01:00
|
|
|
EXPECT_EQ(absl::make_optional(color_space), header.color_space);
|
2018-08-08 14:26:00 +02:00
|
|
|
EXPECT_EQ(kPictureId + 1, vp9_header.picture_id);
|
|
|
|
|
EXPECT_EQ(kTl0PicIdx, vp9_header.tl0_pic_idx);
|
|
|
|
|
EXPECT_EQ(vp9_header.temporal_idx, codec_info.codecSpecific.VP9.temporal_idx);
|
2018-08-27 15:33:42 +02:00
|
|
|
EXPECT_EQ(vp9_header.spatial_idx, encoded_image.SpatialIndex());
|
2018-08-08 14:26:00 +02:00
|
|
|
EXPECT_EQ(vp9_header.num_spatial_layers,
|
2018-07-17 10:16:41 +02:00
|
|
|
codec_info.codecSpecific.VP9.num_spatial_layers);
|
2020-11-11 12:42:56 +01:00
|
|
|
EXPECT_EQ(vp9_header.end_of_picture, codec_info.end_of_picture);
|
2018-07-17 10:16:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST(RtpPayloadParamsTest, PictureIdIsSetForVp8) {
|
|
|
|
|
RtpPayloadState state;
|
|
|
|
|
state.picture_id = kInitialPictureId1;
|
|
|
|
|
state.tl0_pic_idx = kInitialTl0PicIdx1;
|
|
|
|
|
|
|
|
|
|
EncodedImage encoded_image;
|
|
|
|
|
CodecSpecificInfo codec_info;
|
|
|
|
|
codec_info.codecType = kVideoCodecVP8;
|
|
|
|
|
|
2020-04-18 14:36:59 +02:00
|
|
|
RtpPayloadParams params(kSsrc1, &state, FieldTrialBasedConfig());
|
2018-08-27 14:33:18 +02:00
|
|
|
RTPVideoHeader header =
|
|
|
|
|
params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
|
2018-07-17 10:16:41 +02:00
|
|
|
EXPECT_EQ(kVideoCodecVP8, header.codec);
|
Reland "Remove RTPVideoHeader::vp8() accessors."
This reverts commit 1811c04f22a26da3ed2832373a5c92a9786420c3.
Reason for revert: Downstream projects fixed.
Original change's description:
> Revert "Remove RTPVideoHeader::vp8() accessors."
>
> This reverts commit af7afc66427b0e9109e7d492f2805d63d239b914.
>
> Reason for revert: Break downstream projects.
>
> Original change's description:
> > Remove RTPVideoHeader::vp8() accessors.
> >
> > Bug: none
> > Change-Id: Ia7d65148fb36a8f26647bee8a876ce7217ff8a68
> > Reviewed-on: https://webrtc-review.googlesource.com/93321
> > Reviewed-by: Niels Moller <nisse@webrtc.org>
> > Reviewed-by: Stefan Holmer <stefan@webrtc.org>
> > Reviewed-by: Danil Chapovalov <danilchap@webrtc.org>
> > Commit-Queue: Philip Eliasson <philipel@webrtc.org>
> > Cr-Commit-Position: refs/heads/master@{#24626}
>
> TBR=danilchap@webrtc.org,nisse@webrtc.org,sprang@webrtc.org,stefan@webrtc.org,philipel@webrtc.org,holmer@google.com
>
> Change-Id: I3f7f19c0ea810c0fd988c59e6556bbea9b756b33
> No-Presubmit: true
> No-Tree-Checks: true
> No-Try: true
> Bug: none
> Reviewed-on: https://webrtc-review.googlesource.com/98864
> Reviewed-by: Philip Eliasson <philipel@webrtc.org>
> Commit-Queue: Philip Eliasson <philipel@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#24628}
TBR=danilchap@webrtc.org,nisse@webrtc.org,sprang@webrtc.org,stefan@webrtc.org,philipel@webrtc.org,holmer@google.com
Change-Id: I9246f36e638108ae4fc46c1ae4559c8205d50fc1
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: none
Reviewed-on: https://webrtc-review.googlesource.com/98841
Reviewed-by: Philip Eliasson <philipel@webrtc.org>
Commit-Queue: Philip Eliasson <philipel@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#24629}
2018-09-07 13:03:55 +00:00
|
|
|
EXPECT_EQ(kInitialPictureId1 + 1,
|
|
|
|
|
absl::get<RTPVideoHeaderVP8>(header.video_type_header).pictureId);
|
2018-07-17 10:16:41 +02:00
|
|
|
|
|
|
|
|
// State should hold latest used picture id and tl0_pic_idx.
|
|
|
|
|
state = params.state();
|
|
|
|
|
EXPECT_EQ(kInitialPictureId1 + 1, state.picture_id);
|
|
|
|
|
EXPECT_EQ(kInitialTl0PicIdx1 + 1, state.tl0_pic_idx);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST(RtpPayloadParamsTest, PictureIdWraps) {
|
|
|
|
|
RtpPayloadState state;
|
|
|
|
|
state.picture_id = kMaxTwoBytePictureId;
|
|
|
|
|
state.tl0_pic_idx = kInitialTl0PicIdx1;
|
|
|
|
|
|
|
|
|
|
EncodedImage encoded_image;
|
|
|
|
|
CodecSpecificInfo codec_info;
|
|
|
|
|
codec_info.codecType = kVideoCodecVP8;
|
|
|
|
|
codec_info.codecSpecific.VP8.temporalIdx = kNoTemporalIdx;
|
|
|
|
|
|
2020-04-18 14:36:59 +02:00
|
|
|
RtpPayloadParams params(kSsrc1, &state, FieldTrialBasedConfig());
|
2018-08-27 14:33:18 +02:00
|
|
|
RTPVideoHeader header =
|
|
|
|
|
params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
|
2018-07-17 10:16:41 +02:00
|
|
|
EXPECT_EQ(kVideoCodecVP8, header.codec);
|
Reland "Remove RTPVideoHeader::vp8() accessors."
This reverts commit 1811c04f22a26da3ed2832373a5c92a9786420c3.
Reason for revert: Downstream projects fixed.
Original change's description:
> Revert "Remove RTPVideoHeader::vp8() accessors."
>
> This reverts commit af7afc66427b0e9109e7d492f2805d63d239b914.
>
> Reason for revert: Break downstream projects.
>
> Original change's description:
> > Remove RTPVideoHeader::vp8() accessors.
> >
> > Bug: none
> > Change-Id: Ia7d65148fb36a8f26647bee8a876ce7217ff8a68
> > Reviewed-on: https://webrtc-review.googlesource.com/93321
> > Reviewed-by: Niels Moller <nisse@webrtc.org>
> > Reviewed-by: Stefan Holmer <stefan@webrtc.org>
> > Reviewed-by: Danil Chapovalov <danilchap@webrtc.org>
> > Commit-Queue: Philip Eliasson <philipel@webrtc.org>
> > Cr-Commit-Position: refs/heads/master@{#24626}
>
> TBR=danilchap@webrtc.org,nisse@webrtc.org,sprang@webrtc.org,stefan@webrtc.org,philipel@webrtc.org,holmer@google.com
>
> Change-Id: I3f7f19c0ea810c0fd988c59e6556bbea9b756b33
> No-Presubmit: true
> No-Tree-Checks: true
> No-Try: true
> Bug: none
> Reviewed-on: https://webrtc-review.googlesource.com/98864
> Reviewed-by: Philip Eliasson <philipel@webrtc.org>
> Commit-Queue: Philip Eliasson <philipel@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#24628}
TBR=danilchap@webrtc.org,nisse@webrtc.org,sprang@webrtc.org,stefan@webrtc.org,philipel@webrtc.org,holmer@google.com
Change-Id: I9246f36e638108ae4fc46c1ae4559c8205d50fc1
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: none
Reviewed-on: https://webrtc-review.googlesource.com/98841
Reviewed-by: Philip Eliasson <philipel@webrtc.org>
Commit-Queue: Philip Eliasson <philipel@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#24629}
2018-09-07 13:03:55 +00:00
|
|
|
EXPECT_EQ(0,
|
|
|
|
|
absl::get<RTPVideoHeaderVP8>(header.video_type_header).pictureId);
|
2018-07-17 10:16:41 +02:00
|
|
|
|
|
|
|
|
// State should hold latest used picture id and tl0_pic_idx.
|
|
|
|
|
EXPECT_EQ(0, params.state().picture_id); // Wrapped.
|
|
|
|
|
EXPECT_EQ(kInitialTl0PicIdx1, params.state().tl0_pic_idx);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST(RtpPayloadParamsTest, Tl0PicIdxUpdatedForVp8) {
|
|
|
|
|
RtpPayloadState state;
|
|
|
|
|
state.picture_id = kInitialPictureId1;
|
|
|
|
|
state.tl0_pic_idx = kInitialTl0PicIdx1;
|
|
|
|
|
|
|
|
|
|
EncodedImage encoded_image;
|
|
|
|
|
// Modules are sending for this test.
|
|
|
|
|
// OnEncodedImage, temporalIdx: 1.
|
|
|
|
|
CodecSpecificInfo codec_info;
|
|
|
|
|
codec_info.codecType = kVideoCodecVP8;
|
|
|
|
|
codec_info.codecSpecific.VP8.temporalIdx = 1;
|
|
|
|
|
|
2020-04-18 14:36:59 +02:00
|
|
|
RtpPayloadParams params(kSsrc1, &state, FieldTrialBasedConfig());
|
2018-08-27 14:33:18 +02:00
|
|
|
RTPVideoHeader header =
|
|
|
|
|
params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
|
2018-07-17 10:16:41 +02:00
|
|
|
|
|
|
|
|
EXPECT_EQ(kVideoCodecVP8, header.codec);
|
Reland "Remove RTPVideoHeader::vp8() accessors."
This reverts commit 1811c04f22a26da3ed2832373a5c92a9786420c3.
Reason for revert: Downstream projects fixed.
Original change's description:
> Revert "Remove RTPVideoHeader::vp8() accessors."
>
> This reverts commit af7afc66427b0e9109e7d492f2805d63d239b914.
>
> Reason for revert: Break downstream projects.
>
> Original change's description:
> > Remove RTPVideoHeader::vp8() accessors.
> >
> > Bug: none
> > Change-Id: Ia7d65148fb36a8f26647bee8a876ce7217ff8a68
> > Reviewed-on: https://webrtc-review.googlesource.com/93321
> > Reviewed-by: Niels Moller <nisse@webrtc.org>
> > Reviewed-by: Stefan Holmer <stefan@webrtc.org>
> > Reviewed-by: Danil Chapovalov <danilchap@webrtc.org>
> > Commit-Queue: Philip Eliasson <philipel@webrtc.org>
> > Cr-Commit-Position: refs/heads/master@{#24626}
>
> TBR=danilchap@webrtc.org,nisse@webrtc.org,sprang@webrtc.org,stefan@webrtc.org,philipel@webrtc.org,holmer@google.com
>
> Change-Id: I3f7f19c0ea810c0fd988c59e6556bbea9b756b33
> No-Presubmit: true
> No-Tree-Checks: true
> No-Try: true
> Bug: none
> Reviewed-on: https://webrtc-review.googlesource.com/98864
> Reviewed-by: Philip Eliasson <philipel@webrtc.org>
> Commit-Queue: Philip Eliasson <philipel@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#24628}
TBR=danilchap@webrtc.org,nisse@webrtc.org,sprang@webrtc.org,stefan@webrtc.org,philipel@webrtc.org,holmer@google.com
Change-Id: I9246f36e638108ae4fc46c1ae4559c8205d50fc1
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: none
Reviewed-on: https://webrtc-review.googlesource.com/98841
Reviewed-by: Philip Eliasson <philipel@webrtc.org>
Commit-Queue: Philip Eliasson <philipel@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#24629}
2018-09-07 13:03:55 +00:00
|
|
|
const auto& vp8_header =
|
|
|
|
|
absl::get<RTPVideoHeaderVP8>(header.video_type_header);
|
|
|
|
|
EXPECT_EQ(kInitialPictureId1 + 1, vp8_header.pictureId);
|
|
|
|
|
EXPECT_EQ(kInitialTl0PicIdx1, vp8_header.tl0PicIdx);
|
2018-07-17 10:16:41 +02:00
|
|
|
|
|
|
|
|
// OnEncodedImage, temporalIdx: 0.
|
|
|
|
|
codec_info.codecSpecific.VP8.temporalIdx = 0;
|
|
|
|
|
|
2018-08-27 14:33:18 +02:00
|
|
|
header = params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
|
2018-07-17 10:16:41 +02:00
|
|
|
EXPECT_EQ(kVideoCodecVP8, header.codec);
|
Reland "Remove RTPVideoHeader::vp8() accessors."
This reverts commit 1811c04f22a26da3ed2832373a5c92a9786420c3.
Reason for revert: Downstream projects fixed.
Original change's description:
> Revert "Remove RTPVideoHeader::vp8() accessors."
>
> This reverts commit af7afc66427b0e9109e7d492f2805d63d239b914.
>
> Reason for revert: Break downstream projects.
>
> Original change's description:
> > Remove RTPVideoHeader::vp8() accessors.
> >
> > Bug: none
> > Change-Id: Ia7d65148fb36a8f26647bee8a876ce7217ff8a68
> > Reviewed-on: https://webrtc-review.googlesource.com/93321
> > Reviewed-by: Niels Moller <nisse@webrtc.org>
> > Reviewed-by: Stefan Holmer <stefan@webrtc.org>
> > Reviewed-by: Danil Chapovalov <danilchap@webrtc.org>
> > Commit-Queue: Philip Eliasson <philipel@webrtc.org>
> > Cr-Commit-Position: refs/heads/master@{#24626}
>
> TBR=danilchap@webrtc.org,nisse@webrtc.org,sprang@webrtc.org,stefan@webrtc.org,philipel@webrtc.org,holmer@google.com
>
> Change-Id: I3f7f19c0ea810c0fd988c59e6556bbea9b756b33
> No-Presubmit: true
> No-Tree-Checks: true
> No-Try: true
> Bug: none
> Reviewed-on: https://webrtc-review.googlesource.com/98864
> Reviewed-by: Philip Eliasson <philipel@webrtc.org>
> Commit-Queue: Philip Eliasson <philipel@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#24628}
TBR=danilchap@webrtc.org,nisse@webrtc.org,sprang@webrtc.org,stefan@webrtc.org,philipel@webrtc.org,holmer@google.com
Change-Id: I9246f36e638108ae4fc46c1ae4559c8205d50fc1
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: none
Reviewed-on: https://webrtc-review.googlesource.com/98841
Reviewed-by: Philip Eliasson <philipel@webrtc.org>
Commit-Queue: Philip Eliasson <philipel@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#24629}
2018-09-07 13:03:55 +00:00
|
|
|
EXPECT_EQ(kInitialPictureId1 + 2, vp8_header.pictureId);
|
|
|
|
|
EXPECT_EQ(kInitialTl0PicIdx1 + 1, vp8_header.tl0PicIdx);
|
2018-07-17 10:16:41 +02:00
|
|
|
|
|
|
|
|
// State should hold latest used picture id and tl0_pic_idx.
|
|
|
|
|
EXPECT_EQ(kInitialPictureId1 + 2, params.state().picture_id);
|
|
|
|
|
EXPECT_EQ(kInitialTl0PicIdx1 + 1, params.state().tl0_pic_idx);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST(RtpPayloadParamsTest, Tl0PicIdxUpdatedForVp9) {
|
|
|
|
|
RtpPayloadState state;
|
|
|
|
|
state.picture_id = kInitialPictureId1;
|
|
|
|
|
state.tl0_pic_idx = kInitialTl0PicIdx1;
|
|
|
|
|
|
|
|
|
|
EncodedImage encoded_image;
|
|
|
|
|
// Modules are sending for this test.
|
|
|
|
|
// OnEncodedImage, temporalIdx: 1.
|
|
|
|
|
CodecSpecificInfo codec_info;
|
|
|
|
|
codec_info.codecType = kVideoCodecVP9;
|
|
|
|
|
codec_info.codecSpecific.VP9.temporal_idx = 1;
|
|
|
|
|
codec_info.codecSpecific.VP9.first_frame_in_picture = true;
|
|
|
|
|
|
2020-04-18 14:36:59 +02:00
|
|
|
RtpPayloadParams params(kSsrc1, &state, FieldTrialBasedConfig());
|
2018-08-27 14:33:18 +02:00
|
|
|
RTPVideoHeader header =
|
|
|
|
|
params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
|
2018-07-17 10:16:41 +02:00
|
|
|
|
|
|
|
|
EXPECT_EQ(kVideoCodecVP9, header.codec);
|
2018-08-08 14:26:00 +02:00
|
|
|
const auto& vp9_header =
|
|
|
|
|
absl::get<RTPVideoHeaderVP9>(header.video_type_header);
|
|
|
|
|
EXPECT_EQ(kInitialPictureId1 + 1, vp9_header.picture_id);
|
|
|
|
|
EXPECT_EQ(kInitialTl0PicIdx1, vp9_header.tl0_pic_idx);
|
2018-07-17 10:16:41 +02:00
|
|
|
|
|
|
|
|
// OnEncodedImage, temporalIdx: 0.
|
|
|
|
|
codec_info.codecSpecific.VP9.temporal_idx = 0;
|
|
|
|
|
|
2018-08-27 14:33:18 +02:00
|
|
|
header = params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
|
2018-07-17 10:16:41 +02:00
|
|
|
|
|
|
|
|
EXPECT_EQ(kVideoCodecVP9, header.codec);
|
2018-08-08 14:26:00 +02:00
|
|
|
EXPECT_EQ(kInitialPictureId1 + 2, vp9_header.picture_id);
|
|
|
|
|
EXPECT_EQ(kInitialTl0PicIdx1 + 1, vp9_header.tl0_pic_idx);
|
2018-07-17 10:16:41 +02:00
|
|
|
|
|
|
|
|
// OnEncodedImage, first_frame_in_picture = false
|
|
|
|
|
codec_info.codecSpecific.VP9.first_frame_in_picture = false;
|
|
|
|
|
|
2018-08-27 14:33:18 +02:00
|
|
|
header = params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
|
2018-07-17 10:16:41 +02:00
|
|
|
|
|
|
|
|
EXPECT_EQ(kVideoCodecVP9, header.codec);
|
2018-08-08 14:26:00 +02:00
|
|
|
EXPECT_EQ(kInitialPictureId1 + 2, vp9_header.picture_id);
|
|
|
|
|
EXPECT_EQ(kInitialTl0PicIdx1 + 1, vp9_header.tl0_pic_idx);
|
2018-07-17 10:16:41 +02:00
|
|
|
|
|
|
|
|
// State should hold latest used picture id and tl0_pic_idx.
|
|
|
|
|
EXPECT_EQ(kInitialPictureId1 + 2, params.state().picture_id);
|
|
|
|
|
EXPECT_EQ(kInitialTl0PicIdx1 + 1, params.state().tl0_pic_idx);
|
|
|
|
|
}
|
2018-08-27 14:33:18 +02:00
|
|
|
|
|
|
|
|
TEST(RtpPayloadParamsTest, PictureIdForOldGenericFormat) {
|
2022-03-09 15:12:07 +01:00
|
|
|
test::ScopedKeyValueConfig field_trials("WebRTC-GenericPictureId/Enabled/");
|
2018-08-27 14:33:18 +02:00
|
|
|
RtpPayloadState state{};
|
|
|
|
|
|
|
|
|
|
EncodedImage encoded_image;
|
2019-03-01 13:53:55 +01:00
|
|
|
CodecSpecificInfo codec_info;
|
2018-08-27 14:33:18 +02:00
|
|
|
codec_info.codecType = kVideoCodecGeneric;
|
2020-02-17 20:03:57 +01:00
|
|
|
encoded_image._frameType = VideoFrameType::kVideoFrameKey;
|
2018-08-27 14:33:18 +02:00
|
|
|
|
2022-03-09 15:12:07 +01:00
|
|
|
RtpPayloadParams params(kSsrc1, &state, field_trials);
|
2018-08-27 14:33:18 +02:00
|
|
|
RTPVideoHeader header =
|
2020-02-17 20:03:57 +01:00
|
|
|
params.GetRtpVideoHeader(encoded_image, &codec_info, 10);
|
2018-08-27 14:33:18 +02:00
|
|
|
|
|
|
|
|
EXPECT_EQ(kVideoCodecGeneric, header.codec);
|
2020-01-28 18:36:57 +01:00
|
|
|
const auto* generic =
|
|
|
|
|
absl::get_if<RTPVideoHeaderLegacyGeneric>(&header.video_type_header);
|
|
|
|
|
ASSERT_TRUE(generic);
|
|
|
|
|
EXPECT_EQ(0, generic->picture_id);
|
2018-08-27 14:33:18 +02:00
|
|
|
|
2020-02-17 20:03:57 +01:00
|
|
|
encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
|
|
|
|
|
header = params.GetRtpVideoHeader(encoded_image, &codec_info, 20);
|
2020-01-28 18:36:57 +01:00
|
|
|
generic =
|
|
|
|
|
absl::get_if<RTPVideoHeaderLegacyGeneric>(&header.video_type_header);
|
|
|
|
|
ASSERT_TRUE(generic);
|
|
|
|
|
EXPECT_EQ(1, generic->picture_id);
|
2018-08-27 14:33:18 +02:00
|
|
|
}
|
|
|
|
|
|
2019-06-13 15:13:16 +02:00
|
|
|
TEST(RtpPayloadParamsTest, GenericDescriptorForGenericCodec) {
|
2021-09-01 15:21:16 +02:00
|
|
|
RtpPayloadState state;
|
2019-06-13 15:13:16 +02:00
|
|
|
|
|
|
|
|
EncodedImage encoded_image;
|
|
|
|
|
encoded_image._frameType = VideoFrameType::kVideoFrameKey;
|
|
|
|
|
CodecSpecificInfo codec_info;
|
|
|
|
|
codec_info.codecType = kVideoCodecGeneric;
|
|
|
|
|
|
2020-04-18 14:36:59 +02:00
|
|
|
RtpPayloadParams params(kSsrc1, &state, FieldTrialBasedConfig());
|
2019-06-13 15:13:16 +02:00
|
|
|
RTPVideoHeader header =
|
|
|
|
|
params.GetRtpVideoHeader(encoded_image, &codec_info, 0);
|
|
|
|
|
|
2021-09-01 15:21:16 +02:00
|
|
|
EXPECT_THAT(header.codec, Eq(kVideoCodecGeneric));
|
|
|
|
|
|
2019-06-13 15:13:16 +02:00
|
|
|
ASSERT_TRUE(header.generic);
|
2021-09-01 15:21:16 +02:00
|
|
|
EXPECT_THAT(header.generic->frame_id, Eq(0));
|
|
|
|
|
EXPECT_THAT(header.generic->spatial_index, Eq(0));
|
|
|
|
|
EXPECT_THAT(header.generic->temporal_index, Eq(0));
|
|
|
|
|
EXPECT_THAT(header.generic->decode_target_indications,
|
|
|
|
|
ElementsAre(DecodeTargetIndication::kSwitch));
|
2019-06-13 15:13:16 +02:00
|
|
|
EXPECT_THAT(header.generic->dependencies, IsEmpty());
|
2021-09-01 15:21:16 +02:00
|
|
|
EXPECT_THAT(header.generic->chain_diffs, ElementsAre(0));
|
2019-06-13 15:13:16 +02:00
|
|
|
|
|
|
|
|
encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
|
2021-09-01 15:21:16 +02:00
|
|
|
header = params.GetRtpVideoHeader(encoded_image, &codec_info, 3);
|
2019-06-13 15:13:16 +02:00
|
|
|
ASSERT_TRUE(header.generic);
|
2021-09-01 15:21:16 +02:00
|
|
|
EXPECT_THAT(header.generic->frame_id, Eq(3));
|
|
|
|
|
EXPECT_THAT(header.generic->spatial_index, Eq(0));
|
|
|
|
|
EXPECT_THAT(header.generic->temporal_index, Eq(0));
|
2019-06-13 15:13:16 +02:00
|
|
|
EXPECT_THAT(header.generic->dependencies, ElementsAre(0));
|
2021-09-01 15:21:16 +02:00
|
|
|
EXPECT_THAT(header.generic->decode_target_indications,
|
|
|
|
|
ElementsAre(DecodeTargetIndication::kSwitch));
|
|
|
|
|
EXPECT_THAT(header.generic->chain_diffs, ElementsAre(3));
|
2019-06-13 15:13:16 +02:00
|
|
|
}
|
|
|
|
|
|
2020-02-10 16:22:57 +01:00
|
|
|
TEST(RtpPayloadParamsTest, SetsGenericFromGenericFrameInfo) {
|
|
|
|
|
RtpPayloadState state;
|
|
|
|
|
EncodedImage encoded_image;
|
|
|
|
|
CodecSpecificInfo codec_info;
|
|
|
|
|
|
2020-04-18 14:36:59 +02:00
|
|
|
RtpPayloadParams params(kSsrc1, &state, FieldTrialBasedConfig());
|
2020-02-10 16:22:57 +01:00
|
|
|
|
|
|
|
|
encoded_image._frameType = VideoFrameType::kVideoFrameKey;
|
|
|
|
|
codec_info.generic_frame_info =
|
|
|
|
|
GenericFrameInfo::Builder().S(1).T(0).Dtis("S").Build();
|
|
|
|
|
codec_info.generic_frame_info->encoder_buffers = {
|
|
|
|
|
{/*id=*/0, /*referenced=*/false, /*updated=*/true}};
|
2020-05-19 14:48:19 +02:00
|
|
|
codec_info.generic_frame_info->part_of_chain = {true, false};
|
2020-02-10 16:22:57 +01:00
|
|
|
RTPVideoHeader key_header =
|
|
|
|
|
params.GetRtpVideoHeader(encoded_image, &codec_info, /*frame_id=*/1);
|
|
|
|
|
|
|
|
|
|
ASSERT_TRUE(key_header.generic);
|
|
|
|
|
EXPECT_EQ(key_header.generic->spatial_index, 1);
|
|
|
|
|
EXPECT_EQ(key_header.generic->temporal_index, 0);
|
|
|
|
|
EXPECT_EQ(key_header.generic->frame_id, 1);
|
|
|
|
|
EXPECT_THAT(key_header.generic->dependencies, IsEmpty());
|
|
|
|
|
EXPECT_THAT(key_header.generic->decode_target_indications,
|
|
|
|
|
ElementsAre(DecodeTargetIndication::kSwitch));
|
2020-05-19 14:48:19 +02:00
|
|
|
EXPECT_THAT(key_header.generic->chain_diffs, SizeIs(2));
|
2020-02-10 16:22:57 +01:00
|
|
|
|
|
|
|
|
encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
|
|
|
|
|
codec_info.generic_frame_info =
|
|
|
|
|
GenericFrameInfo::Builder().S(2).T(3).Dtis("D").Build();
|
|
|
|
|
codec_info.generic_frame_info->encoder_buffers = {
|
|
|
|
|
{/*id=*/0, /*referenced=*/true, /*updated=*/false}};
|
2020-05-19 14:48:19 +02:00
|
|
|
codec_info.generic_frame_info->part_of_chain = {false, false};
|
2020-02-10 16:22:57 +01:00
|
|
|
RTPVideoHeader delta_header =
|
|
|
|
|
params.GetRtpVideoHeader(encoded_image, &codec_info, /*frame_id=*/3);
|
|
|
|
|
|
|
|
|
|
ASSERT_TRUE(delta_header.generic);
|
|
|
|
|
EXPECT_EQ(delta_header.generic->spatial_index, 2);
|
|
|
|
|
EXPECT_EQ(delta_header.generic->temporal_index, 3);
|
|
|
|
|
EXPECT_EQ(delta_header.generic->frame_id, 3);
|
|
|
|
|
EXPECT_THAT(delta_header.generic->dependencies, ElementsAre(1));
|
|
|
|
|
EXPECT_THAT(delta_header.generic->decode_target_indications,
|
|
|
|
|
ElementsAre(DecodeTargetIndication::kDiscardable));
|
2020-05-19 14:48:19 +02:00
|
|
|
EXPECT_THAT(delta_header.generic->chain_diffs, SizeIs(2));
|
2020-02-10 16:22:57 +01:00
|
|
|
}
|
|
|
|
|
|
2018-08-27 14:33:18 +02:00
|
|
|
class RtpPayloadParamsVp8ToGenericTest : public ::testing::Test {
|
|
|
|
|
public:
|
|
|
|
|
enum LayerSync { kNoSync, kSync };
|
|
|
|
|
|
2018-09-26 12:25:31 +02:00
|
|
|
RtpPayloadParamsVp8ToGenericTest()
|
2020-06-03 14:11:26 +02:00
|
|
|
: state_(), params_(123, &state_, trials_config_) {}
|
2018-08-27 14:33:18 +02:00
|
|
|
|
|
|
|
|
void ConvertAndCheck(int temporal_index,
|
|
|
|
|
int64_t shared_frame_id,
|
2020-01-07 19:16:33 +00:00
|
|
|
VideoFrameType frame_type,
|
2018-08-27 14:33:18 +02:00
|
|
|
LayerSync layer_sync,
|
2018-10-17 14:36:08 +02:00
|
|
|
const std::set<int64_t>& expected_deps,
|
|
|
|
|
uint16_t width = 0,
|
|
|
|
|
uint16_t height = 0) {
|
2018-08-27 14:33:18 +02:00
|
|
|
EncodedImage encoded_image;
|
2020-01-07 19:16:33 +00:00
|
|
|
encoded_image._frameType = frame_type;
|
2018-10-17 14:36:08 +02:00
|
|
|
encoded_image._encodedWidth = width;
|
|
|
|
|
encoded_image._encodedHeight = height;
|
2018-08-27 14:33:18 +02:00
|
|
|
|
2019-03-01 13:53:55 +01:00
|
|
|
CodecSpecificInfo codec_info;
|
2018-08-27 14:33:18 +02:00
|
|
|
codec_info.codecType = kVideoCodecVP8;
|
2020-01-07 19:16:33 +00:00
|
|
|
codec_info.codecSpecific.VP8.temporalIdx = temporal_index;
|
|
|
|
|
codec_info.codecSpecific.VP8.layerSync = layer_sync == kSync;
|
2018-08-27 14:33:18 +02:00
|
|
|
|
|
|
|
|
RTPVideoHeader header =
|
|
|
|
|
params_.GetRtpVideoHeader(encoded_image, &codec_info, shared_frame_id);
|
|
|
|
|
|
|
|
|
|
ASSERT_TRUE(header.generic);
|
|
|
|
|
EXPECT_EQ(header.generic->spatial_index, 0);
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(header.generic->frame_id, shared_frame_id);
|
|
|
|
|
EXPECT_EQ(header.generic->temporal_index, temporal_index);
|
2020-01-07 19:16:33 +00:00
|
|
|
std::set<int64_t> actual_deps(header.generic->dependencies.begin(),
|
|
|
|
|
header.generic->dependencies.end());
|
|
|
|
|
EXPECT_EQ(expected_deps, actual_deps);
|
2018-10-17 14:36:08 +02:00
|
|
|
|
|
|
|
|
EXPECT_EQ(header.width, width);
|
|
|
|
|
EXPECT_EQ(header.height, height);
|
2018-08-27 14:33:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected:
|
2020-04-18 14:36:59 +02:00
|
|
|
FieldTrialBasedConfig trials_config_;
|
2018-08-27 14:33:18 +02:00
|
|
|
RtpPayloadState state_;
|
|
|
|
|
RtpPayloadParams params_;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
TEST_F(RtpPayloadParamsVp8ToGenericTest, Keyframe) {
|
2020-01-07 19:16:33 +00:00
|
|
|
ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
|
|
|
|
|
ConvertAndCheck(0, 1, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
|
|
|
|
|
ConvertAndCheck(0, 2, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
|
2018-08-27 14:33:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(RtpPayloadParamsVp8ToGenericTest, TooHighTemporalIndex) {
|
2020-01-07 19:16:33 +00:00
|
|
|
ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
|
2018-08-27 14:33:18 +02:00
|
|
|
|
|
|
|
|
EncodedImage encoded_image;
|
2019-03-21 15:43:58 +01:00
|
|
|
encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
|
2019-03-01 13:53:55 +01:00
|
|
|
CodecSpecificInfo codec_info;
|
2018-08-27 14:33:18 +02:00
|
|
|
codec_info.codecType = kVideoCodecVP8;
|
|
|
|
|
codec_info.codecSpecific.VP8.temporalIdx =
|
|
|
|
|
RtpGenericFrameDescriptor::kMaxTemporalLayers;
|
|
|
|
|
codec_info.codecSpecific.VP8.layerSync = false;
|
|
|
|
|
|
|
|
|
|
RTPVideoHeader header =
|
|
|
|
|
params_.GetRtpVideoHeader(encoded_image, &codec_info, 1);
|
|
|
|
|
EXPECT_FALSE(header.generic);
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-07 19:16:33 +00:00
|
|
|
TEST_F(RtpPayloadParamsVp8ToGenericTest, LayerSync) {
|
|
|
|
|
// 02120212 pattern
|
|
|
|
|
ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
|
|
|
|
|
ConvertAndCheck(2, 1, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
|
|
|
|
|
ConvertAndCheck(1, 2, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
|
|
|
|
|
ConvertAndCheck(2, 3, VideoFrameType::kVideoFrameDelta, kNoSync, {0, 1, 2});
|
|
|
|
|
|
|
|
|
|
ConvertAndCheck(0, 4, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
|
|
|
|
|
ConvertAndCheck(2, 5, VideoFrameType::kVideoFrameDelta, kNoSync, {2, 3, 4});
|
|
|
|
|
ConvertAndCheck(1, 6, VideoFrameType::kVideoFrameDelta, kSync,
|
|
|
|
|
{4}); // layer sync
|
|
|
|
|
ConvertAndCheck(2, 7, VideoFrameType::kVideoFrameDelta, kNoSync, {4, 5, 6});
|
2018-08-27 14:33:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(RtpPayloadParamsVp8ToGenericTest, FrameIdGaps) {
|
|
|
|
|
// 0101 pattern
|
2020-01-07 19:16:33 +00:00
|
|
|
ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
|
|
|
|
|
ConvertAndCheck(1, 1, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
|
2018-08-27 14:33:18 +02:00
|
|
|
|
2020-01-07 19:16:33 +00:00
|
|
|
ConvertAndCheck(0, 5, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
|
|
|
|
|
ConvertAndCheck(1, 10, VideoFrameType::kVideoFrameDelta, kNoSync, {1, 5});
|
2018-08-27 14:33:18 +02:00
|
|
|
|
2020-01-07 19:16:33 +00:00
|
|
|
ConvertAndCheck(0, 15, VideoFrameType::kVideoFrameDelta, kNoSync, {5});
|
|
|
|
|
ConvertAndCheck(1, 20, VideoFrameType::kVideoFrameDelta, kNoSync, {10, 15});
|
2018-08-27 14:33:18 +02:00
|
|
|
}
|
|
|
|
|
|
2021-09-14 11:46:44 +02:00
|
|
|
TEST(RtpPayloadParamsVp9ToGenericTest, NoScalability) {
|
|
|
|
|
RtpPayloadState state;
|
|
|
|
|
RtpPayloadParams params(/*ssrc=*/123, &state, FieldTrialBasedConfig());
|
2021-04-22 15:20:28 +02:00
|
|
|
|
|
|
|
|
EncodedImage encoded_image;
|
|
|
|
|
CodecSpecificInfo codec_info;
|
|
|
|
|
codec_info.codecType = kVideoCodecVP9;
|
|
|
|
|
codec_info.codecSpecific.VP9.num_spatial_layers = 1;
|
|
|
|
|
codec_info.codecSpecific.VP9.temporal_idx = kNoTemporalIdx;
|
|
|
|
|
codec_info.codecSpecific.VP9.first_frame_in_picture = true;
|
|
|
|
|
codec_info.end_of_picture = true;
|
|
|
|
|
|
|
|
|
|
// Key frame.
|
|
|
|
|
encoded_image._frameType = VideoFrameType::kVideoFrameKey;
|
|
|
|
|
codec_info.codecSpecific.VP9.inter_pic_predicted = false;
|
|
|
|
|
codec_info.codecSpecific.VP9.num_ref_pics = 0;
|
|
|
|
|
RTPVideoHeader header = params.GetRtpVideoHeader(encoded_image, &codec_info,
|
|
|
|
|
/*shared_frame_id=*/1);
|
|
|
|
|
|
|
|
|
|
ASSERT_TRUE(header.generic);
|
|
|
|
|
EXPECT_EQ(header.generic->spatial_index, 0);
|
|
|
|
|
EXPECT_EQ(header.generic->temporal_index, 0);
|
|
|
|
|
EXPECT_EQ(header.generic->frame_id, 1);
|
|
|
|
|
ASSERT_THAT(header.generic->decode_target_indications, Not(IsEmpty()));
|
|
|
|
|
EXPECT_EQ(header.generic->decode_target_indications[0],
|
|
|
|
|
DecodeTargetIndication::kSwitch);
|
|
|
|
|
EXPECT_THAT(header.generic->dependencies, IsEmpty());
|
|
|
|
|
EXPECT_THAT(header.generic->chain_diffs, ElementsAre(0));
|
|
|
|
|
|
|
|
|
|
// Delta frame.
|
|
|
|
|
encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
|
|
|
|
|
codec_info.codecSpecific.VP9.inter_pic_predicted = true;
|
|
|
|
|
codec_info.codecSpecific.VP9.num_ref_pics = 1;
|
|
|
|
|
codec_info.codecSpecific.VP9.p_diff[0] = 1;
|
|
|
|
|
header = params.GetRtpVideoHeader(encoded_image, &codec_info,
|
|
|
|
|
/*shared_frame_id=*/3);
|
|
|
|
|
|
|
|
|
|
ASSERT_TRUE(header.generic);
|
|
|
|
|
EXPECT_EQ(header.generic->spatial_index, 0);
|
|
|
|
|
EXPECT_EQ(header.generic->temporal_index, 0);
|
|
|
|
|
EXPECT_EQ(header.generic->frame_id, 3);
|
|
|
|
|
ASSERT_THAT(header.generic->decode_target_indications, Not(IsEmpty()));
|
|
|
|
|
EXPECT_EQ(header.generic->decode_target_indications[0],
|
|
|
|
|
DecodeTargetIndication::kSwitch);
|
|
|
|
|
EXPECT_THAT(header.generic->dependencies, ElementsAre(1));
|
|
|
|
|
// previous frame in the chain was frame#1,
|
|
|
|
|
EXPECT_THAT(header.generic->chain_diffs, ElementsAre(3 - 1));
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-14 11:46:44 +02:00
|
|
|
TEST(RtpPayloadParamsVp9ToGenericTest, TemporalScalabilityWith2Layers) {
|
2021-04-22 15:20:28 +02:00
|
|
|
// Test with 2 temporal layers structure that is not used by webrtc:
|
|
|
|
|
// 1---3 5
|
|
|
|
|
// / / / ...
|
|
|
|
|
// 0---2---4---
|
2021-09-14 11:46:44 +02:00
|
|
|
RtpPayloadState state;
|
|
|
|
|
RtpPayloadParams params(/*ssrc=*/123, &state, FieldTrialBasedConfig());
|
2021-04-22 15:20:28 +02:00
|
|
|
|
|
|
|
|
EncodedImage image;
|
|
|
|
|
CodecSpecificInfo info;
|
|
|
|
|
info.codecType = kVideoCodecVP9;
|
|
|
|
|
info.codecSpecific.VP9.num_spatial_layers = 1;
|
|
|
|
|
info.codecSpecific.VP9.first_frame_in_picture = true;
|
|
|
|
|
info.end_of_picture = true;
|
|
|
|
|
|
|
|
|
|
RTPVideoHeader headers[6];
|
|
|
|
|
// Key frame.
|
|
|
|
|
image._frameType = VideoFrameType::kVideoFrameKey;
|
|
|
|
|
info.codecSpecific.VP9.inter_pic_predicted = false;
|
|
|
|
|
info.codecSpecific.VP9.num_ref_pics = 0;
|
|
|
|
|
info.codecSpecific.VP9.temporal_up_switch = true;
|
|
|
|
|
info.codecSpecific.VP9.temporal_idx = 0;
|
|
|
|
|
headers[0] = params.GetRtpVideoHeader(image, &info, /*shared_frame_id=*/1);
|
|
|
|
|
|
|
|
|
|
// Delta frames.
|
|
|
|
|
info.codecSpecific.VP9.inter_pic_predicted = true;
|
|
|
|
|
image._frameType = VideoFrameType::kVideoFrameDelta;
|
|
|
|
|
|
|
|
|
|
info.codecSpecific.VP9.temporal_up_switch = true;
|
|
|
|
|
info.codecSpecific.VP9.temporal_idx = 1;
|
|
|
|
|
info.codecSpecific.VP9.num_ref_pics = 1;
|
|
|
|
|
info.codecSpecific.VP9.p_diff[0] = 1;
|
|
|
|
|
headers[1] = params.GetRtpVideoHeader(image, &info, /*shared_frame_id=*/3);
|
|
|
|
|
|
|
|
|
|
info.codecSpecific.VP9.temporal_up_switch = false;
|
|
|
|
|
info.codecSpecific.VP9.temporal_idx = 0;
|
|
|
|
|
info.codecSpecific.VP9.num_ref_pics = 1;
|
|
|
|
|
info.codecSpecific.VP9.p_diff[0] = 2;
|
|
|
|
|
headers[2] = params.GetRtpVideoHeader(image, &info, /*shared_frame_id=*/5);
|
|
|
|
|
|
|
|
|
|
info.codecSpecific.VP9.temporal_up_switch = false;
|
|
|
|
|
info.codecSpecific.VP9.temporal_idx = 1;
|
|
|
|
|
info.codecSpecific.VP9.num_ref_pics = 2;
|
|
|
|
|
info.codecSpecific.VP9.p_diff[0] = 1;
|
|
|
|
|
info.codecSpecific.VP9.p_diff[1] = 2;
|
|
|
|
|
headers[3] = params.GetRtpVideoHeader(image, &info, /*shared_frame_id=*/7);
|
|
|
|
|
|
|
|
|
|
info.codecSpecific.VP9.temporal_up_switch = true;
|
|
|
|
|
info.codecSpecific.VP9.temporal_idx = 0;
|
|
|
|
|
info.codecSpecific.VP9.num_ref_pics = 1;
|
|
|
|
|
info.codecSpecific.VP9.p_diff[0] = 2;
|
|
|
|
|
headers[4] = params.GetRtpVideoHeader(image, &info, /*shared_frame_id=*/9);
|
|
|
|
|
|
|
|
|
|
info.codecSpecific.VP9.temporal_up_switch = true;
|
|
|
|
|
info.codecSpecific.VP9.temporal_idx = 1;
|
|
|
|
|
info.codecSpecific.VP9.num_ref_pics = 1;
|
|
|
|
|
info.codecSpecific.VP9.p_diff[0] = 1;
|
|
|
|
|
headers[5] = params.GetRtpVideoHeader(image, &info, /*shared_frame_id=*/11);
|
|
|
|
|
|
|
|
|
|
ASSERT_TRUE(headers[0].generic);
|
|
|
|
|
int num_decode_targets = headers[0].generic->decode_target_indications.size();
|
|
|
|
|
ASSERT_GE(num_decode_targets, 2);
|
|
|
|
|
|
|
|
|
|
for (int frame_idx = 0; frame_idx < 6; ++frame_idx) {
|
|
|
|
|
const RTPVideoHeader& header = headers[frame_idx];
|
|
|
|
|
ASSERT_TRUE(header.generic);
|
|
|
|
|
EXPECT_EQ(header.generic->spatial_index, 0);
|
|
|
|
|
EXPECT_EQ(header.generic->temporal_index, frame_idx % 2);
|
|
|
|
|
EXPECT_EQ(header.generic->frame_id, 1 + 2 * frame_idx);
|
|
|
|
|
ASSERT_THAT(header.generic->decode_target_indications,
|
|
|
|
|
SizeIs(num_decode_targets));
|
|
|
|
|
// Expect only T0 frames are needed for the 1st decode target.
|
|
|
|
|
if (header.generic->temporal_index == 0) {
|
|
|
|
|
EXPECT_NE(header.generic->decode_target_indications[0],
|
|
|
|
|
DecodeTargetIndication::kNotPresent);
|
|
|
|
|
} else {
|
|
|
|
|
EXPECT_EQ(header.generic->decode_target_indications[0],
|
|
|
|
|
DecodeTargetIndication::kNotPresent);
|
|
|
|
|
}
|
|
|
|
|
// Expect all frames are needed for the 2nd decode target.
|
|
|
|
|
EXPECT_NE(header.generic->decode_target_indications[1],
|
|
|
|
|
DecodeTargetIndication::kNotPresent);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Expect switch at every beginning of the pattern.
|
|
|
|
|
EXPECT_THAT(headers[0].generic->decode_target_indications,
|
|
|
|
|
Each(DecodeTargetIndication::kSwitch));
|
|
|
|
|
EXPECT_THAT(headers[4].generic->decode_target_indications,
|
|
|
|
|
Each(DecodeTargetIndication::kSwitch));
|
|
|
|
|
|
|
|
|
|
EXPECT_THAT(headers[0].generic->dependencies, IsEmpty()); // T0, 1
|
|
|
|
|
EXPECT_THAT(headers[1].generic->dependencies, ElementsAre(1)); // T1, 3
|
|
|
|
|
EXPECT_THAT(headers[2].generic->dependencies, ElementsAre(1)); // T0, 5
|
|
|
|
|
EXPECT_THAT(headers[3].generic->dependencies, ElementsAre(5, 3)); // T1, 7
|
|
|
|
|
EXPECT_THAT(headers[4].generic->dependencies, ElementsAre(5)); // T0, 9
|
|
|
|
|
EXPECT_THAT(headers[5].generic->dependencies, ElementsAre(9)); // T1, 11
|
|
|
|
|
|
|
|
|
|
EXPECT_THAT(headers[0].generic->chain_diffs, ElementsAre(0));
|
|
|
|
|
EXPECT_THAT(headers[1].generic->chain_diffs, ElementsAre(2));
|
|
|
|
|
EXPECT_THAT(headers[2].generic->chain_diffs, ElementsAre(4));
|
|
|
|
|
EXPECT_THAT(headers[3].generic->chain_diffs, ElementsAre(2));
|
|
|
|
|
EXPECT_THAT(headers[4].generic->chain_diffs, ElementsAre(4));
|
|
|
|
|
EXPECT_THAT(headers[5].generic->chain_diffs, ElementsAre(2));
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-14 11:46:44 +02:00
|
|
|
TEST(RtpPayloadParamsVp9ToGenericTest, TemporalScalabilityWith3Layers) {
|
2021-04-22 15:20:28 +02:00
|
|
|
// Test with 3 temporal layers structure that is not used by webrtc, but used
|
|
|
|
|
// by chromium: https://imgur.com/pURAGvp
|
2021-09-14 11:46:44 +02:00
|
|
|
RtpPayloadState state;
|
|
|
|
|
RtpPayloadParams params(/*ssrc=*/123, &state, FieldTrialBasedConfig());
|
2021-04-22 15:20:28 +02:00
|
|
|
|
|
|
|
|
EncodedImage image;
|
|
|
|
|
CodecSpecificInfo info;
|
|
|
|
|
info.codecType = kVideoCodecVP9;
|
|
|
|
|
info.codecSpecific.VP9.num_spatial_layers = 1;
|
|
|
|
|
info.codecSpecific.VP9.first_frame_in_picture = true;
|
|
|
|
|
info.end_of_picture = true;
|
|
|
|
|
|
|
|
|
|
RTPVideoHeader headers[9];
|
|
|
|
|
// Key frame.
|
|
|
|
|
image._frameType = VideoFrameType::kVideoFrameKey;
|
|
|
|
|
info.codecSpecific.VP9.inter_pic_predicted = false;
|
|
|
|
|
info.codecSpecific.VP9.num_ref_pics = 0;
|
|
|
|
|
info.codecSpecific.VP9.temporal_up_switch = true;
|
|
|
|
|
info.codecSpecific.VP9.temporal_idx = 0;
|
|
|
|
|
headers[0] = params.GetRtpVideoHeader(image, &info, /*shared_frame_id=*/1);
|
|
|
|
|
|
|
|
|
|
// Delta frames.
|
|
|
|
|
info.codecSpecific.VP9.inter_pic_predicted = true;
|
|
|
|
|
image._frameType = VideoFrameType::kVideoFrameDelta;
|
|
|
|
|
|
|
|
|
|
info.codecSpecific.VP9.temporal_up_switch = true;
|
|
|
|
|
info.codecSpecific.VP9.temporal_idx = 2;
|
|
|
|
|
info.codecSpecific.VP9.num_ref_pics = 1;
|
|
|
|
|
info.codecSpecific.VP9.p_diff[0] = 1;
|
|
|
|
|
headers[1] = params.GetRtpVideoHeader(image, &info, /*shared_frame_id=*/3);
|
|
|
|
|
|
|
|
|
|
info.codecSpecific.VP9.temporal_up_switch = true;
|
|
|
|
|
info.codecSpecific.VP9.temporal_idx = 1;
|
|
|
|
|
info.codecSpecific.VP9.num_ref_pics = 1;
|
|
|
|
|
info.codecSpecific.VP9.p_diff[0] = 2;
|
|
|
|
|
headers[2] = params.GetRtpVideoHeader(image, &info, /*shared_frame_id=*/5);
|
|
|
|
|
|
|
|
|
|
info.codecSpecific.VP9.temporal_up_switch = true;
|
|
|
|
|
info.codecSpecific.VP9.temporal_idx = 2;
|
|
|
|
|
info.codecSpecific.VP9.num_ref_pics = 1;
|
|
|
|
|
info.codecSpecific.VP9.p_diff[0] = 1;
|
|
|
|
|
headers[3] = params.GetRtpVideoHeader(image, &info, /*shared_frame_id=*/7);
|
|
|
|
|
|
|
|
|
|
info.codecSpecific.VP9.temporal_up_switch = false;
|
|
|
|
|
info.codecSpecific.VP9.temporal_idx = 0;
|
|
|
|
|
info.codecSpecific.VP9.num_ref_pics = 1;
|
|
|
|
|
info.codecSpecific.VP9.p_diff[0] = 4;
|
|
|
|
|
headers[4] = params.GetRtpVideoHeader(image, &info, /*shared_frame_id=*/9);
|
|
|
|
|
|
|
|
|
|
info.codecSpecific.VP9.temporal_up_switch = true;
|
|
|
|
|
info.codecSpecific.VP9.temporal_idx = 2;
|
|
|
|
|
info.codecSpecific.VP9.num_ref_pics = 2;
|
|
|
|
|
info.codecSpecific.VP9.p_diff[0] = 1;
|
|
|
|
|
info.codecSpecific.VP9.p_diff[1] = 3;
|
|
|
|
|
headers[5] = params.GetRtpVideoHeader(image, &info, /*shared_frame_id=*/11);
|
|
|
|
|
|
|
|
|
|
info.codecSpecific.VP9.temporal_up_switch = false;
|
|
|
|
|
info.codecSpecific.VP9.temporal_idx = 1;
|
|
|
|
|
info.codecSpecific.VP9.num_ref_pics = 2;
|
|
|
|
|
info.codecSpecific.VP9.p_diff[0] = 2;
|
|
|
|
|
info.codecSpecific.VP9.p_diff[1] = 4;
|
|
|
|
|
headers[6] = params.GetRtpVideoHeader(image, &info, /*shared_frame_id=*/13);
|
|
|
|
|
|
|
|
|
|
info.codecSpecific.VP9.temporal_up_switch = true;
|
|
|
|
|
info.codecSpecific.VP9.temporal_idx = 2;
|
|
|
|
|
info.codecSpecific.VP9.num_ref_pics = 1;
|
|
|
|
|
info.codecSpecific.VP9.p_diff[0] = 1;
|
|
|
|
|
headers[7] = params.GetRtpVideoHeader(image, &info, /*shared_frame_id=*/15);
|
|
|
|
|
|
|
|
|
|
info.codecSpecific.VP9.temporal_up_switch = true;
|
|
|
|
|
info.codecSpecific.VP9.temporal_idx = 0;
|
|
|
|
|
info.codecSpecific.VP9.num_ref_pics = 1;
|
|
|
|
|
info.codecSpecific.VP9.p_diff[0] = 4;
|
|
|
|
|
headers[8] = params.GetRtpVideoHeader(image, &info, /*shared_frame_id=*/17);
|
|
|
|
|
|
|
|
|
|
ASSERT_TRUE(headers[0].generic);
|
|
|
|
|
int num_decode_targets = headers[0].generic->decode_target_indications.size();
|
|
|
|
|
ASSERT_GE(num_decode_targets, 3);
|
|
|
|
|
|
|
|
|
|
for (int frame_idx = 0; frame_idx < 9; ++frame_idx) {
|
|
|
|
|
const RTPVideoHeader& header = headers[frame_idx];
|
|
|
|
|
ASSERT_TRUE(header.generic);
|
|
|
|
|
EXPECT_EQ(header.generic->spatial_index, 0);
|
|
|
|
|
EXPECT_EQ(header.generic->frame_id, 1 + 2 * frame_idx);
|
|
|
|
|
ASSERT_THAT(header.generic->decode_target_indications,
|
|
|
|
|
SizeIs(num_decode_targets));
|
|
|
|
|
// Expect only T0 frames are needed for the 1st decode target.
|
|
|
|
|
if (header.generic->temporal_index == 0) {
|
|
|
|
|
EXPECT_NE(header.generic->decode_target_indications[0],
|
|
|
|
|
DecodeTargetIndication::kNotPresent);
|
|
|
|
|
} else {
|
|
|
|
|
EXPECT_EQ(header.generic->decode_target_indications[0],
|
|
|
|
|
DecodeTargetIndication::kNotPresent);
|
|
|
|
|
}
|
|
|
|
|
// Expect only T0 and T1 frames are needed for the 2nd decode target.
|
|
|
|
|
if (header.generic->temporal_index <= 1) {
|
|
|
|
|
EXPECT_NE(header.generic->decode_target_indications[1],
|
|
|
|
|
DecodeTargetIndication::kNotPresent);
|
|
|
|
|
} else {
|
|
|
|
|
EXPECT_EQ(header.generic->decode_target_indications[1],
|
|
|
|
|
DecodeTargetIndication::kNotPresent);
|
|
|
|
|
}
|
|
|
|
|
// Expect all frames are needed for the 3rd decode target.
|
|
|
|
|
EXPECT_NE(header.generic->decode_target_indications[2],
|
|
|
|
|
DecodeTargetIndication::kNotPresent);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(headers[0].generic->temporal_index, 0);
|
|
|
|
|
EXPECT_EQ(headers[1].generic->temporal_index, 2);
|
|
|
|
|
EXPECT_EQ(headers[2].generic->temporal_index, 1);
|
|
|
|
|
EXPECT_EQ(headers[3].generic->temporal_index, 2);
|
|
|
|
|
EXPECT_EQ(headers[4].generic->temporal_index, 0);
|
|
|
|
|
EXPECT_EQ(headers[5].generic->temporal_index, 2);
|
|
|
|
|
EXPECT_EQ(headers[6].generic->temporal_index, 1);
|
|
|
|
|
EXPECT_EQ(headers[7].generic->temporal_index, 2);
|
|
|
|
|
EXPECT_EQ(headers[8].generic->temporal_index, 0);
|
|
|
|
|
|
|
|
|
|
// Expect switch at every beginning of the pattern.
|
|
|
|
|
EXPECT_THAT(headers[0].generic->decode_target_indications,
|
|
|
|
|
Each(DecodeTargetIndication::kSwitch));
|
|
|
|
|
EXPECT_THAT(headers[8].generic->decode_target_indications,
|
|
|
|
|
Each(DecodeTargetIndication::kSwitch));
|
|
|
|
|
|
|
|
|
|
EXPECT_THAT(headers[0].generic->dependencies, IsEmpty()); // T0, 1
|
|
|
|
|
EXPECT_THAT(headers[1].generic->dependencies, ElementsAre(1)); // T2, 3
|
|
|
|
|
EXPECT_THAT(headers[2].generic->dependencies, ElementsAre(1)); // T1, 5
|
|
|
|
|
EXPECT_THAT(headers[3].generic->dependencies, ElementsAre(5)); // T2, 7
|
|
|
|
|
EXPECT_THAT(headers[4].generic->dependencies, ElementsAre(1)); // T0, 9
|
|
|
|
|
EXPECT_THAT(headers[5].generic->dependencies, ElementsAre(9, 5)); // T2, 11
|
|
|
|
|
EXPECT_THAT(headers[6].generic->dependencies, ElementsAre(9, 5)); // T1, 13
|
|
|
|
|
EXPECT_THAT(headers[7].generic->dependencies, ElementsAre(13)); // T2, 15
|
|
|
|
|
EXPECT_THAT(headers[8].generic->dependencies, ElementsAre(9)); // T0, 17
|
|
|
|
|
|
|
|
|
|
EXPECT_THAT(headers[0].generic->chain_diffs, ElementsAre(0));
|
|
|
|
|
EXPECT_THAT(headers[1].generic->chain_diffs, ElementsAre(2));
|
|
|
|
|
EXPECT_THAT(headers[2].generic->chain_diffs, ElementsAre(4));
|
|
|
|
|
EXPECT_THAT(headers[3].generic->chain_diffs, ElementsAre(6));
|
|
|
|
|
EXPECT_THAT(headers[4].generic->chain_diffs, ElementsAre(8));
|
|
|
|
|
EXPECT_THAT(headers[5].generic->chain_diffs, ElementsAre(2));
|
|
|
|
|
EXPECT_THAT(headers[6].generic->chain_diffs, ElementsAre(4));
|
|
|
|
|
EXPECT_THAT(headers[7].generic->chain_diffs, ElementsAre(6));
|
|
|
|
|
EXPECT_THAT(headers[8].generic->chain_diffs, ElementsAre(8));
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-14 11:46:44 +02:00
|
|
|
TEST(RtpPayloadParamsVp9ToGenericTest, SpatialScalabilityKSvc) {
|
2021-04-22 15:20:28 +02:00
|
|
|
// 1---3--
|
|
|
|
|
// | ...
|
|
|
|
|
// 0---2--
|
2021-09-14 11:46:44 +02:00
|
|
|
RtpPayloadState state;
|
|
|
|
|
RtpPayloadParams params(/*ssrc=*/123, &state, FieldTrialBasedConfig());
|
2021-04-22 15:20:28 +02:00
|
|
|
|
|
|
|
|
EncodedImage image;
|
|
|
|
|
CodecSpecificInfo info;
|
|
|
|
|
info.codecType = kVideoCodecVP9;
|
|
|
|
|
info.codecSpecific.VP9.num_spatial_layers = 2;
|
|
|
|
|
info.codecSpecific.VP9.first_frame_in_picture = true;
|
|
|
|
|
|
|
|
|
|
RTPVideoHeader headers[4];
|
|
|
|
|
// Key frame.
|
|
|
|
|
image._frameType = VideoFrameType::kVideoFrameKey;
|
|
|
|
|
image.SetSpatialIndex(0);
|
|
|
|
|
info.codecSpecific.VP9.inter_pic_predicted = false;
|
|
|
|
|
info.codecSpecific.VP9.inter_layer_predicted = false;
|
|
|
|
|
info.codecSpecific.VP9.non_ref_for_inter_layer_pred = false;
|
|
|
|
|
info.codecSpecific.VP9.num_ref_pics = 0;
|
|
|
|
|
info.codecSpecific.VP9.first_frame_in_picture = true;
|
|
|
|
|
info.end_of_picture = false;
|
|
|
|
|
headers[0] = params.GetRtpVideoHeader(image, &info, /*shared_frame_id=*/1);
|
|
|
|
|
|
|
|
|
|
image.SetSpatialIndex(1);
|
|
|
|
|
info.codecSpecific.VP9.inter_layer_predicted = true;
|
|
|
|
|
info.codecSpecific.VP9.non_ref_for_inter_layer_pred = true;
|
|
|
|
|
info.codecSpecific.VP9.first_frame_in_picture = false;
|
|
|
|
|
info.end_of_picture = true;
|
|
|
|
|
headers[1] = params.GetRtpVideoHeader(image, &info, /*shared_frame_id=*/3);
|
|
|
|
|
|
|
|
|
|
// Delta frames.
|
|
|
|
|
info.codecSpecific.VP9.inter_pic_predicted = true;
|
|
|
|
|
image._frameType = VideoFrameType::kVideoFrameDelta;
|
|
|
|
|
info.codecSpecific.VP9.num_ref_pics = 1;
|
|
|
|
|
info.codecSpecific.VP9.p_diff[0] = 1;
|
|
|
|
|
|
|
|
|
|
image.SetSpatialIndex(0);
|
|
|
|
|
info.codecSpecific.VP9.inter_layer_predicted = false;
|
|
|
|
|
info.codecSpecific.VP9.non_ref_for_inter_layer_pred = true;
|
|
|
|
|
info.codecSpecific.VP9.first_frame_in_picture = true;
|
|
|
|
|
info.end_of_picture = false;
|
|
|
|
|
headers[2] = params.GetRtpVideoHeader(image, &info, /*shared_frame_id=*/5);
|
|
|
|
|
|
|
|
|
|
image.SetSpatialIndex(1);
|
|
|
|
|
info.codecSpecific.VP9.inter_layer_predicted = false;
|
|
|
|
|
info.codecSpecific.VP9.non_ref_for_inter_layer_pred = true;
|
|
|
|
|
info.codecSpecific.VP9.first_frame_in_picture = false;
|
|
|
|
|
info.end_of_picture = true;
|
|
|
|
|
headers[3] = params.GetRtpVideoHeader(image, &info, /*shared_frame_id=*/7);
|
|
|
|
|
|
|
|
|
|
ASSERT_TRUE(headers[0].generic);
|
|
|
|
|
int num_decode_targets = headers[0].generic->decode_target_indications.size();
|
|
|
|
|
// Rely on implementation detail there are always kMaxTemporalStreams temporal
|
|
|
|
|
// layers assumed, in particular assume Decode Target#0 matches layer S0T0,
|
|
|
|
|
// and Decode Target#kMaxTemporalStreams matches layer S1T0.
|
|
|
|
|
ASSERT_EQ(num_decode_targets, kMaxTemporalStreams * 2);
|
|
|
|
|
|
|
|
|
|
for (int frame_idx = 0; frame_idx < 4; ++frame_idx) {
|
|
|
|
|
const RTPVideoHeader& header = headers[frame_idx];
|
|
|
|
|
ASSERT_TRUE(header.generic);
|
|
|
|
|
EXPECT_EQ(header.generic->spatial_index, frame_idx % 2);
|
|
|
|
|
EXPECT_EQ(header.generic->temporal_index, 0);
|
|
|
|
|
EXPECT_EQ(header.generic->frame_id, 1 + 2 * frame_idx);
|
|
|
|
|
ASSERT_THAT(header.generic->decode_target_indications,
|
|
|
|
|
SizeIs(num_decode_targets));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Expect S0 key frame is switch for both Decode Targets.
|
|
|
|
|
EXPECT_EQ(headers[0].generic->decode_target_indications[0],
|
|
|
|
|
DecodeTargetIndication::kSwitch);
|
|
|
|
|
EXPECT_EQ(headers[0].generic->decode_target_indications[kMaxTemporalStreams],
|
|
|
|
|
DecodeTargetIndication::kSwitch);
|
|
|
|
|
// S1 key frame is only needed for the 2nd Decode Targets.
|
|
|
|
|
EXPECT_EQ(headers[1].generic->decode_target_indications[0],
|
|
|
|
|
DecodeTargetIndication::kNotPresent);
|
|
|
|
|
EXPECT_NE(headers[1].generic->decode_target_indications[kMaxTemporalStreams],
|
|
|
|
|
DecodeTargetIndication::kNotPresent);
|
|
|
|
|
// Delta frames are only needed for their own Decode Targets.
|
|
|
|
|
EXPECT_NE(headers[2].generic->decode_target_indications[0],
|
|
|
|
|
DecodeTargetIndication::kNotPresent);
|
|
|
|
|
EXPECT_EQ(headers[2].generic->decode_target_indications[kMaxTemporalStreams],
|
|
|
|
|
DecodeTargetIndication::kNotPresent);
|
|
|
|
|
EXPECT_EQ(headers[3].generic->decode_target_indications[0],
|
|
|
|
|
DecodeTargetIndication::kNotPresent);
|
|
|
|
|
EXPECT_NE(headers[3].generic->decode_target_indications[kMaxTemporalStreams],
|
|
|
|
|
DecodeTargetIndication::kNotPresent);
|
|
|
|
|
|
|
|
|
|
EXPECT_THAT(headers[0].generic->dependencies, IsEmpty()); // S0, 1
|
|
|
|
|
EXPECT_THAT(headers[1].generic->dependencies, ElementsAre(1)); // S1, 3
|
|
|
|
|
EXPECT_THAT(headers[2].generic->dependencies, ElementsAre(1)); // S0, 5
|
|
|
|
|
EXPECT_THAT(headers[3].generic->dependencies, ElementsAre(3)); // S1, 7
|
|
|
|
|
|
|
|
|
|
EXPECT_THAT(headers[0].generic->chain_diffs, ElementsAre(0, 0));
|
|
|
|
|
EXPECT_THAT(headers[1].generic->chain_diffs, ElementsAre(2, 2));
|
|
|
|
|
EXPECT_THAT(headers[2].generic->chain_diffs, ElementsAre(4, 2));
|
|
|
|
|
EXPECT_THAT(headers[3].generic->chain_diffs, ElementsAre(2, 4));
|
|
|
|
|
}
|
|
|
|
|
|
2019-06-13 15:13:16 +02:00
|
|
|
class RtpPayloadParamsH264ToGenericTest : public ::testing::Test {
|
|
|
|
|
public:
|
|
|
|
|
enum LayerSync { kNoSync, kSync };
|
|
|
|
|
|
|
|
|
|
RtpPayloadParamsH264ToGenericTest()
|
2020-06-03 14:11:26 +02:00
|
|
|
: state_(), params_(123, &state_, trials_config_) {}
|
2019-06-13 15:13:16 +02:00
|
|
|
|
|
|
|
|
void ConvertAndCheck(int temporal_index,
|
|
|
|
|
int64_t shared_frame_id,
|
|
|
|
|
VideoFrameType frame_type,
|
|
|
|
|
LayerSync layer_sync,
|
|
|
|
|
const std::set<int64_t>& expected_deps,
|
|
|
|
|
uint16_t width = 0,
|
|
|
|
|
uint16_t height = 0) {
|
|
|
|
|
EncodedImage encoded_image;
|
|
|
|
|
encoded_image._frameType = frame_type;
|
|
|
|
|
encoded_image._encodedWidth = width;
|
|
|
|
|
encoded_image._encodedHeight = height;
|
|
|
|
|
|
|
|
|
|
CodecSpecificInfo codec_info;
|
|
|
|
|
codec_info.codecType = kVideoCodecH264;
|
|
|
|
|
codec_info.codecSpecific.H264.temporal_idx = temporal_index;
|
|
|
|
|
codec_info.codecSpecific.H264.base_layer_sync = layer_sync == kSync;
|
|
|
|
|
|
|
|
|
|
RTPVideoHeader header =
|
|
|
|
|
params_.GetRtpVideoHeader(encoded_image, &codec_info, shared_frame_id);
|
|
|
|
|
|
|
|
|
|
ASSERT_TRUE(header.generic);
|
|
|
|
|
EXPECT_EQ(header.generic->spatial_index, 0);
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(header.generic->frame_id, shared_frame_id);
|
|
|
|
|
EXPECT_EQ(header.generic->temporal_index, temporal_index);
|
|
|
|
|
std::set<int64_t> actual_deps(header.generic->dependencies.begin(),
|
|
|
|
|
header.generic->dependencies.end());
|
|
|
|
|
EXPECT_EQ(expected_deps, actual_deps);
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(header.width, width);
|
|
|
|
|
EXPECT_EQ(header.height, height);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected:
|
2020-04-18 14:36:59 +02:00
|
|
|
FieldTrialBasedConfig trials_config_;
|
2019-06-13 15:13:16 +02:00
|
|
|
RtpPayloadState state_;
|
|
|
|
|
RtpPayloadParams params_;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
TEST_F(RtpPayloadParamsH264ToGenericTest, Keyframe) {
|
|
|
|
|
ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
|
|
|
|
|
ConvertAndCheck(0, 1, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
|
|
|
|
|
ConvertAndCheck(0, 2, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(RtpPayloadParamsH264ToGenericTest, TooHighTemporalIndex) {
|
|
|
|
|
ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
|
|
|
|
|
|
|
|
|
|
EncodedImage encoded_image;
|
|
|
|
|
encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
|
|
|
|
|
CodecSpecificInfo codec_info;
|
|
|
|
|
codec_info.codecType = kVideoCodecH264;
|
|
|
|
|
codec_info.codecSpecific.H264.temporal_idx =
|
|
|
|
|
RtpGenericFrameDescriptor::kMaxTemporalLayers;
|
|
|
|
|
codec_info.codecSpecific.H264.base_layer_sync = false;
|
|
|
|
|
|
|
|
|
|
RTPVideoHeader header =
|
|
|
|
|
params_.GetRtpVideoHeader(encoded_image, &codec_info, 1);
|
|
|
|
|
EXPECT_FALSE(header.generic);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(RtpPayloadParamsH264ToGenericTest, LayerSync) {
|
|
|
|
|
// 02120212 pattern
|
|
|
|
|
ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
|
|
|
|
|
ConvertAndCheck(2, 1, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
|
|
|
|
|
ConvertAndCheck(1, 2, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
|
|
|
|
|
ConvertAndCheck(2, 3, VideoFrameType::kVideoFrameDelta, kNoSync, {0, 1, 2});
|
|
|
|
|
|
|
|
|
|
ConvertAndCheck(0, 4, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
|
|
|
|
|
ConvertAndCheck(2, 5, VideoFrameType::kVideoFrameDelta, kNoSync, {2, 3, 4});
|
|
|
|
|
ConvertAndCheck(1, 6, VideoFrameType::kVideoFrameDelta, kSync,
|
|
|
|
|
{4}); // layer sync
|
|
|
|
|
ConvertAndCheck(2, 7, VideoFrameType::kVideoFrameDelta, kNoSync, {4, 5, 6});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(RtpPayloadParamsH264ToGenericTest, FrameIdGaps) {
|
|
|
|
|
// 0101 pattern
|
|
|
|
|
ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
|
|
|
|
|
ConvertAndCheck(1, 1, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
|
|
|
|
|
|
|
|
|
|
ConvertAndCheck(0, 5, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
|
|
|
|
|
ConvertAndCheck(1, 10, VideoFrameType::kVideoFrameDelta, kNoSync, {1, 5});
|
|
|
|
|
|
|
|
|
|
ConvertAndCheck(0, 15, VideoFrameType::kVideoFrameDelta, kNoSync, {5});
|
|
|
|
|
ConvertAndCheck(1, 20, VideoFrameType::kVideoFrameDelta, kNoSync, {10, 15});
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-17 10:16:41 +02:00
|
|
|
} // namespace webrtc
|