blob: bddec73687945528723298de41ddb55ca3e1580e [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
hta9aa96882016-12-06 05:36:03 -080013#include <utility>
14
Danil Chapovalovf7f8a1f2018-08-28 19:45:31 +020015#include "absl/memory/memory.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"
Danil Chapovalov376e1142018-09-04 16:11:58 +020020#include "rtc_base/checks.h"
stefan@webrtc.org2ec56062014-07-31 14:59:24 +000021
22namespace webrtc {
Danil Chapovalovf7f8a1f2018-08-28 19:45:31 +020023
24std::unique_ptr<RtpPacketizer> RtpPacketizer::Create(
25 VideoCodecType type,
26 rtc::ArrayView<const uint8_t> payload,
27 PayloadSizeLimits limits,
28 // Codec-specific details.
29 const RTPVideoHeader& rtp_video_header,
30 FrameType frame_type,
31 const RTPFragmentationHeader* fragmentation) {
stefan@webrtc.org2ec56062014-07-31 14:59:24 +000032 switch (type) {
philipel7d745e52018-08-02 14:03:53 +020033 case kVideoCodecH264: {
34 const auto& h264 =
Danil Chapovalovf7f8a1f2018-08-28 19:45:31 +020035 absl::get<RTPVideoHeaderH264>(rtp_video_header.video_type_header);
36 auto packetizer = absl::make_unique<RtpPacketizerH264>(
37 limits.max_payload_len, limits.last_packet_reduction_len,
38 h264.packetization_mode);
39 packetizer->SetPayloadData(payload.data(), payload.size(), fragmentation);
40 return std::move(packetizer);
philipel7d745e52018-08-02 14:03:53 +020041 }
Danil Chapovalovf7f8a1f2018-08-28 19:45:31 +020042 case kVideoCodecVP8: {
43 const auto& vp8 =
44 absl::get<RTPVideoHeaderVP8>(rtp_video_header.video_type_header);
Danil Chapovalov8d1b5822018-08-30 11:14:05 +020045 return absl::make_unique<RtpPacketizerVp8>(payload, limits, vp8);
Danil Chapovalovf7f8a1f2018-08-28 19:45:31 +020046 }
philipel29d88462018-08-08 14:26:00 +020047 case kVideoCodecVP9: {
48 const auto& vp9 =
Danil Chapovalovf7f8a1f2018-08-28 19:45:31 +020049 absl::get<RTPVideoHeaderVP9>(rtp_video_header.video_type_header);
50 auto packetizer = absl::make_unique<RtpPacketizerVp9>(
51 vp9, limits.max_payload_len, limits.last_packet_reduction_len);
52 packetizer->SetPayloadData(payload.data(), payload.size(), nullptr);
53 return std::move(packetizer);
philipel29d88462018-08-08 14:26:00 +020054 }
Danil Chapovalovf7f8a1f2018-08-28 19:45:31 +020055 default: {
56 auto packetizer = absl::make_unique<RtpPacketizerGeneric>(
57 rtp_video_header, frame_type, limits.max_payload_len,
58 limits.last_packet_reduction_len);
59 packetizer->SetPayloadData(payload.data(), payload.size(), nullptr);
60 return std::move(packetizer);
61 }
stefan@webrtc.org2ec56062014-07-31 14:59:24 +000062 }
stefan@webrtc.org2ec56062014-07-31 14:59:24 +000063}
64
Danil Chapovalov376e1142018-09-04 16:11:58 +020065std::vector<size_t> RtpPacketizer::SplitAboutEqually(
66 size_t payload_len,
67 const PayloadSizeLimits& limits) {
68 RTC_CHECK_GT(limits.max_payload_len, limits.last_packet_reduction_len);
69
70 // Last packet can be smaller. Pretend that it's the same size, but we must
71 // write more payload to it.
72 size_t total_bytes = payload_len + limits.last_packet_reduction_len;
73 // Integer divisions with rounding up.
74 size_t num_packets_left =
75 (total_bytes + limits.max_payload_len - 1) / limits.max_payload_len;
76 size_t bytes_per_packet = total_bytes / num_packets_left;
77 size_t num_larger_packets = total_bytes % num_packets_left;
78 size_t remaining_data = payload_len;
79
80 std::vector<size_t> result;
81 result.reserve(num_packets_left);
82 while (remaining_data > 0) {
83 // Last num_larger_packets are 1 byte wider than the rest. Increase
84 // per-packet payload size when needed.
85 if (num_packets_left == num_larger_packets)
86 ++bytes_per_packet;
87 size_t current_packet_bytes = bytes_per_packet;
88 if (current_packet_bytes > remaining_data) {
89 current_packet_bytes = remaining_data;
90 }
91 // This is not the last packet in the whole payload, but there's no data
92 // left for the last packet. Leave at least one byte for the last packet.
93 if (num_packets_left == 2 && current_packet_bytes == remaining_data) {
94 --current_packet_bytes;
95 }
96
97 result.push_back(current_packet_bytes);
98
99 remaining_data -= current_packet_bytes;
100 --num_packets_left;
101 }
102
103 return result;
104}
105
Niels Möller520ca4e2018-06-04 11:14:38 +0200106RtpDepacketizer* RtpDepacketizer::Create(VideoCodecType type) {
stefan@webrtc.org2ec56062014-07-31 14:59:24 +0000107 switch (type) {
Niels Möller520ca4e2018-06-04 11:14:38 +0200108 case kVideoCodecH264:
pbos@webrtc.org730d2702014-09-29 08:00:22 +0000109 return new RtpDepacketizerH264();
Niels Möller520ca4e2018-06-04 11:14:38 +0200110 case kVideoCodecVP8:
pbos@webrtc.org730d2702014-09-29 08:00:22 +0000111 return new RtpDepacketizerVp8();
Niels Möller520ca4e2018-06-04 11:14:38 +0200112 case kVideoCodecVP9:
asaperssonf38ea3c2015-07-28 04:02:54 -0700113 return new RtpDepacketizerVp9();
Niels Moller1788dcb2018-08-09 06:18:57 +0000114 default:
Niels Möller2ff1f2a2018-08-09 16:16:34 +0200115 return new RtpDepacketizerGeneric();
stefan@webrtc.org2ec56062014-07-31 14:59:24 +0000116 }
stefan@webrtc.org2ec56062014-07-31 14:59:24 +0000117}
118} // namespace webrtc