blob: d0915cc0051e51c0775e811e7dd9a942cbc74025 [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: {
philipel7d745e52018-08-02 14:03:53 +020072 auto& h264_header = rtp->video_type_header.emplace<RTPVideoHeaderH264>();
73 h264_header.packetization_mode =
Stefan Holmerf7044682018-07-17 10:16:41 +020074 info.codecSpecific.H264.packetization_mode;
75 rtp->simulcastIdx = info.codecSpecific.H264.simulcast_idx;
76 return;
77 }
78 case kVideoCodecMultiplex:
79 case kVideoCodecGeneric:
80 rtp->codec = kVideoCodecGeneric;
81 rtp->simulcastIdx = info.codecSpecific.generic.simulcast_idx;
82 return;
83 default:
84 return;
85 }
86}
87
88void SetVideoTiming(const EncodedImage& image, VideoSendTiming* timing) {
89 if (image.timing_.flags == VideoSendTiming::TimingFrameFlags::kInvalid ||
90 image.timing_.flags == VideoSendTiming::TimingFrameFlags::kNotTriggered) {
91 timing->flags = VideoSendTiming::TimingFrameFlags::kInvalid;
92 return;
93 }
94
95 timing->encode_start_delta_ms = VideoSendTiming::GetDeltaCappedMs(
96 image.capture_time_ms_, image.timing_.encode_start_ms);
97 timing->encode_finish_delta_ms = VideoSendTiming::GetDeltaCappedMs(
98 image.capture_time_ms_, image.timing_.encode_finish_ms);
99 timing->packetization_finish_delta_ms = 0;
100 timing->pacer_exit_delta_ms = 0;
101 timing->network_timestamp_delta_ms = 0;
102 timing->network2_timestamp_delta_ms = 0;
103 timing->flags = image.timing_.flags;
104}
105} // namespace
106
107RtpPayloadParams::RtpPayloadParams(const uint32_t ssrc,
108 const RtpPayloadState* state)
109 : ssrc_(ssrc) {
110 Random random(rtc::TimeMicros());
111 state_.picture_id =
112 state ? state->picture_id : (random.Rand<int16_t>() & 0x7FFF);
113 state_.tl0_pic_idx = state ? state->tl0_pic_idx : (random.Rand<uint8_t>());
114}
115RtpPayloadParams::~RtpPayloadParams() {}
116
117RTPVideoHeader RtpPayloadParams::GetRtpVideoHeader(
118 const EncodedImage& image,
119 const CodecSpecificInfo* codec_specific_info) {
120 RTPVideoHeader rtp_video_header;
121 if (codec_specific_info) {
122 PopulateRtpWithCodecSpecifics(*codec_specific_info, &rtp_video_header);
123 }
124 rtp_video_header.rotation = image.rotation_;
125 rtp_video_header.content_type = image.content_type_;
126 rtp_video_header.playout_delay = image.playout_delay_;
127
128 SetVideoTiming(image, &rtp_video_header.video_timing);
129
130 // Sets picture id and tl0 pic idx.
131 const bool first_frame_in_picture =
132 (codec_specific_info && codec_specific_info->codecType == kVideoCodecVP9)
133 ? codec_specific_info->codecSpecific.VP9.first_frame_in_picture
134 : true;
135 Set(&rtp_video_header, first_frame_in_picture);
136 return rtp_video_header;
137}
138
139uint32_t RtpPayloadParams::ssrc() const {
140 return ssrc_;
141}
142
143RtpPayloadState RtpPayloadParams::state() const {
144 return state_;
145}
146
147void RtpPayloadParams::Set(RTPVideoHeader* rtp_video_header,
148 bool first_frame_in_picture) {
149 // Always set picture id. Set tl0_pic_idx iff temporal index is set.
150 if (first_frame_in_picture) {
151 state_.picture_id = (static_cast<uint16_t>(state_.picture_id) + 1) & 0x7FFF;
152 }
153 if (rtp_video_header->codec == kVideoCodecVP8) {
154 rtp_video_header->vp8().pictureId = state_.picture_id;
155
156 if (rtp_video_header->vp8().temporalIdx != kNoTemporalIdx) {
157 if (rtp_video_header->vp8().temporalIdx == 0) {
158 ++state_.tl0_pic_idx;
159 }
160 rtp_video_header->vp8().tl0PicIdx = state_.tl0_pic_idx;
161 }
162 }
163 if (rtp_video_header->codec == kVideoCodecVP9) {
164 rtp_video_header->vp9().picture_id = state_.picture_id;
165
166 // Note that in the case that we have no temporal layers but we do have
167 // spatial layers, packets will carry layering info with a temporal_idx of
168 // zero, and we then have to set and increment tl0_pic_idx.
169 if (rtp_video_header->vp9().temporal_idx != kNoTemporalIdx ||
170 rtp_video_header->vp9().spatial_idx != kNoSpatialIdx) {
171 if (first_frame_in_picture &&
172 (rtp_video_header->vp9().temporal_idx == 0 ||
173 rtp_video_header->vp9().temporal_idx == kNoTemporalIdx)) {
174 ++state_.tl0_pic_idx;
175 }
176 rtp_video_header->vp9().tl0_pic_idx = state_.tl0_pic_idx;
177 }
178 }
179}
180} // namespace webrtc