mirror of
https://github.com/mpv-player/mpv
synced 2024-11-03 03:19:24 +01:00
ac3/spdif patch by German Gomez Garcia <german@piraos.com>
git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@1529 b3059339-0415-0410-9bf9-f77b7e298cf2
This commit is contained in:
parent
26543fef95
commit
7c9c86fb97
@ -538,3 +538,11 @@ audiocodec imc
|
|||||||
format 0x401
|
format 0x401
|
||||||
driver acm
|
driver acm
|
||||||
dll "imc32.acm"
|
dll "imc32.acm"
|
||||||
|
|
||||||
|
audiocodec hwac3
|
||||||
|
info "AC3 through SPDIF"
|
||||||
|
status working
|
||||||
|
format 0x2000
|
||||||
|
driver hwac3
|
||||||
|
dll "ac3-iec958.c"
|
||||||
|
|
||||||
|
2
Makefile
2
Makefile
@ -16,7 +16,7 @@ PRG_CFG = codec-cfg
|
|||||||
#prefix = /usr/local
|
#prefix = /usr/local
|
||||||
BINDIR = ${prefix}/bin
|
BINDIR = ${prefix}/bin
|
||||||
# BINDIR = /usr/local/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)
|
OBJS = $(SRCS:.c=.o)
|
||||||
CFLAGS = $(OPTFLAGS) -Iloader -Ilibvo $(CSS_INC) $(EXTRA_INC) # -Wall
|
CFLAGS = $(OPTFLAGS) -Iloader -Ilibvo $(CSS_INC) $(EXTRA_INC) # -Wall
|
||||||
A_LIBS = -Lmp3lib -lMP3 -Llibac3 -lac3 $(ALSA_LIB) $(ESD_LIB)
|
A_LIBS = -Lmp3lib -lMP3 -Llibac3 -lac3 $(ALSA_LIB) $(ESD_LIB)
|
||||||
|
139
ac3-iec958.c
Normal file
139
ac3-iec958.c
Normal file
@ -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;
|
||||||
|
}
|
13
ac3-iec958.h
Normal file
13
ac3-iec958.h
Normal file
@ -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
|
@ -204,6 +204,7 @@ static short get_driver(char *s,int audioflag)
|
|||||||
"msgsm",
|
"msgsm",
|
||||||
"dshow",
|
"dshow",
|
||||||
"dvdpcm",
|
"dvdpcm",
|
||||||
|
"hwac3",
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
static char *videodrv[] = {
|
static char *videodrv[] = {
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#define AFM_GSM 6
|
#define AFM_GSM 6
|
||||||
#define AFM_DSHOW 7
|
#define AFM_DSHOW 7
|
||||||
#define AFM_DVDPCM 8
|
#define AFM_DVDPCM 8
|
||||||
|
#define AFM_HWAC3 9
|
||||||
|
|
||||||
#define VFM_MPEG 1
|
#define VFM_MPEG 1
|
||||||
#define VFM_VFW 2
|
#define VFM_VFW 2
|
||||||
|
36
dec_audio.c
36
dec_audio.c
@ -29,6 +29,8 @@ int fakemono=0;
|
|||||||
|
|
||||||
#include "xa/xa_gsm.h"
|
#include "xa/xa_gsm.h"
|
||||||
|
|
||||||
|
#include "ac3-iec958.h"
|
||||||
|
|
||||||
#ifdef USE_DIRECTSHOW
|
#ifdef USE_DIRECTSHOW
|
||||||
#include "loader/DirectShow/DS_AudioDec.h"
|
#include "loader/DirectShow/DS_AudioDec.h"
|
||||||
#endif
|
#endif
|
||||||
@ -130,6 +132,11 @@ case AFM_AC3:
|
|||||||
// Dolby AC3 audio:
|
// Dolby AC3 audio:
|
||||||
sh_audio->audio_out_minsize=4*256*6;
|
sh_audio->audio_out_minsize=4*256*6;
|
||||||
break;
|
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:
|
case AFM_GSM:
|
||||||
// MS-GSM audio codec:
|
// MS-GSM audio codec:
|
||||||
sh_audio->audio_out_minsize=4*320;
|
sh_audio->audio_out_minsize=4*320;
|
||||||
@ -219,6 +226,28 @@ case AFM_AC3: {
|
|||||||
}
|
}
|
||||||
break;
|
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: {
|
case AFM_ALAW: {
|
||||||
// aLaw audio codec:
|
// aLaw audio codec:
|
||||||
sh_audio->channels=sh_audio->wf->nChannels;
|
sh_audio->channels=sh_audio->wf->nChannels;
|
||||||
@ -332,6 +361,12 @@ int decode_audio(sh_audio_t *sh_audio,unsigned char *buf,int minlen,int maxlen){
|
|||||||
}
|
}
|
||||||
//printf("{3:%d}",avi_header.idx_pos);fflush(stdout);
|
//printf("{3:%d}",avi_header.idx_pos);fflush(stdout);
|
||||||
break;
|
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
|
#ifdef USE_WIN32DLL
|
||||||
case AFM_ACM:
|
case AFM_ACM:
|
||||||
// len=sh_audio->audio_out_minsize; // optimal decoded fragment size
|
// len=sh_audio->audio_out_minsize; // optimal decoded fragment size
|
||||||
@ -387,6 +422,7 @@ void resync_audio_stream(sh_audio_t *sh_audio){
|
|||||||
break;
|
break;
|
||||||
case AFM_ACM:
|
case AFM_ACM:
|
||||||
case AFM_DSHOW:
|
case AFM_DSHOW:
|
||||||
|
case AFM_HWAC3:
|
||||||
sh_audio->a_in_buffer_len=0; // reset ACM/DShow audio buffer
|
sh_audio->a_in_buffer_len=0; // reset ACM/DShow audio buffer
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -55,6 +55,9 @@ static int control(int cmd,int arg){
|
|||||||
{
|
{
|
||||||
ao_control_vol_t *vol = (ao_control_vol_t *)arg;
|
ao_control_vol_t *vol = (ao_control_vol_t *)arg;
|
||||||
int fd, v, mcmd, devs;
|
int fd, v, mcmd, devs;
|
||||||
|
|
||||||
|
if(ao_format == AFMT_AC3)
|
||||||
|
return CONTROL_TRUE;
|
||||||
|
|
||||||
if ((fd = open("/dev/mixer", O_RDONLY)) > 0)
|
if ((fd = open("/dev/mixer", O_RDONLY)) > 0)
|
||||||
{
|
{
|
||||||
@ -119,9 +122,14 @@ static int init(int rate,int channels,int format,int flags){
|
|||||||
|
|
||||||
ao_format=format;
|
ao_format=format;
|
||||||
ioctl (audio_fd, SNDCTL_DSP_SETFMT, &ao_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",
|
printf("audio_setup: sample format: %s (requested: %s)\n",
|
||||||
audio_out_format_name(ao_format), audio_out_format_name(format));
|
audio_out_format_name(ao_format), audio_out_format_name(format));
|
||||||
|
|
||||||
|
if(format != AFMT_AC3) {
|
||||||
ao_channels=channels-1;
|
ao_channels=channels-1;
|
||||||
ioctl (audio_fd, SNDCTL_DSP_STEREO, &ao_channels);
|
ioctl (audio_fd, SNDCTL_DSP_STEREO, &ao_channels);
|
||||||
|
|
||||||
@ -129,6 +137,7 @@ static int init(int rate,int channels,int format,int flags){
|
|||||||
ao_samplerate=rate;
|
ao_samplerate=rate;
|
||||||
ioctl (audio_fd, SNDCTL_DSP_SPEED, &ao_samplerate);
|
ioctl (audio_fd, SNDCTL_DSP_SPEED, &ao_samplerate);
|
||||||
printf("audio_setup: using %d Hz samplerate (requested: %d)\n",ao_samplerate,rate);
|
printf("audio_setup: using %d Hz samplerate (requested: %d)\n",ao_samplerate,rate);
|
||||||
|
}
|
||||||
|
|
||||||
if(ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &zz)==-1){
|
if(ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &zz)==-1){
|
||||||
int r=0;
|
int r=0;
|
||||||
@ -191,9 +200,10 @@ static void reset(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
ioctl (audio_fd, SNDCTL_DSP_SETFMT, &ao_format);
|
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_STEREO, &ao_channels);
|
||||||
ioctl (audio_fd, SNDCTL_DSP_SPEED, &ao_samplerate);
|
ioctl (audio_fd, SNDCTL_DSP_SPEED, &ao_samplerate);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// stop playing, keep buffers (for pause)
|
// stop playing, keep buffers (for pause)
|
||||||
|
@ -87,6 +87,8 @@ char *audio_out_format_name(int format)
|
|||||||
return("Unsigned 16-bit (Big-Endian)");
|
return("Unsigned 16-bit (Big-Endian)");
|
||||||
case AFMT_MPEG:
|
case AFMT_MPEG:
|
||||||
return("MPEG (2) audio");
|
return("MPEG (2) audio");
|
||||||
|
case AFMT_AC3:
|
||||||
|
return("AC3");
|
||||||
/*
|
/*
|
||||||
the following two formats are not available with old linux kernel
|
the following two formats are not available with old linux kernel
|
||||||
headers (e.g. in 2.2.16)
|
headers (e.g. in 2.2.16)
|
||||||
|
Loading…
Reference in New Issue
Block a user