blob: df576f6d32573b5f115e10e347f997ee0f60eadd [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"
16#include "rtc_base/random.h"
17#include "rtc_base/timeutils.h"
18
19namespace webrtc {
20
21namespace {
22void PopulateRtpWithCodecSpecifics(const CodecSpecificInfo& info,
23 RTPVideoHeader* rtp) {
24 rtp->codec = info.codecType;
25 switch (info.codecType) {
26 case kVideoCodecVP8: {
27 rtp->vp8().InitRTPVideoHeaderVP8();
28 rtp->vp8().nonReference = info.codecSpecific.VP8.nonReference;
29 rtp->vp8().temporalIdx = info.codecSpecific.VP8.temporalIdx;
30 rtp->vp8().layerSync = info.codecSpecific.VP8.layerSync;
31 rtp->vp8().keyIdx = info.codecSpecific.VP8.keyIdx;
32 rtp->simulcastIdx = info.codecSpecific.VP8.simulcastIdx;
33 return;
34 }
35 case kVideoCodecVP9: {
36 rtp->vp9().InitRTPVideoHeaderVP9();
37 rtp->vp9().inter_pic_predicted =
38 info.codecSpecific.VP9.inter_pic_predicted;
39 rtp->vp9().flexible_mode = info.codecSpecific.VP9.flexible_mode;
40 rtp->vp9().ss_data_available = info.codecSpecific.VP9.ss_data_available;
41 rtp->vp9().non_ref_for_inter_layer_pred =
42 info.codecSpecific.VP9.non_ref_for_inter_layer_pred;
43 rtp->vp9().temporal_idx = info.codecSpecific.VP9.temporal_idx;
44 rtp->vp9().spatial_idx = info.codecSpecific.VP9.spatial_idx;
45 rtp->vp9().temporal_up_switch = info.codecSpecific.VP9.temporal_up_switch;
46 rtp->vp9().inter_layer_predicted =
47 info.codecSpecific.VP9.inter_layer_predicted;
48 rtp->vp9().gof_idx = info.codecSpecific.VP9.gof_idx;
49 rtp->vp9().num_spatial_layers = info.codecSpecific.VP9.num_spatial_layers;
50
51 if (info.codecSpecific.VP9.ss_data_available) {
52 rtp->vp9().spatial_layer_resolution_present =
53 info.codecSpecific.VP9.spatial_layer_resolution_present;
54 if (info.codecSpecific.VP9.spatial_layer_resolution_present) {
55 for (size_t i = 0; i < info.codecSpecific.VP9.num_spatial_layers;
56 ++i) {
57 rtp->vp9().width[i] = info.codecSpecific.VP9.width[i];
58 rtp->vp9().height[i] = info.codecSpecific.VP9.height[i];
59 }
60 }
61 rtp->vp9().gof.CopyGofInfoVP9(info.codecSpecific.VP9.gof);
62 }
63
64 rtp->vp9().num_ref_pics = info.codecSpecific.VP9.num_ref_pics;
65 for (int i = 0; i < info.codecSpecific.VP9.num_ref_pics; ++i) {
66 rtp->vp9().pid_diff[i] = info.codecSpecific.VP9.p_diff[i];
67 }
68 rtp->vp9().end_of_picture = info.codecSpecific.VP9.end_of_picture;
69 return;
70 }
71 case kVideoCodecH264: {
72 rtp->h264().packetization_mode =
73 info.codecSpecific.H264.packetization_mode;
74 rtp->simulcastIdx = info.codecSpecific.H264.simulcast_idx;
75 return;
76 }
77 case kVideoCodecMultiplex:
78 case kVideoCodecGeneric:
79 rtp->codec = kVideoCodecGeneric;
80 rtp->simulcastIdx = info.codecSpecific.generic.simulcast_idx;
81 return;
82 default:
83 return;
84 }
85}
86
87void SetVideoTiming(const EncodedImage& image, VideoSendTiming* timing) {
88 if (image.timing_.flags == VideoSendTiming::TimingFrameFlags::kInvalid ||
89 image.timing_.flags == VideoSendTiming::TimingFrameFlags::kNotTriggered) {
90 timing->flags = VideoSendTiming::TimingFrameFlags::kInvalid;
91 return;
92 }
93
94 timing->encode_start_delta_ms = VideoSendTiming::GetDeltaCappedMs(
95 image.capture_time_ms_, image.timing_.encode_start_ms);
96 timing->encode_finish_delta_ms = VideoSendTiming::GetDeltaCappedMs(
97 image.capture_time_ms_, image.timing_.encode_finish_ms);
98 timing->packetization_finish_delta_ms = 0;
99 timing->pacer_exit_delta_ms = 0;
100 timing->network_timestamp_delta_ms = 0;
101 timing->network2_timestamp_delta_ms = 0;
102 timing->flags = image.timing_.flags;
103}
104} // namespace
105
106RtpPayloadParams::RtpPayloadParams(const uint32_t ssrc,
107 const RtpPayloadState* state)
108 : ssrc_(ssrc) {
109 Random random(rtc::TimeMicros());
110 state_.picture_id =
111 state ? state->picture_id : (random.Rand<int16_t>() & 0x7FFF);
112 state_.tl0_pic_idx = state ? state->tl0_pic_idx : (random.Rand<uint8_t>());
113}
114RtpPayloadParams::~RtpPayloadParams() {}
115
116RTPVideoHeader RtpPayloadParams::GetRtpVideoHeader(
117 const EncodedImage& image,
118 const CodecSpecificInfo* codec_specific_info) {
119 RTPVideoHeader rtp_video_header;
120 if (codec_specific_info) {
121 PopulateRtpWithCodecSpecifics(*codec_specific_info, &rtp_video_header);
122 }
123 rtp_video_header.rotation = image.rotation_;
124 rtp_video_header.content_type = image.content_type_;
125 rtp_video_header.playout_delay = image.playout_delay_;
126
127 SetVideoTiming(image, &rtp_video_header.video_timing);
128
129 // Sets picture id and tl0 pic idx.
130 const bool first_frame_in_picture =
131 (codec_specific_info && codec_specific_info->codecType == kVideoCodecVP9)
132 ? codec_specific_info->codecSpecific.VP9.first_frame_in_picture
133 : true;
134 Set(&rtp_video_header, first_frame_in_picture);
135 return rtp_video_header;
136}
137
138uint32_t RtpPayloadParams::ssrc() const {
139 return ssrc_;
140}
141
142RtpPayloadState RtpPayloadParams::state() const {
143 return state_;
144}
145
146void RtpPayloadParams::Set(RTPVideoHeader* rtp_video_header,
147 bool first_frame_in_picture) {
148 // Always set picture id. Set tl0_pic_idx iff temporal index is set.
149 if (first_frame_in_picture) {
150 state_.picture_id = (static_cast<uint16_t>(state_.picture_id) + 1) & 0x7FFF;
151 }
152 if (rtp_video_header->codec == kVideoCodecVP8) {
153 rtp_video_header->vp8().pictureId = state_.picture_id;
154
155 if (rtp_video_header->vp8().temporalIdx != kNoTemporalIdx) {
156 if (rtp_video_header->vp8().temporalIdx == 0) {
157 ++state_.tl0_pic_idx;
158 }
159 rtp_video_header->vp8().tl0PicIdx = state_.tl0_pic_idx;
160 }
161 }
162 if (rtp_video_header->codec == kVideoCodecVP9) {
163 rtp_video_header->vp9().picture_id = state_.picture_id;
164
165 // Note that in the case that we have no temporal layers but we do have
166 // spatial layers, packets will carry layering info with a temporal_idx of
167 // zero, and we then have to set and increment tl0_pic_idx.
168 if (rtp_video_header->vp9().temporal_idx != kNoTemporalIdx ||
169 rtp_video_header->vp9().spatial_idx != kNoSpatialIdx) {
170 if (first_frame_in_picture &&
171 (rtp_video_header->vp9().temporal_idx == 0 ||
172 rtp_video_header->vp9().temporal_idx == kNoTemporalIdx)) {
173 ++state_.tl0_pic_idx;
174 }
175 rtp_video_header->vp9().tl0_pic_idx = state_.tl0_pic_idx;
176 }
177 }
178}
179} // namespace webrtc