rtp_receiver_video.cc revision 2f44673d665899ca788ae44247a9a7f4764f5e2b
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 <math.h>
14
15#include <cassert>  // assert
16#include <cstring>  // memcpy()
17
18#include "webrtc/modules/rtp_rtcp/source/receiver_fec.h"
19#include "webrtc/modules/rtp_rtcp/source/rtp_format_video_generic.h"
20#include "webrtc/modules/rtp_rtcp/source/rtp_payload_registry.h"
21#include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h"
22#include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
23#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
24#include "webrtc/system_wrappers/interface/trace.h"
25#include "webrtc/system_wrappers/interface/trace_event.h"
26
27namespace webrtc {
28uint32_t BitRateBPS(uint16_t x) {
29  return (x & 0x3fff) * uint32_t(pow(10.0f, (2 + (x >> 14))));
30}
31
32RTPReceiverVideo::RTPReceiverVideo(
33    const int32_t id,
34    const RTPPayloadRegistry* rtp_rtp_payload_registry,
35    RtpData* data_callback)
36    : RTPReceiverStrategy(data_callback),
37      id_(id),
38      rtp_rtp_payload_registry_(rtp_rtp_payload_registry),
39      critical_section_receiver_video_(
40          CriticalSectionWrapper::CreateCriticalSection()),
41      current_fec_frame_decoded_(false),
42      receive_fec_(NULL) {
43}
44
45RTPReceiverVideo::~RTPReceiverVideo() {
46  delete critical_section_receiver_video_;
47  delete receive_fec_;
48}
49
50bool RTPReceiverVideo::ShouldReportCsrcChanges(
51    uint8_t payload_type) const {
52  // Always do this for video packets.
53  return true;
54}
55
56int32_t RTPReceiverVideo::OnNewPayloadTypeCreated(
57    const char payload_name[RTP_PAYLOAD_NAME_SIZE],
58    const int8_t payload_type,
59    const uint32_t frequency) {
60  if (ModuleRTPUtility::StringCompare(payload_name, "ULPFEC", 6)) {
61    // Enable FEC if not enabled.
62    if (receive_fec_ == NULL) {
63      receive_fec_ = new ReceiverFEC(id_, this);
64    }
65    receive_fec_->SetPayloadTypeFEC(payload_type);
66  }
67  return 0;
68}
69
70int32_t RTPReceiverVideo::ParseRtpPacket(
71    WebRtcRTPHeader* rtp_header,
72    const ModuleRTPUtility::PayloadUnion& specific_payload,
73    const bool is_red,
74    const uint8_t* packet,
75    const uint16_t packet_length,
76    const int64_t timestamp_ms,
77    const bool is_first_packet) {
78  TRACE_EVENT_INSTANT2("webrtc_rtp", "RTPReceiverVideo::ParseRtpPacket",
79                       "seqnum", rtp_header->header.sequenceNumber,
80                       "timestamp", rtp_header->header.timestamp);
81  const uint8_t* payload_data =
82      ModuleRTPUtility::GetPayloadData(rtp_header, packet);
83  const uint16_t payload_data_length =
84      ModuleRTPUtility::GetPayloadDataLength(rtp_header, packet_length);
85  return ParseVideoCodecSpecific(rtp_header,
86                                 payload_data,
87                                 payload_data_length,
88                                 specific_payload.Video.videoCodecType,
89                                 is_red,
90                                 packet,
91                                 packet_length,
92                                 timestamp_ms,
93                                 is_first_packet);
94}
95
96int32_t RTPReceiverVideo::GetFrequencyHz() const {
97  return kDefaultVideoFrequency;
98}
99
100RTPAliveType RTPReceiverVideo::ProcessDeadOrAlive(
101    uint16_t last_payload_length) const {
102  return kRtpDead;
103}
104
105int32_t RTPReceiverVideo::InvokeOnInitializeDecoder(
106    RtpFeedback* callback,
107    const int32_t id,
108    const int8_t payload_type,
109    const char payload_name[RTP_PAYLOAD_NAME_SIZE],
110    const ModuleRTPUtility::PayloadUnion& specific_payload) const {
111  // For video we just go with default values.
112  if (-1 == callback->OnInitializeDecoder(
113      id, payload_type, payload_name, kDefaultVideoFrequency, 1, 0)) {
114    WEBRTC_TRACE(kTraceError,
115                 kTraceRtpRtcp,
116                 id,
117                 "Failed to create video decoder for payload type:%d",
118                 payload_type);
119    return -1;
120  }
121  return 0;
122}
123
124// we have no critext when calling this
125// we are not allowed to have any critsects when calling
126// CallbackOfReceivedPayloadData
127int32_t RTPReceiverVideo::ParseVideoCodecSpecific(
128    WebRtcRTPHeader* rtp_header,
129    const uint8_t* payload_data,
130    const uint16_t payload_data_length,
131    const RtpVideoCodecTypes video_type,
132    const bool is_red,
133    const uint8_t* incoming_rtp_packet,
134    const uint16_t incoming_rtp_packet_size,
135    const int64_t now_ms,
136    const bool is_first_packet) {
137  int32_t ret_val = 0;
138
139  critical_section_receiver_video_->Enter();
140
141  if (is_red) {
142    if (receive_fec_ == NULL) {
143      critical_section_receiver_video_->Leave();
144      return -1;
145    }
146    bool FECpacket = false;
147    ret_val = receive_fec_->AddReceivedFECPacket(
148        rtp_header, incoming_rtp_packet, payload_data_length, FECpacket);
149    if (ret_val != -1) {
150      ret_val = receive_fec_->ProcessReceivedFEC();
151    }
152    critical_section_receiver_video_->Leave();
153
154    if (ret_val == 0 && FECpacket) {
155      // Callback with the received FEC packet.
156      // The normal packets are delivered after parsing.
157      // This contains the original RTP packet header but with
158      // empty payload and data length.
159      rtp_header->frameType = kFrameEmpty;
160      // We need this for the routing.
161      int32_t ret_val = SetCodecType(video_type, rtp_header);
162      if (ret_val != 0) {
163        return ret_val;
164      }
165      // Pass the length of FEC packets so that they can be accounted for in
166      // the bandwidth estimator.
167      ret_val = data_callback_->OnReceivedPayloadData(
168          NULL, payload_data_length, rtp_header);
169    }
170  } else {
171    // will leave the critical_section_receiver_video_ critsect
172    ret_val = ParseVideoCodecSpecificSwitch(rtp_header,
173                                            payload_data,
174                                            payload_data_length,
175                                            video_type,
176                                            is_first_packet);
177  }
178  return ret_val;
179}
180
181int32_t RTPReceiverVideo::BuildRTPheader(
182    const WebRtcRTPHeader* rtp_header,
183    uint8_t* data_buffer) const {
184  data_buffer[0] = static_cast<uint8_t>(0x80);  // version 2
185  data_buffer[1] = static_cast<uint8_t>(rtp_header->header.payloadType);
186  if (rtp_header->header.markerBit) {
187    data_buffer[1] |= kRtpMarkerBitMask;  // MarkerBit is 1
188  }
189  ModuleRTPUtility::AssignUWord16ToBuffer(data_buffer + 2,
190                                          rtp_header->header.sequenceNumber);
191  ModuleRTPUtility::AssignUWord32ToBuffer(data_buffer + 4,
192                                          rtp_header->header.timestamp);
193  ModuleRTPUtility::AssignUWord32ToBuffer(data_buffer + 8,
194                                          rtp_header->header.ssrc);
195
196  int32_t rtp_header_length = 12;
197
198  // Add the CSRCs if any
199  if (rtp_header->header.numCSRCs > 0) {
200    if (rtp_header->header.numCSRCs > 16) {
201      // error
202      assert(false);
203    }
204    uint8_t* ptr = &data_buffer[rtp_header_length];
205    for (uint32_t i = 0; i < rtp_header->header.numCSRCs; ++i) {
206      ModuleRTPUtility::AssignUWord32ToBuffer(ptr,
207                                              rtp_header->header.arrOfCSRCs[i]);
208      ptr += 4;
209    }
210    data_buffer[0] = (data_buffer[0] & 0xf0) | rtp_header->header.numCSRCs;
211    // Update length of header
212    rtp_header_length += sizeof(uint32_t) * rtp_header->header.numCSRCs;
213  }
214  return rtp_header_length;
215}
216
217int32_t RTPReceiverVideo::ReceiveRecoveredPacketCallback(
218    WebRtcRTPHeader* rtp_header,
219    const uint8_t* payload_data,
220    const uint16_t payload_data_length) {
221  // TODO(pwestin) Re-factor this to avoid the messy critsect handling.
222  critical_section_receiver_video_->Enter();
223
224  current_fec_frame_decoded_ = true;
225
226  ModuleRTPUtility::Payload* payload = NULL;
227  if (rtp_rtp_payload_registry_->PayloadTypeToPayload(
228          rtp_header->header.payloadType, payload) != 0) {
229    critical_section_receiver_video_->Leave();
230    return -1;
231  }
232  // here we can re-create the original lost packet so that we can use it for
233  // the relay we need to re-create the RED header too
234  uint8_t recovered_packet[IP_PACKET_SIZE];
235  uint16_t rtp_header_length =
236      (uint16_t) BuildRTPheader(rtp_header, recovered_packet);
237
238  const uint8_t kREDForFECHeaderLength = 1;
239
240  // replace pltype
241  recovered_packet[1] &= 0x80;  // Reset.
242  recovered_packet[1] += rtp_rtp_payload_registry_->red_payload_type();
243
244  // add RED header
245  recovered_packet[rtp_header_length] = rtp_header->header.payloadType;
246  // f-bit always 0
247
248  memcpy(recovered_packet + rtp_header_length + kREDForFECHeaderLength,
249         payload_data,
250         payload_data_length);
251
252  // A recovered packet can be the first packet, but we lack the ability to
253  // detect it at the moment since we do not store the history of recently
254  // received packets. Most codecs like VP8 deal with this in other ways.
255  bool is_first_packet = false;
256
257  return ParseVideoCodecSpecificSwitch(
258      rtp_header,
259      payload_data,
260      payload_data_length,
261      payload->typeSpecific.Video.videoCodecType,
262      is_first_packet);
263}
264
265int32_t RTPReceiverVideo::SetCodecType(
266    const RtpVideoCodecTypes video_type,
267    WebRtcRTPHeader* rtp_header) const {
268  switch (video_type) {
269    case kRtpGenericVideo:
270      rtp_header->type.Video.codec = kRTPVideoGeneric;
271      break;
272    case kRtpVp8Video:
273      rtp_header->type.Video.codec = kRTPVideoVP8;
274      break;
275    case kRtpFecVideo:
276      rtp_header->type.Video.codec = kRTPVideoFEC;
277      break;
278  }
279  return 0;
280}
281
282int32_t RTPReceiverVideo::ParseVideoCodecSpecificSwitch(
283    WebRtcRTPHeader* rtp_header,
284    const uint8_t* payload_data,
285    const uint16_t payload_data_length,
286    const RtpVideoCodecTypes video_type,
287    const bool is_first_packet) {
288  int32_t ret_val = SetCodecType(video_type, rtp_header);
289  if (ret_val != 0) {
290    critical_section_receiver_video_->Leave();
291    return ret_val;
292  }
293  WEBRTC_TRACE(kTraceStream,
294               kTraceRtpRtcp,
295               id_,
296               "%s(timestamp:%u)",
297               __FUNCTION__,
298               rtp_header->header.timestamp);
299
300  // All receive functions release critical_section_receiver_video_ before
301  // returning.
302  switch (video_type) {
303    case kRtpGenericVideo:
304      rtp_header->type.Video.isFirstPacket = is_first_packet;
305      return ReceiveGenericCodec(rtp_header, payload_data, payload_data_length);
306    case kRtpVp8Video:
307      return ReceiveVp8Codec(rtp_header, payload_data, payload_data_length);
308    case kRtpFecVideo:
309      break;
310  }
311  critical_section_receiver_video_->Leave();
312  return -1;
313}
314
315int32_t RTPReceiverVideo::ReceiveVp8Codec(
316    WebRtcRTPHeader* rtp_header,
317    const uint8_t* payload_data,
318    const uint16_t payload_data_length) {
319  bool success;
320  ModuleRTPUtility::RTPPayload parsed_packet;
321  if (payload_data_length == 0) {
322    success = true;
323    parsed_packet.info.VP8.dataLength = 0;
324  } else {
325    ModuleRTPUtility::RTPPayloadParser rtp_payload_parser(
326        kRtpVp8Video, payload_data, payload_data_length, id_);
327
328    success = rtp_payload_parser.Parse(parsed_packet);
329  }
330  // from here down we only work on local data
331  critical_section_receiver_video_->Leave();
332
333  if (!success) {
334    return -1;
335  }
336  if (parsed_packet.info.VP8.dataLength == 0) {
337    // we have an "empty" VP8 packet, it's ok, could be one way video
338    // Inform the jitter buffer about this packet.
339    rtp_header->frameType = kFrameEmpty;
340    if (data_callback_->OnReceivedPayloadData(NULL, 0, rtp_header) != 0) {
341      return -1;
342    }
343    return 0;
344  }
345  rtp_header->frameType = (parsed_packet.frameType == ModuleRTPUtility::kIFrame)
346      ? kVideoFrameKey : kVideoFrameDelta;
347
348  RTPVideoHeaderVP8* to_header = &rtp_header->type.Video.codecHeader.VP8;
349  ModuleRTPUtility::RTPPayloadVP8* from_header = &parsed_packet.info.VP8;
350
351  rtp_header->type.Video.isFirstPacket =
352      from_header->beginningOfPartition && (from_header->partitionID == 0);
353  to_header->nonReference = from_header->nonReferenceFrame;
354  to_header->pictureId =
355      from_header->hasPictureID ? from_header->pictureID : kNoPictureId;
356  to_header->tl0PicIdx =
357      from_header->hasTl0PicIdx ? from_header->tl0PicIdx : kNoTl0PicIdx;
358  if (from_header->hasTID) {
359    to_header->temporalIdx = from_header->tID;
360    to_header->layerSync = from_header->layerSync;
361  } else {
362    to_header->temporalIdx = kNoTemporalIdx;
363    to_header->layerSync = false;
364  }
365  to_header->keyIdx = from_header->hasKeyIdx ? from_header->keyIdx : kNoKeyIdx;
366
367  rtp_header->type.Video.width = from_header->frameWidth;
368  rtp_header->type.Video.height = from_header->frameHeight;
369
370  to_header->partitionId = from_header->partitionID;
371  to_header->beginningOfPartition = from_header->beginningOfPartition;
372
373  if (data_callback_->OnReceivedPayloadData(parsed_packet.info.VP8.data,
374                                            parsed_packet.info.VP8.dataLength,
375                                            rtp_header) != 0) {
376    return -1;
377  }
378  return 0;
379}
380
381int32_t RTPReceiverVideo::ReceiveGenericCodec(
382    WebRtcRTPHeader* rtp_header,
383    const uint8_t* payload_data,
384    uint16_t payload_data_length) {
385  uint8_t generic_header = *payload_data++;
386  --payload_data_length;
387
388  rtp_header->frameType =
389      ((generic_header & RtpFormatVideoGeneric::kKeyFrameBit) != 0) ?
390      kVideoFrameKey : kVideoFrameDelta;
391  rtp_header->type.Video.isFirstPacket =
392      (generic_header & RtpFormatVideoGeneric::kFirstPacketBit) != 0;
393
394  critical_section_receiver_video_->Leave();
395
396  if (data_callback_->OnReceivedPayloadData(
397          payload_data, payload_data_length, rtp_header) != 0) {
398    return -1;
399  }
400  return 0;
401}
402}  // namespace webrtc
403