1 /* Copyright (C)2012 Xiph.Org Foundation
2 Copyright (C)2012 Gregory Maxwell
3 Copyright (C)2012 Jean-Marc Valin
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions
10 - Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
13 - Redistributions in binary form must reproduce the above copyright
14 notice, this list of conditions and the following disclaimer in the
15 documentation and/or other materials provided with the distribution.
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
21 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 #define I64FORMAT "I64d"
36 #define I64uFORMAT "I64u"
38 #define I64FORMAT "lld"
39 #define I64uFORMAT "llu"
44 #include "diag_range.h"
46 /*This is some non-exported code copied wholesale from libopus.
47 *Normal programs shouldn't need these functions, but we use them here
48 *to parse deep inside multichannel packets in order to get diagnostic
49 *data for save-range. If you're thinking about copying it and you aren't
50 *making an opus stream diagnostic tool, you're probably doing something
52 static int parse_size(const unsigned char *data, opus_int32 len, short *size)
58 } else if (data[0]<252)
67 *size = 4*data[1] + data[0];
72 static int opus_packet_parse_impl(const unsigned char *data, opus_int32 len,
73 int self_delimited, unsigned char *out_toc,
74 const unsigned char *frames[48], short size[48], int *payload_offset)
79 unsigned char ch, toc;
82 const unsigned char *data0 = data;
87 framesize = opus_packet_get_samples_per_frame(data, 48000);
106 return OPUS_INVALID_PACKET;
107 size[0] = last_size = len/2;
113 bytes = parse_size(data, len, size);
115 if (size[0]<0 || size[0] > len)
116 return OPUS_INVALID_PACKET;
118 last_size = len-size[0];
120 /* Multiple CBR/VBR frames (from 0 to 120 ms) */
123 return OPUS_INVALID_PACKET;
124 /* Number of frames encoded in bits 0 to 5 */
127 if (count <= 0 || framesize*count > 5760)
128 return OPUS_INVALID_PACKET;
130 /* Padding flag is bit 6 */
137 return OPUS_INVALID_PACKET;
140 padding += p==255 ? 254: p;
145 return OPUS_INVALID_PACKET;
146 /* VBR flag is bit 7 */
152 for (i=0;i<count-1;i++)
154 bytes = parse_size(data, len, size+i);
156 if (size[i]<0 || size[i] > len)
157 return OPUS_INVALID_PACKET;
159 last_size -= bytes+size[i];
162 return OPUS_INVALID_PACKET;
163 } else if (!self_delimited)
166 last_size = len/count;
167 if (last_size*count!=len)
168 return OPUS_INVALID_PACKET;
169 for (i=0;i<count-1;i++)
174 /* Self-delimited framing has an extra size for the last frame. */
177 bytes = parse_size(data, len, size+count-1);
179 if (size[count-1]<0 || size[count-1] > len)
180 return OPUS_INVALID_PACKET;
182 /* For CBR packets, apply the size to all the frames. */
185 if (size[count-1]*count > len)
186 return OPUS_INVALID_PACKET;
187 for (i=0;i<count-1;i++)
188 size[i] = size[count-1];
189 } else if(size[count-1] > last_size)
190 return OPUS_INVALID_PACKET;
193 /* Because it's not encoded explicitly, it's possible the size of the
194 last packet (or all the packets, for the CBR case) is larger than
195 1275. Reject them here.*/
196 if (last_size > 1275)
197 return OPUS_INVALID_PACKET;
198 size[count-1] = last_size;
203 for (i=0;i<count;i++)
214 *payload_offset = data-data0;
219 void save_range(FILE *frange, int frame_size, unsigned char *packet, int nbBytes, opus_uint32 *rngs, int nb_streams){
221 const unsigned char *subpkt;
222 static const char *bw_strings[5]={"NB","MB","WB","SWB","FB"};
223 static const char *mode_strings[3]={"LP","HYB","MDCT"};
224 fprintf(frange,"%d, %d, ",frame_size,nbBytes);
227 for(i=0;i<nb_streams;i++){
228 int j,payload_offset,nf;
229 const unsigned char *frames[48];
233 nf=opus_packet_parse_impl(subpkt,parsed_size,i+1!=nb_streams,
234 &toc,frames,size,&payload_offset);
235 fprintf(frange,"[[%d",(int)(frames[0]-subpkt));
236 for(j=0;j<nf;j++)fprintf(frange,", %d",size[j]);
237 fprintf(frange,"], %s, %s, %c, %d",
238 mode_strings[((((subpkt[0]>>3)+48)&92)+4)>>5],
239 bw_strings[opus_packet_get_bandwidth(subpkt)-OPUS_BANDWIDTH_NARROWBAND],
240 subpkt[0]&4?'S':'M',opus_packet_get_samples_per_frame(subpkt,48000));
241 fprintf(frange,", %" I64uFORMAT "]%s",(unsigned long long)rngs[i],i+1==nb_streams?"\n":", ");
242 parsed_size-=payload_offset;
243 subpkt+=payload_offset;