~ubuntu-branches/ubuntu/trusty/sflphone/trusty

« back to all changes in this revision

Viewing changes to daemon/libs/pjproject-2.0.1/pjmedia/src/pjmedia/g711.c

  • Committer: Package Import Robot
  • Author(s): Mark Purcell
  • Date: 2014-01-28 18:23:36 UTC
  • mfrom: (4.3.4 sid)
  • Revision ID: package-import@ubuntu.com-20140128182336-jrsv0k9u6cawc068
Tags: 1.3.0-1
* New upstream release 
  - Fixes "New Upstream Release" (Closes: #735846)
  - Fixes "Ringtone does not stop" (Closes: #727164)
  - Fixes "[sflphone-kde] crash on startup" (Closes: #718178)
  - Fixes "sflphone GUI crashes when call is hung up" (Closes: #736583)
* Build-Depends: ensure GnuTLS 2.6
  - libucommon-dev (>= 6.0.7-1.1), libccrtp-dev (>= 2.0.6-3)
  - Fixes "FTBFS Build-Depends libgnutls{26,28}-dev" (Closes: #722040)
* Fix "boost 1.49 is going away" unversioned Build-Depends: (Closes: #736746)
* Add Build-Depends: libsndfile-dev, nepomuk-core-dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* $Id: g711.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
 
/* This file contains file from Sun Microsystems, Inc, with the complete
21
 
 * notice in the second half of this file.
22
 
 */
23
 
#include <pjmedia/g711.h>
24
 
#include <pjmedia/codec.h>
25
 
#include <pjmedia/alaw_ulaw.h>
26
 
#include <pjmedia/endpoint.h>
27
 
#include <pjmedia/errno.h>
28
 
#include <pjmedia/port.h>
29
 
#include <pjmedia/plc.h>
30
 
#include <pjmedia/silencedet.h>
31
 
#include <pj/pool.h>
32
 
#include <pj/string.h>
33
 
#include <pj/assert.h>
34
 
 
35
 
#if defined(PJMEDIA_HAS_G711_CODEC) && PJMEDIA_HAS_G711_CODEC!=0
36
 
 
37
 
/* We removed PLC in 0.6 (and re-enabled it again in 0.9!) */
38
 
#define PLC_DISABLED    0
39
 
 
40
 
 
41
 
#define G711_BPS            64000
42
 
#define G711_CODEC_CNT      0   /* number of codec to preallocate in memory */
43
 
#define PTIME               10  /* basic frame size is 10 msec      */
44
 
#define FRAME_SIZE          (8000 * PTIME / 1000)   /* 80 bytes     */
45
 
#define SAMPLES_PER_FRAME   (8000 * PTIME / 1000)   /* 80 samples   */
46
 
 
47
 
/* Prototypes for G711 factory */
48
 
static pj_status_t g711_test_alloc( pjmedia_codec_factory *factory,
49
 
                                    const pjmedia_codec_info *id );
50
 
static pj_status_t g711_default_attr( pjmedia_codec_factory *factory,
51
 
                                      const pjmedia_codec_info *id,
52
 
                                      pjmedia_codec_param *attr );
53
 
static pj_status_t g711_enum_codecs (pjmedia_codec_factory *factory,
54
 
                                     unsigned *count,
55
 
                                     pjmedia_codec_info codecs[]);
56
 
static pj_status_t g711_alloc_codec( pjmedia_codec_factory *factory,
57
 
                                     const pjmedia_codec_info *id,
58
 
                                     pjmedia_codec **p_codec);
59
 
static pj_status_t g711_dealloc_codec( pjmedia_codec_factory *factory,
60
 
                                       pjmedia_codec *codec );
61
 
 
62
 
/* Prototypes for G711 implementation. */
63
 
static pj_status_t  g711_init( pjmedia_codec *codec,
64
 
                               pj_pool_t *pool );
65
 
static pj_status_t  g711_open( pjmedia_codec *codec,
66
 
                               pjmedia_codec_param *attr );
67
 
static pj_status_t  g711_close( pjmedia_codec *codec );
68
 
static pj_status_t  g711_modify(pjmedia_codec *codec,
69
 
                                const pjmedia_codec_param *attr );
70
 
static pj_status_t  g711_parse(pjmedia_codec *codec,
71
 
                               void *pkt,
72
 
                               pj_size_t pkt_size,
73
 
                               const pj_timestamp *timestamp,
74
 
                               unsigned *frame_cnt,
75
 
                               pjmedia_frame frames[]);
76
 
static pj_status_t  g711_encode( pjmedia_codec *codec,
77
 
                                 const struct pjmedia_frame *input,
78
 
                                 unsigned output_buf_len,
79
 
                                 struct pjmedia_frame *output);
80
 
static pj_status_t  g711_decode( pjmedia_codec *codec,
81
 
                                 const struct pjmedia_frame *input,
82
 
                                 unsigned output_buf_len,
83
 
                                 struct pjmedia_frame *output);
84
 
#if !PLC_DISABLED
85
 
static pj_status_t  g711_recover( pjmedia_codec *codec,
86
 
                                  unsigned output_buf_len,
87
 
                                  struct pjmedia_frame *output);
88
 
#endif
89
 
 
90
 
/* Definition for G711 codec operations. */
91
 
static pjmedia_codec_op g711_op =
92
 
{
93
 
    &g711_init,
94
 
    &g711_open,
95
 
    &g711_close,
96
 
    &g711_modify,
97
 
    &g711_parse,
98
 
    &g711_encode,
99
 
    &g711_decode,
100
 
#if !PLC_DISABLED
101
 
    &g711_recover
102
 
#else
103
 
    NULL
104
 
#endif
105
 
};
106
 
 
107
 
/* Definition for G711 codec factory operations. */
108
 
static pjmedia_codec_factory_op g711_factory_op =
109
 
{
110
 
    &g711_test_alloc,
111
 
    &g711_default_attr,
112
 
    &g711_enum_codecs,
113
 
    &g711_alloc_codec,
114
 
    &g711_dealloc_codec,
115
 
    &pjmedia_codec_g711_deinit
116
 
};
117
 
 
118
 
/* G711 factory private data */
119
 
static struct g711_factory
120
 
{
121
 
    pjmedia_codec_factory       base;
122
 
    pjmedia_endpt              *endpt;
123
 
    pj_pool_t                  *pool;
124
 
    pj_mutex_t                 *mutex;
125
 
    pjmedia_codec               codec_list;
126
 
} g711_factory;
127
 
 
128
 
/* G711 codec private data. */
129
 
struct g711_private
130
 
{
131
 
    unsigned             pt;
132
 
#if !PLC_DISABLED
133
 
    pj_bool_t            plc_enabled;
134
 
    pjmedia_plc         *plc;
135
 
#endif
136
 
    pj_bool_t            vad_enabled;
137
 
    pjmedia_silence_det *vad;
138
 
    pj_timestamp         last_tx;
139
 
};
140
 
 
141
 
 
142
 
PJ_DEF(pj_status_t) pjmedia_codec_g711_init(pjmedia_endpt *endpt)
143
 
{
144
 
    pjmedia_codec_mgr *codec_mgr;
145
 
    pj_status_t status;
146
 
 
147
 
    if (g711_factory.endpt != NULL) {
148
 
        /* Already initialized. */
149
 
        return PJ_SUCCESS;
150
 
    }
151
 
 
152
 
    /* Init factory */
153
 
    g711_factory.base.op = &g711_factory_op;
154
 
    g711_factory.base.factory_data = NULL;
155
 
    g711_factory.endpt = endpt;
156
 
 
157
 
    pj_list_init(&g711_factory.codec_list);
158
 
 
159
 
    /* Create pool */
160
 
    g711_factory.pool = pjmedia_endpt_create_pool(endpt, "g711", 4000, 4000);
161
 
    if (!g711_factory.pool)
162
 
        return PJ_ENOMEM;
163
 
 
164
 
    /* Create mutex. */
165
 
    status = pj_mutex_create_simple(g711_factory.pool, "g611",
166
 
                                    &g711_factory.mutex);
167
 
    if (status != PJ_SUCCESS)
168
 
        goto on_error;
169
 
 
170
 
    /* Get the codec manager. */
171
 
    codec_mgr = pjmedia_endpt_get_codec_mgr(endpt);
172
 
    if (!codec_mgr) {
173
 
        return PJ_EINVALIDOP;
174
 
    }
175
 
 
176
 
    /* Register codec factory to endpoint. */
177
 
    status = pjmedia_codec_mgr_register_factory(codec_mgr,
178
 
                                                &g711_factory.base);
179
 
    if (status != PJ_SUCCESS)
180
 
        return status;
181
 
 
182
 
 
183
 
    return PJ_SUCCESS;
184
 
 
185
 
on_error:
186
 
    if (g711_factory.mutex) {
187
 
        pj_mutex_destroy(g711_factory.mutex);
188
 
        g711_factory.mutex = NULL;
189
 
    }
190
 
    if (g711_factory.pool) {
191
 
        pj_pool_release(g711_factory.pool);
192
 
        g711_factory.pool = NULL;
193
 
    }
194
 
    return status;
195
 
}
196
 
 
197
 
PJ_DEF(pj_status_t) pjmedia_codec_g711_deinit(void)
198
 
{
199
 
    pjmedia_codec_mgr *codec_mgr;
200
 
    pj_status_t status;
201
 
 
202
 
    if (g711_factory.endpt == NULL) {
203
 
        /* Not registered. */
204
 
        return PJ_SUCCESS;
205
 
    }
206
 
 
207
 
    /* Lock mutex. */
208
 
    pj_mutex_lock(g711_factory.mutex);
209
 
 
210
 
    /* Get the codec manager. */
211
 
    codec_mgr = pjmedia_endpt_get_codec_mgr(g711_factory.endpt);
212
 
    if (!codec_mgr) {
213
 
        g711_factory.endpt = NULL;
214
 
        pj_mutex_unlock(g711_factory.mutex);
215
 
        return PJ_EINVALIDOP;
216
 
    }
217
 
 
218
 
    /* Unregister G711 codec factory. */
219
 
    status = pjmedia_codec_mgr_unregister_factory(codec_mgr,
220
 
                                                  &g711_factory.base);
221
 
    g711_factory.endpt = NULL;
222
 
 
223
 
    /* Destroy mutex. */
224
 
    pj_mutex_destroy(g711_factory.mutex);
225
 
    g711_factory.mutex = NULL;
226
 
 
227
 
 
228
 
    /* Release pool. */
229
 
    pj_pool_release(g711_factory.pool);
230
 
    g711_factory.pool = NULL;
231
 
 
232
 
 
233
 
    return status;
234
 
}
235
 
 
236
 
static pj_status_t g711_test_alloc(pjmedia_codec_factory *factory,
237
 
                                   const pjmedia_codec_info *id )
238
 
{
239
 
    PJ_UNUSED_ARG(factory);
240
 
 
241
 
    /* It's sufficient to check payload type only. */
242
 
    return (id->pt==PJMEDIA_RTP_PT_PCMU || id->pt==PJMEDIA_RTP_PT_PCMA)? 0:-1;
243
 
}
244
 
 
245
 
static pj_status_t g711_default_attr (pjmedia_codec_factory *factory,
246
 
                                      const pjmedia_codec_info *id,
247
 
                                      pjmedia_codec_param *attr )
248
 
{
249
 
    PJ_UNUSED_ARG(factory);
250
 
 
251
 
    pj_bzero(attr, sizeof(pjmedia_codec_param));
252
 
    attr->info.clock_rate = 8000;
253
 
    attr->info.channel_cnt = 1;
254
 
    attr->info.avg_bps = G711_BPS;
255
 
    attr->info.max_bps = G711_BPS;
256
 
    attr->info.pcm_bits_per_sample = 16;
257
 
    attr->info.frm_ptime = PTIME;
258
 
    attr->info.pt = (pj_uint8_t)id->pt;
259
 
 
260
 
    /* Set default frames per packet to 2 (or 20ms) */
261
 
    attr->setting.frm_per_pkt = 2;
262
 
 
263
 
#if !PLC_DISABLED
264
 
    /* Enable plc by default. */
265
 
    attr->setting.plc = 1;
266
 
#endif
267
 
 
268
 
    /* Enable VAD by default. */
269
 
    attr->setting.vad = 1;
270
 
 
271
 
    /* Default all other flag bits disabled. */
272
 
 
273
 
    return PJ_SUCCESS;
274
 
}
275
 
 
276
 
static pj_status_t g711_enum_codecs(pjmedia_codec_factory *factory,
277
 
                                    unsigned *max_count,
278
 
                                    pjmedia_codec_info codecs[])
279
 
{
280
 
    unsigned count = 0;
281
 
 
282
 
    PJ_UNUSED_ARG(factory);
283
 
 
284
 
    if (count < *max_count) {
285
 
        codecs[count].type = PJMEDIA_TYPE_AUDIO;
286
 
        codecs[count].pt = PJMEDIA_RTP_PT_PCMU;
287
 
        codecs[count].encoding_name = pj_str("PCMU");
288
 
        codecs[count].clock_rate = 8000;
289
 
        codecs[count].channel_cnt = 1;
290
 
        ++count;
291
 
    }
292
 
    if (count < *max_count) {
293
 
        codecs[count].type = PJMEDIA_TYPE_AUDIO;
294
 
        codecs[count].pt = PJMEDIA_RTP_PT_PCMA;
295
 
        codecs[count].encoding_name = pj_str("PCMA");
296
 
        codecs[count].clock_rate = 8000;
297
 
        codecs[count].channel_cnt = 1;
298
 
        ++count;
299
 
    }
300
 
 
301
 
    *max_count = count;
302
 
 
303
 
    return PJ_SUCCESS;
304
 
}
305
 
 
306
 
static pj_status_t g711_alloc_codec( pjmedia_codec_factory *factory,
307
 
                                     const pjmedia_codec_info *id,
308
 
                                     pjmedia_codec **p_codec)
309
 
{
310
 
    pjmedia_codec *codec = NULL;
311
 
    pj_status_t status;
312
 
 
313
 
    PJ_ASSERT_RETURN(factory==&g711_factory.base, PJ_EINVAL);
314
 
 
315
 
    /* Lock mutex. */
316
 
    pj_mutex_lock(g711_factory.mutex);
317
 
 
318
 
    /* Allocate new codec if no more is available */
319
 
    if (pj_list_empty(&g711_factory.codec_list)) {
320
 
        struct g711_private *codec_priv;
321
 
 
322
 
        codec = PJ_POOL_ALLOC_T(g711_factory.pool, pjmedia_codec);
323
 
        codec_priv = PJ_POOL_ZALLOC_T(g711_factory.pool, struct g711_private);
324
 
        if (!codec || !codec_priv) {
325
 
            pj_mutex_unlock(g711_factory.mutex);
326
 
            return PJ_ENOMEM;
327
 
        }
328
 
 
329
 
        /* Set the payload type */
330
 
        codec_priv->pt = id->pt;
331
 
 
332
 
#if !PLC_DISABLED
333
 
        /* Create PLC, always with 10ms ptime */
334
 
        status = pjmedia_plc_create(g711_factory.pool, 8000, 80,
335
 
                                    0, &codec_priv->plc);
336
 
        if (status != PJ_SUCCESS) {
337
 
            pj_mutex_unlock(g711_factory.mutex);
338
 
            return status;
339
 
        }
340
 
#endif
341
 
 
342
 
        /* Create VAD */
343
 
        status = pjmedia_silence_det_create(g711_factory.pool,
344
 
                                            8000, 80,
345
 
                                            &codec_priv->vad);
346
 
        if (status != PJ_SUCCESS) {
347
 
            pj_mutex_unlock(g711_factory.mutex);
348
 
            return status;
349
 
        }
350
 
 
351
 
        codec->factory = factory;
352
 
        codec->op = &g711_op;
353
 
        codec->codec_data = codec_priv;
354
 
    } else {
355
 
        codec = g711_factory.codec_list.next;
356
 
        pj_list_erase(codec);
357
 
    }
358
 
 
359
 
    /* Zero the list, for error detection in g711_dealloc_codec */
360
 
    codec->next = codec->prev = NULL;
361
 
 
362
 
    *p_codec = codec;
363
 
 
364
 
    /* Unlock mutex. */
365
 
    pj_mutex_unlock(g711_factory.mutex);
366
 
 
367
 
    return PJ_SUCCESS;
368
 
}
369
 
 
370
 
static pj_status_t g711_dealloc_codec(pjmedia_codec_factory *factory,
371
 
                                      pjmedia_codec *codec )
372
 
{
373
 
    struct g711_private *priv = (struct g711_private*) codec->codec_data;
374
 
    int i = 0;
375
 
 
376
 
    PJ_ASSERT_RETURN(factory==&g711_factory.base, PJ_EINVAL);
377
 
 
378
 
    /* Check that this node has not been deallocated before */
379
 
    pj_assert (codec->next==NULL && codec->prev==NULL);
380
 
    if (codec->next!=NULL || codec->prev!=NULL) {
381
 
        return PJ_EINVALIDOP;
382
 
    }
383
 
 
384
 
#if !PLC_DISABLED
385
 
    /* Clear left samples in the PLC, since codec+plc will be reused
386
 
     * next time.
387
 
     */
388
 
    for (i=0; i<2; ++i) {
389
 
        pj_int16_t frame[SAMPLES_PER_FRAME];
390
 
        pjmedia_zero_samples(frame, PJ_ARRAY_SIZE(frame));
391
 
        pjmedia_plc_save(priv->plc, frame);
392
 
    }
393
 
#else
394
 
    PJ_UNUSED_ARG(i);
395
 
    PJ_UNUSED_ARG(priv);
396
 
#endif
397
 
 
398
 
    /* Lock mutex. */
399
 
    pj_mutex_lock(g711_factory.mutex);
400
 
 
401
 
    /* Insert at the back of the list */
402
 
    pj_list_insert_before(&g711_factory.codec_list, codec);
403
 
 
404
 
    /* Unlock mutex. */
405
 
    pj_mutex_unlock(g711_factory.mutex);
406
 
 
407
 
    return PJ_SUCCESS;
408
 
}
409
 
 
410
 
static pj_status_t g711_init( pjmedia_codec *codec, pj_pool_t *pool )
411
 
{
412
 
    /* There's nothing to do here really */
413
 
    PJ_UNUSED_ARG(codec);
414
 
    PJ_UNUSED_ARG(pool);
415
 
 
416
 
    return PJ_SUCCESS;
417
 
}
418
 
 
419
 
static pj_status_t g711_open(pjmedia_codec *codec,
420
 
                             pjmedia_codec_param *attr )
421
 
{
422
 
    struct g711_private *priv = (struct g711_private*) codec->codec_data;
423
 
    priv->pt = attr->info.pt;
424
 
#if !PLC_DISABLED
425
 
    priv->plc_enabled = (attr->setting.plc != 0);
426
 
#endif
427
 
    priv->vad_enabled = (attr->setting.vad != 0);
428
 
    return PJ_SUCCESS;
429
 
}
430
 
 
431
 
static pj_status_t g711_close( pjmedia_codec *codec )
432
 
{
433
 
    PJ_UNUSED_ARG(codec);
434
 
    /* Nothing to do */
435
 
    return PJ_SUCCESS;
436
 
}
437
 
 
438
 
static pj_status_t  g711_modify(pjmedia_codec *codec,
439
 
                                const pjmedia_codec_param *attr )
440
 
{
441
 
    struct g711_private *priv = (struct g711_private*) codec->codec_data;
442
 
 
443
 
    if (attr->info.pt != priv->pt)
444
 
        return PJMEDIA_EINVALIDPT;
445
 
 
446
 
#if !PLC_DISABLED
447
 
    priv->plc_enabled = (attr->setting.plc != 0);
448
 
#endif
449
 
    priv->vad_enabled = (attr->setting.vad != 0);
450
 
 
451
 
    return PJ_SUCCESS;
452
 
}
453
 
 
454
 
static pj_status_t  g711_parse( pjmedia_codec *codec,
455
 
                                void *pkt,
456
 
                                pj_size_t pkt_size,
457
 
                                const pj_timestamp *ts,
458
 
                                unsigned *frame_cnt,
459
 
                                pjmedia_frame frames[])
460
 
{
461
 
    unsigned count = 0;
462
 
 
463
 
    PJ_UNUSED_ARG(codec);
464
 
 
465
 
    PJ_ASSERT_RETURN(ts && frame_cnt && frames, PJ_EINVAL);
466
 
 
467
 
    while (pkt_size >= FRAME_SIZE && count < *frame_cnt) {
468
 
        frames[count].type = PJMEDIA_FRAME_TYPE_AUDIO;
469
 
        frames[count].buf = pkt;
470
 
        frames[count].size = FRAME_SIZE;
471
 
        frames[count].timestamp.u64 = ts->u64 + SAMPLES_PER_FRAME * count;
472
 
 
473
 
        pkt = ((char*)pkt) + FRAME_SIZE;
474
 
        pkt_size -= FRAME_SIZE;
475
 
 
476
 
        ++count;
477
 
    }
478
 
 
479
 
    *frame_cnt = count;
480
 
    return PJ_SUCCESS;
481
 
}
482
 
 
483
 
static pj_status_t  g711_encode(pjmedia_codec *codec,
484
 
                                const struct pjmedia_frame *input,
485
 
                                unsigned output_buf_len,
486
 
                                struct pjmedia_frame *output)
487
 
{
488
 
    pj_int16_t *samples = (pj_int16_t*) input->buf;
489
 
    struct g711_private *priv = (struct g711_private*) codec->codec_data;
490
 
 
491
 
    /* Check output buffer length */
492
 
    if (output_buf_len < (input->size >> 1))
493
 
        return PJMEDIA_CODEC_EFRMTOOSHORT;
494
 
 
495
 
    /* Detect silence if VAD is enabled */
496
 
    if (priv->vad_enabled) {
497
 
        pj_bool_t is_silence;
498
 
        pj_int32_t silence_period;
499
 
 
500
 
        silence_period = pj_timestamp_diff32(&priv->last_tx,
501
 
                                             &input->timestamp);
502
 
 
503
 
        is_silence = pjmedia_silence_det_detect(priv->vad,
504
 
                                                (const pj_int16_t*) input->buf,
505
 
                                                (input->size >> 1), NULL);
506
 
        if (is_silence &&
507
 
            (PJMEDIA_CODEC_MAX_SILENCE_PERIOD == -1 ||
508
 
             silence_period < PJMEDIA_CODEC_MAX_SILENCE_PERIOD*8000/1000))
509
 
        {
510
 
            output->type = PJMEDIA_FRAME_TYPE_NONE;
511
 
            output->buf = NULL;
512
 
            output->size = 0;
513
 
            output->timestamp = input->timestamp;
514
 
            return PJ_SUCCESS;
515
 
        } else {
516
 
            priv->last_tx = input->timestamp;
517
 
        }
518
 
    }
519
 
 
520
 
    /* Encode */
521
 
    if (priv->pt == PJMEDIA_RTP_PT_PCMA) {
522
 
        unsigned i, n;
523
 
        pj_uint8_t *dst = (pj_uint8_t*) output->buf;
524
 
 
525
 
        n = (input->size >> 1);
526
 
        for (i=0; i!=n; ++i, ++dst) {
527
 
            *dst = pjmedia_linear2alaw(samples[i]);
528
 
        }
529
 
    } else if (priv->pt == PJMEDIA_RTP_PT_PCMU) {
530
 
        unsigned i, n;
531
 
        pj_uint8_t *dst = (pj_uint8_t*) output->buf;
532
 
 
533
 
        n = (input->size >> 1);
534
 
        for (i=0; i!=n; ++i, ++dst) {
535
 
            *dst = pjmedia_linear2ulaw(samples[i]);
536
 
        }
537
 
 
538
 
    } else {
539
 
        return PJMEDIA_EINVALIDPT;
540
 
    }
541
 
 
542
 
    output->type = PJMEDIA_FRAME_TYPE_AUDIO;
543
 
    output->size = (input->size >> 1);
544
 
    output->timestamp = input->timestamp;
545
 
 
546
 
    return PJ_SUCCESS;
547
 
}
548
 
 
549
 
static pj_status_t  g711_decode(pjmedia_codec *codec,
550
 
                                const struct pjmedia_frame *input,
551
 
                                unsigned output_buf_len,
552
 
                                struct pjmedia_frame *output)
553
 
{
554
 
    struct g711_private *priv = (struct g711_private*) codec->codec_data;
555
 
 
556
 
    /* Check output buffer length */
557
 
    PJ_ASSERT_RETURN(output_buf_len >= (input->size << 1),
558
 
                     PJMEDIA_CODEC_EPCMTOOSHORT);
559
 
 
560
 
    /* Input buffer MUST have exactly 80 bytes long */
561
 
    PJ_ASSERT_RETURN(input->size == FRAME_SIZE,
562
 
                     PJMEDIA_CODEC_EFRMINLEN);
563
 
 
564
 
    /* Decode */
565
 
    if (priv->pt == PJMEDIA_RTP_PT_PCMA) {
566
 
        unsigned i;
567
 
        pj_uint8_t *src = (pj_uint8_t*) input->buf;
568
 
        pj_uint16_t *dst = (pj_uint16_t*) output->buf;
569
 
 
570
 
        for (i=0; i!=input->size; ++i) {
571
 
            *dst++ = (pj_uint16_t) pjmedia_alaw2linear(*src++);
572
 
        }
573
 
    } else if (priv->pt == PJMEDIA_RTP_PT_PCMU) {
574
 
        unsigned i;
575
 
        pj_uint8_t *src = (pj_uint8_t*) input->buf;
576
 
        pj_uint16_t *dst = (pj_uint16_t*) output->buf;
577
 
 
578
 
        for (i=0; i!=input->size; ++i) {
579
 
            *dst++ = (pj_uint16_t) pjmedia_ulaw2linear(*src++);
580
 
        }
581
 
 
582
 
    } else {
583
 
        return PJMEDIA_EINVALIDPT;
584
 
    }
585
 
 
586
 
    output->type = PJMEDIA_FRAME_TYPE_AUDIO;
587
 
    output->size = (input->size << 1);
588
 
    output->timestamp = input->timestamp;
589
 
 
590
 
#if !PLC_DISABLED
591
 
    if (priv->plc_enabled)
592
 
        pjmedia_plc_save( priv->plc, (pj_int16_t*)output->buf);
593
 
#endif
594
 
 
595
 
    return PJ_SUCCESS;
596
 
}
597
 
 
598
 
#if !PLC_DISABLED
599
 
static pj_status_t  g711_recover( pjmedia_codec *codec,
600
 
                                  unsigned output_buf_len,
601
 
                                  struct pjmedia_frame *output)
602
 
{
603
 
    struct g711_private *priv = (struct g711_private*) codec->codec_data;
604
 
 
605
 
    if (!priv->plc_enabled)
606
 
        return PJ_EINVALIDOP;
607
 
 
608
 
    PJ_ASSERT_RETURN(output_buf_len >= SAMPLES_PER_FRAME * 2,
609
 
                     PJMEDIA_CODEC_EPCMTOOSHORT);
610
 
 
611
 
    pjmedia_plc_generate(priv->plc, (pj_int16_t*)output->buf);
612
 
    output->size = SAMPLES_PER_FRAME * 2;
613
 
 
614
 
    return PJ_SUCCESS;
615
 
}
616
 
#endif
617
 
 
618
 
#endif  /* PJMEDIA_HAS_G711_CODEC */