• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2019 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 "modules/rtp_rtcp/source/video_rtp_depacketizer_generic.h"
12 
13 #include <stddef.h>
14 #include <stdint.h>
15 
16 #include <utility>
17 
18 #include "absl/types/optional.h"
19 #include "modules/rtp_rtcp/source/rtp_video_header.h"
20 #include "modules/rtp_rtcp/source/video_rtp_depacketizer.h"
21 #include "rtc_base/copy_on_write_buffer.h"
22 #include "rtc_base/logging.h"
23 
24 namespace webrtc {
25 namespace {
26 constexpr uint8_t kKeyFrameBit = 0b0000'0001;
27 constexpr uint8_t kFirstPacketBit = 0b0000'0010;
28 // If this bit is set, there will be an extended header contained in this
29 // packet. This was added later so old clients will not send this.
30 constexpr uint8_t kExtendedHeaderBit = 0b0000'0100;
31 
32 constexpr size_t kGenericHeaderLength = 1;
33 constexpr size_t kExtendedHeaderLength = 2;
34 }  // namespace
35 
36 absl::optional<VideoRtpDepacketizer::ParsedRtpPayload>
Parse(rtc::CopyOnWriteBuffer rtp_payload)37 VideoRtpDepacketizerGeneric::Parse(rtc::CopyOnWriteBuffer rtp_payload) {
38   if (rtp_payload.size() == 0) {
39     RTC_LOG(LS_WARNING) << "Empty payload.";
40     return absl::nullopt;
41   }
42   absl::optional<ParsedRtpPayload> parsed(absl::in_place);
43   const uint8_t* payload_data = rtp_payload.cdata();
44 
45   uint8_t generic_header = payload_data[0];
46   size_t offset = kGenericHeaderLength;
47 
48   parsed->video_header.frame_type = (generic_header & kKeyFrameBit)
49                                         ? VideoFrameType::kVideoFrameKey
50                                         : VideoFrameType::kVideoFrameDelta;
51   parsed->video_header.is_first_packet_in_frame =
52       (generic_header & kFirstPacketBit) != 0;
53   parsed->video_header.codec = kVideoCodecGeneric;
54   parsed->video_header.width = 0;
55   parsed->video_header.height = 0;
56 
57   if (generic_header & kExtendedHeaderBit) {
58     if (rtp_payload.size() < offset + kExtendedHeaderLength) {
59       RTC_LOG(LS_WARNING) << "Too short payload for generic header.";
60       return absl::nullopt;
61     }
62     parsed->video_header.video_type_header
63         .emplace<RTPVideoHeaderLegacyGeneric>()
64         .picture_id = ((payload_data[1] & 0x7F) << 8) | payload_data[2];
65     offset += kExtendedHeaderLength;
66   }
67 
68   parsed->video_payload =
69       rtp_payload.Slice(offset, rtp_payload.size() - offset);
70   return parsed;
71 }
72 }  // namespace webrtc
73