1cabdff1aSopenharmony_ci/*
2cabdff1aSopenharmony_ci * RTP Depacketization of QCELP/PureVoice, RFC 2658
3cabdff1aSopenharmony_ci * Copyright (c) 2010 Martin Storsjo
4cabdff1aSopenharmony_ci *
5cabdff1aSopenharmony_ci * This file is part of FFmpeg.
6cabdff1aSopenharmony_ci *
7cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or
8cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public
9cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either
10cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version.
11cabdff1aSopenharmony_ci *
12cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful,
13cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of
14cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15cabdff1aSopenharmony_ci * Lesser General Public License for more details.
16cabdff1aSopenharmony_ci *
17cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public
18cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software
19cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20cabdff1aSopenharmony_ci */
21cabdff1aSopenharmony_ci
22cabdff1aSopenharmony_ci#include "rtpdec_formats.h"
23cabdff1aSopenharmony_ci
24cabdff1aSopenharmony_cistatic const uint8_t frame_sizes[] = {
25cabdff1aSopenharmony_ci    1, 4, 8, 17, 35
26cabdff1aSopenharmony_ci};
27cabdff1aSopenharmony_ci
28cabdff1aSopenharmony_citypedef struct InterleavePacket {
29cabdff1aSopenharmony_ci    int pos;
30cabdff1aSopenharmony_ci    int size;
31cabdff1aSopenharmony_ci    /* The largest frame is 35 bytes, only 10 frames are allowed per
32cabdff1aSopenharmony_ci     * packet, and we return the first one immediately, so allocate
33cabdff1aSopenharmony_ci     * space for 9 frames */
34cabdff1aSopenharmony_ci    uint8_t data[35*9];
35cabdff1aSopenharmony_ci} InterleavePacket;
36cabdff1aSopenharmony_ci
37cabdff1aSopenharmony_cistruct PayloadContext {
38cabdff1aSopenharmony_ci    int interleave_size;
39cabdff1aSopenharmony_ci    int interleave_index;
40cabdff1aSopenharmony_ci    InterleavePacket group[6];
41cabdff1aSopenharmony_ci    int group_finished;
42cabdff1aSopenharmony_ci
43cabdff1aSopenharmony_ci    /* The maximum packet size, 10 frames of 35 bytes each, and one
44cabdff1aSopenharmony_ci     * packet header byte. */
45cabdff1aSopenharmony_ci    uint8_t  next_data[1 + 35*10];
46cabdff1aSopenharmony_ci    int      next_size;
47cabdff1aSopenharmony_ci    uint32_t next_timestamp;
48cabdff1aSopenharmony_ci};
49cabdff1aSopenharmony_ci
50cabdff1aSopenharmony_cistatic int return_stored_frame(AVFormatContext *ctx, PayloadContext *data,
51cabdff1aSopenharmony_ci                               AVStream *st, AVPacket *pkt, uint32_t *timestamp,
52cabdff1aSopenharmony_ci                               const uint8_t *buf, int len);
53cabdff1aSopenharmony_ci
54cabdff1aSopenharmony_cistatic int store_packet(AVFormatContext *ctx, PayloadContext *data,
55cabdff1aSopenharmony_ci                        AVStream *st, AVPacket *pkt, uint32_t *timestamp,
56cabdff1aSopenharmony_ci                        const uint8_t *buf, int len)
57cabdff1aSopenharmony_ci{
58cabdff1aSopenharmony_ci    int interleave_size, interleave_index;
59cabdff1aSopenharmony_ci    int frame_size, ret;
60cabdff1aSopenharmony_ci    InterleavePacket* ip;
61cabdff1aSopenharmony_ci
62cabdff1aSopenharmony_ci    if (len < 2)
63cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
64cabdff1aSopenharmony_ci
65cabdff1aSopenharmony_ci    interleave_size  = buf[0] >> 3 & 7;
66cabdff1aSopenharmony_ci    interleave_index = buf[0]      & 7;
67cabdff1aSopenharmony_ci
68cabdff1aSopenharmony_ci    if (interleave_size > 5) {
69cabdff1aSopenharmony_ci        av_log(ctx, AV_LOG_ERROR, "Invalid interleave size %d\n",
70cabdff1aSopenharmony_ci                                   interleave_size);
71cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
72cabdff1aSopenharmony_ci    }
73cabdff1aSopenharmony_ci    if (interleave_index > interleave_size) {
74cabdff1aSopenharmony_ci        av_log(ctx, AV_LOG_ERROR, "Invalid interleave index %d/%d\n",
75cabdff1aSopenharmony_ci                                   interleave_index, interleave_size);
76cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
77cabdff1aSopenharmony_ci    }
78cabdff1aSopenharmony_ci    if (interleave_size != data->interleave_size) {
79cabdff1aSopenharmony_ci        int i;
80cabdff1aSopenharmony_ci        /* First packet, or changed interleave size */
81cabdff1aSopenharmony_ci        data->interleave_size = interleave_size;
82cabdff1aSopenharmony_ci        data->interleave_index = 0;
83cabdff1aSopenharmony_ci        for (i = 0; i < 6; i++)
84cabdff1aSopenharmony_ci            data->group[i].size = 0;
85cabdff1aSopenharmony_ci    }
86cabdff1aSopenharmony_ci
87cabdff1aSopenharmony_ci    if (interleave_index < data->interleave_index) {
88cabdff1aSopenharmony_ci        /* Wrapped around - missed the last packet of the previous group. */
89cabdff1aSopenharmony_ci        if (data->group_finished) {
90cabdff1aSopenharmony_ci            /* No more data in the packets in this interleaving group, just
91cabdff1aSopenharmony_ci             * start processing the next one */
92cabdff1aSopenharmony_ci            data->interleave_index = 0;
93cabdff1aSopenharmony_ci        } else {
94cabdff1aSopenharmony_ci            /* Stash away the current packet, emit everything we have of the
95cabdff1aSopenharmony_ci             * previous group. */
96cabdff1aSopenharmony_ci            for (; data->interleave_index <= interleave_size;
97cabdff1aSopenharmony_ci                 data->interleave_index++)
98cabdff1aSopenharmony_ci                data->group[data->interleave_index].size = 0;
99cabdff1aSopenharmony_ci
100cabdff1aSopenharmony_ci            if (len > sizeof(data->next_data))
101cabdff1aSopenharmony_ci                return AVERROR_INVALIDDATA;
102cabdff1aSopenharmony_ci            memcpy(data->next_data, buf, len);
103cabdff1aSopenharmony_ci            data->next_size = len;
104cabdff1aSopenharmony_ci            data->next_timestamp = *timestamp;
105cabdff1aSopenharmony_ci            *timestamp = RTP_NOTS_VALUE;
106cabdff1aSopenharmony_ci
107cabdff1aSopenharmony_ci            data->interleave_index = 0;
108cabdff1aSopenharmony_ci            return return_stored_frame(ctx, data, st, pkt, timestamp, buf, len);
109cabdff1aSopenharmony_ci        }
110cabdff1aSopenharmony_ci    }
111cabdff1aSopenharmony_ci    if (interleave_index > data->interleave_index) {
112cabdff1aSopenharmony_ci        /* We missed a packet */
113cabdff1aSopenharmony_ci        for (; data->interleave_index < interleave_index;
114cabdff1aSopenharmony_ci             data->interleave_index++)
115cabdff1aSopenharmony_ci            data->group[data->interleave_index].size = 0;
116cabdff1aSopenharmony_ci    }
117cabdff1aSopenharmony_ci    data->interleave_index = interleave_index;
118cabdff1aSopenharmony_ci
119cabdff1aSopenharmony_ci    if (buf[1] >= FF_ARRAY_ELEMS(frame_sizes))
120cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
121cabdff1aSopenharmony_ci    frame_size = frame_sizes[buf[1]];
122cabdff1aSopenharmony_ci    if (1 + frame_size > len)
123cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
124cabdff1aSopenharmony_ci
125cabdff1aSopenharmony_ci    if (len - 1 - frame_size > sizeof(data->group[0].data))
126cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
127cabdff1aSopenharmony_ci
128cabdff1aSopenharmony_ci    if ((ret = av_new_packet(pkt, frame_size)) < 0)
129cabdff1aSopenharmony_ci        return ret;
130cabdff1aSopenharmony_ci    memcpy(pkt->data, &buf[1], frame_size);
131cabdff1aSopenharmony_ci    pkt->stream_index = st->index;
132cabdff1aSopenharmony_ci
133cabdff1aSopenharmony_ci    ip = &data->group[data->interleave_index];
134cabdff1aSopenharmony_ci    ip->size = len - 1 - frame_size;
135cabdff1aSopenharmony_ci    ip->pos = 0;
136cabdff1aSopenharmony_ci    memcpy(ip->data, &buf[1 + frame_size], ip->size);
137cabdff1aSopenharmony_ci    /* Each packet must contain the same number of frames according to the
138cabdff1aSopenharmony_ci     * RFC. If there's no data left in this packet, there shouldn't be any
139cabdff1aSopenharmony_ci     * in any of the other frames in the interleaving group either. */
140cabdff1aSopenharmony_ci    data->group_finished = ip->size == 0;
141cabdff1aSopenharmony_ci
142cabdff1aSopenharmony_ci    if (interleave_index == interleave_size) {
143cabdff1aSopenharmony_ci        data->interleave_index = 0;
144cabdff1aSopenharmony_ci        return !data->group_finished;
145cabdff1aSopenharmony_ci    } else {
146cabdff1aSopenharmony_ci        data->interleave_index++;
147cabdff1aSopenharmony_ci        return 0;
148cabdff1aSopenharmony_ci    }
149cabdff1aSopenharmony_ci}
150cabdff1aSopenharmony_ci
151cabdff1aSopenharmony_cistatic int return_stored_frame(AVFormatContext *ctx, PayloadContext *data,
152cabdff1aSopenharmony_ci                               AVStream *st, AVPacket *pkt, uint32_t *timestamp,
153cabdff1aSopenharmony_ci                               const uint8_t *buf, int len)
154cabdff1aSopenharmony_ci{
155cabdff1aSopenharmony_ci    InterleavePacket* ip = &data->group[data->interleave_index];
156cabdff1aSopenharmony_ci    int frame_size, ret;
157cabdff1aSopenharmony_ci
158cabdff1aSopenharmony_ci    if (data->group_finished && data->interleave_index == 0) {
159cabdff1aSopenharmony_ci        *timestamp = data->next_timestamp;
160cabdff1aSopenharmony_ci        ret = store_packet(ctx, data, st, pkt, timestamp, data->next_data,
161cabdff1aSopenharmony_ci                           data->next_size);
162cabdff1aSopenharmony_ci        data->next_size = 0;
163cabdff1aSopenharmony_ci        return ret;
164cabdff1aSopenharmony_ci    }
165cabdff1aSopenharmony_ci
166cabdff1aSopenharmony_ci    if (ip->size == 0) {
167cabdff1aSopenharmony_ci        /* No stored data for this interleave block, output an empty packet */
168cabdff1aSopenharmony_ci        if ((ret = av_new_packet(pkt, 1)) < 0)
169cabdff1aSopenharmony_ci            return ret;
170cabdff1aSopenharmony_ci        pkt->data[0] = 0; // Blank - could also be 14, Erasure
171cabdff1aSopenharmony_ci    } else {
172cabdff1aSopenharmony_ci        if (ip->pos >= ip->size)
173cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
174cabdff1aSopenharmony_ci        if (ip->data[ip->pos] >= FF_ARRAY_ELEMS(frame_sizes))
175cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
176cabdff1aSopenharmony_ci        frame_size = frame_sizes[ip->data[ip->pos]];
177cabdff1aSopenharmony_ci        if (ip->pos + frame_size > ip->size)
178cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
179cabdff1aSopenharmony_ci
180cabdff1aSopenharmony_ci        if ((ret = av_new_packet(pkt, frame_size)) < 0)
181cabdff1aSopenharmony_ci            return ret;
182cabdff1aSopenharmony_ci        memcpy(pkt->data, &ip->data[ip->pos], frame_size);
183cabdff1aSopenharmony_ci
184cabdff1aSopenharmony_ci        ip->pos += frame_size;
185cabdff1aSopenharmony_ci        data->group_finished = ip->pos >= ip->size;
186cabdff1aSopenharmony_ci    }
187cabdff1aSopenharmony_ci    pkt->stream_index = st->index;
188cabdff1aSopenharmony_ci
189cabdff1aSopenharmony_ci    if (data->interleave_index == data->interleave_size) {
190cabdff1aSopenharmony_ci        data->interleave_index = 0;
191cabdff1aSopenharmony_ci        if (!data->group_finished)
192cabdff1aSopenharmony_ci            return 1;
193cabdff1aSopenharmony_ci        else
194cabdff1aSopenharmony_ci            return data->next_size > 0;
195cabdff1aSopenharmony_ci    } else {
196cabdff1aSopenharmony_ci        data->interleave_index++;
197cabdff1aSopenharmony_ci        return 1;
198cabdff1aSopenharmony_ci    }
199cabdff1aSopenharmony_ci}
200cabdff1aSopenharmony_ci
201cabdff1aSopenharmony_cistatic int qcelp_parse_packet(AVFormatContext *ctx, PayloadContext *data,
202cabdff1aSopenharmony_ci                              AVStream *st, AVPacket *pkt, uint32_t *timestamp,
203cabdff1aSopenharmony_ci                              const uint8_t *buf, int len, uint16_t seq,
204cabdff1aSopenharmony_ci                              int flags)
205cabdff1aSopenharmony_ci{
206cabdff1aSopenharmony_ci    if (buf)
207cabdff1aSopenharmony_ci        return store_packet(ctx, data, st, pkt, timestamp, buf, len);
208cabdff1aSopenharmony_ci    else
209cabdff1aSopenharmony_ci        return return_stored_frame(ctx, data, st, pkt, timestamp, buf, len);
210cabdff1aSopenharmony_ci}
211cabdff1aSopenharmony_ci
212cabdff1aSopenharmony_ciconst RTPDynamicProtocolHandler ff_qcelp_dynamic_handler = {
213cabdff1aSopenharmony_ci    .enc_name           = "x-Purevoice",
214cabdff1aSopenharmony_ci    .codec_type         = AVMEDIA_TYPE_AUDIO,
215cabdff1aSopenharmony_ci    .codec_id           = AV_CODEC_ID_QCELP,
216cabdff1aSopenharmony_ci    .priv_data_size     = sizeof(PayloadContext),
217cabdff1aSopenharmony_ci    .static_payload_id  = 12,
218cabdff1aSopenharmony_ci    .parse_packet       = qcelp_parse_packet,
219cabdff1aSopenharmony_ci};
220