blob: df9cb023ad89794eb7c96b04ba1a53ac7714b688 [file] [log] [blame]
stefan@webrtc.org2ec56062014-07-31 14:59:24 +00001/*
2 * Copyright (c) 2014 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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "modules/rtp_rtcp/source/rtp_format.h"
stefan@webrtc.org2ec56062014-07-31 14:59:24 +000012
Mirko Bonadei317a1f02019-09-17 17:06:18 +020013#include <memory>
14
Yves Gerey988cc082018-10-23 12:03:01 +020015#include "absl/types/variant.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020016#include "modules/rtp_rtcp/source/rtp_format_h264.h"
17#include "modules/rtp_rtcp/source/rtp_format_video_generic.h"
18#include "modules/rtp_rtcp/source/rtp_format_vp8.h"
19#include "modules/rtp_rtcp/source/rtp_format_vp9.h"
Yves Gerey988cc082018-10-23 12:03:01 +020020#include "modules/video_coding/codecs/h264/include/h264_globals.h"
21#include "modules/video_coding/codecs/vp8/include/vp8_globals.h"
22#include "modules/video_coding/codecs/vp9/include/vp9_globals.h"
Danil Chapovalov376e1142018-09-04 16:11:58 +020023#include "rtc_base/checks.h"
stefan@webrtc.org2ec56062014-07-31 14:59:24 +000024
25namespace webrtc {
Danil Chapovalovf7f8a1f2018-08-28 19:45:31 +020026
27std::unique_ptr<RtpPacketizer> RtpPacketizer::Create(
Mirta Dvornicicfe68daa2019-05-23 13:21:12 +020028 absl::optional<VideoCodecType> type,
Danil Chapovalovf7f8a1f2018-08-28 19:45:31 +020029 rtc::ArrayView<const uint8_t> payload,
30 PayloadSizeLimits limits,
31 // Codec-specific details.
32 const RTPVideoHeader& rtp_video_header,
Niels Möller87e2d782019-03-07 10:18:23 +010033 VideoFrameType frame_type,
Danil Chapovalovf7f8a1f2018-08-28 19:45:31 +020034 const RTPFragmentationHeader* fragmentation) {
Mirta Dvornicicfe68daa2019-05-23 13:21:12 +020035 if (!type) {
36 // Use raw packetizer.
Mirko Bonadei317a1f02019-09-17 17:06:18 +020037 return std::make_unique<RtpPacketizerGeneric>(payload, limits);
Mirta Dvornicicfe68daa2019-05-23 13:21:12 +020038 }
39
40 switch (*type) {
philipel7d745e52018-08-02 14:03:53 +020041 case kVideoCodecH264: {
Danil Chapovalovfd5fbd02018-09-12 10:23:15 +020042 RTC_CHECK(fragmentation);
philipel7d745e52018-08-02 14:03:53 +020043 const auto& h264 =
Danil Chapovalovf7f8a1f2018-08-28 19:45:31 +020044 absl::get<RTPVideoHeaderH264>(rtp_video_header.video_type_header);
Mirko Bonadei317a1f02019-09-17 17:06:18 +020045 return std::make_unique<RtpPacketizerH264>(
Danil Chapovalovfd5fbd02018-09-12 10:23:15 +020046 payload, limits, h264.packetization_mode, *fragmentation);
philipel7d745e52018-08-02 14:03:53 +020047 }
Danil Chapovalovf7f8a1f2018-08-28 19:45:31 +020048 case kVideoCodecVP8: {
49 const auto& vp8 =
50 absl::get<RTPVideoHeaderVP8>(rtp_video_header.video_type_header);
Mirko Bonadei317a1f02019-09-17 17:06:18 +020051 return std::make_unique<RtpPacketizerVp8>(payload, limits, vp8);
Danil Chapovalovf7f8a1f2018-08-28 19:45:31 +020052 }
philipel29d88462018-08-08 14:26:00 +020053 case kVideoCodecVP9: {
54 const auto& vp9 =
Danil Chapovalovf7f8a1f2018-08-28 19:45:31 +020055 absl::get<RTPVideoHeaderVP9>(rtp_video_header.video_type_header);
Mirko Bonadei317a1f02019-09-17 17:06:18 +020056 return std::make_unique<RtpPacketizerVp9>(payload, limits, vp9);
philipel29d88462018-08-08 14:26:00 +020057 }
Danil Chapovalovf7f8a1f2018-08-28 19:45:31 +020058 default: {
Mirko Bonadei317a1f02019-09-17 17:06:18 +020059 return std::make_unique<RtpPacketizerGeneric>(
Danil Chapovalovaf8c0362018-09-05 16:54:22 +020060 payload, limits, rtp_video_header, frame_type);
Danil Chapovalovf7f8a1f2018-08-28 19:45:31 +020061 }
stefan@webrtc.org2ec56062014-07-31 14:59:24 +000062 }
stefan@webrtc.org2ec56062014-07-31 14:59:24 +000063}
64
Danil Chapovalovfa5ec8d2018-09-07 10:57:26 +020065std::vector<int> RtpPacketizer::SplitAboutEqually(
66 int payload_len,
Danil Chapovalov376e1142018-09-04 16:11:58 +020067 const PayloadSizeLimits& limits) {
Danil Chapovalovfa5ec8d2018-09-07 10:57:26 +020068 RTC_DCHECK_GT(payload_len, 0);
69 // First or last packet larger than normal are unsupported.
70 RTC_DCHECK_GE(limits.first_packet_reduction_len, 0);
71 RTC_DCHECK_GE(limits.last_packet_reduction_len, 0);
Danil Chapovalov376e1142018-09-04 16:11:58 +020072
Danil Chapovalovfa5ec8d2018-09-07 10:57:26 +020073 std::vector<int> result;
Danil Chapovalovfcebe0e2018-10-12 17:51:22 +020074 if (limits.max_payload_len >=
75 limits.single_packet_reduction_len + payload_len) {
76 result.push_back(payload_len);
77 return result;
78 }
Danil Chapovalovfa5ec8d2018-09-07 10:57:26 +020079 if (limits.max_payload_len - limits.first_packet_reduction_len < 1 ||
80 limits.max_payload_len - limits.last_packet_reduction_len < 1) {
81 // Capacity is not enough to put a single byte into one of the packets.
82 return result;
83 }
Danil Chapovalovbace3a42018-09-05 16:15:08 +020084 // First and last packet of the frame can be smaller. Pretend that it's
85 // the same size, but we must write more payload to it.
86 // Assume frame fits in single packet if packet has extra space for sum
87 // of first and last packets reductions.
Danil Chapovalovfa5ec8d2018-09-07 10:57:26 +020088 int total_bytes = payload_len + limits.first_packet_reduction_len +
89 limits.last_packet_reduction_len;
Danil Chapovalov376e1142018-09-04 16:11:58 +020090 // Integer divisions with rounding up.
Danil Chapovalovfa5ec8d2018-09-07 10:57:26 +020091 int num_packets_left =
Danil Chapovalov376e1142018-09-04 16:11:58 +020092 (total_bytes + limits.max_payload_len - 1) / limits.max_payload_len;
Danil Chapovalovfcebe0e2018-10-12 17:51:22 +020093 if (num_packets_left == 1) {
94 // Single packet is a special case handled above.
95 num_packets_left = 2;
96 }
Danil Chapovalov376e1142018-09-04 16:11:58 +020097
Danil Chapovalovfa5ec8d2018-09-07 10:57:26 +020098 if (payload_len < num_packets_left) {
99 // Edge case where limits force to have more packets than there are payload
100 // bytes. This may happen when there is single byte of payload that can't be
101 // put into single packet if
102 // first_packet_reduction + last_packet_reduction >= max_payload_len.
103 return result;
104 }
105
106 int bytes_per_packet = total_bytes / num_packets_left;
107 int num_larger_packets = total_bytes % num_packets_left;
108 int remaining_data = payload_len;
109
Danil Chapovalov376e1142018-09-04 16:11:58 +0200110 result.reserve(num_packets_left);
Danil Chapovalovbace3a42018-09-05 16:15:08 +0200111 bool first_packet = true;
Danil Chapovalov376e1142018-09-04 16:11:58 +0200112 while (remaining_data > 0) {
113 // Last num_larger_packets are 1 byte wider than the rest. Increase
114 // per-packet payload size when needed.
115 if (num_packets_left == num_larger_packets)
116 ++bytes_per_packet;
Danil Chapovalovfa5ec8d2018-09-07 10:57:26 +0200117 int current_packet_bytes = bytes_per_packet;
Danil Chapovalovbace3a42018-09-05 16:15:08 +0200118 if (first_packet) {
119 if (current_packet_bytes > limits.first_packet_reduction_len + 1)
120 current_packet_bytes -= limits.first_packet_reduction_len;
121 else
122 current_packet_bytes = 1;
123 }
Danil Chapovalov376e1142018-09-04 16:11:58 +0200124 if (current_packet_bytes > remaining_data) {
125 current_packet_bytes = remaining_data;
126 }
127 // This is not the last packet in the whole payload, but there's no data
128 // left for the last packet. Leave at least one byte for the last packet.
129 if (num_packets_left == 2 && current_packet_bytes == remaining_data) {
130 --current_packet_bytes;
131 }
Danil Chapovalov376e1142018-09-04 16:11:58 +0200132 result.push_back(current_packet_bytes);
133
134 remaining_data -= current_packet_bytes;
135 --num_packets_left;
Danil Chapovalovbace3a42018-09-05 16:15:08 +0200136 first_packet = false;
Danil Chapovalov376e1142018-09-04 16:11:58 +0200137 }
138
139 return result;
140}
141
Mirta Dvornicicfe68daa2019-05-23 13:21:12 +0200142RtpDepacketizer* RtpDepacketizer::Create(absl::optional<VideoCodecType> type) {
143 if (!type) {
144 // Use raw depacketizer.
145 return new RtpDepacketizerGeneric(/*generic_header_enabled=*/false);
146 }
147
148 switch (*type) {
Niels Möller520ca4e2018-06-04 11:14:38 +0200149 case kVideoCodecH264:
pbos@webrtc.org730d2702014-09-29 08:00:22 +0000150 return new RtpDepacketizerH264();
Niels Möller520ca4e2018-06-04 11:14:38 +0200151 case kVideoCodecVP8:
pbos@webrtc.org730d2702014-09-29 08:00:22 +0000152 return new RtpDepacketizerVp8();
Niels Möller520ca4e2018-06-04 11:14:38 +0200153 case kVideoCodecVP9:
asaperssonf38ea3c2015-07-28 04:02:54 -0700154 return new RtpDepacketizerVp9();
Niels Moller1788dcb2018-08-09 06:18:57 +0000155 default:
Mirta Dvornicica24d9342019-05-16 15:51:15 +0200156 return new RtpDepacketizerGeneric(/*generic_header_enabled=*/true);
stefan@webrtc.org2ec56062014-07-31 14:59:24 +0000157 }
stefan@webrtc.org2ec56062014-07-31 14:59:24 +0000158}
Mirta Dvornicicfe68daa2019-05-23 13:21:12 +0200159
stefan@webrtc.org2ec56062014-07-31 14:59:24 +0000160} // namespace webrtc