blob: d61d40fc8bb48064b4c8cf6a2141f0a9e0bcf900 [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: {
philipel29d88462018-08-08 14:26:00 +020036 auto& vp9_header = rtp->video_type_header.emplace<RTPVideoHeaderVP9>();
37 vp9_header.InitRTPVideoHeaderVP9();
38 vp9_header.inter_pic_predicted =
Stefan Holmerf7044682018-07-17 10:16:41 +020039 info.codecSpecific.VP9.inter_pic_predicted;
philipel29d88462018-08-08 14:26:00 +020040 vp9_header.flexible_mode = info.codecSpecific.VP9.flexible_mode;
41 vp9_header.ss_data_available = info.codecSpecific.VP9.ss_data_available;
42 vp9_header.non_ref_for_inter_layer_pred =
Stefan Holmerf7044682018-07-17 10:16:41 +020043 info.codecSpecific.VP9.non_ref_for_inter_layer_pred;
philipel29d88462018-08-08 14:26:00 +020044 vp9_header.temporal_idx = info.codecSpecific.VP9.temporal_idx;
45 vp9_header.spatial_idx = info.codecSpecific.VP9.spatial_idx;
46 vp9_header.temporal_up_switch = info.codecSpecific.VP9.temporal_up_switch;
47 vp9_header.inter_layer_predicted =
Stefan Holmerf7044682018-07-17 10:16:41 +020048 info.codecSpecific.VP9.inter_layer_predicted;
philipel29d88462018-08-08 14:26:00 +020049 vp9_header.gof_idx = info.codecSpecific.VP9.gof_idx;
50 vp9_header.num_spatial_layers = info.codecSpecific.VP9.num_spatial_layers;
Stefan Holmerf7044682018-07-17 10:16:41 +020051
52 if (info.codecSpecific.VP9.ss_data_available) {
philipel29d88462018-08-08 14:26:00 +020053 vp9_header.spatial_layer_resolution_present =
Stefan Holmerf7044682018-07-17 10:16:41 +020054 info.codecSpecific.VP9.spatial_layer_resolution_present;
55 if (info.codecSpecific.VP9.spatial_layer_resolution_present) {
56 for (size_t i = 0; i < info.codecSpecific.VP9.num_spatial_layers;
57 ++i) {
philipel29d88462018-08-08 14:26:00 +020058 vp9_header.width[i] = info.codecSpecific.VP9.width[i];
59 vp9_header.height[i] = info.codecSpecific.VP9.height[i];
Stefan Holmerf7044682018-07-17 10:16:41 +020060 }
61 }
philipel29d88462018-08-08 14:26:00 +020062 vp9_header.gof.CopyGofInfoVP9(info.codecSpecific.VP9.gof);
Stefan Holmerf7044682018-07-17 10:16:41 +020063 }
64
philipel29d88462018-08-08 14:26:00 +020065 vp9_header.num_ref_pics = info.codecSpecific.VP9.num_ref_pics;
Stefan Holmerf7044682018-07-17 10:16:41 +020066 for (int i = 0; i < info.codecSpecific.VP9.num_ref_pics; ++i) {
philipel29d88462018-08-08 14:26:00 +020067 vp9_header.pid_diff[i] = info.codecSpecific.VP9.p_diff[i];
Stefan Holmerf7044682018-07-17 10:16:41 +020068 }
philipel29d88462018-08-08 14:26:00 +020069 vp9_header.end_of_picture = info.codecSpecific.VP9.end_of_picture;
Stefan Holmerf7044682018-07-17 10:16:41 +020070 return;
71 }
72 case kVideoCodecH264: {
philipel7d745e52018-08-02 14:03:53 +020073 auto& h264_header = rtp->video_type_header.emplace<RTPVideoHeaderH264>();
74 h264_header.packetization_mode =
Stefan Holmerf7044682018-07-17 10:16:41 +020075 info.codecSpecific.H264.packetization_mode;
76 rtp->simulcastIdx = info.codecSpecific.H264.simulcast_idx;
77 return;
78 }
79 case kVideoCodecMultiplex:
80 case kVideoCodecGeneric:
81 rtp->codec = kVideoCodecGeneric;
82 rtp->simulcastIdx = info.codecSpecific.generic.simulcast_idx;
83 return;
84 default:
85 return;
86 }
87}
88
89void SetVideoTiming(const EncodedImage& image, VideoSendTiming* timing) {
90 if (image.timing_.flags == VideoSendTiming::TimingFrameFlags::kInvalid ||
91 image.timing_.flags == VideoSendTiming::TimingFrameFlags::kNotTriggered) {
92 timing->flags = VideoSendTiming::TimingFrameFlags::kInvalid;
93 return;
94 }
95
96 timing->encode_start_delta_ms = VideoSendTiming::GetDeltaCappedMs(
97 image.capture_time_ms_, image.timing_.encode_start_ms);
98 timing->encode_finish_delta_ms = VideoSendTiming::GetDeltaCappedMs(
99 image.capture_time_ms_, image.timing_.encode_finish_ms);
100 timing->packetization_finish_delta_ms = 0;
101 timing->pacer_exit_delta_ms = 0;
102 timing->network_timestamp_delta_ms = 0;
103 timing->network2_timestamp_delta_ms = 0;
104 timing->flags = image.timing_.flags;
105}
106} // namespace
107
108RtpPayloadParams::RtpPayloadParams(const uint32_t ssrc,
109 const RtpPayloadState* state)
110 : ssrc_(ssrc) {
111 Random random(rtc::TimeMicros());
112 state_.picture_id =
113 state ? state->picture_id : (random.Rand<int16_t>() & 0x7FFF);
114 state_.tl0_pic_idx = state ? state->tl0_pic_idx : (random.Rand<uint8_t>());
115}
116RtpPayloadParams::~RtpPayloadParams() {}
117
118RTPVideoHeader RtpPayloadParams::GetRtpVideoHeader(
119 const EncodedImage& image,
120 const CodecSpecificInfo* codec_specific_info) {
121 RTPVideoHeader rtp_video_header;
122 if (codec_specific_info) {
123 PopulateRtpWithCodecSpecifics(*codec_specific_info, &rtp_video_header);
124 }
125 rtp_video_header.rotation = image.rotation_;
126 rtp_video_header.content_type = image.content_type_;
127 rtp_video_header.playout_delay = image.playout_delay_;
128
129 SetVideoTiming(image, &rtp_video_header.video_timing);
130
131 // Sets picture id and tl0 pic idx.
132 const bool first_frame_in_picture =
133 (codec_specific_info && codec_specific_info->codecType == kVideoCodecVP9)
134 ? codec_specific_info->codecSpecific.VP9.first_frame_in_picture
135 : true;
136 Set(&rtp_video_header, first_frame_in_picture);
137 return rtp_video_header;
138}
139
140uint32_t RtpPayloadParams::ssrc() const {
141 return ssrc_;
142}
143
144RtpPayloadState RtpPayloadParams::state() const {
145 return state_;
146}
147
148void RtpPayloadParams::Set(RTPVideoHeader* rtp_video_header,
149 bool first_frame_in_picture) {
150 // Always set picture id. Set tl0_pic_idx iff temporal index is set.
151 if (first_frame_in_picture) {
152 state_.picture_id = (static_cast<uint16_t>(state_.picture_id) + 1) & 0x7FFF;
153 }
154 if (rtp_video_header->codec == kVideoCodecVP8) {
155 rtp_video_header->vp8().pictureId = state_.picture_id;
156
157 if (rtp_video_header->vp8().temporalIdx != kNoTemporalIdx) {
158 if (rtp_video_header->vp8().temporalIdx == 0) {
159 ++state_.tl0_pic_idx;
160 }
161 rtp_video_header->vp8().tl0PicIdx = state_.tl0_pic_idx;
162 }
163 }
164 if (rtp_video_header->codec == kVideoCodecVP9) {
philipel29d88462018-08-08 14:26:00 +0200165 auto& vp9_header =
166 absl::get<RTPVideoHeaderVP9>(rtp_video_header->video_type_header);
167 vp9_header.picture_id = state_.picture_id;
Stefan Holmerf7044682018-07-17 10:16:41 +0200168
169 // Note that in the case that we have no temporal layers but we do have
170 // spatial layers, packets will carry layering info with a temporal_idx of
171 // zero, and we then have to set and increment tl0_pic_idx.
philipel29d88462018-08-08 14:26:00 +0200172 if (vp9_header.temporal_idx != kNoTemporalIdx ||
173 vp9_header.spatial_idx != kNoSpatialIdx) {
Stefan Holmerf7044682018-07-17 10:16:41 +0200174 if (first_frame_in_picture &&
philipel29d88462018-08-08 14:26:00 +0200175 (vp9_header.temporal_idx == 0 ||
176 vp9_header.temporal_idx == kNoTemporalIdx)) {
Stefan Holmerf7044682018-07-17 10:16:41 +0200177 ++state_.tl0_pic_idx;
178 }
philipel29d88462018-08-08 14:26:00 +0200179 vp9_header.tl0_pic_idx = state_.tl0_pic_idx;
Stefan Holmerf7044682018-07-17 10:16:41 +0200180 }
181 }
182}
183} // namespace webrtc