# HG changeset patch # User arpi # Date 997876255 0 # Node ID a444bd456fcc32f748b2a0c914f7ed245a448089 # Parent 187aa4b576a7b5d274d830e0555fbc1bbb3bcb85 ac3/spdif patch by German Gomez Garcia diff -r 187aa4b576a7 -r a444bd456fcc DOCS/codecs.conf --- 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" + diff -r 187aa4b576a7 -r a444bd456fcc Makefile --- 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) diff -r 187aa4b576a7 -r a444bd456fcc ac3-iec958.c --- /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 +#include +#include +#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; +} diff -r 187aa4b576a7 -r a444bd456fcc ac3-iec958.h --- /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 diff -r 187aa4b576a7 -r a444bd456fcc codec-cfg.c --- 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[] = { diff -r 187aa4b576a7 -r a444bd456fcc codec-cfg.h --- 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 diff -r 187aa4b576a7 -r a444bd456fcc dec_audio.c --- 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; } diff -r 187aa4b576a7 -r a444bd456fcc libao2/ao_oss.c --- 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) diff -r 187aa4b576a7 -r a444bd456fcc libao2/audio_out.c --- 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)