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(&param->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(&param->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(&param->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(&param->dec_fmtp,
270 						   &fmtp);
271 	if (status != PJ_SUCCESS)
272 	    return status;
273 
274 	vfd = pjmedia_format_get_video_format_detail(&param->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(&param->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(&param->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(&param->dec_fmtp,
732 						   &fmtp);
733 	if (status != PJ_SUCCESS)
734 	    return status;
735 
736 	vfd = pjmedia_format_get_video_format_detail(&param->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(&param->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(&param->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(&param->dec_fmtp,
854 						  &fmtp);
855 	if (status != PJ_SUCCESS)
856 	    return status;
857 
858 	vfd = pjmedia_format_get_video_format_detail(&param->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