~ubuntu-branches/ubuntu/wily/sflphone/wily

« back to all changes in this revision

Viewing changes to daemon/libs/pjproject-2.1.0/pjmedia/src/pjmedia/vid_codec_util.c

  • Committer: Package Import Robot
  • Author(s): Mark Purcell
  • Date: 2014-01-28 18:23:36 UTC
  • mfrom: (1.1.11)
  • mto: This revision was merged to the branch mainline in revision 24.
  • Revision ID: package-import@ubuntu.com-20140128182336-3xenud1kbnwmf3mz
* New upstream release 
  - Fixes "New Upstream Release" (Closes: #735846)
  - Fixes "Ringtone does not stop" (Closes: #727164)
  - Fixes "[sflphone-kde] crash on startup" (Closes: #718178)
  - Fixes "sflphone GUI crashes when call is hung up" (Closes: #736583)
* Build-Depends: ensure GnuTLS 2.6
  - libucommon-dev (>= 6.0.7-1.1), libccrtp-dev (>= 2.0.6-3)
  - Fixes "FTBFS Build-Depends libgnutls{26,28}-dev" (Closes: #722040)
* Fix "boost 1.49 is going away" unversioned Build-Depends: (Closes: #736746)
* Add Build-Depends: libsndfile-dev, nepomuk-core-dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Id: vid_codec_util.c 4362 2013-02-21 14:51:56Z nanang $ */
 
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        15
 
43
#define DEFAULT_H264_FPS_DENUM      1
 
44
 
 
45
/* Default aspect ratio, if not specified */
 
46
#define DEFAULT_H264_RATIO_NUM      16
 
47
#define DEFAULT_H264_RATIO_DENUM    9
 
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" */
 
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 */
 
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
 
 
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
 
 
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 */
 
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 */
 
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 >= 0 && 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
                pj_status_t status;
 
433
 
 
434
                /* Find field separator ',' */
 
435
                tmp_st = sps_st;
 
436
                p = pj_strchr(&sps_st, ',');
 
437
                if (p) {
 
438
                    tmp_st.slen = p - sps_st.ptr;
 
439
                    sps_st.ptr  = p+1;
 
440
                    sps_st.slen -= (tmp_st.slen+1);
 
441
                } else {
 
442
                    sps_st.slen = 0;
 
443
                }
 
444
 
 
445
                /* Decode field and build NAL unit for this param */
 
446
                nal = &h264_fmtp->sprop_param_sets[
 
447
                                          h264_fmtp->sprop_param_sets_len];
 
448
                tmp_len = PJ_ARRAY_SIZE(h264_fmtp->sprop_param_sets) -
 
449
                          h264_fmtp->sprop_param_sets_len -
 
450
                          PJ_ARRAY_SIZE(start_code);
 
451
                status = pj_base64_decode(&tmp_st,
 
452
                                          nal + PJ_ARRAY_SIZE(start_code),
 
453
                                          &tmp_len);
 
454
                if (status != PJ_SUCCESS)
 
455
                    return PJMEDIA_SDP_EINFMTP;
 
456
 
 
457
                tmp_len += PJ_ARRAY_SIZE(start_code);
 
458
                pj_memcpy(nal, start_code, PJ_ARRAY_SIZE(start_code));
 
459
                h264_fmtp->sprop_param_sets_len += tmp_len;
 
460
            }
 
461
        }
 
462
    }
 
463
 
 
464
    /* When profile-level-id is not specified, use default value "42000A" */
 
465
    if (h264_fmtp->profile_idc == 0) {
 
466
        h264_fmtp->profile_idc = 0x42;
 
467
        h264_fmtp->profile_iop = 0x00;
 
468
        h264_fmtp->level = 0x0A;
 
469
    }
 
470
 
 
471
    return PJ_SUCCESS;
 
472
}
 
473
 
 
474
PJ_DEF(pj_status_t) pjmedia_vid_codec_h264_match_sdp(pj_pool_t *pool,
 
475
                                                     pjmedia_sdp_media *offer,
 
476
                                                     unsigned o_fmt_idx,
 
477
                                                     pjmedia_sdp_media *answer,
 
478
                                                     unsigned a_fmt_idx,
 
479
                                                     unsigned option)
 
480
{
 
481
    const pj_str_t PROFILE_LEVEL_ID     = {"profile-level-id", 16};
 
482
    const pj_str_t PACKETIZATION_MODE   = {"packetization-mode", 18};
 
483
    pjmedia_codec_fmtp o_fmtp_raw, a_fmtp_raw;
 
484
    pjmedia_vid_codec_h264_fmtp o_fmtp, a_fmtp;
 
485
    pj_status_t status;
 
486
 
 
487
    PJ_UNUSED_ARG(pool);
 
488
 
 
489
    /* Parse offer */
 
490
    status = pjmedia_stream_info_parse_fmtp(
 
491
                                    NULL, offer, 
 
492
                                    pj_strtoul(&offer->desc.fmt[o_fmt_idx]),
 
493
                                    &o_fmtp_raw);
 
494
    if (status != PJ_SUCCESS)
 
495
        return status;
 
496
 
 
497
    status = pjmedia_vid_codec_h264_parse_fmtp(&o_fmtp_raw, &o_fmtp);
 
498
    if (status != PJ_SUCCESS)
 
499
        return status;
 
500
 
 
501
    /* Parse answer */
 
502
    status = pjmedia_stream_info_parse_fmtp(
 
503
                                    NULL, answer, 
 
504
                                    pj_strtoul(&answer->desc.fmt[a_fmt_idx]),
 
505
                                    &a_fmtp_raw);
 
506
    if (status != PJ_SUCCESS)
 
507
        return status;
 
508
 
 
509
    status = pjmedia_vid_codec_h264_parse_fmtp(&a_fmtp_raw, &a_fmtp);
 
510
    if (status != PJ_SUCCESS)
 
511
        return status;
 
512
 
 
513
    if (option & PJMEDIA_SDP_NEG_FMT_MATCH_ALLOW_MODIFY_ANSWER) {
 
514
        unsigned i;
 
515
 
 
516
        /* Flexible negotiation, if the answer has higher capability than
 
517
         * the offer, adjust the answer capability to be match to the offer.
 
518
         */
 
519
        if (a_fmtp.profile_idc >= o_fmtp.profile_idc)
 
520
            a_fmtp.profile_idc = o_fmtp.profile_idc;
 
521
        if (a_fmtp.profile_iop != o_fmtp.profile_iop)
 
522
            a_fmtp.profile_iop = o_fmtp.profile_iop;
 
523
        if (a_fmtp.level >= o_fmtp.level)
 
524
            a_fmtp.level = o_fmtp.level;
 
525
        if (a_fmtp.packetization_mode >= o_fmtp.packetization_mode)
 
526
            a_fmtp.packetization_mode = o_fmtp.packetization_mode;
 
527
 
 
528
        /* Match them now */
 
529
#if H264_STRICT_SDP_NEGO
 
530
        if (a_fmtp.profile_idc != o_fmtp.profile_idc ||
 
531
            a_fmtp.profile_iop != o_fmtp.profile_iop ||
 
532
            a_fmtp.level != o_fmtp.level ||
 
533
            a_fmtp.packetization_mode != o_fmtp.packetization_mode)
 
534
        {
 
535
            return PJMEDIA_SDP_EFORMATNOTEQUAL;
 
536
        }
 
537
#else
 
538
        if (a_fmtp.profile_idc != o_fmtp.profile_idc)
 
539
        {
 
540
            return PJMEDIA_SDP_EFORMATNOTEQUAL;
 
541
        }
 
542
#endif
 
543
 
 
544
        /* Update the answer */
 
545
        for (i = 0; i < a_fmtp_raw.cnt; ++i) {
 
546
            if (pj_stricmp(&a_fmtp_raw.param[i].name, &PROFILE_LEVEL_ID) == 0)
 
547
            {
 
548
                char *p = a_fmtp_raw.param[i].val.ptr;
 
549
                pj_val_to_hex_digit(a_fmtp.profile_idc, p);
 
550
                p += 2;
 
551
                pj_val_to_hex_digit(a_fmtp.profile_iop, p);
 
552
                p += 2;
 
553
                pj_val_to_hex_digit(a_fmtp.level, p);
 
554
            }
 
555
            else if (pj_stricmp(&a_fmtp_raw.param[i].name, &PACKETIZATION_MODE) == 0)
 
556
            {
 
557
                char *p = a_fmtp_raw.param[i].val.ptr;
 
558
                *p = '0' + a_fmtp.packetization_mode;
 
559
            }
 
560
        }
 
561
    } else {
 
562
#if H264_STRICT_SDP_NEGO
 
563
        /* Strict negotiation */
 
564
        if (a_fmtp.profile_idc != o_fmtp.profile_idc ||
 
565
            a_fmtp.profile_iop != o_fmtp.profile_iop ||
 
566
            a_fmtp.level != o_fmtp.level ||
 
567
            a_fmtp.packetization_mode != o_fmtp.packetization_mode)
 
568
        {
 
569
            return PJMEDIA_SDP_EFORMATNOTEQUAL;
 
570
        }
 
571
#else
 
572
        /* Permissive negotiation */
 
573
        if (a_fmtp.profile_idc != o_fmtp.profile_idc)
 
574
        {
 
575
            return PJMEDIA_SDP_EFORMATNOTEQUAL;
 
576
        }
 
577
#endif
 
578
    }
 
579
 
 
580
    return PJ_SUCCESS;
 
581
}
 
582
 
 
583
 
 
584
/* Find greatest common divisor (GCD) */
 
585
static unsigned gcd (unsigned a, unsigned b) {
 
586
    unsigned c;
 
587
    while (b) {
 
588
        c = a % b;
 
589
        a = b;
 
590
        b = c;
 
591
    }
 
592
    return a;
 
593
}
 
594
 
 
595
/* Find highest resolution possible for the specified H264 fmtp and
 
596
 * aspect ratio.
 
597
 */
 
598
static pj_status_t find_highest_res(pjmedia_vid_codec_h264_fmtp *fmtp,
 
599
                                    const pjmedia_ratio *fps,
 
600
                                    const pjmedia_ratio *ratio,
 
601
                                    pjmedia_rect_size *size)
 
602
{
 
603
    pjmedia_ratio def_ratio = { DEFAULT_H264_RATIO_NUM,
 
604
                                DEFAULT_H264_RATIO_DENUM };
 
605
    pjmedia_ratio def_fps   = { DEFAULT_H264_FPS_NUM,
 
606
                                DEFAULT_H264_FPS_DENUM };
 
607
    pjmedia_ratio asp_ratio, the_fps;
 
608
    unsigned max_fs, g, scale;
 
609
 
 
610
    pj_assert(size);
 
611
 
 
612
    /* Get the ratio, or just use default if not provided. */
 
613
    if (ratio && ratio->num && ratio->denum) {
 
614
        asp_ratio = *ratio;
 
615
    } else {
 
616
        asp_ratio = def_ratio;
 
617
    }
 
618
 
 
619
    /* Normalize the aspect ratio */
 
620
    g = gcd(asp_ratio.num, asp_ratio.denum);
 
621
    asp_ratio.num /= g;
 
622
    asp_ratio.denum /= g;
 
623
 
 
624
    /* Get the frame rate, or just use default if not provided. */
 
625
    if (fps && fps->num && fps->denum) {
 
626
        the_fps = *fps;
 
627
    } else {
 
628
        the_fps = def_fps;
 
629
    }
 
630
 
 
631
    /* Calculate maximum size (in macroblocks) */
 
632
    max_fs = fmtp->max_mbps * fps->denum / fps->num;
 
633
    max_fs = PJ_MIN(max_fs, fmtp->max_fs);
 
634
 
 
635
    /* Check if the specified ratio is using big numbers
 
636
     * (not normalizable), override it with default ratio!
 
637
     */
 
638
    if ((int)max_fs < asp_ratio.num * asp_ratio.denum)
 
639
        asp_ratio = def_ratio;
 
640
 
 
641
    /* Calculate the scale factor for size */
 
642
    scale = pj_isqrt(max_fs / asp_ratio.denum / asp_ratio.num);
 
643
 
 
644
    /* Calculate the size, note that the frame size is in macroblock units */
 
645
    size->w = asp_ratio.num   * scale * 16;
 
646
    size->h = asp_ratio.denum * scale * 16;
 
647
 
 
648
    return PJ_SUCCESS;
 
649
}
 
650
 
 
651
 
 
652
PJ_DEF(pj_status_t) pjmedia_vid_codec_h264_apply_fmtp(
 
653
                                pjmedia_vid_codec_param *param)
 
654
{
 
655
    if (param->dir & PJMEDIA_DIR_ENCODING) {
 
656
        pjmedia_vid_codec_h264_fmtp fmtp;
 
657
        pjmedia_video_format_detail *vfd;
 
658
        pj_status_t status;
 
659
 
 
660
        /* Get remote param */
 
661
        status = pjmedia_vid_codec_h264_parse_fmtp(&param->enc_fmtp,
 
662
                                                   &fmtp);
 
663
        if (status != PJ_SUCCESS)
 
664
            return status;
 
665
 
 
666
        /* Adjust fps, size, and bitrate to conform to H.264 level
 
667
         * specified by remote SDP fmtp.
 
668
         */
 
669
        vfd = pjmedia_format_get_video_format_detail(&param->enc_fmt,
 
670
                                                     PJ_TRUE);
 
671
 
 
672
        if (vfd->fps.num == 0 || vfd->fps.denum == 0) {
 
673
            vfd->fps.num   = DEFAULT_H264_FPS_NUM;
 
674
            vfd->fps.denum = DEFAULT_H264_FPS_DENUM;
 
675
        }
 
676
 
 
677
        if (vfd->size.w && vfd->size.h) {
 
678
            unsigned mb, mbps;
 
679
            
 
680
            /* Scale down the resolution if it exceeds profile spec */
 
681
            mb = CALC_H264_MB_NUM(vfd->size);
 
682
            mbps = CALC_H264_MBPS(vfd->size, vfd->fps);
 
683
            if (mb > fmtp.max_fs || mbps > fmtp.max_mbps) {
 
684
                pjmedia_ratio r;
 
685
                r.num = vfd->size.w;
 
686
                r.denum = vfd->size.h;
 
687
                find_highest_res(&fmtp, &vfd->fps, &r, &vfd->size);
 
688
            }
 
689
        } else {
 
690
            /* When not specified, just use the highest res possible*/
 
691
            pjmedia_ratio r;
 
692
            r.num = vfd->size.w;
 
693
            r.denum = vfd->size.h;
 
694
            find_highest_res(&fmtp, &vfd->fps, &r, &vfd->size);
 
695
        }
 
696
 
 
697
        /* Encoding bitrate must not be higher than H264 level spec */
 
698
        if (vfd->avg_bps > fmtp.max_br * 1000)
 
699
            vfd->avg_bps = fmtp.max_br * 1000;
 
700
        if (vfd->max_bps > fmtp.max_br * 1000)
 
701
            vfd->max_bps = fmtp.max_br * 1000;
 
702
    }
 
703
 
 
704
    if (param->dir & PJMEDIA_DIR_DECODING) {
 
705
        /* Here we just want to find the highest resolution possible from the
 
706
         * fmtp and set it as the decoder param.
 
707
         */
 
708
        pjmedia_vid_codec_h264_fmtp fmtp;
 
709
        pjmedia_video_format_detail *vfd;
 
710
        pjmedia_ratio r;
 
711
        pjmedia_rect_size highest_size;
 
712
        pj_status_t status;
 
713
        
 
714
        status = pjmedia_vid_codec_h264_parse_fmtp(&param->dec_fmtp,
 
715
                                                   &fmtp);
 
716
        if (status != PJ_SUCCESS)
 
717
            return status;
 
718
 
 
719
        vfd = pjmedia_format_get_video_format_detail(&param->dec_fmt,
 
720
                                                     PJ_TRUE);
 
721
 
 
722
        if (vfd->fps.num == 0 || vfd->fps.denum == 0) {
 
723
            vfd->fps.num   = DEFAULT_H264_FPS_NUM;
 
724
            vfd->fps.denum = DEFAULT_H264_FPS_DENUM;
 
725
        }
 
726
 
 
727
        /* Normalize decoding resolution, i.e: it must not be lower than
 
728
         * the H264 profile level setting used, as this may be used by
 
729
         * app to allocate buffer.
 
730
         */
 
731
        r.num = vfd->size.w;
 
732
        r.denum = vfd->size.h;
 
733
        find_highest_res(&fmtp, &vfd->fps, &r, &highest_size);
 
734
        if (vfd->size.w * vfd->size.h < highest_size.w * highest_size.h)
 
735
            vfd->size = highest_size;
 
736
 
 
737
        /* Normalize decoding bitrate based on H264 level spec */
 
738
        if (vfd->avg_bps < fmtp.max_br * 1000)
 
739
            vfd->avg_bps = fmtp.max_br * 1000;
 
740
        if (vfd->max_bps < fmtp.max_br * 1000)
 
741
            vfd->max_bps = fmtp.max_br * 1000;
 
742
    }
 
743
 
 
744
    return PJ_SUCCESS;
 
745
}
 
746
 
 
747
 
 
748
#endif /* PJMEDIA_HAS_VIDEO */