Line data Source code
1 : /*
2 : * Copyright (c) 2015 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 "webrtc/video/payload_router.h"
12 :
13 : #include "webrtc/base/checks.h"
14 : #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h"
15 : #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h"
16 : #include "webrtc/modules/video_coding/include/video_codec_interface.h"
17 :
18 : namespace webrtc {
19 :
20 : namespace {
21 : // Map information from info into rtp.
22 0 : void CopyCodecSpecific(const CodecSpecificInfo* info, RTPVideoHeader* rtp) {
23 0 : RTC_DCHECK(info);
24 0 : switch (info->codecType) {
25 : case kVideoCodecVP8: {
26 0 : rtp->codec = kRtpVideoVp8;
27 0 : rtp->codecHeader.VP8.InitRTPVideoHeaderVP8();
28 0 : rtp->codecHeader.VP8.pictureId = info->codecSpecific.VP8.pictureId;
29 0 : rtp->codecHeader.VP8.nonReference = info->codecSpecific.VP8.nonReference;
30 0 : rtp->codecHeader.VP8.temporalIdx = info->codecSpecific.VP8.temporalIdx;
31 0 : rtp->codecHeader.VP8.layerSync = info->codecSpecific.VP8.layerSync;
32 0 : rtp->codecHeader.VP8.tl0PicIdx = info->codecSpecific.VP8.tl0PicIdx;
33 0 : rtp->codecHeader.VP8.keyIdx = info->codecSpecific.VP8.keyIdx;
34 0 : rtp->simulcastIdx = info->codecSpecific.VP8.simulcastIdx;
35 0 : return;
36 : }
37 : case kVideoCodecVP9: {
38 0 : rtp->codec = kRtpVideoVp9;
39 0 : rtp->codecHeader.VP9.InitRTPVideoHeaderVP9();
40 0 : rtp->codecHeader.VP9.inter_pic_predicted =
41 0 : info->codecSpecific.VP9.inter_pic_predicted;
42 0 : rtp->codecHeader.VP9.flexible_mode =
43 0 : info->codecSpecific.VP9.flexible_mode;
44 0 : rtp->codecHeader.VP9.ss_data_available =
45 0 : info->codecSpecific.VP9.ss_data_available;
46 0 : rtp->codecHeader.VP9.picture_id = info->codecSpecific.VP9.picture_id;
47 0 : rtp->codecHeader.VP9.tl0_pic_idx = info->codecSpecific.VP9.tl0_pic_idx;
48 0 : rtp->codecHeader.VP9.temporal_idx = info->codecSpecific.VP9.temporal_idx;
49 0 : rtp->codecHeader.VP9.spatial_idx = info->codecSpecific.VP9.spatial_idx;
50 0 : rtp->codecHeader.VP9.temporal_up_switch =
51 0 : info->codecSpecific.VP9.temporal_up_switch;
52 0 : rtp->codecHeader.VP9.inter_layer_predicted =
53 0 : info->codecSpecific.VP9.inter_layer_predicted;
54 0 : rtp->codecHeader.VP9.gof_idx = info->codecSpecific.VP9.gof_idx;
55 0 : rtp->codecHeader.VP9.num_spatial_layers =
56 0 : info->codecSpecific.VP9.num_spatial_layers;
57 :
58 0 : if (info->codecSpecific.VP9.ss_data_available) {
59 0 : rtp->codecHeader.VP9.spatial_layer_resolution_present =
60 0 : info->codecSpecific.VP9.spatial_layer_resolution_present;
61 0 : if (info->codecSpecific.VP9.spatial_layer_resolution_present) {
62 0 : for (size_t i = 0; i < info->codecSpecific.VP9.num_spatial_layers;
63 : ++i) {
64 0 : rtp->codecHeader.VP9.width[i] = info->codecSpecific.VP9.width[i];
65 0 : rtp->codecHeader.VP9.height[i] = info->codecSpecific.VP9.height[i];
66 : }
67 : }
68 0 : rtp->codecHeader.VP9.gof.CopyGofInfoVP9(info->codecSpecific.VP9.gof);
69 : }
70 :
71 0 : rtp->codecHeader.VP9.num_ref_pics = info->codecSpecific.VP9.num_ref_pics;
72 0 : for (int i = 0; i < info->codecSpecific.VP9.num_ref_pics; ++i)
73 0 : rtp->codecHeader.VP9.pid_diff[i] = info->codecSpecific.VP9.p_diff[i];
74 0 : return;
75 : }
76 : case kVideoCodecH264:
77 0 : rtp->codec = kRtpVideoH264;
78 0 : rtp->codecHeader.H264.packetization_mode =
79 0 : info->codecSpecific.H264.packetization_mode;
80 0 : return;
81 : case kVideoCodecGeneric:
82 0 : rtp->codec = kRtpVideoGeneric;
83 0 : rtp->simulcastIdx = info->codecSpecific.generic.simulcast_idx;
84 0 : return;
85 : default:
86 0 : return;
87 : }
88 : }
89 :
90 : } // namespace
91 :
92 0 : PayloadRouter::PayloadRouter(const std::vector<RtpRtcp*>& rtp_modules,
93 0 : int payload_type)
94 : : active_(false),
95 : rtp_modules_(rtp_modules),
96 0 : payload_type_(payload_type) {
97 0 : }
98 :
99 0 : PayloadRouter::~PayloadRouter() {}
100 :
101 0 : void PayloadRouter::SetActive(bool active) {
102 0 : rtc::CritScope lock(&crit_);
103 0 : if (active_ == active)
104 0 : return;
105 0 : active_ = active;
106 :
107 0 : for (auto& module : rtp_modules_) {
108 0 : module->SetSendingStatus(active_);
109 0 : module->SetSendingMediaStatus(active_);
110 : }
111 : }
112 :
113 0 : bool PayloadRouter::IsActive() {
114 0 : rtc::CritScope lock(&crit_);
115 0 : return active_ && !rtp_modules_.empty();
116 : }
117 :
118 0 : EncodedImageCallback::Result PayloadRouter::OnEncodedImage(
119 : const EncodedImage& encoded_image,
120 : const CodecSpecificInfo* codec_specific_info,
121 : const RTPFragmentationHeader* fragmentation) {
122 0 : rtc::CritScope lock(&crit_);
123 0 : RTC_DCHECK(!rtp_modules_.empty());
124 0 : if (!active_)
125 0 : return Result(Result::ERROR_SEND_FAILED);
126 :
127 : RTPVideoHeader rtp_video_header;
128 0 : memset(&rtp_video_header, 0, sizeof(RTPVideoHeader));
129 0 : if (codec_specific_info)
130 0 : CopyCodecSpecific(codec_specific_info, &rtp_video_header);
131 0 : rtp_video_header.rotation = encoded_image.rotation_;
132 0 : rtp_video_header.playout_delay = encoded_image.playout_delay_;
133 :
134 0 : int stream_index = rtp_video_header.simulcastIdx;
135 0 : RTC_DCHECK_LT(stream_index, rtp_modules_.size());
136 : uint32_t frame_id;
137 0 : bool send_result = rtp_modules_[stream_index]->SendOutgoingData(
138 0 : encoded_image._frameType, payload_type_, encoded_image._timeStamp,
139 0 : encoded_image.capture_time_ms_, encoded_image._buffer,
140 0 : encoded_image._length, fragmentation, &rtp_video_header, &frame_id);
141 0 : if (!send_result)
142 0 : return Result(Result::ERROR_SEND_FAILED);
143 :
144 0 : return Result(Result::OK, frame_id);
145 : }
146 :
147 0 : void PayloadRouter::OnBitrateAllocationUpdated(
148 : const BitrateAllocation& bitrate) {
149 0 : rtc::CritScope lock(&crit_);
150 0 : if (IsActive()) {
151 0 : if (rtp_modules_.size() == 1) {
152 : // If spatial scalability is enabled, it is covered by a single stream.
153 0 : rtp_modules_[0]->SetVideoBitrateAllocation(bitrate);
154 : } else {
155 : // Simulcast is in use, split the BitrateAllocation into one struct per
156 : // rtp stream, moving over the temporal layer allocation.
157 0 : for (size_t si = 0; si < rtp_modules_.size(); ++si) {
158 0 : BitrateAllocation layer_bitrate;
159 0 : for (int tl = 0; tl < kMaxTemporalStreams; ++tl)
160 0 : layer_bitrate.SetBitrate(0, tl, bitrate.GetBitrate(si, tl));
161 0 : rtp_modules_[si]->SetVideoBitrateAllocation(layer_bitrate);
162 : }
163 : }
164 : }
165 0 : }
166 :
167 : } // namespace webrtc
|