annotate ffmpeg/libavformat/rtpdec_qcelp.c @ 13:844d341cf643 tip

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