rtp_receiver_video.cc revision 026b892e724c3f47bde92d773d84099768e57ec8
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.h"
18#include "webrtc/modules/rtp_rtcp/source/rtp_format_video_generic.h"
19#include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
20#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
21#include "webrtc/system_wrappers/interface/logging.h"
22#include "webrtc/system_wrappers/interface/trace_event.h"
23
24namespace webrtc {
25
26RTPReceiverStrategy* RTPReceiverStrategy::CreateVideoStrategy(
27    RtpData* data_callback) {
28  return new RTPReceiverVideo(data_callback);
29}
30
31RTPReceiverVideo::RTPReceiverVideo(RtpData* data_callback)
32    : RTPReceiverStrategy(data_callback) {
33}
34
35RTPReceiverVideo::~RTPReceiverVideo() {
36}
37
38bool RTPReceiverVideo::ShouldReportCsrcChanges(uint8_t payload_type) const {
39  // Always do this for video packets.
40  return true;
41}
42
43int32_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
50int32_t RTPReceiverVideo::ParseRtpPacket(WebRtcRTPHeader* rtp_header,
51                                         const PayloadUnion& specific_payload,
52                                         bool is_red,
53                                         const uint8_t* payload,
54                                         size_t payload_length,
55                                         int64_t timestamp_ms,
56                                         bool is_first_packet) {
57  TRACE_EVENT2("webrtc_rtp",
58               "Video::ParseRtp",
59               "seqnum",
60               rtp_header->header.sequenceNumber,
61               "timestamp",
62               rtp_header->header.timestamp);
63  rtp_header->type.Video.codec = specific_payload.Video.videoCodecType;
64
65  const size_t payload_data_length =
66      payload_length - rtp_header->header.paddingLength;
67
68  if (payload == NULL || payload_data_length == 0) {
69    return data_callback_->OnReceivedPayloadData(NULL, 0, rtp_header) == 0 ? 0
70                                                                           : -1;
71  }
72
73  // We are not allowed to hold a critical section when calling below functions.
74  scoped_ptr<RtpDepacketizer> depacketizer(
75      RtpDepacketizer::Create(rtp_header->type.Video.codec));
76  if (depacketizer.get() == NULL) {
77    LOG(LS_ERROR) << "Failed to create depacketizer.";
78    return -1;
79  }
80
81  rtp_header->type.Video.isFirstPacket = is_first_packet;
82  RtpDepacketizer::ParsedPayload parsed_payload;
83  if (!depacketizer->Parse(&parsed_payload, payload, payload_data_length))
84    return -1;
85
86  rtp_header->frameType = parsed_payload.frame_type;
87  rtp_header->type = parsed_payload.type;
88  return data_callback_->OnReceivedPayloadData(parsed_payload.payload,
89                                               parsed_payload.payload_length,
90                                               rtp_header) == 0
91             ? 0
92             : -1;
93}
94
95int RTPReceiverVideo::GetPayloadTypeFrequency() const {
96  return kVideoPayloadTypeFrequency;
97}
98
99RTPAliveType RTPReceiverVideo::ProcessDeadOrAlive(
100    uint16_t last_payload_length) const {
101  return kRtpDead;
102}
103
104int32_t RTPReceiverVideo::InvokeOnInitializeDecoder(
105    RtpFeedback* callback,
106    int32_t id,
107    int8_t payload_type,
108    const char payload_name[RTP_PAYLOAD_NAME_SIZE],
109    const PayloadUnion& specific_payload) const {
110  // For video we just go with default values.
111  if (-1 ==
112      callback->OnInitializeDecoder(
113          id, payload_type, payload_name, kVideoPayloadTypeFrequency, 1, 0)) {
114    LOG(LS_ERROR) << "Failed to created decoder for payload type: "
115                  << static_cast<int>(payload_type);
116    return -1;
117  }
118  return 0;
119}
120
121int32_t RTPReceiverVideo::BuildRTPheader(const WebRtcRTPHeader* rtp_header,
122                                         uint8_t* data_buffer) const {
123  data_buffer[0] = static_cast<uint8_t>(0x80);  // version 2
124  data_buffer[1] = static_cast<uint8_t>(rtp_header->header.payloadType);
125  if (rtp_header->header.markerBit) {
126    data_buffer[1] |= kRtpMarkerBitMask;  // MarkerBit is 1
127  }
128  RtpUtility::AssignUWord16ToBuffer(data_buffer + 2,
129                                    rtp_header->header.sequenceNumber);
130  RtpUtility::AssignUWord32ToBuffer(data_buffer + 4,
131                                    rtp_header->header.timestamp);
132  RtpUtility::AssignUWord32ToBuffer(data_buffer + 8, rtp_header->header.ssrc);
133
134  int32_t rtp_header_length = 12;
135
136  // Add the CSRCs if any
137  if (rtp_header->header.numCSRCs > 0) {
138    if (rtp_header->header.numCSRCs > 16) {
139      // error
140      assert(false);
141    }
142    uint8_t* ptr = &data_buffer[rtp_header_length];
143    for (uint32_t i = 0; i < rtp_header->header.numCSRCs; ++i) {
144      RtpUtility::AssignUWord32ToBuffer(ptr, rtp_header->header.arrOfCSRCs[i]);
145      ptr += 4;
146    }
147    data_buffer[0] = (data_buffer[0] & 0xf0) | rtp_header->header.numCSRCs;
148    // Update length of header
149    rtp_header_length += sizeof(uint32_t) * rtp_header->header.numCSRCs;
150  }
151  return rtp_header_length;
152}
153
154}  // namespace webrtc
155