• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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