100l, mixed up ao_data.samplerate and ao_data.bps when calculating sleep time.
[mplayer/glamo.git] / libao2 / ao_mpegpes.c
blob14918d467e56006ee7ca38c61d3093313a093ee0
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <sys/types.h>
5 #include <sys/stat.h>
6 #include <fcntl.h>
7 #include <unistd.h>
8 #include <inttypes.h>
9 #include <errno.h>
11 #include "config.h"
13 #ifdef CONFIG_DVB
14 #include <poll.h>
15 #include <sys/ioctl.h>
16 #endif
18 #include "audio_out.h"
19 #include "audio_out_internal.h"
21 #include "libaf/af_format.h"
22 #include "libmpdemux/mpeg_packetizer.h"
23 #include "subopt-helper.h"
25 #include "mp_msg.h"
26 #include "help_mp.h"
28 #ifdef CONFIG_DVB
29 #ifndef CONFIG_DVB_HEAD
30 #include <ost/audio.h>
31 audioMixer_t dvb_mixer={255,255};
32 #else
33 #include <linux/dvb/audio.h>
34 audio_mixer_t dvb_mixer={255,255};
35 #endif
36 #endif
38 #define true 1
39 #define false 0
41 extern int vo_mpegpes_fd;
42 int vo_mpegpes_fd2 = -1;
44 #include <errno.h>
46 static ao_info_t info =
48 #ifdef CONFIG_DVB
49 "DVB audio output",
50 #else
51 "MPEG-PES audio output",
52 #endif
53 "mpegpes",
54 "A'rpi",
58 LIBAO_EXTERN(mpegpes)
61 // to set/get/query special features/parameters
62 static int control(int cmd,void *arg){
63 #ifdef CONFIG_DVB
64 switch(cmd){
65 case AOCONTROL_GET_VOLUME:
66 if(vo_mpegpes_fd2>=0){
67 ((ao_control_vol_t*)(arg))->left=dvb_mixer.volume_left/2.56;
68 ((ao_control_vol_t*)(arg))->right=dvb_mixer.volume_right/2.56;
69 return CONTROL_OK;
71 return CONTROL_ERROR;
72 case AOCONTROL_SET_VOLUME:
73 if(vo_mpegpes_fd2>=0){
74 dvb_mixer.volume_left=((ao_control_vol_t*)(arg))->left*2.56;
75 dvb_mixer.volume_right=((ao_control_vol_t*)(arg))->right*2.56;
76 if(dvb_mixer.volume_left>255) dvb_mixer.volume_left=255;
77 if(dvb_mixer.volume_right>255) dvb_mixer.volume_right=255;
78 // printf("Setting DVB volume: %d ; %d \n",dvb_mixer.volume_left,dvb_mixer.volume_right);
79 if ( (ioctl(vo_mpegpes_fd2,AUDIO_SET_MIXER, &dvb_mixer) < 0)){
80 mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_MPEGPES_CantSetMixer,
81 strerror(errno));
82 return CONTROL_ERROR;
84 return CONTROL_OK;
86 return CONTROL_ERROR;
88 #endif
89 return CONTROL_UNKNOWN;
92 static int freq=0;
93 static int freq_id=0;
95 #ifdef CONFIG_DVB
96 static int init_device(int card)
98 char ao_file[30];
99 #ifndef CONFIG_DVB_HEAD
100 mp_msg(MSGT_VO,MSGL_INFO, "Opening /dev/ost/audio\n");
101 sprintf(ao_file, "/dev/ost/audio");
102 #else
103 mp_msg(MSGT_VO,MSGL_INFO, "Opening /dev/dvb/adapter%d/audio0\n", card);
104 sprintf(ao_file, "/dev/dvb/adapter%d/audio0", card);
105 #endif
106 if((vo_mpegpes_fd2 = open(ao_file,O_RDWR|O_NONBLOCK)) < 0)
108 mp_msg(MSGT_VO, MSGL_ERR, "DVB AUDIO DEVICE: %s\n", strerror(errno));
109 return -1;
111 if( (ioctl(vo_mpegpes_fd2,AUDIO_SELECT_SOURCE, AUDIO_SOURCE_MEMORY) < 0))
113 mp_msg(MSGT_VO, MSGL_ERR, "DVB AUDIO SELECT SOURCE: %s\n", strerror(errno));
114 return -1;
116 if((ioctl(vo_mpegpes_fd2,AUDIO_PLAY) < 0))
118 mp_msg(MSGT_VO, MSGL_ERR, "DVB AUDIO PLAY: %s\n", strerror(errno));
119 return -1;
121 if((ioctl(vo_mpegpes_fd2,AUDIO_SET_AV_SYNC, true) < 0))
123 mp_msg(MSGT_VO, MSGL_ERR, "DVB AUDIO SET AV SYNC: %s\n", strerror(errno));
124 return -1;
126 //FIXME: in vo_mpegpes audio was initialized as MUTEd
127 if((ioctl(vo_mpegpes_fd2,AUDIO_SET_MUTE, false) < 0))
129 mp_msg(MSGT_VO, MSGL_ERR, "DVB AUDIO SET MUTE: %s\n", strerror(errno));
130 return -1;
132 return vo_mpegpes_fd2;
134 #endif
136 static int preinit(const char *arg)
138 int card = -1;
139 char *ao_file = NULL;
141 opt_t subopts[] = {
142 {"card", OPT_ARG_INT, &card, NULL},
143 {"file", OPT_ARG_MSTRZ, &ao_file, NULL},
144 {NULL}
147 if(subopt_parse(ao_subdevice, subopts) != 0)
149 mp_msg(MSGT_VO, MSGL_ERR, "AO_MPEGPES, Unrecognized options\n");
150 return -1;
152 if(card==-1)
154 //search the first usable card
155 int n;
156 char file[30];
157 for(n=0; n<4; n++)
159 sprintf(file, "/dev/dvb/adapter%d/audio0", n);
160 if(access(file, F_OK | W_OK)==0)
162 card = n+1;
163 break;
167 if((card < 1) || (card > 4))
169 mp_msg(MSGT_VO, MSGL_ERR, "DVB card number must be between 1 and 4\n");
170 return -1;
172 card--;
174 #ifdef CONFIG_DVB
175 if(!ao_file)
176 return init_device(card);
177 #else
178 if(!ao_file)
179 return vo_mpegpes_fd; //video fd
180 #endif
182 vo_mpegpes_fd2=open(ao_file,O_WRONLY|O_CREAT,0666);
183 if(vo_mpegpes_fd2<0)
185 mp_msg(MSGT_VO, MSGL_ERR, "ao_mpegpes: %s\n", strerror(errno));
186 return -1;
188 return vo_mpegpes_fd2;
191 static int my_ao_write(unsigned char* data,int len){
192 int orig_len = len;
193 #ifdef CONFIG_DVB
194 #define NFD 1
195 struct pollfd pfd[NFD];
197 pfd[0].fd = vo_mpegpes_fd2;
198 pfd[0].events = POLLOUT;
200 while(len>0){
201 if(poll(pfd,NFD,1)){
202 if(pfd[0].revents & POLLOUT){
203 int ret=write(vo_mpegpes_fd2,data,len);
204 if(ret<=0){
205 mp_msg(MSGT_VO, MSGL_ERR, "ao_mpegpes write: %s\n", strerror(errno));
206 usleep(0);
207 } else {
208 len-=ret;
209 data+=ret;
211 } else usleep(1000);
215 #else
216 if(vo_mpegpes_fd2<0) return 0; // no file
217 write(vo_mpegpes_fd2,data,len); // write to file
218 #endif
219 return orig_len;
223 // open & setup audio device
224 // return: 1=success 0=fail
225 static int init(int rate,int channels,int format,int flags){
226 if(preinit(NULL)<0) return 0;
228 ao_data.channels=2;
229 ao_data.outburst=2000;
230 switch(format){
231 case AF_FORMAT_S16_BE:
232 case AF_FORMAT_MPEG2:
233 case AF_FORMAT_AC3:
234 ao_data.format=format;
235 break;
236 default:
237 ao_data.format=AF_FORMAT_S16_BE;
240 switch(rate){
241 case 48000: freq_id=0;break;
242 case 96000: freq_id=1;break;
243 case 44100: freq_id=2;break;
244 case 32000: freq_id=3;break;
245 default:
246 mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_MPEGPES_UnsupSamplerate, rate);
247 #if 0
248 if(rate>48000) rate=96000; else
249 if(rate>44100) rate=48000; else
250 if(rate>32000) rate=44100; else
251 rate=32000;
252 goto retry;
253 #else
254 rate=48000; freq_id=0;
255 #endif
258 ao_data.bps=rate*2*2;
259 freq=ao_data.samplerate=rate;
261 return 1;
264 // close audio device
265 static void uninit(int immed){
269 // stop playing and empty buffers (for seeking/pause)
270 static void reset(void){
274 // stop playing, keep buffers (for pause)
275 static void audio_pause(void)
277 // for now, just call reset();
278 reset();
281 // resume playing, after audio_pause()
282 static void audio_resume(void)
286 void send_pes_packet(unsigned char* data,int len,int id,int timestamp);
287 void send_lpcm_packet(unsigned char* data,int len,int id,int timestamp,int freq_id);
288 extern int vo_pts;
290 // return: how many bytes can be played without blocking
291 static int get_space(void){
292 float x=(float)(vo_pts-ao_data.pts)/90000.0;
293 int y;
294 //FIXME: is it correct?
295 if(vo_mpegpes_fd < 0) return 32000; //not using -vo mpegpes
296 // printf("vo_pts: %5.3f ao_pts: %5.3f\n",vo_pts/90000.0,ao_data.pts/90000.0);
297 if(x<=0) return 0;
298 y=freq*4*x;y/=ao_data.outburst;y*=ao_data.outburst;
299 if(y>32000) y=32000;
300 // printf("diff: %5.3f -> %d \n",x,y);
301 return y;
304 // plays 'len' bytes of 'data'
305 // it should round it down to outburst*n
306 // return: number of bytes played
307 static int play(void* data,int len,int flags){
308 // printf("\nao_mpegpes: play(%d) freq=%d\n",len,freq_id);
309 if(ao_data.format==AF_FORMAT_MPEG2)
310 send_mpeg_pes_packet (data, len, 0x1C0, ao_data.pts, 1, my_ao_write);
311 else {
312 int i;
313 unsigned short *s=data;
314 // if(len>2000) len=2000;
315 // printf("ao_mpegpes: len=%d \n",len);
316 if(ao_data.format==AF_FORMAT_AC3)
317 for(i=0;i<len/2;i++) s[i]=(s[i]>>8)|(s[i]<<8); // le<->be
318 send_mpeg_lpcm_packet(data, len, 0xA0, ao_data.pts, freq_id, my_ao_write);
320 return len;
323 // return: delay in seconds between first and last sample in buffer
324 static float get_delay(void){
326 return 0.0;