Home | History | Annotate | Download | only in source
      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/logging.h"
     21 #include "webrtc/system_wrappers/interface/trace_event.h"
     22 
     23 namespace webrtc {
     24 
     25 RTPReceiverStrategy* RTPReceiverStrategy::CreateVideoStrategy(
     26     RtpData* data_callback) {
     27   return new RTPReceiverVideo(data_callback);
     28 }
     29 
     30 RTPReceiverVideo::RTPReceiverVideo(RtpData* data_callback)
     31     : RTPReceiverStrategy(data_callback) {}
     32 
     33 RTPReceiverVideo::~RTPReceiverVideo() {
     34 }
     35 
     36 bool RTPReceiverVideo::ShouldReportCsrcChanges(
     37     uint8_t payload_type) const {
     38   // Always do this for video packets.
     39   return true;
     40 }
     41 
     42 int32_t RTPReceiverVideo::OnNewPayloadTypeCreated(
     43     const char payload_name[RTP_PAYLOAD_NAME_SIZE],
     44     int8_t payload_type,
     45     uint32_t frequency) {
     46   return 0;
     47 }
     48 
     49 int32_t RTPReceiverVideo::ParseRtpPacket(
     50     WebRtcRTPHeader* rtp_header,
     51     const PayloadUnion& specific_payload,
     52     bool is_red,
     53     const uint8_t* payload,
     54     uint16_t payload_length,
     55     int64_t timestamp_ms,
     56     bool is_first_packet) {
     57   TRACE_EVENT2("webrtc_rtp", "Video::ParseRtp",
     58                "seqnum", rtp_header->header.sequenceNumber,
     59                "timestamp", rtp_header->header.timestamp);
     60   rtp_header->type.Video.codec = specific_payload.Video.videoCodecType;
     61 
     62   const uint16_t payload_data_length =
     63       payload_length - rtp_header->header.paddingLength;
     64 
     65   if (payload_data_length == 0)
     66     return data_callback_->OnReceivedPayloadData(NULL, 0, rtp_header) == 0 ? 0
     67                                                                            : -1;
     68 
     69   return ParseVideoCodecSpecific(rtp_header,
     70                                  payload,
     71                                  payload_data_length,
     72                                  specific_payload.Video.videoCodecType,
     73                                  timestamp_ms,
     74                                  is_first_packet);
     75 }
     76 
     77 int RTPReceiverVideo::GetPayloadTypeFrequency() const {
     78   return kVideoPayloadTypeFrequency;
     79 }
     80 
     81 RTPAliveType RTPReceiverVideo::ProcessDeadOrAlive(
     82     uint16_t last_payload_length) const {
     83   return kRtpDead;
     84 }
     85 
     86 int32_t RTPReceiverVideo::InvokeOnInitializeDecoder(
     87     RtpFeedback* callback,
     88     int32_t id,
     89     int8_t payload_type,
     90     const char payload_name[RTP_PAYLOAD_NAME_SIZE],
     91     const PayloadUnion& specific_payload) const {
     92   // For video we just go with default values.
     93   if (-1 == callback->OnInitializeDecoder(
     94       id, payload_type, payload_name, kVideoPayloadTypeFrequency, 1, 0)) {
     95     LOG(LS_ERROR) << "Failed to created decoder for payload type: "
     96                   << payload_type;
     97     return -1;
     98   }
     99   return 0;
    100 }
    101 
    102 // We are not allowed to hold a critical section when calling this function.
    103 int32_t RTPReceiverVideo::ParseVideoCodecSpecific(
    104     WebRtcRTPHeader* rtp_header,
    105     const uint8_t* payload_data,
    106     uint16_t payload_data_length,
    107     RtpVideoCodecTypes video_type,
    108     int64_t now_ms,
    109     bool is_first_packet) {
    110   switch (rtp_header->type.Video.codec) {
    111     case kRtpVideoGeneric:
    112       rtp_header->type.Video.isFirstPacket = is_first_packet;
    113       return ReceiveGenericCodec(rtp_header, payload_data, payload_data_length);
    114     case kRtpVideoVp8:
    115       return ReceiveVp8Codec(rtp_header, payload_data, payload_data_length);
    116     case kRtpVideoNone:
    117       break;
    118   }
    119   return -1;
    120 }
    121 
    122 int32_t RTPReceiverVideo::BuildRTPheader(
    123     const WebRtcRTPHeader* rtp_header,
    124     uint8_t* data_buffer) const {
    125   data_buffer[0] = static_cast<uint8_t>(0x80);  // version 2
    126   data_buffer[1] = static_cast<uint8_t>(rtp_header->header.payloadType);
    127   if (rtp_header->header.markerBit) {
    128     data_buffer[1] |= kRtpMarkerBitMask;  // MarkerBit is 1
    129   }
    130   ModuleRTPUtility::AssignUWord16ToBuffer(data_buffer + 2,
    131                                           rtp_header->header.sequenceNumber);
    132   ModuleRTPUtility::AssignUWord32ToBuffer(data_buffer + 4,
    133                                           rtp_header->header.timestamp);
    134   ModuleRTPUtility::AssignUWord32ToBuffer(data_buffer + 8,
    135                                           rtp_header->header.ssrc);
    136 
    137   int32_t rtp_header_length = 12;
    138 
    139   // Add the CSRCs if any
    140   if (rtp_header->header.numCSRCs > 0) {
    141     if (rtp_header->header.numCSRCs > 16) {
    142       // error
    143       assert(false);
    144     }
    145     uint8_t* ptr = &data_buffer[rtp_header_length];
    146     for (uint32_t i = 0; i < rtp_header->header.numCSRCs; ++i) {
    147       ModuleRTPUtility::AssignUWord32ToBuffer(ptr,
    148                                               rtp_header->header.arrOfCSRCs[i]);
    149       ptr += 4;
    150     }
    151     data_buffer[0] = (data_buffer[0] & 0xf0) | rtp_header->header.numCSRCs;
    152     // Update length of header
    153     rtp_header_length += sizeof(uint32_t) * rtp_header->header.numCSRCs;
    154   }
    155   return rtp_header_length;
    156 }
    157 
    158 int32_t RTPReceiverVideo::ReceiveVp8Codec(WebRtcRTPHeader* rtp_header,
    159                                           const uint8_t* payload_data,
    160                                           uint16_t payload_data_length) {
    161   ModuleRTPUtility::RTPPayload parsed_packet;
    162   ModuleRTPUtility::RTPPayloadParser rtp_payload_parser(
    163       kRtpVideoVp8, payload_data, payload_data_length);
    164 
    165   if (!rtp_payload_parser.Parse(parsed_packet))
    166     return -1;
    167 
    168   if (parsed_packet.info.VP8.dataLength == 0)
    169     return 0;
    170 
    171   rtp_header->frameType = (parsed_packet.frameType == ModuleRTPUtility::kIFrame)
    172       ? kVideoFrameKey : kVideoFrameDelta;
    173 
    174   RTPVideoHeaderVP8* to_header = &rtp_header->type.Video.codecHeader.VP8;
    175   ModuleRTPUtility::RTPPayloadVP8* from_header = &parsed_packet.info.VP8;
    176 
    177   rtp_header->type.Video.isFirstPacket =
    178       from_header->beginningOfPartition && (from_header->partitionID == 0);
    179   to_header->nonReference = from_header->nonReferenceFrame;
    180   to_header->pictureId =
    181       from_header->hasPictureID ? from_header->pictureID : kNoPictureId;
    182   to_header->tl0PicIdx =
    183       from_header->hasTl0PicIdx ? from_header->tl0PicIdx : kNoTl0PicIdx;
    184   if (from_header->hasTID) {
    185     to_header->temporalIdx = from_header->tID;
    186     to_header->layerSync = from_header->layerSync;
    187   } else {
    188     to_header->temporalIdx = kNoTemporalIdx;
    189     to_header->layerSync = false;
    190   }
    191   to_header->keyIdx = from_header->hasKeyIdx ? from_header->keyIdx : kNoKeyIdx;
    192 
    193   rtp_header->type.Video.width = from_header->frameWidth;
    194   rtp_header->type.Video.height = from_header->frameHeight;
    195 
    196   to_header->partitionId = from_header->partitionID;
    197   to_header->beginningOfPartition = from_header->beginningOfPartition;
    198 
    199   if (data_callback_->OnReceivedPayloadData(parsed_packet.info.VP8.data,
    200                                             parsed_packet.info.VP8.dataLength,
    201                                             rtp_header) != 0) {
    202     return -1;
    203   }
    204   return 0;
    205 }
    206 
    207 int32_t RTPReceiverVideo::ReceiveGenericCodec(
    208     WebRtcRTPHeader* rtp_header,
    209     const uint8_t* payload_data,
    210     uint16_t payload_data_length) {
    211   uint8_t generic_header = *payload_data++;
    212   --payload_data_length;
    213 
    214   rtp_header->frameType =
    215       ((generic_header & RtpFormatVideoGeneric::kKeyFrameBit) != 0) ?
    216       kVideoFrameKey : kVideoFrameDelta;
    217   rtp_header->type.Video.isFirstPacket =
    218       (generic_header & RtpFormatVideoGeneric::kFirstPacketBit) != 0;
    219 
    220   if (data_callback_->OnReceivedPayloadData(
    221           payload_data, payload_data_length, rtp_header) != 0) {
    222     return -1;
    223   }
    224   return 0;
    225 }
    226 }  // namespace webrtc
    227