payload-type-handler.cpp 11.5 KB
Newer Older
1 2
/*
 * payload-type-handler.cpp
3
 * Copyright (C) 2010-2018 Belledonne Communications SARL
4
 *
Ghislain MARY's avatar
Ghislain MARY committed
5 6 7 8
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
9 10 11 12 13 14 15
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
Ghislain MARY's avatar
Ghislain MARY committed
16 17
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 19
 */

20
#include <cmath>
21

22 23 24 25
#include "private.h"

#include "logger/logger.h"

26 27
#include "payload-type-handler.h"

28
// =============================================================================
29 30 31 32 33 34 35

using namespace std;

LINPHONE_BEGIN_NAMESPACE

const int PayloadTypeHandler::udpHeaderSize = 8;
const int PayloadTypeHandler::rtpHeaderSize = 12;
36 37 38 39

// 20 is the minimum, but there may be some options.
const int PayloadTypeHandler::ipv4HeaderSize = 20;

40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
const VbrCodecBitrate PayloadTypeHandler::defaultVbrCodecBitrates[] = {
	{ 64, 44100, 50 },
	{ 64, 16000, 40 },
	{ 32, 16000, 32 },
	{ 32, 8000, 32 },
	{ 0, 8000, 24 },
	{ 0, 0, 0 }
};

// =============================================================================

int PayloadTypeHandler::findPayloadTypeNumber (const bctbx_list_t *assigned, const OrtpPayloadType *pt) {
	const OrtpPayloadType *candidate = nullptr;
	for (const bctbx_list_t *elem = assigned; elem != nullptr; elem = bctbx_list_next(elem)) {
		const OrtpPayloadType *it = reinterpret_cast<const OrtpPayloadType *>(bctbx_list_get_data(elem));
55 56 57 58 59
		if (
			strcasecmp(pt->mime_type, payload_type_get_mime(it)) == 0 &&
			it->clock_rate == pt->clock_rate &&
			((it->channels == pt->channels) || (pt->channels <= 0))
		) {
60
			candidate = it;
61 62 63 64 65 66
			if (
				(it->recv_fmtp && pt->recv_fmtp && (strcasecmp(it->recv_fmtp, pt->recv_fmtp) == 0)) ||
				(!it->recv_fmtp && !pt->recv_fmtp)
			)
				// Exact match.
				break;
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
		}
	}
	return candidate ? payload_type_get_number(candidate) : -1;
}

bool PayloadTypeHandler::hasTelephoneEventPayloadType (const bctbx_list_t *tev, int rate) {
	for (const bctbx_list_t *it = tev; it != nullptr; it = bctbx_list_next(it)) {
		const OrtpPayloadType *pt = reinterpret_cast<OrtpPayloadType *>(bctbx_list_get_data(it));
		if (pt->clock_rate == rate)
			return true;
	}
	return false;
}

bool PayloadTypeHandler::isPayloadTypeUsableForBandwidth (const OrtpPayloadType *pt, int bandwidthLimit) {
	const int videoEnablementLimit = 99;
	double codecBand = 0;
	switch (pt->type) {
		case PAYLOAD_AUDIO_CONTINUOUS:
		case PAYLOAD_AUDIO_PACKETIZED:
			codecBand = getAudioPayloadTypeBandwidth(pt, bandwidthLimit);
			return bandwidthIsGreater(bandwidthLimit, (int)codecBand);
		case PAYLOAD_VIDEO:
90 91
			// Infinite or greater than videoEnablementLimit.
			if (bandwidthLimit <= 0 || bandwidthLimit >= videoEnablementLimit)
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
				return true;
			break;
		case PAYLOAD_TEXT:
			return true;
	}
	return false;
}

int PayloadTypeHandler::lookupTypicalVbrBitrate (int maxBandwidth, int clockRate) {
	if (maxBandwidth <= 0)
		maxBandwidth = defaultVbrCodecBitrates[0].maxAvailableBitrate;
	for (const VbrCodecBitrate *it = &defaultVbrCodecBitrates[0]; it->minClockRate != 0; it++) {
		if ((maxBandwidth >= it->maxAvailableBitrate) && (clockRate >= it->minClockRate))
			return it->recommendedBitrate;
	}
	lError() << "lookupTypicalVbrBitrate(): should not happen";
	return 32;
}

// -----------------------------------------------------------------------------

void PayloadTypeHandler::assignPayloadTypeNumbers (const bctbx_list_t *codecs) {
	OrtpPayloadType *red = nullptr;
	OrtpPayloadType *t140 = nullptr;

	for (const bctbx_list_t *elem = codecs; elem != nullptr; elem = bctbx_list_next(elem)) {
		OrtpPayloadType *pt = reinterpret_cast<OrtpPayloadType *>(bctbx_list_get_data(elem));
		int number = payload_type_get_number(pt);

121
		// Check if number is duplicated: it could be the case if the remote forced us to use a mapping with a previous offer.
122 123 124
		if ((number != -1) && !(pt->flags & PAYLOAD_TYPE_FROZEN_NUMBER)) {
			if (!isPayloadTypeNumberAvailable(codecs, number, pt)) {
				lInfo() << "Reassigning payload type " << number << " " << pt->mime_type << "/" << pt->clock_rate << " because already offered";
125 126
				// Need to be re-assigned.
				number = -1;
127 128 129 130
			}
		}

		if (number == -1) {
131
			int dynNumber = getCore()->getCCore()->codecs_conf.dyn_pt;
132 133 134 135 136 137 138 139
			while (dynNumber < 127) {
				if (isPayloadTypeNumberAvailable(codecs, dynNumber, nullptr)) {
					payload_type_set_number(pt, dynNumber);
					dynNumber++;
					break;
				}
				dynNumber++;
			}
140
			if (dynNumber == 127) {
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
				lError() << "Too many payload types configured ! codec " << pt->mime_type << "/" << pt->clock_rate << " is disabled";
				payload_type_set_enable(pt, false);
			}
		}

		if (strcmp(pt->mime_type, payload_type_t140_red.mime_type) == 0)
			red = pt;
		else if (strcmp(pt->mime_type, payload_type_t140.mime_type) == 0)
			t140 = pt;
	}

	if (t140 && red) {
		int t140_payload_type_number = payload_type_get_number(t140);
		char *red_fmtp = ms_strdup_printf("%i/%i/%i", t140_payload_type_number, t140_payload_type_number, t140_payload_type_number);
		payload_type_set_recv_fmtp(red, red_fmtp);
		ms_free(red_fmtp);
	}
}

160
bctbx_list_t *PayloadTypeHandler::createSpecialPayloadTypes (const bctbx_list_t *codecs) {
161
	bctbx_list_t *result = createTelephoneEventPayloadTypes(codecs);
162
	if (linphone_core_generic_comfort_noise_enabled(getCore()->getCCore())) {
163 164 165 166 167 168 169
		OrtpPayloadType *cn = payload_type_clone(&payload_type_cn);
		payload_type_set_number(cn, 13);
		result = bctbx_list_append(result, cn);
	}
	return result;
}

170
bctbx_list_t *PayloadTypeHandler::createTelephoneEventPayloadTypes (const bctbx_list_t *codecs) {
171 172 173
	bctbx_list_t *result = nullptr;
	for (const bctbx_list_t *it = codecs; it != nullptr; it = bctbx_list_next(it)) {
		const OrtpPayloadType *pt = reinterpret_cast<OrtpPayloadType *>(bctbx_list_get_data(it));
174 175 176 177 178 179 180 181
		if (hasTelephoneEventPayloadType(result, pt->clock_rate))
			continue;

		OrtpPayloadType *tev = payload_type_clone(&payload_type_telephone_event);
		tev->clock_rate = pt->clock_rate;
		// Let it choose the number dynamically as for normal codecs.
		payload_type_set_number(tev, -1);
		// But for first telephone-event, prefer the number that was configured in the core.
182 183
		if (!result && isPayloadTypeNumberAvailable(codecs, getCore()->getCCore()->codecs_conf.telephone_event_pt, nullptr))
			payload_type_set_number(tev, getCore()->getCCore()->codecs_conf.telephone_event_pt);
184
		result = bctbx_list_append(result, tev);
185 186 187 188 189
	}
	return result;
}

bool PayloadTypeHandler::isPayloadTypeUsable (const OrtpPayloadType *pt) {
190 191
	return isPayloadTypeUsableForBandwidth(
		pt, getMinBandwidth(
192 193
			linphone_core_get_download_bandwidth(getCore()->getCCore()),
			linphone_core_get_upload_bandwidth(getCore()->getCCore())
194 195
		)
	);
196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219
}

// -----------------------------------------------------------------------------

bool PayloadTypeHandler::bandwidthIsGreater (int bandwidth1, int bandwidth2) {
	if (bandwidth1 <= 0) return true;
	if (bandwidth2 <= 0) return false;
	return bandwidth1 >= bandwidth2;
}

int PayloadTypeHandler::getAudioPayloadTypeBandwidth (const OrtpPayloadType *pt, int maxBandwidth) {
	if (payload_type_is_vbr(pt)) {
		if (pt->flags & PAYLOAD_TYPE_BITRATE_OVERRIDE) {
			lDebug() << "PayloadType " << pt->mime_type << "/" << pt->clock_rate << " has bitrate override";
			return pt->normal_bitrate / 1000;
		}
		return lookupTypicalVbrBitrate(maxBandwidth, pt->clock_rate);
	}
	/* Rounding codec bandwidth should be avoid, specially for AMR */
	return (int)ceil(getAudioPayloadTypeBandwidthFromCodecBitrate(pt) / 1000.0);
}

/*
 *((codec-birate*ptime/8) + RTP header + UDP header + IP header)*8/ptime;
220
 * ptime=1/npacket
221 222 223
 */
double PayloadTypeHandler::getAudioPayloadTypeBandwidthFromCodecBitrate (const OrtpPayloadType *pt) {
	double npacket = 50;
224 225
	if (strcmp(payload_type_get_mime(&payload_type_aaceld_44k), payload_type_get_mime(pt)) == 0)
		// Special case of aac 44K because ptime=10ms.
226
		npacket = 100;
227
	else if (strcmp(payload_type_get_mime(&payload_type_ilbc), payload_type_get_mime(pt)) == 0)
228
		npacket = 1000 / 30.0;
229

230 231 232 233 234 235 236 237 238 239
	int bitrate = pt->normal_bitrate;
	double packet_size = (((double)bitrate) / (npacket * 8)) + udpHeaderSize + rtpHeaderSize + ipv4HeaderSize;
	return packet_size * 8.0 * npacket;
}

int PayloadTypeHandler::getMaxCodecSampleRate (const bctbx_list_t *codecs) {
	int maxSampleRate = 0;
	for (const bctbx_list_t *it = codecs; it != nullptr; it = bctbx_list_next(it)) {
		OrtpPayloadType *pt = reinterpret_cast<OrtpPayloadType *>(bctbx_list_get_data(it));
		int sampleRate;
240 241
		if (strcasecmp("G722", pt->mime_type) == 0)
			// G722 spec says 8000 but the codec actually requires 16000.
242
			sampleRate = 16000;
243
		else
244
			sampleRate = pt->clock_rate;
245

246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273
		if (sampleRate > maxSampleRate)
			maxSampleRate = sampleRate;
	}
	return maxSampleRate;
}

int PayloadTypeHandler::getMinBandwidth (int downBandwidth, int upBandwidth) {
	if (downBandwidth <= 0) return upBandwidth;
	if (upBandwidth <= 0) return downBandwidth;
	return MIN(downBandwidth, upBandwidth);
}

int PayloadTypeHandler::getRemainingBandwidthForVideo (int total, int audio) {
	int remaining = total - audio - 10;
	if (remaining < 0) remaining = 0;
	return remaining;
}

bool PayloadTypeHandler::isPayloadTypeNumberAvailable (const bctbx_list_t *codecs, int number, const OrtpPayloadType *ignore) {
	for (const bctbx_list_t *elem = codecs; elem != nullptr; elem = bctbx_list_next(elem)) {
		const OrtpPayloadType *pt = reinterpret_cast<OrtpPayloadType *>(bctbx_list_get_data(elem));
		if ((pt != ignore) && (payload_type_get_number(pt) == number)) return false;
	}
	return true;
}

// -----------------------------------------------------------------------------

274
bctbx_list_t *PayloadTypeHandler::makeCodecsList (SalStreamType type, int bandwidthLimit, int maxCodecs, const bctbx_list_t *previousList) {
275 276 277 278
	const bctbx_list_t *allCodecs = nullptr;
	switch (type) {
		default:
		case SalAudio:
279
			allCodecs = getCore()->getCCore()->codecs_conf.audio_codecs;
280 281
			break;
		case SalVideo:
282
			allCodecs = getCore()->getCCore()->codecs_conf.video_codecs;
283 284
			break;
		case SalText:
285
			allCodecs = getCore()->getCCore()->codecs_conf.text_codecs;
286 287 288 289 290 291 292 293 294
			break;
	}

	int nb = 0;
	bctbx_list_t *result = nullptr;
	for (const bctbx_list_t *it = allCodecs; it != nullptr; it = bctbx_list_next(it)) {
		OrtpPayloadType *pt = reinterpret_cast<OrtpPayloadType *>(bctbx_list_get_data(it));
		if (!payload_type_enabled(pt))
			continue;
295 296 297

		if (bandwidthLimit > 0 && !isPayloadTypeUsableForBandwidth(pt, bandwidthLimit)) {
			lInfo() << "Codec " << pt->mime_type << "/" << pt->clock_rate << " eliminated because of audio bandwidth constraint of " <<
298
				bandwidthLimit << " kbit/s";
299 300
			continue;
		}
301

302 303
		if (!isPayloadTypeUsable(pt))
			continue;
304

305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326
		pt = payload_type_clone(pt);

		/* Look for a previously assigned number for this codec */
		int num = findPayloadTypeNumber(previousList, pt);
		if (num != -1) {
			payload_type_set_number(pt, num);
			payload_type_set_flag(pt, PAYLOAD_TYPE_FROZEN_NUMBER);
		}

		result = bctbx_list_append(result, pt);
		nb++;
		if ((maxCodecs > 0) && (nb >= maxCodecs)) break;
	}
	if (type == SalAudio) {
		bctbx_list_t *specials = createSpecialPayloadTypes(result);
		result = bctbx_list_concat(result, specials);
	}
	assignPayloadTypeNumbers(result);
	return result;
}

LINPHONE_END_NAMESPACE