blob: 78d8131e1f36ddc6ddbe8749c632c05b87efca22 [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>
Nanang Izzuddind91af572011-03-31 17:29:54 +000021#include <pjmedia-codec/h264_packetizer.h>
Benny Prijonoc45d9512010-12-10 11:04:30 +000022#include <pjmedia/errno.h>
Nanang Izzuddind91af572011-03-31 17:29:54 +000023#include <pjmedia/vid_codec_util.h>
Benny Prijonoc45d9512010-12-10 11:04:30 +000024#include <pj/assert.h>
25#include <pj/list.h>
26#include <pj/log.h>
27#include <pj/math.h>
28#include <pj/pool.h>
29#include <pj/string.h>
30#include <pj/os.h>
31
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +000032
Benny Prijonoc45d9512010-12-10 11:04:30 +000033/*
34 * Only build this file if PJMEDIA_HAS_FFMPEG_CODEC != 0
35 */
36#if defined(PJMEDIA_HAS_FFMPEG_CODEC) && PJMEDIA_HAS_FFMPEG_CODEC != 0
37
38#define THIS_FILE "ffmpeg_codecs.c"
39
40#include "../pjmedia/ffmpeg_util.h"
41#include <libavcodec/avcodec.h>
42#include <libavformat/avformat.h>
Benny Prijonoc45d9512010-12-10 11:04:30 +000043
44
45/* Prototypes for FFMPEG codecs factory */
46static pj_status_t ffmpeg_test_alloc( pjmedia_vid_codec_factory *factory,
47 const pjmedia_vid_codec_info *id );
48static pj_status_t ffmpeg_default_attr( pjmedia_vid_codec_factory *factory,
49 const pjmedia_vid_codec_info *info,
50 pjmedia_vid_codec_param *attr );
51static pj_status_t ffmpeg_enum_codecs( pjmedia_vid_codec_factory *factory,
52 unsigned *count,
53 pjmedia_vid_codec_info codecs[]);
54static pj_status_t ffmpeg_alloc_codec( pjmedia_vid_codec_factory *factory,
55 const pjmedia_vid_codec_info *info,
56 pjmedia_vid_codec **p_codec);
57static pj_status_t ffmpeg_dealloc_codec( pjmedia_vid_codec_factory *factory,
58 pjmedia_vid_codec *codec );
59
60/* Prototypes for FFMPEG codecs implementation. */
61static pj_status_t ffmpeg_codec_init( pjmedia_vid_codec *codec,
62 pj_pool_t *pool );
63static pj_status_t ffmpeg_codec_open( pjmedia_vid_codec *codec,
64 pjmedia_vid_codec_param *attr );
65static pj_status_t ffmpeg_codec_close( pjmedia_vid_codec *codec );
66static pj_status_t ffmpeg_codec_modify(pjmedia_vid_codec *codec,
67 const pjmedia_vid_codec_param *attr );
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +000068static pj_status_t ffmpeg_codec_get_param(pjmedia_vid_codec *codec,
69 pjmedia_vid_codec_param *param);
Benny Prijonoc45d9512010-12-10 11:04:30 +000070static pj_status_t ffmpeg_packetize ( pjmedia_vid_codec *codec,
71 pj_uint8_t *buf,
72 pj_size_t buf_len,
73 unsigned *pos,
74 const pj_uint8_t **payload,
75 pj_size_t *payload_len);
76static pj_status_t ffmpeg_unpacketize(pjmedia_vid_codec *codec,
77 const pj_uint8_t *payload,
78 pj_size_t payload_len,
79 pj_uint8_t *buf,
Nanang Izzuddind91af572011-03-31 17:29:54 +000080 pj_size_t buf_len,
81 unsigned *pos);
Benny Prijonoc45d9512010-12-10 11:04:30 +000082static pj_status_t ffmpeg_codec_encode( pjmedia_vid_codec *codec,
83 const pjmedia_frame *input,
84 unsigned output_buf_len,
85 pjmedia_frame *output);
86static pj_status_t ffmpeg_codec_decode( pjmedia_vid_codec *codec,
87 const pjmedia_frame *input,
88 unsigned output_buf_len,
89 pjmedia_frame *output);
90static pj_status_t ffmpeg_codec_recover( pjmedia_vid_codec *codec,
91 unsigned output_buf_len,
92 pjmedia_frame *output);
93
94/* Definition for FFMPEG codecs operations. */
95static pjmedia_vid_codec_op ffmpeg_op =
96{
97 &ffmpeg_codec_init,
98 &ffmpeg_codec_open,
99 &ffmpeg_codec_close,
100 &ffmpeg_codec_modify,
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000101 &ffmpeg_codec_get_param,
Benny Prijonoc45d9512010-12-10 11:04:30 +0000102 &ffmpeg_packetize,
103 &ffmpeg_unpacketize,
104 &ffmpeg_codec_encode,
105 &ffmpeg_codec_decode,
106 NULL //&ffmpeg_codec_recover
107};
108
109/* Definition for FFMPEG codecs factory operations. */
110static pjmedia_vid_codec_factory_op ffmpeg_factory_op =
111{
112 &ffmpeg_test_alloc,
113 &ffmpeg_default_attr,
114 &ffmpeg_enum_codecs,
115 &ffmpeg_alloc_codec,
116 &ffmpeg_dealloc_codec
117};
118
119
Benny Prijonoc45d9512010-12-10 11:04:30 +0000120/* FFMPEG codecs factory */
121static struct ffmpeg_factory {
122 pjmedia_vid_codec_factory base;
123 pjmedia_vid_codec_mgr *mgr;
124 pj_pool_factory *pf;
125 pj_pool_t *pool;
126 pj_mutex_t *mutex;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000127} ffmpeg_factory;
128
129
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000130typedef struct ffmpeg_codec_desc ffmpeg_codec_desc;
131
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000132
Benny Prijonoc45d9512010-12-10 11:04:30 +0000133/* FFMPEG codecs private data. */
Nanang Izzuddind91af572011-03-31 17:29:54 +0000134typedef struct ffmpeg_private
135{
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000136 const ffmpeg_codec_desc *desc;
137 pjmedia_vid_codec_param param; /**< Codec param */
138 pj_pool_t *pool; /**< Pool for each instance */
139 pj_timestamp last_tx; /**< Timestamp of last
140 transmit */
141
142 /* Format info and apply format param */
143 const pjmedia_video_format_info *enc_vfi;
144 pjmedia_video_apply_fmt_param enc_vafp;
145 const pjmedia_video_format_info *dec_vfi;
146 pjmedia_video_apply_fmt_param dec_vafp;
147
148 /* The ffmpeg codec states. */
149 AVCodec *enc;
150 AVCodec *dec;
151 AVCodecContext *enc_ctx;
152 AVCodecContext *dec_ctx;
153
154 /* The ffmpeg decoder cannot set the output format, so format conversion
155 * may be needed for post-decoding.
156 */
157 enum PixelFormat expected_dec_fmt;
Nanang Izzuddind91af572011-03-31 17:29:54 +0000158 /**< Expected output format of
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000159 ffmpeg decoder */
Nanang Izzuddind91af572011-03-31 17:29:54 +0000160
161 void *data; /**< Codec specific data */
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000162} ffmpeg_private;
163
164
Nanang Izzuddind91af572011-03-31 17:29:54 +0000165/* Shortcuts for packetize & unpacketize function declaration,
166 * as it has long params and is reused many times!
167 */
168#define FUNC_PACKETIZE(name) \
169 pj_status_t(name)(ffmpeg_private *ff, pj_uint8_t *bits, \
170 pj_size_t bits_len, unsigned *bits_pos, \
171 const pj_uint8_t **payload, pj_size_t *payload_len)
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000172
Nanang Izzuddind91af572011-03-31 17:29:54 +0000173#define FUNC_UNPACKETIZE(name) \
174 pj_status_t(name)(ffmpeg_private *ff, const pj_uint8_t *payload, \
175 pj_size_t payload_len, pj_uint8_t *bits, \
176 pj_size_t bits_len, unsigned *bits_pos)
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000177
Nanang Izzuddind91af572011-03-31 17:29:54 +0000178typedef FUNC_PACKETIZE(*func_packetize);
179typedef FUNC_UNPACKETIZE(*func_unpacketize);
180typedef pj_status_t (*func_preopen) (ffmpeg_private *ff);
181typedef pj_status_t (*func_postopen) (ffmpeg_private *ff);
182
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000183
184/* FFMPEG codec info */
Nanang Izzuddind91af572011-03-31 17:29:54 +0000185struct ffmpeg_codec_desc
186{
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000187 /* Predefined info */
188 pjmedia_vid_codec_info info;
Nanang Izzuddin235e1b42011-02-28 18:59:47 +0000189 pjmedia_format_id base_fmt_id;
Nanang Izzuddin678b2f82011-03-02 08:37:31 +0000190 pj_uint32_t avg_bps;
191 pj_uint32_t max_bps;
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000192 func_packetize packetize;
193 func_unpacketize unpacketize;
Nanang Izzuddind91af572011-03-31 17:29:54 +0000194 func_preopen preopen;
195 func_preopen postopen;
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000196 pjmedia_codec_fmtp dec_fmtp;
197
198 /* Init time defined info */
199 pj_bool_t enabled;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000200 AVCodec *enc;
201 AVCodec *dec;
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000202};
Benny Prijonoc45d9512010-12-10 11:04:30 +0000203
Benny Prijonoc45d9512010-12-10 11:04:30 +0000204
Nanang Izzuddind91af572011-03-31 17:29:54 +0000205/* Codec specific functions */
206static pj_status_t h264_preopen(ffmpeg_private *ff);
207static pj_status_t h264_postopen(ffmpeg_private *ff);
208static pj_status_t h263_preopen(ffmpeg_private *ff);
209static FUNC_PACKETIZE(h264_packetize);
210static FUNC_UNPACKETIZE(h264_unpacketize);
211static FUNC_PACKETIZE(h263_packetize);
212static FUNC_UNPACKETIZE(h263_unpacketize);
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000213
214
215/* Internal codec info */
216ffmpeg_codec_desc codec_desc[] =
217{
218 {
Nanang Izzuddind91af572011-03-31 17:29:54 +0000219 {PJMEDIA_FORMAT_H264, {"H264",4}, PJMEDIA_RTP_PT_H264},
220 0, 500000, 1000000,
221 &h264_packetize, &h264_unpacketize, &h264_preopen, &h264_postopen,
222 /* Leading space for better compatibility (strange indeed!) */
223 {2, { {{" profile-level-id",17}, {"42e01e",6}},
224 {{" packetization-mode",19}, {"1",1}}, } },
225 },
226 {
Benny Prijono135290d2011-03-17 11:33:34 +0000227 {PJMEDIA_FORMAT_H263P, {"H263-1998",9}, PJMEDIA_RTP_PT_H263P},
Nanang Izzuddin678b2f82011-03-02 08:37:31 +0000228 PJMEDIA_FORMAT_H263, 1000000, 2000000,
Nanang Izzuddind91af572011-03-31 17:29:54 +0000229 &h263_packetize, &h263_unpacketize, &h263_preopen, NULL,
230 {2, { {{"CIF",3}, {"1",1}},
231 {{"QCIF",4}, {"1",1}}, } },
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000232 },
233 {
Nanang Izzuddin235e1b42011-02-28 18:59:47 +0000234 {PJMEDIA_FORMAT_H263, {"H263",4}, PJMEDIA_RTP_PT_H263},
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000235 },
236 {
Nanang Izzuddin235e1b42011-02-28 18:59:47 +0000237 {PJMEDIA_FORMAT_H261, {"H261",4}, PJMEDIA_RTP_PT_H261},
238 },
239 {
240 {PJMEDIA_FORMAT_MJPEG, {"JPEG",4}, PJMEDIA_RTP_PT_JPEG},
241 },
242 {
Benny Prijono135290d2011-03-17 11:33:34 +0000243 {PJMEDIA_FORMAT_MPEG4, {"MP4V",4}},
Nanang Izzuddin235e1b42011-02-28 18:59:47 +0000244 },
245 {
Benny Prijono135290d2011-03-17 11:33:34 +0000246 {PJMEDIA_FORMAT_XVID, {"XVID",4}},
Nanang Izzuddin235e1b42011-02-28 18:59:47 +0000247 PJMEDIA_FORMAT_MPEG4,
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000248 },
249};
250
Nanang Izzuddind91af572011-03-31 17:29:54 +0000251
252typedef struct h264_data
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000253{
Nanang Izzuddind91af572011-03-31 17:29:54 +0000254 pjmedia_vid_codec_h264_fmtp fmtp;
255 pjmedia_h264_packetizer *pktz;
256} h264_data;
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000257
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000258
Nanang Izzuddind91af572011-03-31 17:29:54 +0000259static pj_status_t h264_preopen(ffmpeg_private *ff)
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000260{
Nanang Izzuddind91af572011-03-31 17:29:54 +0000261 h264_data *data;
262 pjmedia_h264_packetizer_cfg pktz_cfg;
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000263 pj_status_t status;
264
Nanang Izzuddind91af572011-03-31 17:29:54 +0000265 data = PJ_POOL_ZALLOC_T(ff->pool, h264_data);
266 ff->data = data;
267
268 /* Create packetizer */
269 pktz_cfg.mtu = ff->param.enc_mtu;
270 pktz_cfg.mode = PJMEDIA_H264_PACKETIZER_MODE_NON_INTERLEAVED;
271 status = pjmedia_h264_packetizer_create(ff->pool, &pktz_cfg, &data->pktz);
272 if (status != PJ_SUCCESS)
273 return status;
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000274
275 if (ff->param.dir & PJMEDIA_DIR_ENCODING) {
Nanang Izzuddind91af572011-03-31 17:29:54 +0000276 AVCodecContext *ctx = ff->enc_ctx;
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000277
Nanang Izzuddind91af572011-03-31 17:29:54 +0000278 status = pjmedia_vid_codec_parse_h264_fmtp(&ff->param.enc_fmtp,
279 &data->fmtp);
280 if (status != PJ_SUCCESS)
281 return status;
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000282
Nanang Izzuddind91af572011-03-31 17:29:54 +0000283 ctx->profile = data->fmtp.profile_idc;
284 if (data->fmtp.profile_iop) {
285#if defined(FF_PROFILE_H264_CONSTRAINED)
286 ctx->profile |= FF_PROFILE_H264_CONSTRAINED;
287#endif
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000288 }
Nanang Izzuddind91af572011-03-31 17:29:54 +0000289 ctx->level = data->fmtp.level;
290 PJ_TODO(set_h264_constrain_bits_properly_in_ffmpeg);
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000291
Nanang Izzuddind91af572011-03-31 17:29:54 +0000292 /* Libx264 rejects the "broken" ffmpeg defaults, so just change some */
293 ctx->me_range = 16;
294 ctx->max_qdiff = 4;
295 ctx->qmin = 10;
296 ctx->qmax = 51;
297 ctx->qcompress = 0.6f;
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000298 }
299
300 return PJ_SUCCESS;
301}
302
Nanang Izzuddind91af572011-03-31 17:29:54 +0000303static pj_status_t h264_postopen(ffmpeg_private *ff)
304{
305 h264_data *data = (h264_data*)ff->data;
306 PJ_UNUSED_ARG(data);
307
308 // Where to apply the "sprop-parameter-sets" fmtp from remote SDP?
309 // Through decoder decode() or decoder context extradata?
310 PJ_TODO(apply_h264_fmtp_sprop_parameter_sets_from_remote_sdp);
311
312 return PJ_SUCCESS;
313}
314
315
316static FUNC_PACKETIZE(h264_packetize)
317{
318 h264_data *data = (h264_data*)ff->data;
319 return pjmedia_h264_packetize(data->pktz, bits, bits_len, bits_pos,
320 payload, payload_len);
321}
322
323static FUNC_UNPACKETIZE(h264_unpacketize)
324{
325 h264_data *data = (h264_data*)ff->data;
326 return pjmedia_h264_unpacketize(data->pktz, payload, payload_len,
327 bits, bits_len, bits_pos);
328}
329
330
331typedef struct h263_data
332{
333 pjmedia_h263_packetizer *pktz;
334} h263_data;
335
336/* H263 pre-open */
337static pj_status_t h263_preopen(ffmpeg_private *ff)
338{
339 h263_data *data;
340 pjmedia_h263_packetizer_cfg pktz_cfg;
341 pj_status_t status;
342
343 data = PJ_POOL_ZALLOC_T(ff->pool, h263_data);
344 ff->data = data;
345
346 /* Create packetizer */
347 pktz_cfg.mtu = ff->param.enc_mtu;
348 pktz_cfg.mode = PJMEDIA_H263_PACKETIZER_MODE_RFC4629;
349 status = pjmedia_h263_packetizer_create(ff->pool, &pktz_cfg, &data->pktz);
350 if (status != PJ_SUCCESS)
351 return status;
352
353 /* Apply fmtp settings to codec param */
354 status = pjmedia_vid_codec_h263_apply_fmtp(&ff->param);
355
356 return status;
357}
358
359static FUNC_PACKETIZE(h263_packetize)
360{
361 h263_data *data = (h263_data*)ff->data;
362 return pjmedia_h263_packetize(data->pktz, bits, bits_len, bits_pos,
363 payload, payload_len);
364}
365
366static FUNC_UNPACKETIZE(h263_unpacketize)
367{
368 h263_data *data = (h263_data*)ff->data;
369 return pjmedia_h263_unpacketize(data->pktz, payload, payload_len,
370 bits, bits_len, bits_pos);
371}
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000372
373
Nanang Izzuddin235e1b42011-02-28 18:59:47 +0000374static const ffmpeg_codec_desc* find_codec_desc_by_info(
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000375 const pjmedia_vid_codec_info *info)
376{
377 int i;
378
379 for (i=0; i<PJ_ARRAY_SIZE(codec_desc); ++i) {
380 ffmpeg_codec_desc *desc = &codec_desc[i];
381
382 if (desc->enabled &&
383 (desc->info.fmt_id == info->fmt_id) &&
384 ((desc->info.dir & info->dir) == info->dir) &&
385 pj_stricmp(&desc->info.encoding_name, &info->encoding_name)==0)
386 {
387 return desc;
388 }
389 }
390
391 return NULL;
392}
393
394
Nanang Izzuddin235e1b42011-02-28 18:59:47 +0000395static int find_codec_idx_by_fmt_id(pjmedia_format_id fmt_id)
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000396{
397 int i;
398 for (i=0; i<PJ_ARRAY_SIZE(codec_desc); ++i) {
399 if (codec_desc[i].info.fmt_id == fmt_id)
400 return i;
401 }
402
403 return -1;
404}
Benny Prijonoc45d9512010-12-10 11:04:30 +0000405
406
407/*
408 * Initialize and register FFMPEG codec factory to pjmedia endpoint.
409 */
410PJ_DEF(pj_status_t) pjmedia_codec_ffmpeg_init(pjmedia_vid_codec_mgr *mgr,
411 pj_pool_factory *pf)
412{
413 pj_pool_t *pool;
414 AVCodec *c;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000415 pj_status_t status;
Nanang Izzuddin235e1b42011-02-28 18:59:47 +0000416 unsigned i;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000417
418 if (ffmpeg_factory.pool != NULL) {
419 /* Already initialized. */
420 return PJ_SUCCESS;
421 }
422
423 if (!mgr) mgr = pjmedia_vid_codec_mgr_instance();
424 PJ_ASSERT_RETURN(mgr, PJ_EINVAL);
425
426 /* Create FFMPEG codec factory. */
427 ffmpeg_factory.base.op = &ffmpeg_factory_op;
428 ffmpeg_factory.base.factory_data = NULL;
429 ffmpeg_factory.mgr = mgr;
430 ffmpeg_factory.pf = pf;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000431
432 pool = pj_pool_create(pf, "ffmpeg codec factory", 256, 256, NULL);
433 if (!pool)
434 return PJ_ENOMEM;
435
436 /* Create mutex. */
437 status = pj_mutex_create_simple(pool, "ffmpeg codec factory",
438 &ffmpeg_factory.mutex);
439 if (status != PJ_SUCCESS)
440 goto on_error;
441
442 avcodec_init();
443 avcodec_register_all();
Benny Prijono135290d2011-03-17 11:33:34 +0000444 av_log_set_level(AV_LOG_ERROR);
Benny Prijonoc45d9512010-12-10 11:04:30 +0000445
446 /* Enum FFMPEG codecs */
447 for (c=av_codec_next(NULL); c; c=av_codec_next(c))
448 {
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000449 ffmpeg_codec_desc *desc;
450 pjmedia_format_id fmt_id;
451 int codec_info_idx;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000452
453 if (c->type != CODEC_TYPE_VIDEO)
454 continue;
455
456 /* Video encoder and decoder are usually implemented in separate
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000457 * AVCodec instances. While the codec attributes (e.g: raw formats,
458 * supported fps) are in the encoder.
Benny Prijonoc45d9512010-12-10 11:04:30 +0000459 */
460
Nanang Izzuddin235e1b42011-02-28 18:59:47 +0000461 //PJ_LOG(3, (THIS_FILE, "%s", c->name));
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000462 status = CodecID_to_pjmedia_format_id(c->id, &fmt_id);
463 /* Skip if format ID is unknown */
464 if (status != PJ_SUCCESS)
465 continue;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000466
Nanang Izzuddin235e1b42011-02-28 18:59:47 +0000467 codec_info_idx = find_codec_idx_by_fmt_id(fmt_id);
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000468 /* Skip if codec is unwanted by this wrapper (not listed in
469 * the codec info array)
470 */
471 if (codec_info_idx < 0)
472 continue;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000473
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000474 desc = &codec_desc[codec_info_idx];
Benny Prijonoc45d9512010-12-10 11:04:30 +0000475
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000476 /* Skip duplicated codec implementation */
477 if ((c->encode && (desc->info.dir & PJMEDIA_DIR_ENCODING)) ||
478 (c->decode && (desc->info.dir & PJMEDIA_DIR_DECODING)))
479 {
480 continue;
481 }
Benny Prijonoc45d9512010-12-10 11:04:30 +0000482
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000483 /* Get raw/decoded format ids in the encoder */
484 if (c->pix_fmts && c->encode) {
485 pjmedia_format_id raw_fmt[PJMEDIA_VID_CODEC_MAX_DEC_FMT_CNT];
486 unsigned raw_fmt_cnt = 0;
487 unsigned raw_fmt_cnt_should_be = 0;
488 const enum PixelFormat *p = c->pix_fmts;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000489
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000490 for(;(p && *p != -1) &&
491 (raw_fmt_cnt < PJMEDIA_VID_CODEC_MAX_DEC_FMT_CNT);
492 ++p)
493 {
494 pjmedia_format_id fmt_id;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000495
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000496 raw_fmt_cnt_should_be++;
497 status = PixelFormat_to_pjmedia_format_id(*p, &fmt_id);
498 if (status != PJ_SUCCESS) {
499 PJ_LOG(6, (THIS_FILE, "Unrecognized ffmpeg pixel "
500 "format %d", *p));
501 continue;
502 }
503 raw_fmt[raw_fmt_cnt++] = fmt_id;
504 }
Benny Prijonoc45d9512010-12-10 11:04:30 +0000505
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000506 if (raw_fmt_cnt == 0) {
507 PJ_LOG(5, (THIS_FILE, "No recognized raw format "
508 "for codec [%s/%s], codec ignored",
509 c->name, c->long_name));
510 /* Skip this encoder */
511 continue;
512 }
Benny Prijonoc45d9512010-12-10 11:04:30 +0000513
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000514 if (raw_fmt_cnt < raw_fmt_cnt_should_be) {
515 PJ_LOG(6, (THIS_FILE, "Codec [%s/%s] have %d raw formats, "
516 "recognized only %d raw formats",
517 c->name, c->long_name,
518 raw_fmt_cnt_should_be, raw_fmt_cnt));
519 }
Benny Prijonoc45d9512010-12-10 11:04:30 +0000520
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000521 desc->info.dec_fmt_id_cnt = raw_fmt_cnt;
522 pj_memcpy(desc->info.dec_fmt_id, raw_fmt,
523 sizeof(raw_fmt[0])*raw_fmt_cnt);
524 }
525
526 /* Get supported framerates */
527 if (c->supported_framerates) {
528 const AVRational *fr = c->supported_framerates;
529 while ((fr->num != 0 || fr->den != 0) &&
530 desc->info.fps_cnt < PJMEDIA_VID_CODEC_MAX_FPS_CNT)
531 {
532 desc->info.fps[desc->info.fps_cnt].num = fr->num;
533 desc->info.fps[desc->info.fps_cnt].denum = fr->den;
534 ++desc->info.fps_cnt;
535 ++fr;
536 }
537 }
538
539 /* Get ffmpeg encoder instance */
540 if (c->encode && !desc->enc) {
541 desc->info.dir |= PJMEDIA_DIR_ENCODING;
542 desc->enc = c;
543 }
544
545 /* Get ffmpeg decoder instance */
546 if (c->decode && !desc->dec) {
547 desc->info.dir |= PJMEDIA_DIR_DECODING;
548 desc->dec = c;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000549 }
550
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000551 /* Enable this codec when any ffmpeg codec instance are recognized
552 * and the supported raw formats info has been collected.
553 */
554 if ((desc->dec || desc->enc) && desc->info.dec_fmt_id_cnt)
555 {
556 desc->enabled = PJ_TRUE;
557 }
Benny Prijonoc45d9512010-12-10 11:04:30 +0000558
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000559 /* Normalize default value of clock rate */
560 if (desc->info.clock_rate == 0)
561 desc->info.clock_rate = 90000;
Benny Prijono135290d2011-03-17 11:33:34 +0000562
563 /* Set RTP packetization support flag in the codec info */
564 desc->info.has_rtp_pack = (desc->packetize != NULL) &&
565 (desc->unpacketize != NULL);
Benny Prijonoc45d9512010-12-10 11:04:30 +0000566 }
567
Nanang Izzuddin235e1b42011-02-28 18:59:47 +0000568 /* Init unassigned encoder/decoder description from base codec */
569 for (i = 0; i < PJ_ARRAY_SIZE(codec_desc); ++i) {
570 ffmpeg_codec_desc *desc = &codec_desc[i];
571
572 if (desc->base_fmt_id && (!desc->dec || !desc->enc)) {
573 ffmpeg_codec_desc *base_desc = NULL;
574 int base_desc_idx;
575 pjmedia_dir copied_dir = PJMEDIA_DIR_NONE;
576
577 base_desc_idx = find_codec_idx_by_fmt_id(desc->base_fmt_id);
578 if (base_desc_idx != -1)
579 base_desc = &codec_desc[base_desc_idx];
580 if (!base_desc || !base_desc->enabled)
581 continue;
582
583 /* Copy description from base codec */
584 if (!desc->info.dec_fmt_id_cnt) {
585 desc->info.dec_fmt_id_cnt = base_desc->info.dec_fmt_id_cnt;
586 pj_memcpy(desc->info.dec_fmt_id, base_desc->info.dec_fmt_id,
587 sizeof(pjmedia_format_id)*desc->info.dec_fmt_id_cnt);
588 }
589 if (!desc->info.fps_cnt) {
590 desc->info.fps_cnt = base_desc->info.fps_cnt;
591 pj_memcpy(desc->info.fps, base_desc->info.fps,
592 sizeof(desc->info.fps[0])*desc->info.fps_cnt);
593 }
594 if (!desc->info.clock_rate) {
595 desc->info.clock_rate = base_desc->info.clock_rate;
596 }
597 if (!desc->dec && base_desc->dec) {
598 copied_dir |= PJMEDIA_DIR_DECODING;
599 desc->dec = base_desc->dec;
600 }
601 if (!desc->enc && base_desc->enc) {
602 copied_dir |= PJMEDIA_DIR_ENCODING;
603 desc->enc = base_desc->enc;
604 }
605
606 desc->info.dir |= copied_dir;
607 desc->enabled = (desc->info.dir != PJMEDIA_DIR_NONE);
608
609 if (copied_dir != PJMEDIA_DIR_NONE) {
610 const char *dir_name[] = {NULL, "encoder", "decoder", "codec"};
611 PJ_LOG(5, (THIS_FILE, "The %.*s %s is using base codec (%.*s)",
612 desc->info.encoding_name.slen,
613 desc->info.encoding_name.ptr,
614 dir_name[copied_dir],
615 base_desc->info.encoding_name.slen,
616 base_desc->info.encoding_name.ptr));
617 }
618 }
619 }
620
Benny Prijonoc45d9512010-12-10 11:04:30 +0000621 /* Register codec factory to codec manager. */
622 status = pjmedia_vid_codec_mgr_register_factory(mgr,
623 &ffmpeg_factory.base);
624 if (status != PJ_SUCCESS)
625 goto on_error;
626
627 ffmpeg_factory.pool = pool;
628
629 /* Done. */
630 return PJ_SUCCESS;
631
632on_error:
633 pj_pool_release(pool);
634 return status;
635}
636
637/*
638 * Unregister FFMPEG codecs factory from pjmedia endpoint.
639 */
640PJ_DEF(pj_status_t) pjmedia_codec_ffmpeg_deinit(void)
641{
642 pj_status_t status = PJ_SUCCESS;
643
644 if (ffmpeg_factory.pool == NULL) {
645 /* Already deinitialized */
646 return PJ_SUCCESS;
647 }
648
649 pj_mutex_lock(ffmpeg_factory.mutex);
650
651 /* Unregister FFMPEG codecs factory. */
652 status = pjmedia_vid_codec_mgr_unregister_factory(ffmpeg_factory.mgr,
653 &ffmpeg_factory.base);
654
655 /* Destroy mutex. */
656 pj_mutex_destroy(ffmpeg_factory.mutex);
657
658 /* Destroy pool. */
659 pj_pool_release(ffmpeg_factory.pool);
660 ffmpeg_factory.pool = NULL;
661
662 return status;
663}
664
665
Benny Prijonoc45d9512010-12-10 11:04:30 +0000666/*
667 * Check if factory can allocate the specified codec.
668 */
669static pj_status_t ffmpeg_test_alloc( pjmedia_vid_codec_factory *factory,
670 const pjmedia_vid_codec_info *info )
671{
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000672 const ffmpeg_codec_desc *desc;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000673
674 PJ_ASSERT_RETURN(factory==&ffmpeg_factory.base, PJ_EINVAL);
675 PJ_ASSERT_RETURN(info, PJ_EINVAL);
676
Nanang Izzuddin235e1b42011-02-28 18:59:47 +0000677 desc = find_codec_desc_by_info(info);
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000678 if (!desc) {
Benny Prijonoc45d9512010-12-10 11:04:30 +0000679 return PJMEDIA_CODEC_EUNSUP;
680 }
681
682 return PJ_SUCCESS;
683}
684
685/*
686 * Generate default attribute.
687 */
688static pj_status_t ffmpeg_default_attr( pjmedia_vid_codec_factory *factory,
689 const pjmedia_vid_codec_info *info,
690 pjmedia_vid_codec_param *attr )
691{
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000692 const ffmpeg_codec_desc *desc;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000693
694 PJ_ASSERT_RETURN(factory==&ffmpeg_factory.base, PJ_EINVAL);
695 PJ_ASSERT_RETURN(info && attr, PJ_EINVAL);
696
Nanang Izzuddin235e1b42011-02-28 18:59:47 +0000697 desc = find_codec_desc_by_info(info);
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000698 if (!desc) {
Benny Prijonoc45d9512010-12-10 11:04:30 +0000699 return PJMEDIA_CODEC_EUNSUP;
700 }
701
702 pj_bzero(attr, sizeof(pjmedia_vid_codec_param));
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000703
704 /* Direction */
705 attr->dir = desc->info.dir;
706
707 /* Encoded format */
708 pjmedia_format_init_video(&attr->enc_fmt, desc->info.fmt_id,
709 352, 288, 30000, 1001);
710
711 /* Decoded format */
712 pjmedia_format_init_video(&attr->dec_fmt, desc->info.dec_fmt_id[0],
713 352, 288, 30000, 1001);
714
715 /* Decoding fmtp */
716 attr->dec_fmtp = desc->dec_fmtp;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000717
Nanang Izzuddin678b2f82011-03-02 08:37:31 +0000718 /* Bitrate */
719 attr->enc_fmt.det.vid.avg_bps = desc->avg_bps;
720 attr->enc_fmt.det.vid.max_bps = desc->max_bps;
721
Nanang Izzuddind91af572011-03-31 17:29:54 +0000722 /* MTU */
723 attr->enc_mtu = PJMEDIA_MAX_MTU;
724
Benny Prijonoc45d9512010-12-10 11:04:30 +0000725 return PJ_SUCCESS;
726}
727
728/*
729 * Enum codecs supported by this factory.
730 */
731static pj_status_t ffmpeg_enum_codecs( pjmedia_vid_codec_factory *factory,
732 unsigned *count,
733 pjmedia_vid_codec_info codecs[])
734{
Nanang Izzuddin235e1b42011-02-28 18:59:47 +0000735 unsigned i, max_cnt;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000736
737 PJ_ASSERT_RETURN(codecs && *count > 0, PJ_EINVAL);
738 PJ_ASSERT_RETURN(factory == &ffmpeg_factory.base, PJ_EINVAL);
739
Nanang Izzuddin235e1b42011-02-28 18:59:47 +0000740 max_cnt = PJ_MIN(*count, PJ_ARRAY_SIZE(codec_desc));
741 *count = 0;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000742
Nanang Izzuddin235e1b42011-02-28 18:59:47 +0000743 for (i=0; i<max_cnt; ++i) {
744 if (codec_desc[i].enabled) {
745 pj_memcpy(&codecs[*count], &codec_desc[i].info,
746 sizeof(pjmedia_vid_codec_info));
747 (*count)++;
748 }
Benny Prijonoc45d9512010-12-10 11:04:30 +0000749 }
Benny Prijonoc45d9512010-12-10 11:04:30 +0000750
751 return PJ_SUCCESS;
752}
753
754/*
755 * Allocate a new codec instance.
756 */
757static pj_status_t ffmpeg_alloc_codec( pjmedia_vid_codec_factory *factory,
758 const pjmedia_vid_codec_info *info,
759 pjmedia_vid_codec **p_codec)
760{
761 ffmpeg_private *ff;
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000762 const ffmpeg_codec_desc *desc;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000763 pjmedia_vid_codec *codec;
764 pj_pool_t *pool = NULL;
765 pj_status_t status = PJ_SUCCESS;
766
767 PJ_ASSERT_RETURN(factory && info && p_codec, PJ_EINVAL);
768 PJ_ASSERT_RETURN(factory == &ffmpeg_factory.base, PJ_EINVAL);
769
Nanang Izzuddin235e1b42011-02-28 18:59:47 +0000770 desc = find_codec_desc_by_info(info);
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000771 if (!desc) {
Benny Prijonoc45d9512010-12-10 11:04:30 +0000772 return PJMEDIA_CODEC_EUNSUP;
773 }
774
775 /* Create pool for codec instance */
776 pool = pj_pool_create(ffmpeg_factory.pf, "ffmpeg codec", 512, 512, NULL);
777 codec = PJ_POOL_ZALLOC_T(pool, pjmedia_vid_codec);
778 if (!codec) {
779 status = PJ_ENOMEM;
780 goto on_error;
781 }
782 codec->op = &ffmpeg_op;
783 codec->factory = factory;
784 ff = PJ_POOL_ZALLOC_T(pool, ffmpeg_private);
785 if (!ff) {
786 status = PJ_ENOMEM;
787 goto on_error;
788 }
789 codec->codec_data = ff;
790 ff->pool = pool;
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000791 ff->enc = desc->enc;
792 ff->dec = desc->dec;
793 ff->desc = desc;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000794
795 *p_codec = codec;
796 return PJ_SUCCESS;
797
798on_error:
799 if (pool)
800 pj_pool_release(pool);
801 return status;
802}
803
804/*
805 * Free codec.
806 */
807static pj_status_t ffmpeg_dealloc_codec( pjmedia_vid_codec_factory *factory,
808 pjmedia_vid_codec *codec )
809{
810 ffmpeg_private *ff;
811 pj_pool_t *pool;
812
813 PJ_ASSERT_RETURN(factory && codec, PJ_EINVAL);
814 PJ_ASSERT_RETURN(factory == &ffmpeg_factory.base, PJ_EINVAL);
815
816 /* Close codec, if it's not closed. */
817 ff = (ffmpeg_private*) codec->codec_data;
818 pool = ff->pool;
819 codec->codec_data = NULL;
820 pj_pool_release(pool);
821
822 return PJ_SUCCESS;
823}
824
825/*
826 * Init codec.
827 */
828static pj_status_t ffmpeg_codec_init( pjmedia_vid_codec *codec,
829 pj_pool_t *pool )
830{
831 PJ_UNUSED_ARG(codec);
832 PJ_UNUSED_ARG(pool);
833 return PJ_SUCCESS;
834}
835
836static void print_ffmpeg_err(int err)
837{
838#if LIBAVCODEC_VERSION_MAJOR >= 52 && LIBAVCODEC_VERSION_MINOR >= 72
839 char errbuf[512];
840 if (av_strerror(err, errbuf, sizeof(errbuf)) >= 0)
841 PJ_LOG(1, (THIS_FILE, "ffmpeg err %d: %s", err, errbuf));
842#else
843 PJ_LOG(1, (THIS_FILE, "ffmpeg err %d", err));
844#endif
845
846}
847
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000848static enum PixelFormat dec_get_format(struct AVCodecContext *s,
Nanang Izzuddind91af572011-03-31 17:29:54 +0000849 const enum PixelFormat * fmt)
Benny Prijonoc45d9512010-12-10 11:04:30 +0000850{
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000851 ffmpeg_private *ff = (ffmpeg_private*)s->opaque;
852 enum PixelFormat def_fmt = *fmt;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000853
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000854 while (*fmt != -1) {
855 if (*fmt == ff->expected_dec_fmt)
856 return *fmt;
857 ++fmt;
858 }
Benny Prijonoc45d9512010-12-10 11:04:30 +0000859
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000860 pj_assert(!"Inconsistency in supported formats");
861 return def_fmt;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000862}
863
Benny Prijonoc45d9512010-12-10 11:04:30 +0000864
865static pj_status_t open_ffmpeg_codec(ffmpeg_private *ff,
866 pj_mutex_t *ff_mutex)
867{
868 enum PixelFormat pix_fmt;
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000869 pjmedia_video_format_detail *vfd;
Nanang Izzuddind91af572011-03-31 17:29:54 +0000870 pj_bool_t enc_opened = PJ_FALSE, dec_opened = PJ_FALSE;
871 pj_status_t status;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000872
Nanang Izzuddind91af572011-03-31 17:29:54 +0000873 /* Get decoded pixel format */
Benny Prijonoc45d9512010-12-10 11:04:30 +0000874 status = pjmedia_format_id_to_PixelFormat(ff->param.dec_fmt.id,
875 &pix_fmt);
876 if (status != PJ_SUCCESS)
877 return status;
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000878 ff->expected_dec_fmt = pix_fmt;
879
Nanang Izzuddind91af572011-03-31 17:29:54 +0000880 /* Get video format detail for shortcut access to encoded format */
881 vfd = pjmedia_format_get_video_format_detail(&ff->param.enc_fmt,
882 PJ_TRUE);
883
884 /* Allocate ffmpeg codec context */
885 if (ff->param.dir & PJMEDIA_DIR_ENCODING) {
886 ff->enc_ctx = avcodec_alloc_context();
887 if (ff->enc_ctx == NULL)
888 goto on_error;
889 }
890 if (ff->param.dir & PJMEDIA_DIR_DECODING) {
891 ff->dec_ctx = avcodec_alloc_context();
892 if (ff->dec_ctx == NULL)
893 goto on_error;
894 }
895
896 /* Let the codec apply specific settings before the codec opened */
897 if (ff->desc->preopen) {
898 status = (*ff->desc->preopen)(ff);
899 if (status != PJ_SUCCESS)
900 goto on_error;
901 }
902
903 if (ff->param.dir & PJMEDIA_DIR_ENCODING) {
904 AVCodecContext *ctx = ff->enc_ctx;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000905 int err;
906
Nanang Izzuddind91af572011-03-31 17:29:54 +0000907 /* Init common settings */
Benny Prijonoc45d9512010-12-10 11:04:30 +0000908 ctx->pix_fmt = pix_fmt;
Nanang Izzuddind91af572011-03-31 17:29:54 +0000909 ctx->width = vfd->size.w;
910 ctx->height = vfd->size.h;
911 ctx->time_base.num = vfd->fps.denum;
912 ctx->time_base.den = vfd->fps.num;
913 if (vfd->avg_bps) {
914 ctx->bit_rate = vfd->avg_bps;
915 if (vfd->max_bps > vfd->avg_bps)
916 ctx->bit_rate_tolerance = vfd->max_bps - vfd->avg_bps;
917 }
918 ctx->strict_std_compliance = FF_COMPLIANCE_STRICT;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000919 ctx->workaround_bugs = FF_BUG_AUTODETECT;
920 ctx->opaque = ff;
921
Nanang Izzuddin2636c142011-04-01 07:12:59 +0000922 /* Set no delay, note that this may cause some codec functionals
923 * not working (e.g: rate control).
924 */
925 ctx->rc_lookahead = 0;
926
Nanang Izzuddind91af572011-03-31 17:29:54 +0000927 /* Open ffmpeg codec */
Benny Prijonoc45d9512010-12-10 11:04:30 +0000928 pj_mutex_lock(ff_mutex);
Nanang Izzuddind91af572011-03-31 17:29:54 +0000929 err = avcodec_open(ctx, ff->enc);
Benny Prijonoc45d9512010-12-10 11:04:30 +0000930 pj_mutex_unlock(ff_mutex);
931 if (err < 0) {
932 print_ffmpeg_err(err);
Nanang Izzuddind91af572011-03-31 17:29:54 +0000933 status = PJMEDIA_CODEC_EFAILED;
934 goto on_error;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000935 }
Nanang Izzuddind91af572011-03-31 17:29:54 +0000936 enc_opened = PJ_TRUE;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000937 }
Nanang Izzuddind91af572011-03-31 17:29:54 +0000938
939 if (ff->param.dir & PJMEDIA_DIR_DECODING) {
940 AVCodecContext *ctx = ff->dec_ctx;
941 int err;
942
943 /* Init common settings */
944 /* Width/height may be overriden by ffmpeg after first decoding. */
945 ctx->width = ctx->coded_width = ff->param.dec_fmt.det.vid.size.w;
946 ctx->height = ctx->coded_height = ff->param.dec_fmt.det.vid.size.h;
947 ctx->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
948 ctx->workaround_bugs = FF_BUG_AUTODETECT;
949 ctx->opaque = ff;
950 ctx->get_format = &dec_get_format;
951
952 /* Open ffmpeg codec */
953 pj_mutex_lock(ff_mutex);
954 err = avcodec_open(ctx, ff->dec);
955 pj_mutex_unlock(ff_mutex);
956 if (err < 0) {
957 print_ffmpeg_err(err);
958 status = PJMEDIA_CODEC_EFAILED;
959 goto on_error;
960 }
961 dec_opened = PJ_TRUE;
962 }
963
964 /* Let the codec apply specific settings after the codec opened */
965 if (ff->desc->postopen) {
966 status = (*ff->desc->postopen)(ff);
967 if (status != PJ_SUCCESS)
968 goto on_error;
969 }
970
Benny Prijonoc45d9512010-12-10 11:04:30 +0000971 return PJ_SUCCESS;
Nanang Izzuddind91af572011-03-31 17:29:54 +0000972
973on_error:
974 if (ff->enc_ctx) {
975 if (enc_opened)
976 avcodec_close(ff->enc_ctx);
977 av_free(ff->enc_ctx);
978 ff->enc_ctx = NULL;
979 }
980 if (ff->dec_ctx) {
981 if (dec_opened)
982 avcodec_close(ff->dec_ctx);
983 av_free(ff->dec_ctx);
984 ff->dec_ctx = NULL;
985 }
986 return status;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000987}
988
989/*
990 * Open codec.
991 */
992static pj_status_t ffmpeg_codec_open( pjmedia_vid_codec *codec,
993 pjmedia_vid_codec_param *attr )
994{
995 ffmpeg_private *ff;
996 pj_status_t status;
997 pj_mutex_t *ff_mutex;
998
999 PJ_ASSERT_RETURN(codec && attr, PJ_EINVAL);
1000 ff = (ffmpeg_private*)codec->codec_data;
1001
Benny Prijonoc45d9512010-12-10 11:04:30 +00001002 pj_memcpy(&ff->param, attr, sizeof(*attr));
1003
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001004 /* Open the codec */
Benny Prijonoc45d9512010-12-10 11:04:30 +00001005 ff_mutex = ((struct ffmpeg_factory*)codec->factory)->mutex;
1006 status = open_ffmpeg_codec(ff, ff_mutex);
1007 if (status != PJ_SUCCESS)
1008 goto on_error;
1009
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001010 /* Init format info and apply-param of decoder */
1011 ff->dec_vfi = pjmedia_get_video_format_info(NULL, ff->param.dec_fmt.id);
1012 if (!ff->dec_vfi) {
1013 status = PJ_EINVAL;
1014 goto on_error;
1015 }
1016 pj_bzero(&ff->dec_vafp, sizeof(ff->dec_vafp));
1017 ff->dec_vafp.size = ff->param.dec_fmt.det.vid.size;
1018 ff->dec_vafp.buffer = NULL;
1019 status = (*ff->dec_vfi->apply_fmt)(ff->dec_vfi, &ff->dec_vafp);
1020 if (status != PJ_SUCCESS) {
1021 goto on_error;
1022 }
1023
1024 /* Init format info and apply-param of encoder */
1025 ff->enc_vfi = pjmedia_get_video_format_info(NULL, ff->param.dec_fmt.id);
1026 if (!ff->enc_vfi) {
1027 status = PJ_EINVAL;
1028 goto on_error;
1029 }
1030 pj_bzero(&ff->enc_vafp, sizeof(ff->enc_vafp));
1031 ff->enc_vafp.size = ff->param.enc_fmt.det.vid.size;
1032 ff->enc_vafp.buffer = NULL;
1033 status = (*ff->enc_vfi->apply_fmt)(ff->enc_vfi, &ff->enc_vafp);
1034 if (status != PJ_SUCCESS) {
1035 goto on_error;
1036 }
1037
1038 /* Update codec attributes, e.g: encoding format may be changed by
1039 * SDP fmtp negotiation.
1040 */
1041 pj_memcpy(attr, &ff->param, sizeof(*attr));
1042
Benny Prijonoc45d9512010-12-10 11:04:30 +00001043 return PJ_SUCCESS;
1044
1045on_error:
1046 ffmpeg_codec_close(codec);
1047 return status;
1048}
1049
1050/*
1051 * Close codec.
1052 */
1053static pj_status_t ffmpeg_codec_close( pjmedia_vid_codec *codec )
1054{
1055 ffmpeg_private *ff;
1056 pj_mutex_t *ff_mutex;
1057
1058 PJ_ASSERT_RETURN(codec, PJ_EINVAL);
1059 ff = (ffmpeg_private*)codec->codec_data;
1060 ff_mutex = ((struct ffmpeg_factory*)codec->factory)->mutex;
1061
1062 pj_mutex_lock(ff_mutex);
1063 if (ff->enc_ctx) {
1064 avcodec_close(ff->enc_ctx);
1065 av_free(ff->enc_ctx);
1066 }
1067 if (ff->dec_ctx && ff->dec_ctx!=ff->enc_ctx) {
1068 avcodec_close(ff->dec_ctx);
1069 av_free(ff->dec_ctx);
1070 }
Benny Prijonoc45d9512010-12-10 11:04:30 +00001071 ff->enc_ctx = NULL;
1072 ff->dec_ctx = NULL;
Benny Prijonoc45d9512010-12-10 11:04:30 +00001073 pj_mutex_unlock(ff_mutex);
1074
1075 return PJ_SUCCESS;
1076}
1077
1078
1079/*
1080 * Modify codec settings.
1081 */
1082static pj_status_t ffmpeg_codec_modify( pjmedia_vid_codec *codec,
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001083 const pjmedia_vid_codec_param *attr)
Benny Prijonoc45d9512010-12-10 11:04:30 +00001084{
1085 ffmpeg_private *ff = (ffmpeg_private*)codec->codec_data;
1086
1087 PJ_UNUSED_ARG(attr);
1088 PJ_UNUSED_ARG(ff);
1089
1090 return PJ_ENOTSUP;
1091}
1092
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001093static pj_status_t ffmpeg_codec_get_param(pjmedia_vid_codec *codec,
1094 pjmedia_vid_codec_param *param)
1095{
1096 ffmpeg_private *ff;
1097
1098 PJ_ASSERT_RETURN(codec && param, PJ_EINVAL);
1099
1100 ff = (ffmpeg_private*)codec->codec_data;
1101 pj_memcpy(param, &ff->param, sizeof(*param));
1102
1103 return PJ_SUCCESS;
1104}
1105
1106
Benny Prijonoc45d9512010-12-10 11:04:30 +00001107static pj_status_t ffmpeg_packetize ( pjmedia_vid_codec *codec,
Nanang Izzuddind91af572011-03-31 17:29:54 +00001108 pj_uint8_t *bits,
1109 pj_size_t bits_len,
1110 unsigned *bits_pos,
Benny Prijonoc45d9512010-12-10 11:04:30 +00001111 const pj_uint8_t **payload,
1112 pj_size_t *payload_len)
1113{
1114 ffmpeg_private *ff = (ffmpeg_private*)codec->codec_data;
1115
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001116 if (ff->desc->packetize) {
Nanang Izzuddind91af572011-03-31 17:29:54 +00001117 return (*ff->desc->packetize)(ff, bits, bits_len, bits_pos,
1118 payload, payload_len);
Benny Prijonoc45d9512010-12-10 11:04:30 +00001119 }
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001120
1121 return PJ_ENOTSUP;
Benny Prijonoc45d9512010-12-10 11:04:30 +00001122}
1123
1124static pj_status_t ffmpeg_unpacketize(pjmedia_vid_codec *codec,
1125 const pj_uint8_t *payload,
1126 pj_size_t payload_len,
Nanang Izzuddind91af572011-03-31 17:29:54 +00001127 pj_uint8_t *bits,
1128 pj_size_t bits_len,
1129 unsigned *bits_pos)
Benny Prijonoc45d9512010-12-10 11:04:30 +00001130{
1131 ffmpeg_private *ff = (ffmpeg_private*)codec->codec_data;
1132
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001133 if (ff->desc->unpacketize) {
Nanang Izzuddind91af572011-03-31 17:29:54 +00001134 return (*ff->desc->unpacketize)(ff, payload, payload_len,
1135 bits, bits_len, bits_pos);
Benny Prijonoc45d9512010-12-10 11:04:30 +00001136 }
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001137
1138 return PJ_ENOTSUP;
Benny Prijonoc45d9512010-12-10 11:04:30 +00001139}
1140
Benny Prijonoc45d9512010-12-10 11:04:30 +00001141
1142/*
1143 * Encode frames.
1144 */
1145static pj_status_t ffmpeg_codec_encode( pjmedia_vid_codec *codec,
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001146 const pjmedia_frame *input,
Benny Prijonoc45d9512010-12-10 11:04:30 +00001147 unsigned output_buf_len,
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001148 pjmedia_frame *output)
Benny Prijonoc45d9512010-12-10 11:04:30 +00001149{
1150 ffmpeg_private *ff = (ffmpeg_private*)codec->codec_data;
1151 pj_uint8_t *p = (pj_uint8_t*)input->buf;
1152 AVFrame avframe;
1153 pj_uint8_t *out_buf = (pj_uint8_t*)output->buf;
1154 int out_buf_len = output_buf_len;
1155 int err;
Nanang Izzuddind91af572011-03-31 17:29:54 +00001156 AVRational src_timebase;
Nanang Izzuddinada41262011-03-22 09:43:24 +00001157 /* For some reasons (e.g: SSE/MMX usage), the avcodec_encode_video() must
1158 * have stack aligned to 16 bytes. Let's try to be safe by preparing the
1159 * 16-bytes aligned stack here, in case it's not managed by the ffmpeg.
1160 */
1161 PJ_ALIGN_DATA(pj_uint32_t i[4], 16);
Benny Prijonoc45d9512010-12-10 11:04:30 +00001162
Nanang Izzuddind91af572011-03-31 17:29:54 +00001163 if ((long)i & 0xF) {
1164 PJ_LOG(2,(THIS_FILE, "Stack alignment fails"));
1165 }
1166
Benny Prijonoc45d9512010-12-10 11:04:30 +00001167 /* Check if encoder has been opened */
1168 PJ_ASSERT_RETURN(ff->enc_ctx, PJ_EINVALIDOP);
1169
Benny Prijonoc45d9512010-12-10 11:04:30 +00001170 avcodec_get_frame_defaults(&avframe);
Nanang Izzuddind91af572011-03-31 17:29:54 +00001171 src_timebase.num = 1;
1172 src_timebase.den = ff->desc->info.clock_rate;
1173 avframe.pts = av_rescale_q(input->timestamp.u64, src_timebase,
1174 ff->enc_ctx->time_base);
Benny Prijonoc45d9512010-12-10 11:04:30 +00001175
Nanang Izzuddinada41262011-03-22 09:43:24 +00001176 for (i[0] = 0; i[0] < ff->enc_vfi->plane_cnt; ++i[0]) {
1177 avframe.data[i[0]] = p;
1178 avframe.linesize[i[0]] = ff->enc_vafp.strides[i[0]];
1179 p += ff->enc_vafp.plane_bytes[i[0]];
Benny Prijonoc45d9512010-12-10 11:04:30 +00001180 }
1181
Nanang Izzuddinada41262011-03-22 09:43:24 +00001182 err = avcodec_encode_video(ff->enc_ctx, out_buf, out_buf_len, &avframe);
Benny Prijonoc45d9512010-12-10 11:04:30 +00001183 if (err < 0) {
1184 print_ffmpeg_err(err);
Benny Prijono135290d2011-03-17 11:33:34 +00001185 return PJMEDIA_CODEC_EFAILED;
Benny Prijonoc45d9512010-12-10 11:04:30 +00001186 } else {
1187 output->size = err;
1188 }
1189
1190 return PJ_SUCCESS;
1191}
1192
1193/*
1194 * Decode frame.
1195 */
1196static pj_status_t ffmpeg_codec_decode( pjmedia_vid_codec *codec,
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001197 const pjmedia_frame *input,
Benny Prijonoc45d9512010-12-10 11:04:30 +00001198 unsigned output_buf_len,
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001199 pjmedia_frame *output)
Benny Prijonoc45d9512010-12-10 11:04:30 +00001200{
1201 ffmpeg_private *ff = (ffmpeg_private*)codec->codec_data;
1202 AVFrame avframe;
1203 AVPacket avpacket;
1204 int err, got_picture;
1205
1206 /* Check if decoder has been opened */
1207 PJ_ASSERT_RETURN(ff->dec_ctx, PJ_EINVALIDOP);
1208
Nanang Izzuddin98610702011-03-01 17:40:17 +00001209 /* Reset output frame bit info */
1210 output->bit_info = 0;
1211
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001212 /* Validate output buffer size */
Nanang Izzuddin98610702011-03-01 17:40:17 +00001213 if (ff->dec_vafp.framebytes > output_buf_len)
1214 return PJ_ETOOSMALL;
Benny Prijonoc45d9512010-12-10 11:04:30 +00001215
1216 /* Init frame to receive the decoded data, the ffmpeg codec context will
1217 * automatically provide the decoded buffer (single buffer used for the
1218 * whole decoding session, and seems to be freed when the codec context
1219 * closed).
1220 */
1221 avcodec_get_frame_defaults(&avframe);
1222
1223 /* Init packet, the container of the encoded data */
1224 av_init_packet(&avpacket);
1225 avpacket.data = (pj_uint8_t*)input->buf;
1226 avpacket.size = input->size;
1227
1228 /* ffmpeg warns:
1229 * - input buffer padding, at least FF_INPUT_BUFFER_PADDING_SIZE
1230 * - null terminated
1231 * Normally, encoded buffer is allocated more than needed, so lets just
1232 * bzero the input buffer end/pad, hope it will be just fine.
1233 */
1234 pj_bzero(avpacket.data+avpacket.size, FF_INPUT_BUFFER_PADDING_SIZE);
1235
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001236 output->bit_info = 0;
Benny Prijono135290d2011-03-17 11:33:34 +00001237 output->timestamp = input->timestamp;
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001238
Benny Prijonoc45d9512010-12-10 11:04:30 +00001239#if LIBAVCODEC_VERSION_MAJOR >= 52 && LIBAVCODEC_VERSION_MINOR >= 72
Nanang Izzuddind91af572011-03-31 17:29:54 +00001240 //avpacket.flags = AV_PKT_FLAG_KEY;
Benny Prijonoc45d9512010-12-10 11:04:30 +00001241#else
1242 avpacket.flags = 0;
1243#endif
1244
1245#if LIBAVCODEC_VERSION_MAJOR >= 52 && LIBAVCODEC_VERSION_MINOR >= 72
1246 err = avcodec_decode_video2(ff->dec_ctx, &avframe,
1247 &got_picture, &avpacket);
1248#else
1249 err = avcodec_decode_video(ff->dec_ctx, &avframe,
1250 &got_picture, avpacket.data, avpacket.size);
1251#endif
1252 if (err < 0) {
Benny Prijono135290d2011-03-17 11:33:34 +00001253 output->type = PJMEDIA_FRAME_TYPE_NONE;
1254 output->size = 0;
Benny Prijonoc45d9512010-12-10 11:04:30 +00001255 print_ffmpeg_err(err);
Benny Prijono135290d2011-03-17 11:33:34 +00001256 return PJMEDIA_CODEC_EFAILED;
Benny Prijonoc45d9512010-12-10 11:04:30 +00001257 } else if (got_picture) {
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001258 pjmedia_video_apply_fmt_param *vafp = &ff->dec_vafp;
Benny Prijonoc45d9512010-12-10 11:04:30 +00001259 pj_uint8_t *q = (pj_uint8_t*)output->buf;
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001260 unsigned i;
Benny Prijonoc45d9512010-12-10 11:04:30 +00001261
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001262 /* Decoder output format is set by libavcodec, in case it is different
1263 * to the configured param.
1264 */
1265 if (ff->dec_ctx->pix_fmt != ff->expected_dec_fmt ||
1266 ff->dec_ctx->coded_width != (int)vafp->size.w ||
1267 ff->dec_ctx->coded_height != (int)vafp->size.h)
1268 {
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001269 pjmedia_format_id new_fmt_id;
1270 pj_status_t status;
1271
1272 /* Get current raw format id from ffmpeg decoder context */
1273 status = PixelFormat_to_pjmedia_format_id(ff->dec_ctx->pix_fmt,
1274 &new_fmt_id);
1275 if (status != PJ_SUCCESS)
1276 return status;
1277
1278 /* Update decoder format in param */
1279 ff->param.dec_fmt.id = new_fmt_id;
1280 ff->param.dec_fmt.det.vid.size.w = ff->dec_ctx->coded_width;
1281 ff->param.dec_fmt.det.vid.size.h = ff->dec_ctx->coded_height;
1282
1283 /* Re-init format info and apply-param of decoder */
1284 ff->dec_vfi = pjmedia_get_video_format_info(NULL, ff->param.dec_fmt.id);
1285 if (!ff->dec_vfi)
Benny Prijono135290d2011-03-17 11:33:34 +00001286 return PJ_ENOTSUP;
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001287 pj_bzero(&ff->dec_vafp, sizeof(ff->dec_vafp));
1288 ff->dec_vafp.size = ff->param.dec_fmt.det.vid.size;
1289 ff->dec_vafp.buffer = NULL;
1290 status = (*ff->dec_vfi->apply_fmt)(ff->dec_vfi, &ff->dec_vafp);
1291 if (status != PJ_SUCCESS)
1292 return status;
1293
1294 /* Notify application via the bit_info field of pjmedia_frame */
1295 output->bit_info = PJMEDIA_VID_CODEC_EVENT_FMT_CHANGED;
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001296
Nanang Izzuddin98610702011-03-01 17:40:17 +00001297 /* Check provided buffer size after format changed */
1298 if (vafp->framebytes > output_buf_len)
1299 return PJ_ETOOSMALL;
1300 }
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001301
1302 /* Get the decoded data */
1303 for (i = 0; i < ff->dec_vfi->plane_cnt; ++i) {
1304 pj_uint8_t *p = avframe.data[i];
1305
1306 /* The decoded data may contain padding */
1307 if (avframe.linesize[i]!=vafp->strides[i]) {
1308 /* Padding exists, copy line by line */
1309 pj_uint8_t *q_end;
1310
1311 q_end = q+vafp->plane_bytes[i];
1312 while(q < q_end) {
1313 pj_memcpy(q, p, vafp->strides[i]);
1314 q += vafp->strides[i];
1315 p += avframe.linesize[i];
1316 }
1317 } else {
1318 /* No padding, copy the whole plane */
1319 pj_memcpy(q, p, vafp->plane_bytes[i]);
1320 q += vafp->plane_bytes[i];
1321 }
1322 }
1323
Benny Prijono135290d2011-03-17 11:33:34 +00001324 output->type = PJMEDIA_FRAME_TYPE_VIDEO;
Benny Prijonoc45d9512010-12-10 11:04:30 +00001325 output->size = vafp->framebytes;
1326 } else {
Benny Prijono135290d2011-03-17 11:33:34 +00001327 output->type = PJMEDIA_FRAME_TYPE_NONE;
1328 output->size = 0;
Benny Prijonoc45d9512010-12-10 11:04:30 +00001329 }
Benny Prijono135290d2011-03-17 11:33:34 +00001330
Benny Prijonoc45d9512010-12-10 11:04:30 +00001331 return PJ_SUCCESS;
1332}
1333
1334/*
1335 * Recover lost frame.
1336 */
1337static pj_status_t ffmpeg_codec_recover( pjmedia_vid_codec *codec,
1338 unsigned output_buf_len,
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001339 pjmedia_frame *output)
Benny Prijonoc45d9512010-12-10 11:04:30 +00001340{
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001341 PJ_UNUSED_ARG(codec);
Benny Prijonoc45d9512010-12-10 11:04:30 +00001342 PJ_UNUSED_ARG(output_buf_len);
1343 PJ_UNUSED_ARG(output);
Benny Prijonoc45d9512010-12-10 11:04:30 +00001344
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001345 return PJ_ENOTSUP;
Benny Prijonoc45d9512010-12-10 11:04:30 +00001346}
1347
1348#ifdef _MSC_VER
1349# pragma comment( lib, "avcodec.lib")
Benny Prijonoc45d9512010-12-10 11:04:30 +00001350#endif
1351
1352#endif /* PJMEDIA_HAS_FFMPEG_CODEC */
1353