2 * This file is part of MPlayer.
4 * MPlayer is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * MPlayer is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 #include "ad_internal.h"
27 #include "libaf/reorder_ch.h"
29 static const ad_info_t info
=
31 "Ogg/Vorbis audio decoder",
37 "Felix Buenemann, A'rpi",
42 LIBAD_EXTERN(libvorbis
)
45 #include <tremor/ivorbiscodec.h>
47 #include <vorbis/codec.h>
50 // This struct is also defined in demux_ogg.c => common header ?
51 typedef struct ov_struct_st
{
52 vorbis_info vi
; /* struct that stores all the static vorbis bitstream
54 vorbis_comment vc
; /* struct that stores all the bitstream user comments */
55 vorbis_dsp_state vd
; /* central working state for the packet->PCM decoder */
56 vorbis_block vb
; /* local working space for packet->PCM decode */
57 float rg_scale
; /* replaygain scale */
63 static int read_vorbis_comment( char* ptr
, const char* comment
, const char* format
, ... ) {
67 va_start( va
, format
);
68 clen
= strlen( comment
);
69 ret
= strncasecmp( ptr
, comment
, clen
) == 0 ? vsscanf( ptr
+clen
, format
, va
) : 0;
75 static int preinit(sh_audio_t
*sh
)
77 sh
->audio_out_minsize
=1024*4; // 1024 samples/frame
81 static int init(sh_audio_t
*sh
)
83 unsigned int offset
, i
, length
, hsizes
[3];
85 unsigned char* extradata
;
88 struct ov_struct_st
*ov
;
90 vorbis_comment_clear(&vc); \
91 vorbis_info_clear(&ov->vi); \
96 /// Init the decoder with the 3 header packets
97 ov
= malloc(sizeof(struct ov_struct_st
));
98 vorbis_info_init(&ov
->vi
);
99 vorbis_comment_init(&vc
);
102 mp_msg(MSGT_DECAUDIO
,MSGL_ERR
,"ad_vorbis, extradata seems to be absent! exit\n");
106 if(! sh
->wf
->cbSize
) {
107 mp_msg(MSGT_DECAUDIO
,MSGL_ERR
,"ad_vorbis, extradata seems to be absent!, exit\n");
111 mp_msg(MSGT_DECAUDIO
,MSGL_V
,"ad_vorbis, extradata seems is %d bytes long\n", sh
->wf
->cbSize
);
112 extradata
= (char*) (sh
->wf
+1);
114 mp_msg(MSGT_DECAUDIO
,MSGL_ERR
,"ad_vorbis, extradata seems to be NULL!, exit\n");
118 if(*extradata
!= 2) {
119 mp_msg (MSGT_DEMUX
, MSGL_WARN
, "ad_vorbis: Vorbis track does not contain valid headers.\n");
124 for (i
=0; i
< 2; i
++) {
126 while ((extradata
[offset
] == (unsigned char) 0xFF) && length
< sh
->wf
->cbSize
) {
130 if(offset
>= (sh
->wf
->cbSize
- 1)) {
131 mp_msg (MSGT_DEMUX
, MSGL_WARN
, "ad_vorbis: Vorbis track does not contain valid headers.\n");
134 length
+= extradata
[offset
];
136 mp_msg (MSGT_DEMUX
, MSGL_V
, "ad_vorbis, offset: %u, length: %u\n", offset
, length
);
140 headers
[0] = &extradata
[offset
];
141 headers
[1] = &extradata
[offset
+ hsizes
[0]];
142 headers
[2] = &extradata
[offset
+ hsizes
[0] + hsizes
[1]];
143 hsizes
[2] = sh
->wf
->cbSize
- offset
- hsizes
[0] - hsizes
[1];
144 mp_msg (MSGT_DEMUX
, MSGL_V
, "ad_vorbis, header sizes: %d %d %d\n", hsizes
[0], hsizes
[1], hsizes
[2]);
147 op
.bytes
= hsizes
[i
];
148 op
.packet
= headers
[i
];
150 if(vorbis_synthesis_headerin(&ov
->vi
,&vc
,&op
) <0) {
151 mp_msg(MSGT_DECAUDIO
,MSGL_ERR
,"OggVorbis: header n. %d broken! len=%ld\n", i
, op
.bytes
);
155 float rg_gain
=0.f
, rg_peak
=0.f
;
156 char **ptr
=vc
.user_comments
;
158 mp_msg(MSGT_DECAUDIO
,MSGL_V
,"OggVorbisComment: %s\n",*ptr
);
160 read_vorbis_comment( *ptr
, "replaygain_album_gain=", "%f", &rg_gain
);
161 read_vorbis_comment( *ptr
, "rg_audiophile=", "%f", &rg_gain
);
163 read_vorbis_comment( *ptr
, "replaygain_track_gain=", "%f", &rg_gain
);
164 read_vorbis_comment( *ptr
, "rg_radio=", "%f", &rg_gain
);
166 read_vorbis_comment( *ptr
, "replaygain_album_peak=", "%f", &rg_peak
);
168 read_vorbis_comment( *ptr
, "replaygain_track_peak=", "%f", &rg_peak
);
169 read_vorbis_comment( *ptr
, "rg_peak=", "%f", &rg_peak
);
173 /* replaygain: scale */
175 ov
->rg_scale
= 1.f
; /* just in case pow() isn't standard-conformant */
177 ov
->rg_scale
= pow(10.f
, rg_gain
/20);
178 /* replaygain: anticlip */
179 if(ov
->rg_scale
* rg_peak
> 1.f
)
180 ov
->rg_scale
= 1.f
/ rg_peak
;
181 /* replaygain: security */
182 if(ov
->rg_scale
> 15.)
185 ov
->rg_scale_int
= (int)(ov
->rg_scale
*64.f
);
187 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
,
188 (ov
->vi
.bitrate_lower
!=ov
->vi
.bitrate_nominal
)||(ov
->vi
.bitrate_upper
!=ov
->vi
.bitrate_nominal
)?'V':'C');
189 if(rg_gain
|| rg_peak
)
190 mp_msg(MSGT_DECAUDIO
,MSGL_V
,"OggVorbis: Gain = %+.2f dB, Peak = %.4f, Scale = %.2f\n", rg_gain
, rg_peak
, ov
->rg_scale
);
191 mp_msg(MSGT_DECAUDIO
,MSGL_V
,"OggVorbis: Encoded by: %s\n",vc
.vendor
);
195 vorbis_comment_clear(&vc
);
197 // printf("lower=%d upper=%d \n",(int)ov->vi.bitrate_lower,(int)ov->vi.bitrate_upper);
200 sh
->channels
=ov
->vi
.channels
;
201 sh
->samplerate
=ov
->vi
.rate
;
203 // assume 128kbit if bitrate not specified in the header
204 sh
->i_bps
=((ov
->vi
.bitrate_nominal
>0) ? ov
->vi
.bitrate_nominal
: 128000)/8;
207 /// Finish the decoder init
208 vorbis_synthesis_init(&ov
->vd
,&ov
->vi
);
209 vorbis_block_init(&ov
->vd
,&ov
->vb
);
210 mp_msg(MSGT_DECAUDIO
,MSGL_V
,"OggVorbis: Init OK!\n");
215 static void uninit(sh_audio_t
*sh
)
217 struct ov_struct_st
*ov
= sh
->context
;
218 vorbis_dsp_clear(&ov
->vd
);
219 vorbis_block_clear(&ov
->vb
);
220 vorbis_info_clear(&ov
->vi
);
224 static int control(sh_audio_t
*sh
,int cmd
,void* arg
, ...)
229 case ADCTRL_RESYNC_STREAM
:
231 case ADCTRL_SKIP_FRAME
:
235 return CONTROL_UNKNOWN
;
238 static int decode_audio(sh_audio_t
*sh
,unsigned char *buf
,int minlen
,int maxlen
)
248 struct ov_struct_st
*ov
= sh
->context
;
249 while(len
< minlen
) {
250 while((samples
=vorbis_synthesis_pcmout(&ov
->vd
,&pcm
))<=0){
253 memset(&op
,0,sizeof(op
)); //op.b_o_s = op.e_o_s = 0;
254 op
.bytes
= ds_get_packet_pts(sh
->ds
,&op
.packet
, &pts
);
255 if(op
.bytes
<=0) break;
256 if (pts
!= MP_NOPTS_VALUE
) {
260 if(vorbis_synthesis(&ov
->vb
,&op
)==0) /* test for success! */
261 vorbis_synthesis_blockin(&ov
->vd
,&ov
->vb
);
263 if(samples
<=0) break; // error/EOF
267 int convsize
=(maxlen
-len
)/(2*ov
->vi
.channels
); // max size!
268 int bout
=((samples
<convsize
)?samples
:convsize
);
270 if(bout
<=0) break; // no buffer space
272 /* convert floats to 16 bit signed ints (host order) and
275 if (ov
->rg_scale_int
== 64) {
276 for(i
=0;i
<ov
->vi
.channels
;i
++){
277 ogg_int16_t
*convbuffer
=(ogg_int16_t
*)(&buf
[len
]);
278 ogg_int16_t
*ptr
=convbuffer
+i
;
279 ogg_int32_t
*mono
=pcm
[i
];
282 /* might as well guard against clipping */
292 ptr
+=ov
->vi
.channels
;
296 #endif /* CONFIG_TREMOR */
298 #ifndef CONFIG_TREMOR
299 scale
= 32767.f
* ov
->rg_scale
;
301 for(i
=0;i
<ov
->vi
.channels
;i
++){
302 ogg_int16_t
*convbuffer
=(ogg_int16_t
*)(&buf
[len
]);
303 ogg_int16_t
*ptr
=convbuffer
+i
;
305 ogg_int32_t
*mono
=pcm
[i
];
307 int val
=(mono
[j
]*ov
->rg_scale_int
)>>(9+6);
311 int val
=mono
[j
]*scale
;
312 /* might as well guard against clipping */
321 #endif /* CONFIG_TREMOR */
323 ptr
+=ov
->vi
.channels
;
329 mp_msg(MSGT_DECAUDIO
,MSGL_DBG2
,"Clipping in frame %ld\n",(long)(ov
->vd
.sequence
));
330 len
+=2*ov
->vi
.channels
*bout
;
331 sh
->pts_bytes
+= 2*ov
->vi
.channels
*bout
;
332 mp_msg(MSGT_DECAUDIO
,MSGL_DBG2
,"\n[decoded: %d / %d ]\n",bout
,samples
);
334 vorbis_synthesis_read(&ov
->vd
,bout
); /* tell libvorbis how
338 // if (!samples) break; // why? how?
341 if (len
> 0 && ov
->vi
.channels
>= 5) {
342 reorder_channel_nch(buf
, AF_CHANNEL_LAYOUT_VORBIS_DEFAULT
,
343 AF_CHANNEL_LAYOUT_MPLAYER_DEFAULT
,
344 ov
->vi
.channels
, len
/ sh
->samplesize
,