1 /* Copyright (c) 2011 Xiph.Org Foundation
2 Written by Jean-Marc Valin */
3 /*
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions
6 are met:
7
8 - Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10
11 - Redistributions in binary form must reproduce the above copyright
12 notice, this list of conditions and the following disclaimer in the
13 documentation and/or other materials provided with the distribution.
14
15 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
19 OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 #ifdef HAVE_CONFIG_H
29 #include "config.h"
30 #endif
31
32 #include "opus.h"
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36
37 #define MAX_PACKETOUT 32000
38
usage(char * argv0)39 void usage(char *argv0)
40 {
41 fprintf(stderr, "usage: %s [options] input_file output_file\n", argv0);
42 }
43
int_to_char(opus_uint32 i,unsigned char ch[4])44 static void int_to_char(opus_uint32 i, unsigned char ch[4])
45 {
46 ch[0] = i>>24;
47 ch[1] = (i>>16)&0xFF;
48 ch[2] = (i>>8)&0xFF;
49 ch[3] = i&0xFF;
50 }
51
char_to_int(unsigned char ch[4])52 static opus_uint32 char_to_int(unsigned char ch[4])
53 {
54 return ((opus_uint32)ch[0]<<24) | ((opus_uint32)ch[1]<<16)
55 | ((opus_uint32)ch[2]<< 8) | (opus_uint32)ch[3];
56 }
57
main(int argc,char * argv[])58 int main(int argc, char *argv[])
59 {
60 int i, eof=0;
61 FILE *fin, *fout;
62 unsigned char packets[48][1500];
63 int len[48];
64 int rng[48];
65 OpusRepacketizer *rp;
66 unsigned char output_packet[MAX_PACKETOUT];
67 int merge = 1, split=0;
68
69 if (argc < 3)
70 {
71 usage(argv[0]);
72 return EXIT_FAILURE;
73 }
74 for (i=1;i<argc-2;i++)
75 {
76 if (strcmp(argv[i], "-merge")==0)
77 {
78 merge = atoi(argv[i+1]);
79 if(merge<1)
80 {
81 fprintf(stderr, "-merge parameter must be at least 1.\n");
82 return EXIT_FAILURE;
83 }
84 if(merge>48)
85 {
86 fprintf(stderr, "-merge parameter must be less than 48.\n");
87 return EXIT_FAILURE;
88 }
89 i++;
90 } else if (strcmp(argv[i], "-split")==0)
91 split = 1;
92 else
93 {
94 fprintf(stderr, "Unknown option: %s\n", argv[i]);
95 usage(argv[0]);
96 return EXIT_FAILURE;
97 }
98 }
99 fin = fopen(argv[argc-2], "r");
100 if(fin==NULL)
101 {
102 fprintf(stderr, "Error opening input file: %s\n", argv[argc-2]);
103 return EXIT_FAILURE;
104 }
105 fout = fopen(argv[argc-1], "w");
106 if(fout==NULL)
107 {
108 fprintf(stderr, "Error opening output file: %s\n", argv[argc-1]);
109 fclose(fin);
110 return EXIT_FAILURE;
111 }
112
113 rp = opus_repacketizer_create();
114 while (!eof)
115 {
116 int err;
117 int nb_packets=merge;
118 opus_repacketizer_init(rp);
119 for (i=0;i<nb_packets;i++)
120 {
121 unsigned char ch[4];
122 if (fread(ch, 1, 4, fin)!=4)
123 {
124 if (feof(fin))
125 {
126 eof = 1;
127 } else {
128 fprintf(stderr, "Error reading payload length.\n");
129 fclose(fin);
130 fclose(fout);
131 return EXIT_FAILURE;
132 }
133 break;
134 }
135 len[i] = char_to_int(ch);
136 /*fprintf(stderr, "in len = %d\n", len[i]);*/
137 if (len[i]>1500 || len[i]<0)
138 {
139 if (feof(fin))
140 {
141 eof = 1;
142 } else {
143 fprintf(stderr, "Invalid payload length\n");
144 fclose(fin);
145 fclose(fout);
146 return EXIT_FAILURE;
147 }
148 break;
149 }
150 if (fread(ch, 1, 4, fin)!=4)
151 {
152 if (feof(fin))
153 {
154 eof = 1;
155 } else {
156 fprintf(stderr, "Error reading.\n");
157 fclose(fin);
158 fclose(fout);
159 return EXIT_FAILURE;
160 }
161 break;
162 }
163 rng[i] = char_to_int(ch);
164 if (fread(packets[i], len[i], 1, fin)!=1) {
165 if (feof(fin))
166 {
167 eof = 1;
168 } else {
169 fprintf(stderr, "Error reading packet of %u bytes.\n", len[i]);
170 fclose(fin);
171 fclose(fout);
172 return EXIT_FAILURE;
173 }
174 break;
175 }
176 err = opus_repacketizer_cat(rp, packets[i], len[i]);
177 if (err!=OPUS_OK)
178 {
179 fprintf(stderr, "opus_repacketizer_cat() failed: %s\n", opus_strerror(err));
180 break;
181 }
182 }
183 nb_packets = i;
184
185 if (eof)
186 break;
187
188 if (!split)
189 {
190 err = opus_repacketizer_out(rp, output_packet, MAX_PACKETOUT);
191 if (err>0) {
192 unsigned char int_field[4];
193 int_to_char(err, int_field);
194 if(fwrite(int_field, 1, 4, fout)!=4){
195 fprintf(stderr, "Error writing.\n");
196 return EXIT_FAILURE;
197 }
198 int_to_char(rng[nb_packets-1], int_field);
199 if (fwrite(int_field, 1, 4, fout)!=4) {
200 fprintf(stderr, "Error writing.\n");
201 return EXIT_FAILURE;
202 }
203 if (fwrite(output_packet, 1, err, fout)!=(unsigned)err) {
204 fprintf(stderr, "Error writing.\n");
205 return EXIT_FAILURE;
206 }
207 /*fprintf(stderr, "out len = %d\n", err);*/
208 } else {
209 fprintf(stderr, "opus_repacketizer_out() failed: %s\n", opus_strerror(err));
210 }
211 } else {
212 int nb_frames = opus_repacketizer_get_nb_frames(rp);
213 for (i=0;i<nb_frames;i++)
214 {
215 err = opus_repacketizer_out_range(rp, i, i+1, output_packet, MAX_PACKETOUT);
216 if (err>0) {
217 unsigned char int_field[4];
218 int_to_char(err, int_field);
219 if (fwrite(int_field, 1, 4, fout)!=4) {
220 fprintf(stderr, "Error writing.\n");
221 return EXIT_FAILURE;
222 }
223 if (i==nb_frames-1)
224 int_to_char(rng[nb_packets-1], int_field);
225 else
226 int_to_char(0, int_field);
227 if (fwrite(int_field, 1, 4, fout)!=4) {
228 fprintf(stderr, "Error writing.\n");
229 return EXIT_FAILURE;
230 }
231 if (fwrite(output_packet, 1, err, fout)!=(unsigned)err) {
232 fprintf(stderr, "Error writing.\n");
233 return EXIT_FAILURE;
234 }
235 /*fprintf(stderr, "out len = %d\n", err);*/
236 } else {
237 fprintf(stderr, "opus_repacketizer_out() failed: %s\n", opus_strerror(err));
238 }
239
240 }
241 }
242 }
243
244 fclose(fin);
245 fclose(fout);
246 return EXIT_SUCCESS;
247 }
248