blob: 96ff50bfde52436391fece4e9b6556a8ccd9bc4e [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 Izzuddin56b2ce42011-04-06 13:55:01 +0000178#define FUNC_FMT_MATCH(name) \
179 pj_status_t(name)(pj_pool_t *pool, \
180 pjmedia_sdp_media *offer, unsigned o_fmt_idx, \
181 pjmedia_sdp_media *answer, unsigned a_fmt_idx, \
182 unsigned option)
183
184
185/* Type definition of codec specific functions */
Nanang Izzuddind91af572011-03-31 17:29:54 +0000186typedef FUNC_PACKETIZE(*func_packetize);
187typedef FUNC_UNPACKETIZE(*func_unpacketize);
188typedef pj_status_t (*func_preopen) (ffmpeg_private *ff);
189typedef pj_status_t (*func_postopen) (ffmpeg_private *ff);
Nanang Izzuddin56b2ce42011-04-06 13:55:01 +0000190typedef FUNC_FMT_MATCH(*func_sdp_fmt_match);
Nanang Izzuddind91af572011-03-31 17:29:54 +0000191
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000192
193/* FFMPEG codec info */
Nanang Izzuddind91af572011-03-31 17:29:54 +0000194struct ffmpeg_codec_desc
195{
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000196 /* Predefined info */
197 pjmedia_vid_codec_info info;
Nanang Izzuddin56b2ce42011-04-06 13:55:01 +0000198 pjmedia_format_id base_fmt_id; /**< Some codecs may be exactly
199 same or compatible with
200 another codec, base format
201 will tell the initializer
202 to copy this codec desc
203 from its base format */
Nanang Izzuddin678b2f82011-03-02 08:37:31 +0000204 pj_uint32_t avg_bps;
205 pj_uint32_t max_bps;
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000206 func_packetize packetize;
207 func_unpacketize unpacketize;
Nanang Izzuddind91af572011-03-31 17:29:54 +0000208 func_preopen preopen;
209 func_preopen postopen;
Nanang Izzuddin56b2ce42011-04-06 13:55:01 +0000210 func_sdp_fmt_match sdp_fmt_match;
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000211 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
Benny Prijonoc45d9512010-12-10 11:04:30 +0000219
Benny Prijono284b80f2011-04-07 05:12:35 +0000220/* H264 constants */
221#define PROFILE_H264_BASELINE 66
222#define PROFILE_H264_MAIN 77
223
Nanang Izzuddind91af572011-03-31 17:29:54 +0000224/* Codec specific functions */
225static pj_status_t h264_preopen(ffmpeg_private *ff);
226static pj_status_t h264_postopen(ffmpeg_private *ff);
227static pj_status_t h263_preopen(ffmpeg_private *ff);
228static FUNC_PACKETIZE(h264_packetize);
229static FUNC_UNPACKETIZE(h264_unpacketize);
230static FUNC_PACKETIZE(h263_packetize);
231static FUNC_UNPACKETIZE(h263_unpacketize);
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000232
233
234/* Internal codec info */
235ffmpeg_codec_desc codec_desc[] =
236{
237 {
Nanang Izzuddin56b2ce42011-04-06 13:55:01 +0000238 {PJMEDIA_FORMAT_H264, PJMEDIA_RTP_PT_H264, {"H264",4},
239 {"Constrained Baseline (level=30, pack=1)", 39}},
240 0, 128000, 1000000,
Nanang Izzuddind91af572011-03-31 17:29:54 +0000241 &h264_packetize, &h264_unpacketize, &h264_preopen, &h264_postopen,
Nanang Izzuddin56b2ce42011-04-06 13:55:01 +0000242 &pjmedia_vid_codec_h264_match_sdp,
Nanang Izzuddind91af572011-03-31 17:29:54 +0000243 /* Leading space for better compatibility (strange indeed!) */
Nanang Izzuddin56b2ce42011-04-06 13:55:01 +0000244 {2, { {{"profile-level-id",16}, {"42e01e",6}},
Nanang Izzuddind91af572011-03-31 17:29:54 +0000245 {{" packetization-mode",19}, {"1",1}}, } },
246 },
247 {
Nanang Izzuddin56b2ce42011-04-06 13:55:01 +0000248 {PJMEDIA_FORMAT_H264, PJMEDIA_RTP_PT_H264_RSV1, {"H264",4},
249 {"Baseline (level=30, pack=1)", 27}},
250 PJMEDIA_FORMAT_H264, 128000, 1000000,
251 &h264_packetize, &h264_unpacketize, &h264_preopen, &h264_postopen,
252 &pjmedia_vid_codec_h264_match_sdp,
253 {2, { {{"profile-level-id",16}, {"42001e",6}},
254 {{" packetization-mode",19}, {"1",1}}, } },
255 },
256 {
257 {PJMEDIA_FORMAT_H263P, PJMEDIA_RTP_PT_H263P, {"H263-1998",9}},
Nanang Izzuddin678b2f82011-03-02 08:37:31 +0000258 PJMEDIA_FORMAT_H263, 1000000, 2000000,
Nanang Izzuddin56b2ce42011-04-06 13:55:01 +0000259 &h263_packetize, &h263_unpacketize, &h263_preopen, NULL, NULL,
Nanang Izzuddind91af572011-03-31 17:29:54 +0000260 {2, { {{"CIF",3}, {"1",1}},
261 {{"QCIF",4}, {"1",1}}, } },
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000262 },
Nanang Izzuddind00d3f22011-04-11 20:04:27 +0000263 {
264 {PJMEDIA_FORMAT_H263, PJMEDIA_RTP_PT_H263, {"H263",4}},
265 PJMEDIA_FORMAT_H263, 1000000, 2000000,
266 &h263_packetize, &h263_unpacketize, &h263_preopen, NULL, NULL,
267 {2, { {{"CIF",3}, {"1",1}},
268 {{"QCIF",4}, {"1",1}}, } },
269 },
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000270 {
Nanang Izzuddin56b2ce42011-04-06 13:55:01 +0000271 {PJMEDIA_FORMAT_H263, PJMEDIA_RTP_PT_H263, {"H263",4}},
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000272 },
273 {
Nanang Izzuddin56b2ce42011-04-06 13:55:01 +0000274 {PJMEDIA_FORMAT_H261, PJMEDIA_RTP_PT_H261, {"H261",4}},
Nanang Izzuddin235e1b42011-02-28 18:59:47 +0000275 },
276 {
Nanang Izzuddin56b2ce42011-04-06 13:55:01 +0000277 {PJMEDIA_FORMAT_MJPEG, PJMEDIA_RTP_PT_JPEG, {"JPEG",4}},
Nanang Izzuddin235e1b42011-02-28 18:59:47 +0000278 },
279 {
Nanang Izzuddin56b2ce42011-04-06 13:55:01 +0000280 {PJMEDIA_FORMAT_MPEG4, 0, {"MP4V",4}},
Nanang Izzuddin235e1b42011-02-28 18:59:47 +0000281 },
282 {
Nanang Izzuddin56b2ce42011-04-06 13:55:01 +0000283 {PJMEDIA_FORMAT_XVID, 0, {"XVID",4}},
Nanang Izzuddin235e1b42011-02-28 18:59:47 +0000284 PJMEDIA_FORMAT_MPEG4,
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000285 },
286};
287
Nanang Izzuddind91af572011-03-31 17:29:54 +0000288
289typedef struct h264_data
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000290{
Nanang Izzuddind91af572011-03-31 17:29:54 +0000291 pjmedia_vid_codec_h264_fmtp fmtp;
292 pjmedia_h264_packetizer *pktz;
293} h264_data;
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000294
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000295
Nanang Izzuddind91af572011-03-31 17:29:54 +0000296static pj_status_t h264_preopen(ffmpeg_private *ff)
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000297{
Nanang Izzuddind91af572011-03-31 17:29:54 +0000298 h264_data *data;
299 pjmedia_h264_packetizer_cfg pktz_cfg;
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000300 pj_status_t status;
301
Nanang Izzuddind91af572011-03-31 17:29:54 +0000302 data = PJ_POOL_ZALLOC_T(ff->pool, h264_data);
303 ff->data = data;
304
Nanang Izzuddin56b2ce42011-04-06 13:55:01 +0000305 /* Parse remote fmtp */
306 status = pjmedia_vid_codec_h264_parse_fmtp(&ff->param.enc_fmtp,
307 &data->fmtp);
308 if (status != PJ_SUCCESS)
309 return status;
310
Nanang Izzuddind91af572011-03-31 17:29:54 +0000311 /* Create packetizer */
312 pktz_cfg.mtu = ff->param.enc_mtu;
Nanang Izzuddin5f8d5892011-04-12 18:24:19 +0000313#if 0
Nanang Izzuddin56b2ce42011-04-06 13:55:01 +0000314 if (data->fmtp.packetization_mode == 0)
315 pktz_cfg.mode = PJMEDIA_H264_PACKETIZER_MODE_SINGLE_NAL;
316 else if (data->fmtp.packetization_mode == 1)
317 pktz_cfg.mode = PJMEDIA_H264_PACKETIZER_MODE_NON_INTERLEAVED;
318 else
319 return PJ_ENOTSUP;
Nanang Izzuddin5f8d5892011-04-12 18:24:19 +0000320#else
321 if (data->fmtp.packetization_mode!=
322 PJMEDIA_H264_PACKETIZER_MODE_SINGLE_NAL &&
323 data->fmtp.packetization_mode!=
324 PJMEDIA_H264_PACKETIZER_MODE_NON_INTERLEAVED)
325 {
326 return PJ_ENOTSUP;
327 }
328 /* Better always send in single NAL mode for better compatibility */
329 pktz_cfg.mode = PJMEDIA_H264_PACKETIZER_MODE_SINGLE_NAL;
330#endif
Nanang Izzuddin56b2ce42011-04-06 13:55:01 +0000331
Nanang Izzuddind91af572011-03-31 17:29:54 +0000332 status = pjmedia_h264_packetizer_create(ff->pool, &pktz_cfg, &data->pktz);
333 if (status != PJ_SUCCESS)
334 return status;
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000335
Nanang Izzuddin5f8d5892011-04-12 18:24:19 +0000336 /* Apply SDP fmtp to format in codec param */
337 status = pjmedia_vid_codec_h264_apply_fmtp(&ff->param);
338 if (status != PJ_SUCCESS)
339 return status;
340
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000341 if (ff->param.dir & PJMEDIA_DIR_ENCODING) {
Nanang Izzuddind91af572011-03-31 17:29:54 +0000342 AVCodecContext *ctx = ff->enc_ctx;
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000343
Nanang Izzuddin56b2ce42011-04-06 13:55:01 +0000344 /* Apply profile. Note that, for x264 backend, ffmpeg doesn't seem to
345 * use this profile param field, so let's try to apply it "manually".
346 */
Nanang Izzuddind91af572011-03-31 17:29:54 +0000347 ctx->profile = data->fmtp.profile_idc;
Benny Prijono284b80f2011-04-07 05:12:35 +0000348 if (ctx->profile == PROFILE_H264_BASELINE) {
Nanang Izzuddin56b2ce42011-04-06 13:55:01 +0000349 /* Baseline profile settings (the most used profile in
350 * conversational/real-time communications).
351 */
352 ctx->coder_type = FF_CODER_TYPE_VLC;
353 ctx->max_b_frames = 0;
354 ctx->flags2 &= ~(CODEC_FLAG2_WPRED | CODEC_FLAG2_8X8DCT);
355 ctx->weighted_p_pred = 0;
Benny Prijono284b80f2011-04-07 05:12:35 +0000356 } else if (ctx->profile == PROFILE_H264_MAIN) {
Nanang Izzuddin56b2ce42011-04-06 13:55:01 +0000357 ctx->flags2 &= ~CODEC_FLAG2_8X8DCT;
358 }
359
360 /* Apply profile constraint bits. */
361 // The x264 doesn't seem to support non-constrained (baseline) profile
362 // so this shouldn't be a problem (for now).
363 //PJ_TODO(set_h264_constraint_bits_properly_in_ffmpeg);
Nanang Izzuddind91af572011-03-31 17:29:54 +0000364 if (data->fmtp.profile_iop) {
365#if defined(FF_PROFILE_H264_CONSTRAINED)
366 ctx->profile |= FF_PROFILE_H264_CONSTRAINED;
367#endif
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000368 }
Nanang Izzuddin56b2ce42011-04-06 13:55:01 +0000369
370 /* Apply profile level. */
Nanang Izzuddind91af572011-03-31 17:29:54 +0000371 ctx->level = data->fmtp.level;
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000372
Nanang Izzuddind91af572011-03-31 17:29:54 +0000373 /* Libx264 rejects the "broken" ffmpeg defaults, so just change some */
374 ctx->me_range = 16;
375 ctx->max_qdiff = 4;
Nanang Izzuddind00d3f22011-04-11 20:04:27 +0000376 ctx->qmin = 20;
377 ctx->qmax = 32;
Nanang Izzuddind91af572011-03-31 17:29:54 +0000378 ctx->qcompress = 0.6f;
Nanang Izzuddind00d3f22011-04-11 20:04:27 +0000379
380 ctx->rtp_payload_size = ff->param.enc_mtu;
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000381 }
382
Nanang Izzuddin81f0e6a2011-04-06 14:56:03 +0000383 if (ff->param.dir & PJMEDIA_DIR_DECODING) {
384 AVCodecContext *ctx = ff->dec_ctx;
385
386 /* Apply the "sprop-parameter-sets" fmtp from remote SDP to
387 * extradata of ffmpeg codec context.
388 */
389 if (data->fmtp.sprop_param_sets_len) {
390 ctx->extradata_size = data->fmtp.sprop_param_sets_len;
391 ctx->extradata = data->fmtp.sprop_param_sets;
392 }
393 }
394
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000395 return PJ_SUCCESS;
396}
397
Nanang Izzuddind91af572011-03-31 17:29:54 +0000398static pj_status_t h264_postopen(ffmpeg_private *ff)
399{
400 h264_data *data = (h264_data*)ff->data;
401 PJ_UNUSED_ARG(data);
Nanang Izzuddind91af572011-03-31 17:29:54 +0000402 return PJ_SUCCESS;
403}
404
405
406static FUNC_PACKETIZE(h264_packetize)
407{
408 h264_data *data = (h264_data*)ff->data;
409 return pjmedia_h264_packetize(data->pktz, bits, bits_len, bits_pos,
410 payload, payload_len);
411}
412
413static FUNC_UNPACKETIZE(h264_unpacketize)
414{
415 h264_data *data = (h264_data*)ff->data;
416 return pjmedia_h264_unpacketize(data->pktz, payload, payload_len,
417 bits, bits_len, bits_pos);
418}
419
420
421typedef struct h263_data
422{
423 pjmedia_h263_packetizer *pktz;
424} h263_data;
425
426/* H263 pre-open */
427static pj_status_t h263_preopen(ffmpeg_private *ff)
428{
429 h263_data *data;
430 pjmedia_h263_packetizer_cfg pktz_cfg;
431 pj_status_t status;
432
433 data = PJ_POOL_ZALLOC_T(ff->pool, h263_data);
434 ff->data = data;
435
436 /* Create packetizer */
437 pktz_cfg.mtu = ff->param.enc_mtu;
438 pktz_cfg.mode = PJMEDIA_H263_PACKETIZER_MODE_RFC4629;
439 status = pjmedia_h263_packetizer_create(ff->pool, &pktz_cfg, &data->pktz);
440 if (status != PJ_SUCCESS)
441 return status;
442
443 /* Apply fmtp settings to codec param */
444 status = pjmedia_vid_codec_h263_apply_fmtp(&ff->param);
445
446 return status;
447}
448
449static FUNC_PACKETIZE(h263_packetize)
450{
451 h263_data *data = (h263_data*)ff->data;
452 return pjmedia_h263_packetize(data->pktz, bits, bits_len, bits_pos,
453 payload, payload_len);
454}
455
456static FUNC_UNPACKETIZE(h263_unpacketize)
457{
458 h263_data *data = (h263_data*)ff->data;
459 return pjmedia_h263_unpacketize(data->pktz, payload, payload_len,
460 bits, bits_len, bits_pos);
461}
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000462
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) &&
Nanang Izzuddin56b2ce42011-04-06 13:55:01 +0000475 (desc->info.pt == info->pt))
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000476 {
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
Benny Prijono643a9012011-07-12 23:16:27 +0000543#if LIBAVCODEC_VERSION_MAJOR <= 52
544# define AVMEDIA_TYPE_VIDEO CODEC_TYPE_VIDEO
545#endif
546 if (c->type != AVMEDIA_TYPE_VIDEO)
Benny Prijonoc45d9512010-12-10 11:04:30 +0000547 continue;
548
549 /* Video encoder and decoder are usually implemented in separate
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000550 * AVCodec instances. While the codec attributes (e.g: raw formats,
551 * supported fps) are in the encoder.
Benny Prijonoc45d9512010-12-10 11:04:30 +0000552 */
553
Nanang Izzuddin235e1b42011-02-28 18:59:47 +0000554 //PJ_LOG(3, (THIS_FILE, "%s", c->name));
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000555 status = CodecID_to_pjmedia_format_id(c->id, &fmt_id);
556 /* Skip if format ID is unknown */
557 if (status != PJ_SUCCESS)
558 continue;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000559
Nanang Izzuddin235e1b42011-02-28 18:59:47 +0000560 codec_info_idx = find_codec_idx_by_fmt_id(fmt_id);
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000561 /* Skip if codec is unwanted by this wrapper (not listed in
562 * the codec info array)
563 */
564 if (codec_info_idx < 0)
565 continue;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000566
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000567 desc = &codec_desc[codec_info_idx];
Benny Prijonoc45d9512010-12-10 11:04:30 +0000568
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000569 /* Skip duplicated codec implementation */
570 if ((c->encode && (desc->info.dir & PJMEDIA_DIR_ENCODING)) ||
571 (c->decode && (desc->info.dir & PJMEDIA_DIR_DECODING)))
572 {
573 continue;
574 }
Benny Prijonoc45d9512010-12-10 11:04:30 +0000575
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000576 /* Get raw/decoded format ids in the encoder */
577 if (c->pix_fmts && c->encode) {
578 pjmedia_format_id raw_fmt[PJMEDIA_VID_CODEC_MAX_DEC_FMT_CNT];
579 unsigned raw_fmt_cnt = 0;
580 unsigned raw_fmt_cnt_should_be = 0;
581 const enum PixelFormat *p = c->pix_fmts;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000582
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000583 for(;(p && *p != -1) &&
584 (raw_fmt_cnt < PJMEDIA_VID_CODEC_MAX_DEC_FMT_CNT);
585 ++p)
586 {
587 pjmedia_format_id fmt_id;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000588
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000589 raw_fmt_cnt_should_be++;
590 status = PixelFormat_to_pjmedia_format_id(*p, &fmt_id);
591 if (status != PJ_SUCCESS) {
592 PJ_LOG(6, (THIS_FILE, "Unrecognized ffmpeg pixel "
593 "format %d", *p));
594 continue;
595 }
596 raw_fmt[raw_fmt_cnt++] = fmt_id;
597 }
Benny Prijonoc45d9512010-12-10 11:04:30 +0000598
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000599 if (raw_fmt_cnt == 0) {
600 PJ_LOG(5, (THIS_FILE, "No recognized raw format "
601 "for codec [%s/%s], codec ignored",
602 c->name, c->long_name));
603 /* Skip this encoder */
604 continue;
605 }
Benny Prijonoc45d9512010-12-10 11:04:30 +0000606
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000607 if (raw_fmt_cnt < raw_fmt_cnt_should_be) {
608 PJ_LOG(6, (THIS_FILE, "Codec [%s/%s] have %d raw formats, "
609 "recognized only %d raw formats",
610 c->name, c->long_name,
611 raw_fmt_cnt_should_be, raw_fmt_cnt));
612 }
Benny Prijonoc45d9512010-12-10 11:04:30 +0000613
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000614 desc->info.dec_fmt_id_cnt = raw_fmt_cnt;
615 pj_memcpy(desc->info.dec_fmt_id, raw_fmt,
616 sizeof(raw_fmt[0])*raw_fmt_cnt);
617 }
618
619 /* Get supported framerates */
620 if (c->supported_framerates) {
621 const AVRational *fr = c->supported_framerates;
622 while ((fr->num != 0 || fr->den != 0) &&
623 desc->info.fps_cnt < PJMEDIA_VID_CODEC_MAX_FPS_CNT)
624 {
625 desc->info.fps[desc->info.fps_cnt].num = fr->num;
626 desc->info.fps[desc->info.fps_cnt].denum = fr->den;
627 ++desc->info.fps_cnt;
628 ++fr;
629 }
630 }
631
632 /* Get ffmpeg encoder instance */
633 if (c->encode && !desc->enc) {
634 desc->info.dir |= PJMEDIA_DIR_ENCODING;
635 desc->enc = c;
636 }
637
638 /* Get ffmpeg decoder instance */
639 if (c->decode && !desc->dec) {
640 desc->info.dir |= PJMEDIA_DIR_DECODING;
641 desc->dec = c;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000642 }
643
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000644 /* Enable this codec when any ffmpeg codec instance are recognized
645 * and the supported raw formats info has been collected.
646 */
647 if ((desc->dec || desc->enc) && desc->info.dec_fmt_id_cnt)
648 {
649 desc->enabled = PJ_TRUE;
650 }
Benny Prijonoc45d9512010-12-10 11:04:30 +0000651
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000652 /* Normalize default value of clock rate */
653 if (desc->info.clock_rate == 0)
654 desc->info.clock_rate = 90000;
Benny Prijono135290d2011-03-17 11:33:34 +0000655
656 /* Set RTP packetization support flag in the codec info */
657 desc->info.has_rtp_pack = (desc->packetize != NULL) &&
658 (desc->unpacketize != NULL);
Benny Prijonoc45d9512010-12-10 11:04:30 +0000659 }
660
Nanang Izzuddin56b2ce42011-04-06 13:55:01 +0000661 /* Review all codecs for applying base format, registering format match for
662 * SDP negotiation, etc.
663 */
Nanang Izzuddin235e1b42011-02-28 18:59:47 +0000664 for (i = 0; i < PJ_ARRAY_SIZE(codec_desc); ++i) {
665 ffmpeg_codec_desc *desc = &codec_desc[i];
666
Nanang Izzuddin56b2ce42011-04-06 13:55:01 +0000667 /* Init encoder/decoder description from base format */
Nanang Izzuddin235e1b42011-02-28 18:59:47 +0000668 if (desc->base_fmt_id && (!desc->dec || !desc->enc)) {
669 ffmpeg_codec_desc *base_desc = NULL;
670 int base_desc_idx;
671 pjmedia_dir copied_dir = PJMEDIA_DIR_NONE;
672
673 base_desc_idx = find_codec_idx_by_fmt_id(desc->base_fmt_id);
674 if (base_desc_idx != -1)
675 base_desc = &codec_desc[base_desc_idx];
676 if (!base_desc || !base_desc->enabled)
677 continue;
678
679 /* Copy description from base codec */
680 if (!desc->info.dec_fmt_id_cnt) {
681 desc->info.dec_fmt_id_cnt = base_desc->info.dec_fmt_id_cnt;
682 pj_memcpy(desc->info.dec_fmt_id, base_desc->info.dec_fmt_id,
683 sizeof(pjmedia_format_id)*desc->info.dec_fmt_id_cnt);
684 }
685 if (!desc->info.fps_cnt) {
686 desc->info.fps_cnt = base_desc->info.fps_cnt;
687 pj_memcpy(desc->info.fps, base_desc->info.fps,
688 sizeof(desc->info.fps[0])*desc->info.fps_cnt);
689 }
690 if (!desc->info.clock_rate) {
691 desc->info.clock_rate = base_desc->info.clock_rate;
692 }
693 if (!desc->dec && base_desc->dec) {
694 copied_dir |= PJMEDIA_DIR_DECODING;
695 desc->dec = base_desc->dec;
696 }
697 if (!desc->enc && base_desc->enc) {
698 copied_dir |= PJMEDIA_DIR_ENCODING;
699 desc->enc = base_desc->enc;
700 }
701
702 desc->info.dir |= copied_dir;
703 desc->enabled = (desc->info.dir != PJMEDIA_DIR_NONE);
Nanang Izzuddin56b2ce42011-04-06 13:55:01 +0000704 desc->info.has_rtp_pack = (desc->packetize != NULL) &&
705 (desc->unpacketize != NULL);
Nanang Izzuddin235e1b42011-02-28 18:59:47 +0000706
707 if (copied_dir != PJMEDIA_DIR_NONE) {
708 const char *dir_name[] = {NULL, "encoder", "decoder", "codec"};
709 PJ_LOG(5, (THIS_FILE, "The %.*s %s is using base codec (%.*s)",
710 desc->info.encoding_name.slen,
711 desc->info.encoding_name.ptr,
712 dir_name[copied_dir],
713 base_desc->info.encoding_name.slen,
714 base_desc->info.encoding_name.ptr));
715 }
716 }
Nanang Izzuddin56b2ce42011-04-06 13:55:01 +0000717
718 /* Registering format match for SDP negotiation */
719 if (desc->sdp_fmt_match) {
720 status = pjmedia_sdp_neg_register_fmt_match_cb(
721 &desc->info.encoding_name,
722 desc->sdp_fmt_match);
723 pj_assert(status == PJ_SUCCESS);
724 }
Nanang Izzuddin235e1b42011-02-28 18:59:47 +0000725 }
726
Benny Prijonoc45d9512010-12-10 11:04:30 +0000727 /* Register codec factory to codec manager. */
728 status = pjmedia_vid_codec_mgr_register_factory(mgr,
729 &ffmpeg_factory.base);
730 if (status != PJ_SUCCESS)
731 goto on_error;
732
733 ffmpeg_factory.pool = pool;
734
735 /* Done. */
736 return PJ_SUCCESS;
737
738on_error:
739 pj_pool_release(pool);
740 return status;
741}
742
743/*
744 * Unregister FFMPEG codecs factory from pjmedia endpoint.
745 */
746PJ_DEF(pj_status_t) pjmedia_codec_ffmpeg_deinit(void)
747{
748 pj_status_t status = PJ_SUCCESS;
749
750 if (ffmpeg_factory.pool == NULL) {
751 /* Already deinitialized */
752 return PJ_SUCCESS;
753 }
754
755 pj_mutex_lock(ffmpeg_factory.mutex);
756
757 /* Unregister FFMPEG codecs factory. */
758 status = pjmedia_vid_codec_mgr_unregister_factory(ffmpeg_factory.mgr,
759 &ffmpeg_factory.base);
760
761 /* Destroy mutex. */
762 pj_mutex_destroy(ffmpeg_factory.mutex);
763
764 /* Destroy pool. */
765 pj_pool_release(ffmpeg_factory.pool);
766 ffmpeg_factory.pool = NULL;
767
768 return status;
769}
770
771
Benny Prijonoc45d9512010-12-10 11:04:30 +0000772/*
773 * Check if factory can allocate the specified codec.
774 */
775static pj_status_t ffmpeg_test_alloc( pjmedia_vid_codec_factory *factory,
776 const pjmedia_vid_codec_info *info )
777{
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000778 const ffmpeg_codec_desc *desc;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000779
780 PJ_ASSERT_RETURN(factory==&ffmpeg_factory.base, PJ_EINVAL);
781 PJ_ASSERT_RETURN(info, PJ_EINVAL);
782
Nanang Izzuddin235e1b42011-02-28 18:59:47 +0000783 desc = find_codec_desc_by_info(info);
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000784 if (!desc) {
Benny Prijonoc45d9512010-12-10 11:04:30 +0000785 return PJMEDIA_CODEC_EUNSUP;
786 }
787
788 return PJ_SUCCESS;
789}
790
791/*
792 * Generate default attribute.
793 */
794static pj_status_t ffmpeg_default_attr( pjmedia_vid_codec_factory *factory,
795 const pjmedia_vid_codec_info *info,
796 pjmedia_vid_codec_param *attr )
797{
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000798 const ffmpeg_codec_desc *desc;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000799
800 PJ_ASSERT_RETURN(factory==&ffmpeg_factory.base, PJ_EINVAL);
801 PJ_ASSERT_RETURN(info && attr, PJ_EINVAL);
802
Nanang Izzuddin235e1b42011-02-28 18:59:47 +0000803 desc = find_codec_desc_by_info(info);
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000804 if (!desc) {
Benny Prijonoc45d9512010-12-10 11:04:30 +0000805 return PJMEDIA_CODEC_EUNSUP;
806 }
807
808 pj_bzero(attr, sizeof(pjmedia_vid_codec_param));
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000809
810 /* Direction */
811 attr->dir = desc->info.dir;
812
813 /* Encoded format */
814 pjmedia_format_init_video(&attr->enc_fmt, desc->info.fmt_id,
815 352, 288, 30000, 1001);
816
817 /* Decoded format */
818 pjmedia_format_init_video(&attr->dec_fmt, desc->info.dec_fmt_id[0],
Nanang Izzuddind00d3f22011-04-11 20:04:27 +0000819 //352, 288, 30000, 1001);
820 720, 576, 30000, 1001);
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000821
822 /* Decoding fmtp */
823 attr->dec_fmtp = desc->dec_fmtp;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000824
Nanang Izzuddin678b2f82011-03-02 08:37:31 +0000825 /* Bitrate */
826 attr->enc_fmt.det.vid.avg_bps = desc->avg_bps;
827 attr->enc_fmt.det.vid.max_bps = desc->max_bps;
828
Nanang Izzuddind91af572011-03-31 17:29:54 +0000829 /* MTU */
830 attr->enc_mtu = PJMEDIA_MAX_MTU;
831
Benny Prijonoc45d9512010-12-10 11:04:30 +0000832 return PJ_SUCCESS;
833}
834
835/*
836 * Enum codecs supported by this factory.
837 */
838static pj_status_t ffmpeg_enum_codecs( pjmedia_vid_codec_factory *factory,
839 unsigned *count,
840 pjmedia_vid_codec_info codecs[])
841{
Nanang Izzuddin235e1b42011-02-28 18:59:47 +0000842 unsigned i, max_cnt;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000843
844 PJ_ASSERT_RETURN(codecs && *count > 0, PJ_EINVAL);
845 PJ_ASSERT_RETURN(factory == &ffmpeg_factory.base, PJ_EINVAL);
846
Nanang Izzuddin235e1b42011-02-28 18:59:47 +0000847 max_cnt = PJ_MIN(*count, PJ_ARRAY_SIZE(codec_desc));
848 *count = 0;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000849
Nanang Izzuddin235e1b42011-02-28 18:59:47 +0000850 for (i=0; i<max_cnt; ++i) {
851 if (codec_desc[i].enabled) {
852 pj_memcpy(&codecs[*count], &codec_desc[i].info,
853 sizeof(pjmedia_vid_codec_info));
854 (*count)++;
855 }
Benny Prijonoc45d9512010-12-10 11:04:30 +0000856 }
Benny Prijonoc45d9512010-12-10 11:04:30 +0000857
858 return PJ_SUCCESS;
859}
860
861/*
862 * Allocate a new codec instance.
863 */
864static pj_status_t ffmpeg_alloc_codec( pjmedia_vid_codec_factory *factory,
865 const pjmedia_vid_codec_info *info,
866 pjmedia_vid_codec **p_codec)
867{
868 ffmpeg_private *ff;
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000869 const ffmpeg_codec_desc *desc;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000870 pjmedia_vid_codec *codec;
871 pj_pool_t *pool = NULL;
872 pj_status_t status = PJ_SUCCESS;
873
874 PJ_ASSERT_RETURN(factory && info && p_codec, PJ_EINVAL);
875 PJ_ASSERT_RETURN(factory == &ffmpeg_factory.base, PJ_EINVAL);
876
Nanang Izzuddin235e1b42011-02-28 18:59:47 +0000877 desc = find_codec_desc_by_info(info);
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000878 if (!desc) {
Benny Prijonoc45d9512010-12-10 11:04:30 +0000879 return PJMEDIA_CODEC_EUNSUP;
880 }
881
882 /* Create pool for codec instance */
883 pool = pj_pool_create(ffmpeg_factory.pf, "ffmpeg codec", 512, 512, NULL);
Benny Prijonod4b5e872011-07-12 09:08:56 +0000884 codec = PJ_POOL_ALLOC_T(pool, pjmedia_vid_codec);
Benny Prijonoc45d9512010-12-10 11:04:30 +0000885 if (!codec) {
886 status = PJ_ENOMEM;
887 goto on_error;
888 }
Benny Prijonofcf5db32011-07-14 04:56:08 +0000889 pjmedia_vid_codec_init(codec, PJMEDIA_SIG_VID_CODEC_FFMPEG);
Benny Prijonoc45d9512010-12-10 11:04:30 +0000890 codec->op = &ffmpeg_op;
891 codec->factory = factory;
892 ff = PJ_POOL_ZALLOC_T(pool, ffmpeg_private);
893 if (!ff) {
894 status = PJ_ENOMEM;
895 goto on_error;
896 }
897 codec->codec_data = ff;
898 ff->pool = pool;
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000899 ff->enc = desc->enc;
900 ff->dec = desc->dec;
901 ff->desc = desc;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000902
903 *p_codec = codec;
904 return PJ_SUCCESS;
905
906on_error:
907 if (pool)
908 pj_pool_release(pool);
909 return status;
910}
911
912/*
913 * Free codec.
914 */
915static pj_status_t ffmpeg_dealloc_codec( pjmedia_vid_codec_factory *factory,
916 pjmedia_vid_codec *codec )
917{
918 ffmpeg_private *ff;
919 pj_pool_t *pool;
920
921 PJ_ASSERT_RETURN(factory && codec, PJ_EINVAL);
922 PJ_ASSERT_RETURN(factory == &ffmpeg_factory.base, PJ_EINVAL);
923
924 /* Close codec, if it's not closed. */
925 ff = (ffmpeg_private*) codec->codec_data;
926 pool = ff->pool;
927 codec->codec_data = NULL;
928 pj_pool_release(pool);
929
930 return PJ_SUCCESS;
931}
932
933/*
934 * Init codec.
935 */
936static pj_status_t ffmpeg_codec_init( pjmedia_vid_codec *codec,
937 pj_pool_t *pool )
938{
939 PJ_UNUSED_ARG(codec);
940 PJ_UNUSED_ARG(pool);
941 return PJ_SUCCESS;
942}
943
944static void print_ffmpeg_err(int err)
945{
Benny Prijono643a9012011-07-12 23:16:27 +0000946#if LIBAVCODEC_VERSION_MAJOR > 52 || \
947 (LIBAVCODEC_VERSION_MAJOR >= 52 && LIBAVCODEC_VERSION_MINOR >= 72)
Benny Prijonoc45d9512010-12-10 11:04:30 +0000948 char errbuf[512];
949 if (av_strerror(err, errbuf, sizeof(errbuf)) >= 0)
Benny Prijono63572992011-04-13 18:06:21 +0000950 PJ_LOG(5, (THIS_FILE, "ffmpeg err %d: %s", err, errbuf));
Benny Prijonoc45d9512010-12-10 11:04:30 +0000951#else
Benny Prijono63572992011-04-13 18:06:21 +0000952 PJ_LOG(5, (THIS_FILE, "ffmpeg err %d", err));
Benny Prijonoc45d9512010-12-10 11:04:30 +0000953#endif
954
955}
956
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000957static enum PixelFormat dec_get_format(struct AVCodecContext *s,
Nanang Izzuddind91af572011-03-31 17:29:54 +0000958 const enum PixelFormat * fmt)
Benny Prijonoc45d9512010-12-10 11:04:30 +0000959{
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000960 ffmpeg_private *ff = (ffmpeg_private*)s->opaque;
961 enum PixelFormat def_fmt = *fmt;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000962
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000963 while (*fmt != -1) {
964 if (*fmt == ff->expected_dec_fmt)
965 return *fmt;
966 ++fmt;
967 }
Benny Prijonoc45d9512010-12-10 11:04:30 +0000968
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000969 pj_assert(!"Inconsistency in supported formats");
970 return def_fmt;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000971}
972
Benny Prijonoc45d9512010-12-10 11:04:30 +0000973
974static pj_status_t open_ffmpeg_codec(ffmpeg_private *ff,
975 pj_mutex_t *ff_mutex)
976{
977 enum PixelFormat pix_fmt;
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000978 pjmedia_video_format_detail *vfd;
Nanang Izzuddind91af572011-03-31 17:29:54 +0000979 pj_bool_t enc_opened = PJ_FALSE, dec_opened = PJ_FALSE;
980 pj_status_t status;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000981
Nanang Izzuddind91af572011-03-31 17:29:54 +0000982 /* Get decoded pixel format */
Benny Prijonoc45d9512010-12-10 11:04:30 +0000983 status = pjmedia_format_id_to_PixelFormat(ff->param.dec_fmt.id,
984 &pix_fmt);
985 if (status != PJ_SUCCESS)
986 return status;
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000987 ff->expected_dec_fmt = pix_fmt;
988
Nanang Izzuddind91af572011-03-31 17:29:54 +0000989 /* Get video format detail for shortcut access to encoded format */
990 vfd = pjmedia_format_get_video_format_detail(&ff->param.enc_fmt,
991 PJ_TRUE);
992
993 /* Allocate ffmpeg codec context */
994 if (ff->param.dir & PJMEDIA_DIR_ENCODING) {
995 ff->enc_ctx = avcodec_alloc_context();
996 if (ff->enc_ctx == NULL)
997 goto on_error;
998 }
999 if (ff->param.dir & PJMEDIA_DIR_DECODING) {
1000 ff->dec_ctx = avcodec_alloc_context();
1001 if (ff->dec_ctx == NULL)
1002 goto on_error;
1003 }
1004
1005 /* Let the codec apply specific settings before the codec opened */
1006 if (ff->desc->preopen) {
1007 status = (*ff->desc->preopen)(ff);
1008 if (status != PJ_SUCCESS)
1009 goto on_error;
1010 }
1011
1012 if (ff->param.dir & PJMEDIA_DIR_ENCODING) {
1013 AVCodecContext *ctx = ff->enc_ctx;
Benny Prijonoc45d9512010-12-10 11:04:30 +00001014 int err;
1015
Nanang Izzuddind91af572011-03-31 17:29:54 +00001016 /* Init common settings */
Benny Prijonoc45d9512010-12-10 11:04:30 +00001017 ctx->pix_fmt = pix_fmt;
Nanang Izzuddind91af572011-03-31 17:29:54 +00001018 ctx->width = vfd->size.w;
1019 ctx->height = vfd->size.h;
1020 ctx->time_base.num = vfd->fps.denum;
1021 ctx->time_base.den = vfd->fps.num;
1022 if (vfd->avg_bps) {
1023 ctx->bit_rate = vfd->avg_bps;
1024 if (vfd->max_bps > vfd->avg_bps)
1025 ctx->bit_rate_tolerance = vfd->max_bps - vfd->avg_bps;
1026 }
1027 ctx->strict_std_compliance = FF_COMPLIANCE_STRICT;
Benny Prijonoc45d9512010-12-10 11:04:30 +00001028 ctx->workaround_bugs = FF_BUG_AUTODETECT;
1029 ctx->opaque = ff;
1030
Nanang Izzuddin2636c142011-04-01 07:12:59 +00001031 /* Set no delay, note that this may cause some codec functionals
1032 * not working (e.g: rate control).
1033 */
Benny Prijono643a9012011-07-12 23:16:27 +00001034#if LIBAVCODEC_VERSION_MAJOR > 52 || \
1035 (LIBAVCODEC_VERSION_MAJOR >= 52 && LIBAVCODEC_VERSION_MINOR >= 113)
Nanang Izzuddin2636c142011-04-01 07:12:59 +00001036 ctx->rc_lookahead = 0;
Benny Prijonoea508b42011-04-06 06:58:38 +00001037#endif
Nanang Izzuddin2636c142011-04-01 07:12:59 +00001038
Nanang Izzuddind91af572011-03-31 17:29:54 +00001039 /* Open ffmpeg codec */
Benny Prijonoc45d9512010-12-10 11:04:30 +00001040 pj_mutex_lock(ff_mutex);
Nanang Izzuddind91af572011-03-31 17:29:54 +00001041 err = avcodec_open(ctx, ff->enc);
Benny Prijonoc45d9512010-12-10 11:04:30 +00001042 pj_mutex_unlock(ff_mutex);
1043 if (err < 0) {
1044 print_ffmpeg_err(err);
Nanang Izzuddind91af572011-03-31 17:29:54 +00001045 status = PJMEDIA_CODEC_EFAILED;
1046 goto on_error;
Benny Prijonoc45d9512010-12-10 11:04:30 +00001047 }
Nanang Izzuddind91af572011-03-31 17:29:54 +00001048 enc_opened = PJ_TRUE;
Benny Prijonoc45d9512010-12-10 11:04:30 +00001049 }
Nanang Izzuddind91af572011-03-31 17:29:54 +00001050
1051 if (ff->param.dir & PJMEDIA_DIR_DECODING) {
1052 AVCodecContext *ctx = ff->dec_ctx;
1053 int err;
1054
1055 /* Init common settings */
1056 /* Width/height may be overriden by ffmpeg after first decoding. */
1057 ctx->width = ctx->coded_width = ff->param.dec_fmt.det.vid.size.w;
1058 ctx->height = ctx->coded_height = ff->param.dec_fmt.det.vid.size.h;
1059 ctx->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
1060 ctx->workaround_bugs = FF_BUG_AUTODETECT;
1061 ctx->opaque = ff;
1062 ctx->get_format = &dec_get_format;
1063
1064 /* Open ffmpeg codec */
1065 pj_mutex_lock(ff_mutex);
1066 err = avcodec_open(ctx, ff->dec);
1067 pj_mutex_unlock(ff_mutex);
1068 if (err < 0) {
1069 print_ffmpeg_err(err);
1070 status = PJMEDIA_CODEC_EFAILED;
1071 goto on_error;
1072 }
1073 dec_opened = PJ_TRUE;
1074 }
1075
1076 /* Let the codec apply specific settings after the codec opened */
1077 if (ff->desc->postopen) {
1078 status = (*ff->desc->postopen)(ff);
1079 if (status != PJ_SUCCESS)
1080 goto on_error;
1081 }
1082
Benny Prijonoc45d9512010-12-10 11:04:30 +00001083 return PJ_SUCCESS;
Nanang Izzuddind91af572011-03-31 17:29:54 +00001084
1085on_error:
1086 if (ff->enc_ctx) {
1087 if (enc_opened)
1088 avcodec_close(ff->enc_ctx);
1089 av_free(ff->enc_ctx);
1090 ff->enc_ctx = NULL;
1091 }
1092 if (ff->dec_ctx) {
1093 if (dec_opened)
1094 avcodec_close(ff->dec_ctx);
1095 av_free(ff->dec_ctx);
1096 ff->dec_ctx = NULL;
1097 }
1098 return status;
Benny Prijonoc45d9512010-12-10 11:04:30 +00001099}
1100
1101/*
1102 * Open codec.
1103 */
1104static pj_status_t ffmpeg_codec_open( pjmedia_vid_codec *codec,
1105 pjmedia_vid_codec_param *attr )
1106{
1107 ffmpeg_private *ff;
1108 pj_status_t status;
1109 pj_mutex_t *ff_mutex;
1110
1111 PJ_ASSERT_RETURN(codec && attr, PJ_EINVAL);
1112 ff = (ffmpeg_private*)codec->codec_data;
1113
Benny Prijonoc45d9512010-12-10 11:04:30 +00001114 pj_memcpy(&ff->param, attr, sizeof(*attr));
1115
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001116 /* Open the codec */
Benny Prijonoc45d9512010-12-10 11:04:30 +00001117 ff_mutex = ((struct ffmpeg_factory*)codec->factory)->mutex;
1118 status = open_ffmpeg_codec(ff, ff_mutex);
1119 if (status != PJ_SUCCESS)
1120 goto on_error;
1121
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001122 /* Init format info and apply-param of decoder */
1123 ff->dec_vfi = pjmedia_get_video_format_info(NULL, ff->param.dec_fmt.id);
1124 if (!ff->dec_vfi) {
1125 status = PJ_EINVAL;
1126 goto on_error;
1127 }
1128 pj_bzero(&ff->dec_vafp, sizeof(ff->dec_vafp));
1129 ff->dec_vafp.size = ff->param.dec_fmt.det.vid.size;
1130 ff->dec_vafp.buffer = NULL;
1131 status = (*ff->dec_vfi->apply_fmt)(ff->dec_vfi, &ff->dec_vafp);
1132 if (status != PJ_SUCCESS) {
1133 goto on_error;
1134 }
1135
1136 /* Init format info and apply-param of encoder */
1137 ff->enc_vfi = pjmedia_get_video_format_info(NULL, ff->param.dec_fmt.id);
1138 if (!ff->enc_vfi) {
1139 status = PJ_EINVAL;
1140 goto on_error;
1141 }
1142 pj_bzero(&ff->enc_vafp, sizeof(ff->enc_vafp));
1143 ff->enc_vafp.size = ff->param.enc_fmt.det.vid.size;
1144 ff->enc_vafp.buffer = NULL;
1145 status = (*ff->enc_vfi->apply_fmt)(ff->enc_vfi, &ff->enc_vafp);
1146 if (status != PJ_SUCCESS) {
1147 goto on_error;
1148 }
1149
1150 /* Update codec attributes, e.g: encoding format may be changed by
1151 * SDP fmtp negotiation.
1152 */
1153 pj_memcpy(attr, &ff->param, sizeof(*attr));
1154
Benny Prijonoc45d9512010-12-10 11:04:30 +00001155 return PJ_SUCCESS;
1156
1157on_error:
1158 ffmpeg_codec_close(codec);
1159 return status;
1160}
1161
1162/*
1163 * Close codec.
1164 */
1165static pj_status_t ffmpeg_codec_close( pjmedia_vid_codec *codec )
1166{
1167 ffmpeg_private *ff;
1168 pj_mutex_t *ff_mutex;
1169
1170 PJ_ASSERT_RETURN(codec, PJ_EINVAL);
1171 ff = (ffmpeg_private*)codec->codec_data;
1172 ff_mutex = ((struct ffmpeg_factory*)codec->factory)->mutex;
1173
1174 pj_mutex_lock(ff_mutex);
1175 if (ff->enc_ctx) {
1176 avcodec_close(ff->enc_ctx);
1177 av_free(ff->enc_ctx);
1178 }
1179 if (ff->dec_ctx && ff->dec_ctx!=ff->enc_ctx) {
1180 avcodec_close(ff->dec_ctx);
1181 av_free(ff->dec_ctx);
1182 }
Benny Prijonoc45d9512010-12-10 11:04:30 +00001183 ff->enc_ctx = NULL;
1184 ff->dec_ctx = NULL;
Benny Prijonoc45d9512010-12-10 11:04:30 +00001185 pj_mutex_unlock(ff_mutex);
1186
1187 return PJ_SUCCESS;
1188}
1189
1190
1191/*
1192 * Modify codec settings.
1193 */
1194static pj_status_t ffmpeg_codec_modify( pjmedia_vid_codec *codec,
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001195 const pjmedia_vid_codec_param *attr)
Benny Prijonoc45d9512010-12-10 11:04:30 +00001196{
1197 ffmpeg_private *ff = (ffmpeg_private*)codec->codec_data;
1198
1199 PJ_UNUSED_ARG(attr);
1200 PJ_UNUSED_ARG(ff);
1201
1202 return PJ_ENOTSUP;
1203}
1204
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001205static pj_status_t ffmpeg_codec_get_param(pjmedia_vid_codec *codec,
1206 pjmedia_vid_codec_param *param)
1207{
1208 ffmpeg_private *ff;
1209
1210 PJ_ASSERT_RETURN(codec && param, PJ_EINVAL);
1211
1212 ff = (ffmpeg_private*)codec->codec_data;
1213 pj_memcpy(param, &ff->param, sizeof(*param));
1214
1215 return PJ_SUCCESS;
1216}
1217
1218
Benny Prijonoc45d9512010-12-10 11:04:30 +00001219static pj_status_t ffmpeg_packetize ( pjmedia_vid_codec *codec,
Nanang Izzuddind91af572011-03-31 17:29:54 +00001220 pj_uint8_t *bits,
1221 pj_size_t bits_len,
1222 unsigned *bits_pos,
Benny Prijonoc45d9512010-12-10 11:04:30 +00001223 const pj_uint8_t **payload,
1224 pj_size_t *payload_len)
1225{
1226 ffmpeg_private *ff = (ffmpeg_private*)codec->codec_data;
1227
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001228 if (ff->desc->packetize) {
Nanang Izzuddind91af572011-03-31 17:29:54 +00001229 return (*ff->desc->packetize)(ff, bits, bits_len, bits_pos,
1230 payload, payload_len);
Benny Prijonoc45d9512010-12-10 11:04:30 +00001231 }
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001232
1233 return PJ_ENOTSUP;
Benny Prijonoc45d9512010-12-10 11:04:30 +00001234}
1235
1236static pj_status_t ffmpeg_unpacketize(pjmedia_vid_codec *codec,
1237 const pj_uint8_t *payload,
1238 pj_size_t payload_len,
Nanang Izzuddind91af572011-03-31 17:29:54 +00001239 pj_uint8_t *bits,
1240 pj_size_t bits_len,
1241 unsigned *bits_pos)
Benny Prijonoc45d9512010-12-10 11:04:30 +00001242{
1243 ffmpeg_private *ff = (ffmpeg_private*)codec->codec_data;
1244
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001245 if (ff->desc->unpacketize) {
Nanang Izzuddind91af572011-03-31 17:29:54 +00001246 return (*ff->desc->unpacketize)(ff, payload, payload_len,
1247 bits, bits_len, bits_pos);
Benny Prijonoc45d9512010-12-10 11:04:30 +00001248 }
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001249
1250 return PJ_ENOTSUP;
Benny Prijonoc45d9512010-12-10 11:04:30 +00001251}
1252
Benny Prijonoc45d9512010-12-10 11:04:30 +00001253
1254/*
1255 * Encode frames.
1256 */
1257static pj_status_t ffmpeg_codec_encode( pjmedia_vid_codec *codec,
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001258 const pjmedia_frame *input,
Benny Prijonoc45d9512010-12-10 11:04:30 +00001259 unsigned output_buf_len,
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001260 pjmedia_frame *output)
Benny Prijonoc45d9512010-12-10 11:04:30 +00001261{
1262 ffmpeg_private *ff = (ffmpeg_private*)codec->codec_data;
1263 pj_uint8_t *p = (pj_uint8_t*)input->buf;
1264 AVFrame avframe;
1265 pj_uint8_t *out_buf = (pj_uint8_t*)output->buf;
1266 int out_buf_len = output_buf_len;
1267 int err;
Nanang Izzuddin5f8d5892011-04-12 18:24:19 +00001268 //AVRational src_timebase;
Nanang Izzuddinada41262011-03-22 09:43:24 +00001269 /* For some reasons (e.g: SSE/MMX usage), the avcodec_encode_video() must
1270 * have stack aligned to 16 bytes. Let's try to be safe by preparing the
1271 * 16-bytes aligned stack here, in case it's not managed by the ffmpeg.
1272 */
1273 PJ_ALIGN_DATA(pj_uint32_t i[4], 16);
Benny Prijonoc45d9512010-12-10 11:04:30 +00001274
Nanang Izzuddind91af572011-03-31 17:29:54 +00001275 if ((long)i & 0xF) {
1276 PJ_LOG(2,(THIS_FILE, "Stack alignment fails"));
1277 }
1278
Benny Prijonoc45d9512010-12-10 11:04:30 +00001279 /* Check if encoder has been opened */
1280 PJ_ASSERT_RETURN(ff->enc_ctx, PJ_EINVALIDOP);
1281
Benny Prijonoc45d9512010-12-10 11:04:30 +00001282 avcodec_get_frame_defaults(&avframe);
Nanang Izzuddind00d3f22011-04-11 20:04:27 +00001283
1284 // Let ffmpeg manage the timestamps
1285 /*
Nanang Izzuddind91af572011-03-31 17:29:54 +00001286 src_timebase.num = 1;
1287 src_timebase.den = ff->desc->info.clock_rate;
1288 avframe.pts = av_rescale_q(input->timestamp.u64, src_timebase,
1289 ff->enc_ctx->time_base);
Nanang Izzuddind00d3f22011-04-11 20:04:27 +00001290 */
Benny Prijonoc45d9512010-12-10 11:04:30 +00001291
Nanang Izzuddinada41262011-03-22 09:43:24 +00001292 for (i[0] = 0; i[0] < ff->enc_vfi->plane_cnt; ++i[0]) {
1293 avframe.data[i[0]] = p;
1294 avframe.linesize[i[0]] = ff->enc_vafp.strides[i[0]];
1295 p += ff->enc_vafp.plane_bytes[i[0]];
Benny Prijonoc45d9512010-12-10 11:04:30 +00001296 }
1297
Nanang Izzuddinada41262011-03-22 09:43:24 +00001298 err = avcodec_encode_video(ff->enc_ctx, out_buf, out_buf_len, &avframe);
Benny Prijonoc45d9512010-12-10 11:04:30 +00001299 if (err < 0) {
1300 print_ffmpeg_err(err);
Benny Prijono135290d2011-03-17 11:33:34 +00001301 return PJMEDIA_CODEC_EFAILED;
Benny Prijonoc45d9512010-12-10 11:04:30 +00001302 } else {
1303 output->size = err;
1304 }
1305
1306 return PJ_SUCCESS;
1307}
1308
1309/*
1310 * Decode frame.
1311 */
1312static pj_status_t ffmpeg_codec_decode( pjmedia_vid_codec *codec,
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001313 const pjmedia_frame *input,
Benny Prijonoc45d9512010-12-10 11:04:30 +00001314 unsigned output_buf_len,
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001315 pjmedia_frame *output)
Benny Prijonoc45d9512010-12-10 11:04:30 +00001316{
1317 ffmpeg_private *ff = (ffmpeg_private*)codec->codec_data;
1318 AVFrame avframe;
1319 AVPacket avpacket;
1320 int err, got_picture;
1321
1322 /* Check if decoder has been opened */
1323 PJ_ASSERT_RETURN(ff->dec_ctx, PJ_EINVALIDOP);
1324
Nanang Izzuddin98610702011-03-01 17:40:17 +00001325 /* Reset output frame bit info */
1326 output->bit_info = 0;
1327
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001328 /* Validate output buffer size */
Nanang Izzuddin4ab5aac2011-05-10 11:38:27 +00001329 // Do this validation later after getting decoding result, where the real
1330 // decoded size will be assured.
Nanang Izzuddinabaaffa2011-05-10 11:44:03 +00001331 //if (ff->dec_vafp.framebytes > output_buf_len)
1332 //return PJ_ETOOSMALL;
Benny Prijonoc45d9512010-12-10 11:04:30 +00001333
1334 /* Init frame to receive the decoded data, the ffmpeg codec context will
1335 * automatically provide the decoded buffer (single buffer used for the
1336 * whole decoding session, and seems to be freed when the codec context
1337 * closed).
1338 */
1339 avcodec_get_frame_defaults(&avframe);
1340
1341 /* Init packet, the container of the encoded data */
1342 av_init_packet(&avpacket);
1343 avpacket.data = (pj_uint8_t*)input->buf;
1344 avpacket.size = input->size;
1345
1346 /* ffmpeg warns:
1347 * - input buffer padding, at least FF_INPUT_BUFFER_PADDING_SIZE
1348 * - null terminated
1349 * Normally, encoded buffer is allocated more than needed, so lets just
1350 * bzero the input buffer end/pad, hope it will be just fine.
1351 */
1352 pj_bzero(avpacket.data+avpacket.size, FF_INPUT_BUFFER_PADDING_SIZE);
1353
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001354 output->bit_info = 0;
Benny Prijono135290d2011-03-17 11:33:34 +00001355 output->timestamp = input->timestamp;
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001356
Benny Prijono643a9012011-07-12 23:16:27 +00001357#if LIBAVCODEC_VERSION_MAJOR > 52 || \
1358 (LIBAVCODEC_VERSION_MAJOR >= 52 && LIBAVCODEC_VERSION_MINOR >= 72)
Nanang Izzuddind91af572011-03-31 17:29:54 +00001359 //avpacket.flags = AV_PKT_FLAG_KEY;
Benny Prijonoc45d9512010-12-10 11:04:30 +00001360#else
1361 avpacket.flags = 0;
1362#endif
1363
Benny Prijono643a9012011-07-12 23:16:27 +00001364#if LIBAVCODEC_VERSION_MAJOR > 52 || \
1365 (LIBAVCODEC_VERSION_MAJOR >= 52 && LIBAVCODEC_VERSION_MINOR >= 72)
Benny Prijonoc45d9512010-12-10 11:04:30 +00001366 err = avcodec_decode_video2(ff->dec_ctx, &avframe,
1367 &got_picture, &avpacket);
1368#else
1369 err = avcodec_decode_video(ff->dec_ctx, &avframe,
1370 &got_picture, avpacket.data, avpacket.size);
1371#endif
1372 if (err < 0) {
Benny Prijono135290d2011-03-17 11:33:34 +00001373 output->type = PJMEDIA_FRAME_TYPE_NONE;
1374 output->size = 0;
Benny Prijonoc45d9512010-12-10 11:04:30 +00001375 print_ffmpeg_err(err);
Benny Prijono135290d2011-03-17 11:33:34 +00001376 return PJMEDIA_CODEC_EFAILED;
Benny Prijonoc45d9512010-12-10 11:04:30 +00001377 } else if (got_picture) {
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001378 pjmedia_video_apply_fmt_param *vafp = &ff->dec_vafp;
Benny Prijonoc45d9512010-12-10 11:04:30 +00001379 pj_uint8_t *q = (pj_uint8_t*)output->buf;
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001380 unsigned i;
Benny Prijonoc45d9512010-12-10 11:04:30 +00001381
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001382 /* Decoder output format is set by libavcodec, in case it is different
1383 * to the configured param.
1384 */
1385 if (ff->dec_ctx->pix_fmt != ff->expected_dec_fmt ||
Benny Prijono63572992011-04-13 18:06:21 +00001386 ff->dec_ctx->width != (int)vafp->size.w ||
1387 ff->dec_ctx->height != (int)vafp->size.h)
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001388 {
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001389 pjmedia_format_id new_fmt_id;
1390 pj_status_t status;
1391
1392 /* Get current raw format id from ffmpeg decoder context */
1393 status = PixelFormat_to_pjmedia_format_id(ff->dec_ctx->pix_fmt,
1394 &new_fmt_id);
1395 if (status != PJ_SUCCESS)
1396 return status;
1397
1398 /* Update decoder format in param */
1399 ff->param.dec_fmt.id = new_fmt_id;
Benny Prijono63572992011-04-13 18:06:21 +00001400 ff->param.dec_fmt.det.vid.size.w = ff->dec_ctx->width;
1401 ff->param.dec_fmt.det.vid.size.h = ff->dec_ctx->height;
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001402
1403 /* Re-init format info and apply-param of decoder */
1404 ff->dec_vfi = pjmedia_get_video_format_info(NULL, ff->param.dec_fmt.id);
1405 if (!ff->dec_vfi)
Benny Prijono135290d2011-03-17 11:33:34 +00001406 return PJ_ENOTSUP;
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001407 pj_bzero(&ff->dec_vafp, sizeof(ff->dec_vafp));
1408 ff->dec_vafp.size = ff->param.dec_fmt.det.vid.size;
1409 ff->dec_vafp.buffer = NULL;
1410 status = (*ff->dec_vfi->apply_fmt)(ff->dec_vfi, &ff->dec_vafp);
1411 if (status != PJ_SUCCESS)
1412 return status;
1413
Benny Prijonod4b5e872011-07-12 09:08:56 +00001414 /* Broadcast event */
1415 if (pjmedia_event_publisher_has_sub(&codec->epub)) {
1416 pjmedia_event event;
1417
1418 pjmedia_event_init(&event, PJMEDIA_EVENT_FMT_CHANGED,
1419 &input->timestamp, &codec->epub);
1420 event.data.fmt_changed.dir = PJMEDIA_DIR_DECODING;
1421 pj_memcpy(&event.data.fmt_changed.new_fmt, &ff->param.dec_fmt,
1422 sizeof(ff->param.dec_fmt));
1423 pjmedia_event_publish(&codec->epub, &event);
1424 }
Nanang Izzuddin98610702011-03-01 17:40:17 +00001425 }
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001426
Nanang Izzuddin4ab5aac2011-05-10 11:38:27 +00001427 /* Check provided buffer size */
Benny Prijono63572992011-04-13 18:06:21 +00001428 if (vafp->framebytes > output_buf_len)
1429 return PJ_ETOOSMALL;
1430
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001431 /* Get the decoded data */
1432 for (i = 0; i < ff->dec_vfi->plane_cnt; ++i) {
1433 pj_uint8_t *p = avframe.data[i];
1434
1435 /* The decoded data may contain padding */
1436 if (avframe.linesize[i]!=vafp->strides[i]) {
1437 /* Padding exists, copy line by line */
1438 pj_uint8_t *q_end;
1439
1440 q_end = q+vafp->plane_bytes[i];
1441 while(q < q_end) {
1442 pj_memcpy(q, p, vafp->strides[i]);
1443 q += vafp->strides[i];
1444 p += avframe.linesize[i];
1445 }
1446 } else {
1447 /* No padding, copy the whole plane */
1448 pj_memcpy(q, p, vafp->plane_bytes[i]);
1449 q += vafp->plane_bytes[i];
1450 }
1451 }
1452
Benny Prijono135290d2011-03-17 11:33:34 +00001453 output->type = PJMEDIA_FRAME_TYPE_VIDEO;
Benny Prijonoc45d9512010-12-10 11:04:30 +00001454 output->size = vafp->framebytes;
Benny Prijono2ba6d272011-07-12 10:54:56 +00001455
1456 /* Check if we got key frame */
1457 if (avframe.key_frame && pjmedia_event_publisher_has_sub(&codec->epub))
1458 {
1459 pjmedia_event event;
1460
1461 pjmedia_event_init(&event, PJMEDIA_EVENT_KEY_FRAME_FOUND,
1462 &output->timestamp, &codec->epub);
1463 pjmedia_event_publish(&codec->epub, &event);
1464 }
Benny Prijonoc45d9512010-12-10 11:04:30 +00001465 } else {
Benny Prijono135290d2011-03-17 11:33:34 +00001466 output->type = PJMEDIA_FRAME_TYPE_NONE;
1467 output->size = 0;
Benny Prijonoc45d9512010-12-10 11:04:30 +00001468 }
Benny Prijono135290d2011-03-17 11:33:34 +00001469
Benny Prijonoc45d9512010-12-10 11:04:30 +00001470 return PJ_SUCCESS;
1471}
1472
1473/*
1474 * Recover lost frame.
1475 */
1476static pj_status_t ffmpeg_codec_recover( pjmedia_vid_codec *codec,
1477 unsigned output_buf_len,
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001478 pjmedia_frame *output)
Benny Prijonoc45d9512010-12-10 11:04:30 +00001479{
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001480 PJ_UNUSED_ARG(codec);
Benny Prijonoc45d9512010-12-10 11:04:30 +00001481 PJ_UNUSED_ARG(output_buf_len);
1482 PJ_UNUSED_ARG(output);
Benny Prijonoc45d9512010-12-10 11:04:30 +00001483
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001484 return PJ_ENOTSUP;
Benny Prijonoc45d9512010-12-10 11:04:30 +00001485}
1486
1487#ifdef _MSC_VER
1488# pragma comment( lib, "avcodec.lib")
Benny Prijonoc45d9512010-12-10 11:04:30 +00001489#endif
1490
1491#endif /* PJMEDIA_HAS_FFMPEG_CODEC */
1492