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