9 #include "ad_internal.h"
11 static ad_info_t info
=
13 "Ogg/Vorbis audio decoder",
15 "Felix Buenemann, A'rpi",
20 LIBAD_EXTERN(libvorbis
)
23 #include <tremor/ivorbiscodec.h>
25 #include <vorbis/codec.h>
28 // This struct is also defined in demux_ogg.c => common header ?
29 typedef struct ov_struct_st
{
30 vorbis_info vi
; /* struct that stores all the static vorbis bitstream
32 vorbis_comment vc
; /* struct that stores all the bitstream user comments */
33 vorbis_dsp_state vd
; /* central working state for the packet->PCM decoder */
34 vorbis_block vb
; /* local working space for packet->PCM decode */
35 float rg_scale
; /* replaygain scale */
41 static int read_vorbis_comment( char* ptr
, const char* comment
, const char* format
, ... ) {
45 va_start( va
, format
);
46 clen
= strlen( comment
);
47 ret
= strncasecmp( ptr
, comment
, clen
) == 0 ? vsscanf( ptr
+clen
, format
, va
) : 0;
53 static int preinit(sh_audio_t
*sh
)
55 sh
->audio_out_minsize
=1024*4; // 1024 samples/frame
59 static int init(sh_audio_t
*sh
)
61 unsigned int offset
, i
, length
, hsizes
[3];
63 unsigned char* extradata
;
66 struct ov_struct_st
*ov
;
68 vorbis_comment_clear(&vc); \
69 vorbis_info_clear(&ov->vi); \
74 /// Init the decoder with the 3 header packets
75 ov
= malloc(sizeof(struct ov_struct_st
));
76 vorbis_info_init(&ov
->vi
);
77 vorbis_comment_init(&vc
);
80 mp_msg(MSGT_DECAUDIO
,MSGL_ERR
,"ad_vorbis, extradata seems to be absent! exit\n");
84 if(! sh
->wf
->cbSize
) {
85 mp_msg(MSGT_DECAUDIO
,MSGL_ERR
,"ad_vorbis, extradata seems to be absent!, exit\n");
89 mp_msg(MSGT_DECAUDIO
,MSGL_V
,"ad_vorbis, extradata seems is %d bytes long\n", sh
->wf
->cbSize
);
90 extradata
= (char*) (sh
->wf
+1);
92 mp_msg(MSGT_DECAUDIO
,MSGL_ERR
,"ad_vorbis, extradata seems to be NULL!, exit\n");
97 mp_msg (MSGT_DEMUX
, MSGL_WARN
, "ad_vorbis: Vorbis track does not contain valid headers.\n");
102 for (i
=0; i
< 2; i
++) {
104 while ((extradata
[offset
] == (unsigned char) 0xFF) && length
< sh
->wf
->cbSize
) {
108 if(offset
>= (sh
->wf
->cbSize
- 1)) {
109 mp_msg (MSGT_DEMUX
, MSGL_WARN
, "ad_vorbis: Vorbis track does not contain valid headers.\n");
112 length
+= extradata
[offset
];
114 mp_msg (MSGT_DEMUX
, MSGL_V
, "ad_vorbis, offset: %u, length: %u\n", offset
, length
);
118 headers
[0] = &extradata
[offset
];
119 headers
[1] = &extradata
[offset
+ hsizes
[0]];
120 headers
[2] = &extradata
[offset
+ hsizes
[0] + hsizes
[1]];
121 hsizes
[2] = sh
->wf
->cbSize
- offset
- hsizes
[0] - hsizes
[1];
122 mp_msg (MSGT_DEMUX
, MSGL_V
, "ad_vorbis, header sizes: %d %d %d\n", hsizes
[0], hsizes
[1], hsizes
[2]);
125 op
.bytes
= hsizes
[i
];
126 op
.packet
= headers
[i
];
128 if(vorbis_synthesis_headerin(&ov
->vi
,&vc
,&op
) <0) {
129 mp_msg(MSGT_DECAUDIO
,MSGL_ERR
,"OggVorbis: header n. %d broken! len=%ld\n", i
, op
.bytes
);
133 float rg_gain
=0.f
, rg_peak
=0.f
;
134 char **ptr
=vc
.user_comments
;
136 mp_msg(MSGT_DECAUDIO
,MSGL_V
,"OggVorbisComment: %s\n",*ptr
);
138 read_vorbis_comment( *ptr
, "replaygain_album_gain=", "%f", &rg_gain
);
139 read_vorbis_comment( *ptr
, "rg_audiophile=", "%f", &rg_gain
);
141 read_vorbis_comment( *ptr
, "replaygain_track_gain=", "%f", &rg_gain
);
142 read_vorbis_comment( *ptr
, "rg_radio=", "%f", &rg_gain
);
144 read_vorbis_comment( *ptr
, "replaygain_album_peak=", "%f", &rg_peak
);
146 read_vorbis_comment( *ptr
, "replaygain_track_peak=", "%f", &rg_peak
);
147 read_vorbis_comment( *ptr
, "rg_peak=", "%f", &rg_peak
);
151 /* replaygain: scale */
153 ov
->rg_scale
= 1.f
; /* just in case pow() isn't standard-conformant */
155 ov
->rg_scale
= pow(10.f
, rg_gain
/20);
156 /* replaygain: anticlip */
157 if(ov
->rg_scale
* rg_peak
> 1.f
)
158 ov
->rg_scale
= 1.f
/ rg_peak
;
159 /* replaygain: security */
160 if(ov
->rg_scale
> 15.)
163 ov
->rg_scale_int
= (int)(ov
->rg_scale
*64.f
);
165 mp_msg(MSGT_DECAUDIO
,MSGL_V
,"OggVorbis: Bitstream is %d channel%s, %dHz, %dbit/s %cBR\n",(int)ov
->vi
.channels
,ov
->vi
.channels
>1?"s":"",(int)ov
->vi
.rate
,(int)ov
->vi
.bitrate_nominal
,
166 (ov
->vi
.bitrate_lower
!=ov
->vi
.bitrate_nominal
)||(ov
->vi
.bitrate_upper
!=ov
->vi
.bitrate_nominal
)?'V':'C');
167 if(rg_gain
|| rg_peak
)
168 mp_msg(MSGT_DECAUDIO
,MSGL_V
,"OggVorbis: Gain = %+.2f dB, Peak = %.4f, Scale = %.2f\n", rg_gain
, rg_peak
, ov
->rg_scale
);
169 mp_msg(MSGT_DECAUDIO
,MSGL_V
,"OggVorbis: Encoded by: %s\n",vc
.vendor
);
173 vorbis_comment_clear(&vc
);
175 // printf("lower=%d upper=%d \n",(int)ov->vi.bitrate_lower,(int)ov->vi.bitrate_upper);
178 sh
->channels
=ov
->vi
.channels
;
179 sh
->samplerate
=ov
->vi
.rate
;
181 // assume 128kbit if bitrate not specified in the header
182 sh
->i_bps
=((ov
->vi
.bitrate_nominal
>0) ? ov
->vi
.bitrate_nominal
: 128000)/8;
185 /// Finish the decoder init
186 vorbis_synthesis_init(&ov
->vd
,&ov
->vi
);
187 vorbis_block_init(&ov
->vd
,&ov
->vb
);
188 mp_msg(MSGT_DECAUDIO
,MSGL_V
,"OggVorbis: Init OK!\n");
193 static void uninit(sh_audio_t
*sh
)
195 struct ov_struct_st
*ov
= sh
->context
;
196 vorbis_dsp_clear(&ov
->vd
);
197 vorbis_block_clear(&ov
->vb
);
198 vorbis_info_clear(&ov
->vi
);
202 static int control(sh_audio_t
*sh
,int cmd
,void* arg
, ...)
207 case ADCTRL_RESYNC_STREAM
:
209 case ADCTRL_SKIP_FRAME
:
213 return CONTROL_UNKNOWN
;
216 static int decode_audio(sh_audio_t
*sh
,unsigned char *buf
,int minlen
,int maxlen
)
226 struct ov_struct_st
*ov
= sh
->context
;
227 while(len
< minlen
) {
228 while((samples
=vorbis_synthesis_pcmout(&ov
->vd
,&pcm
))<=0){
231 memset(&op
,0,sizeof(op
)); //op.b_o_s = op.e_o_s = 0;
232 op
.bytes
= ds_get_packet_pts(sh
->ds
,&op
.packet
, &pts
);
233 if(op
.bytes
<=0) break;
234 if (pts
!= MP_NOPTS_VALUE
) {
238 if(vorbis_synthesis(&ov
->vb
,&op
)==0) /* test for success! */
239 vorbis_synthesis_blockin(&ov
->vd
,&ov
->vb
);
241 if(samples
<=0) break; // error/EOF
245 int convsize
=(maxlen
-len
)/(2*ov
->vi
.channels
); // max size!
246 int bout
=((samples
<convsize
)?samples
:convsize
);
248 if(bout
<=0) break; // no buffer space
250 /* convert floats to 16 bit signed ints (host order) and
253 if (ov
->rg_scale_int
== 64) {
254 for(i
=0;i
<ov
->vi
.channels
;i
++){
255 ogg_int16_t
*convbuffer
=(ogg_int16_t
*)(&buf
[len
]);
256 ogg_int16_t
*ptr
=convbuffer
+i
;
257 ogg_int32_t
*mono
=pcm
[i
];
260 /* might as well guard against clipping */
270 ptr
+=ov
->vi
.channels
;
277 scale
= 32767.f
* ov
->rg_scale
;
279 for(i
=0;i
<ov
->vi
.channels
;i
++){
280 ogg_int16_t
*convbuffer
=(ogg_int16_t
*)(&buf
[len
]);
281 ogg_int16_t
*ptr
=convbuffer
+i
;
283 ogg_int32_t
*mono
=pcm
[i
];
285 int val
=(mono
[j
]*ov
->rg_scale_int
)>>(9+6);
289 int val
=mono
[j
]*scale
;
290 /* might as well guard against clipping */
301 ptr
+=ov
->vi
.channels
;
307 mp_msg(MSGT_DECAUDIO
,MSGL_DBG2
,"Clipping in frame %ld\n",(long)(ov
->vd
.sequence
));
308 len
+=2*ov
->vi
.channels
*bout
;
309 sh
->pts_bytes
+= 2*ov
->vi
.channels
*bout
;
310 mp_msg(MSGT_DECAUDIO
,MSGL_DBG2
,"\n[decoded: %d / %d ]\n",bout
,samples
);
312 vorbis_synthesis_read(&ov
->vd
,bout
); /* tell libvorbis how
316 // if (!samples) break; // why? how?