Ticket #1489: ffmpeg_aud_codecs.c

File ffmpeg_aud_codecs.c, 30.9 KB (added by bennylp, 9 years ago)
Line 
1/* $Id: gsm.c 3664 2011-07-19 03:42:28Z nanang $ */
2/*
3 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
4 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 */
20#include <libavcodec/avcodec.h>
21#include <libavformat/avformat.h>
22#include <pjmedia.h>
23#include <pjlib.h>
24
25#define PJMEDIA_HAS_FFMPEG_AUD_CODECS 1
26
27#if defined(PJMEDIA_HAS_FFMPEG_AUD_CODECS) && PJMEDIA_HAS_FFMPEG_AUD_CODECS != 0
28
29#define THIS_FILE               "ffmpeg_aud_codec.c"
30
31#define LIBAVCODEC_VER_AT_LEAST(major,minor)  (LIBAVCODEC_VERSION_MAJOR > major || \
32                                               (LIBAVCODEC_VERSION_MAJOR == major && \
33                                                LIBAVCODEC_VERSION_MINOR >= minor))
34
35/* Prototypes for FFMPEG factory */
36static pj_status_t ff_test_alloc( pjmedia_codec_factory *factory,
37                                   const pjmedia_codec_info *id );
38static pj_status_t ff_default_attr( pjmedia_codec_factory *factory,
39                                     const pjmedia_codec_info *id,
40                                     pjmedia_codec_param *attr );
41static pj_status_t ff_enum_codecs( pjmedia_codec_factory *factory,
42                                    unsigned *count,
43                                    pjmedia_codec_info codecs[]);
44static pj_status_t ff_alloc_codec( pjmedia_codec_factory *factory,
45                                    const pjmedia_codec_info *id,
46                                    pjmedia_codec **p_codec);
47static pj_status_t ff_dealloc_codec( pjmedia_codec_factory *factory,
48                                      pjmedia_codec *codec );
49
50/* Prototypes for FFMPEG implementation. */
51static pj_status_t  ff_codec_init( pjmedia_codec *codec,
52                                    pj_pool_t *pool );
53static pj_status_t  ff_codec_open( pjmedia_codec *codec,
54                                    pjmedia_codec_param *attr );
55static pj_status_t  ff_codec_close( pjmedia_codec *codec );
56static pj_status_t  ff_codec_modify(pjmedia_codec *codec,
57                                     const pjmedia_codec_param *attr );
58static pj_status_t  ff_codec_parse( pjmedia_codec *codec,
59                                     void *pkt,
60                                     pj_size_t pkt_size,
61                                     const pj_timestamp *ts,
62                                     unsigned *frame_cnt,
63                                     pjmedia_frame frames[]);
64static pj_status_t  ff_codec_encode( pjmedia_codec *codec,
65                                      const struct pjmedia_frame *input,
66                                      unsigned output_buf_len,
67                                      struct pjmedia_frame *output);
68static pj_status_t  ff_codec_decode( pjmedia_codec *codec,
69                                      const struct pjmedia_frame *input,
70                                      unsigned output_buf_len,
71                                      struct pjmedia_frame *output);
72static pj_status_t  ff_codec_recover(pjmedia_codec *codec,
73                                      unsigned output_buf_len,
74                                      struct pjmedia_frame *output);
75
76PJ_DECL(pj_status_t) pjmedia_codec_ff_deinit(void);
77
78/* Definition for FFMPEG codec operations. */
79static pjmedia_codec_op ff_op =
80{
81    &ff_codec_init,
82    &ff_codec_open,
83    &ff_codec_close,
84    &ff_codec_modify,
85    &ff_codec_parse,
86    &ff_codec_encode,
87    &ff_codec_decode,
88    &ff_codec_recover
89    NULL
90#endif
91};
92
93/* Definition for FFMPEG codec factory operations. */
94static pjmedia_codec_factory_op ff_factory_op =
95{
96    &ff_test_alloc,
97    &ff_default_attr,
98    &ff_enum_codecs,
99    &ff_alloc_codec,
100    &ff_dealloc_codec,
101    &pjmedia_codec_ff_deinit
102};
103
104/* FFMPEG factory */
105static struct ff_codec_factory
106{
107    pjmedia_codec_factory    base;
108    pjmedia_endpt           *endpt;
109    pj_pool_t               *pool;
110} ff_codec_factory;
111
112
113/* FFmpeg codec desc */
114static struct ff_codec_desc
115{
116    pjmedia_dir          dir;   /* available dir */
117    enum CodecID         ff_codec_id;
118    pjmedia_format_id    fmt_id;
119    char                 name[16];
120
121    unsigned             min_clock_rate, max_clock_rate;
122    unsigned             min_bps, max_bps, def_bps;
123    unsigned             max_channels;
124
125} ff_codec_desc[] =
126{
127    {
128        PJMEDIA_DIR_ENCODING_DECODING,
129        CODEC_ID_MP2, PJMEDIA_FORMAT_PACK(' ', 'M', 'P', '2'), "MP2",
130        8000, 48000,            /* clock rate range */
131        16000, 384*1000, 64000, /* bitrate range and default */
132        6
133    },
134    {
135        PJMEDIA_DIR_ENCODING_DECODING,
136        CODEC_ID_MP3, PJMEDIA_FORMAT_PACK(' ', 'M', 'P', '3'), "MP3",
137        8000, 48000,            /* clock rate range */
138        8000, 320*1000, 64000,  /* bitrate range and default  */
139        6
140    },
141#if 0
142    /* Problem with decoding AAC frames giving error:
143     *   "aac channel element 0.0 is not allocated"
144     * Relevant info:
145     *   http://lzone.de/aac+decoding+with+ffmpeg+doesn%27t+work
146     */
147    {
148        PJMEDIA_DIR_ENCODING_DECODING,
149        CODEC_ID_AAC, PJMEDIA_FORMAT_PACK(' ', 'A', 'A', 'C'), "AAC",
150        8000, 96000,            /* clock rate range */
151        10000, 44*1000, 12000,  /* bitrate range is unknown*/
152        2
153    },
154#endif
155#if 0
156    /* AC3 doesn't support PCM16 as sample format. It only supports
157     * AV_SAMPLE_FMT_FLT
158     */
159    {
160        PJMEDIA_DIR_ENCODING_DECODING,
161        CODEC_ID_AC3, PJMEDIA_FORMAT_PACK(' ', 'A', 'C', '3'), "AC3",
162        8000, 96000,            /* clock rate range */
163        10000, 44*1000, 12000,  /* bitrate range is unknown*/
164        6
165    },
166#endif
167#if 0
168    /* Vorbis only supports 2 channels */
169    {
170        PJMEDIA_DIR_ENCODING_DECODING,
171        CODEC_ID_VORBIS, PJMEDIA_FORMAT_PACK('V', 'O', 'R', 'B'), "Vorbis",
172        8000, 192*1000,         /* clock rate range */
173        8000, 500*1000, 64000,  /* bitrate range is unknown*/
174        255
175    },
176#endif
177#if 0
178    /* Untested */
179    {
180        PJMEDIA_DIR_ENCODING_DECODING,
181        CODEC_ID_G723_1, PJMEDIA_FORMAT_PACK('G', '7', '2', '3'), "G723.1",
182        8000, 8000,             /* clock rate is fixed */
183        5300, 6400, 6400,       /* bitrate is 5.3 and 6.4*/
184        1
185    },
186    {
187        PJMEDIA_DIR_ENCODING_DECODING,
188        CODEC_ID_ADPCM_G726, PJMEDIA_FORMAT_PACK('G', '7', '2', '6'), "G726",
189        8000, 8000,             /* clock rate is fixed */
190        16000, 40000, 16000,    /* bitrate range */
191        1
192    },
193#endif
194};
195
196/* FFMPEG codec private data. */
197struct ff_data
198{
199    pj_pool_t           *pool;
200    struct ff_codec_desc*desc;
201
202    struct enc_state
203    {
204        AVCodec         *codec;
205        AVCodecContext  *ctx;
206    } enc;
207
208    struct dec_state
209    {
210        AVCodec         *codec;
211        AVCodecContext  *ctx;
212
213        unsigned         frm_size;      /* Encoded frame size in bytes */
214
215        /*
216         * Decoding buffers:
217         */
218        pj_uint8_t      *bit_buf;       /* Bitstream buffer */
219        unsigned         bit_buf_cap;   /* Capabity in bytes */
220        unsigned         bit_buf_size;  /* Current size */
221
222        pj_int16_t      *pcm_buf;       /* Decoded PCM buffer */
223        unsigned         pcm_buf_cap;   /* Capacity in bytes */
224        unsigned         pcm_buf_size;  /* Current size in bytes */
225    } dec;
226
227    unsigned             clock_rate;
228    unsigned             channel_count;
229    unsigned             ptime;
230    unsigned             samples_per_frame;
231    pj_bool_t            plc_enabled;
232    pjmedia_plc         *plc;
233    pj_bool_t            vad_enabled;
234    pjmedia_silence_det *vad;
235    pj_timestamp         last_tx;
236};
237
238
239/*
240 * Initialize and register FFMPEG codec factory to pjmedia endpoint.
241 */
242PJ_DEF(pj_status_t) pjmedia_codec_ff_init( pjmedia_endpt *endpt )
243{
244    pjmedia_codec_mgr *codec_mgr;
245    unsigned i;
246    pj_status_t status;
247
248    if (ff_codec_factory.pool != NULL)
249        return PJ_SUCCESS;
250
251    /* Create FFMPEG codec factory. */
252    ff_codec_factory.base.op = &ff_factory_op;
253    ff_codec_factory.base.factory_data = NULL;
254    ff_codec_factory.endpt = endpt;
255
256    ff_codec_factory.pool = pjmedia_endpt_create_pool(endpt, "ffmpeg_aud",
257                                                      512, 512);
258    if (!ff_codec_factory.pool)
259        return PJ_ENOMEM;
260
261    avcodec_register_all();
262
263    /* Enumerate codecs */
264    PJ_LOG(4,(THIS_FILE, "Enumerating ffmpeg audio codecs availability:"));
265    for (i=0; i<PJ_ARRAY_SIZE(ff_codec_desc); ++i) {
266        struct ff_codec_desc *desc = &ff_codec_desc[i];
267        pjmedia_dir dir = 0;
268        char *dir_name;
269
270        if (avcodec_find_encoder(desc->ff_codec_id) != NULL)
271            dir |= PJMEDIA_DIR_ENCODING;
272        if (avcodec_find_decoder(desc->ff_codec_id) != NULL)
273            dir |= PJMEDIA_DIR_DECODING;
274
275        switch (dir) {
276        case 0:
277            dir_name = "not available";
278            break;
279        case PJMEDIA_DIR_ENCODING:
280            dir_name = "encoding only";
281            break;
282        case PJMEDIA_DIR_DECODING:
283            dir_name = "decoding only";
284            break;
285        default:
286            dir_name = "encoding and decoding";
287            break;
288        }
289
290        desc->dir = (desc->dir & dir);
291        PJ_LOG(4,(THIS_FILE, " %d. %s: %s", i+1, desc->name, dir_name));
292    }
293
294    /* Get the codec manager. */
295    codec_mgr = pjmedia_endpt_get_codec_mgr(endpt);
296    if (!codec_mgr) {
297        status = PJ_EINVALIDOP;
298        goto on_error;
299    }
300
301    /* Register codec factory to endpoint. */
302    status = pjmedia_codec_mgr_register_factory(codec_mgr,
303                                                &ff_codec_factory.base);
304    if (status != PJ_SUCCESS)
305        goto on_error;
306
307    /* Done. */
308    return PJ_SUCCESS;
309
310on_error:
311    pj_pool_release(ff_codec_factory.pool);
312    ff_codec_factory.pool = NULL;
313    return status;
314}
315
316
317/*
318 * Unregister FFMPEG codec factory from pjmedia endpoint and deinitialize
319 * the FFMPEG codec library.
320 */
321PJ_DEF(pj_status_t) pjmedia_codec_ff_deinit(void)
322{
323    pjmedia_codec_mgr *codec_mgr;
324    pj_status_t status;
325
326    if (ff_codec_factory.pool == NULL)
327        return PJ_SUCCESS;
328
329    /* Get the codec manager. */
330    codec_mgr = pjmedia_endpt_get_codec_mgr(ff_codec_factory.endpt);
331    if (!codec_mgr) {
332        pj_pool_release(ff_codec_factory.pool);
333        ff_codec_factory.pool = NULL;
334        return PJ_EINVALIDOP;
335    }
336
337    /* Unregister FFMPEG codec factory. */
338    status = pjmedia_codec_mgr_unregister_factory(codec_mgr,
339                                                  &ff_codec_factory.base);
340
341    /* Destroy pool. */
342    pj_pool_release(ff_codec_factory.pool);
343    ff_codec_factory.pool = NULL;
344
345    return status;
346}
347
348/*
349 * Find descriptor for the specified codec info.
350 */
351static struct ff_codec_desc* find_desc(const pjmedia_codec_info *info)
352{
353    unsigned i;
354    /* Match mostly by the name only */
355    for (i=0; i<PJ_ARRAY_SIZE(ff_codec_desc); ++i) {
356        struct ff_codec_desc *ffcd = &ff_codec_desc[i];
357        if (info->type == PJMEDIA_TYPE_AUDIO &&
358            info->clock_rate >= ffcd->min_clock_rate &&
359            info->clock_rate <= ffcd->max_clock_rate &&
360            info->channel_cnt <= ffcd->max_channels &&
361            pj_stricmp2(&info->encoding_name, ffcd->name)==0)
362        {
363            return ffcd;
364        }
365    }
366    return NULL;
367}
368
369/*
370 * Check if factory can allocate the specified codec.
371 */
372static pj_status_t ff_test_alloc( pjmedia_codec_factory *factory,
373                                   const pjmedia_codec_info *info )
374{
375    PJ_UNUSED_ARG(factory);
376    return find_desc(info)? PJ_SUCCESS : PJMEDIA_CODEC_EUNSUP;
377}
378
379/*
380 * Generate default attribute.
381 */
382static pj_status_t ff_default_attr ( pjmedia_codec_factory *factory,
383                                     const pjmedia_codec_info *id,
384                                     pjmedia_codec_param *attr )
385{
386    struct ff_codec_desc *desc = find_desc(id);
387    unsigned ff_frame_size = 0;
388
389    PJ_UNUSED_ARG(factory);
390
391    if (!desc)
392        return PJMEDIA_CODEC_EUNSUP;
393
394    if (desc->dir & PJMEDIA_DIR_ENCODING) {
395        AVCodec *codec;
396        AVCodecContext *ctx;
397        AVDictionary *av_opt;
398
399        codec = avcodec_find_encoder(desc->ff_codec_id);
400        PJ_ASSERT_RETURN(codec != NULL, PJ_EBUG);
401
402        ctx = avcodec_alloc_context3(codec);
403
404        /* put sample parameters */
405        ctx->bit_rate = desc->def_bps;
406        ctx->sample_rate = id->clock_rate;
407        ctx->channels = id->channel_cnt;
408        ctx->sample_fmt = AV_SAMPLE_FMT_S16;
409        av_opt = NULL;
410        if (avcodec_open2(ctx, codec, &av_opt) < 0) {
411            PJ_LOG(4,(THIS_FILE, "Error opening ffmpeg codec %s", desc->name));
412            return PJ_EUNKNOWN;
413        }
414
415        ff_frame_size = ctx->frame_size;
416
417        avcodec_close(ctx);
418        av_free(ctx);
419    } else {
420        AVCodec *codec;
421        AVCodecContext *ctx;
422        AVDictionary *av_opt;
423
424        codec = avcodec_find_decoder(desc->ff_codec_id);
425        PJ_ASSERT_RETURN(codec != NULL, PJ_EBUG);
426
427        ctx = avcodec_alloc_context3(codec);
428
429        /* put sample parameters */
430        ctx->bit_rate = desc->def_bps;
431        ctx->sample_rate = id->clock_rate;
432        ctx->channels = id->channel_cnt;
433        ctx->sample_fmt = AV_SAMPLE_FMT_S16;
434        av_opt = NULL;
435        if (avcodec_open2(ctx, codec, &av_opt) < 0) {
436            PJ_LOG(4,(THIS_FILE, "Error opening ffmpeg codec %s", desc->name));
437            return PJ_EUNKNOWN;
438        }
439
440        ff_frame_size = ctx->frame_size;
441
442        avcodec_close(ctx);
443        av_free(ctx);
444    }
445
446    pj_bzero(attr, sizeof(pjmedia_codec_param));
447    attr->info.clock_rate = id->clock_rate;
448    attr->info.channel_cnt = id->channel_cnt;
449    attr->info.avg_bps = desc->def_bps;
450    attr->info.max_bps = desc->max_bps;
451    attr->info.pcm_bits_per_sample = 16;
452    attr->info.frm_ptime = (ff_frame_size * 1000 / id->clock_rate);
453    attr->info.pt = 0xFF;       /* invalid */
454
455    attr->setting.frm_per_pkt = 1;
456    attr->setting.vad = 0;
457    attr->setting.plc = 0;
458
459    return PJ_SUCCESS;
460}
461
462/*
463 * Enum codecs supported by this factory (i.e. only GSM!).
464 */
465static pj_status_t ff_enum_codecs(pjmedia_codec_factory *factory,
466                                    unsigned *count,
467                                    pjmedia_codec_info codecs[])
468{
469    PJ_UNUSED_ARG(factory);
470    PJ_ASSERT_RETURN(codecs && *count > 0, PJ_EINVAL);
471
472    /* These ffmpeg codecs are not ready for RTP transfer yet! */
473    *count = 0;
474
475    return PJ_SUCCESS;
476}
477
478/*
479 * Allocate a new GSM codec instance.
480 */
481static pj_status_t ff_alloc_codec( pjmedia_codec_factory *factory,
482                                    const pjmedia_codec_info *id,
483                                    pjmedia_codec **p_codec)
484{
485    pjmedia_codec *codec;
486    pj_pool_t *pool = NULL;
487    struct ff_data *ff_data;
488    struct ff_codec_desc *desc;
489    pj_status_t status = -1;
490
491    PJ_ASSERT_RETURN(factory && id && p_codec, PJ_EINVAL);
492    PJ_ASSERT_RETURN(factory == &ff_codec_factory.base, PJ_EINVAL);
493
494    desc = find_desc(id);
495    if (!desc)
496        return PJMEDIA_CODEC_EUNSUP;
497
498    pool = pj_pool_create(ff_codec_factory.pool->factory, "ffaud%p",
499                          512, 512, NULL);
500
501    codec = PJ_POOL_ZALLOC_T(pool, pjmedia_codec);
502    PJ_ASSERT_RETURN(codec != NULL, PJ_ENOMEM);
503    codec->op = &ff_op;
504    codec->factory = factory;
505
506    ff_data = PJ_POOL_ZALLOC_T(pool, struct ff_data);
507    ff_data->pool = pool;
508    ff_data->desc = desc;
509    ff_data->clock_rate = id->clock_rate;
510    codec->codec_data = ff_data;
511
512    /* Done for now */
513
514    *p_codec = codec;
515    return PJ_SUCCESS;
516}
517
518/*
519 * Free codec.
520 */
521static pj_status_t ff_dealloc_codec( pjmedia_codec_factory *factory,
522                                      pjmedia_codec *codec )
523{
524    struct ff_data *ff_data;
525    pj_pool_t *pool;
526
527    PJ_ASSERT_RETURN(factory && codec, PJ_EINVAL);
528    PJ_ASSERT_RETURN(factory == &ff_codec_factory.base, PJ_EINVAL);
529
530    ff_data = (struct ff_data*) codec->codec_data;
531    if (!ff_data || !ff_data->pool)
532        return PJ_SUCCESS;
533
534    if (ff_data->dec.ctx) {
535        avcodec_close(ff_data->dec.ctx);
536        av_free(ff_data->dec.ctx);
537        ff_data->dec.ctx = NULL;
538        ff_data->dec.codec = NULL;
539    }
540
541    if (ff_data->enc.ctx) {
542        avcodec_close(ff_data->enc.ctx);
543        av_free(ff_data->enc.ctx);
544        ff_data->enc.ctx = NULL;
545        ff_data->enc.codec = NULL;
546    }
547
548    pool = ff_data->pool;
549    ff_data->pool = NULL;
550    pj_pool_release(pool);
551
552    return PJ_SUCCESS;
553}
554
555/*
556 * Init codec.
557 */
558static pj_status_t ff_codec_init( pjmedia_codec *codec, pj_pool_t *pool )
559{
560    PJ_UNUSED_ARG(codec);
561    PJ_UNUSED_ARG(pool);
562    return PJ_SUCCESS;
563}
564
565/*
566 * Open codec.
567 */
568static pj_status_t ff_codec_open( pjmedia_codec *codec,
569                                   pjmedia_codec_param *attr )
570{
571    struct ff_data *ff_data = (struct ff_data*) codec->codec_data;
572    AVDictionary *av_opt;
573    pj_status_t status;
574
575    pj_assert(ff_data != NULL);
576    pj_assert(ff_data->enc.ctx == NULL && ff_data->dec.ctx == NULL);
577
578    ff_data->clock_rate = attr->info.clock_rate;
579    ff_data->channel_count = attr->info.channel_cnt;
580    ff_data->ptime = attr->info.frm_ptime;
581    ff_data->samples_per_frame = ff_data->clock_rate * ff_data->channel_count *
582                                 ff_data->ptime / 1000;
583
584    /* decoder */
585    if (ff_data->desc->dir & PJMEDIA_DIR_DECODING) {
586        if (attr->setting.plc) {
587            status = pjmedia_plc_create(ff_data->pool, ff_data->clock_rate,
588                                        ff_data->samples_per_frame, 0,
589                                        &ff_data->plc);
590            if (status != PJ_SUCCESS)
591                return status;
592        }
593
594        ff_data->dec.codec = avcodec_find_decoder(ff_data->desc->ff_codec_id);
595        if (!ff_data->dec.codec) {
596            return PJ_EUNKNOWN;
597        }
598
599        ff_data->dec.ctx = avcodec_alloc_context3(ff_data->dec.codec);
600
601        av_opt = NULL;
602        if (avcodec_open2(ff_data->dec.ctx, ff_data->dec.codec, &av_opt) < 0) {
603            return PJ_EUNKNOWN;
604        }
605
606        /* decoder buffer */
607        ff_data->dec.frm_size = ff_data->desc->max_bps * ff_data->ptime /
608                                1000 / 8;
609        /* 200ms worth of buffer: */
610        ff_data->dec.bit_buf_cap = ff_data->desc->max_bps * 200 / 1000 / 8;
611        ff_data->dec.bit_buf = (pj_uint8_t*)
612                               pj_pool_alloc(ff_data->pool,
613                                             ff_data->dec.bit_buf_cap);
614        /* ffmpeg needs AVCODEC_MAX_AUDIO_FRAME_SIZE or 192000 or otherwise
615         * avcodec_decode_audio3() will fail
616         */
617        //ff_data->dec.pcm_buf_cap = ff_data->samples_per_frame * 3;
618        ff_data->dec.pcm_buf_cap = 192000 * 2;
619        ff_data->dec.pcm_buf = (pj_uint16_t*)
620                               pj_pool_alloc(ff_data->pool,
621                                             ff_data->dec.pcm_buf_cap);
622
623    }
624
625    /* encoder */
626    if (ff_data->desc->dir & PJMEDIA_DIR_ENCODING) {
627        /* Create silence detector */
628        status = pjmedia_silence_det_create(ff_data->pool, ff_data->clock_rate,
629                                            ff_data->samples_per_frame,
630                                            &ff_data->vad);
631        if (status != PJ_SUCCESS)
632            return status;
633
634        ff_data->enc.codec = avcodec_find_encoder(ff_data->desc->ff_codec_id);
635        if (!ff_data->enc.codec) {
636            return PJ_EUNKNOWN;
637        }
638
639        ff_data->enc.ctx = avcodec_alloc_context3(ff_data->enc.codec);
640        ff_data->enc.ctx->bit_rate = attr->info.avg_bps;
641        ff_data->enc.ctx->sample_rate = attr->info.clock_rate;
642        ff_data->enc.ctx->channels = attr->info.channel_cnt;
643        ff_data->enc.ctx->sample_fmt = AV_SAMPLE_FMT_S16;
644
645        av_opt = NULL;
646        if (avcodec_open2(ff_data->enc.ctx, ff_data->enc.codec, &av_opt) < 0) {
647            return PJ_EUNKNOWN;
648        }
649    }
650
651    ff_data->vad_enabled = (attr->setting.vad != 0);
652    ff_data->plc_enabled = (attr->setting.plc != 0);
653
654    return PJ_SUCCESS;
655}
656
657/*
658 * Close codec.
659 */
660static pj_status_t ff_codec_close( pjmedia_codec *codec )
661{
662    PJ_UNUSED_ARG(codec);
663    return PJ_SUCCESS;
664}
665
666
667/*
668 * Modify codec settings.
669 */
670static pj_status_t  ff_codec_modify( pjmedia_codec *codec,
671                                     const pjmedia_codec_param *attr )
672{
673    struct ff_data *ff_data = (struct ff_data*) codec->codec_data;
674
675    pj_assert(ff_data != NULL);
676    pj_assert(ff_data->enc.codec!= NULL && ff_data->dec.ctx != NULL);
677
678    ff_data->vad_enabled = (attr->setting.vad != 0);
679    ff_data->plc_enabled = (attr->setting.plc != 0);
680
681    return PJ_SUCCESS;
682}
683
684
685/*
686 * Get frames in the packet.
687 */
688static pj_status_t  ff_codec_parse( pjmedia_codec *codec,
689                                     void *pkt,
690                                     pj_size_t pkt_size,
691                                     const pj_timestamp *ts,
692                                     unsigned *frame_cnt,
693                                     pjmedia_frame frames[])
694{
695    struct ff_data *ff_data = (struct ff_data*) codec->codec_data;
696    unsigned count = 0;
697
698    while (pkt_size > 0 && count < *frame_cnt) {
699        unsigned frame_size;
700
701        pj_bzero(&frames[count], sizeof(frames[count]));
702
703        frame_size = pkt_size >= ff_data->dec.frm_size ?
704                        ff_data->dec.frm_size : pkt_size;
705        frames[count].buf = (char*)pkt;
706        frames[count].size = frame_size;
707        frames[count].timestamp = *ts;
708        frames[count].type = PJMEDIA_FRAME_TYPE_AUDIO;
709
710        pkt += frame_size;
711        pkt_size -= frame_size;
712        count++;
713    }
714
715    *frame_cnt = count;
716    return PJ_SUCCESS;
717}
718
719/*
720 * Encode frame.
721 */
722static pj_status_t ff_codec_encode( pjmedia_codec *codec,
723                                     const struct pjmedia_frame *input,
724                                     unsigned output_buf_len,
725                                     struct pjmedia_frame *output)
726{
727    struct ff_data *ff_data = (struct ff_data*) codec->codec_data;
728    pj_int16_t *pcm_in;
729    unsigned in_size;
730    pj_uint8_t *out_buf;
731    int out_buf_size;
732
733    pj_assert(ff_data && input && output);
734
735    if (!ff_data->enc.ctx)
736        return PJMEDIA_CODEC_EUNSUP;
737
738    pcm_in = (pj_int16_t*)input->buf;
739    in_size = input->size;
740
741    /* Detect silence */
742    if (ff_data->vad_enabled) {
743        pj_bool_t is_silence;
744        pj_int32_t silence_duration;
745
746        silence_duration = pj_timestamp_diff32(&ff_data->last_tx,
747                                               &input->timestamp);
748
749        is_silence = pjmedia_silence_det_detect(ff_data->vad,
750                                                pcm_in, (in_size >> 1), NULL);
751        if (is_silence &&
752            (PJMEDIA_CODEC_MAX_SILENCE_PERIOD == -1 ||
753             silence_duration < PJMEDIA_CODEC_MAX_SILENCE_PERIOD*8000/1000))
754        {
755            output->type = PJMEDIA_FRAME_TYPE_NONE;
756            output->buf = NULL;
757            output->size = 0;
758            output->timestamp = input->timestamp;
759            return PJ_SUCCESS;
760        } else {
761            ff_data->last_tx = input->timestamp;
762        }
763    }
764
765    /* Encode */
766    output->size = 0;
767    out_buf = (pj_uint8_t*)output->buf;
768    out_buf_size = output_buf_len;
769
770    while (in_size >= ff_data->samples_per_frame * 2) {
771        int out_size;
772
773        out_size = avcodec_encode_audio(ff_data->enc.ctx,
774                                        out_buf, out_buf_size,
775                                        pcm_in);
776        if (out_size < 0)
777            break;
778
779        pcm_in += ff_data->samples_per_frame;
780        out_buf += out_size;
781        out_buf_size -= out_size;
782
783        output->size += out_size;
784        in_size -= ff_data->samples_per_frame * 2;
785    }
786
787    if (output->size) {
788        output->type = PJMEDIA_FRAME_TYPE_AUDIO;
789    } else {
790        output->type = PJMEDIA_FRAME_TYPE_NONE;
791    }
792    output->timestamp = input->timestamp;
793
794    return PJ_SUCCESS;
795}
796
797/*
798 * Decode frame.
799 */
800static pj_status_t ff_codec_decode( pjmedia_codec *codec,
801                                     const struct pjmedia_frame *input,
802                                     unsigned output_buf_len,
803                                     struct pjmedia_frame *output)
804{
805    struct ff_data *ff_data = (struct ff_data*) codec->codec_data;
806    unsigned size_to_copy;
807    unsigned max_to_copy;
808    AVPacket av_pkt;
809
810    pj_assert(ff_data != NULL);
811    PJ_ASSERT_RETURN(input && output, PJ_EINVAL);
812
813    if (!ff_data->dec.ctx)
814        return PJMEDIA_CODEC_EUNSUP;
815
816    av_init_packet(&av_pkt);
817
818    /* Append packet to the end of bitstream buffer */
819    size_to_copy = input->size;
820    max_to_copy = ff_data->dec.bit_buf_cap - ff_data->dec.bit_buf_size - 1;
821    if (size_to_copy >  max_to_copy)
822        size_to_copy = max_to_copy;
823    pj_memcpy(ff_data->dec.bit_buf + ff_data->dec.bit_buf_size,
824              input->buf, size_to_copy);
825    ff_data->dec.bit_buf_size += size_to_copy;
826
827    av_pkt.data = ff_data->dec.bit_buf;
828    av_pkt.size = ff_data->dec.bit_buf_size;
829    av_pkt.data[av_pkt.size] = '\0';
830
831    while (av_pkt.size != 0) {
832        AVPacket orig_pkt;
833        int dec_len, out_size;
834
835        orig_pkt = av_pkt;
836        out_size = ff_data->dec.pcm_buf_cap - ff_data->dec.pcm_buf_size;
837        dec_len = avcodec_decode_audio3(ff_data->dec.ctx,
838                                        ff_data->dec.pcm_buf +
839                                            ff_data->dec.pcm_buf_size/2,
840                                        &out_size, &av_pkt);
841        if (dec_len <= 0)
842            break;
843
844        ff_data->dec.pcm_buf_size += out_size;
845        if (av_pkt.data == orig_pkt.data) {
846            /* Just in case ffmpeg doesn't modify av_pkt */
847            av_pkt.data += dec_len;
848            av_pkt.size = orig_pkt.size - dec_len;
849        }
850    }
851
852    /* Remove decoded bitstream */
853    if (av_pkt.size && av_pkt.size != ff_data->dec.bit_buf_size) {
854        pj_memmove(ff_data->dec.bit_buf,
855                   ff_data->dec.bit_buf+(ff_data->dec.bit_buf_size - av_pkt.size),
856                   av_pkt.size);
857    }
858    ff_data->dec.bit_buf_size = av_pkt.size;
859
860    /* If we have uncopied bitstream from the packet, copy now */
861    if (size_to_copy < input->size) {
862        const char *src = (const char*)input->buf + size_to_copy;
863        size_to_copy = input->size - size_to_copy;
864        max_to_copy = ff_data->dec.bit_buf_cap - ff_data->dec.bit_buf_size - 1;
865        if (size_to_copy >  max_to_copy)
866            size_to_copy = max_to_copy;
867        pj_memcpy(ff_data->dec.bit_buf + ff_data->dec.bit_buf_size,
868                  src, size_to_copy);
869        ff_data->dec.bit_buf_size += size_to_copy;
870    }
871
872    /* Get one frame from output buffer, if any */
873    if (ff_data->dec.pcm_buf_size >= ff_data->samples_per_frame * 2) {
874        output->type = PJMEDIA_FRAME_TYPE_AUDIO;
875        pjmedia_copy_samples((short*)output->buf, ff_data->dec.pcm_buf,
876                             ff_data->samples_per_frame);
877        output->size = ff_data->samples_per_frame * 2;
878        output->timestamp = input->timestamp;
879
880        pjmedia_move_samples(ff_data->dec.pcm_buf,
881                             ff_data->dec.pcm_buf + ff_data->samples_per_frame,
882                             ff_data->dec.pcm_buf_size/2 -
883                                 ff_data->samples_per_frame);
884        ff_data->dec.pcm_buf_size -= (ff_data->samples_per_frame * 2);
885
886        if (ff_data->plc_enabled)
887            pjmedia_plc_save( ff_data->plc, (pj_int16_t*)output->buf);
888
889    } else {
890        output->type = PJMEDIA_FRAME_TYPE_NONE;
891        output->buf = NULL;
892        output->size = 0;
893        output->timestamp = input->timestamp;
894    }
895
896    return PJ_SUCCESS;
897}
898
899
900/*
901 * Recover lost frame.
902 */
903static pj_status_t  ff_codec_recover(pjmedia_codec *codec,
904                                      unsigned output_buf_len,
905                                      struct pjmedia_frame *output)
906{
907    struct ff_data *ff_data = (struct ff_data*) codec->codec_data;
908    PJ_ASSERT_RETURN(ff_data->plc_enabled, PJ_EINVALIDOP);
909    PJ_ASSERT_RETURN(output_buf_len >= ff_data->samples_per_frame,
910                     PJMEDIA_CODEC_EPCMTOOSHORT);
911
912    if (!ff_data->dec.ctx)
913        return PJMEDIA_CODEC_EUNSUP;
914
915    /* Ideally we should first check the pcm buffer for available frame.. */
916
917    pjmedia_plc_generate(ff_data->plc, (pj_int16_t*)output->buf);
918    output->size = ff_data->samples_per_frame * 2;
919
920    /* Reset buffers */
921    //ff_data->dec.bit_buf_size = 0;
922    ff_data->dec.pcm_buf_size = 0;
923
924    return PJ_SUCCESS;
925}
926
927
928
929#endif  /* PJMEDIA_HAS_FFMPEG_AUD_CODECS */
930
931static const char *desc =
932 " encdec                                                               \n"
933 "                                                                      \n"
934 " PURPOSE:                                                             \n"
935 "  Encode input WAV with a codec, and decode the result to another WAV \n"
936 "\n"
937 "\n"
938 " USAGE:                                                               \n"
939 "  encdec codec input.wav output.wav                                   \n"
940 "\n"
941 "\n"
942 " where:\n"
943 "  codec         Set the codec name.                                   \n"
944 "  input.wav     Set the input WAV filename.                           \n"
945 "  output.wav    Set the output WAV filename.                          \n"
946
947 "\n"
948;
949
950//#undef PJ_TRACE
951//#define PJ_TRACE 1
952
953#ifndef PJ_TRACE
954#       define PJ_TRACE 0
955#endif
956
957#if PJ_TRACE
958#   define TRACE_(expr)     PJ_LOG(4,expr)
959#else
960#   define TRACE_(expr)
961#endif
962
963
964static void err(const char *op, pj_status_t status)
965{
966    char errmsg[PJ_ERR_MSG_SIZE];
967    pj_strerror(status, errmsg, sizeof(errmsg));
968    PJ_LOG(3,("", "%s error: %s", op, errmsg));
969}
970
971#define CHECK(op)   do { \
972                        status = op; \
973                        if (status != PJ_SUCCESS) { \
974                            err(#op, status); \
975                            return status; \
976                        } \
977                    } \
978                    while (0)
979
980static pjmedia_endpt *mept;
981static unsigned file_msec_duration;
982
983static pj_status_t enc_dec_test(unsigned desc_idx,
984                                const char *filein,
985                                const char *fileout)
986{
987    pj_pool_t *pool;
988    pjmedia_codec_mgr *cm;
989    pjmedia_codec *codec;
990    pjmedia_codec_info ci, *pci = &ci;
991    pjmedia_codec_param param;
992    unsigned cnt, samples_per_frame;
993    pj_str_t tmp;
994    pjmedia_port *wavin, *wavout;
995    unsigned lost_pct;
996    pj_int16_t *pcmbuf;
997    pj_uint8_t *bitstream;
998    unsigned pcmbuf_size, bistream_size;
999    pj_status_t status;
1000
1001#define T   file_msec_duration/1000, file_msec_duration%1000
1002
1003    pool = pjmedia_endpt_create_pool(mept, "encdec", 1000, 1000);
1004
1005    cm = pjmedia_endpt_get_codec_mgr(mept);
1006
1007#ifdef LOST_PCT
1008    lost_pct = LOST_PCT;
1009#else
1010    lost_pct = 0;
1011#endif
1012
1013    PJ_LOG(3,(THIS_FILE, "Encode decode test with %s",
1014              ff_codec_desc[desc_idx].name));
1015
1016    /* Open once to get clock rate etc */
1017    CHECK( pjmedia_wav_player_port_create(pool, filein, 20,
1018                                          PJMEDIA_FILE_NO_LOOP, 0, &wavin) );
1019
1020    /* First get_default_param() to obtain ptime */
1021    ci.type = PJMEDIA_TYPE_AUDIO;
1022    ci.encoding_name = pj_str((char*)ff_codec_desc[desc_idx].name);
1023    ci.channel_cnt = wavin->info.fmt.det.aud.channel_count;
1024    ci.clock_rate = wavin->info.fmt.det.aud.clock_rate;
1025    ci.pt = 0xFF;
1026    CHECK( pjmedia_codec_mgr_get_default_param(cm, pci, &param) );
1027
1028    pjmedia_port_destroy(wavin);
1029
1030    /* Open again with correct ptime */
1031    CHECK( pjmedia_wav_player_port_create(pool, filein,
1032                                          param.info.frm_ptime,
1033                                          PJMEDIA_FILE_NO_LOOP,
1034                                          8000, &wavin) );
1035
1036    samples_per_frame = param.info.clock_rate * param.info.frm_ptime / 1000;
1037
1038    /* Control VAD */
1039    param.setting.vad = 0;
1040
1041    /* Open wav for writing */
1042    CHECK( pjmedia_wav_writer_port_create(pool, fileout,
1043                                          param.info.clock_rate,
1044                                          param.info.channel_cnt,
1045                                          samples_per_frame,
1046                                          16, 0, 8000, &wavout) );
1047
1048    /* Alloc codec */
1049    CHECK( pjmedia_codec_mgr_alloc_codec(cm, pci, &codec) );
1050    CHECK( pjmedia_codec_init(codec, pool) );
1051    CHECK( pjmedia_codec_open(codec, &param) );
1052
1053    /* AAC+ encoder needs 768 */
1054    pcmbuf_size = 4000;
1055    pcmbuf = pj_pool_alloc(pool, pcmbuf_size);
1056    bistream_size = 3000;
1057    bitstream = pj_pool_alloc(pool, bistream_size);
1058
1059    for (;;) {
1060        pjmedia_frame frm_pcm, frm_bit, out_frm, frames[4];
1061        pj_timestamp ts;
1062
1063        frm_pcm.type = PJMEDIA_FRAME_TYPE_AUDIO;
1064        frm_pcm.buf = (char*)pcmbuf;
1065        frm_pcm.size = samples_per_frame * 2;
1066
1067        /* Read from WAV */
1068        if (pjmedia_port_get_frame(wavin, &frm_pcm) != PJ_SUCCESS)
1069            break;
1070        if (frm_pcm.type != PJMEDIA_FRAME_TYPE_AUDIO)
1071            break;;
1072
1073        /* Update duration */
1074        file_msec_duration += samples_per_frame * 1000 /
1075                              param.info.clock_rate;
1076
1077        /* Encode */
1078        frm_bit.buf = bitstream;
1079        frm_bit.size = bistream_size;
1080        CHECK(pjmedia_codec_encode(codec, &frm_pcm, bistream_size,
1081                                   &frm_bit));
1082
1083        /* On DTX, write zero frame to wavout to maintain duration */
1084        if (frm_bit.size == 0 || frm_bit.type != PJMEDIA_FRAME_TYPE_AUDIO) {
1085            out_frm.buf = (char*)pcmbuf;
1086            out_frm.size = samples_per_frame * 2;
1087            pj_bzero(out_frm.buf, out_frm.size);
1088            CHECK( pjmedia_port_put_frame(wavout, &out_frm) );
1089            TRACE_((THIS_FILE, "%d.%03d read: %u, enc: %u",
1090                    T, frm_pcm.size, frm_bit.size));
1091            continue;
1092        }
1093
1094        /* Parse the bitstream (not really necessary for this case
1095         * since we always decode 1 frame, but it's still good
1096         * for testing)
1097         */
1098        ts.u64 = 0;
1099        cnt = PJ_ARRAY_SIZE(frames);
1100        CHECK( pjmedia_codec_parse(codec, bitstream, frm_bit.size, &ts, &cnt,
1101                                   frames) );
1102        CHECK( (cnt==1 ? PJ_SUCCESS : -1) );
1103
1104        /* Decode or simulate packet loss */
1105        out_frm.buf = (char*)pcmbuf;
1106        out_frm.size = pcmbuf_size;
1107
1108        if (0 && (pj_rand() % 100) < (int)lost_pct) {
1109            /* Simulate loss */
1110            CHECK( pjmedia_codec_recover(codec, samples_per_frame * 2, &out_frm) );
1111            TRACE_((THIS_FILE, "%d.%03d Packet lost", T));
1112        } else {
1113            /* Decode */
1114            CHECK( pjmedia_codec_decode(codec, &frames[0], samples_per_frame * 2,
1115                                     &out_frm) );
1116        }
1117
1118        /* Write to WAV */
1119        CHECK( pjmedia_port_put_frame(wavout, &out_frm) );
1120
1121        TRACE_((THIS_FILE, "%d.%03d read: %u, enc: %u, dec/write: %u",
1122                T, frm_pcm.size, frm_bit.size, out_frm.size));
1123    }
1124
1125    /* Close wavs */
1126    pjmedia_port_destroy(wavout);
1127    pjmedia_port_destroy(wavin);
1128
1129    /* Close codec */
1130    pjmedia_codec_close(codec);
1131    pjmedia_codec_mgr_dealloc_codec(cm, codec);
1132
1133    /* Release pool */
1134    pj_pool_release(pool);
1135
1136    return PJ_SUCCESS;
1137}
1138
1139
1140int main(int argc, char *argv[])
1141{
1142    pj_caching_pool cp;
1143    pj_time_val t0, t1;
1144    pj_status_t status;
1145
1146    CHECK( pj_init() );
1147
1148    pj_caching_pool_init(&cp, NULL, 0);
1149
1150    CHECK( pjmedia_endpt_create(&cp.factory, NULL, 1, &mept) );
1151
1152    /* Register all codecs */
1153    CHECK( pjmedia_codec_ff_init( mept ) );
1154
1155    pj_gettimeofday(&t0);
1156    status = enc_dec_test(3, "/home/bennylp/Desktop/project/pjsip/1.x/pjsip-apps/bin/SaveAPrayer.wav",
1157                          "/home/bennylp/Desktop/project/pjsip/1.x/pjsip-apps/bin/output.wav");
1158    pj_gettimeofday(&t1);
1159    PJ_TIME_VAL_SUB(t1, t0);
1160
1161    pjmedia_endpt_destroy(mept);
1162    pj_caching_pool_destroy(&cp);
1163    pj_shutdown();
1164
1165    if (status == PJ_SUCCESS) {
1166        puts("");
1167        puts("Success");
1168        printf("Duration: %ds.%03d\n", file_msec_duration/1000,
1169                                       file_msec_duration%1000);
1170        printf("Time: %lds.%03ld\n", t1.sec, t1.msec);
1171    }
1172
1173    return 0;
1174}
1175