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