1 /*
2 * tcmp3cut.c
3 *
4 * Copyright (C) Thomas Oestreich - June 2001
5 *
6 * This file is part of transcode, a video stream processing tool
7 *
8 * transcode is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2, or (at your option)
11 * any later version.
12 *
13 * transcode is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with GNU Make; see the file COPYING. If not, write to
20 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
21 *
22 */
23
24 #include "transcode.h"
25 #include "framebuffer.h"
26 #include "aud_scan.h"
27
28 #include <sys/errno.h>
29
30
31 #define EXE "tcmp3cut"
32
33 int verbose=TC_QUIET;
34
35 #define CHUNK_SIZE 4096
36
37 static int min=0, max=0;
38
39
40
41 /* ------------------------------------------------------------
42 *
43 * print a usage/version message
44 *
45 * ------------------------------------------------------------*/
46
version(void)47 void version(void)
48 {
49 printf("%s (%s v%s) (C) 2003 Tilmann Bitterberg\n", EXE, PACKAGE, VERSION);
50 }
51
usage(int status)52 static void usage(int status)
53 {
54 version();
55
56 fprintf(stderr,"\nUsage: %s [options]\n", EXE);
57
58 fprintf(stderr," -i file input file name\n");
59 fprintf(stderr," -o base output file name base\n");
60 fprintf(stderr," -e r[,b[,c]] MP3 audio stream parameter [%d,%d,%d]\n", RATE, BITS, CHANNELS);
61 fprintf(stderr," -t c1[,c2[,.]] cut points in milliseconds\n");
62 fprintf(stderr," -d mode verbosity mode\n");
63 fprintf(stderr," -v print version\n");
64
65 exit(status);
66
67 }
68
69
70 /* ------------------------------------------------------------
71 *
72 * scan stream
73 *
74 * ------------------------------------------------------------*/
75
76 #define MAX_SONGS 50
77
main(int argc,char * argv[])78 int main(int argc, char *argv[])
79 {
80
81
82 int fd=-1;
83 FILE *out=NULL;
84
85 int n=0, ch;
86 char *name=NULL, *offset=NULL, *base=NULL;
87 char outfile[1024];
88 int cursong=0;
89
90 int bytes_read;
91
92 uint64_t total=0;
93
94 int a_rate=RATE, a_bits=BITS, chan=CHANNELS;
95 int songs[MAX_SONGS];
96 int numsongs=0;
97
98 int on=1;
99
100 char buffer[CHUNK_SIZE];
101
102 uint32_t i=0;
103
104 if (argc<2)
105 usage(EXIT_SUCCESS);
106
107 while ((ch = getopt(argc, argv, "o:e:i:t:d:v?h")) != -1) {
108
109 switch (ch) {
110 case 'd':
111
112 if(optarg[0]=='-') usage(EXIT_FAILURE);
113 verbose = atoi(optarg);
114
115 break;
116
117 case 'e':
118
119 if(optarg[0]=='-') usage(EXIT_FAILURE);
120
121 if (3 != sscanf(optarg,"%d,%d,%d", &a_rate, &a_bits, &chan)) fprintf(stderr, "invalid pcm parameter set for option -e");
122
123 if(a_rate > RATE || a_rate <= 0) {
124 fprintf(stderr, "invalid pcm parameter 'rate' for option -e");
125 usage(EXIT_FAILURE);
126 }
127
128 if(!(a_bits == 16 || a_bits == 8)) {
129 fprintf(stderr, "invalid pcm parameter 'bits' for option -e");
130 usage(EXIT_FAILURE);
131 }
132
133 if(!(chan == 0 || chan == 1 || chan == 2)) {
134 fprintf(stderr, "invalid pcm parameter 'channels' for option -e");
135 usage(EXIT_FAILURE);
136 }
137
138 break;
139
140 case 'i':
141
142 if(optarg[0]=='-') usage(EXIT_FAILURE);
143 name = optarg;
144 break;
145
146 case 't':
147 if(optarg[0]=='-') usage(EXIT_FAILURE);
148
149 offset = optarg;
150 i=0;
151 songs[i]=atoi(offset);
152 while ((offset = strchr(offset,','))) {
153 offset++;
154 i++;
155 songs[i]=atoi(offset);
156 }
157 numsongs=i+1;
158 break;
159
160 case 'o':
161 if(optarg[0]=='-') usage(EXIT_FAILURE);
162 base = optarg;
163 break;
164 case 'v':
165 version();
166 exit(0);
167 break;
168
169 case 'h':
170 usage(EXIT_SUCCESS);
171 default:
172 usage(EXIT_FAILURE);
173 }
174 }
175
176 printf("Got %d songs:\n", numsongs);
177 for (n=0; n<numsongs; n++)
178 printf("%d : %d\n", n, songs[n]);
179
180
181 if (!name) {
182 fprintf(stderr, "No filename given\n");
183 exit (EXIT_FAILURE);
184 }
185
186 if ( (fd = open(name, O_RDONLY)) < 0) {
187 perror("open()");
188 return -1;
189 }
190
191 if ( (fd = open(name, O_RDONLY)) < 0) {
192 perror("open()");
193 return -1;
194 }
195
196 tc_snprintf(outfile, sizeof(outfile), "%s-%04d.mp3", base, cursong);
197 if ( (out = fopen(outfile, "w")) == NULL) {
198 perror ("fopen() output");
199 return -1;
200 }
201
202 if(1) {
203
204 uint8_t header[4];
205 int framesize = 0;
206 int chunks = 0;
207 int srate=0 , chans=0, bitrate=0;
208 off_t pos=0;
209 double ms = 0;
210
211 min = 500;
212 max = 0;
213
214 pos = lseek(fd, 0, SEEK_CUR);
215 // find mp3 header
216 while ((total += read(fd, header, 4))) {
217 if ( (framesize = tc_get_mp3_header (header, &chans, &srate, &bitrate)) > 0) {
218 fwrite (header, 4, 1,out);
219 ms += (framesize*8)/(bitrate);
220 break;
221 }
222 pos++;
223 lseek(fd, pos, SEEK_SET);
224 }
225 printf("POS %lld\n", (long long)pos);
226
227 // Example for _1_ mp3 chunk
228 //
229 // fps = 25
230 // framesize = 480 bytes
231 // bitrate = 160 kbit/s == 20 kbytes/s == 20480 bytes/s == 819.20 bytes / frame
232 //
233 // 480 bytes = 480/20480 s/bytes = .0234 s = 23.4 ms
234 //
235 // ms = (framesize*1000*8)/(bitrate*1000);
236 // why 1000 and not 1024?
237 // correct? yes! verified with "cat file.mp3|mpg123 -w /dev/null -v -" -- tibit
238
239 while (on) {
240 if ( (bytes_read = read(fd, buffer, framesize-4)) != framesize-4) {
241 on = 0;
242 } else {
243 total += bytes_read;
244 fwrite (buffer, bytes_read, 1,out);
245 while ((total += read(fd, header, 4))) {
246
247 //printf("%x %x %x %x\n", header[0]&0xff, header[1]&0xff, header[2]&0xff, header[3]&0xff);
248
249 if ( (framesize = tc_get_mp3_header (header, &chans, &srate, &bitrate)) < 0) {
250 fprintf(stderr, "[%s] corrupt mp3 file?\n", EXE);
251 on = 0;
252 break;
253 } else {
254
255 /*
256 printf("Found new header (%d) (framesize = %d) chan(%d) srate(%d) bitrate(%d)\n",
257 chunks, framesize, chans, srate, bitrate);
258 */
259
260 ms += (framesize*8)/(bitrate);
261 // close/open
262
263 if (ms>=songs[cursong]) {
264 fclose(out);
265 cursong++;
266 if (cursong>numsongs)
267 break;
268 tc_snprintf(outfile, sizeof(outfile), "%s-%04d.mp3", base, cursong);
269 if ( (out = fopen(outfile, "w")) == NULL) {
270 perror ("fopen() output");
271 return -1;
272 }
273 }
274 fwrite (header, 4, 1,out);
275
276 ++chunks;
277 break;
278 }
279 }
280
281
282 }
283 }
284 fclose(out);
285 close(fd);
286 return(0);
287 }
288
289
290 fprintf(stderr, "[%s] unable to handle codec/filetype\n", EXE);
291
292 exit(1);
293
294 }
295
296 /*************************************************************************/
297
298 /*
299 * Local variables:
300 * c-file-style: "stroustrup"
301 * c-file-offsets: ((case-label . *) (statement-case-intro . *))
302 * indent-tabs-mode: nil
303 * End:
304 *
305 * vim: expandtab shiftwidth=4:
306 */
307