1 /*
2 * extract_ac3.c
3 *
4 * Copyright (C) Thomas Oestreich - June 2001
5 * Copyright (C) Aaron Holtzman <aholtzma@ess.engr.uvic.ca> - June 1999
6 *
7 * Ideas and bitstream syntax info borrowed from code written
8 * by Nathan Laredo <laredo@gnu.org>
9 *
10 * Multiple track support by Yuqing Deng <deng@tinker.chem.brown.edu>
11 *
12 * This file is part of transcode, a video stream processing tool
13 *
14 * transcode is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2, or (at your option)
17 * any later version.
18 *
19 * transcode is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with GNU Make; see the file COPYING. If not, write to
26 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
27 *
28 */
29
30 #undef DDBUG
31 //#define DDBUG
32
33 #include "transcode.h"
34 #include "libtc/libtc.h"
35 #include "tcinfo.h"
36
37 #include <sys/mman.h>
38 #include <limits.h>
39
40 #include "ioaux.h"
41 #include "aux_pes.h"
42 #include "tc.h"
43
44
read_tc_time_stamp(const char * s)45 static unsigned int read_tc_time_stamp(const char *s)
46 {
47
48 unsigned long i, j;
49 unsigned long clock_ref=0, clock_ref_ext=0;
50
51 if(s[0] & 0x40) {
52
53 i = stream_read_int32(s);
54 j = stream_read_int16(s+4);
55
56 if(i & 0x40000000 || (i >> 28) == 2) {
57 clock_ref = ((i & 0x31000000) << 3);
58 clock_ref |= ((i & 0x03fff800) << 4);
59 clock_ref |= ((i & 0x000003ff) << 5);
60 clock_ref |= ((j & 0xf800) >> 11);
61 clock_ref_ext = (j >> 1) & 0x1ff;
62 }
63 }
64
65 return ((unsigned int) (clock_ref * 300 + clock_ref_ext));
66 }
67
68
69 #define BUFFER_SIZE 262144
70 static uint8_t *buffer = NULL;
71 static FILE *in_file, *out_file;
72
73 static unsigned int track_code=0, vdr_work_around=0;
74
75 static int get_pts=0;
76
77 static subtitle_header_t subtitle_header;
78 static char *subtitle_header_str="SUBTITLE";
79
pes_ac3_loop(void)80 static void pes_ac3_loop (void)
81 {
82 static int mpeg1_skip_table[16] = {
83 1, 0xffff, 5, 10, 0xffff, 0xffff, 0xffff, 0xffff,
84 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff
85 };
86
87 uint8_t * buf;
88 uint8_t * end;
89 uint8_t * tmp1=NULL;
90 uint8_t * tmp2=NULL;
91 int complain_loudly;
92
93 char pack_buf[16];
94
95 unsigned int pack_lpts=0;
96 double pack_rpts=0.0f, last_rpts=0.0f, offset_rpts=0.0f, abs_rpts=0.0f;
97 double pack_sub_rpts=0.0f, abs_sub_rpts=0.0f;
98
99 int discont=0;
100
101 unsigned long i_pts, i_dts;
102
103 complain_loudly = 1;
104 buf = buffer;
105
106 do {
107 end = buf + fread (buf, 1, buffer + BUFFER_SIZE - buf, in_file);
108 buf = buffer;
109
110 //scan buffer
111 while (buf + 4 <= end) {
112
113 // check for valid start code
114 if (buf[0] || buf[1] || (buf[2] != 0x01)) {
115 if (complain_loudly && (verbose & TC_DEBUG)) {
116 tc_log_warn(__FILE__, "missing start code at %#lx",
117 ftell (in_file) - (end - buf));
118 if ((buf[0] == 0) && (buf[1] == 0) && (buf[2] == 0))
119 tc_log_warn(__FILE__, "incorrect zero-byte padding detected - ignored");
120 complain_loudly = 0;
121 }
122 buf++;
123 continue;
124 }// check for valid start code
125
126 if(verbose & TC_STATS)
127 tc_log_msg(__FILE__, "packet code 0x%x", buf[3]);
128
129 switch (buf[3]) {
130
131 case 0xb9: /* program end code */
132 return;
133
134 //check for PTS
135
136
137 case 0xe0: /* video */
138
139 tmp2 = buf + 6 + (buf[4] << 8) + buf[5];
140
141 if (tmp2 > end)
142 goto copy;
143
144 if ((buf[6] & 0xc0) == 0x80) {
145 /* mpeg2 */
146 tmp1 = buf + 9 + buf[8];
147 } else {
148 /* mpeg1 */
149 for (tmp1 = buf + 6; *tmp1 == 0xff; tmp1++)
150 if (tmp1 == buf + 6 + 16) {
151 tc_log_warn(__FILE__, "too much stuffing");
152 buf = tmp2;
153 break;
154 }
155 if ((*tmp1 & 0xc0) == 0x40)
156 tmp1 += 2;
157 tmp1 += mpeg1_skip_table [*tmp1 >> 4];
158 }
159
160 // get pts time stamp:
161 ac_memcpy(pack_buf, &buf[6], 16);
162
163 if(get_pts_dts(pack_buf, &i_pts, &i_dts)) {
164 pack_rpts = (double) i_pts/90000.;
165
166 if(pack_rpts < last_rpts){ // pts resets when a new chapter begins
167 offset_rpts += last_rpts;
168 ++discont;
169 }
170
171 //default
172 last_rpts=pack_rpts;
173 abs_rpts=pack_rpts + offset_rpts;
174
175 //tc_log_msg(__FILE__, "PTS=%8.3f ABS=%8.3f", pack_rpts, abs_rpts);
176 }
177
178 buf = tmp2;
179 break;
180
181 case 0xba: /* pack header */
182
183 if(get_pts) {
184 ac_memcpy(pack_buf, &buf[4], 6);
185 pack_lpts = read_tc_time_stamp(pack_buf);
186 }
187
188 /* skip */
189 if ((buf[4] & 0xc0) == 0x40) /* mpeg2 */
190 tmp1 = buf + 14 + (buf[13] & 7);
191 else if ((buf[4] & 0xf0) == 0x20) /* mpeg1 */
192 tmp1 = buf + 12;
193 else if (buf + 5 > end)
194 goto copy;
195 else {
196 tc_log_error(__FILE__, "weird pack header");
197 import_exit(1);
198 }
199
200 if (tmp1 > end)
201 goto copy;
202 buf = tmp1;
203 break;
204
205
206 case 0xbd: /* private stream 1 */
207 tmp2 = buf + 6 + (buf[4] << 8) + buf[5];
208 if (tmp2 > end)
209 goto copy;
210 if ((buf[6] & 0xc0) == 0x80) /* mpeg2 */
211 tmp1 = buf + 9 + buf[8];
212 else { /* mpeg1 */
213 for (tmp1 = buf + 6; *tmp1 == 0xff; tmp1++)
214 if (tmp1 == buf + 6 + 16) {
215 tc_log_warn(__FILE__, "too much stuffing");
216 buf = tmp2;
217 break;
218 }
219 if ((*tmp1 & 0xc0) == 0x40)
220 tmp1 += 2;
221 tmp1 += mpeg1_skip_table [*tmp1 >> 4];
222 }
223
224 if(verbose & TC_STATS)
225 tc_log_msg(__FILE__, "track code 0x%x", *tmp1);
226
227 if(vdr_work_around) {
228 if (tmp1 < tmp2) {
229 TC_PIPE_WRITE(fileno(out_file), tmp1, tmp2-tmp1);
230 /* yeah, I know that's ugly -- FR */
231 }
232 } else {
233
234 //subtitle
235
236 if (*tmp1 == track_code && track_code < 0x40) {
237
238 if (tmp1 < tmp2) {
239
240 // get pts time stamp:
241 ac_memcpy(pack_buf, &buf[6], 16);
242
243 if(get_pts_dts(pack_buf, &i_pts, &i_dts)) {
244 pack_sub_rpts = (double) i_pts/90000.;
245
246 //i suppose there *canNOT* be 2 sub chunks from the
247 //same sub line over a chapter change
248 //let's add the video offset to the subs
249 abs_sub_rpts=pack_sub_rpts + offset_rpts;
250
251 //tc_log_msg(__FILE__, "sub PTS=%8.3f ABS=%8.3f", pack_rpts, abs_rpts);
252 }
253
254 subtitle_header.lpts = pack_lpts;
255 subtitle_header.rpts = abs_sub_rpts;
256 subtitle_header.discont_ctr = discont;
257 subtitle_header.header_version = TC_SUBTITLE_HDRMAGIC;
258 subtitle_header.header_length = sizeof(subtitle_header_t);
259 subtitle_header.payload_length=tmp2-tmp1;
260
261 if(verbose & TC_STATS)
262 tc_log_msg(__FILE__, "subtitle=0x%x size=%4d lpts=%d rpts=%f rptsfromvid=%f",
263 track_code, subtitle_header.payload_length,
264 subtitle_header.lpts, subtitle_header.rpts,
265 abs_rpts);
266
267 if(tc_pwrite(STDOUT_FILENO, (uint8_t*) subtitle_header_str, strlen(subtitle_header_str))<0) {
268 tc_log_error(__FILE__, "error writing subtitle: %s",
269 strerror(errno));
270 import_exit(1);
271 }
272 if(tc_pwrite(STDOUT_FILENO, (uint8_t*) &subtitle_header, sizeof(subtitle_header_t))<0) {
273 tc_log_error(__FILE__, "error writing subtitle: %s",
274 strerror(errno));
275 import_exit(1);
276 }
277 if(tc_pwrite(STDOUT_FILENO, tmp1, tmp2-tmp1)<0) {
278 tc_log_error(__FILE__, "error writing subtitle: %s",
279 strerror(errno));
280 import_exit(1);
281 }
282 }
283 }
284
285 //ac3 package
286
287 if (*tmp1 == track_code && track_code >= 0x80) {
288 tmp1 += 4;
289 #if 0
290 //test
291 if(0) {
292 ac_memcpy(pack_buf, &buf[6], 16);
293 get_pts_dts(pack_buf, &i_pts, &i_dts);
294 tc_log_msg(__FILE__, "AC3 PTS=%f", (double) i_pts/90000.);
295 }
296 #endif
297 if (tmp1 < tmp2) {
298 TC_PIPE_WRITE(fileno(out_file), tmp1, tmp2-tmp1);
299 /* yeah, I know that's ugly -- FR */
300 }
301 }
302 }
303
304 buf = tmp2;
305 break;
306
307 default:
308 if (buf[3] < 0xb9)
309 tc_log_warn(__FILE__, "broken stream - skipping data");
310
311 /* skip */
312 tmp1 = buf + 6 + (buf[4] << 8) + buf[5];
313 if (tmp1 > end)
314 goto copy;
315 buf = tmp1;
316 break;
317
318 } //start code selection
319 } //scan buffer
320
321 if (buf < end) {
322 copy:
323 /* we only pass here for mpeg1 ps streams */
324 memmove (buffer, buf, end - buf);
325 }
326 buf = buffer + (end - buf);
327
328 } while (end == buffer + BUFFER_SIZE);
329 }
330
331
332
333
334 FILE *fd;
335
336 #define MAX_BUF 4096
337 static char audio[MAX_BUF];
338
339
340 /* from ac3scan.c */
get_ac3_bitrate(uint8_t * ptr)341 static int get_ac3_bitrate(uint8_t *ptr)
342 {
343 static const int bitrates[] = {
344 32, 40, 48, 56,
345 64, 80, 96, 112,
346 128, 160, 192, 224,
347 256, 320, 384, 448,
348 512, 576, 640
349 };
350 int ratecode = (ptr[2] & 0x3E) >> 1;
351 if (ratecode < sizeof(bitrates)/sizeof(*bitrates))
352 return bitrates[ratecode];
353 return -1;
354 }
355
get_ac3_samplerate(uint8_t * ptr)356 static int get_ac3_samplerate(uint8_t *ptr)
357 {
358 static const int samplerates[] = {48000, 44100, 32000, -1};
359 return samplerates[ptr[2]>>6];
360 }
361
get_ac3_framesize(uint8_t * ptr)362 static int get_ac3_framesize(uint8_t *ptr)
363 {
364 int bitrate = get_ac3_bitrate(ptr);
365 int samplerate = get_ac3_samplerate(ptr);
366 if (bitrate < 0 || samplerate < 0)
367 return -1;
368 return bitrate * 96000 / samplerate + (samplerate==44100 ? ptr[2]&1 : 0);
369 }
370
371
ac3scan(int infd,int outfd)372 static int ac3scan(int infd, int outfd)
373 {
374 int pseudo_frame_size = 0, j = 0, i = 0, s = 0;
375 unsigned long k = 0;
376 #ifdef DDBUG
377 int n = 0;
378 #endif
379 char buffer[SIZE_PCM_FRAME];
380 int frame_size, bitrate;
381 float rbytes;
382 uint16_t sync_word = 0;
383 ssize_t bytes_read;
384
385 // need to find syncframe:
386 for (;;) {
387 k = 0;
388 for (;;) {
389 bytes_read = tc_pread(infd, &buffer[s], 1);
390 if (bytes_read <= 0) {
391 // ac3 sync frame scan failed
392 if (bytes_read == 0) /* EOF */
393 return 0;
394 else
395 return ERROR_INVALID_HEADER;
396 }
397
398 sync_word = (sync_word << 8) + (uint8_t) buffer[s];
399
400 s = (s + 1) % 2;
401 ++i;
402 ++k;
403
404 if (sync_word == 0x0b77) {
405 break;
406 }
407
408 if (k > (1 << 20)) {
409 tc_log_error(__FILE__, "no AC3 sync frame found within 1024 kB of stream");
410 return 1;
411 }
412 }
413 i = i - 2;
414 #ifdef DDBUG
415 tc_log_msg(__FILE__, "found sync frame at offset %d (%d)", i, j);
416 #endif
417 // read rest of header
418 if (tc_pread(infd, &buffer[2], 3) !=3) {
419 return ERROR_INVALID_HEADER;
420 }
421
422 if ((frame_size = 2 * get_ac3_framesize(&buffer[2])) < 1) {
423 tc_log_error(__FILE__, "ac3 framesize %d invalid", frame_size);
424 return 1;
425 }
426
427 //FIXME: I assume that a single AC3 frame contains 6kB PCM bytes
428
429 rbytes = (float) SIZE_PCM_FRAME/1024/6 * frame_size;
430 pseudo_frame_size = (int) rbytes;
431
432 if ((bitrate = get_ac3_bitrate(&buffer[2])) < 1) {
433 tc_log_error(__FILE__, "ac3 bitrate invalid");
434 return 1;
435 }
436
437 // write out frame header
438
439 #ifdef DDBUG
440 tc_log_msg(__FILE__, "[%05d] %04d bytes, pcm pseudo frame %04d bytes, bitrate %03d kBits/s",
441 n++, frame_size, pseudo_frame_size, bitrate);
442 #endif
443
444 // s points directly at first byte of syncword
445 tc_pwrite(outfd, &buffer[s], 1);
446 s = (s + 1) % 2;
447 tc_pwrite(outfd, &buffer[s], 1);
448 s = (s + 1) % 2;
449
450 // read packet
451 tc_pread(infd, &buffer[5], frame_size-5);
452 tc_pwrite(outfd, &buffer[2], frame_size-2);
453
454 i += frame_size;
455 j = i;
456 }
457 return 0;
458 }
459
460
461 /* ------------------------------------------------------------
462 *
463 * extract thread
464 *
465 * magic: TC_MAGIC_VOB
466 * TC_MAGIC_AVI
467 * TC_MAGIC_RAW <-- default
468 *
469 * ------------------------------------------------------------*/
470
471
extract_ac3(info_t * ipipe)472 void extract_ac3(info_t *ipipe)
473 {
474
475 int error=0;
476
477 avi_t *avifile;
478
479 long frames, bytes, padding, n;
480
481 verbose = ipipe->verbose;
482
483 buffer = tc_malloc (BUFFER_SIZE);
484
485 switch(ipipe->magic) {
486
487 case TC_MAGIC_VDR:
488
489 in_file = fdopen(ipipe->fd_in, "r");
490 out_file = fdopen(ipipe->fd_out, "w");
491
492 vdr_work_around=1;
493
494 pes_ac3_loop();
495
496 fclose(in_file);
497 fclose(out_file);
498
499 break;
500
501 case TC_MAGIC_VOB:
502
503 in_file = fdopen(ipipe->fd_in, "r");
504 out_file = fdopen(ipipe->fd_out, "w");
505
506
507 if(ipipe->codec==TC_CODEC_PS1) {
508
509 track_code = ipipe->track;
510 get_pts=1;
511
512 if(track_code < 0) import_exit(1);
513
514 } else {
515 if (ipipe->track < 0 || ipipe->track >= TC_MAX_AUD_TRACKS) {
516 tc_log_error(__FILE__, "invalid track number: %d", ipipe->track);
517 import_exit(1);
518 }
519
520 // DTS tracks begin with ID 0x88, ac3 with 0x80
521 if (ipipe->codec == TC_CODEC_DTS)
522 track_code = ipipe->track + 0x88;
523 else
524 track_code = ipipe->track + 0x80;
525 }
526
527 pes_ac3_loop();
528
529 fclose(in_file);
530 fclose(out_file);
531
532 break;
533
534
535 case TC_MAGIC_AVI:
536
537 if(ipipe->stype == TC_STYPE_STDIN){
538 tc_log_error(__FILE__, "invalid magic/stype - exit");
539 error=1;
540 break;
541 }
542
543 // scan file
544 if (ipipe->nav_seek_file) {
545 if(NULL == (avifile = AVI_open_indexfd(ipipe->fd_in,0,ipipe->nav_seek_file))) {
546 AVI_print_error("AVI open");
547 break;
548 }
549 } else {
550 if(NULL == (avifile = AVI_open_fd(ipipe->fd_in,1))) {
551 AVI_print_error("AVI open");
552 break;
553 }
554 }
555
556 //set selected for multi-audio AVI-files
557 AVI_set_audio_track(avifile, ipipe->track);
558
559 // get total audio size
560 bytes = AVI_audio_bytes(avifile);
561
562 padding = bytes % MAX_BUF;
563 frames = bytes / MAX_BUF;
564
565 for (n=0; n<frames; ++n) {
566
567 if(AVI_read_audio(avifile, audio, MAX_BUF)<0) {
568 error=1;
569 break;
570 }
571
572 if(tc_pwrite(ipipe->fd_out, audio, MAX_BUF)!= MAX_BUF) {
573 error=1;
574 break;
575 }
576 }
577
578 if((bytes = AVI_read_audio(avifile, audio, padding)) < padding)
579 error=1;
580
581 if(tc_pwrite(ipipe->fd_out, audio, bytes)!= bytes) error=1;
582
583 break;
584
585 case TC_MAGIC_RAW:
586 default:
587
588 if(ipipe->magic == TC_MAGIC_UNKNOWN)
589 tc_log_warn(__FILE__, "no file type specified, assuming %s",
590 filetype(TC_MAGIC_RAW));
591
592 error=ac3scan(ipipe->fd_in, ipipe->fd_out);
593 break;
594 }
595
596 free (buffer);
597 import_exit(error);
598
599 }
600
601