Mercurial > mplayer.hg
changeset 1828:60afe3421c04
OggVorbis support, ALPHA state!
author | atmos4 |
---|---|
date | Sat, 01 Sep 2001 19:44:49 +0000 |
parents | 9d62dcf8c7c5 |
children | a4156c8cdd57 |
files | codec-cfg.c codec-cfg.h dec_audio.c etc/codecs.conf stheader.h |
diffstat | 5 files changed, 266 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/codec-cfg.c Sat Sep 01 19:43:41 2001 +0000 +++ b/codec-cfg.c Sat Sep 01 19:44:49 2001 +0000 @@ -205,6 +205,7 @@ "dshow", "dvdpcm", "hwac3", + "libvorbis", NULL }; static char *videodrv[] = {
--- a/codec-cfg.h Sat Sep 01 19:43:41 2001 +0000 +++ b/codec-cfg.h Sat Sep 01 19:44:49 2001 +0000 @@ -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
--- a/dec_audio.c Sat Sep 01 19:43:41 2001 +0000 +++ b/dec_audio.c Sat Sep 01 19:44:49 2001 +0000 @@ -37,6 +37,12 @@ #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 @@ // 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 @@ } #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 @@ 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 @@ 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;
--- a/etc/codecs.conf Sat Sep 01 19:43:41 2001 +0000 +++ b/etc/codecs.conf Sat Sep 01 19:44:49 2001 +0000 @@ -546,3 +546,15 @@ 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" +
--- a/stheader.h Sat Sep 01 19:43:41 2001 +0000 +++ b/stheader.h Sat Sep 01 19:44:49 2001 +0000 @@ -7,6 +7,24 @@ } 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 @@ // 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 {