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