Libav 0.7.1
|
00001 00022 #include "rtpdec_formats.h" 00023 00024 static const uint8_t frame_sizes[] = { 00025 1, 4, 8, 17, 35 00026 }; 00027 00028 typedef struct { 00029 int pos; 00030 int size; 00031 /* The largest frame is 35 bytes, only 10 frames are allowed per 00032 * packet, and we return the first one immediately, so allocate 00033 * space for 9 frames */ 00034 uint8_t data[35*9]; 00035 } InterleavePacket; 00036 00037 struct PayloadContext { 00038 int interleave_size; 00039 int interleave_index; 00040 InterleavePacket group[6]; 00041 int group_finished; 00042 00043 /* The maximum packet size, 10 frames of 35 bytes each, and one 00044 * packet header byte. */ 00045 uint8_t next_data[1 + 35*10]; 00046 int next_size; 00047 uint32_t next_timestamp; 00048 }; 00049 00050 static PayloadContext *qcelp_new_context(void) 00051 { 00052 return av_mallocz(sizeof(PayloadContext)); 00053 } 00054 00055 static void qcelp_free_context(PayloadContext *data) 00056 { 00057 av_free(data); 00058 } 00059 00060 static int return_stored_frame(AVFormatContext *ctx, PayloadContext *data, 00061 AVStream *st, AVPacket *pkt, uint32_t *timestamp, 00062 const uint8_t *buf, int len); 00063 00064 static int store_packet(AVFormatContext *ctx, PayloadContext *data, 00065 AVStream *st, AVPacket *pkt, uint32_t *timestamp, 00066 const uint8_t *buf, int len) 00067 { 00068 int interleave_size, interleave_index; 00069 int frame_size, ret; 00070 InterleavePacket* ip; 00071 00072 if (len < 2) 00073 return AVERROR_INVALIDDATA; 00074 00075 interleave_size = buf[0] >> 3 & 7; 00076 interleave_index = buf[0] & 7; 00077 00078 if (interleave_size > 5) { 00079 av_log(ctx, AV_LOG_ERROR, "Invalid interleave size %d\n", 00080 interleave_size); 00081 return AVERROR_INVALIDDATA; 00082 } 00083 if (interleave_index > interleave_size) { 00084 av_log(ctx, AV_LOG_ERROR, "Invalid interleave index %d/%d\n", 00085 interleave_index, interleave_size); 00086 return AVERROR_INVALIDDATA; 00087 } 00088 if (interleave_size != data->interleave_size) { 00089 int i; 00090 /* First packet, or changed interleave size */ 00091 data->interleave_size = interleave_size; 00092 data->interleave_index = 0; 00093 for (i = 0; i < 6; i++) 00094 data->group[i].size = 0; 00095 } 00096 00097 if (interleave_index < data->interleave_index) { 00098 /* Wrapped around - missed the last packet of the previous group. */ 00099 if (data->group_finished) { 00100 /* No more data in the packets in this interleaving group, just 00101 * start processing the next one */ 00102 data->interleave_index = 0; 00103 } else { 00104 /* Stash away the current packet, emit everything we have of the 00105 * previous group. */ 00106 for (; data->interleave_index <= interleave_size; 00107 data->interleave_index++) 00108 data->group[data->interleave_index].size = 0; 00109 00110 if (len > sizeof(data->next_data)) 00111 return AVERROR_INVALIDDATA; 00112 memcpy(data->next_data, buf, len); 00113 data->next_size = len; 00114 data->next_timestamp = *timestamp; 00115 *timestamp = RTP_NOTS_VALUE; 00116 00117 data->interleave_index = 0; 00118 return return_stored_frame(ctx, data, st, pkt, timestamp, buf, len); 00119 } 00120 } 00121 if (interleave_index > data->interleave_index) { 00122 /* We missed a packet */ 00123 for (; data->interleave_index < interleave_index; 00124 data->interleave_index++) 00125 data->group[data->interleave_index].size = 0; 00126 } 00127 data->interleave_index = interleave_index; 00128 00129 if (buf[1] >= FF_ARRAY_ELEMS(frame_sizes)) 00130 return AVERROR_INVALIDDATA; 00131 frame_size = frame_sizes[buf[1]]; 00132 if (1 + frame_size > len) 00133 return AVERROR_INVALIDDATA; 00134 00135 if (len - 1 - frame_size > sizeof(data->group[0].data)) 00136 return AVERROR_INVALIDDATA; 00137 00138 if ((ret = av_new_packet(pkt, frame_size)) < 0) 00139 return ret; 00140 memcpy(pkt->data, &buf[1], frame_size); 00141 pkt->stream_index = st->index; 00142 00143 ip = &data->group[data->interleave_index]; 00144 ip->size = len - 1 - frame_size; 00145 ip->pos = 0; 00146 memcpy(ip->data, &buf[1 + frame_size], ip->size); 00147 /* Each packet must contain the same number of frames according to the 00148 * RFC. If there's no data left in this packet, there shouldn't be any 00149 * in any of the other frames in the interleaving group either. */ 00150 data->group_finished = ip->size == 0; 00151 00152 if (interleave_index == interleave_size) { 00153 data->interleave_index = 0; 00154 return !data->group_finished; 00155 } else { 00156 data->interleave_index++; 00157 return 0; 00158 } 00159 } 00160 00161 static int return_stored_frame(AVFormatContext *ctx, PayloadContext *data, 00162 AVStream *st, AVPacket *pkt, uint32_t *timestamp, 00163 const uint8_t *buf, int len) 00164 { 00165 InterleavePacket* ip = &data->group[data->interleave_index]; 00166 int frame_size, ret; 00167 00168 if (data->group_finished && data->interleave_index == 0) { 00169 *timestamp = data->next_timestamp; 00170 ret = store_packet(ctx, data, st, pkt, timestamp, data->next_data, 00171 data->next_size); 00172 data->next_size = 0; 00173 return ret; 00174 } 00175 00176 if (ip->size == 0) { 00177 /* No stored data for this interleave block, output an empty packet */ 00178 if ((ret = av_new_packet(pkt, 1)) < 0) 00179 return ret; 00180 pkt->data[0] = 0; // Blank - could also be 14, Erasure 00181 } else { 00182 if (ip->pos >= ip->size) 00183 return AVERROR_INVALIDDATA; 00184 if (ip->data[ip->pos] >= FF_ARRAY_ELEMS(frame_sizes)) 00185 return AVERROR_INVALIDDATA; 00186 frame_size = frame_sizes[ip->data[ip->pos]]; 00187 if (ip->pos + frame_size > ip->size) 00188 return AVERROR_INVALIDDATA; 00189 00190 if ((ret = av_new_packet(pkt, frame_size)) < 0) 00191 return ret; 00192 memcpy(pkt->data, &ip->data[ip->pos], frame_size); 00193 00194 ip->pos += frame_size; 00195 data->group_finished = ip->pos >= ip->size; 00196 } 00197 pkt->stream_index = st->index; 00198 00199 if (data->interleave_index == data->interleave_size) { 00200 data->interleave_index = 0; 00201 if (!data->group_finished) 00202 return 1; 00203 else 00204 return data->next_size > 0; 00205 } else { 00206 data->interleave_index++; 00207 return 1; 00208 } 00209 } 00210 00211 static int qcelp_parse_packet(AVFormatContext *ctx, PayloadContext *data, 00212 AVStream *st, AVPacket *pkt, uint32_t *timestamp, 00213 const uint8_t *buf, int len, int flags) 00214 { 00215 if (buf) 00216 return store_packet(ctx, data, st, pkt, timestamp, buf, len); 00217 else 00218 return return_stored_frame(ctx, data, st, pkt, timestamp, buf, len); 00219 } 00220 00221 RTPDynamicProtocolHandler ff_qcelp_dynamic_handler = { 00222 .enc_name = "x-Purevoice", 00223 .codec_type = AVMEDIA_TYPE_AUDIO, 00224 .codec_id = CODEC_ID_QCELP, 00225 .static_payload_id = 12, 00226 .alloc = qcelp_new_context, 00227 .free = qcelp_free_context, 00228 .parse_packet = qcelp_parse_packet 00229 };