- add third_party src.
[platform/framework/web/crosswalk.git] / src / third_party / webrtc / modules / rtp_rtcp / source / rtp_receiver_video.cc
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/trace.h"
21 #include "webrtc/system_wrappers/interface/trace_event.h"
22
23 namespace webrtc {
24
25 RTPReceiverStrategy* RTPReceiverStrategy::CreateVideoStrategy(
26     int32_t id, RtpData* data_callback) {
27   return new RTPReceiverVideo(id, data_callback);
28 }
29
30 RTPReceiverVideo::RTPReceiverVideo(int32_t id, RtpData* data_callback)
31     : RTPReceiverStrategy(data_callback),
32       id_(id) {}
33
34 RTPReceiverVideo::~RTPReceiverVideo() {
35 }
36
37 bool RTPReceiverVideo::ShouldReportCsrcChanges(
38     uint8_t payload_type) const {
39   // Always do this for video packets.
40   return true;
41 }
42
43 int32_t RTPReceiverVideo::OnNewPayloadTypeCreated(
44     const char payload_name[RTP_PAYLOAD_NAME_SIZE],
45     int8_t payload_type,
46     uint32_t frequency) {
47   return 0;
48 }
49
50 int32_t RTPReceiverVideo::ParseRtpPacket(
51     WebRtcRTPHeader* rtp_header,
52     const PayloadUnion& specific_payload,
53     bool is_red,
54     const uint8_t* payload,
55     uint16_t payload_length,
56     int64_t timestamp_ms,
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;
62
63   const uint16_t payload_data_length =
64       payload_length - rtp_header->header.paddingLength;
65
66   if (payload_data_length == 0)
67     return data_callback_->OnReceivedPayloadData(NULL, 0, rtp_header) == 0 ? 0
68                                                                            : -1;
69
70   return ParseVideoCodecSpecific(rtp_header,
71                                  payload,
72                                  payload_data_length,
73                                  specific_payload.Video.videoCodecType,
74                                  timestamp_ms,
75                                  is_first_packet);
76 }
77
78 int RTPReceiverVideo::GetPayloadTypeFrequency() const {
79   return kVideoPayloadTypeFrequency;
80 }
81
82 RTPAliveType RTPReceiverVideo::ProcessDeadOrAlive(
83     uint16_t last_payload_length) const {
84   return kRtpDead;
85 }
86
87 int32_t RTPReceiverVideo::InvokeOnInitializeDecoder(
88     RtpFeedback* callback,
89     int32_t id,
90     int8_t payload_type,
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,
97                  kTraceRtpRtcp,
98                  id,
99                  "Failed to create video decoder for payload type:%d",
100                  payload_type);
101     return -1;
102   }
103   return 0;
104 }
105
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,
112     int64_t now_ms,
113     bool is_first_packet) {
114   WEBRTC_TRACE(kTraceStream,
115                kTraceRtpRtcp,
116                id_,
117                "%s(timestamp:%u)",
118                __FUNCTION__,
119                rtp_header->header.timestamp);
120
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);
125     case kRtpVideoVp8:
126       return ReceiveVp8Codec(rtp_header, payload_data, payload_data_length);
127     case kRtpVideoNone:
128       break;
129   }
130   return -1;
131 }
132
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
140   }
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);
147
148   int32_t rtp_header_length = 12;
149
150   // Add the CSRCs if any
151   if (rtp_header->header.numCSRCs > 0) {
152     if (rtp_header->header.numCSRCs > 16) {
153       // error
154       assert(false);
155     }
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]);
160       ptr += 4;
161     }
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;
165   }
166   return rtp_header_length;
167 }
168
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;
173   uint32_t id;
174   {
175     CriticalSectionScoped cs(crit_sect_.get());
176     id = id_;
177   }
178   ModuleRTPUtility::RTPPayloadParser rtp_payload_parser(
179       kRtpVideoVp8, payload_data, payload_data_length, id);
180
181   if (!rtp_payload_parser.Parse(parsed_packet))
182     return -1;
183
184   if (parsed_packet.info.VP8.dataLength == 0)
185     return 0;
186
187   rtp_header->frameType = (parsed_packet.frameType == ModuleRTPUtility::kIFrame)
188       ? kVideoFrameKey : kVideoFrameDelta;
189
190   RTPVideoHeaderVP8* to_header = &rtp_header->type.Video.codecHeader.VP8;
191   ModuleRTPUtility::RTPPayloadVP8* from_header = &parsed_packet.info.VP8;
192
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;
203   } else {
204     to_header->temporalIdx = kNoTemporalIdx;
205     to_header->layerSync = false;
206   }
207   to_header->keyIdx = from_header->hasKeyIdx ? from_header->keyIdx : kNoKeyIdx;
208
209   rtp_header->type.Video.width = from_header->frameWidth;
210   rtp_header->type.Video.height = from_header->frameHeight;
211
212   to_header->partitionId = from_header->partitionID;
213   to_header->beginningOfPartition = from_header->beginningOfPartition;
214
215   if (data_callback_->OnReceivedPayloadData(parsed_packet.info.VP8.data,
216                                             parsed_packet.info.VP8.dataLength,
217                                             rtp_header) != 0) {
218     return -1;
219   }
220   return 0;
221 }
222
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;
229
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;
235
236   if (data_callback_->OnReceivedPayloadData(
237           payload_data, payload_data_length, rtp_header) != 0) {
238     return -1;
239   }
240   return 0;
241 }
242 }  // namespace webrtc