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