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/base/checks.h"
17 #include "webrtc/base/logging.h"
18 #include "webrtc/base/trace_event.h"
19 #include "webrtc/modules/rtp_rtcp/include/rtp_cvo.h"
20 #include "webrtc/modules/rtp_rtcp/include/rtp_payload_registry.h"
21 #include "webrtc/modules/rtp_rtcp/source/rtp_format.h"
22 #include "webrtc/modules/rtp_rtcp/source/rtp_format_video_generic.h"
23 #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
24 #include "webrtc/system_wrappers/include/critical_section_wrapper.h"
25 
26 namespace webrtc {
27 
CreateVideoStrategy(RtpData * data_callback)28 RTPReceiverStrategy* RTPReceiverStrategy::CreateVideoStrategy(
29     RtpData* data_callback) {
30   return new RTPReceiverVideo(data_callback);
31 }
32 
RTPReceiverVideo(RtpData * data_callback)33 RTPReceiverVideo::RTPReceiverVideo(RtpData* data_callback)
34     : RTPReceiverStrategy(data_callback) {
35 }
36 
~RTPReceiverVideo()37 RTPReceiverVideo::~RTPReceiverVideo() {
38 }
39 
ShouldReportCsrcChanges(uint8_t payload_type) const40 bool RTPReceiverVideo::ShouldReportCsrcChanges(uint8_t payload_type) const {
41   // Always do this for video packets.
42   return true;
43 }
44 
OnNewPayloadTypeCreated(const char payload_name[RTP_PAYLOAD_NAME_SIZE],int8_t payload_type,uint32_t frequency)45 int32_t RTPReceiverVideo::OnNewPayloadTypeCreated(
46     const char payload_name[RTP_PAYLOAD_NAME_SIZE],
47     int8_t payload_type,
48     uint32_t frequency) {
49   return 0;
50 }
51 
ParseRtpPacket(WebRtcRTPHeader * rtp_header,const PayloadUnion & specific_payload,bool is_red,const uint8_t * payload,size_t payload_length,int64_t timestamp_ms,bool is_first_packet)52 int32_t RTPReceiverVideo::ParseRtpPacket(WebRtcRTPHeader* rtp_header,
53                                          const PayloadUnion& specific_payload,
54                                          bool is_red,
55                                          const uint8_t* payload,
56                                          size_t payload_length,
57                                          int64_t timestamp_ms,
58                                          bool is_first_packet) {
59   TRACE_EVENT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "Video::ParseRtp",
60                "seqnum", rtp_header->header.sequenceNumber, "timestamp",
61                rtp_header->header.timestamp);
62   rtp_header->type.Video.codec = specific_payload.Video.videoCodecType;
63 
64   RTC_DCHECK_GE(payload_length, rtp_header->header.paddingLength);
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   rtc::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   rtp_header->type.Video.rotation = kVideoRotation_0;
89 
90   // Retrieve the video rotation information.
91   if (rtp_header->header.extension.hasVideoRotation) {
92     rtp_header->type.Video.rotation = ConvertCVOByteToVideoRotation(
93         rtp_header->header.extension.videoRotation);
94   }
95 
96   return data_callback_->OnReceivedPayloadData(parsed_payload.payload,
97                                                parsed_payload.payload_length,
98                                                rtp_header) == 0
99              ? 0
100              : -1;
101 }
102 
GetPayloadTypeFrequency() const103 int RTPReceiverVideo::GetPayloadTypeFrequency() const {
104   return kVideoPayloadTypeFrequency;
105 }
106 
ProcessDeadOrAlive(uint16_t last_payload_length) const107 RTPAliveType RTPReceiverVideo::ProcessDeadOrAlive(
108     uint16_t last_payload_length) const {
109   return kRtpDead;
110 }
111 
InvokeOnInitializeDecoder(RtpFeedback * callback,int8_t payload_type,const char payload_name[RTP_PAYLOAD_NAME_SIZE],const PayloadUnion & specific_payload) const112 int32_t RTPReceiverVideo::InvokeOnInitializeDecoder(
113     RtpFeedback* callback,
114     int8_t payload_type,
115     const char payload_name[RTP_PAYLOAD_NAME_SIZE],
116     const PayloadUnion& specific_payload) const {
117   // For video we just go with default values.
118   if (-1 ==
119       callback->OnInitializeDecoder(payload_type, payload_name,
120                                     kVideoPayloadTypeFrequency, 1, 0)) {
121     LOG(LS_ERROR) << "Failed to created decoder for payload type: "
122                   << static_cast<int>(payload_type);
123     return -1;
124   }
125   return 0;
126 }
127 
128 }  // namespace webrtc
129