1 /* $Id$ */
2 /*
3 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
4 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20 #include <pjmedia/vid_codec_util.h>
21 #include <pjmedia/errno.h>
22 #include <pjmedia/stream_common.h>
23 #include <pjlib-util/base64.h>
24 #include <pj/ctype.h>
25 #include <pj/math.h>
26
27
28 #if defined(PJMEDIA_HAS_VIDEO) && (PJMEDIA_HAS_VIDEO != 0)
29
30
31 #define THIS_FILE "vid_codec_util.c"
32
33 /* If this is set to non-zero, H.264 custom negotiation will require
34 * "profile-level-id" and "packetization-mode" to be exact match to
35 * get a successful negotiation. Note that flexible answer (updating
36 * SDP answer to match remote offer) is always active regardless the
37 * value of this macro.
38 */
39 #define H264_STRICT_SDP_NEGO 0
40
41 /* Default frame rate, if not specified */
42 #define DEFAULT_H264_FPS_NUM 10
43 #define DEFAULT_H264_FPS_DENUM 1
44
45 /* Default aspect ratio, if not specified */
46 #define DEFAULT_H264_RATIO_NUM 4
47 #define DEFAULT_H264_RATIO_DENUM 3
48
49
50 /* ITU resolution definition */
51 struct mpi_resolution_t
52 {
53 pj_str_t name;
54 pjmedia_rect_size size;
55 }
56 mpi_resolutions [] =
57 {
58 {{"CIF",3}, {352,288}},
59 {{"QCIF",4}, {176,144}},
60 {{"SQCIF",5}, {88,72}},
61 {{"CIF4",4}, {704,576}},
62 {{"CIF16",5}, {1408,1142}},
63 };
64
65
66 #define CALC_H264_MB_NUM(size) (((size.w+15)/16)*((size.h+15)/16))
67 #define CALC_H264_MBPS(size,fps) CALC_H264_MB_NUM(size)*fps.num/fps.denum
68
69
70 /* Parse fmtp value for custom resolution, e.g: "CUSTOM=800,600,2" */
parse_custom_res_fmtp(const pj_str_t * fmtp_val,pjmedia_rect_size * size,unsigned * mpi)71 static pj_status_t parse_custom_res_fmtp(const pj_str_t *fmtp_val,
72 pjmedia_rect_size *size,
73 unsigned *mpi)
74 {
75 const char *p, *p_end;
76 pj_str_t token;
77 unsigned long val[3] = {0};
78 unsigned i = 0;
79
80 p = token.ptr = fmtp_val->ptr;
81 p_end = p + fmtp_val->slen;
82
83 while (p<=p_end && i<PJ_ARRAY_SIZE(val)) {
84 if (*p==',' || p==p_end) {
85 token.slen = (char*)p - token.ptr;
86 val[i++] = pj_strtoul(&token);
87 token.ptr = (char*)p+1;
88 }
89 ++p;
90 }
91
92 if (!val[0] || !val[1])
93 return PJ_ETOOSMALL;
94
95 if (val[2]<1 || val[2]>32)
96 return PJ_EINVAL;
97
98 size->w = val[0];
99 size->h = val[1];
100 *mpi = val[2];
101 return PJ_SUCCESS;
102 }
103
104
105 /* H263 fmtp parser */
pjmedia_vid_codec_parse_h263_fmtp(const pjmedia_codec_fmtp * fmtp,pjmedia_vid_codec_h263_fmtp * h263_fmtp)106 PJ_DEF(pj_status_t) pjmedia_vid_codec_parse_h263_fmtp(
107 const pjmedia_codec_fmtp *fmtp,
108 pjmedia_vid_codec_h263_fmtp *h263_fmtp)
109 {
110 const pj_str_t CUSTOM = {"CUSTOM", 6};
111 unsigned i;
112
113 pj_bzero(h263_fmtp, sizeof(*h263_fmtp));
114
115 for (i=0; i<fmtp->cnt; ++i) {
116 unsigned j;
117 pj_bool_t parsed = PJ_FALSE;
118
119 if (h263_fmtp->mpi_cnt >= PJ_ARRAY_SIZE(h263_fmtp->mpi)) {
120 pj_assert(!"Too small MPI array in H263 fmtp");
121 continue;
122 }
123
124 /* Standard size MPIs */
125 for (j=0; j<PJ_ARRAY_SIZE(mpi_resolutions) && !parsed; ++j) {
126 if (pj_stricmp(&fmtp->param[i].name, &mpi_resolutions[j].name)==0)
127 {
128 unsigned mpi;
129
130 mpi = pj_strtoul(&fmtp->param[i].val);
131 if (mpi<1 || mpi>32)
132 return PJMEDIA_SDP_EINFMTP;
133
134 h263_fmtp->mpi[h263_fmtp->mpi_cnt].size =
135 mpi_resolutions[j].size;
136 h263_fmtp->mpi[h263_fmtp->mpi_cnt].val = mpi;
137 ++h263_fmtp->mpi_cnt;
138 parsed = PJ_TRUE;
139 }
140 }
141 if (parsed)
142 continue;
143
144 /* Custom size MPIs */
145 if (pj_stricmp(&fmtp->param[i].name, &CUSTOM)==0) {
146 pjmedia_rect_size size;
147 unsigned mpi;
148 pj_status_t status;
149
150 status = parse_custom_res_fmtp(&fmtp->param[i].val, &size, &mpi);
151 if (status != PJ_SUCCESS)
152 return PJMEDIA_SDP_EINFMTP;
153
154 h263_fmtp->mpi[h263_fmtp->mpi_cnt].size = size;
155 h263_fmtp->mpi[h263_fmtp->mpi_cnt].val = mpi;
156 ++h263_fmtp->mpi_cnt;
157 }
158 }
159
160 return PJ_SUCCESS;
161 }
162
163
fps_to_mpi(const pjmedia_ratio * fps)164 static unsigned fps_to_mpi(const pjmedia_ratio *fps)
165 {
166 unsigned mpi;
167
168 /* Original formula = (fps->denum * 30000) / (fps->num * 1001) */
169 mpi = (fps->denum*30000 + fps->num*1001/2) / (fps->num*1001);
170
171 /* Normalize, should be in the range of 1-32 */
172 if (mpi > 32) mpi = 32;
173 if (mpi < 1) mpi = 1;
174
175 return mpi;
176 }
177
pjmedia_vid_codec_h263_apply_fmtp(pjmedia_vid_codec_param * param)178 PJ_DEF(pj_status_t) pjmedia_vid_codec_h263_apply_fmtp(
179 pjmedia_vid_codec_param *param)
180 {
181 if (param->dir & PJMEDIA_DIR_ENCODING) {
182 pjmedia_vid_codec_h263_fmtp fmtp_loc, fmtp_rem;
183 pjmedia_rect_size size = {0};
184 unsigned mpi = 0;
185 pjmedia_video_format_detail *vfd;
186 pj_status_t status;
187
188 vfd = pjmedia_format_get_video_format_detail(¶m->enc_fmt,
189 PJ_TRUE);
190
191 /* Get local param */
192 // Local param should be fetched from "param->enc_fmt" instead of
193 // "param->dec_fmtp".
194 //status = pjmedia_vid_codec_parse_h263_fmtp(¶m->dec_fmtp,
195 // &fmtp_loc);
196 //if (status != PJ_SUCCESS)
197 // return status;
198 fmtp_loc.mpi_cnt = 1;
199 fmtp_loc.mpi[0].size = vfd->size;
200 fmtp_loc.mpi[0].val = fps_to_mpi(&vfd->fps);
201
202 /* Get remote param */
203 status = pjmedia_vid_codec_parse_h263_fmtp(¶m->enc_fmtp,
204 &fmtp_rem);
205 if (status != PJ_SUCCESS)
206 return status;
207
208 /* Negotiate size & MPI setting */
209 if (fmtp_rem.mpi_cnt == 0) {
210 /* Remote doesn't specify MPI setting, send QCIF=1 */
211 size.w = 176;
212 size.h = 144;
213 mpi = 1;
214 //} else if (fmtp_loc.mpi_cnt == 0) {
215 // /* Local MPI setting not set, just use remote preference. */
216 // size = fmtp_rem.mpi[0].size;
217 // mpi = fmtp_rem.mpi[0].val;
218 } else {
219 /* Both have preferences, let's try to match them */
220 unsigned i, j;
221 pj_bool_t matched = PJ_FALSE;
222 pj_uint32_t min_diff = 0xFFFFFFFF;
223 pj_uint32_t loc_sq, rem_sq, diff;
224
225 /* Find the exact size match or the closest size, then choose
226 * the highest MPI among the match/closest pair.
227 */
228 for (i = 0; i < fmtp_rem.mpi_cnt && !matched; ++i) {
229 rem_sq = fmtp_rem.mpi[i].size.w * fmtp_rem.mpi[i].size.h;
230 for (j = 0; j < fmtp_loc.mpi_cnt; ++j) {
231 /* See if we got exact match */
232 if (fmtp_rem.mpi[i].size.w == fmtp_loc.mpi[j].size.w &&
233 fmtp_rem.mpi[i].size.h == fmtp_loc.mpi[j].size.h)
234 {
235 size = fmtp_rem.mpi[i].size;
236 mpi = PJ_MAX(fmtp_rem.mpi[i].val,
237 fmtp_loc.mpi[j].val);
238 matched = PJ_TRUE;
239 break;
240 }
241
242 /* Otherwise keep looking for the closest match */
243 loc_sq = fmtp_loc.mpi[j].size.w * fmtp_loc.mpi[j].size.h;
244 diff = loc_sq>rem_sq? (loc_sq-rem_sq):(rem_sq-loc_sq);
245 if (diff < min_diff) {
246 size = rem_sq<loc_sq? fmtp_rem.mpi[i].size :
247 fmtp_loc.mpi[j].size;
248 mpi = PJ_MAX(fmtp_rem.mpi[i].val,
249 fmtp_loc.mpi[j].val);
250 }
251 }
252 }
253 }
254
255 /* Apply the negotiation result */
256 vfd->size = size;
257 vfd->fps.num = 30000;
258 vfd->fps.denum = 1001 * mpi;
259 }
260
261 if (param->dir & PJMEDIA_DIR_DECODING) {
262 /* Here we just want to find the highest resolution and the lowest MPI
263 * we support and set it as the decoder param.
264 */
265 pjmedia_vid_codec_h263_fmtp fmtp;
266 pjmedia_video_format_detail *vfd;
267 pj_status_t status;
268
269 status = pjmedia_vid_codec_parse_h263_fmtp(¶m->dec_fmtp,
270 &fmtp);
271 if (status != PJ_SUCCESS)
272 return status;
273
274 vfd = pjmedia_format_get_video_format_detail(¶m->dec_fmt,
275 PJ_TRUE);
276
277 if (fmtp.mpi_cnt == 0) {
278 /* No resolution specified, lets just assume 4CIF=1! */
279 vfd->size.w = 704;
280 vfd->size.h = 576;
281 vfd->fps.num = 30000;
282 vfd->fps.denum = 1001;
283 } else {
284 unsigned i, max_size = 0, max_size_idx = 0, min_mpi = 32;
285
286 /* Get the largest size and the lowest MPI */
287 for (i = 0; i < fmtp.mpi_cnt; ++i) {
288 if (fmtp.mpi[i].size.w * fmtp.mpi[i].size.h > max_size) {
289 max_size = fmtp.mpi[i].size.w * fmtp.mpi[i].size.h;
290 max_size_idx = i;
291 }
292 if (fmtp.mpi[i].val < min_mpi)
293 min_mpi = fmtp.mpi[i].val;
294 }
295
296 vfd->size = fmtp.mpi[max_size_idx].size;
297 vfd->fps.num = 30000;
298 vfd->fps.denum = 1001 * min_mpi;
299 }
300 }
301
302 return PJ_SUCCESS;
303 }
304
305
306 /* Declaration of H.264 level info */
307 typedef struct h264_level_info_t
308 {
309 unsigned id; /* Level id. */
310 unsigned max_mbps; /* Max macroblocks per second. */
311 unsigned max_mb; /* Max macroblocks. */
312 unsigned max_br; /* Max bitrate (kbps). */
313 } h264_level_info_t;
314
315
316 /* Init H264 parameters based on profile-level-id */
init_h264_profile(const pj_str_t * profile,pjmedia_vid_codec_h264_fmtp * fmtp)317 static pj_status_t init_h264_profile(const pj_str_t *profile,
318 pjmedia_vid_codec_h264_fmtp *fmtp)
319 {
320 const h264_level_info_t level_info[] =
321 {
322 { 10, 1485, 99, 64 },
323 { 9, 1485, 99, 128 }, /*< level 1b */
324 { 11, 3000, 396, 192 },
325 { 12, 6000, 396, 384 },
326 { 13, 11880, 396, 768 },
327 { 20, 11880, 396, 2000 },
328 { 21, 19800, 792, 4000 },
329 { 22, 20250, 1620, 4000 },
330 { 30, 40500, 1620, 10000 },
331 { 31, 108000, 3600, 14000 },
332 { 32, 216000, 5120, 20000 },
333 { 40, 245760, 8192, 20000 },
334 { 41, 245760, 8192, 50000 },
335 { 42, 522240, 8704, 50000 },
336 { 50, 589824, 22080, 135000 },
337 { 51, 983040, 36864, 240000 },
338 };
339 unsigned i, tmp;
340 pj_str_t endst;
341 const h264_level_info_t *li = NULL;
342
343 if (profile->slen != 6)
344 return PJMEDIA_SDP_EINFMTP;
345
346 tmp = pj_strtoul2(profile, &endst, 16);
347 if (endst.slen)
348 return PJMEDIA_SDP_EINFMTP;
349
350 fmtp->profile_idc = (pj_uint8_t)((tmp >> 16) & 0xFF);
351 fmtp->profile_iop = (pj_uint8_t)((tmp >> 8) & 0xFF);
352 fmtp->level = (pj_uint8_t)(tmp & 0xFF);
353
354 for (i = 0; i < PJ_ARRAY_SIZE(level_info); ++i) {
355 if (level_info[i].id == fmtp->level) {
356 li = &level_info[i];
357 break;
358 }
359 }
360 if (li == NULL)
361 return PJMEDIA_SDP_EINFMTP;
362
363 /* Init profile level spec */
364 if (fmtp->max_br == 0)
365 fmtp->max_br = li->max_br;
366 if (fmtp->max_mbps == 0)
367 fmtp->max_mbps = li->max_mbps;
368 if (fmtp->max_fs == 0)
369 fmtp->max_fs = li->max_mb;
370
371 return PJ_SUCCESS;
372 }
373
374
375 /* H264 fmtp parser */
pjmedia_vid_codec_h264_parse_fmtp(const pjmedia_codec_fmtp * fmtp,pjmedia_vid_codec_h264_fmtp * h264_fmtp)376 PJ_DEF(pj_status_t) pjmedia_vid_codec_h264_parse_fmtp(
377 const pjmedia_codec_fmtp *fmtp,
378 pjmedia_vid_codec_h264_fmtp *h264_fmtp)
379 {
380 const pj_str_t PROFILE_LEVEL_ID = {"profile-level-id", 16};
381 const pj_str_t MAX_MBPS = {"max-mbps", 8};
382 const pj_str_t MAX_FS = {"max-fs", 6};
383 const pj_str_t MAX_CPB = {"max-cpb", 7};
384 const pj_str_t MAX_DPB = {"max-dpb", 7};
385 const pj_str_t MAX_BR = {"max-br", 6};
386 const pj_str_t PACKETIZATION_MODE = {"packetization-mode", 18};
387 const pj_str_t SPROP_PARAMETER_SETS = {"sprop-parameter-sets", 20};
388 unsigned i;
389 pj_status_t status;
390
391 pj_bzero(h264_fmtp, sizeof(*h264_fmtp));
392
393 for (i=0; i<fmtp->cnt; ++i) {
394 unsigned tmp;
395 if (pj_stricmp(&fmtp->param[i].name, &PROFILE_LEVEL_ID)==0) {
396 /* Init H264 parameters based on level, if not set yet */
397 status = init_h264_profile(&fmtp->param[i].val, h264_fmtp);
398 if (status != PJ_SUCCESS)
399 return status;
400 } else if (pj_stricmp(&fmtp->param[i].name, &PACKETIZATION_MODE)==0) {
401 tmp = pj_strtoul(&fmtp->param[i].val);
402 if (tmp <= 2)
403 h264_fmtp->packetization_mode = (pj_uint8_t)tmp;
404 else
405 return PJMEDIA_SDP_EINFMTP;
406 } else if (pj_stricmp(&fmtp->param[i].name, &MAX_MBPS)==0) {
407 tmp = pj_strtoul(&fmtp->param[i].val);
408 h264_fmtp->max_mbps = PJ_MAX(tmp, h264_fmtp->max_mbps);
409 } else if (pj_stricmp(&fmtp->param[i].name, &MAX_FS)==0) {
410 tmp = pj_strtoul(&fmtp->param[i].val);
411 h264_fmtp->max_fs = PJ_MAX(tmp, h264_fmtp->max_fs);
412 } else if (pj_stricmp(&fmtp->param[i].name, &MAX_CPB)==0) {
413 tmp = pj_strtoul(&fmtp->param[i].val);
414 h264_fmtp->max_cpb = PJ_MAX(tmp, h264_fmtp->max_cpb);
415 } else if (pj_stricmp(&fmtp->param[i].name, &MAX_DPB)==0) {
416 tmp = pj_strtoul(&fmtp->param[i].val);
417 h264_fmtp->max_dpb = PJ_MAX(tmp, h264_fmtp->max_dpb);
418 } else if (pj_stricmp(&fmtp->param[i].name, &MAX_BR)==0) {
419 tmp = pj_strtoul(&fmtp->param[i].val);
420 h264_fmtp->max_br = PJ_MAX(tmp, h264_fmtp->max_br);
421 } else if (pj_stricmp(&fmtp->param[i].name, &SPROP_PARAMETER_SETS)==0)
422 {
423 pj_str_t sps_st;
424
425 sps_st = fmtp->param[i].val;
426 while (sps_st.slen) {
427 pj_str_t tmp_st;
428 int tmp_len;
429 const pj_uint8_t start_code[3] = {0, 0, 1};
430 char *p;
431 pj_uint8_t *nal;
432
433 /* Find field separator ',' */
434 tmp_st = sps_st;
435 p = pj_strchr(&sps_st, ',');
436 if (p) {
437 tmp_st.slen = p - sps_st.ptr;
438 sps_st.ptr = p+1;
439 sps_st.slen -= (tmp_st.slen+1);
440 } else {
441 sps_st.slen = 0;
442 }
443
444 /* Decode field and build NAL unit for this param */
445 nal = &h264_fmtp->sprop_param_sets[
446 h264_fmtp->sprop_param_sets_len];
447 tmp_len = PJ_ARRAY_SIZE(h264_fmtp->sprop_param_sets) -
448 (int)h264_fmtp->sprop_param_sets_len -
449 PJ_ARRAY_SIZE(start_code);
450 status = pj_base64_decode(&tmp_st,
451 nal + PJ_ARRAY_SIZE(start_code),
452 &tmp_len);
453 if (status != PJ_SUCCESS)
454 return PJMEDIA_SDP_EINFMTP;
455
456 tmp_len += PJ_ARRAY_SIZE(start_code);
457 pj_memcpy(nal, start_code, PJ_ARRAY_SIZE(start_code));
458 h264_fmtp->sprop_param_sets_len += tmp_len;
459 }
460 }
461 }
462
463 /* When profile-level-id is not specified, use default value "42000A" */
464 if (h264_fmtp->profile_idc == 0) {
465 const pj_str_t DEF_PROFILE = {"42000A", 6};
466
467 status = init_h264_profile(&DEF_PROFILE, h264_fmtp);
468 if (status != PJ_SUCCESS)
469 return status;
470 }
471
472 return PJ_SUCCESS;
473 }
474
pjmedia_vid_codec_h264_match_sdp(pj_pool_t * pool,pjmedia_sdp_media * offer,unsigned o_fmt_idx,pjmedia_sdp_media * answer,unsigned a_fmt_idx,unsigned option)475 PJ_DEF(pj_status_t) pjmedia_vid_codec_h264_match_sdp(pj_pool_t *pool,
476 pjmedia_sdp_media *offer,
477 unsigned o_fmt_idx,
478 pjmedia_sdp_media *answer,
479 unsigned a_fmt_idx,
480 unsigned option)
481 {
482 const pj_str_t PROFILE_LEVEL_ID = {"profile-level-id", 16};
483 const pj_str_t PACKETIZATION_MODE = {"packetization-mode", 18};
484 pjmedia_codec_fmtp o_fmtp_raw, a_fmtp_raw;
485 pjmedia_vid_codec_h264_fmtp o_fmtp, a_fmtp;
486 pj_status_t status;
487
488 PJ_UNUSED_ARG(pool);
489
490 /* Parse offer */
491 status = pjmedia_stream_info_parse_fmtp(
492 NULL, offer,
493 pj_strtoul(&offer->desc.fmt[o_fmt_idx]),
494 &o_fmtp_raw);
495 if (status != PJ_SUCCESS)
496 return status;
497
498 status = pjmedia_vid_codec_h264_parse_fmtp(&o_fmtp_raw, &o_fmtp);
499 if (status != PJ_SUCCESS)
500 return status;
501
502 /* Parse answer */
503 status = pjmedia_stream_info_parse_fmtp(
504 NULL, answer,
505 pj_strtoul(&answer->desc.fmt[a_fmt_idx]),
506 &a_fmtp_raw);
507 if (status != PJ_SUCCESS)
508 return status;
509
510 status = pjmedia_vid_codec_h264_parse_fmtp(&a_fmtp_raw, &a_fmtp);
511 if (status != PJ_SUCCESS)
512 return status;
513
514 if (option & PJMEDIA_SDP_NEG_FMT_MATCH_ALLOW_MODIFY_ANSWER) {
515 unsigned i;
516
517 /* Flexible negotiation, if the answer has higher capability than
518 * the offer, adjust the answer capability to be match to the offer.
519 */
520 if (a_fmtp.profile_idc >= o_fmtp.profile_idc)
521 a_fmtp.profile_idc = o_fmtp.profile_idc;
522 if (a_fmtp.profile_iop != o_fmtp.profile_iop)
523 a_fmtp.profile_iop = o_fmtp.profile_iop;
524 if (a_fmtp.level >= o_fmtp.level)
525 a_fmtp.level = o_fmtp.level;
526 if (a_fmtp.packetization_mode >= o_fmtp.packetization_mode)
527 a_fmtp.packetization_mode = o_fmtp.packetization_mode;
528
529 /* Match them now */
530 #if H264_STRICT_SDP_NEGO
531 if (a_fmtp.profile_idc != o_fmtp.profile_idc ||
532 a_fmtp.profile_iop != o_fmtp.profile_iop ||
533 a_fmtp.level != o_fmtp.level ||
534 a_fmtp.packetization_mode != o_fmtp.packetization_mode)
535 {
536 return PJMEDIA_SDP_EFORMATNOTEQUAL;
537 }
538 #else
539 if (a_fmtp.profile_idc != o_fmtp.profile_idc)
540 {
541 return PJMEDIA_SDP_EFORMATNOTEQUAL;
542 }
543 #endif
544
545 /* Update the answer */
546 for (i = 0; i < a_fmtp_raw.cnt; ++i) {
547 if (pj_stricmp(&a_fmtp_raw.param[i].name, &PROFILE_LEVEL_ID) == 0)
548 {
549 char *p = a_fmtp_raw.param[i].val.ptr;
550 pj_val_to_hex_digit(a_fmtp.profile_idc, p);
551 p += 2;
552 pj_val_to_hex_digit(a_fmtp.profile_iop, p);
553 p += 2;
554 pj_val_to_hex_digit(a_fmtp.level, p);
555 }
556 else if (pj_stricmp(&a_fmtp_raw.param[i].name, &PACKETIZATION_MODE) == 0)
557 {
558 char *p = a_fmtp_raw.param[i].val.ptr;
559 *p = '0' + a_fmtp.packetization_mode;
560 }
561 }
562 } else {
563 #if H264_STRICT_SDP_NEGO
564 /* Strict negotiation */
565 if (a_fmtp.profile_idc != o_fmtp.profile_idc ||
566 a_fmtp.profile_iop != o_fmtp.profile_iop ||
567 a_fmtp.level != o_fmtp.level ||
568 a_fmtp.packetization_mode != o_fmtp.packetization_mode)
569 {
570 return PJMEDIA_SDP_EFORMATNOTEQUAL;
571 }
572 #else
573 /* Permissive negotiation */
574 if (a_fmtp.profile_idc != o_fmtp.profile_idc)
575 {
576 return PJMEDIA_SDP_EFORMATNOTEQUAL;
577 }
578 #endif
579 }
580
581 return PJ_SUCCESS;
582 }
583
584
585 /* Find greatest common divisor (GCD) */
gcd(unsigned a,unsigned b)586 static unsigned gcd (unsigned a, unsigned b) {
587 unsigned c;
588 while (b) {
589 c = a % b;
590 a = b;
591 b = c;
592 }
593 return a;
594 }
595
596 /* Find highest resolution possible for the specified H264 fmtp and
597 * aspect ratio.
598 */
find_highest_res(pjmedia_vid_codec_h264_fmtp * fmtp,const pjmedia_ratio * fps,const pjmedia_ratio * ratio,pjmedia_rect_size * size,pj_bool_t is_decoding)599 static pj_status_t find_highest_res(pjmedia_vid_codec_h264_fmtp *fmtp,
600 const pjmedia_ratio *fps,
601 const pjmedia_ratio *ratio,
602 pjmedia_rect_size *size,
603 pj_bool_t is_decoding)
604 {
605 pjmedia_ratio def_ratio = { DEFAULT_H264_RATIO_NUM,
606 DEFAULT_H264_RATIO_DENUM };
607 pjmedia_ratio def_fps = { DEFAULT_H264_FPS_NUM,
608 DEFAULT_H264_FPS_DENUM };
609 pjmedia_ratio asp_ratio, the_fps;
610 unsigned max_fs, g, scale;
611
612 pj_assert(size);
613
614 /* Get the ratio, or just use default if not provided. */
615 if (ratio && ratio->num && ratio->denum) {
616 asp_ratio = *ratio;
617 } else {
618 asp_ratio = def_ratio;
619 }
620
621 /* Normalize the aspect ratio */
622 g = gcd(asp_ratio.num, asp_ratio.denum);
623 asp_ratio.num /= g;
624 asp_ratio.denum /= g;
625
626 /* Get the frame rate, or just use default if not provided. */
627 if (fps && fps->num && fps->denum) {
628 the_fps = *fps;
629 } else {
630 the_fps = def_fps;
631 }
632
633 /* Calculate maximum size (in macroblocks) */
634 max_fs = fmtp->max_mbps * the_fps.denum / the_fps.num;
635 max_fs = PJ_MIN(max_fs, fmtp->max_fs);
636
637 /* Check if the specified ratio is using big numbers
638 * (not normalizable), override it!
639 */
640 if ((int)max_fs < asp_ratio.num * asp_ratio.denum) {
641 if ((int)max_fs >= def_ratio.num * def_ratio.denum)
642 asp_ratio = def_ratio;
643 else
644 asp_ratio.num = asp_ratio.denum = 1;
645 }
646
647 /* Calculate the scale factor for size */
648 scale = pj_isqrt(max_fs / asp_ratio.denum / asp_ratio.num);
649
650 /* Calculate the size, note that the frame size is in macroblock units */
651 size->w = asp_ratio.num * scale * 16;
652 size->h = asp_ratio.denum * scale * 16;
653
654 /* #1769: for decoding, size is usually used for allocating buffer,
655 * so we need to make sure that frame size is not less than max_fs.
656 */
657 if (is_decoding && ((size->w * size->h) >> 8) < max_fs) {
658 /* Size is less than max_fs, recalculate using ratio 1:1 and
659 * round up the scale.
660 */
661 scale = pj_isqrt(max_fs) + 1;
662 size->w = size->h = scale * 16;
663 }
664
665 return PJ_SUCCESS;
666 }
667
668
pjmedia_vid_codec_h264_apply_fmtp(pjmedia_vid_codec_param * param)669 PJ_DEF(pj_status_t) pjmedia_vid_codec_h264_apply_fmtp(
670 pjmedia_vid_codec_param *param)
671 {
672 if (param->dir & PJMEDIA_DIR_ENCODING) {
673 pjmedia_vid_codec_h264_fmtp fmtp;
674 pjmedia_video_format_detail *vfd;
675 pj_status_t status;
676
677 /* Get remote param */
678 status = pjmedia_vid_codec_h264_parse_fmtp(¶m->enc_fmtp,
679 &fmtp);
680 if (status != PJ_SUCCESS)
681 return status;
682
683 /* Adjust fps, size, and bitrate to conform to H.264 level
684 * specified by remote SDP fmtp.
685 */
686 vfd = pjmedia_format_get_video_format_detail(¶m->enc_fmt,
687 PJ_TRUE);
688
689 if (vfd->fps.num == 0 || vfd->fps.denum == 0) {
690 vfd->fps.num = DEFAULT_H264_FPS_NUM;
691 vfd->fps.denum = DEFAULT_H264_FPS_DENUM;
692 }
693
694 if (vfd->size.w && vfd->size.h) {
695 unsigned mb, mbps;
696
697 /* Scale down the resolution if it exceeds profile spec */
698 mb = CALC_H264_MB_NUM(vfd->size);
699 mbps = CALC_H264_MBPS(vfd->size, vfd->fps);
700 if (mb > fmtp.max_fs || mbps > fmtp.max_mbps) {
701 pjmedia_ratio r;
702 r.num = vfd->size.w;
703 r.denum = vfd->size.h;
704 find_highest_res(&fmtp, &vfd->fps, &r, &vfd->size, PJ_FALSE);
705 }
706 } else {
707 /* When not specified, just use the highest res possible*/
708 pjmedia_ratio r;
709 r.num = vfd->size.w;
710 r.denum = vfd->size.h;
711 find_highest_res(&fmtp, &vfd->fps, &r, &vfd->size, PJ_FALSE);
712 }
713
714 /* Encoding bitrate must not be higher than H264 level spec */
715 if (vfd->avg_bps > fmtp.max_br * 1000)
716 vfd->avg_bps = fmtp.max_br * 1000;
717 if (vfd->max_bps > fmtp.max_br * 1000)
718 vfd->max_bps = fmtp.max_br * 1000;
719 }
720
721 if (param->dir & PJMEDIA_DIR_DECODING) {
722 /* Here we just want to find the highest resolution possible from the
723 * fmtp and set it as the decoder param.
724 */
725 pjmedia_vid_codec_h264_fmtp fmtp;
726 pjmedia_video_format_detail *vfd;
727 pjmedia_ratio r;
728 pjmedia_rect_size highest_size;
729 pj_status_t status;
730
731 status = pjmedia_vid_codec_h264_parse_fmtp(¶m->dec_fmtp,
732 &fmtp);
733 if (status != PJ_SUCCESS)
734 return status;
735
736 vfd = pjmedia_format_get_video_format_detail(¶m->dec_fmt,
737 PJ_TRUE);
738
739 if (vfd->fps.num == 0 || vfd->fps.denum == 0) {
740 vfd->fps.num = DEFAULT_H264_FPS_NUM;
741 vfd->fps.denum = DEFAULT_H264_FPS_DENUM;
742 }
743
744 /* Normalize decoding resolution, i.e: it must not be lower than
745 * the H264 profile level setting used, as this may be used by
746 * app to allocate buffer.
747 */
748 r.num = vfd->size.w;
749 r.denum = vfd->size.h;
750 find_highest_res(&fmtp, &vfd->fps, &r, &highest_size, PJ_TRUE);
751 if (vfd->size.w * vfd->size.h < highest_size.w * highest_size.h)
752 vfd->size = highest_size;
753
754 /* Normalize decoding bitrate based on H264 level spec */
755 if (vfd->avg_bps < fmtp.max_br * 1000)
756 vfd->avg_bps = fmtp.max_br * 1000;
757 if (vfd->max_bps < fmtp.max_br * 1000)
758 vfd->max_bps = fmtp.max_br * 1000;
759 }
760
761 return PJ_SUCCESS;
762 }
763
764
765 /* VPX fmtp parser */
pjmedia_vid_codec_vpx_parse_fmtp(const pjmedia_codec_fmtp * fmtp,pjmedia_vid_codec_vpx_fmtp * vpx_fmtp)766 PJ_DEF(pj_status_t) pjmedia_vid_codec_vpx_parse_fmtp(
767 const pjmedia_codec_fmtp *fmtp,
768 pjmedia_vid_codec_vpx_fmtp *vpx_fmtp)
769 {
770 const pj_str_t PROFILE_ID = {"profile-id", 10};
771 const pj_str_t MAX_FR = {"max-fr", 6};
772 const pj_str_t MAX_FS = {"max-fs", 6};
773
774 unsigned i;
775
776 pj_bzero(vpx_fmtp, sizeof(*vpx_fmtp));
777
778 for (i = 0; i < fmtp->cnt; ++i) {
779 unsigned tmp;
780
781 if (pj_stricmp(&fmtp->param[i].name, &MAX_FS) == 0) {
782 tmp = pj_strtoul(&fmtp->param[i].val);
783 vpx_fmtp->max_fs = PJ_MAX(tmp, vpx_fmtp->max_fs);
784 } else if (pj_stricmp(&fmtp->param[i].name, &MAX_FR) == 0) {
785 tmp = pj_strtoul(&fmtp->param[i].val);
786 vpx_fmtp->max_fr = PJ_MAX(tmp, vpx_fmtp->max_fr);
787 } else if (pj_stricmp(&fmtp->param[i].name, &PROFILE_ID) == 0) {
788 tmp = pj_strtoul(&fmtp->param[i].val);
789 vpx_fmtp->profile_id = (pj_uint8_t)
790 PJ_MAX(tmp, vpx_fmtp->profile_id);
791 }
792 }
793
794 return PJ_SUCCESS;
795 }
796
797
pjmedia_vid_codec_vpx_apply_fmtp(pjmedia_vid_codec_param * param)798 PJ_DEF(pj_status_t) pjmedia_vid_codec_vpx_apply_fmtp(
799 pjmedia_vid_codec_param *param)
800 {
801 if (param->dir & PJMEDIA_DIR_ENCODING) {
802 pjmedia_vid_codec_vpx_fmtp fmtp;
803 pjmedia_video_format_detail *vfd;
804 pj_status_t status;
805
806 /* Get remote param */
807 status = pjmedia_vid_codec_vpx_parse_fmtp(¶m->enc_fmtp,
808 &fmtp);
809 if (status != PJ_SUCCESS)
810 return status;
811
812 /* Adjust fps and size to conform to the parameter
813 * specified by remote SDP fmtp.
814 */
815 vfd = pjmedia_format_get_video_format_detail(¶m->enc_fmt,
816 PJ_TRUE);
817
818 if (fmtp.max_fr > 0) {
819 if ((float)vfd->fps.num/vfd->fps.denum > (float)fmtp.max_fr) {
820 vfd->fps.num = fmtp.max_fr;
821 vfd->fps.denum = 1;
822 }
823 }
824
825 if (fmtp.max_fs > 0) {
826 unsigned max_res = ((int)pj_isqrt(fmtp.max_fs * 8)) * 16;
827
828 if (vfd->size.w > max_res || vfd->size.h > max_res) {
829 /* Here we maintain the aspect ratio. Or should we scale down
830 * to some predetermined resolution instead (for example,
831 * if the requested resolution is 640x480 and max_res is
832 * 600, should we scale down to 480x360)?
833 */
834 unsigned larger = (vfd->size.w > vfd->size.h)?
835 vfd->size.w: vfd->size.h;
836 float scale = (float)max_res/larger;
837
838 vfd->size.w = (int)(scale * vfd->size.w);
839 vfd->size.h = (int)(scale * vfd->size.h);
840 }
841 }
842 }
843
844 if (param->dir & PJMEDIA_DIR_DECODING) {
845 /* Here we just want to find the highest fps and resolution possible
846 * from the fmtp and set it as the decoder param.
847 */
848 pjmedia_vid_codec_vpx_fmtp fmtp;
849 pjmedia_video_format_detail *vfd;
850 pj_status_t status;
851
852 /* Get remote param */
853 status = pjmedia_vid_codec_vpx_parse_fmtp(¶m->dec_fmtp,
854 &fmtp);
855 if (status != PJ_SUCCESS)
856 return status;
857
858 vfd = pjmedia_format_get_video_format_detail(¶m->dec_fmt,
859 PJ_TRUE);
860
861 if (fmtp.max_fr > 0) {
862 vfd->fps.num = fmtp.max_fr;
863 vfd->fps.denum = 1;
864 }
865
866 if (fmtp.max_fs > 0) {
867 unsigned max_res = ((int)pj_isqrt(fmtp.max_fs * 8)) * 16;
868
869 vfd->size.w = max_res;
870 vfd->size.h = max_res;
871 }
872 }
873
874 return PJ_SUCCESS;
875 }
876
877
878 #endif /* PJMEDIA_HAS_VIDEO */
879