blob: 608688b396dcddf0f56e893713e4b40e7be0fd8e [file] [log] [blame]
Stefan Holmerf7044682018-07-17 10:16:41 +02001/*
2 * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include "call/rtp_payload_params.h"
12
13#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
14#include "modules/video_coding/include/video_codec_interface.h"
15#include "rtc_base/checks.h"
philipelbf2b6202018-08-27 14:33:18 +020016#include "rtc_base/logging.h"
Stefan Holmerf7044682018-07-17 10:16:41 +020017#include "rtc_base/random.h"
18#include "rtc_base/timeutils.h"
philipelbf2b6202018-08-27 14:33:18 +020019#include "system_wrappers/include/field_trial.h"
Stefan Holmerf7044682018-07-17 10:16:41 +020020
21namespace webrtc {
22
23namespace {
24void PopulateRtpWithCodecSpecifics(const CodecSpecificInfo& info,
25 RTPVideoHeader* rtp) {
26 rtp->codec = info.codecType;
27 switch (info.codecType) {
28 case kVideoCodecVP8: {
29 rtp->vp8().InitRTPVideoHeaderVP8();
30 rtp->vp8().nonReference = info.codecSpecific.VP8.nonReference;
31 rtp->vp8().temporalIdx = info.codecSpecific.VP8.temporalIdx;
32 rtp->vp8().layerSync = info.codecSpecific.VP8.layerSync;
33 rtp->vp8().keyIdx = info.codecSpecific.VP8.keyIdx;
Niels Moller5a998d72018-08-29 14:35:58 +000034 rtp->simulcastIdx = info.codecSpecific.VP8.simulcastIdx;
Stefan Holmerf7044682018-07-17 10:16:41 +020035 return;
36 }
37 case kVideoCodecVP9: {
philipel29d88462018-08-08 14:26:00 +020038 auto& vp9_header = rtp->video_type_header.emplace<RTPVideoHeaderVP9>();
39 vp9_header.InitRTPVideoHeaderVP9();
40 vp9_header.inter_pic_predicted =
Stefan Holmerf7044682018-07-17 10:16:41 +020041 info.codecSpecific.VP9.inter_pic_predicted;
philipel29d88462018-08-08 14:26:00 +020042 vp9_header.flexible_mode = info.codecSpecific.VP9.flexible_mode;
43 vp9_header.ss_data_available = info.codecSpecific.VP9.ss_data_available;
44 vp9_header.non_ref_for_inter_layer_pred =
Stefan Holmerf7044682018-07-17 10:16:41 +020045 info.codecSpecific.VP9.non_ref_for_inter_layer_pred;
philipel29d88462018-08-08 14:26:00 +020046 vp9_header.temporal_idx = info.codecSpecific.VP9.temporal_idx;
Niels Moller5a998d72018-08-29 14:35:58 +000047 vp9_header.spatial_idx = info.codecSpecific.VP9.spatial_idx;
philipel29d88462018-08-08 14:26:00 +020048 vp9_header.temporal_up_switch = info.codecSpecific.VP9.temporal_up_switch;
49 vp9_header.inter_layer_predicted =
Stefan Holmerf7044682018-07-17 10:16:41 +020050 info.codecSpecific.VP9.inter_layer_predicted;
philipel29d88462018-08-08 14:26:00 +020051 vp9_header.gof_idx = info.codecSpecific.VP9.gof_idx;
52 vp9_header.num_spatial_layers = info.codecSpecific.VP9.num_spatial_layers;
Niels Moller5a998d72018-08-29 14:35:58 +000053
Stefan Holmerf7044682018-07-17 10:16:41 +020054 if (info.codecSpecific.VP9.ss_data_available) {
philipel29d88462018-08-08 14:26:00 +020055 vp9_header.spatial_layer_resolution_present =
Stefan Holmerf7044682018-07-17 10:16:41 +020056 info.codecSpecific.VP9.spatial_layer_resolution_present;
57 if (info.codecSpecific.VP9.spatial_layer_resolution_present) {
58 for (size_t i = 0; i < info.codecSpecific.VP9.num_spatial_layers;
59 ++i) {
philipel29d88462018-08-08 14:26:00 +020060 vp9_header.width[i] = info.codecSpecific.VP9.width[i];
61 vp9_header.height[i] = info.codecSpecific.VP9.height[i];
Stefan Holmerf7044682018-07-17 10:16:41 +020062 }
63 }
philipel29d88462018-08-08 14:26:00 +020064 vp9_header.gof.CopyGofInfoVP9(info.codecSpecific.VP9.gof);
Stefan Holmerf7044682018-07-17 10:16:41 +020065 }
66
philipel29d88462018-08-08 14:26:00 +020067 vp9_header.num_ref_pics = info.codecSpecific.VP9.num_ref_pics;
Stefan Holmerf7044682018-07-17 10:16:41 +020068 for (int i = 0; i < info.codecSpecific.VP9.num_ref_pics; ++i) {
philipel29d88462018-08-08 14:26:00 +020069 vp9_header.pid_diff[i] = info.codecSpecific.VP9.p_diff[i];
Stefan Holmerf7044682018-07-17 10:16:41 +020070 }
philipel29d88462018-08-08 14:26:00 +020071 vp9_header.end_of_picture = info.codecSpecific.VP9.end_of_picture;
Stefan Holmerf7044682018-07-17 10:16:41 +020072 return;
73 }
74 case kVideoCodecH264: {
philipel7d745e52018-08-02 14:03:53 +020075 auto& h264_header = rtp->video_type_header.emplace<RTPVideoHeaderH264>();
76 h264_header.packetization_mode =
Stefan Holmerf7044682018-07-17 10:16:41 +020077 info.codecSpecific.H264.packetization_mode;
Niels Moller5a998d72018-08-29 14:35:58 +000078 rtp->simulcastIdx = info.codecSpecific.H264.simulcast_idx;
Stefan Holmerf7044682018-07-17 10:16:41 +020079 return;
80 }
81 case kVideoCodecMultiplex:
82 case kVideoCodecGeneric:
83 rtp->codec = kVideoCodecGeneric;
Niels Moller5a998d72018-08-29 14:35:58 +000084 rtp->simulcastIdx = info.codecSpecific.generic.simulcast_idx;
Stefan Holmerf7044682018-07-17 10:16:41 +020085 return;
86 default:
87 return;
88 }
89}
90
91void SetVideoTiming(const EncodedImage& image, VideoSendTiming* timing) {
92 if (image.timing_.flags == VideoSendTiming::TimingFrameFlags::kInvalid ||
93 image.timing_.flags == VideoSendTiming::TimingFrameFlags::kNotTriggered) {
94 timing->flags = VideoSendTiming::TimingFrameFlags::kInvalid;
95 return;
96 }
97
98 timing->encode_start_delta_ms = VideoSendTiming::GetDeltaCappedMs(
99 image.capture_time_ms_, image.timing_.encode_start_ms);
100 timing->encode_finish_delta_ms = VideoSendTiming::GetDeltaCappedMs(
101 image.capture_time_ms_, image.timing_.encode_finish_ms);
102 timing->packetization_finish_delta_ms = 0;
103 timing->pacer_exit_delta_ms = 0;
104 timing->network_timestamp_delta_ms = 0;
105 timing->network2_timestamp_delta_ms = 0;
106 timing->flags = image.timing_.flags;
107}
108} // namespace
109
110RtpPayloadParams::RtpPayloadParams(const uint32_t ssrc,
111 const RtpPayloadState* state)
philipelbf2b6202018-08-27 14:33:18 +0200112 : ssrc_(ssrc),
113 generic_picture_id_experiment_(
114 field_trial::IsEnabled("WebRTC-GenericPictureId")) {
115 for (auto& spatial_layer : last_shared_frame_id_)
116 spatial_layer.fill(-1);
117
Stefan Holmerf7044682018-07-17 10:16:41 +0200118 Random random(rtc::TimeMicros());
119 state_.picture_id =
120 state ? state->picture_id : (random.Rand<int16_t>() & 0x7FFF);
121 state_.tl0_pic_idx = state ? state->tl0_pic_idx : (random.Rand<uint8_t>());
122}
philipelbf2b6202018-08-27 14:33:18 +0200123
124RtpPayloadParams::RtpPayloadParams(const RtpPayloadParams& other) = default;
125
Stefan Holmerf7044682018-07-17 10:16:41 +0200126RtpPayloadParams::~RtpPayloadParams() {}
127
128RTPVideoHeader RtpPayloadParams::GetRtpVideoHeader(
129 const EncodedImage& image,
philipelbf2b6202018-08-27 14:33:18 +0200130 const CodecSpecificInfo* codec_specific_info,
131 int64_t shared_frame_id) {
Stefan Holmerf7044682018-07-17 10:16:41 +0200132 RTPVideoHeader rtp_video_header;
133 if (codec_specific_info) {
Niels Moller5a998d72018-08-29 14:35:58 +0000134 PopulateRtpWithCodecSpecifics(*codec_specific_info, &rtp_video_header);
Stefan Holmerf7044682018-07-17 10:16:41 +0200135 }
136 rtp_video_header.rotation = image.rotation_;
137 rtp_video_header.content_type = image.content_type_;
138 rtp_video_header.playout_delay = image.playout_delay_;
139
140 SetVideoTiming(image, &rtp_video_header.video_timing);
141
philipelbf2b6202018-08-27 14:33:18 +0200142 const bool is_keyframe = image._frameType == kVideoFrameKey;
Stefan Holmerf7044682018-07-17 10:16:41 +0200143 const bool first_frame_in_picture =
144 (codec_specific_info && codec_specific_info->codecType == kVideoCodecVP9)
145 ? codec_specific_info->codecSpecific.VP9.first_frame_in_picture
146 : true;
philipelbf2b6202018-08-27 14:33:18 +0200147
148 SetCodecSpecific(&rtp_video_header, first_frame_in_picture);
149 SetGeneric(shared_frame_id, is_keyframe, &rtp_video_header);
150
Stefan Holmerf7044682018-07-17 10:16:41 +0200151 return rtp_video_header;
152}
153
154uint32_t RtpPayloadParams::ssrc() const {
155 return ssrc_;
156}
157
158RtpPayloadState RtpPayloadParams::state() const {
159 return state_;
160}
161
philipelbf2b6202018-08-27 14:33:18 +0200162void RtpPayloadParams::SetCodecSpecific(RTPVideoHeader* rtp_video_header,
163 bool first_frame_in_picture) {
Stefan Holmerf7044682018-07-17 10:16:41 +0200164 // Always set picture id. Set tl0_pic_idx iff temporal index is set.
165 if (first_frame_in_picture) {
166 state_.picture_id = (static_cast<uint16_t>(state_.picture_id) + 1) & 0x7FFF;
167 }
168 if (rtp_video_header->codec == kVideoCodecVP8) {
169 rtp_video_header->vp8().pictureId = state_.picture_id;
170
171 if (rtp_video_header->vp8().temporalIdx != kNoTemporalIdx) {
172 if (rtp_video_header->vp8().temporalIdx == 0) {
173 ++state_.tl0_pic_idx;
174 }
175 rtp_video_header->vp8().tl0PicIdx = state_.tl0_pic_idx;
176 }
177 }
178 if (rtp_video_header->codec == kVideoCodecVP9) {
philipel29d88462018-08-08 14:26:00 +0200179 auto& vp9_header =
180 absl::get<RTPVideoHeaderVP9>(rtp_video_header->video_type_header);
181 vp9_header.picture_id = state_.picture_id;
Stefan Holmerf7044682018-07-17 10:16:41 +0200182
183 // Note that in the case that we have no temporal layers but we do have
184 // spatial layers, packets will carry layering info with a temporal_idx of
185 // zero, and we then have to set and increment tl0_pic_idx.
philipel29d88462018-08-08 14:26:00 +0200186 if (vp9_header.temporal_idx != kNoTemporalIdx ||
187 vp9_header.spatial_idx != kNoSpatialIdx) {
Stefan Holmerf7044682018-07-17 10:16:41 +0200188 if (first_frame_in_picture &&
philipel29d88462018-08-08 14:26:00 +0200189 (vp9_header.temporal_idx == 0 ||
190 vp9_header.temporal_idx == kNoTemporalIdx)) {
Stefan Holmerf7044682018-07-17 10:16:41 +0200191 ++state_.tl0_pic_idx;
192 }
philipel29d88462018-08-08 14:26:00 +0200193 vp9_header.tl0_pic_idx = state_.tl0_pic_idx;
Stefan Holmerf7044682018-07-17 10:16:41 +0200194 }
195 }
philipelbf2b6202018-08-27 14:33:18 +0200196 // There are currently two generic descriptors in WebRTC. The old descriptor
197 // can not share a picture id space between simulcast streams, so we use the
198 // |picture_id| in this case. We let the |picture_id| tag along in |frame_id|
199 // until the old generic format can be removed.
200 // TODO(philipel): Remove this when the new generic format has been fully
201 // implemented.
202 if (generic_picture_id_experiment_ &&
203 rtp_video_header->codec == kVideoCodecGeneric) {
204 rtp_video_header->generic.emplace().frame_id = state_.picture_id;
205 }
Stefan Holmerf7044682018-07-17 10:16:41 +0200206}
philipelbf2b6202018-08-27 14:33:18 +0200207
208void RtpPayloadParams::SetGeneric(int64_t frame_id,
209 bool is_keyframe,
210 RTPVideoHeader* rtp_video_header) {
211 if (rtp_video_header->codec == kVideoCodecVP8) {
212 Vp8ToGeneric(frame_id, is_keyframe, rtp_video_header);
213 }
214
215 // TODO(philipel): Implement VP9 to new generic descriptor.
216 // TODO(philipel): Implement H264 to new generic descriptor.
217 // TODO(philipel): Implement generic codec to new generic descriptor.
218}
219
220void RtpPayloadParams::Vp8ToGeneric(int64_t shared_frame_id,
221 bool is_keyframe,
222 RTPVideoHeader* rtp_video_header) {
223 const auto& vp8_header =
224 absl::get<RTPVideoHeaderVP8>(rtp_video_header->video_type_header);
225 const int spatial_index = 0;
226 const int temporal_index =
227 vp8_header.temporalIdx != kNoTemporalIdx ? vp8_header.temporalIdx : 0;
228
229 if (temporal_index >= RtpGenericFrameDescriptor::kMaxTemporalLayers ||
230 spatial_index >= RtpGenericFrameDescriptor::kMaxSpatialLayers) {
231 RTC_LOG(LS_WARNING) << "Temporal and/or spatial index is too high to be "
232 "used with generic frame descriptor.";
233 return;
234 }
235
236 RTPVideoHeader::GenericDescriptorInfo& generic =
237 rtp_video_header->generic.emplace();
238
239 generic.frame_id = shared_frame_id;
240 generic.spatial_index = spatial_index;
241 generic.temporal_index = temporal_index;
242
243 if (is_keyframe) {
244 RTC_DCHECK_EQ(temporal_index, 0);
245 last_shared_frame_id_[spatial_index].fill(-1);
246 last_shared_frame_id_[spatial_index][temporal_index] = shared_frame_id;
247 return;
248 }
249
250 if (vp8_header.layerSync) {
251 int64_t tl0_frame_id = last_shared_frame_id_[spatial_index][0];
252
253 for (int i = 1; i < RtpGenericFrameDescriptor::kMaxTemporalLayers; ++i) {
254 if (last_shared_frame_id_[spatial_index][i] < tl0_frame_id) {
255 last_shared_frame_id_[spatial_index][i] = -1;
256 }
257 }
258
259 RTC_DCHECK_GE(tl0_frame_id, 0);
260 RTC_DCHECK_LT(tl0_frame_id, shared_frame_id);
261 generic.dependencies.push_back(tl0_frame_id);
262 } else {
263 for (int i = 0; i <= temporal_index; ++i) {
264 int64_t frame_id = last_shared_frame_id_[spatial_index][i];
265
266 if (frame_id != -1) {
267 RTC_DCHECK_LT(frame_id, shared_frame_id);
268 generic.dependencies.push_back(frame_id);
269 }
270 }
271 }
272
273 last_shared_frame_id_[spatial_index][temporal_index] = shared_frame_id;
274}
275
Stefan Holmerf7044682018-07-17 10:16:41 +0200276} // namespace webrtc