blob: e4562c7adeb913980690331eccf0387e22bffab2 [file] [log] [blame]
Benny Prijonoc45d9512010-12-10 11:04:30 +00001/* $Id$ */
2/*
3 * Copyright (C) 2010 Teluu Inc. (http://www.teluu.com)
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19#include <pjmedia-codec/ffmpeg_codecs.h>
20#include <pjmedia-codec/h263_packetizer.h>
21#include <pjmedia/errno.h>
22#include <pj/assert.h>
23#include <pj/list.h>
24#include <pj/log.h>
25#include <pj/math.h>
26#include <pj/pool.h>
27#include <pj/string.h>
28#include <pj/os.h>
29
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +000030
Benny Prijonoc45d9512010-12-10 11:04:30 +000031/*
32 * Only build this file if PJMEDIA_HAS_FFMPEG_CODEC != 0
33 */
34#if defined(PJMEDIA_HAS_FFMPEG_CODEC) && PJMEDIA_HAS_FFMPEG_CODEC != 0
35
36#define THIS_FILE "ffmpeg_codecs.c"
37
38#include "../pjmedia/ffmpeg_util.h"
39#include <libavcodec/avcodec.h>
40#include <libavformat/avformat.h>
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +000041#include <libswscale/swscale.h>
Benny Prijonoc45d9512010-12-10 11:04:30 +000042
43
44#define PJMEDIA_FORMAT_FFMPEG_UNKNOWN PJMEDIA_FORMAT_PACK('f','f','0','0');
45
46
47/* Prototypes for FFMPEG codecs factory */
48static pj_status_t ffmpeg_test_alloc( pjmedia_vid_codec_factory *factory,
49 const pjmedia_vid_codec_info *id );
50static pj_status_t ffmpeg_default_attr( pjmedia_vid_codec_factory *factory,
51 const pjmedia_vid_codec_info *info,
52 pjmedia_vid_codec_param *attr );
53static pj_status_t ffmpeg_enum_codecs( pjmedia_vid_codec_factory *factory,
54 unsigned *count,
55 pjmedia_vid_codec_info codecs[]);
56static pj_status_t ffmpeg_alloc_codec( pjmedia_vid_codec_factory *factory,
57 const pjmedia_vid_codec_info *info,
58 pjmedia_vid_codec **p_codec);
59static pj_status_t ffmpeg_dealloc_codec( pjmedia_vid_codec_factory *factory,
60 pjmedia_vid_codec *codec );
61
62/* Prototypes for FFMPEG codecs implementation. */
63static pj_status_t ffmpeg_codec_init( pjmedia_vid_codec *codec,
64 pj_pool_t *pool );
65static pj_status_t ffmpeg_codec_open( pjmedia_vid_codec *codec,
66 pjmedia_vid_codec_param *attr );
67static pj_status_t ffmpeg_codec_close( pjmedia_vid_codec *codec );
68static pj_status_t ffmpeg_codec_modify(pjmedia_vid_codec *codec,
69 const pjmedia_vid_codec_param *attr );
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +000070static pj_status_t ffmpeg_codec_get_param(pjmedia_vid_codec *codec,
71 pjmedia_vid_codec_param *param);
Benny Prijonoc45d9512010-12-10 11:04:30 +000072static pj_status_t ffmpeg_packetize ( pjmedia_vid_codec *codec,
73 pj_uint8_t *buf,
74 pj_size_t buf_len,
75 unsigned *pos,
76 const pj_uint8_t **payload,
77 pj_size_t *payload_len);
78static pj_status_t ffmpeg_unpacketize(pjmedia_vid_codec *codec,
79 const pj_uint8_t *payload,
80 pj_size_t payload_len,
81 pj_uint8_t *buf,
82 pj_size_t *buf_len);
83static pj_status_t ffmpeg_codec_encode( pjmedia_vid_codec *codec,
84 const pjmedia_frame *input,
85 unsigned output_buf_len,
86 pjmedia_frame *output);
87static pj_status_t ffmpeg_codec_decode( pjmedia_vid_codec *codec,
88 const pjmedia_frame *input,
89 unsigned output_buf_len,
90 pjmedia_frame *output);
91static pj_status_t ffmpeg_codec_recover( pjmedia_vid_codec *codec,
92 unsigned output_buf_len,
93 pjmedia_frame *output);
94
95/* Definition for FFMPEG codecs operations. */
96static pjmedia_vid_codec_op ffmpeg_op =
97{
98 &ffmpeg_codec_init,
99 &ffmpeg_codec_open,
100 &ffmpeg_codec_close,
101 &ffmpeg_codec_modify,
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000102 &ffmpeg_codec_get_param,
Benny Prijonoc45d9512010-12-10 11:04:30 +0000103 &ffmpeg_packetize,
104 &ffmpeg_unpacketize,
105 &ffmpeg_codec_encode,
106 &ffmpeg_codec_decode,
107 NULL //&ffmpeg_codec_recover
108};
109
110/* Definition for FFMPEG codecs factory operations. */
111static pjmedia_vid_codec_factory_op ffmpeg_factory_op =
112{
113 &ffmpeg_test_alloc,
114 &ffmpeg_default_attr,
115 &ffmpeg_enum_codecs,
116 &ffmpeg_alloc_codec,
117 &ffmpeg_dealloc_codec
118};
119
120
Benny Prijonoc45d9512010-12-10 11:04:30 +0000121/* FFMPEG codecs factory */
122static struct ffmpeg_factory {
123 pjmedia_vid_codec_factory base;
124 pjmedia_vid_codec_mgr *mgr;
125 pj_pool_factory *pf;
126 pj_pool_t *pool;
127 pj_mutex_t *mutex;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000128} ffmpeg_factory;
129
130
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000131typedef struct ffmpeg_codec_desc ffmpeg_codec_desc;
132
133/* ITU resolution ID */
134typedef enum itu_res_id {
135 ITU_RES_SQCIF,
136 ITU_RES_QCIF,
137 ITU_RES_CIF,
138 ITU_RES_4CIF,
139 ITU_RES_16CIF,
140 ITU_RES_CUSTOM,
141} itu_res_id;
142
143/* ITU resolution definition */
144struct itu_res {
145 itu_res_id id;
146 pj_str_t name;
147 pjmedia_rect_size size;
148} itu_res_def [] =
149{
150 {ITU_RES_16CIF, {"16CIF",5}, {1408,1142}},
151 {ITU_RES_4CIF, {"4CIF",4}, {704,576}},
152 {ITU_RES_CIF, {"CIF",3}, {352,288}},
153 {ITU_RES_QCIF, {"QCIF",4}, {176,144}},
154 {ITU_RES_SQCIF, {"SQCIF",5}, {88,72}},
155 {ITU_RES_CUSTOM, {"CUSTOM",6}, {0,0}},
156};
157
Benny Prijonoc45d9512010-12-10 11:04:30 +0000158/* FFMPEG codecs private data. */
159typedef struct ffmpeg_private {
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000160 const ffmpeg_codec_desc *desc;
161 pjmedia_vid_codec_param param; /**< Codec param */
162 pj_pool_t *pool; /**< Pool for each instance */
163 pj_timestamp last_tx; /**< Timestamp of last
164 transmit */
165
166 /* Format info and apply format param */
167 const pjmedia_video_format_info *enc_vfi;
168 pjmedia_video_apply_fmt_param enc_vafp;
169 const pjmedia_video_format_info *dec_vfi;
170 pjmedia_video_apply_fmt_param dec_vafp;
171
172 /* The ffmpeg codec states. */
173 AVCodec *enc;
174 AVCodec *dec;
175 AVCodecContext *enc_ctx;
176 AVCodecContext *dec_ctx;
177
178 /* The ffmpeg decoder cannot set the output format, so format conversion
179 * may be needed for post-decoding.
180 */
181 enum PixelFormat expected_dec_fmt;
182 /**< expected output format of
183 ffmpeg decoder */
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000184} ffmpeg_private;
185
186
187typedef pj_status_t (*func_packetize) (pj_uint8_t *buf,
188 pj_size_t buf_len,
189 unsigned *pos,
190 int max_payload_len,
191 const pj_uint8_t **payload,
192 pj_size_t *payload_len);
193
194typedef pj_status_t (*func_unpacketize) (const pj_uint8_t *payload,
195 pj_size_t payload_len,
196 pj_uint8_t *bits,
197 pj_size_t *bits_len);
198
199typedef pj_status_t (*func_parse_fmtp) (ffmpeg_private *ff);
200
201/* FFMPEG codec info */
202struct ffmpeg_codec_desc {
203 /* Predefined info */
204 pjmedia_vid_codec_info info;
Nanang Izzuddin235e1b42011-02-28 18:59:47 +0000205 pjmedia_format_id base_fmt_id;
Nanang Izzuddin678b2f82011-03-02 08:37:31 +0000206 pj_uint32_t avg_bps;
207 pj_uint32_t max_bps;
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000208 func_packetize packetize;
209 func_unpacketize unpacketize;
210 func_parse_fmtp parse_fmtp;
211 pjmedia_codec_fmtp dec_fmtp;
212
213 /* Init time defined info */
214 pj_bool_t enabled;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000215 AVCodec *enc;
216 AVCodec *dec;
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000217};
Benny Prijonoc45d9512010-12-10 11:04:30 +0000218
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000219/* H263 packetizer */
220static pj_status_t h263_packetize(pj_uint8_t *buf,
221 pj_size_t buf_len,
222 unsigned *pos,
223 int max_payload_len,
224 const pj_uint8_t **payload,
225 pj_size_t *payload_len)
226{
227 return pjmedia_h263_packetize(buf, buf_len, pos, max_payload_len,
228 payload, payload_len);
229}
Benny Prijonoc45d9512010-12-10 11:04:30 +0000230
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000231/* H263 unpacketizer */
232static pj_status_t h263_unpacketize(const pj_uint8_t *payload,
233 pj_size_t payload_len,
234 pj_uint8_t *bits,
235 pj_size_t *bits_len)
236{
237 return pjmedia_h263_unpacketize(payload, payload_len, bits, bits_len);
238}
239
240/* H263 fmtp parser */
241static pj_status_t h263_parse_fmtp(ffmpeg_private *ff);
242
243
244/* Internal codec info */
245ffmpeg_codec_desc codec_desc[] =
246{
247 {
Benny Prijono135290d2011-03-17 11:33:34 +0000248 {PJMEDIA_FORMAT_H263P, {"H263-1998",9}, PJMEDIA_RTP_PT_H263P},
Nanang Izzuddin678b2f82011-03-02 08:37:31 +0000249 PJMEDIA_FORMAT_H263, 1000000, 2000000,
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000250 &h263_packetize, &h263_unpacketize, &h263_parse_fmtp,
251 {2, { {{"CIF",3}, {"2",1}}, {{"QCIF",4}, {"1",1}}, } },
252 },
253 {
Nanang Izzuddin235e1b42011-02-28 18:59:47 +0000254 {PJMEDIA_FORMAT_H263, {"H263",4}, PJMEDIA_RTP_PT_H263},
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000255 },
256 {
Benny Prijono135290d2011-03-17 11:33:34 +0000257 {PJMEDIA_FORMAT_H264, {"H264",4}, PJMEDIA_RTP_PT_H264},
258 },
259 {
Nanang Izzuddin235e1b42011-02-28 18:59:47 +0000260 {PJMEDIA_FORMAT_H261, {"H261",4}, PJMEDIA_RTP_PT_H261},
261 },
262 {
263 {PJMEDIA_FORMAT_MJPEG, {"JPEG",4}, PJMEDIA_RTP_PT_JPEG},
264 },
265 {
Benny Prijono135290d2011-03-17 11:33:34 +0000266 {PJMEDIA_FORMAT_MPEG4, {"MP4V",4}},
Nanang Izzuddin235e1b42011-02-28 18:59:47 +0000267 },
268 {
Benny Prijono135290d2011-03-17 11:33:34 +0000269 {PJMEDIA_FORMAT_XVID, {"XVID",4}},
Nanang Izzuddin235e1b42011-02-28 18:59:47 +0000270 PJMEDIA_FORMAT_MPEG4,
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000271 },
272};
273
274/* Parse fmtp value for custom resolution, e.g: "CUSTOM=800,600,2" */
275static pj_status_t parse_fmtp_itu_custom_res(const pj_str_t *fmtp_val,
276 pjmedia_rect_size *size,
277 unsigned *mpi)
278{
279 const char *p, *p_end;
280 pj_str_t token;
281 unsigned long val[3] = {0};
282 unsigned i = 0;
283
284 p = token.ptr = fmtp_val->ptr;
285 p_end = p + fmtp_val->slen;
286
287 while (p<=p_end && i<PJ_ARRAY_SIZE(val)) {
288 if (*p==',' || p==p_end) {
289 token.slen = (char*)p - token.ptr;
290 val[i++] = pj_strtoul(&token);
291 token.ptr = (char*)p+1;
292 }
293 ++p;
294 }
295
296 if (!val[0] || !val[1])
297 return PJ_ETOOSMALL;
298
299 if (val[2]<1 || val[2]>32)
300 return PJ_EINVAL;
301
302 size->w = val[0];
303 size->h = val[1];
304 *mpi = val[2];
305 return PJ_SUCCESS;
306}
307
308#define CALC_ITU_CUSTOM_RES_SCORE(size, mpi) ((size)->w * (size)->h / mpi)
309
310/* ITU codec capabilities */
311typedef struct itu_cap
312{
313 /* Lowest MPI for each non-custom resolution */
314 unsigned lowest_mpi[PJ_ARRAY_SIZE(itu_res_def)];
315 /* For custom resolution, we use maximum processing score */
316 unsigned custom_res_max_score;
317} itu_cap;
318
319
320static pj_status_t load_itu_cap(const pjmedia_codec_fmtp *fmtp,
321 itu_cap *cap)
322{
323 unsigned i, j;
324 unsigned min_mpi = 0;
325
326 /* Get Minimum Picture Interval (MPI) for each resolution. If a resolution
327 * has no MPI setting in fmtp, the MPI setting is derived from the higher
328 * resolution.
329 */
330 for (i=0; i<PJ_ARRAY_SIZE(itu_res_def); ++i) {
331
332 /* Init lowest MPI */
333 cap->lowest_mpi[i] = min_mpi? min_mpi:1;
334
335 for (j=0; j<fmtp->cnt; ++j) {
336 if (pj_stricmp(&fmtp->param[j].name, &itu_res_def[i].name)==0) {
337 pjmedia_rect_size size;
338 unsigned mpi;
339 unsigned score;
340
341 if (i != ITU_RES_CUSTOM) {
342 size = itu_res_def[i].size;
343 mpi = pj_strtoul(&fmtp->param[j].val);
344 if (min_mpi)
345 min_mpi = PJ_MIN(mpi, min_mpi);
346 else
347 min_mpi = mpi;
348
349 /* Update the lowest MPI for this resolution */
350 cap->lowest_mpi[i] = min_mpi;
351
352 /* Also update the processing score for the custom
353 * resolution.
354 */
355 score = CALC_ITU_CUSTOM_RES_SCORE(&size, mpi);
356 cap->custom_res_max_score =
357 PJ_MAX(score, cap->custom_res_max_score);
358 } else {
359
360
361 if (parse_fmtp_itu_custom_res(&fmtp->param[j].val,
362 &size, &mpi) == PJ_SUCCESS)
363 {
364 score = CALC_ITU_CUSTOM_RES_SCORE(&size, mpi);
365 cap->custom_res_max_score =
366 PJ_MAX(score, cap->custom_res_max_score);
367 }
368 }
369 }
370 }
371 }
372
373 return PJ_SUCCESS;
374}
375
376/* H263 fmtp parser */
377static pj_status_t h263_parse_fmtp(ffmpeg_private *ff)
378{
379 pjmedia_dir dir;
380 pj_status_t status;
381
382 dir = ff->param.dir;
383
384 if (ff->param.dir & PJMEDIA_DIR_ENCODING) {
385 pjmedia_vid_codec_param param_ref;
386 pjmedia_codec_fmtp *fmtp_rem, *fmtp_ref;
387 itu_cap local_cap;
388 pjmedia_rect_size size = {0};
389 unsigned mpi = 0;
390 pj_bool_t got_good_res = PJ_FALSE;
391 pj_bool_t has_prefered_res = PJ_FALSE;
392 unsigned i, j;
393
394 fmtp_rem = &ff->param.enc_fmtp;
395 dir &= ~PJMEDIA_DIR_ENCODING;
396
397 /* Get default fmtp setting as the reference for local capabilities */
398 status = pjmedia_vid_codec_mgr_get_default_param(
399 ffmpeg_factory.mgr, &ff->desc->info, &param_ref);
400 fmtp_ref = (status==PJ_SUCCESS)? &param_ref.enc_fmtp : fmtp_rem;
401
402 /* Load default local capabilities */
403 status = load_itu_cap(fmtp_ref, &local_cap);
404 pj_assert(status == PJ_SUCCESS);
405
406 /* Negotiate resolution and MPI */
407 for (i=0; i<fmtp_rem->cnt && !got_good_res; ++i)
408 {
409 for (j=0; j<PJ_ARRAY_SIZE(itu_res_def) && !got_good_res; ++j)
410 {
411 if (pj_stricmp(&fmtp_rem->param[i].name, &itu_res_def[j].name))
412 continue;
413
414 has_prefered_res = PJ_TRUE;
415 if (j == ITU_RES_CUSTOM) {
416 unsigned score;
417
418 if (parse_fmtp_itu_custom_res(&fmtp_rem->param[i].val,
419 &size, &mpi) != PJ_SUCCESS)
420 {
421 /* Invalid custom resolution format, skip this
422 * custom resolution
423 */
424 break;
425 }
426
427 score = CALC_ITU_CUSTOM_RES_SCORE(&size, mpi);
428 if (score <= local_cap.custom_res_max_score)
429 got_good_res = PJ_TRUE;
430 } else {
431 mpi = pj_strtoul(&fmtp_rem->param[i].val);
432 if (mpi>=1 && mpi<=32 && mpi>=local_cap.lowest_mpi[j]) {
433 got_good_res = PJ_TRUE;
434 size = itu_res_def[j].size;
435 }
436 }
437 }
438 }
439
440 if (has_prefered_res) {
441 if (got_good_res) {
442 pjmedia_video_format_detail *vfd;
443
444 /* Apply this size & MPI */
445 vfd = pjmedia_format_get_video_format_detail(&ff->param.enc_fmt,
446 PJ_TRUE);
447 vfd->size = size;
448 vfd->fps.num = 30000;
449 vfd->fps.denum = 1001 * mpi;
450 got_good_res = PJ_TRUE;
451
452 PJ_TODO(NOTIFY_APP_ABOUT_THIS_NEW_ENCODING_FORMAT);
453 } else {
Benny Prijono135290d2011-03-17 11:33:34 +0000454 return PJMEDIA_EBADFMT;
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000455 }
456 }
457 }
458
459 return PJ_SUCCESS;
460}
461
462
463
Nanang Izzuddin235e1b42011-02-28 18:59:47 +0000464static const ffmpeg_codec_desc* find_codec_desc_by_info(
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000465 const pjmedia_vid_codec_info *info)
466{
467 int i;
468
469 for (i=0; i<PJ_ARRAY_SIZE(codec_desc); ++i) {
470 ffmpeg_codec_desc *desc = &codec_desc[i];
471
472 if (desc->enabled &&
473 (desc->info.fmt_id == info->fmt_id) &&
474 ((desc->info.dir & info->dir) == info->dir) &&
475 pj_stricmp(&desc->info.encoding_name, &info->encoding_name)==0)
476 {
477 return desc;
478 }
479 }
480
481 return NULL;
482}
483
484
Nanang Izzuddin235e1b42011-02-28 18:59:47 +0000485static int find_codec_idx_by_fmt_id(pjmedia_format_id fmt_id)
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000486{
487 int i;
488 for (i=0; i<PJ_ARRAY_SIZE(codec_desc); ++i) {
489 if (codec_desc[i].info.fmt_id == fmt_id)
490 return i;
491 }
492
493 return -1;
494}
Benny Prijonoc45d9512010-12-10 11:04:30 +0000495
496
497/*
498 * Initialize and register FFMPEG codec factory to pjmedia endpoint.
499 */
500PJ_DEF(pj_status_t) pjmedia_codec_ffmpeg_init(pjmedia_vid_codec_mgr *mgr,
501 pj_pool_factory *pf)
502{
503 pj_pool_t *pool;
504 AVCodec *c;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000505 pj_status_t status;
Nanang Izzuddin235e1b42011-02-28 18:59:47 +0000506 unsigned i;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000507
508 if (ffmpeg_factory.pool != NULL) {
509 /* Already initialized. */
510 return PJ_SUCCESS;
511 }
512
513 if (!mgr) mgr = pjmedia_vid_codec_mgr_instance();
514 PJ_ASSERT_RETURN(mgr, PJ_EINVAL);
515
516 /* Create FFMPEG codec factory. */
517 ffmpeg_factory.base.op = &ffmpeg_factory_op;
518 ffmpeg_factory.base.factory_data = NULL;
519 ffmpeg_factory.mgr = mgr;
520 ffmpeg_factory.pf = pf;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000521
522 pool = pj_pool_create(pf, "ffmpeg codec factory", 256, 256, NULL);
523 if (!pool)
524 return PJ_ENOMEM;
525
526 /* Create mutex. */
527 status = pj_mutex_create_simple(pool, "ffmpeg codec factory",
528 &ffmpeg_factory.mutex);
529 if (status != PJ_SUCCESS)
530 goto on_error;
531
532 avcodec_init();
533 avcodec_register_all();
Benny Prijono135290d2011-03-17 11:33:34 +0000534 av_log_set_level(AV_LOG_ERROR);
Benny Prijonoc45d9512010-12-10 11:04:30 +0000535
536 /* Enum FFMPEG codecs */
537 for (c=av_codec_next(NULL); c; c=av_codec_next(c))
538 {
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000539 ffmpeg_codec_desc *desc;
540 pjmedia_format_id fmt_id;
541 int codec_info_idx;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000542
543 if (c->type != CODEC_TYPE_VIDEO)
544 continue;
545
546 /* Video encoder and decoder are usually implemented in separate
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000547 * AVCodec instances. While the codec attributes (e.g: raw formats,
548 * supported fps) are in the encoder.
Benny Prijonoc45d9512010-12-10 11:04:30 +0000549 */
550
Nanang Izzuddin235e1b42011-02-28 18:59:47 +0000551 //PJ_LOG(3, (THIS_FILE, "%s", c->name));
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000552 status = CodecID_to_pjmedia_format_id(c->id, &fmt_id);
553 /* Skip if format ID is unknown */
554 if (status != PJ_SUCCESS)
555 continue;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000556
Nanang Izzuddin235e1b42011-02-28 18:59:47 +0000557 codec_info_idx = find_codec_idx_by_fmt_id(fmt_id);
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000558 /* Skip if codec is unwanted by this wrapper (not listed in
559 * the codec info array)
560 */
561 if (codec_info_idx < 0)
562 continue;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000563
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000564 desc = &codec_desc[codec_info_idx];
Benny Prijonoc45d9512010-12-10 11:04:30 +0000565
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000566 /* Skip duplicated codec implementation */
567 if ((c->encode && (desc->info.dir & PJMEDIA_DIR_ENCODING)) ||
568 (c->decode && (desc->info.dir & PJMEDIA_DIR_DECODING)))
569 {
570 continue;
571 }
Benny Prijonoc45d9512010-12-10 11:04:30 +0000572
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000573 /* Get raw/decoded format ids in the encoder */
574 if (c->pix_fmts && c->encode) {
575 pjmedia_format_id raw_fmt[PJMEDIA_VID_CODEC_MAX_DEC_FMT_CNT];
576 unsigned raw_fmt_cnt = 0;
577 unsigned raw_fmt_cnt_should_be = 0;
578 const enum PixelFormat *p = c->pix_fmts;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000579
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000580 for(;(p && *p != -1) &&
581 (raw_fmt_cnt < PJMEDIA_VID_CODEC_MAX_DEC_FMT_CNT);
582 ++p)
583 {
584 pjmedia_format_id fmt_id;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000585
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000586 raw_fmt_cnt_should_be++;
587 status = PixelFormat_to_pjmedia_format_id(*p, &fmt_id);
588 if (status != PJ_SUCCESS) {
589 PJ_LOG(6, (THIS_FILE, "Unrecognized ffmpeg pixel "
590 "format %d", *p));
591 continue;
592 }
593 raw_fmt[raw_fmt_cnt++] = fmt_id;
594 }
Benny Prijonoc45d9512010-12-10 11:04:30 +0000595
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000596 if (raw_fmt_cnt == 0) {
597 PJ_LOG(5, (THIS_FILE, "No recognized raw format "
598 "for codec [%s/%s], codec ignored",
599 c->name, c->long_name));
600 /* Skip this encoder */
601 continue;
602 }
Benny Prijonoc45d9512010-12-10 11:04:30 +0000603
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000604 if (raw_fmt_cnt < raw_fmt_cnt_should_be) {
605 PJ_LOG(6, (THIS_FILE, "Codec [%s/%s] have %d raw formats, "
606 "recognized only %d raw formats",
607 c->name, c->long_name,
608 raw_fmt_cnt_should_be, raw_fmt_cnt));
609 }
Benny Prijonoc45d9512010-12-10 11:04:30 +0000610
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000611 desc->info.dec_fmt_id_cnt = raw_fmt_cnt;
612 pj_memcpy(desc->info.dec_fmt_id, raw_fmt,
613 sizeof(raw_fmt[0])*raw_fmt_cnt);
614 }
615
616 /* Get supported framerates */
617 if (c->supported_framerates) {
618 const AVRational *fr = c->supported_framerates;
619 while ((fr->num != 0 || fr->den != 0) &&
620 desc->info.fps_cnt < PJMEDIA_VID_CODEC_MAX_FPS_CNT)
621 {
622 desc->info.fps[desc->info.fps_cnt].num = fr->num;
623 desc->info.fps[desc->info.fps_cnt].denum = fr->den;
624 ++desc->info.fps_cnt;
625 ++fr;
626 }
627 }
628
629 /* Get ffmpeg encoder instance */
630 if (c->encode && !desc->enc) {
631 desc->info.dir |= PJMEDIA_DIR_ENCODING;
632 desc->enc = c;
633 }
634
635 /* Get ffmpeg decoder instance */
636 if (c->decode && !desc->dec) {
637 desc->info.dir |= PJMEDIA_DIR_DECODING;
638 desc->dec = c;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000639 }
640
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000641 /* Enable this codec when any ffmpeg codec instance are recognized
642 * and the supported raw formats info has been collected.
643 */
644 if ((desc->dec || desc->enc) && desc->info.dec_fmt_id_cnt)
645 {
646 desc->enabled = PJ_TRUE;
647 }
Benny Prijonoc45d9512010-12-10 11:04:30 +0000648
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000649 /* Normalize default value of clock rate */
650 if (desc->info.clock_rate == 0)
651 desc->info.clock_rate = 90000;
Benny Prijono135290d2011-03-17 11:33:34 +0000652
653 /* Set RTP packetization support flag in the codec info */
654 desc->info.has_rtp_pack = (desc->packetize != NULL) &&
655 (desc->unpacketize != NULL);
Benny Prijonoc45d9512010-12-10 11:04:30 +0000656 }
657
Nanang Izzuddin235e1b42011-02-28 18:59:47 +0000658 /* Init unassigned encoder/decoder description from base codec */
659 for (i = 0; i < PJ_ARRAY_SIZE(codec_desc); ++i) {
660 ffmpeg_codec_desc *desc = &codec_desc[i];
661
662 if (desc->base_fmt_id && (!desc->dec || !desc->enc)) {
663 ffmpeg_codec_desc *base_desc = NULL;
664 int base_desc_idx;
665 pjmedia_dir copied_dir = PJMEDIA_DIR_NONE;
666
667 base_desc_idx = find_codec_idx_by_fmt_id(desc->base_fmt_id);
668 if (base_desc_idx != -1)
669 base_desc = &codec_desc[base_desc_idx];
670 if (!base_desc || !base_desc->enabled)
671 continue;
672
673 /* Copy description from base codec */
674 if (!desc->info.dec_fmt_id_cnt) {
675 desc->info.dec_fmt_id_cnt = base_desc->info.dec_fmt_id_cnt;
676 pj_memcpy(desc->info.dec_fmt_id, base_desc->info.dec_fmt_id,
677 sizeof(pjmedia_format_id)*desc->info.dec_fmt_id_cnt);
678 }
679 if (!desc->info.fps_cnt) {
680 desc->info.fps_cnt = base_desc->info.fps_cnt;
681 pj_memcpy(desc->info.fps, base_desc->info.fps,
682 sizeof(desc->info.fps[0])*desc->info.fps_cnt);
683 }
684 if (!desc->info.clock_rate) {
685 desc->info.clock_rate = base_desc->info.clock_rate;
686 }
687 if (!desc->dec && base_desc->dec) {
688 copied_dir |= PJMEDIA_DIR_DECODING;
689 desc->dec = base_desc->dec;
690 }
691 if (!desc->enc && base_desc->enc) {
692 copied_dir |= PJMEDIA_DIR_ENCODING;
693 desc->enc = base_desc->enc;
694 }
695
696 desc->info.dir |= copied_dir;
697 desc->enabled = (desc->info.dir != PJMEDIA_DIR_NONE);
698
699 if (copied_dir != PJMEDIA_DIR_NONE) {
700 const char *dir_name[] = {NULL, "encoder", "decoder", "codec"};
701 PJ_LOG(5, (THIS_FILE, "The %.*s %s is using base codec (%.*s)",
702 desc->info.encoding_name.slen,
703 desc->info.encoding_name.ptr,
704 dir_name[copied_dir],
705 base_desc->info.encoding_name.slen,
706 base_desc->info.encoding_name.ptr));
707 }
708 }
709 }
710
Benny Prijonoc45d9512010-12-10 11:04:30 +0000711 /* Register codec factory to codec manager. */
712 status = pjmedia_vid_codec_mgr_register_factory(mgr,
713 &ffmpeg_factory.base);
714 if (status != PJ_SUCCESS)
715 goto on_error;
716
717 ffmpeg_factory.pool = pool;
718
719 /* Done. */
720 return PJ_SUCCESS;
721
722on_error:
723 pj_pool_release(pool);
724 return status;
725}
726
727/*
728 * Unregister FFMPEG codecs factory from pjmedia endpoint.
729 */
730PJ_DEF(pj_status_t) pjmedia_codec_ffmpeg_deinit(void)
731{
732 pj_status_t status = PJ_SUCCESS;
733
734 if (ffmpeg_factory.pool == NULL) {
735 /* Already deinitialized */
736 return PJ_SUCCESS;
737 }
738
739 pj_mutex_lock(ffmpeg_factory.mutex);
740
741 /* Unregister FFMPEG codecs factory. */
742 status = pjmedia_vid_codec_mgr_unregister_factory(ffmpeg_factory.mgr,
743 &ffmpeg_factory.base);
744
745 /* Destroy mutex. */
746 pj_mutex_destroy(ffmpeg_factory.mutex);
747
748 /* Destroy pool. */
749 pj_pool_release(ffmpeg_factory.pool);
750 ffmpeg_factory.pool = NULL;
751
752 return status;
753}
754
755
Benny Prijonoc45d9512010-12-10 11:04:30 +0000756/*
757 * Check if factory can allocate the specified codec.
758 */
759static pj_status_t ffmpeg_test_alloc( pjmedia_vid_codec_factory *factory,
760 const pjmedia_vid_codec_info *info )
761{
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000762 const ffmpeg_codec_desc *desc;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000763
764 PJ_ASSERT_RETURN(factory==&ffmpeg_factory.base, PJ_EINVAL);
765 PJ_ASSERT_RETURN(info, PJ_EINVAL);
766
Nanang Izzuddin235e1b42011-02-28 18:59:47 +0000767 desc = find_codec_desc_by_info(info);
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000768 if (!desc) {
Benny Prijonoc45d9512010-12-10 11:04:30 +0000769 return PJMEDIA_CODEC_EUNSUP;
770 }
771
772 return PJ_SUCCESS;
773}
774
775/*
776 * Generate default attribute.
777 */
778static pj_status_t ffmpeg_default_attr( pjmedia_vid_codec_factory *factory,
779 const pjmedia_vid_codec_info *info,
780 pjmedia_vid_codec_param *attr )
781{
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000782 const ffmpeg_codec_desc *desc;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000783
784 PJ_ASSERT_RETURN(factory==&ffmpeg_factory.base, PJ_EINVAL);
785 PJ_ASSERT_RETURN(info && attr, PJ_EINVAL);
786
Nanang Izzuddin235e1b42011-02-28 18:59:47 +0000787 desc = find_codec_desc_by_info(info);
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000788 if (!desc) {
Benny Prijonoc45d9512010-12-10 11:04:30 +0000789 return PJMEDIA_CODEC_EUNSUP;
790 }
791
792 pj_bzero(attr, sizeof(pjmedia_vid_codec_param));
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000793
794 /* Direction */
795 attr->dir = desc->info.dir;
796
797 /* Encoded format */
798 pjmedia_format_init_video(&attr->enc_fmt, desc->info.fmt_id,
799 352, 288, 30000, 1001);
800
801 /* Decoded format */
802 pjmedia_format_init_video(&attr->dec_fmt, desc->info.dec_fmt_id[0],
803 352, 288, 30000, 1001);
804
805 /* Decoding fmtp */
806 attr->dec_fmtp = desc->dec_fmtp;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000807
Nanang Izzuddin678b2f82011-03-02 08:37:31 +0000808 /* Bitrate */
809 attr->enc_fmt.det.vid.avg_bps = desc->avg_bps;
810 attr->enc_fmt.det.vid.max_bps = desc->max_bps;
811
Benny Prijonoc45d9512010-12-10 11:04:30 +0000812 return PJ_SUCCESS;
813}
814
815/*
816 * Enum codecs supported by this factory.
817 */
818static pj_status_t ffmpeg_enum_codecs( pjmedia_vid_codec_factory *factory,
819 unsigned *count,
820 pjmedia_vid_codec_info codecs[])
821{
Nanang Izzuddin235e1b42011-02-28 18:59:47 +0000822 unsigned i, max_cnt;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000823
824 PJ_ASSERT_RETURN(codecs && *count > 0, PJ_EINVAL);
825 PJ_ASSERT_RETURN(factory == &ffmpeg_factory.base, PJ_EINVAL);
826
Nanang Izzuddin235e1b42011-02-28 18:59:47 +0000827 max_cnt = PJ_MIN(*count, PJ_ARRAY_SIZE(codec_desc));
828 *count = 0;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000829
Nanang Izzuddin235e1b42011-02-28 18:59:47 +0000830 for (i=0; i<max_cnt; ++i) {
831 if (codec_desc[i].enabled) {
832 pj_memcpy(&codecs[*count], &codec_desc[i].info,
833 sizeof(pjmedia_vid_codec_info));
834 (*count)++;
835 }
Benny Prijonoc45d9512010-12-10 11:04:30 +0000836 }
Benny Prijonoc45d9512010-12-10 11:04:30 +0000837
838 return PJ_SUCCESS;
839}
840
841/*
842 * Allocate a new codec instance.
843 */
844static pj_status_t ffmpeg_alloc_codec( pjmedia_vid_codec_factory *factory,
845 const pjmedia_vid_codec_info *info,
846 pjmedia_vid_codec **p_codec)
847{
848 ffmpeg_private *ff;
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000849 const ffmpeg_codec_desc *desc;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000850 pjmedia_vid_codec *codec;
851 pj_pool_t *pool = NULL;
852 pj_status_t status = PJ_SUCCESS;
853
854 PJ_ASSERT_RETURN(factory && info && p_codec, PJ_EINVAL);
855 PJ_ASSERT_RETURN(factory == &ffmpeg_factory.base, PJ_EINVAL);
856
Nanang Izzuddin235e1b42011-02-28 18:59:47 +0000857 desc = find_codec_desc_by_info(info);
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000858 if (!desc) {
Benny Prijonoc45d9512010-12-10 11:04:30 +0000859 return PJMEDIA_CODEC_EUNSUP;
860 }
861
862 /* Create pool for codec instance */
863 pool = pj_pool_create(ffmpeg_factory.pf, "ffmpeg codec", 512, 512, NULL);
864 codec = PJ_POOL_ZALLOC_T(pool, pjmedia_vid_codec);
865 if (!codec) {
866 status = PJ_ENOMEM;
867 goto on_error;
868 }
869 codec->op = &ffmpeg_op;
870 codec->factory = factory;
871 ff = PJ_POOL_ZALLOC_T(pool, ffmpeg_private);
872 if (!ff) {
873 status = PJ_ENOMEM;
874 goto on_error;
875 }
876 codec->codec_data = ff;
877 ff->pool = pool;
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000878 ff->enc = desc->enc;
879 ff->dec = desc->dec;
880 ff->desc = desc;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000881
882 *p_codec = codec;
883 return PJ_SUCCESS;
884
885on_error:
886 if (pool)
887 pj_pool_release(pool);
888 return status;
889}
890
891/*
892 * Free codec.
893 */
894static pj_status_t ffmpeg_dealloc_codec( pjmedia_vid_codec_factory *factory,
895 pjmedia_vid_codec *codec )
896{
897 ffmpeg_private *ff;
898 pj_pool_t *pool;
899
900 PJ_ASSERT_RETURN(factory && codec, PJ_EINVAL);
901 PJ_ASSERT_RETURN(factory == &ffmpeg_factory.base, PJ_EINVAL);
902
903 /* Close codec, if it's not closed. */
904 ff = (ffmpeg_private*) codec->codec_data;
905 pool = ff->pool;
906 codec->codec_data = NULL;
907 pj_pool_release(pool);
908
909 return PJ_SUCCESS;
910}
911
912/*
913 * Init codec.
914 */
915static pj_status_t ffmpeg_codec_init( pjmedia_vid_codec *codec,
916 pj_pool_t *pool )
917{
918 PJ_UNUSED_ARG(codec);
919 PJ_UNUSED_ARG(pool);
920 return PJ_SUCCESS;
921}
922
923static void print_ffmpeg_err(int err)
924{
925#if LIBAVCODEC_VERSION_MAJOR >= 52 && LIBAVCODEC_VERSION_MINOR >= 72
926 char errbuf[512];
927 if (av_strerror(err, errbuf, sizeof(errbuf)) >= 0)
928 PJ_LOG(1, (THIS_FILE, "ffmpeg err %d: %s", err, errbuf));
929#else
930 PJ_LOG(1, (THIS_FILE, "ffmpeg err %d", err));
931#endif
932
933}
934
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000935static enum PixelFormat dec_get_format(struct AVCodecContext *s,
Benny Prijonoc45d9512010-12-10 11:04:30 +0000936 const enum PixelFormat * fmt)
937{
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000938 ffmpeg_private *ff = (ffmpeg_private*)s->opaque;
939 enum PixelFormat def_fmt = *fmt;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000940
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000941 while (*fmt != -1) {
942 if (*fmt == ff->expected_dec_fmt)
943 return *fmt;
944 ++fmt;
945 }
Benny Prijonoc45d9512010-12-10 11:04:30 +0000946
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000947 pj_assert(!"Inconsistency in supported formats");
948 return def_fmt;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000949}
950
Benny Prijonoc45d9512010-12-10 11:04:30 +0000951
952static pj_status_t open_ffmpeg_codec(ffmpeg_private *ff,
953 pj_mutex_t *ff_mutex)
954{
955 enum PixelFormat pix_fmt;
956 pj_status_t status;
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000957 pjmedia_video_format_detail *vfd;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000958
959 status = pjmedia_format_id_to_PixelFormat(ff->param.dec_fmt.id,
960 &pix_fmt);
961 if (status != PJ_SUCCESS)
962 return status;
963
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000964 vfd = pjmedia_format_get_video_format_detail(&ff->param.enc_fmt,
965 PJ_TRUE);
966 ff->expected_dec_fmt = pix_fmt;
967
Benny Prijonoc45d9512010-12-10 11:04:30 +0000968 while (((ff->param.dir & PJMEDIA_DIR_ENCODING) && ff->enc_ctx == NULL) ||
969 ((ff->param.dir & PJMEDIA_DIR_DECODING) && ff->dec_ctx == NULL))
970 {
971 pjmedia_dir dir;
972 AVCodecContext *ctx = NULL;
973 AVCodec *codec = NULL;
974 int err;
975
976 /* Set which direction to open */
977 if (ff->param.dir==PJMEDIA_DIR_ENCODING_DECODING && ff->enc!=ff->dec) {
978 dir = ff->enc_ctx? PJMEDIA_DIR_DECODING : PJMEDIA_DIR_ENCODING;
979 } else {
980 dir = ff->param.dir;
981 }
982
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000983 /* Init ffmpeg codec context */
Benny Prijonoc45d9512010-12-10 11:04:30 +0000984 ctx = avcodec_alloc_context();
985
986 /* Common attributes */
987 ctx->pix_fmt = pix_fmt;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000988 ctx->workaround_bugs = FF_BUG_AUTODETECT;
989 ctx->opaque = ff;
990
991 if (dir & PJMEDIA_DIR_ENCODING) {
992 codec = ff->enc;
993
994 /* Encoding only attributes */
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000995 ctx->width = vfd->size.w;
996 ctx->height = vfd->size.h;
997 ctx->time_base.num = vfd->fps.denum;
998 ctx->time_base.den = vfd->fps.num;
Nanang Izzuddin678b2f82011-03-02 08:37:31 +0000999 if (vfd->avg_bps) {
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001000 ctx->bit_rate = vfd->avg_bps;
Benny Prijono135290d2011-03-17 11:33:34 +00001001 if (vfd->max_bps > vfd->avg_bps)
Nanang Izzuddin678b2f82011-03-02 08:37:31 +00001002 ctx->bit_rate_tolerance = vfd->max_bps - vfd->avg_bps;
1003 }
Benny Prijonoc45d9512010-12-10 11:04:30 +00001004
Benny Prijono135290d2011-03-17 11:33:34 +00001005 /* Libx264 experimental setting (it rejects ffmpeg defaults) */
1006 if (ff->param.enc_fmt.id == PJMEDIA_FORMAT_H264) {
1007 ctx->me_range = 16;
1008 ctx->max_qdiff = 4;
1009 ctx->qmin = 10;
1010 ctx->qmax = 51;
1011 ctx->qcompress = 0.6f;
1012 }
1013
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001014 /* For encoder, should be better to be strict to the standards */
Benny Prijonoc45d9512010-12-10 11:04:30 +00001015 ctx->strict_std_compliance = FF_COMPLIANCE_STRICT;
1016 }
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001017
Benny Prijonoc45d9512010-12-10 11:04:30 +00001018 if (dir & PJMEDIA_DIR_DECODING) {
1019 codec = ff->dec;
1020
1021 /* Decoding only attributes */
Nanang Izzuddin235e1b42011-02-28 18:59:47 +00001022
1023 /* Width/height may be overriden by ffmpeg after first decoding. */
1024 ctx->width = ctx->coded_width = ff->param.dec_fmt.det.vid.size.w;
1025 ctx->height = ctx->coded_height = ff->param.dec_fmt.det.vid.size.h;
Benny Prijonoc45d9512010-12-10 11:04:30 +00001026
1027 /* For decoder, be more flexible */
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001028 if (ff->param.dir!=PJMEDIA_DIR_ENCODING_DECODING ||
1029 ff->enc!=ff->dec)
1030 {
Benny Prijonoc45d9512010-12-10 11:04:30 +00001031 ctx->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001032 }
Benny Prijonoc45d9512010-12-10 11:04:30 +00001033
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001034 ctx->get_format = &dec_get_format;
Benny Prijonoc45d9512010-12-10 11:04:30 +00001035 }
1036
1037 /* avcodec_open() should be protected */
1038 pj_mutex_lock(ff_mutex);
1039 err = avcodec_open(ctx, codec);
1040 pj_mutex_unlock(ff_mutex);
1041 if (err < 0) {
1042 print_ffmpeg_err(err);
Benny Prijono135290d2011-03-17 11:33:34 +00001043 return PJMEDIA_CODEC_EFAILED;
Benny Prijonoc45d9512010-12-10 11:04:30 +00001044 }
1045
1046 if (dir & PJMEDIA_DIR_ENCODING)
1047 ff->enc_ctx = ctx;
1048 if (dir & PJMEDIA_DIR_DECODING)
1049 ff->dec_ctx = ctx;
1050 }
1051
1052 return PJ_SUCCESS;
1053}
1054
1055/*
1056 * Open codec.
1057 */
1058static pj_status_t ffmpeg_codec_open( pjmedia_vid_codec *codec,
1059 pjmedia_vid_codec_param *attr )
1060{
1061 ffmpeg_private *ff;
1062 pj_status_t status;
1063 pj_mutex_t *ff_mutex;
1064
1065 PJ_ASSERT_RETURN(codec && attr, PJ_EINVAL);
1066 ff = (ffmpeg_private*)codec->codec_data;
1067
Benny Prijonoc45d9512010-12-10 11:04:30 +00001068 pj_memcpy(&ff->param, attr, sizeof(*attr));
1069
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001070 /* Apply SDP fmtp attribute */
1071 if (ff->desc->parse_fmtp) {
1072 status = (*ff->desc->parse_fmtp)(ff);
1073 if (status != PJ_SUCCESS)
1074 goto on_error;
1075 }
1076
1077 /* Open the codec */
Benny Prijonoc45d9512010-12-10 11:04:30 +00001078 ff_mutex = ((struct ffmpeg_factory*)codec->factory)->mutex;
1079 status = open_ffmpeg_codec(ff, ff_mutex);
1080 if (status != PJ_SUCCESS)
1081 goto on_error;
1082
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001083 /* Init format info and apply-param of decoder */
1084 ff->dec_vfi = pjmedia_get_video_format_info(NULL, ff->param.dec_fmt.id);
1085 if (!ff->dec_vfi) {
1086 status = PJ_EINVAL;
1087 goto on_error;
1088 }
1089 pj_bzero(&ff->dec_vafp, sizeof(ff->dec_vafp));
1090 ff->dec_vafp.size = ff->param.dec_fmt.det.vid.size;
1091 ff->dec_vafp.buffer = NULL;
1092 status = (*ff->dec_vfi->apply_fmt)(ff->dec_vfi, &ff->dec_vafp);
1093 if (status != PJ_SUCCESS) {
1094 goto on_error;
1095 }
1096
1097 /* Init format info and apply-param of encoder */
1098 ff->enc_vfi = pjmedia_get_video_format_info(NULL, ff->param.dec_fmt.id);
1099 if (!ff->enc_vfi) {
1100 status = PJ_EINVAL;
1101 goto on_error;
1102 }
1103 pj_bzero(&ff->enc_vafp, sizeof(ff->enc_vafp));
1104 ff->enc_vafp.size = ff->param.enc_fmt.det.vid.size;
1105 ff->enc_vafp.buffer = NULL;
1106 status = (*ff->enc_vfi->apply_fmt)(ff->enc_vfi, &ff->enc_vafp);
1107 if (status != PJ_SUCCESS) {
1108 goto on_error;
1109 }
1110
1111 /* Update codec attributes, e.g: encoding format may be changed by
1112 * SDP fmtp negotiation.
1113 */
1114 pj_memcpy(attr, &ff->param, sizeof(*attr));
1115
Benny Prijonoc45d9512010-12-10 11:04:30 +00001116 return PJ_SUCCESS;
1117
1118on_error:
1119 ffmpeg_codec_close(codec);
1120 return status;
1121}
1122
1123/*
1124 * Close codec.
1125 */
1126static pj_status_t ffmpeg_codec_close( pjmedia_vid_codec *codec )
1127{
1128 ffmpeg_private *ff;
1129 pj_mutex_t *ff_mutex;
1130
1131 PJ_ASSERT_RETURN(codec, PJ_EINVAL);
1132 ff = (ffmpeg_private*)codec->codec_data;
1133 ff_mutex = ((struct ffmpeg_factory*)codec->factory)->mutex;
1134
1135 pj_mutex_lock(ff_mutex);
1136 if (ff->enc_ctx) {
1137 avcodec_close(ff->enc_ctx);
1138 av_free(ff->enc_ctx);
1139 }
1140 if (ff->dec_ctx && ff->dec_ctx!=ff->enc_ctx) {
1141 avcodec_close(ff->dec_ctx);
1142 av_free(ff->dec_ctx);
1143 }
Benny Prijonoc45d9512010-12-10 11:04:30 +00001144 ff->enc_ctx = NULL;
1145 ff->dec_ctx = NULL;
Benny Prijonoc45d9512010-12-10 11:04:30 +00001146 pj_mutex_unlock(ff_mutex);
1147
1148 return PJ_SUCCESS;
1149}
1150
1151
1152/*
1153 * Modify codec settings.
1154 */
1155static pj_status_t ffmpeg_codec_modify( pjmedia_vid_codec *codec,
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001156 const pjmedia_vid_codec_param *attr)
Benny Prijonoc45d9512010-12-10 11:04:30 +00001157{
1158 ffmpeg_private *ff = (ffmpeg_private*)codec->codec_data;
1159
1160 PJ_UNUSED_ARG(attr);
1161 PJ_UNUSED_ARG(ff);
1162
1163 return PJ_ENOTSUP;
1164}
1165
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001166static pj_status_t ffmpeg_codec_get_param(pjmedia_vid_codec *codec,
1167 pjmedia_vid_codec_param *param)
1168{
1169 ffmpeg_private *ff;
1170
1171 PJ_ASSERT_RETURN(codec && param, PJ_EINVAL);
1172
1173 ff = (ffmpeg_private*)codec->codec_data;
1174 pj_memcpy(param, &ff->param, sizeof(*param));
1175
1176 return PJ_SUCCESS;
1177}
1178
1179
Benny Prijonoc45d9512010-12-10 11:04:30 +00001180static pj_status_t ffmpeg_packetize ( pjmedia_vid_codec *codec,
1181 pj_uint8_t *buf,
1182 pj_size_t buf_len,
1183 unsigned *pos,
1184 const pj_uint8_t **payload,
1185 pj_size_t *payload_len)
1186{
1187 ffmpeg_private *ff = (ffmpeg_private*)codec->codec_data;
1188
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001189 if (ff->desc->packetize) {
1190 return (*ff->desc->packetize)(buf, buf_len, pos,
1191 ff->param.enc_mtu, payload,
1192 payload_len);
Benny Prijonoc45d9512010-12-10 11:04:30 +00001193 }
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001194
1195 return PJ_ENOTSUP;
Benny Prijonoc45d9512010-12-10 11:04:30 +00001196}
1197
1198static pj_status_t ffmpeg_unpacketize(pjmedia_vid_codec *codec,
1199 const pj_uint8_t *payload,
1200 pj_size_t payload_len,
1201 pj_uint8_t *buf,
1202 pj_size_t *buf_len)
1203{
1204 ffmpeg_private *ff = (ffmpeg_private*)codec->codec_data;
1205
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001206 if (ff->desc->unpacketize) {
1207 return (*ff->desc->unpacketize)(payload, payload_len,
1208 buf, buf_len);
Benny Prijonoc45d9512010-12-10 11:04:30 +00001209 }
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001210
1211 return PJ_ENOTSUP;
Benny Prijonoc45d9512010-12-10 11:04:30 +00001212}
1213
Benny Prijonoc45d9512010-12-10 11:04:30 +00001214
1215/*
1216 * Encode frames.
1217 */
1218static pj_status_t ffmpeg_codec_encode( pjmedia_vid_codec *codec,
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001219 const pjmedia_frame *input,
Benny Prijonoc45d9512010-12-10 11:04:30 +00001220 unsigned output_buf_len,
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001221 pjmedia_frame *output)
Benny Prijonoc45d9512010-12-10 11:04:30 +00001222{
1223 ffmpeg_private *ff = (ffmpeg_private*)codec->codec_data;
1224 pj_uint8_t *p = (pj_uint8_t*)input->buf;
1225 AVFrame avframe;
1226 pj_uint8_t *out_buf = (pj_uint8_t*)output->buf;
1227 int out_buf_len = output_buf_len;
1228 int err;
Nanang Izzuddinada41262011-03-22 09:43:24 +00001229
1230 /* For some reasons (e.g: SSE/MMX usage), the avcodec_encode_video() must
1231 * have stack aligned to 16 bytes. Let's try to be safe by preparing the
1232 * 16-bytes aligned stack here, in case it's not managed by the ffmpeg.
1233 */
1234 PJ_ALIGN_DATA(pj_uint32_t i[4], 16);
Benny Prijonoc45d9512010-12-10 11:04:30 +00001235
1236 /* Check if encoder has been opened */
1237 PJ_ASSERT_RETURN(ff->enc_ctx, PJ_EINVALIDOP);
1238
Benny Prijonoc45d9512010-12-10 11:04:30 +00001239 avcodec_get_frame_defaults(&avframe);
Benny Prijono135290d2011-03-17 11:33:34 +00001240 avframe.pts = input->timestamp.u64;
Benny Prijonoc45d9512010-12-10 11:04:30 +00001241
Nanang Izzuddinada41262011-03-22 09:43:24 +00001242 for (i[0] = 0; i[0] < ff->enc_vfi->plane_cnt; ++i[0]) {
1243 avframe.data[i[0]] = p;
1244 avframe.linesize[i[0]] = ff->enc_vafp.strides[i[0]];
1245 p += ff->enc_vafp.plane_bytes[i[0]];
Benny Prijonoc45d9512010-12-10 11:04:30 +00001246 }
1247
Nanang Izzuddinada41262011-03-22 09:43:24 +00001248 err = avcodec_encode_video(ff->enc_ctx, out_buf, out_buf_len, &avframe);
Benny Prijonoc45d9512010-12-10 11:04:30 +00001249 if (err < 0) {
1250 print_ffmpeg_err(err);
Benny Prijono135290d2011-03-17 11:33:34 +00001251 return PJMEDIA_CODEC_EFAILED;
Benny Prijonoc45d9512010-12-10 11:04:30 +00001252 } else {
1253 output->size = err;
1254 }
1255
1256 return PJ_SUCCESS;
1257}
1258
1259/*
1260 * Decode frame.
1261 */
1262static pj_status_t ffmpeg_codec_decode( pjmedia_vid_codec *codec,
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001263 const pjmedia_frame *input,
Benny Prijonoc45d9512010-12-10 11:04:30 +00001264 unsigned output_buf_len,
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001265 pjmedia_frame *output)
Benny Prijonoc45d9512010-12-10 11:04:30 +00001266{
1267 ffmpeg_private *ff = (ffmpeg_private*)codec->codec_data;
1268 AVFrame avframe;
1269 AVPacket avpacket;
1270 int err, got_picture;
1271
1272 /* Check if decoder has been opened */
1273 PJ_ASSERT_RETURN(ff->dec_ctx, PJ_EINVALIDOP);
1274
Nanang Izzuddin98610702011-03-01 17:40:17 +00001275 /* Reset output frame bit info */
1276 output->bit_info = 0;
1277
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001278 /* Validate output buffer size */
Nanang Izzuddin98610702011-03-01 17:40:17 +00001279 if (ff->dec_vafp.framebytes > output_buf_len)
1280 return PJ_ETOOSMALL;
Benny Prijonoc45d9512010-12-10 11:04:30 +00001281
1282 /* Init frame to receive the decoded data, the ffmpeg codec context will
1283 * automatically provide the decoded buffer (single buffer used for the
1284 * whole decoding session, and seems to be freed when the codec context
1285 * closed).
1286 */
1287 avcodec_get_frame_defaults(&avframe);
1288
1289 /* Init packet, the container of the encoded data */
1290 av_init_packet(&avpacket);
1291 avpacket.data = (pj_uint8_t*)input->buf;
1292 avpacket.size = input->size;
1293
1294 /* ffmpeg warns:
1295 * - input buffer padding, at least FF_INPUT_BUFFER_PADDING_SIZE
1296 * - null terminated
1297 * Normally, encoded buffer is allocated more than needed, so lets just
1298 * bzero the input buffer end/pad, hope it will be just fine.
1299 */
1300 pj_bzero(avpacket.data+avpacket.size, FF_INPUT_BUFFER_PADDING_SIZE);
1301
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001302 output->bit_info = 0;
Benny Prijono135290d2011-03-17 11:33:34 +00001303 output->timestamp = input->timestamp;
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001304
Benny Prijonoc45d9512010-12-10 11:04:30 +00001305#if LIBAVCODEC_VERSION_MAJOR >= 52 && LIBAVCODEC_VERSION_MINOR >= 72
1306 avpacket.flags = AV_PKT_FLAG_KEY;
1307#else
1308 avpacket.flags = 0;
1309#endif
1310
1311#if LIBAVCODEC_VERSION_MAJOR >= 52 && LIBAVCODEC_VERSION_MINOR >= 72
1312 err = avcodec_decode_video2(ff->dec_ctx, &avframe,
1313 &got_picture, &avpacket);
1314#else
1315 err = avcodec_decode_video(ff->dec_ctx, &avframe,
1316 &got_picture, avpacket.data, avpacket.size);
1317#endif
1318 if (err < 0) {
Benny Prijono135290d2011-03-17 11:33:34 +00001319 output->type = PJMEDIA_FRAME_TYPE_NONE;
1320 output->size = 0;
Benny Prijonoc45d9512010-12-10 11:04:30 +00001321 print_ffmpeg_err(err);
Benny Prijono135290d2011-03-17 11:33:34 +00001322 return PJMEDIA_CODEC_EFAILED;
Benny Prijonoc45d9512010-12-10 11:04:30 +00001323 } else if (got_picture) {
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001324 pjmedia_video_apply_fmt_param *vafp = &ff->dec_vafp;
Benny Prijonoc45d9512010-12-10 11:04:30 +00001325 pj_uint8_t *q = (pj_uint8_t*)output->buf;
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001326 unsigned i;
Benny Prijonoc45d9512010-12-10 11:04:30 +00001327
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001328 /* Decoder output format is set by libavcodec, in case it is different
1329 * to the configured param.
1330 */
1331 if (ff->dec_ctx->pix_fmt != ff->expected_dec_fmt ||
1332 ff->dec_ctx->coded_width != (int)vafp->size.w ||
1333 ff->dec_ctx->coded_height != (int)vafp->size.h)
1334 {
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001335 pjmedia_format_id new_fmt_id;
1336 pj_status_t status;
1337
1338 /* Get current raw format id from ffmpeg decoder context */
1339 status = PixelFormat_to_pjmedia_format_id(ff->dec_ctx->pix_fmt,
1340 &new_fmt_id);
1341 if (status != PJ_SUCCESS)
1342 return status;
1343
1344 /* Update decoder format in param */
1345 ff->param.dec_fmt.id = new_fmt_id;
1346 ff->param.dec_fmt.det.vid.size.w = ff->dec_ctx->coded_width;
1347 ff->param.dec_fmt.det.vid.size.h = ff->dec_ctx->coded_height;
1348
1349 /* Re-init format info and apply-param of decoder */
1350 ff->dec_vfi = pjmedia_get_video_format_info(NULL, ff->param.dec_fmt.id);
1351 if (!ff->dec_vfi)
Benny Prijono135290d2011-03-17 11:33:34 +00001352 return PJ_ENOTSUP;
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001353 pj_bzero(&ff->dec_vafp, sizeof(ff->dec_vafp));
1354 ff->dec_vafp.size = ff->param.dec_fmt.det.vid.size;
1355 ff->dec_vafp.buffer = NULL;
1356 status = (*ff->dec_vfi->apply_fmt)(ff->dec_vfi, &ff->dec_vafp);
1357 if (status != PJ_SUCCESS)
1358 return status;
1359
1360 /* Notify application via the bit_info field of pjmedia_frame */
1361 output->bit_info = PJMEDIA_VID_CODEC_EVENT_FMT_CHANGED;
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001362
Nanang Izzuddin98610702011-03-01 17:40:17 +00001363 /* Check provided buffer size after format changed */
1364 if (vafp->framebytes > output_buf_len)
1365 return PJ_ETOOSMALL;
1366 }
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001367
1368 /* Get the decoded data */
1369 for (i = 0; i < ff->dec_vfi->plane_cnt; ++i) {
1370 pj_uint8_t *p = avframe.data[i];
1371
1372 /* The decoded data may contain padding */
1373 if (avframe.linesize[i]!=vafp->strides[i]) {
1374 /* Padding exists, copy line by line */
1375 pj_uint8_t *q_end;
1376
1377 q_end = q+vafp->plane_bytes[i];
1378 while(q < q_end) {
1379 pj_memcpy(q, p, vafp->strides[i]);
1380 q += vafp->strides[i];
1381 p += avframe.linesize[i];
1382 }
1383 } else {
1384 /* No padding, copy the whole plane */
1385 pj_memcpy(q, p, vafp->plane_bytes[i]);
1386 q += vafp->plane_bytes[i];
1387 }
1388 }
1389
Benny Prijono135290d2011-03-17 11:33:34 +00001390 output->type = PJMEDIA_FRAME_TYPE_VIDEO;
Benny Prijonoc45d9512010-12-10 11:04:30 +00001391 output->size = vafp->framebytes;
1392 } else {
Benny Prijono135290d2011-03-17 11:33:34 +00001393 output->type = PJMEDIA_FRAME_TYPE_NONE;
1394 output->size = 0;
Benny Prijonoc45d9512010-12-10 11:04:30 +00001395 }
Benny Prijono135290d2011-03-17 11:33:34 +00001396
Benny Prijonoc45d9512010-12-10 11:04:30 +00001397 return PJ_SUCCESS;
1398}
1399
1400/*
1401 * Recover lost frame.
1402 */
1403static pj_status_t ffmpeg_codec_recover( pjmedia_vid_codec *codec,
1404 unsigned output_buf_len,
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001405 pjmedia_frame *output)
Benny Prijonoc45d9512010-12-10 11:04:30 +00001406{
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001407 PJ_UNUSED_ARG(codec);
Benny Prijonoc45d9512010-12-10 11:04:30 +00001408 PJ_UNUSED_ARG(output_buf_len);
1409 PJ_UNUSED_ARG(output);
Benny Prijonoc45d9512010-12-10 11:04:30 +00001410
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001411 return PJ_ENOTSUP;
Benny Prijonoc45d9512010-12-10 11:04:30 +00001412}
1413
1414#ifdef _MSC_VER
1415# pragma comment( lib, "avcodec.lib")
Benny Prijonoc45d9512010-12-10 11:04:30 +00001416#endif
1417
1418#endif /* PJMEDIA_HAS_FFMPEG_CODEC */
1419