changeset 1528:a444bd456fcc

ac3/spdif patch by German Gomez Garcia <german@piraos.com>
author arpi
date Wed, 15 Aug 2001 11:50:55 +0000
parents 187aa4b576a7
children 81aa2d701ae0
files DOCS/codecs.conf Makefile ac3-iec958.c ac3-iec958.h codec-cfg.c codec-cfg.h dec_audio.c libao2/ao_oss.c libao2/audio_out.c
diffstat 9 files changed, 212 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/DOCS/codecs.conf	Wed Aug 15 07:21:33 2001 +0000
+++ b/DOCS/codecs.conf	Wed Aug 15 11:50:55 2001 +0000
@@ -538,3 +538,11 @@
   format 0x401
   driver acm
   dll "imc32.acm"
+
+audiocodec hwac3
+  info "AC3 through SPDIF"
+  status working
+  format 0x2000
+  driver hwac3
+  dll "ac3-iec958.c"
+
--- a/Makefile	Wed Aug 15 07:21:33 2001 +0000
+++ b/Makefile	Wed Aug 15 11:50:55 2001 +0000
@@ -16,7 +16,7 @@
 #prefix = /usr/local
 BINDIR = ${prefix}/bin
 # BINDIR = /usr/local/bin
-SRCS = open.c parse_es.c find_sub.c aviprint.c dec_audio.c dec_video.c aviwrite.c aviheader.c asfheader.c demux_avi.c demux_asf.c demux_mpg.c demux_mov.c demuxer.c stream.c codec-cfg.c subreader.c linux/getch2.c linux/timer-lx.c linux/shmem.c xa/xa_gsm.c lirc_mp.c cfgparser.c mixer.c dvdauth.c spudec.c $(STREAM_SRCS)
+SRCS = open.c parse_es.c ac3-iec958.c find_sub.c aviprint.c dec_audio.c dec_video.c aviwrite.c aviheader.c asfheader.c demux_avi.c demux_asf.c demux_mpg.c demux_mov.c demuxer.c stream.c codec-cfg.c subreader.c linux/getch2.c linux/timer-lx.c linux/shmem.c xa/xa_gsm.c lirc_mp.c cfgparser.c mixer.c dvdauth.c spudec.c $(STREAM_SRCS)
 OBJS = $(SRCS:.c=.o)
 CFLAGS = $(OPTFLAGS) -Iloader -Ilibvo $(CSS_INC) $(EXTRA_INC) # -Wall
 A_LIBS = -Lmp3lib -lMP3 -Llibac3 -lac3 $(ALSA_LIB) $(ESD_LIB)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ac3-iec958.c	Wed Aug 15 11:50:55 2001 +0000
@@ -0,0 +1,139 @@
+/*  ----------------------------------------------------------------------
+
+    Copyright (C) 2001  Juha Yrjölä  (jyrjola@cc.hut.fi)
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+    ---------------------------------------------------------------------- */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include "ac3-iec958.h"
+
+struct frmsize_s
+{
+        unsigned short bit_rate;
+        unsigned short frm_size[3];
+};
+                
+static const struct frmsize_s frmsizecod_tbl[64] =
+{
+        { 32  ,{64   ,69   ,96   } },
+        { 32  ,{64   ,70   ,96   } },
+        { 40  ,{80   ,87   ,120  } },
+        { 40  ,{80   ,88   ,120  } },
+        { 48  ,{96   ,104  ,144  } },
+        { 48  ,{96   ,105  ,144  } },
+        { 56  ,{112  ,121  ,168  } },
+        { 56  ,{112  ,122  ,168  } },
+        { 64  ,{128  ,139  ,192  } },
+        { 64  ,{128  ,140  ,192  } },
+        { 80  ,{160  ,174  ,240  } },
+        { 80  ,{160  ,175  ,240  } },
+        { 96  ,{192  ,208  ,288  } },
+        { 96  ,{192  ,209  ,288  } },
+        { 112 ,{224  ,243  ,336  } },
+        { 112 ,{224  ,244  ,336  } },
+        { 128 ,{256  ,278  ,384  } },
+        { 128 ,{256  ,279  ,384  } },
+        { 160 ,{320  ,348  ,480  } },
+        { 160 ,{320  ,349  ,480  } },
+        { 192 ,{384  ,417  ,576  } },
+        { 192 ,{384  ,418  ,576  } },
+        { 224 ,{448  ,487  ,672  } },
+        { 224 ,{448  ,488  ,672  } },
+        { 256 ,{512  ,557  ,768  } },
+        { 256 ,{512  ,558  ,768  } },
+        { 320 ,{640  ,696  ,960  } },
+        { 320 ,{640  ,697  ,960  } },
+        { 384 ,{768  ,835  ,1152 } },
+        { 384 ,{768  ,836  ,1152 } },
+        { 448 ,{896  ,975  ,1344 } },
+        { 448 ,{896  ,976  ,1344 } },
+        { 512 ,{1024 ,1114 ,1536 } },
+        { 512 ,{1024 ,1115 ,1536 } },
+        { 576 ,{1152 ,1253 ,1728 } },
+        { 576 ,{1152 ,1254 ,1728 } },
+        { 640 ,{1280 ,1393 ,1920 } },
+        { 640 ,{1280 ,1394 ,1920 } }
+};
+
+struct syncframe {
+  struct syncinfo {
+    unsigned char syncword[2];
+    unsigned char crc1[2];
+    unsigned char code;
+  } syncinfo;
+  struct bsi {
+    unsigned char bsidmod;
+    unsigned char acmod;
+  } bsi;
+}; 
+
+void ac3_iec958_build_burst(int length, int data_type, int big_endian, unsigned char * data, unsigned char * out)
+{
+	const char sync[4] = { 0x72, 0xF8, 0x1F, 0x4E };
+
+	memcpy(out, sync, 4);
+	if (length)
+		out[4] = data_type; /* & 0x1F; */
+	else
+		out[4] = 0;
+	out[5] = 0x00;
+	out[6] = (length*8) & 0xFF;
+	out[7] = ((length*8) >> 8) & 0xFF;
+	if (big_endian)
+		swab(data, out + 8, length);
+	else
+		memcpy(data, out + 8, length);
+	memset(out + 8 + length, 0, 6144 - 8 - length);
+}
+
+int ac3_iec958_parse_syncinfo(unsigned char *buf, int size, struct hwac3info *ai, int *skipped)
+{
+	int samplerates[4] = { 48000, 44100, 32000, -1 };
+	unsigned short sync = 0;
+	unsigned char *ptr = buf;
+	int fscod, frmsizecod;
+	struct syncframe *sf;
+	
+	sync = buf[0] << 8;
+	sync |= buf[1];
+	ptr = buf + 2;
+	*skipped = 0;
+	while (sync != 0xb77 && *skipped < size - 8) {
+		sync <<= 8;
+		sync |= *ptr;
+		ptr++;
+		*skipped += 1;
+	}
+	if (sync != 0xb77)
+		return -1;
+	ptr -= 2;
+	sf = (struct syncframe *) ptr;
+	fscod = (sf->syncinfo.code >> 6) & 0x03;
+	ai->samplerate = samplerates[fscod];
+	if (ai->samplerate == -1)
+		return -1;
+	frmsizecod = sf->syncinfo.code & 0x3f;
+	ai->framesize = 2 * frmsizecod_tbl[frmsizecod].frm_size[fscod];
+	ai->bitrate = frmsizecod_tbl[frmsizecod].bit_rate;
+	if (((sf->bsi.bsidmod >> 3) & 0x1f) != 0x08)
+		return -1;
+	ai->bsmod = sf->bsi.bsidmod & 0x7;
+
+	return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ac3-iec958.h	Wed Aug 15 11:50:55 2001 +0000
@@ -0,0 +1,13 @@
+#ifndef _AC3_IEC958_H
+#define _AC3_IEC958_H
+
+#define IEC61937_DATA_TYPE_AC3 1
+
+struct hwac3info {
+  int bitrate, framesize, samplerate, bsmod;
+};
+
+void ac3_iec958_build_burst(int length, int data_type, int big_endian, unsigned char * data, unsigned char * out);
+int ac3_iec958_parse_syncinfo(unsigned char *buf, int size, struct hwac3info *ai, int *skipped);
+
+#endif
--- a/codec-cfg.c	Wed Aug 15 07:21:33 2001 +0000
+++ b/codec-cfg.c	Wed Aug 15 11:50:55 2001 +0000
@@ -204,6 +204,7 @@
 		"msgsm",
 		"dshow",
 		"dvdpcm",
+		"hwac3",
 		NULL
 	};
 	static char *videodrv[] = {
--- a/codec-cfg.h	Wed Aug 15 07:21:33 2001 +0000
+++ b/codec-cfg.h	Wed Aug 15 11:50:55 2001 +0000
@@ -26,6 +26,7 @@
 #define AFM_GSM 6
 #define AFM_DSHOW 7
 #define AFM_DVDPCM 8
+#define AFM_HWAC3 9
 
 #define VFM_MPEG 1
 #define VFM_VFW 2
--- a/dec_audio.c	Wed Aug 15 07:21:33 2001 +0000
+++ b/dec_audio.c	Wed Aug 15 11:50:55 2001 +0000
@@ -29,6 +29,8 @@
 
 #include "xa/xa_gsm.h"
 
+#include "ac3-iec958.h"
+
 #ifdef USE_DIRECTSHOW
 #include "loader/DirectShow/DS_AudioDec.h"
 #endif
@@ -130,6 +132,11 @@
   // Dolby AC3 audio:
   sh_audio->audio_out_minsize=4*256*6;
   break;
+case AFM_HWAC3:
+  // Dolby AC3 audio:
+  sh_audio->audio_out_minsize=4*256*6;
+  sh_audio->sample_format = AFMT_AC3;
+  break;
 case AFM_GSM:
   // MS-GSM audio codec:
   sh_audio->audio_out_minsize=4*320;
@@ -219,6 +226,28 @@
   }
   break;
 }
+case AFM_HWAC3: {
+  unsigned char *buffer;		    
+  struct hwac3info ai;
+  int len, skipped;
+  len = ds_get_packet(sh_audio->ds, &buffer);
+  if(ac3_iec958_parse_syncinfo(buffer, len, &ai, &skipped) < 0) {
+      fprintf(stderr, "AC3 stream not valid.\n");
+      driver = 0;
+      break;
+  }
+  if(ai.samplerate != 48000) {
+      fprintf(stderr, "Only 48000 Hz streams supported.\n");
+      driver = 0;
+      break;
+  }
+  sh_audio->samplerate=ai.samplerate;
+//  sh_audio->samplesize=ai.framesize;
+  sh_audio->channels=1;
+  sh_audio->i_bps=ai.bitrate*(1000/8);
+  sh_audio->ac3_frame=malloc(6144);
+  break;
+}
 case AFM_ALAW: {
   // aLaw audio codec:
   sh_audio->channels=sh_audio->wf->nChannels;
@@ -332,6 +361,12 @@
         }
         //printf("{3:%d}",avi_header.idx_pos);fflush(stdout);
         break;
+      case AFM_HWAC3: // AC3 through SPDIF
+	if(demux_read_data(sh_audio->ds,sh_audio->ac3_frame, 6144) != 6144) 
+	    break; //EOF 
+	ac3_iec958_build_burst(1536, 0x1F, 1, buf, sh_audio->ac3_frame);
+	len = 6144;
+	break;
 #ifdef USE_WIN32DLL
       case AFM_ACM:
 //        len=sh_audio->audio_out_minsize; // optimal decoded fragment size
@@ -387,6 +422,7 @@
           break;
         case AFM_ACM:
         case AFM_DSHOW:
+	case AFM_HWAC3:
           sh_audio->a_in_buffer_len=0;        // reset ACM/DShow audio buffer
           break;
         }
--- a/libao2/ao_oss.c	Wed Aug 15 07:21:33 2001 +0000
+++ b/libao2/ao_oss.c	Wed Aug 15 11:50:55 2001 +0000
@@ -55,6 +55,9 @@
 	{
 	    ao_control_vol_t *vol = (ao_control_vol_t *)arg;
 	    int fd, v, mcmd, devs;
+
+	    if(ao_format == AFMT_AC3)
+		return CONTROL_TRUE;
     
 	    if ((fd = open("/dev/mixer", O_RDONLY)) > 0)
 	    {
@@ -119,9 +122,14 @@
 
   ao_format=format;
   ioctl (audio_fd, SNDCTL_DSP_SETFMT, &ao_format);
+  if(format == AFMT_AC3 && ao_format != AFMT_AC3) {
+      printf("Can't set audio device %s to AC3 output\n", dsp);
+      return 0;
+  }
   printf("audio_setup: sample format: %s (requested: %s)\n",
     audio_out_format_name(ao_format), audio_out_format_name(format));
   
+  if(format != AFMT_AC3) {
   ao_channels=channels-1;
   ioctl (audio_fd, SNDCTL_DSP_STEREO, &ao_channels);
   
@@ -129,6 +137,7 @@
   ao_samplerate=rate;
   ioctl (audio_fd, SNDCTL_DSP_SPEED, &ao_samplerate);
   printf("audio_setup: using %d Hz samplerate (requested: %d)\n",ao_samplerate,rate);
+  }
 
   if(ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &zz)==-1){
       int r=0;
@@ -191,9 +200,10 @@
     }
 
   ioctl (audio_fd, SNDCTL_DSP_SETFMT, &ao_format);
+  if(ao_format != AFMT_AC3) {
   ioctl (audio_fd, SNDCTL_DSP_STEREO, &ao_channels);
   ioctl (audio_fd, SNDCTL_DSP_SPEED, &ao_samplerate);
-
+  }
 }
 
 // stop playing, keep buffers (for pause)
--- a/libao2/audio_out.c	Wed Aug 15 07:21:33 2001 +0000
+++ b/libao2/audio_out.c	Wed Aug 15 11:50:55 2001 +0000
@@ -87,6 +87,8 @@
 	    return("Unsigned 16-bit (Big-Endian)");
 	case AFMT_MPEG:
 	    return("MPEG (2) audio");
+	case AFMT_AC3:
+	    return("AC3");
 /*
   the following two formats are not available with old linux kernel
   headers (e.g. in 2.2.16)