rtp_receiver_video.cc revision 2ec560606be6519dc4e32a1e6855b0f362ca498d
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
34RTPReceiverVideo::~RTPReceiverVideo() {
35}
36
37bool RTPReceiverVideo::ShouldReportCsrcChanges(
38    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(
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
78int RTPReceiverVideo::GetPayloadTypeFrequency() const {
79  return kVideoPayloadTypeFrequency;
80}
81
82RTPAliveType RTPReceiverVideo::ProcessDeadOrAlive(
83    uint16_t last_payload_length) const {
84  return kRtpDead;
85}
86
87int32_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    LOG(LS_ERROR) << "Failed to created decoder for payload type: "
97                  << payload_type;
98    return -1;
99  }
100  return 0;
101}
102
103// We are not allowed to hold a critical section when calling this function.
104int32_t RTPReceiverVideo::ParseVideoCodecSpecific(
105    WebRtcRTPHeader* rtp_header,
106    const uint8_t* payload_data,
107    uint16_t payload_data_length,
108    RtpVideoCodecTypes video_type,
109    int64_t now_ms,
110    bool is_first_packet) {
111  switch (rtp_header->type.Video.codec) {
112    case kRtpVideoGeneric:
113      rtp_header->type.Video.isFirstPacket = is_first_packet;
114      return ReceiveGenericCodec(rtp_header, payload_data, payload_data_length);
115    case kRtpVideoVp8:
116      return ReceiveVp8Codec(rtp_header, payload_data, payload_data_length);
117    case kRtpVideoH264: {
118      scoped_ptr<RtpDepacketizer> depacketizer(RtpDepacketizer::Create(
119          rtp_header->type.Video.codec, data_callback_));
120      return depacketizer->Parse(rtp_header, payload_data, payload_data_length)
121                 ? 0
122                 : -1;
123    }
124    case kRtpVideoNone:
125      break;
126  }
127  return -1;
128}
129
130int32_t RTPReceiverVideo::BuildRTPheader(
131    const WebRtcRTPHeader* rtp_header,
132    uint8_t* data_buffer) const {
133  data_buffer[0] = static_cast<uint8_t>(0x80);  // version 2
134  data_buffer[1] = static_cast<uint8_t>(rtp_header->header.payloadType);
135  if (rtp_header->header.markerBit) {
136    data_buffer[1] |= kRtpMarkerBitMask;  // MarkerBit is 1
137  }
138  RtpUtility::AssignUWord16ToBuffer(data_buffer + 2,
139                                    rtp_header->header.sequenceNumber);
140  RtpUtility::AssignUWord32ToBuffer(data_buffer + 4,
141                                    rtp_header->header.timestamp);
142  RtpUtility::AssignUWord32ToBuffer(data_buffer + 8, rtp_header->header.ssrc);
143
144  int32_t rtp_header_length = 12;
145
146  // Add the CSRCs if any
147  if (rtp_header->header.numCSRCs > 0) {
148    if (rtp_header->header.numCSRCs > 16) {
149      // error
150      assert(false);
151    }
152    uint8_t* ptr = &data_buffer[rtp_header_length];
153    for (uint32_t i = 0; i < rtp_header->header.numCSRCs; ++i) {
154      RtpUtility::AssignUWord32ToBuffer(ptr, rtp_header->header.arrOfCSRCs[i]);
155      ptr += 4;
156    }
157    data_buffer[0] = (data_buffer[0] & 0xf0) | rtp_header->header.numCSRCs;
158    // Update length of header
159    rtp_header_length += sizeof(uint32_t) * rtp_header->header.numCSRCs;
160  }
161  return rtp_header_length;
162}
163
164int32_t RTPReceiverVideo::ReceiveVp8Codec(WebRtcRTPHeader* rtp_header,
165                                          const uint8_t* payload_data,
166                                          uint16_t payload_data_length) {
167  RtpUtility::RTPPayload parsed_packet;
168  RtpUtility::RTPPayloadParser rtp_payload_parser(
169      kRtpVideoVp8, payload_data, payload_data_length);
170
171  if (!rtp_payload_parser.Parse(parsed_packet))
172    return -1;
173
174  if (parsed_packet.info.VP8.dataLength == 0)
175    return 0;
176
177  rtp_header->frameType = (parsed_packet.frameType == RtpUtility::kIFrame)
178                              ? kVideoFrameKey
179                              : kVideoFrameDelta;
180
181  RTPVideoHeaderVP8* to_header = &rtp_header->type.Video.codecHeader.VP8;
182  RtpUtility::RTPPayloadVP8* from_header = &parsed_packet.info.VP8;
183
184  rtp_header->type.Video.isFirstPacket =
185      from_header->beginningOfPartition && (from_header->partitionID == 0);
186  to_header->nonReference = from_header->nonReferenceFrame;
187  to_header->pictureId =
188      from_header->hasPictureID ? from_header->pictureID : kNoPictureId;
189  to_header->tl0PicIdx =
190      from_header->hasTl0PicIdx ? from_header->tl0PicIdx : kNoTl0PicIdx;
191  if (from_header->hasTID) {
192    to_header->temporalIdx = from_header->tID;
193    to_header->layerSync = from_header->layerSync;
194  } else {
195    to_header->temporalIdx = kNoTemporalIdx;
196    to_header->layerSync = false;
197  }
198  to_header->keyIdx = from_header->hasKeyIdx ? from_header->keyIdx : kNoKeyIdx;
199
200  rtp_header->type.Video.width = from_header->frameWidth;
201  rtp_header->type.Video.height = from_header->frameHeight;
202
203  to_header->partitionId = from_header->partitionID;
204  to_header->beginningOfPartition = from_header->beginningOfPartition;
205
206  if (data_callback_->OnReceivedPayloadData(parsed_packet.info.VP8.data,
207                                            parsed_packet.info.VP8.dataLength,
208                                            rtp_header) != 0) {
209    return -1;
210  }
211  return 0;
212}
213
214int32_t RTPReceiverVideo::ReceiveGenericCodec(
215    WebRtcRTPHeader* rtp_header,
216    const uint8_t* payload_data,
217    uint16_t payload_data_length) {
218  uint8_t generic_header = *payload_data++;
219  --payload_data_length;
220
221  rtp_header->frameType =
222      ((generic_header & RtpFormatVideoGeneric::kKeyFrameBit) != 0) ?
223      kVideoFrameKey : kVideoFrameDelta;
224  rtp_header->type.Video.isFirstPacket =
225      (generic_header & RtpFormatVideoGeneric::kFirstPacketBit) != 0;
226
227  if (data_callback_->OnReceivedPayloadData(
228          payload_data, payload_data_length, rtp_header) != 0) {
229    return -1;
230  }
231  return 0;
232}
233}  // namespace webrtc
234