Mercurial > mplayer.hg
comparison libao2/ao_mpegpes.c @ 19184:3f2de7ba8aa0
split the incestous intercourse between ao_mpegpes and vo_mpegpes; now the devices can be used separately
author | nicodvb |
---|---|
date | Wed, 26 Jul 2006 21:40:43 +0000 |
parents | f580a7755ac5 |
children | 64264df4c4e1 |
comparison
equal
deleted
inserted
replaced
19183:942000d171f4 | 19184:3f2de7ba8aa0 |
---|---|
1 #include <stdio.h> | 1 #include <stdio.h> |
2 #include <stdlib.h> | 2 #include <stdlib.h> |
3 #include <string.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 <sys/poll.h> | |
4 | 10 |
5 #include "config.h" | 11 #include "config.h" |
6 | 12 |
7 #ifdef HAVE_DVB_HEAD | 13 #ifdef HAVE_DVB_HEAD |
8 #define HAVE_DVB 1 | 14 #define HAVE_DVB 1 |
14 | 20 |
15 #include "audio_out.h" | 21 #include "audio_out.h" |
16 #include "audio_out_internal.h" | 22 #include "audio_out_internal.h" |
17 | 23 |
18 #include "libaf/af_format.h" | 24 #include "libaf/af_format.h" |
25 #include "libmpdemux/mpeg_packetizer.h" | |
26 #include "subopt-helper.h" | |
19 | 27 |
20 #include "mp_msg.h" | 28 #include "mp_msg.h" |
21 #include "help_mp.h" | 29 #include "help_mp.h" |
22 | 30 |
23 #ifdef HAVE_DVB | 31 #ifdef HAVE_DVB |
27 #else | 35 #else |
28 #include <linux/dvb/audio.h> | 36 #include <linux/dvb/audio.h> |
29 audio_mixer_t dvb_mixer={255,255}; | 37 audio_mixer_t dvb_mixer={255,255}; |
30 #endif | 38 #endif |
31 #endif | 39 #endif |
40 | |
41 #define true 1 | |
42 #define false 0 | |
43 | |
32 extern int vo_mpegpes_fd; | 44 extern int vo_mpegpes_fd; |
33 extern int vo_mpegpes_fd2; | 45 int vo_mpegpes_fd2 = -1; |
34 | 46 |
35 #include <errno.h> | 47 #include <errno.h> |
36 | 48 |
37 static ao_info_t info = | 49 static ao_info_t info = |
38 { | 50 { |
81 } | 93 } |
82 | 94 |
83 static int freq=0; | 95 static int freq=0; |
84 static int freq_id=0; | 96 static int freq_id=0; |
85 | 97 |
98 #ifdef HAVE_DVB | |
99 static int init_device(int card) | |
100 { | |
101 char ao_file[30]; | |
102 #ifndef HAVE_DVB_HEAD | |
103 mp_msg(MSGT_VO,MSGL_INFO, "Opening /dev/ost/audio\n"); | |
104 sprintf(ao_file, "/dev/ost/audio"); | |
105 #else | |
106 mp_msg(MSGT_VO,MSGL_INFO, "Opening /dev/dvb/adapter%d/audio0\n", card); | |
107 sprintf(ao_file, "/dev/dvb/adapter%d/audio0", card); | |
108 #endif | |
109 if((vo_mpegpes_fd2 = open(ao_file,O_RDWR|O_NONBLOCK)) < 0) | |
110 { | |
111 perror("DVB AUDIO DEVICE: "); | |
112 return -1; | |
113 } | |
114 if( (ioctl(vo_mpegpes_fd2,AUDIO_SELECT_SOURCE, AUDIO_SOURCE_MEMORY) < 0)) | |
115 { | |
116 perror("DVB AUDIO SELECT SOURCE: "); | |
117 return -1; | |
118 } | |
119 if((ioctl(vo_mpegpes_fd2,AUDIO_PLAY) < 0)) | |
120 { | |
121 perror("DVB AUDIO PLAY: "); | |
122 return -1; | |
123 } | |
124 if((ioctl(vo_mpegpes_fd2,AUDIO_SET_AV_SYNC, true) < 0)) | |
125 { | |
126 perror("DVB AUDIO SET AV SYNC: "); | |
127 return -1; | |
128 } | |
129 //FIXME: in vo_mpegpes audio was inited as MUTEd | |
130 if((ioctl(vo_mpegpes_fd2,AUDIO_SET_MUTE, false) < 0)) | |
131 { | |
132 perror("DVB AUDIO SET MUTE: "); | |
133 return -1; | |
134 } | |
135 return vo_mpegpes_fd2; | |
136 } | |
137 #endif | |
138 | |
139 static int preinit(const char *arg) | |
140 { | |
141 int card = 1; | |
142 char *ao_file = NULL; | |
143 | |
144 opt_t subopts[] = { | |
145 {"card", OPT_ARG_INT, &card, NULL}, | |
146 {"file", OPT_ARG_MSTRZ, &ao_file, NULL}, | |
147 {NULL} | |
148 }; | |
149 | |
150 if(subopt_parse(ao_subdevice, subopts) != 0) | |
151 { | |
152 mp_msg(MSGT_VO, MSGL_ERR, "AO_MPEGPES, Unrecognized options\n"); | |
153 return -1; | |
154 } | |
155 if((card < 1) || (card > 4)) | |
156 { | |
157 mp_msg(MSGT_VO, MSGL_ERR, "DVB card number must be between 1 and 4\n"); | |
158 return -1; | |
159 } | |
160 card--; | |
161 | |
162 #ifdef HAVE_DVB | |
163 if(!ao_file) | |
164 return init_device(card); | |
165 #else | |
166 if(!ao_file) | |
167 { | |
168 if(vo_mpegpes_fd >= 0) | |
169 { | |
170 vo_mpegpes_fd2 = vo_mpegpes_fd; | |
171 return vo_mpegpes_fd2; //video fd | |
172 } | |
173 else | |
174 ao_file = "audiograb.mpg"; | |
175 } | |
176 #endif | |
177 | |
178 vo_mpegpes_fd2=open(ao_file,O_WRONLY|O_CREAT,0666); | |
179 if(vo_mpegpes_fd2<0) | |
180 { | |
181 perror("ao_mpegpes"); | |
182 return -1; | |
183 } | |
184 return vo_mpegpes_fd2; | |
185 } | |
186 | |
187 static int my_ao_write(unsigned char* data,int len){ | |
188 int orig_len = len; | |
189 #ifdef HAVE_DVB | |
190 #define NFD 1 | |
191 struct pollfd pfd[NFD]; | |
192 | |
193 pfd[0].fd = vo_mpegpes_fd2; | |
194 pfd[0].events = POLLOUT; | |
195 | |
196 while(len>0){ | |
197 if(poll(pfd,NFD,1)){ | |
198 if(pfd[0].revents & POLLOUT){ | |
199 int ret=write(vo_mpegpes_fd2,data,len); | |
200 if(ret<=0){ | |
201 perror("write"); | |
202 usleep(0); | |
203 } else { | |
204 len-=ret; | |
205 data+=ret; | |
206 } | |
207 } else usleep(1000); | |
208 } | |
209 } | |
210 | |
211 #else | |
212 if(vo_mpegpes_fd2<0) return 0; // no file | |
213 write(vo_mpegpes_fd2,data,len); // write to file | |
214 #endif | |
215 return orig_len; | |
216 } | |
217 | |
218 | |
86 // open & setup audio device | 219 // open & setup audio device |
87 // return: 1=success 0=fail | 220 // return: 1=success 0=fail |
88 static int init(int rate,int channels,int format,int flags){ | 221 static int init(int rate,int channels,int format,int flags){ |
89 | 222 if(preinit(NULL)<0) return 0; |
90 #ifdef HAVE_DVB | |
91 if(vo_mpegpes_fd2<0) return 0; // couldn't open audio dev | |
92 #else | |
93 if(vo_mpegpes_fd<0) return 0; // no file | |
94 #endif | |
95 | 223 |
96 ao_data.channels=2; | 224 ao_data.channels=2; |
97 ao_data.outburst=2000; | 225 ao_data.outburst=2000; |
98 switch(format){ | 226 switch(format){ |
99 case AF_FORMAT_S16_LE: | 227 case AF_FORMAT_S16_LE: |
159 | 287 |
160 // return: how many bytes can be played without blocking | 288 // return: how many bytes can be played without blocking |
161 static int get_space(void){ | 289 static int get_space(void){ |
162 float x=(float)(vo_pts-ao_data.pts)/90000.0; | 290 float x=(float)(vo_pts-ao_data.pts)/90000.0; |
163 int y; | 291 int y; |
292 //FIXME: is it correct? | |
293 if(vo_mpegpes_fd < 0) return 32000; //not using -vo mpegpes | |
164 // printf("vo_pts: %5.3f ao_pts: %5.3f\n",vo_pts/90000.0,ao_data.pts/90000.0); | 294 // printf("vo_pts: %5.3f ao_pts: %5.3f\n",vo_pts/90000.0,ao_data.pts/90000.0); |
165 if(x<=0) return 0; | 295 if(x<=0) return 0; |
166 y=freq*4*x;y/=ao_data.outburst;y*=ao_data.outburst; | 296 y=freq*4*x;y/=ao_data.outburst;y*=ao_data.outburst; |
167 if(y>32000) y=32000; | 297 if(y>32000) y=32000; |
168 // printf("diff: %5.3f -> %d \n",x,y); | 298 // printf("diff: %5.3f -> %d \n",x,y); |
173 // it should round it down to outburst*n | 303 // it should round it down to outburst*n |
174 // return: number of bytes played | 304 // return: number of bytes played |
175 static int play(void* data,int len,int flags){ | 305 static int play(void* data,int len,int flags){ |
176 // printf("\nao_mpegpes: play(%d) freq=%d\n",len,freq_id); | 306 // printf("\nao_mpegpes: play(%d) freq=%d\n",len,freq_id); |
177 if(ao_data.format==AF_FORMAT_MPEG2) | 307 if(ao_data.format==AF_FORMAT_MPEG2) |
178 send_pes_packet(data,len,0x1C0,ao_data.pts); | 308 send_mpeg_pes_packet (data, len, 0x1C0, ao_data.pts, 1, my_ao_write); |
179 else { | 309 else { |
180 int i; | 310 int i; |
181 unsigned short *s=data; | 311 unsigned short *s=data; |
182 // if(len>2000) len=2000; | 312 // if(len>2000) len=2000; |
183 // printf("ao_mpegpes: len=%d \n",len); | 313 // printf("ao_mpegpes: len=%d \n",len); |
184 if(ao_data.format==AF_FORMAT_S16_LE || ao_data.format==AF_FORMAT_AC3) | 314 if(ao_data.format==AF_FORMAT_S16_LE || ao_data.format==AF_FORMAT_AC3) |
185 for(i=0;i<len/2;i++) s[i]=(s[i]>>8)|(s[i]<<8); // le<->be | 315 for(i=0;i<len/2;i++) s[i]=(s[i]>>8)|(s[i]<<8); // le<->be |
186 send_lpcm_packet(data,len,0xA0,ao_data.pts,freq_id); | 316 send_mpeg_lpcm_packet(data, len, 0xA0, ao_data.pts, freq_id, my_ao_write); |
187 } | 317 } |
188 return len; | 318 return len; |
189 } | 319 } |
190 | 320 |
191 // return: delay in seconds between first and last sample in buffer | 321 // return: delay in seconds between first and last sample in buffer |