1
0
mirror of https://github.com/mpv-player/mpv synced 2025-02-17 04:58:06 +00:00

OggVorbis support, ALPHA state!

git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@1829 b3059339-0415-0410-9bf9-f77b7e298cf2
This commit is contained in:
atmos4 2001-09-01 19:44:49 +00:00
parent 5d0b354e7a
commit aada0e47d2
5 changed files with 266 additions and 1 deletions

View File

@ -205,6 +205,7 @@ static short get_driver(char *s,int audioflag)
"dshow",
"dvdpcm",
"hwac3",
"libvorbis",
NULL
};
static char *videodrv[] = {

View File

@ -27,6 +27,7 @@
#define AFM_DSHOW 7
#define AFM_DVDPCM 8
#define AFM_HWAC3 9
#define AFM_VORBIS 10
#define VFM_MPEG 1
#define VFM_VFW 2

View File

@ -37,6 +37,12 @@ int fakemono=0;
#include "loader/DirectShow/DS_AudioDec.h"
#endif
#ifdef HAVE_OGGVORBIS
/* XXX is math.h really needed? - atmos */
#include <math.h>
#include <vorbis/codec.h>
#endif
extern int init_acm_audio_codec(sh_audio_t *sh_audio);
extern int acm_decode_audio(sh_audio_t *sh_audio, void* a_buffer,int minlen,int maxlen);
@ -110,7 +116,7 @@ case AFM_DSHOW:
// Win32 DShow audio codec:
// printf("DShow_audio: channs=%d rate=%d\n",sh_audio->channels,sh_audio->samplerate);
if(DS_AudioDecoder_Open(sh_audio->codec->dll,&sh_audio->codec->guid,sh_audio->wf)){
mp_msg(MSGT_DECAUDIO,MSGL_ERR,"ERROR: Could not load/initialize Win32/DirctShow AUDIO codec: %s\n",sh_audio->codec->dll);
mp_msg(MSGT_DECAUDIO,MSGL_ERR,"ERROR: Could not load/initialize Win32/DirectShow AUDIO codec: %s\n",sh_audio->codec->dll);
driver=0;
} else {
sh_audio->i_bps=sh_audio->wf->nAvgBytesPerSec;
@ -125,6 +131,15 @@ case AFM_DSHOW:
}
#endif
break;
case AFM_VORBIS:
#ifndef HAVE_OGGVORBIS
mp_msg(MSGT_DECAUDIO,MSGL_ERR,"OggVorbis audio codec disabled -> force nosound :(\n");
driver=0;
#else
/* OggVorbis audio via libvorbis, compatible with files created by nandub and zorannt codec */
sh_audio->audio_out_minsize=4096;
#endif
break;
case AFM_PCM:
case AFM_DVDPCM:
case AFM_ALAW:
@ -288,6 +303,126 @@ case AFM_MPEG: {
sh_audio->i_bps=MP3_bitrate*(1000/8);
break;
}
#ifdef HAVE_OGGVORBIS
case AFM_VORBIS: {
// OggVorbis Audio:
#if 0 /* just here for reference - atmos */
ogg_sync_state oy; /* sync and verify incoming physical bitstream */
ogg_stream_state os; /* take physical pages, weld into a logical
stream of packets */
ogg_page og; /* one Ogg bitstream page. Vorbis packets are inside */
ogg_packet op; /* one raw packet of data for decode */
vorbis_info vi; /* struct that stores all the static vorbis bitstream
settings */
vorbis_comment vc; /* struct that stores all the bitstream user comments */
vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */
vorbis_block vb; /* local working space for packet->PCM decode */
#else
/* nix, nada, rien, nothing, nem, nüx */
#endif
uint32_t hdrsizes[3];/* stores vorbis header sizes from AVI audio header,
maybe use ogg_uint32_t */
//int i;
int ret;
char *buffer;
ogg_packet hdr;
//ov_struct_t *s=&sh_audio->ov;
sh_audio->ov=malloc(sizeof(ov_struct_t));
//s=&sh_audio->ov;
vorbis_info_init(&sh_audio->ov->vi);
vorbis_comment_init(&sh_audio->ov->vc);
printf("OggVorbis: cbsize: %i\n", sh_audio->wf->cbSize);
memcpy(hdrsizes, ((unsigned char*)sh_audio->wf)+2*sizeof(WAVEFORMATEX), 3*sizeof(uint32_t));
printf("OggVorbis: Read header sizes: initial: %i comment: %i codebook: %i\n", hdrsizes[0], hdrsizes[1], hdrsizes[2]);
/*for(i=12; i <= 40; i+=2) { // header bruteforce :)
memcpy(hdrsizes, ((unsigned char*)sh_audio->wf)+i, 3*sizeof(uint32_t));
printf("OggVorbis: Read header sizes (%i): %ld %ld %ld\n", i, hdrsizes[0], hdrsizes[1], hdrsizes[2]);
}*/
/* read headers */ // FIXME disable sound on errors here, we absolutely need this headers! - atmos
hdr.packet=NULL;
hdr.b_o_s = 1; /* beginning of stream for first packet */
hdr.bytes = hdrsizes[0];
hdr.packet = realloc(hdr.packet,hdr.bytes);
memcpy(hdr.packet,((unsigned char*)sh_audio->wf)+2*sizeof(WAVEFORMATEX)+3*sizeof(uint32_t),hdr.bytes);
if(vorbis_synthesis_headerin(&sh_audio->ov->vi,&sh_audio->ov->vc,&hdr)<0)
printf("OggVorbis: initial (identification) header broken!\n");
hdr.b_o_s = 0;
hdr.bytes = hdrsizes[1];
hdr.packet = realloc(hdr.packet,hdr.bytes);
memcpy(hdr.packet,((unsigned char*)sh_audio->wf)+2*sizeof(WAVEFORMATEX)+3*sizeof(uint32_t)+hdrsizes[0],hdr.bytes);
if(vorbis_synthesis_headerin(&sh_audio->ov->vi,&sh_audio->ov->vc,&hdr)<0)
printf("OggVorbis: comment header broken!\n");
hdr.bytes = hdrsizes[2];
hdr.packet = realloc(hdr.packet,hdr.bytes);
memcpy(hdr.packet,((unsigned char*)sh_audio->wf)+2*sizeof(WAVEFORMATEX)+3*sizeof(uint32_t)+hdrsizes[0]+hdrsizes[1],hdr.bytes);
if(vorbis_synthesis_headerin(&sh_audio->ov->vi,&sh_audio->ov->vc,&hdr)<0)
printf("OggVorbis: codebook header broken!\n");
hdr.bytes=0;
hdr.packet = realloc(hdr.packet,hdr.bytes); /* free */
/* done with the headers */
/* Throw the comments plus a few lines about the bitstream we're
decoding */
{
char **ptr=sh_audio->ov->vc.user_comments;
while(*ptr){
printf("OggVorbisComment: %s\n",*ptr);
++ptr;
}
printf("OggVorbis: Bitstream is %d channel, %ldHz, %ldkbit/s %cBR\n",sh_audio->ov->vi.channels,sh_audio->ov->vi.rate,sh_audio->ov->vi.bitrate_nominal/1000, (sh_audio->ov->vi.bitrate_lower!=sh_audio->ov->vi.bitrate_nominal)||(sh_audio->ov->vi.bitrate_upper!=sh_audio->ov->vi.bitrate_nominal)?'V':'C');
printf("OggVorbis: Encoded by: %s\n",sh_audio->ov->vc.vendor);
}
sh_audio->channels=sh_audio->ov->vi.channels;
sh_audio->samplerate=sh_audio->ov->vi.rate;
sh_audio->i_bps=sh_audio->ov->vi.bitrate_nominal/8;
// printf("[\n");
sh_audio->a_buffer_len=sh_audio->audio_out_minsize;///ov->vi.channels;
// printf("]\n");
/* OK, got and parsed all three headers. Initialize the Vorbis
packet->PCM decoder. */
vorbis_synthesis_init(&sh_audio->ov->vd,&sh_audio->ov->vi); /* central decode state */
vorbis_block_init(&sh_audio->ov->vd,&sh_audio->ov->vb); /* local state for most of the decode
so multiple block decodes can
proceed in parallel. We could init
multiple vorbis_block structures
for vd here */
//printf("OggVorbis: synthesis and block init done.\n");
ogg_sync_init(&sh_audio->ov->oy); /* Now we can read pages */
while((ret = ogg_sync_pageout(&sh_audio->ov->oy,&sh_audio->ov->og))!=1) {
if(ret == -1)
printf("OggVorbis: Pageout: not properly synced, had to skip some bytes.\n");
else
if(ret == 0) {
printf("OggVorbis: Pageout: need more data to verify page, reading more data.\n");
/* submit a a_buffer_len block to libvorbis' Ogg layer */
buffer=ogg_sync_buffer(&sh_audio->ov->oy,sh_audio->a_buffer_len);
ogg_sync_wrote(&sh_audio->ov->oy,demux_read_data(sh_audio->ds,buffer,sh_audio->a_buffer_len));
}
}
printf("OggVorbis: Pageout: successfull.\n");
/* commenting out pagein to leave data (hopefully) to the decoder - atmos */
//ogg_stream_pagein(&sh_audio->ov->os,&sh_audio->ov->og); /* we can ignore any errors here
// as they'll also become apparent
// at packetout */
/* Get the serial number and set up the rest of decode. */
/* serialno first; use it to set up a logical stream */
ogg_stream_init(&sh_audio->ov->os,ogg_page_serialno(&sh_audio->ov->og));
printf("OggVorbis: Init OK!\n");
break;
}
#endif
}
if(!sh_audio->channels || !sh_audio->samplerate){
@ -318,6 +453,101 @@ int decode_audio(sh_audio_t *sh_audio,unsigned char *buf,int minlen,int maxlen){
len=MP3_DecodeFrame(buf,-1);
// len=MP3_DecodeFrame(buf,3);
break;
case AFM_VORBIS: { // OggVorbis
/* note: good minlen would be 4k or 8k IMHO - atmos */
int ret;
char *buffer;
int bytes;
int samples;
float **pcm;
ogg_int16_t convbuffer[4096];
int convsize;
minlen=4096; // XXX hack, not neccessarily needed - atmos
convsize=minlen/sh_audio->ov->vi.channels;
while((ret = ogg_sync_pageout(&sh_audio->ov->oy,&sh_audio->ov->og))!=1) {
if(ret == -1)
printf("OggVorbis: Pageout: not properly synced, had to skip some bytes.\n");
else
if(ret == 0) {
//printf("OggVorbis: Pageout: need more data to verify page, reading more data.\n");
/* submit a minlen k block to libvorbis' Ogg layer */
buffer=ogg_sync_buffer(&sh_audio->ov->oy,minlen);
bytes=demux_read_data(sh_audio->ds,buffer,minlen);
ogg_sync_wrote(&sh_audio->ov->oy,bytes);
if(bytes==0)
printf("OggVorbis: 0Bytes written, possible End of Stream\n");
}
}
//printf("OggVorbis: Pageout: successfull, pagin in.\n");
if(ogg_stream_pagein(&sh_audio->ov->os,&sh_audio->ov->og)<0)
printf("OggVorbis: Pagein failed!\n");
ret=ogg_stream_packetout(&sh_audio->ov->os,&sh_audio->ov->op);
if(ret==0)
printf("OggVorbis: Packetout: need more data, FIXME!\n");
else
if(ret<0)
printf("OggVorbis: Packetout: missing or corrupt data, skipping packet!\n");
else {
/* we have a packet. Decode it */
if(vorbis_synthesis(&sh_audio->ov->vb,&sh_audio->ov->op)==0) /* test for success! */
vorbis_synthesis_blockin(&sh_audio->ov->vd,&sh_audio->ov->vb);
/* **pcm is a multichannel float vector. In stereo, for
example, pcm[0] is left, and pcm[1] is right. samples is
the size of each channel. Convert the float values
(-1.<=range<=1.) to whatever PCM format and write it out */
while((samples=vorbis_synthesis_pcmout(&sh_audio->ov->vd,&pcm))>0){
int i,j;
int clipflag=0;
int bout=(samples<convsize?samples:convsize);
/* convert floats to 16 bit signed ints (host order) and
interleave */
for(i=0;i<sh_audio->ov->vi.channels;i++){
ogg_int16_t *ptr=convbuffer+i;
float *mono=pcm[i];
for(j=0;j<bout;j++){
#if 1
int val=mono[j]*32767.f;
#else /* optional dither */
int val=mono[j]*32767.f+drand48()-0.5f;
#endif
/* might as well guard against clipping */
if(val>32767){
val=32767;
clipflag=1;
}
if(val<-32768){
val=-32768;
clipflag=1;
}
*ptr=val;
ptr+=sh_audio->ov->vi.channels;
}
}
if(clipflag)
printf("Clipping in frame %ld\n",(long)(sh_audio->ov->vd.sequence));
//fwrite(convbuffer,2*sh_audio->ov->vi.channels,bout,stderr); //dump pcm to file for debugging
len=2*sh_audio->ov->vi.channels*bout;
memcpy(buf,convbuffer,len);
vorbis_synthesis_read(&sh_audio->ov->vd,bout); /* tell libvorbis how
many samples we
actually consumed */
}
if(ogg_page_eos(&sh_audio->ov->og))
printf("OggVorbis: End of Stream reached!\n"); // FIXME clearup decoder, notify mplayer - atmos
} // from else, packetout ok
break;
}
case AFM_PCM: // AVI PCM
len=demux_read_data(sh_audio->ds,buf,minlen);
break;

View File

@ -546,3 +546,15 @@ audiocodec hwac3
driver hwac3
dll "ac3-iec958.c"
audiocodec vorbis
info "OggVorbis Audio Decoder"
status working
comment "OggVorbis driver using libvorbis"
format 0xFFFE
driver libvorbis
dll "libvorbis"
flags seekable
; acm codec doesn't work, haven't tried zorannt dshow codec
; driver acm
; dll "vorbis.acm"

View File

@ -7,6 +7,24 @@ typedef struct {
} codecinfo_t;
*/
#ifdef HAVE_OGGVORBIS
#include <math.h>
#include <vorbis/codec.h>
typedef struct {
ogg_sync_state oy; /* sync and verify incoming physical bitstream */
ogg_stream_state os; /* take physical pages, weld into a logical
stream of packets */
ogg_page og; /* one Ogg bitstream page. Vorbis packets are inside */
ogg_packet op; /* one raw packet of data for decode */
vorbis_info vi; /* struct that stores all the static vorbis bitstream
settings */
vorbis_comment vc; /* struct that stores all the bitstream user comments */
vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */
vorbis_block vb; /* local working space for packet->PCM decode */
} ov_struct_t;
#endif
typedef struct {
demux_stream_t *ds;
unsigned int format;
@ -40,6 +58,9 @@ typedef struct {
// ac3_frame_t *ac3_frame;
void* ac3_frame;
int pcm_bswap;
#ifdef HAVE_OGGVORBIS
ov_struct_t *ov; // should be assigned on init
#endif
} sh_audio_t;
typedef struct {