1 /*
2 * Copyright (c) 2012 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/modules/rtp_rtcp/source/rtp_receiver_video.h"
12
13 #include <assert.h>
14 #include <string.h>
15
16 #include "webrtc/modules/rtp_rtcp/interface/rtp_payload_registry.h"
17 #include "webrtc/modules/rtp_rtcp/source/rtp_format_video_generic.h"
18 #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
19 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
20 #include "webrtc/system_wrappers/interface/logging.h"
21 #include "webrtc/system_wrappers/interface/trace_event.h"
22
23 namespace webrtc {
24
CreateVideoStrategy(RtpData * data_callback)25 RTPReceiverStrategy* RTPReceiverStrategy::CreateVideoStrategy(
26 RtpData* data_callback) {
27 return new RTPReceiverVideo(data_callback);
28 }
29
RTPReceiverVideo(RtpData * data_callback)30 RTPReceiverVideo::RTPReceiverVideo(RtpData* data_callback)
31 : RTPReceiverStrategy(data_callback) {}
32
~RTPReceiverVideo()33 RTPReceiverVideo::~RTPReceiverVideo() {
34 }
35
ShouldReportCsrcChanges(uint8_t payload_type) const36 bool RTPReceiverVideo::ShouldReportCsrcChanges(
37 uint8_t payload_type) const {
38 // Always do this for video packets.
39 return true;
40 }
41
OnNewPayloadTypeCreated(const char payload_name[RTP_PAYLOAD_NAME_SIZE],int8_t payload_type,uint32_t frequency)42 int32_t RTPReceiverVideo::OnNewPayloadTypeCreated(
43 const char payload_name[RTP_PAYLOAD_NAME_SIZE],
44 int8_t payload_type,
45 uint32_t frequency) {
46 return 0;
47 }
48
ParseRtpPacket(WebRtcRTPHeader * rtp_header,const PayloadUnion & specific_payload,bool is_red,const uint8_t * payload,uint16_t payload_length,int64_t timestamp_ms,bool is_first_packet)49 int32_t RTPReceiverVideo::ParseRtpPacket(
50 WebRtcRTPHeader* rtp_header,
51 const PayloadUnion& specific_payload,
52 bool is_red,
53 const uint8_t* payload,
54 uint16_t payload_length,
55 int64_t timestamp_ms,
56 bool is_first_packet) {
57 TRACE_EVENT2("webrtc_rtp", "Video::ParseRtp",
58 "seqnum", rtp_header->header.sequenceNumber,
59 "timestamp", rtp_header->header.timestamp);
60 rtp_header->type.Video.codec = specific_payload.Video.videoCodecType;
61
62 const uint16_t payload_data_length =
63 payload_length - rtp_header->header.paddingLength;
64
65 if (payload_data_length == 0)
66 return data_callback_->OnReceivedPayloadData(NULL, 0, rtp_header) == 0 ? 0
67 : -1;
68
69 return ParseVideoCodecSpecific(rtp_header,
70 payload,
71 payload_data_length,
72 specific_payload.Video.videoCodecType,
73 timestamp_ms,
74 is_first_packet);
75 }
76
GetPayloadTypeFrequency() const77 int RTPReceiverVideo::GetPayloadTypeFrequency() const {
78 return kVideoPayloadTypeFrequency;
79 }
80
ProcessDeadOrAlive(uint16_t last_payload_length) const81 RTPAliveType RTPReceiverVideo::ProcessDeadOrAlive(
82 uint16_t last_payload_length) const {
83 return kRtpDead;
84 }
85
InvokeOnInitializeDecoder(RtpFeedback * callback,int32_t id,int8_t payload_type,const char payload_name[RTP_PAYLOAD_NAME_SIZE],const PayloadUnion & specific_payload) const86 int32_t RTPReceiverVideo::InvokeOnInitializeDecoder(
87 RtpFeedback* callback,
88 int32_t id,
89 int8_t payload_type,
90 const char payload_name[RTP_PAYLOAD_NAME_SIZE],
91 const PayloadUnion& specific_payload) const {
92 // For video we just go with default values.
93 if (-1 == callback->OnInitializeDecoder(
94 id, payload_type, payload_name, kVideoPayloadTypeFrequency, 1, 0)) {
95 LOG(LS_ERROR) << "Failed to created decoder for payload type: "
96 << payload_type;
97 return -1;
98 }
99 return 0;
100 }
101
102 // We are not allowed to hold a critical section when calling this function.
ParseVideoCodecSpecific(WebRtcRTPHeader * rtp_header,const uint8_t * payload_data,uint16_t payload_data_length,RtpVideoCodecTypes video_type,int64_t now_ms,bool is_first_packet)103 int32_t RTPReceiverVideo::ParseVideoCodecSpecific(
104 WebRtcRTPHeader* rtp_header,
105 const uint8_t* payload_data,
106 uint16_t payload_data_length,
107 RtpVideoCodecTypes video_type,
108 int64_t now_ms,
109 bool is_first_packet) {
110 switch (rtp_header->type.Video.codec) {
111 case kRtpVideoGeneric:
112 rtp_header->type.Video.isFirstPacket = is_first_packet;
113 return ReceiveGenericCodec(rtp_header, payload_data, payload_data_length);
114 case kRtpVideoVp8:
115 return ReceiveVp8Codec(rtp_header, payload_data, payload_data_length);
116 case kRtpVideoNone:
117 break;
118 }
119 return -1;
120 }
121
BuildRTPheader(const WebRtcRTPHeader * rtp_header,uint8_t * data_buffer) const122 int32_t RTPReceiverVideo::BuildRTPheader(
123 const WebRtcRTPHeader* rtp_header,
124 uint8_t* data_buffer) const {
125 data_buffer[0] = static_cast<uint8_t>(0x80); // version 2
126 data_buffer[1] = static_cast<uint8_t>(rtp_header->header.payloadType);
127 if (rtp_header->header.markerBit) {
128 data_buffer[1] |= kRtpMarkerBitMask; // MarkerBit is 1
129 }
130 ModuleRTPUtility::AssignUWord16ToBuffer(data_buffer + 2,
131 rtp_header->header.sequenceNumber);
132 ModuleRTPUtility::AssignUWord32ToBuffer(data_buffer + 4,
133 rtp_header->header.timestamp);
134 ModuleRTPUtility::AssignUWord32ToBuffer(data_buffer + 8,
135 rtp_header->header.ssrc);
136
137 int32_t rtp_header_length = 12;
138
139 // Add the CSRCs if any
140 if (rtp_header->header.numCSRCs > 0) {
141 if (rtp_header->header.numCSRCs > 16) {
142 // error
143 assert(false);
144 }
145 uint8_t* ptr = &data_buffer[rtp_header_length];
146 for (uint32_t i = 0; i < rtp_header->header.numCSRCs; ++i) {
147 ModuleRTPUtility::AssignUWord32ToBuffer(ptr,
148 rtp_header->header.arrOfCSRCs[i]);
149 ptr += 4;
150 }
151 data_buffer[0] = (data_buffer[0] & 0xf0) | rtp_header->header.numCSRCs;
152 // Update length of header
153 rtp_header_length += sizeof(uint32_t) * rtp_header->header.numCSRCs;
154 }
155 return rtp_header_length;
156 }
157
ReceiveVp8Codec(WebRtcRTPHeader * rtp_header,const uint8_t * payload_data,uint16_t payload_data_length)158 int32_t RTPReceiverVideo::ReceiveVp8Codec(WebRtcRTPHeader* rtp_header,
159 const uint8_t* payload_data,
160 uint16_t payload_data_length) {
161 ModuleRTPUtility::RTPPayload parsed_packet;
162 ModuleRTPUtility::RTPPayloadParser rtp_payload_parser(
163 kRtpVideoVp8, payload_data, payload_data_length);
164
165 if (!rtp_payload_parser.Parse(parsed_packet))
166 return -1;
167
168 if (parsed_packet.info.VP8.dataLength == 0)
169 return 0;
170
171 rtp_header->frameType = (parsed_packet.frameType == ModuleRTPUtility::kIFrame)
172 ? kVideoFrameKey : kVideoFrameDelta;
173
174 RTPVideoHeaderVP8* to_header = &rtp_header->type.Video.codecHeader.VP8;
175 ModuleRTPUtility::RTPPayloadVP8* from_header = &parsed_packet.info.VP8;
176
177 rtp_header->type.Video.isFirstPacket =
178 from_header->beginningOfPartition && (from_header->partitionID == 0);
179 to_header->nonReference = from_header->nonReferenceFrame;
180 to_header->pictureId =
181 from_header->hasPictureID ? from_header->pictureID : kNoPictureId;
182 to_header->tl0PicIdx =
183 from_header->hasTl0PicIdx ? from_header->tl0PicIdx : kNoTl0PicIdx;
184 if (from_header->hasTID) {
185 to_header->temporalIdx = from_header->tID;
186 to_header->layerSync = from_header->layerSync;
187 } else {
188 to_header->temporalIdx = kNoTemporalIdx;
189 to_header->layerSync = false;
190 }
191 to_header->keyIdx = from_header->hasKeyIdx ? from_header->keyIdx : kNoKeyIdx;
192
193 rtp_header->type.Video.width = from_header->frameWidth;
194 rtp_header->type.Video.height = from_header->frameHeight;
195
196 to_header->partitionId = from_header->partitionID;
197 to_header->beginningOfPartition = from_header->beginningOfPartition;
198
199 if (data_callback_->OnReceivedPayloadData(parsed_packet.info.VP8.data,
200 parsed_packet.info.VP8.dataLength,
201 rtp_header) != 0) {
202 return -1;
203 }
204 return 0;
205 }
206
ReceiveGenericCodec(WebRtcRTPHeader * rtp_header,const uint8_t * payload_data,uint16_t payload_data_length)207 int32_t RTPReceiverVideo::ReceiveGenericCodec(
208 WebRtcRTPHeader* rtp_header,
209 const uint8_t* payload_data,
210 uint16_t payload_data_length) {
211 uint8_t generic_header = *payload_data++;
212 --payload_data_length;
213
214 rtp_header->frameType =
215 ((generic_header & RtpFormatVideoGeneric::kKeyFrameBit) != 0) ?
216 kVideoFrameKey : kVideoFrameDelta;
217 rtp_header->type.Video.isFirstPacket =
218 (generic_header & RtpFormatVideoGeneric::kFirstPacketBit) != 0;
219
220 if (data_callback_->OnReceivedPayloadData(
221 payload_data, payload_data_length, rtp_header) != 0) {
222 return -1;
223 }
224 return 0;
225 }
226 } // namespace webrtc
227