2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
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.
11 #include "webrtc/modules/rtp_rtcp/source/rtp_receiver_video.h"
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/trace.h"
21 #include "webrtc/system_wrappers/interface/trace_event.h"
25 RTPReceiverStrategy* RTPReceiverStrategy::CreateVideoStrategy(
26 int32_t id, RtpData* data_callback) {
27 return new RTPReceiverVideo(id, data_callback);
30 RTPReceiverVideo::RTPReceiverVideo(int32_t id, RtpData* data_callback)
31 : RTPReceiverStrategy(data_callback),
34 RTPReceiverVideo::~RTPReceiverVideo() {
37 bool RTPReceiverVideo::ShouldReportCsrcChanges(
38 uint8_t payload_type) const {
39 // Always do this for video packets.
43 int32_t RTPReceiverVideo::OnNewPayloadTypeCreated(
44 const char payload_name[RTP_PAYLOAD_NAME_SIZE],
50 int32_t RTPReceiverVideo::ParseRtpPacket(
51 WebRtcRTPHeader* rtp_header,
52 const PayloadUnion& specific_payload,
54 const uint8_t* payload,
55 uint16_t payload_length,
57 bool is_first_packet) {
58 TRACE_EVENT2("webrtc_rtp", "Video::ParseRtp",
59 "seqnum", rtp_header->header.sequenceNumber,
60 "timestamp", rtp_header->header.timestamp);
61 rtp_header->type.Video.codec = specific_payload.Video.videoCodecType;
63 const uint16_t payload_data_length =
64 payload_length - rtp_header->header.paddingLength;
66 if (payload_data_length == 0)
67 return data_callback_->OnReceivedPayloadData(NULL, 0, rtp_header) == 0 ? 0
70 return ParseVideoCodecSpecific(rtp_header,
73 specific_payload.Video.videoCodecType,
78 int RTPReceiverVideo::GetPayloadTypeFrequency() const {
79 return kVideoPayloadTypeFrequency;
82 RTPAliveType RTPReceiverVideo::ProcessDeadOrAlive(
83 uint16_t last_payload_length) const {
87 int32_t RTPReceiverVideo::InvokeOnInitializeDecoder(
88 RtpFeedback* callback,
91 const char payload_name[RTP_PAYLOAD_NAME_SIZE],
92 const PayloadUnion& specific_payload) const {
93 // For video we just go with default values.
94 if (-1 == callback->OnInitializeDecoder(
95 id, payload_type, payload_name, kVideoPayloadTypeFrequency, 1, 0)) {
96 WEBRTC_TRACE(kTraceError,
99 "Failed to create video decoder for payload type:%d",
106 // We are not allowed to hold a critical section when calling this function.
107 int32_t RTPReceiverVideo::ParseVideoCodecSpecific(
108 WebRtcRTPHeader* rtp_header,
109 const uint8_t* payload_data,
110 uint16_t payload_data_length,
111 RtpVideoCodecTypes video_type,
113 bool is_first_packet) {
114 WEBRTC_TRACE(kTraceStream,
119 rtp_header->header.timestamp);
121 switch (rtp_header->type.Video.codec) {
122 case kRtpVideoGeneric:
123 rtp_header->type.Video.isFirstPacket = is_first_packet;
124 return ReceiveGenericCodec(rtp_header, payload_data, payload_data_length);
126 return ReceiveVp8Codec(rtp_header, payload_data, payload_data_length);
133 int32_t RTPReceiverVideo::BuildRTPheader(
134 const WebRtcRTPHeader* rtp_header,
135 uint8_t* data_buffer) const {
136 data_buffer[0] = static_cast<uint8_t>(0x80); // version 2
137 data_buffer[1] = static_cast<uint8_t>(rtp_header->header.payloadType);
138 if (rtp_header->header.markerBit) {
139 data_buffer[1] |= kRtpMarkerBitMask; // MarkerBit is 1
141 ModuleRTPUtility::AssignUWord16ToBuffer(data_buffer + 2,
142 rtp_header->header.sequenceNumber);
143 ModuleRTPUtility::AssignUWord32ToBuffer(data_buffer + 4,
144 rtp_header->header.timestamp);
145 ModuleRTPUtility::AssignUWord32ToBuffer(data_buffer + 8,
146 rtp_header->header.ssrc);
148 int32_t rtp_header_length = 12;
150 // Add the CSRCs if any
151 if (rtp_header->header.numCSRCs > 0) {
152 if (rtp_header->header.numCSRCs > 16) {
156 uint8_t* ptr = &data_buffer[rtp_header_length];
157 for (uint32_t i = 0; i < rtp_header->header.numCSRCs; ++i) {
158 ModuleRTPUtility::AssignUWord32ToBuffer(ptr,
159 rtp_header->header.arrOfCSRCs[i]);
162 data_buffer[0] = (data_buffer[0] & 0xf0) | rtp_header->header.numCSRCs;
163 // Update length of header
164 rtp_header_length += sizeof(uint32_t) * rtp_header->header.numCSRCs;
166 return rtp_header_length;
169 int32_t RTPReceiverVideo::ReceiveVp8Codec(WebRtcRTPHeader* rtp_header,
170 const uint8_t* payload_data,
171 uint16_t payload_data_length) {
172 ModuleRTPUtility::RTPPayload parsed_packet;
175 CriticalSectionScoped cs(crit_sect_.get());
178 ModuleRTPUtility::RTPPayloadParser rtp_payload_parser(
179 kRtpVideoVp8, payload_data, payload_data_length, id);
181 if (!rtp_payload_parser.Parse(parsed_packet))
184 if (parsed_packet.info.VP8.dataLength == 0)
187 rtp_header->frameType = (parsed_packet.frameType == ModuleRTPUtility::kIFrame)
188 ? kVideoFrameKey : kVideoFrameDelta;
190 RTPVideoHeaderVP8* to_header = &rtp_header->type.Video.codecHeader.VP8;
191 ModuleRTPUtility::RTPPayloadVP8* from_header = &parsed_packet.info.VP8;
193 rtp_header->type.Video.isFirstPacket =
194 from_header->beginningOfPartition && (from_header->partitionID == 0);
195 to_header->nonReference = from_header->nonReferenceFrame;
196 to_header->pictureId =
197 from_header->hasPictureID ? from_header->pictureID : kNoPictureId;
198 to_header->tl0PicIdx =
199 from_header->hasTl0PicIdx ? from_header->tl0PicIdx : kNoTl0PicIdx;
200 if (from_header->hasTID) {
201 to_header->temporalIdx = from_header->tID;
202 to_header->layerSync = from_header->layerSync;
204 to_header->temporalIdx = kNoTemporalIdx;
205 to_header->layerSync = false;
207 to_header->keyIdx = from_header->hasKeyIdx ? from_header->keyIdx : kNoKeyIdx;
209 rtp_header->type.Video.width = from_header->frameWidth;
210 rtp_header->type.Video.height = from_header->frameHeight;
212 to_header->partitionId = from_header->partitionID;
213 to_header->beginningOfPartition = from_header->beginningOfPartition;
215 if (data_callback_->OnReceivedPayloadData(parsed_packet.info.VP8.data,
216 parsed_packet.info.VP8.dataLength,
223 int32_t RTPReceiverVideo::ReceiveGenericCodec(
224 WebRtcRTPHeader* rtp_header,
225 const uint8_t* payload_data,
226 uint16_t payload_data_length) {
227 uint8_t generic_header = *payload_data++;
228 --payload_data_length;
230 rtp_header->frameType =
231 ((generic_header & RtpFormatVideoGeneric::kKeyFrameBit) != 0) ?
232 kVideoFrameKey : kVideoFrameDelta;
233 rtp_header->type.Video.isFirstPacket =
234 (generic_header & RtpFormatVideoGeneric::kFirstPacketBit) != 0;
236 if (data_callback_->OnReceivedPayloadData(
237 payload_data, payload_data_length, rtp_header) != 0) {
242 } // namespace webrtc