blob: 8f1bcd04d3ff9944fe73223b7a698bd9347f0d3c [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
543 if (c->type != CODEC_TYPE_VIDEO)
544 continue;
545
546 /* Video encoder and decoder are usually implemented in separate
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000547 * AVCodec instances. While the codec attributes (e.g: raw formats,
548 * supported fps) are in the encoder.
Benny Prijonoc45d9512010-12-10 11:04:30 +0000549 */
550
Nanang Izzuddin235e1b42011-02-28 18:59:47 +0000551 //PJ_LOG(3, (THIS_FILE, "%s", c->name));
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000552 status = CodecID_to_pjmedia_format_id(c->id, &fmt_id);
553 /* Skip if format ID is unknown */
554 if (status != PJ_SUCCESS)
555 continue;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000556
Nanang Izzuddin235e1b42011-02-28 18:59:47 +0000557 codec_info_idx = find_codec_idx_by_fmt_id(fmt_id);
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000558 /* Skip if codec is unwanted by this wrapper (not listed in
559 * the codec info array)
560 */
561 if (codec_info_idx < 0)
562 continue;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000563
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000564 desc = &codec_desc[codec_info_idx];
Benny Prijonoc45d9512010-12-10 11:04:30 +0000565
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000566 /* Skip duplicated codec implementation */
567 if ((c->encode && (desc->info.dir & PJMEDIA_DIR_ENCODING)) ||
568 (c->decode && (desc->info.dir & PJMEDIA_DIR_DECODING)))
569 {
570 continue;
571 }
Benny Prijonoc45d9512010-12-10 11:04:30 +0000572
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000573 /* Get raw/decoded format ids in the encoder */
574 if (c->pix_fmts && c->encode) {
575 pjmedia_format_id raw_fmt[PJMEDIA_VID_CODEC_MAX_DEC_FMT_CNT];
576 unsigned raw_fmt_cnt = 0;
577 unsigned raw_fmt_cnt_should_be = 0;
578 const enum PixelFormat *p = c->pix_fmts;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000579
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000580 for(;(p && *p != -1) &&
581 (raw_fmt_cnt < PJMEDIA_VID_CODEC_MAX_DEC_FMT_CNT);
582 ++p)
583 {
584 pjmedia_format_id fmt_id;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000585
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000586 raw_fmt_cnt_should_be++;
587 status = PixelFormat_to_pjmedia_format_id(*p, &fmt_id);
588 if (status != PJ_SUCCESS) {
589 PJ_LOG(6, (THIS_FILE, "Unrecognized ffmpeg pixel "
590 "format %d", *p));
591 continue;
592 }
593 raw_fmt[raw_fmt_cnt++] = fmt_id;
594 }
Benny Prijonoc45d9512010-12-10 11:04:30 +0000595
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000596 if (raw_fmt_cnt == 0) {
597 PJ_LOG(5, (THIS_FILE, "No recognized raw format "
598 "for codec [%s/%s], codec ignored",
599 c->name, c->long_name));
600 /* Skip this encoder */
601 continue;
602 }
Benny Prijonoc45d9512010-12-10 11:04:30 +0000603
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000604 if (raw_fmt_cnt < raw_fmt_cnt_should_be) {
605 PJ_LOG(6, (THIS_FILE, "Codec [%s/%s] have %d raw formats, "
606 "recognized only %d raw formats",
607 c->name, c->long_name,
608 raw_fmt_cnt_should_be, raw_fmt_cnt));
609 }
Benny Prijonoc45d9512010-12-10 11:04:30 +0000610
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000611 desc->info.dec_fmt_id_cnt = raw_fmt_cnt;
612 pj_memcpy(desc->info.dec_fmt_id, raw_fmt,
613 sizeof(raw_fmt[0])*raw_fmt_cnt);
614 }
615
616 /* Get supported framerates */
617 if (c->supported_framerates) {
618 const AVRational *fr = c->supported_framerates;
619 while ((fr->num != 0 || fr->den != 0) &&
620 desc->info.fps_cnt < PJMEDIA_VID_CODEC_MAX_FPS_CNT)
621 {
622 desc->info.fps[desc->info.fps_cnt].num = fr->num;
623 desc->info.fps[desc->info.fps_cnt].denum = fr->den;
624 ++desc->info.fps_cnt;
625 ++fr;
626 }
627 }
628
629 /* Get ffmpeg encoder instance */
630 if (c->encode && !desc->enc) {
631 desc->info.dir |= PJMEDIA_DIR_ENCODING;
632 desc->enc = c;
633 }
634
635 /* Get ffmpeg decoder instance */
636 if (c->decode && !desc->dec) {
637 desc->info.dir |= PJMEDIA_DIR_DECODING;
638 desc->dec = c;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000639 }
640
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000641 /* Enable this codec when any ffmpeg codec instance are recognized
642 * and the supported raw formats info has been collected.
643 */
644 if ((desc->dec || desc->enc) && desc->info.dec_fmt_id_cnt)
645 {
646 desc->enabled = PJ_TRUE;
647 }
Benny Prijonoc45d9512010-12-10 11:04:30 +0000648
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000649 /* Normalize default value of clock rate */
650 if (desc->info.clock_rate == 0)
651 desc->info.clock_rate = 90000;
Benny Prijono135290d2011-03-17 11:33:34 +0000652
653 /* Set RTP packetization support flag in the codec info */
654 desc->info.has_rtp_pack = (desc->packetize != NULL) &&
655 (desc->unpacketize != NULL);
Benny Prijonoc45d9512010-12-10 11:04:30 +0000656 }
657
Nanang Izzuddin56b2ce42011-04-06 13:55:01 +0000658 /* Review all codecs for applying base format, registering format match for
659 * SDP negotiation, etc.
660 */
Nanang Izzuddin235e1b42011-02-28 18:59:47 +0000661 for (i = 0; i < PJ_ARRAY_SIZE(codec_desc); ++i) {
662 ffmpeg_codec_desc *desc = &codec_desc[i];
663
Nanang Izzuddin56b2ce42011-04-06 13:55:01 +0000664 /* Init encoder/decoder description from base format */
Nanang Izzuddin235e1b42011-02-28 18:59:47 +0000665 if (desc->base_fmt_id && (!desc->dec || !desc->enc)) {
666 ffmpeg_codec_desc *base_desc = NULL;
667 int base_desc_idx;
668 pjmedia_dir copied_dir = PJMEDIA_DIR_NONE;
669
670 base_desc_idx = find_codec_idx_by_fmt_id(desc->base_fmt_id);
671 if (base_desc_idx != -1)
672 base_desc = &codec_desc[base_desc_idx];
673 if (!base_desc || !base_desc->enabled)
674 continue;
675
676 /* Copy description from base codec */
677 if (!desc->info.dec_fmt_id_cnt) {
678 desc->info.dec_fmt_id_cnt = base_desc->info.dec_fmt_id_cnt;
679 pj_memcpy(desc->info.dec_fmt_id, base_desc->info.dec_fmt_id,
680 sizeof(pjmedia_format_id)*desc->info.dec_fmt_id_cnt);
681 }
682 if (!desc->info.fps_cnt) {
683 desc->info.fps_cnt = base_desc->info.fps_cnt;
684 pj_memcpy(desc->info.fps, base_desc->info.fps,
685 sizeof(desc->info.fps[0])*desc->info.fps_cnt);
686 }
687 if (!desc->info.clock_rate) {
688 desc->info.clock_rate = base_desc->info.clock_rate;
689 }
690 if (!desc->dec && base_desc->dec) {
691 copied_dir |= PJMEDIA_DIR_DECODING;
692 desc->dec = base_desc->dec;
693 }
694 if (!desc->enc && base_desc->enc) {
695 copied_dir |= PJMEDIA_DIR_ENCODING;
696 desc->enc = base_desc->enc;
697 }
698
699 desc->info.dir |= copied_dir;
700 desc->enabled = (desc->info.dir != PJMEDIA_DIR_NONE);
Nanang Izzuddin56b2ce42011-04-06 13:55:01 +0000701 desc->info.has_rtp_pack = (desc->packetize != NULL) &&
702 (desc->unpacketize != NULL);
Nanang Izzuddin235e1b42011-02-28 18:59:47 +0000703
704 if (copied_dir != PJMEDIA_DIR_NONE) {
705 const char *dir_name[] = {NULL, "encoder", "decoder", "codec"};
706 PJ_LOG(5, (THIS_FILE, "The %.*s %s is using base codec (%.*s)",
707 desc->info.encoding_name.slen,
708 desc->info.encoding_name.ptr,
709 dir_name[copied_dir],
710 base_desc->info.encoding_name.slen,
711 base_desc->info.encoding_name.ptr));
712 }
713 }
Nanang Izzuddin56b2ce42011-04-06 13:55:01 +0000714
715 /* Registering format match for SDP negotiation */
716 if (desc->sdp_fmt_match) {
717 status = pjmedia_sdp_neg_register_fmt_match_cb(
718 &desc->info.encoding_name,
719 desc->sdp_fmt_match);
720 pj_assert(status == PJ_SUCCESS);
721 }
Nanang Izzuddin235e1b42011-02-28 18:59:47 +0000722 }
723
Benny Prijonoc45d9512010-12-10 11:04:30 +0000724 /* Register codec factory to codec manager. */
725 status = pjmedia_vid_codec_mgr_register_factory(mgr,
726 &ffmpeg_factory.base);
727 if (status != PJ_SUCCESS)
728 goto on_error;
729
730 ffmpeg_factory.pool = pool;
731
732 /* Done. */
733 return PJ_SUCCESS;
734
735on_error:
736 pj_pool_release(pool);
737 return status;
738}
739
740/*
741 * Unregister FFMPEG codecs factory from pjmedia endpoint.
742 */
743PJ_DEF(pj_status_t) pjmedia_codec_ffmpeg_deinit(void)
744{
745 pj_status_t status = PJ_SUCCESS;
746
747 if (ffmpeg_factory.pool == NULL) {
748 /* Already deinitialized */
749 return PJ_SUCCESS;
750 }
751
752 pj_mutex_lock(ffmpeg_factory.mutex);
753
754 /* Unregister FFMPEG codecs factory. */
755 status = pjmedia_vid_codec_mgr_unregister_factory(ffmpeg_factory.mgr,
756 &ffmpeg_factory.base);
757
758 /* Destroy mutex. */
759 pj_mutex_destroy(ffmpeg_factory.mutex);
760
761 /* Destroy pool. */
762 pj_pool_release(ffmpeg_factory.pool);
763 ffmpeg_factory.pool = NULL;
764
765 return status;
766}
767
768
Benny Prijonoc45d9512010-12-10 11:04:30 +0000769/*
770 * Check if factory can allocate the specified codec.
771 */
772static pj_status_t ffmpeg_test_alloc( pjmedia_vid_codec_factory *factory,
773 const pjmedia_vid_codec_info *info )
774{
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000775 const ffmpeg_codec_desc *desc;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000776
777 PJ_ASSERT_RETURN(factory==&ffmpeg_factory.base, PJ_EINVAL);
778 PJ_ASSERT_RETURN(info, PJ_EINVAL);
779
Nanang Izzuddin235e1b42011-02-28 18:59:47 +0000780 desc = find_codec_desc_by_info(info);
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000781 if (!desc) {
Benny Prijonoc45d9512010-12-10 11:04:30 +0000782 return PJMEDIA_CODEC_EUNSUP;
783 }
784
785 return PJ_SUCCESS;
786}
787
788/*
789 * Generate default attribute.
790 */
791static pj_status_t ffmpeg_default_attr( pjmedia_vid_codec_factory *factory,
792 const pjmedia_vid_codec_info *info,
793 pjmedia_vid_codec_param *attr )
794{
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000795 const ffmpeg_codec_desc *desc;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000796
797 PJ_ASSERT_RETURN(factory==&ffmpeg_factory.base, PJ_EINVAL);
798 PJ_ASSERT_RETURN(info && attr, PJ_EINVAL);
799
Nanang Izzuddin235e1b42011-02-28 18:59:47 +0000800 desc = find_codec_desc_by_info(info);
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000801 if (!desc) {
Benny Prijonoc45d9512010-12-10 11:04:30 +0000802 return PJMEDIA_CODEC_EUNSUP;
803 }
804
805 pj_bzero(attr, sizeof(pjmedia_vid_codec_param));
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000806
807 /* Direction */
808 attr->dir = desc->info.dir;
809
810 /* Encoded format */
811 pjmedia_format_init_video(&attr->enc_fmt, desc->info.fmt_id,
812 352, 288, 30000, 1001);
813
814 /* Decoded format */
815 pjmedia_format_init_video(&attr->dec_fmt, desc->info.dec_fmt_id[0],
Nanang Izzuddind00d3f22011-04-11 20:04:27 +0000816 //352, 288, 30000, 1001);
817 720, 576, 30000, 1001);
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000818
819 /* Decoding fmtp */
820 attr->dec_fmtp = desc->dec_fmtp;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000821
Nanang Izzuddin678b2f82011-03-02 08:37:31 +0000822 /* Bitrate */
823 attr->enc_fmt.det.vid.avg_bps = desc->avg_bps;
824 attr->enc_fmt.det.vid.max_bps = desc->max_bps;
825
Nanang Izzuddind91af572011-03-31 17:29:54 +0000826 /* MTU */
827 attr->enc_mtu = PJMEDIA_MAX_MTU;
828
Benny Prijonoc45d9512010-12-10 11:04:30 +0000829 return PJ_SUCCESS;
830}
831
832/*
833 * Enum codecs supported by this factory.
834 */
835static pj_status_t ffmpeg_enum_codecs( pjmedia_vid_codec_factory *factory,
836 unsigned *count,
837 pjmedia_vid_codec_info codecs[])
838{
Nanang Izzuddin235e1b42011-02-28 18:59:47 +0000839 unsigned i, max_cnt;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000840
841 PJ_ASSERT_RETURN(codecs && *count > 0, PJ_EINVAL);
842 PJ_ASSERT_RETURN(factory == &ffmpeg_factory.base, PJ_EINVAL);
843
Nanang Izzuddin235e1b42011-02-28 18:59:47 +0000844 max_cnt = PJ_MIN(*count, PJ_ARRAY_SIZE(codec_desc));
845 *count = 0;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000846
Nanang Izzuddin235e1b42011-02-28 18:59:47 +0000847 for (i=0; i<max_cnt; ++i) {
848 if (codec_desc[i].enabled) {
849 pj_memcpy(&codecs[*count], &codec_desc[i].info,
850 sizeof(pjmedia_vid_codec_info));
851 (*count)++;
852 }
Benny Prijonoc45d9512010-12-10 11:04:30 +0000853 }
Benny Prijonoc45d9512010-12-10 11:04:30 +0000854
855 return PJ_SUCCESS;
856}
857
858/*
859 * Allocate a new codec instance.
860 */
861static pj_status_t ffmpeg_alloc_codec( pjmedia_vid_codec_factory *factory,
862 const pjmedia_vid_codec_info *info,
863 pjmedia_vid_codec **p_codec)
864{
865 ffmpeg_private *ff;
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000866 const ffmpeg_codec_desc *desc;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000867 pjmedia_vid_codec *codec;
868 pj_pool_t *pool = NULL;
869 pj_status_t status = PJ_SUCCESS;
870
871 PJ_ASSERT_RETURN(factory && info && p_codec, PJ_EINVAL);
872 PJ_ASSERT_RETURN(factory == &ffmpeg_factory.base, PJ_EINVAL);
873
Nanang Izzuddin235e1b42011-02-28 18:59:47 +0000874 desc = find_codec_desc_by_info(info);
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000875 if (!desc) {
Benny Prijonoc45d9512010-12-10 11:04:30 +0000876 return PJMEDIA_CODEC_EUNSUP;
877 }
878
879 /* Create pool for codec instance */
880 pool = pj_pool_create(ffmpeg_factory.pf, "ffmpeg codec", 512, 512, NULL);
881 codec = PJ_POOL_ZALLOC_T(pool, pjmedia_vid_codec);
882 if (!codec) {
883 status = PJ_ENOMEM;
884 goto on_error;
885 }
886 codec->op = &ffmpeg_op;
887 codec->factory = factory;
888 ff = PJ_POOL_ZALLOC_T(pool, ffmpeg_private);
889 if (!ff) {
890 status = PJ_ENOMEM;
891 goto on_error;
892 }
893 codec->codec_data = ff;
894 ff->pool = pool;
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000895 ff->enc = desc->enc;
896 ff->dec = desc->dec;
897 ff->desc = desc;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000898
899 *p_codec = codec;
900 return PJ_SUCCESS;
901
902on_error:
903 if (pool)
904 pj_pool_release(pool);
905 return status;
906}
907
908/*
909 * Free codec.
910 */
911static pj_status_t ffmpeg_dealloc_codec( pjmedia_vid_codec_factory *factory,
912 pjmedia_vid_codec *codec )
913{
914 ffmpeg_private *ff;
915 pj_pool_t *pool;
916
917 PJ_ASSERT_RETURN(factory && codec, PJ_EINVAL);
918 PJ_ASSERT_RETURN(factory == &ffmpeg_factory.base, PJ_EINVAL);
919
920 /* Close codec, if it's not closed. */
921 ff = (ffmpeg_private*) codec->codec_data;
922 pool = ff->pool;
923 codec->codec_data = NULL;
924 pj_pool_release(pool);
925
926 return PJ_SUCCESS;
927}
928
929/*
930 * Init codec.
931 */
932static pj_status_t ffmpeg_codec_init( pjmedia_vid_codec *codec,
933 pj_pool_t *pool )
934{
935 PJ_UNUSED_ARG(codec);
936 PJ_UNUSED_ARG(pool);
937 return PJ_SUCCESS;
938}
939
940static void print_ffmpeg_err(int err)
941{
942#if LIBAVCODEC_VERSION_MAJOR >= 52 && LIBAVCODEC_VERSION_MINOR >= 72
943 char errbuf[512];
944 if (av_strerror(err, errbuf, sizeof(errbuf)) >= 0)
Benny Prijono63572992011-04-13 18:06:21 +0000945 PJ_LOG(5, (THIS_FILE, "ffmpeg err %d: %s", err, errbuf));
Benny Prijonoc45d9512010-12-10 11:04:30 +0000946#else
Benny Prijono63572992011-04-13 18:06:21 +0000947 PJ_LOG(5, (THIS_FILE, "ffmpeg err %d", err));
Benny Prijonoc45d9512010-12-10 11:04:30 +0000948#endif
949
950}
951
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000952static enum PixelFormat dec_get_format(struct AVCodecContext *s,
Nanang Izzuddind91af572011-03-31 17:29:54 +0000953 const enum PixelFormat * fmt)
Benny Prijonoc45d9512010-12-10 11:04:30 +0000954{
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000955 ffmpeg_private *ff = (ffmpeg_private*)s->opaque;
956 enum PixelFormat def_fmt = *fmt;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000957
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000958 while (*fmt != -1) {
959 if (*fmt == ff->expected_dec_fmt)
960 return *fmt;
961 ++fmt;
962 }
Benny Prijonoc45d9512010-12-10 11:04:30 +0000963
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000964 pj_assert(!"Inconsistency in supported formats");
965 return def_fmt;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000966}
967
Benny Prijonoc45d9512010-12-10 11:04:30 +0000968
969static pj_status_t open_ffmpeg_codec(ffmpeg_private *ff,
970 pj_mutex_t *ff_mutex)
971{
972 enum PixelFormat pix_fmt;
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000973 pjmedia_video_format_detail *vfd;
Nanang Izzuddind91af572011-03-31 17:29:54 +0000974 pj_bool_t enc_opened = PJ_FALSE, dec_opened = PJ_FALSE;
975 pj_status_t status;
Benny Prijonoc45d9512010-12-10 11:04:30 +0000976
Nanang Izzuddind91af572011-03-31 17:29:54 +0000977 /* Get decoded pixel format */
Benny Prijonoc45d9512010-12-10 11:04:30 +0000978 status = pjmedia_format_id_to_PixelFormat(ff->param.dec_fmt.id,
979 &pix_fmt);
980 if (status != PJ_SUCCESS)
981 return status;
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +0000982 ff->expected_dec_fmt = pix_fmt;
983
Nanang Izzuddind91af572011-03-31 17:29:54 +0000984 /* Get video format detail for shortcut access to encoded format */
985 vfd = pjmedia_format_get_video_format_detail(&ff->param.enc_fmt,
986 PJ_TRUE);
987
988 /* Allocate ffmpeg codec context */
989 if (ff->param.dir & PJMEDIA_DIR_ENCODING) {
990 ff->enc_ctx = avcodec_alloc_context();
991 if (ff->enc_ctx == NULL)
992 goto on_error;
993 }
994 if (ff->param.dir & PJMEDIA_DIR_DECODING) {
995 ff->dec_ctx = avcodec_alloc_context();
996 if (ff->dec_ctx == NULL)
997 goto on_error;
998 }
999
1000 /* Let the codec apply specific settings before the codec opened */
1001 if (ff->desc->preopen) {
1002 status = (*ff->desc->preopen)(ff);
1003 if (status != PJ_SUCCESS)
1004 goto on_error;
1005 }
1006
1007 if (ff->param.dir & PJMEDIA_DIR_ENCODING) {
1008 AVCodecContext *ctx = ff->enc_ctx;
Benny Prijonoc45d9512010-12-10 11:04:30 +00001009 int err;
1010
Nanang Izzuddind91af572011-03-31 17:29:54 +00001011 /* Init common settings */
Benny Prijonoc45d9512010-12-10 11:04:30 +00001012 ctx->pix_fmt = pix_fmt;
Nanang Izzuddind91af572011-03-31 17:29:54 +00001013 ctx->width = vfd->size.w;
1014 ctx->height = vfd->size.h;
1015 ctx->time_base.num = vfd->fps.denum;
1016 ctx->time_base.den = vfd->fps.num;
1017 if (vfd->avg_bps) {
1018 ctx->bit_rate = vfd->avg_bps;
1019 if (vfd->max_bps > vfd->avg_bps)
1020 ctx->bit_rate_tolerance = vfd->max_bps - vfd->avg_bps;
1021 }
1022 ctx->strict_std_compliance = FF_COMPLIANCE_STRICT;
Benny Prijonoc45d9512010-12-10 11:04:30 +00001023 ctx->workaround_bugs = FF_BUG_AUTODETECT;
1024 ctx->opaque = ff;
1025
Nanang Izzuddin2636c142011-04-01 07:12:59 +00001026 /* Set no delay, note that this may cause some codec functionals
1027 * not working (e.g: rate control).
1028 */
Benny Prijonoea508b42011-04-06 06:58:38 +00001029#if LIBAVCODEC_VERSION_MAJOR >= 52 && LIBAVCODEC_VERSION_MINOR >= 113
Nanang Izzuddin2636c142011-04-01 07:12:59 +00001030 ctx->rc_lookahead = 0;
Benny Prijonoea508b42011-04-06 06:58:38 +00001031#endif
Nanang Izzuddin2636c142011-04-01 07:12:59 +00001032
Nanang Izzuddind91af572011-03-31 17:29:54 +00001033 /* Open ffmpeg codec */
Benny Prijonoc45d9512010-12-10 11:04:30 +00001034 pj_mutex_lock(ff_mutex);
Nanang Izzuddind91af572011-03-31 17:29:54 +00001035 err = avcodec_open(ctx, ff->enc);
Benny Prijonoc45d9512010-12-10 11:04:30 +00001036 pj_mutex_unlock(ff_mutex);
1037 if (err < 0) {
1038 print_ffmpeg_err(err);
Nanang Izzuddind91af572011-03-31 17:29:54 +00001039 status = PJMEDIA_CODEC_EFAILED;
1040 goto on_error;
Benny Prijonoc45d9512010-12-10 11:04:30 +00001041 }
Nanang Izzuddind91af572011-03-31 17:29:54 +00001042 enc_opened = PJ_TRUE;
Benny Prijonoc45d9512010-12-10 11:04:30 +00001043 }
Nanang Izzuddind91af572011-03-31 17:29:54 +00001044
1045 if (ff->param.dir & PJMEDIA_DIR_DECODING) {
1046 AVCodecContext *ctx = ff->dec_ctx;
1047 int err;
1048
1049 /* Init common settings */
1050 /* Width/height may be overriden by ffmpeg after first decoding. */
1051 ctx->width = ctx->coded_width = ff->param.dec_fmt.det.vid.size.w;
1052 ctx->height = ctx->coded_height = ff->param.dec_fmt.det.vid.size.h;
1053 ctx->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
1054 ctx->workaround_bugs = FF_BUG_AUTODETECT;
1055 ctx->opaque = ff;
1056 ctx->get_format = &dec_get_format;
1057
1058 /* Open ffmpeg codec */
1059 pj_mutex_lock(ff_mutex);
1060 err = avcodec_open(ctx, ff->dec);
1061 pj_mutex_unlock(ff_mutex);
1062 if (err < 0) {
1063 print_ffmpeg_err(err);
1064 status = PJMEDIA_CODEC_EFAILED;
1065 goto on_error;
1066 }
1067 dec_opened = PJ_TRUE;
1068 }
1069
1070 /* Let the codec apply specific settings after the codec opened */
1071 if (ff->desc->postopen) {
1072 status = (*ff->desc->postopen)(ff);
1073 if (status != PJ_SUCCESS)
1074 goto on_error;
1075 }
1076
Benny Prijonoc45d9512010-12-10 11:04:30 +00001077 return PJ_SUCCESS;
Nanang Izzuddind91af572011-03-31 17:29:54 +00001078
1079on_error:
1080 if (ff->enc_ctx) {
1081 if (enc_opened)
1082 avcodec_close(ff->enc_ctx);
1083 av_free(ff->enc_ctx);
1084 ff->enc_ctx = NULL;
1085 }
1086 if (ff->dec_ctx) {
1087 if (dec_opened)
1088 avcodec_close(ff->dec_ctx);
1089 av_free(ff->dec_ctx);
1090 ff->dec_ctx = NULL;
1091 }
1092 return status;
Benny Prijonoc45d9512010-12-10 11:04:30 +00001093}
1094
1095/*
1096 * Open codec.
1097 */
1098static pj_status_t ffmpeg_codec_open( pjmedia_vid_codec *codec,
1099 pjmedia_vid_codec_param *attr )
1100{
1101 ffmpeg_private *ff;
1102 pj_status_t status;
1103 pj_mutex_t *ff_mutex;
1104
1105 PJ_ASSERT_RETURN(codec && attr, PJ_EINVAL);
1106 ff = (ffmpeg_private*)codec->codec_data;
1107
Benny Prijonoc45d9512010-12-10 11:04:30 +00001108 pj_memcpy(&ff->param, attr, sizeof(*attr));
1109
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001110 /* Open the codec */
Benny Prijonoc45d9512010-12-10 11:04:30 +00001111 ff_mutex = ((struct ffmpeg_factory*)codec->factory)->mutex;
1112 status = open_ffmpeg_codec(ff, ff_mutex);
1113 if (status != PJ_SUCCESS)
1114 goto on_error;
1115
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001116 /* Init format info and apply-param of decoder */
1117 ff->dec_vfi = pjmedia_get_video_format_info(NULL, ff->param.dec_fmt.id);
1118 if (!ff->dec_vfi) {
1119 status = PJ_EINVAL;
1120 goto on_error;
1121 }
1122 pj_bzero(&ff->dec_vafp, sizeof(ff->dec_vafp));
1123 ff->dec_vafp.size = ff->param.dec_fmt.det.vid.size;
1124 ff->dec_vafp.buffer = NULL;
1125 status = (*ff->dec_vfi->apply_fmt)(ff->dec_vfi, &ff->dec_vafp);
1126 if (status != PJ_SUCCESS) {
1127 goto on_error;
1128 }
1129
1130 /* Init format info and apply-param of encoder */
1131 ff->enc_vfi = pjmedia_get_video_format_info(NULL, ff->param.dec_fmt.id);
1132 if (!ff->enc_vfi) {
1133 status = PJ_EINVAL;
1134 goto on_error;
1135 }
1136 pj_bzero(&ff->enc_vafp, sizeof(ff->enc_vafp));
1137 ff->enc_vafp.size = ff->param.enc_fmt.det.vid.size;
1138 ff->enc_vafp.buffer = NULL;
1139 status = (*ff->enc_vfi->apply_fmt)(ff->enc_vfi, &ff->enc_vafp);
1140 if (status != PJ_SUCCESS) {
1141 goto on_error;
1142 }
1143
1144 /* Update codec attributes, e.g: encoding format may be changed by
1145 * SDP fmtp negotiation.
1146 */
1147 pj_memcpy(attr, &ff->param, sizeof(*attr));
1148
Benny Prijonoc45d9512010-12-10 11:04:30 +00001149 return PJ_SUCCESS;
1150
1151on_error:
1152 ffmpeg_codec_close(codec);
1153 return status;
1154}
1155
1156/*
1157 * Close codec.
1158 */
1159static pj_status_t ffmpeg_codec_close( pjmedia_vid_codec *codec )
1160{
1161 ffmpeg_private *ff;
1162 pj_mutex_t *ff_mutex;
1163
1164 PJ_ASSERT_RETURN(codec, PJ_EINVAL);
1165 ff = (ffmpeg_private*)codec->codec_data;
1166 ff_mutex = ((struct ffmpeg_factory*)codec->factory)->mutex;
1167
1168 pj_mutex_lock(ff_mutex);
1169 if (ff->enc_ctx) {
1170 avcodec_close(ff->enc_ctx);
1171 av_free(ff->enc_ctx);
1172 }
1173 if (ff->dec_ctx && ff->dec_ctx!=ff->enc_ctx) {
1174 avcodec_close(ff->dec_ctx);
1175 av_free(ff->dec_ctx);
1176 }
Benny Prijonoc45d9512010-12-10 11:04:30 +00001177 ff->enc_ctx = NULL;
1178 ff->dec_ctx = NULL;
Benny Prijonoc45d9512010-12-10 11:04:30 +00001179 pj_mutex_unlock(ff_mutex);
1180
1181 return PJ_SUCCESS;
1182}
1183
1184
1185/*
1186 * Modify codec settings.
1187 */
1188static pj_status_t ffmpeg_codec_modify( pjmedia_vid_codec *codec,
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001189 const pjmedia_vid_codec_param *attr)
Benny Prijonoc45d9512010-12-10 11:04:30 +00001190{
1191 ffmpeg_private *ff = (ffmpeg_private*)codec->codec_data;
1192
1193 PJ_UNUSED_ARG(attr);
1194 PJ_UNUSED_ARG(ff);
1195
1196 return PJ_ENOTSUP;
1197}
1198
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001199static pj_status_t ffmpeg_codec_get_param(pjmedia_vid_codec *codec,
1200 pjmedia_vid_codec_param *param)
1201{
1202 ffmpeg_private *ff;
1203
1204 PJ_ASSERT_RETURN(codec && param, PJ_EINVAL);
1205
1206 ff = (ffmpeg_private*)codec->codec_data;
1207 pj_memcpy(param, &ff->param, sizeof(*param));
1208
1209 return PJ_SUCCESS;
1210}
1211
1212
Benny Prijonoc45d9512010-12-10 11:04:30 +00001213static pj_status_t ffmpeg_packetize ( pjmedia_vid_codec *codec,
Nanang Izzuddind91af572011-03-31 17:29:54 +00001214 pj_uint8_t *bits,
1215 pj_size_t bits_len,
1216 unsigned *bits_pos,
Benny Prijonoc45d9512010-12-10 11:04:30 +00001217 const pj_uint8_t **payload,
1218 pj_size_t *payload_len)
1219{
1220 ffmpeg_private *ff = (ffmpeg_private*)codec->codec_data;
1221
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001222 if (ff->desc->packetize) {
Nanang Izzuddind91af572011-03-31 17:29:54 +00001223 return (*ff->desc->packetize)(ff, bits, bits_len, bits_pos,
1224 payload, payload_len);
Benny Prijonoc45d9512010-12-10 11:04:30 +00001225 }
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001226
1227 return PJ_ENOTSUP;
Benny Prijonoc45d9512010-12-10 11:04:30 +00001228}
1229
1230static pj_status_t ffmpeg_unpacketize(pjmedia_vid_codec *codec,
1231 const pj_uint8_t *payload,
1232 pj_size_t payload_len,
Nanang Izzuddind91af572011-03-31 17:29:54 +00001233 pj_uint8_t *bits,
1234 pj_size_t bits_len,
1235 unsigned *bits_pos)
Benny Prijonoc45d9512010-12-10 11:04:30 +00001236{
1237 ffmpeg_private *ff = (ffmpeg_private*)codec->codec_data;
1238
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001239 if (ff->desc->unpacketize) {
Nanang Izzuddind91af572011-03-31 17:29:54 +00001240 return (*ff->desc->unpacketize)(ff, payload, payload_len,
1241 bits, bits_len, bits_pos);
Benny Prijonoc45d9512010-12-10 11:04:30 +00001242 }
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001243
1244 return PJ_ENOTSUP;
Benny Prijonoc45d9512010-12-10 11:04:30 +00001245}
1246
Benny Prijonoc45d9512010-12-10 11:04:30 +00001247
1248/*
1249 * Encode frames.
1250 */
1251static pj_status_t ffmpeg_codec_encode( pjmedia_vid_codec *codec,
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001252 const pjmedia_frame *input,
Benny Prijonoc45d9512010-12-10 11:04:30 +00001253 unsigned output_buf_len,
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001254 pjmedia_frame *output)
Benny Prijonoc45d9512010-12-10 11:04:30 +00001255{
1256 ffmpeg_private *ff = (ffmpeg_private*)codec->codec_data;
1257 pj_uint8_t *p = (pj_uint8_t*)input->buf;
1258 AVFrame avframe;
1259 pj_uint8_t *out_buf = (pj_uint8_t*)output->buf;
1260 int out_buf_len = output_buf_len;
1261 int err;
Nanang Izzuddin5f8d5892011-04-12 18:24:19 +00001262 //AVRational src_timebase;
Nanang Izzuddinada41262011-03-22 09:43:24 +00001263 /* For some reasons (e.g: SSE/MMX usage), the avcodec_encode_video() must
1264 * have stack aligned to 16 bytes. Let's try to be safe by preparing the
1265 * 16-bytes aligned stack here, in case it's not managed by the ffmpeg.
1266 */
1267 PJ_ALIGN_DATA(pj_uint32_t i[4], 16);
Benny Prijonoc45d9512010-12-10 11:04:30 +00001268
Nanang Izzuddind91af572011-03-31 17:29:54 +00001269 if ((long)i & 0xF) {
1270 PJ_LOG(2,(THIS_FILE, "Stack alignment fails"));
1271 }
1272
Benny Prijonoc45d9512010-12-10 11:04:30 +00001273 /* Check if encoder has been opened */
1274 PJ_ASSERT_RETURN(ff->enc_ctx, PJ_EINVALIDOP);
1275
Benny Prijonoc45d9512010-12-10 11:04:30 +00001276 avcodec_get_frame_defaults(&avframe);
Nanang Izzuddind00d3f22011-04-11 20:04:27 +00001277
1278 // Let ffmpeg manage the timestamps
1279 /*
Nanang Izzuddind91af572011-03-31 17:29:54 +00001280 src_timebase.num = 1;
1281 src_timebase.den = ff->desc->info.clock_rate;
1282 avframe.pts = av_rescale_q(input->timestamp.u64, src_timebase,
1283 ff->enc_ctx->time_base);
Nanang Izzuddind00d3f22011-04-11 20:04:27 +00001284 */
Benny Prijonoc45d9512010-12-10 11:04:30 +00001285
Nanang Izzuddinada41262011-03-22 09:43:24 +00001286 for (i[0] = 0; i[0] < ff->enc_vfi->plane_cnt; ++i[0]) {
1287 avframe.data[i[0]] = p;
1288 avframe.linesize[i[0]] = ff->enc_vafp.strides[i[0]];
1289 p += ff->enc_vafp.plane_bytes[i[0]];
Benny Prijonoc45d9512010-12-10 11:04:30 +00001290 }
1291
Nanang Izzuddinada41262011-03-22 09:43:24 +00001292 err = avcodec_encode_video(ff->enc_ctx, out_buf, out_buf_len, &avframe);
Benny Prijonoc45d9512010-12-10 11:04:30 +00001293 if (err < 0) {
1294 print_ffmpeg_err(err);
Benny Prijono135290d2011-03-17 11:33:34 +00001295 return PJMEDIA_CODEC_EFAILED;
Benny Prijonoc45d9512010-12-10 11:04:30 +00001296 } else {
1297 output->size = err;
1298 }
1299
1300 return PJ_SUCCESS;
1301}
1302
1303/*
1304 * Decode frame.
1305 */
1306static pj_status_t ffmpeg_codec_decode( pjmedia_vid_codec *codec,
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001307 const pjmedia_frame *input,
Benny Prijonoc45d9512010-12-10 11:04:30 +00001308 unsigned output_buf_len,
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001309 pjmedia_frame *output)
Benny Prijonoc45d9512010-12-10 11:04:30 +00001310{
1311 ffmpeg_private *ff = (ffmpeg_private*)codec->codec_data;
1312 AVFrame avframe;
1313 AVPacket avpacket;
1314 int err, got_picture;
1315
1316 /* Check if decoder has been opened */
1317 PJ_ASSERT_RETURN(ff->dec_ctx, PJ_EINVALIDOP);
1318
Nanang Izzuddin98610702011-03-01 17:40:17 +00001319 /* Reset output frame bit info */
1320 output->bit_info = 0;
1321
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001322 /* Validate output buffer size */
Nanang Izzuddin98610702011-03-01 17:40:17 +00001323 if (ff->dec_vafp.framebytes > output_buf_len)
1324 return PJ_ETOOSMALL;
Benny Prijonoc45d9512010-12-10 11:04:30 +00001325
1326 /* Init frame to receive the decoded data, the ffmpeg codec context will
1327 * automatically provide the decoded buffer (single buffer used for the
1328 * whole decoding session, and seems to be freed when the codec context
1329 * closed).
1330 */
1331 avcodec_get_frame_defaults(&avframe);
1332
1333 /* Init packet, the container of the encoded data */
1334 av_init_packet(&avpacket);
1335 avpacket.data = (pj_uint8_t*)input->buf;
1336 avpacket.size = input->size;
1337
1338 /* ffmpeg warns:
1339 * - input buffer padding, at least FF_INPUT_BUFFER_PADDING_SIZE
1340 * - null terminated
1341 * Normally, encoded buffer is allocated more than needed, so lets just
1342 * bzero the input buffer end/pad, hope it will be just fine.
1343 */
1344 pj_bzero(avpacket.data+avpacket.size, FF_INPUT_BUFFER_PADDING_SIZE);
1345
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001346 output->bit_info = 0;
Benny Prijono135290d2011-03-17 11:33:34 +00001347 output->timestamp = input->timestamp;
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001348
Benny Prijonoc45d9512010-12-10 11:04:30 +00001349#if LIBAVCODEC_VERSION_MAJOR >= 52 && LIBAVCODEC_VERSION_MINOR >= 72
Nanang Izzuddind91af572011-03-31 17:29:54 +00001350 //avpacket.flags = AV_PKT_FLAG_KEY;
Benny Prijonoc45d9512010-12-10 11:04:30 +00001351#else
1352 avpacket.flags = 0;
1353#endif
1354
1355#if LIBAVCODEC_VERSION_MAJOR >= 52 && LIBAVCODEC_VERSION_MINOR >= 72
1356 err = avcodec_decode_video2(ff->dec_ctx, &avframe,
1357 &got_picture, &avpacket);
1358#else
1359 err = avcodec_decode_video(ff->dec_ctx, &avframe,
1360 &got_picture, avpacket.data, avpacket.size);
1361#endif
1362 if (err < 0) {
Benny Prijono135290d2011-03-17 11:33:34 +00001363 output->type = PJMEDIA_FRAME_TYPE_NONE;
1364 output->size = 0;
Benny Prijonoc45d9512010-12-10 11:04:30 +00001365 print_ffmpeg_err(err);
Benny Prijono135290d2011-03-17 11:33:34 +00001366 return PJMEDIA_CODEC_EFAILED;
Benny Prijonoc45d9512010-12-10 11:04:30 +00001367 } else if (got_picture) {
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001368 pjmedia_video_apply_fmt_param *vafp = &ff->dec_vafp;
Benny Prijonoc45d9512010-12-10 11:04:30 +00001369 pj_uint8_t *q = (pj_uint8_t*)output->buf;
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001370 unsigned i;
Benny Prijonoc45d9512010-12-10 11:04:30 +00001371
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001372 /* Decoder output format is set by libavcodec, in case it is different
1373 * to the configured param.
1374 */
1375 if (ff->dec_ctx->pix_fmt != ff->expected_dec_fmt ||
Benny Prijono63572992011-04-13 18:06:21 +00001376 ff->dec_ctx->width != (int)vafp->size.w ||
1377 ff->dec_ctx->height != (int)vafp->size.h)
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001378 {
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001379 pjmedia_format_id new_fmt_id;
1380 pj_status_t status;
1381
1382 /* Get current raw format id from ffmpeg decoder context */
1383 status = PixelFormat_to_pjmedia_format_id(ff->dec_ctx->pix_fmt,
1384 &new_fmt_id);
1385 if (status != PJ_SUCCESS)
1386 return status;
1387
1388 /* Update decoder format in param */
1389 ff->param.dec_fmt.id = new_fmt_id;
Benny Prijono63572992011-04-13 18:06:21 +00001390 ff->param.dec_fmt.det.vid.size.w = ff->dec_ctx->width;
1391 ff->param.dec_fmt.det.vid.size.h = ff->dec_ctx->height;
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001392
1393 /* Re-init format info and apply-param of decoder */
1394 ff->dec_vfi = pjmedia_get_video_format_info(NULL, ff->param.dec_fmt.id);
1395 if (!ff->dec_vfi)
Benny Prijono135290d2011-03-17 11:33:34 +00001396 return PJ_ENOTSUP;
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001397 pj_bzero(&ff->dec_vafp, sizeof(ff->dec_vafp));
1398 ff->dec_vafp.size = ff->param.dec_fmt.det.vid.size;
1399 ff->dec_vafp.buffer = NULL;
1400 status = (*ff->dec_vfi->apply_fmt)(ff->dec_vfi, &ff->dec_vafp);
1401 if (status != PJ_SUCCESS)
1402 return status;
1403
1404 /* Notify application via the bit_info field of pjmedia_frame */
1405 output->bit_info = PJMEDIA_VID_CODEC_EVENT_FMT_CHANGED;
Nanang Izzuddin98610702011-03-01 17:40:17 +00001406 }
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001407
Benny Prijono63572992011-04-13 18:06:21 +00001408 /* Check provided buffer size after format changed */
1409 if (vafp->framebytes > output_buf_len)
1410 return PJ_ETOOSMALL;
1411
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001412 /* Get the decoded data */
1413 for (i = 0; i < ff->dec_vfi->plane_cnt; ++i) {
1414 pj_uint8_t *p = avframe.data[i];
1415
1416 /* The decoded data may contain padding */
1417 if (avframe.linesize[i]!=vafp->strides[i]) {
1418 /* Padding exists, copy line by line */
1419 pj_uint8_t *q_end;
1420
1421 q_end = q+vafp->plane_bytes[i];
1422 while(q < q_end) {
1423 pj_memcpy(q, p, vafp->strides[i]);
1424 q += vafp->strides[i];
1425 p += avframe.linesize[i];
1426 }
1427 } else {
1428 /* No padding, copy the whole plane */
1429 pj_memcpy(q, p, vafp->plane_bytes[i]);
1430 q += vafp->plane_bytes[i];
1431 }
1432 }
1433
Benny Prijono135290d2011-03-17 11:33:34 +00001434 output->type = PJMEDIA_FRAME_TYPE_VIDEO;
Benny Prijonoc45d9512010-12-10 11:04:30 +00001435 output->size = vafp->framebytes;
1436 } else {
Benny Prijono135290d2011-03-17 11:33:34 +00001437 output->type = PJMEDIA_FRAME_TYPE_NONE;
1438 output->size = 0;
Benny Prijonoc45d9512010-12-10 11:04:30 +00001439 }
Benny Prijono135290d2011-03-17 11:33:34 +00001440
Benny Prijonoc45d9512010-12-10 11:04:30 +00001441 return PJ_SUCCESS;
1442}
1443
1444/*
1445 * Recover lost frame.
1446 */
1447static pj_status_t ffmpeg_codec_recover( pjmedia_vid_codec *codec,
1448 unsigned output_buf_len,
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001449 pjmedia_frame *output)
Benny Prijonoc45d9512010-12-10 11:04:30 +00001450{
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001451 PJ_UNUSED_ARG(codec);
Benny Prijonoc45d9512010-12-10 11:04:30 +00001452 PJ_UNUSED_ARG(output_buf_len);
1453 PJ_UNUSED_ARG(output);
Benny Prijonoc45d9512010-12-10 11:04:30 +00001454
Nanang Izzuddina9c1cf42011-02-24 07:47:55 +00001455 return PJ_ENOTSUP;
Benny Prijonoc45d9512010-12-10 11:04:30 +00001456}
1457
1458#ifdef _MSC_VER
1459# pragma comment( lib, "avcodec.lib")
Benny Prijonoc45d9512010-12-10 11:04:30 +00001460#endif
1461
1462#endif /* PJMEDIA_HAS_FFMPEG_CODEC */
1463