Mercurial > mplayer.hg
comparison libmpcodecs/ad_vorbis.c @ 5427:0b5462a620fc
vorbis driver ported, and also fixed a bug, as nominal_bitrate can be -1
author | arpi |
---|---|
date | Sun, 31 Mar 2002 20:08:19 +0000 |
parents | |
children | e4c2a5541a6a |
comparison
equal
deleted
inserted
replaced
5426:d72dc493c5d3 | 5427:0b5462a620fc |
---|---|
1 | |
2 #include <stdio.h> | |
3 #include <stdlib.h> | |
4 #include <unistd.h> | |
5 | |
6 #include "config.h" | |
7 #include "ad_internal.h" | |
8 | |
9 #ifdef HAVE_OGGVORBIS | |
10 | |
11 static ad_info_t info = | |
12 { | |
13 "Ogg/Vorbis audio decoder", | |
14 "libvorbis", | |
15 AFM_VORBIS, | |
16 "Felix Buenemann, A'rpi", | |
17 "libvorbis", | |
18 "buggy" | |
19 }; | |
20 | |
21 LIBAD_EXTERN(vorbis) | |
22 | |
23 #include <math.h> | |
24 #include <vorbis/codec.h> | |
25 | |
26 // This struct is also defined in demux_ogg.c => common header ? | |
27 typedef struct ov_struct_st { | |
28 vorbis_info vi; /* struct that stores all the static vorbis bitstream | |
29 settings */ | |
30 vorbis_comment vc; /* struct that stores all the bitstream user comments */ | |
31 vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */ | |
32 vorbis_block vb; /* local working space for packet->PCM decode */ | |
33 } ov_struct_t; | |
34 | |
35 static int preinit(sh_audio_t *sh) | |
36 { | |
37 sh->audio_out_minsize=1024*4; // 1024 samples/frame | |
38 return 1; | |
39 } | |
40 | |
41 static int init(sh_audio_t *sh) | |
42 { | |
43 ogg_packet op; | |
44 vorbis_comment vc; | |
45 struct ov_struct_st *ov; | |
46 | |
47 /// Init the decoder with the 3 header packets | |
48 ov = (struct ov_struct_st*)malloc(sizeof(struct ov_struct_st)); | |
49 vorbis_info_init(&ov->vi); | |
50 vorbis_comment_init(&vc); | |
51 op.bytes = ds_get_packet(sh->ds,&op.packet); | |
52 op.b_o_s = 1; | |
53 /// Header | |
54 if(vorbis_synthesis_headerin(&ov->vi,&vc,&op) <0) { | |
55 mp_msg(MSGT_DECAUDIO,MSGL_ERR,"OggVorbis: initial (identification) header broken!\n"); | |
56 free(ov); | |
57 return 0; | |
58 } | |
59 op.bytes = ds_get_packet(sh->ds,&op.packet); | |
60 op.b_o_s = 0; | |
61 /// Comments | |
62 if(vorbis_synthesis_headerin(&ov->vi,&vc,&op) <0) { | |
63 mp_msg(MSGT_DECAUDIO,MSGL_ERR,"OggVorbis: comment header broken!\n"); | |
64 free(ov); | |
65 return 0; | |
66 } | |
67 op.bytes = ds_get_packet(sh->ds,&op.packet); | |
68 //// Codebook | |
69 if(vorbis_synthesis_headerin(&ov->vi,&vc,&op)<0) { | |
70 mp_msg(MSGT_DECAUDIO,MSGL_WARN,"OggVorbis: codebook header broken!\n"); | |
71 free(ov); | |
72 return 0; | |
73 } else { /// Print the infos | |
74 char **ptr=vc.user_comments; | |
75 while(*ptr){ | |
76 mp_msg(MSGT_DECAUDIO,MSGL_V,"OggVorbisComment: %s\n",*ptr); | |
77 ++ptr; | |
78 } | |
79 mp_msg(MSGT_DECAUDIO,MSGL_V,"OggVorbis: Bitstream is %d channel, %dHz, %dbit/s %cBR\n",(int)ov->vi.channels,(int)ov->vi.rate,(int)ov->vi.bitrate_nominal, | |
80 (ov->vi.bitrate_lower!=ov->vi.bitrate_nominal)||(ov->vi.bitrate_upper!=ov->vi.bitrate_nominal)?'V':'C'); | |
81 mp_msg(MSGT_DECAUDIO,MSGL_V,"OggVorbis: Encoded by: %s\n",vc.vendor); | |
82 } | |
83 | |
84 // printf("lower=%d upper=%d \n",(int)ov->vi.bitrate_lower,(int)ov->vi.bitrate_upper); | |
85 | |
86 // Setup the decoder | |
87 sh->channels=ov->vi.channels; | |
88 sh->samplerate=ov->vi.rate; | |
89 // assume 128kbit if bitrate not specified in the header | |
90 sh->i_bps=((ov->vi.bitrate_nominal>0) ? ov->vi.bitrate_nominal : 128000)/8; | |
91 sh->context = ov; | |
92 | |
93 /// Finish the decoder init | |
94 vorbis_synthesis_init(&ov->vd,&ov->vi); | |
95 vorbis_block_init(&ov->vd,&ov->vb); | |
96 mp_msg(MSGT_DECAUDIO,MSGL_V,"OggVorbis: Init OK!\n"); | |
97 | |
98 return 1; | |
99 } | |
100 | |
101 static void uninit(sh_audio_t *sh) | |
102 { | |
103 } | |
104 | |
105 static int control(sh_audio_t *sh,int cmd,void* arg, ...) | |
106 { | |
107 switch(cmd) | |
108 { | |
109 #if 0 | |
110 case ADCTRL_RESYNC_STREAM: | |
111 return CONTROL_TRUE; | |
112 case ADCTRL_SKIP_FRAME: | |
113 return CONTROL_TRUE; | |
114 #endif | |
115 } | |
116 return CONTROL_UNKNOWN; | |
117 } | |
118 | |
119 static int decode_audio(sh_audio_t *sh,unsigned char *buf,int minlen,int maxlen) | |
120 { | |
121 int len = 0; | |
122 int samples; | |
123 float **pcm; | |
124 ogg_packet op; | |
125 char* np; | |
126 struct ov_struct_st *ov = sh->context; | |
127 op.b_o_s = op.e_o_s = 0; | |
128 while(len < minlen) { | |
129 op.bytes = ds_get_packet(sh->ds,&op.packet); | |
130 if(!op.packet) | |
131 break; | |
132 if(vorbis_synthesis(&ov->vb,&op)==0) /* test for success! */ | |
133 vorbis_synthesis_blockin(&ov->vd,&ov->vb); | |
134 while((samples=vorbis_synthesis_pcmout(&ov->vd,&pcm))>0){ | |
135 int i,j; | |
136 int clipflag=0; | |
137 int convsize=(maxlen-len)/(2*ov->vi.channels); // max size! | |
138 int bout=(samples<convsize?samples:convsize); | |
139 | |
140 if(bout<=0) break; | |
141 | |
142 /* convert floats to 16 bit signed ints (host order) and | |
143 interleave */ | |
144 for(i=0;i<ov->vi.channels;i++){ | |
145 ogg_int16_t *convbuffer=(ogg_int16_t *)(&buf[len]); | |
146 ogg_int16_t *ptr=convbuffer+i; | |
147 float *mono=pcm[i]; | |
148 for(j=0;j<bout;j++){ | |
149 #if 1 | |
150 int val=mono[j]*32767.f; | |
151 #else /* optional dither */ | |
152 int val=mono[j]*32767.f+drand48()-0.5f; | |
153 #endif | |
154 /* might as well guard against clipping */ | |
155 if(val>32767){ | |
156 val=32767; | |
157 clipflag=1; | |
158 } | |
159 if(val<-32768){ | |
160 val=-32768; | |
161 clipflag=1; | |
162 } | |
163 *ptr=val; | |
164 ptr+=ov->vi.channels; | |
165 } | |
166 } | |
167 | |
168 if(clipflag) | |
169 mp_msg(MSGT_DECAUDIO,MSGL_DBG2,"Clipping in frame %ld\n",(long)(ov->vd.sequence)); | |
170 len+=2*ov->vi.channels*bout; | |
171 mp_msg(MSGT_DECAUDIO,MSGL_DBG2,"\n[decoded: %d / %d ]\n",bout,samples); | |
172 vorbis_synthesis_read(&ov->vd,bout); /* tell libvorbis how | |
173 many samples we | |
174 actually consumed */ | |
175 } | |
176 } | |
177 | |
178 | |
179 | |
180 return len; | |
181 } | |
182 | |
183 #endif /* !HAVE_OGGVORBIS */ | |
184 |