summaryrefslogtreecommitdiffstats
path: root/plugins/codecs/iLBC/iLBCdecode.c
blob: d127f1608d6d1d1897aceac0fd182ec44831d81b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
/* iLBCdecode.c
 * iLBC codec
 *
 * Wireshark - Network traffic analyzer
 * By Gerald Combs <gerald@wireshark.org>
 * Copyright 1998 Gerald Combs
 *
 * SPDX-License-Identifier: GPL-2.0-or-later
 */

#include "config.h"

#include <stdio.h>

#include <glib.h>

#include "ilbc.h"
#include "wsutil/codecs.h"
#include "ws_attributes.h"

#define ILBC_20MS 20
#define ILBC_30MS 30
#define ILBC_PAYLOAD_LEN_20MS 38
#define ILBC_PAYLOAD_LEN_30MS 50
#define SAMPLE_SIZE 2

typedef struct {
#ifdef LIBILBC_VERSION_MAJOR
    IlbcDecoderInstance *ilbc_ctx;  /* Real iLBC context */
#else
    iLBC_decinst_t *ilbc_ctx;  /* Real iLBC context */
#endif
    guint8 payload_len; /* Remember last payload_len */
} ilbc_ctx_t;

void codec_register_iLBC(void);

static void *
codec_iLBC_init(codec_context_t *ctx _U_)
{
    ilbc_ctx_t *priv;

    priv=(ilbc_ctx_t *)g_malloc0(sizeof(*priv));
    WebRtcIlbcfix_DecoderCreate(&(priv->ilbc_ctx));

    return priv;
}

static void
codec_iLBC_release(codec_context_t *ctx)
{
    WebRtcIlbcfix_DecoderFree(((ilbc_ctx_t *)ctx->priv)->ilbc_ctx);
    g_free(ctx);
}

static unsigned
codec_iLBC_get_channels(codec_context_t *ctx _U_)
{
    return 1;
}

static unsigned
codec_iLBC_get_frequency(codec_context_t *ctx _U_)
{
    return 8000;
}

static size_t
codec_iLBC_decode(codec_context_t *ctx,
        const void *inputBytes, size_t inputBytesSize,
        void *outputSamples, size_t *outputSamplesSize)
{
    int16_t speechType; // Not used in Wireshark code
#ifdef LIBILBC_VERSION_MAJOR
    int8_t *dataIn  = (int8_t *)inputBytes;
#else
    int16_t *dataIn  = (int16_t *)inputBytes;
#endif
    int16_t *dataOut = (int16_t *)outputSamples;
    ilbc_ctx_t *dataCtx = (ilbc_ctx_t *)ctx->priv;
    size_t outputSamplesCount;

    if (!outputSamples || !outputSamplesSize)
    {
        if (0 == inputBytesSize%ILBC_PAYLOAD_LEN_20MS) {
            /* 20ms packet size = 160 samples = 320 bytes */
            return BLOCKL_20MS*SAMPLE_SIZE;
        } else if (0 == inputBytesSize%ILBC_PAYLOAD_LEN_30MS) {
            /* 30ms packet size = 240 samples = 480 bytes */
            return BLOCKL_30MS*SAMPLE_SIZE;
        } else {
            /* unknown packet size */
            return 0;
        }
    }

    if (0 == inputBytesSize%ILBC_PAYLOAD_LEN_20MS) {
        /* 20ms packet size */
        if (dataCtx->payload_len != ILBC_20MS) {
            WebRtcIlbcfix_DecoderInit(dataCtx->ilbc_ctx, ILBC_20MS);
            dataCtx->payload_len = ILBC_20MS;
        }
        outputSamplesCount = WebRtcIlbcfix_Decode(dataCtx->ilbc_ctx, dataIn,
                               (int16_t)inputBytesSize, dataOut, &speechType);
    } else if (0 == inputBytesSize%ILBC_PAYLOAD_LEN_30MS) {
        /* 30ms packet size */
        if (dataCtx->payload_len != ILBC_30MS) {
            WebRtcIlbcfix_DecoderInit(dataCtx->ilbc_ctx, ILBC_30MS);
            dataCtx->payload_len = ILBC_30MS;
        }
        outputSamplesCount = WebRtcIlbcfix_Decode(dataCtx->ilbc_ctx, dataIn,
                               (int16_t)inputBytesSize, dataOut, &speechType);
    } else {
        /* unknown packet size */
        outputSamplesCount = 0;
    }

    /* WebRtcIlbcfix_Decode returns count of samples, but we return count of bytes */
    *outputSamplesSize = outputSamplesCount*SAMPLE_SIZE;
    return *outputSamplesSize;
}

void
codec_register_iLBC(void)
{
    register_codec("iLBC", codec_iLBC_init, codec_iLBC_release,
            codec_iLBC_get_channels, codec_iLBC_get_frequency, codec_iLBC_decode);
}

/*
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
 *
 * Local variables:
 * c-basic-offset: 4
 * tab-width: 8
 * indent-tabs-mode: nil
 * End:
 *
 * vi: set shiftwidth=4 tabstop=8 expandtab:
 * :indentSize=4:tabSize=8:noTabs=true:
 */