6074
|
1 #include <math.h>
|
6069
|
2 #include <stdio.h>
|
|
3 #include <stdlib.h>
|
|
4 #include <sys/ioctl.h>
|
|
5 #include <inttypes.h>
|
6074
|
6 #include <dxr2ioctl.h>
|
14123
|
7 #include "config.h"
|
|
8 #include "mp_msg.h"
|
|
9 #include "help_mp.h"
|
21372
|
10 #include "libavutil/common.h"
|
21507
|
11 #include "mpbswap.h"
|
6069
|
12
|
|
13 #include "audio_out.h"
|
|
14 #include "audio_out_internal.h"
|
14245
|
15 #include "libaf/af_format.h"
|
19151
|
16 #include "libmpdemux/mpeg_packetizer.h"
|
6069
|
17
|
|
18
|
|
19 static ao_info_t info =
|
|
20 {
|
|
21 "DXR2 audio output",
|
|
22 "dxr2",
|
15755
|
23 "Tobias Diedrich <ranma+mplayer@tdiedrich.de>",
|
6069
|
24 ""
|
|
25 };
|
|
26
|
|
27 LIBAO_EXTERN(dxr2)
|
|
28
|
6074
|
29 static int volume=19;
|
19164
|
30 static int last_freq_id = -1;
|
6074
|
31 extern int dxr2_fd;
|
|
32
|
6069
|
33 // to set/get/query special features/parameters
|
9633
|
34 static int control(int cmd,void *arg){
|
6074
|
35 switch(cmd){
|
|
36 case AOCONTROL_GET_VOLUME:
|
|
37 if(dxr2_fd > 0) {
|
|
38 ao_control_vol_t* vol = (ao_control_vol_t*)arg;
|
|
39 vol->left = vol->right = volume * 19.0 / 100.0;
|
|
40 return CONTROL_OK;
|
|
41 }
|
|
42 return CONTROL_ERROR;
|
|
43 case AOCONTROL_SET_VOLUME:
|
|
44 if(dxr2_fd > 0) {
|
|
45 dxr2_oneArg_t v;
|
|
46 float diff;
|
|
47 ao_control_vol_t* vol = (ao_control_vol_t*)arg;
|
|
48 // We need this trick because the volume stepping is often too small
|
|
49 diff = ((vol->left+vol->right) / 2 - (volume*19.0/100.0)) * 19.0 / 100.0;
|
|
50 v.arg = volume + (diff > 0 ? ceil(diff) : floor(diff));
|
|
51 if(v.arg > 19) v.arg = 19;
|
|
52 if(v.arg < 0) v.arg = 0;
|
|
53 if(v.arg != volume) {
|
|
54 volume = v.arg;
|
|
55 if( ioctl(dxr2_fd,DXR2_IOC_SET_AUDIO_VOLUME,&v) < 0) {
|
13383
|
56 mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_DXR2_SetVolFailed,volume);
|
6074
|
57 return CONTROL_ERROR;
|
|
58 }
|
|
59 }
|
|
60 return CONTROL_OK;
|
|
61 }
|
|
62 return CONTROL_ERROR;
|
|
63 }
|
6069
|
64 return CONTROL_UNKNOWN;
|
|
65 }
|
|
66
|
|
67 static int freq=0;
|
|
68 static int freq_id=0;
|
|
69
|
|
70 // open & setup audio device
|
|
71 // return: 1=success 0=fail
|
|
72 static int init(int rate,int channels,int format,int flags){
|
|
73
|
6111
|
74 if(dxr2_fd <= 0)
|
|
75 return 0;
|
|
76
|
19164
|
77 last_freq_id = -1;
|
|
78
|
6069
|
79 ao_data.outburst=2048;
|
|
80 ao_data.samplerate=rate;
|
|
81 ao_data.channels=channels;
|
|
82 ao_data.buffersize=2048;
|
|
83 ao_data.bps=rate*4;
|
|
84 ao_data.format=format;
|
|
85 freq=rate;
|
|
86
|
|
87 switch(rate){
|
|
88 case 48000:
|
6074
|
89 freq_id=DXR2_AUDIO_FREQ_48;
|
6069
|
90 break;
|
|
91 case 96000:
|
6074
|
92 freq_id=DXR2_AUDIO_FREQ_96;
|
6069
|
93 break;
|
|
94 case 44100:
|
6074
|
95 freq_id=DXR2_AUDIO_FREQ_441;
|
6069
|
96 break;
|
|
97 case 32000:
|
6074
|
98 freq_id=DXR2_AUDIO_FREQ_32;
|
6069
|
99 break;
|
|
100 case 22050:
|
6074
|
101 freq_id=DXR2_AUDIO_FREQ_2205;
|
6069
|
102 break;
|
6074
|
103 #ifdef DXR2_AUDIO_FREQ_24
|
|
104 // This is not yet in the dxr2 driver CVS
|
|
105 // you can get the patch at
|
17064
|
106 // http://www.tdiedrich.de/~ranma/patches/dxr2.pcm1723.20020513
|
6069
|
107 case 24000:
|
6074
|
108 freq_id=DXR2_AUDIO_FREQ_24;
|
6069
|
109 break;
|
|
110 case 64000:
|
6074
|
111 freq_id=DXR2_AUDIO_FREQ_64;
|
6069
|
112 break;
|
|
113 case 88200:
|
6074
|
114 freq_id=DXR2_AUDIO_FREQ_882;
|
6069
|
115 break;
|
|
116 #endif
|
|
117 default:
|
13383
|
118 mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_DXR2_UnsupSamplerate,rate);
|
6069
|
119 return 0;
|
|
120 }
|
|
121
|
|
122 return 1;
|
|
123 }
|
|
124
|
|
125 // close audio device
|
12145
|
126 static void uninit(int immed){
|
6069
|
127
|
|
128 }
|
|
129
|
|
130 // stop playing and empty buffers (for seeking/pause)
|
18915
|
131 static void reset(void){
|
6069
|
132
|
|
133 }
|
|
134
|
|
135 // stop playing, keep buffers (for pause)
|
18915
|
136 static void audio_pause(void)
|
6069
|
137 {
|
|
138 // for now, just call reset();
|
|
139 reset();
|
|
140 }
|
|
141
|
|
142 // resume playing, after audio_pause()
|
18915
|
143 static void audio_resume(void)
|
6069
|
144 {
|
|
145 }
|
|
146
|
|
147 extern int vo_pts;
|
|
148 // return: how many bytes can be played without blocking
|
18915
|
149 static int get_space(void){
|
6069
|
150 float x=(float)(vo_pts-ao_data.pts)/90000.0;
|
|
151 int y;
|
|
152 if(x<=0) return 0;
|
|
153 y=freq*4*x;y/=ao_data.outburst;y*=ao_data.outburst;
|
|
154 if(y>32768) y=32768;
|
|
155 return y;
|
|
156 }
|
|
157
|
19164
|
158 static void dxr2_send_lpcm_packet(unsigned char* data,int len,int id,unsigned int timestamp,int freq_id)
|
|
159 {
|
|
160 extern int write_dxr2(unsigned char *data, int len);
|
|
161
|
|
162 if(dxr2_fd < 0) {
|
|
163 mp_msg(MSGT_AO,MSGL_ERR,"DXR2 fd is not valid\n");
|
|
164 return;
|
|
165 }
|
|
166
|
|
167 if(last_freq_id != freq_id) {
|
|
168 ioctl(dxr2_fd, DXR2_IOC_SET_AUDIO_SAMPLE_FREQUENCY, &freq_id);
|
|
169 last_freq_id = freq_id;
|
|
170 }
|
|
171
|
|
172 send_mpeg_lpcm_packet (data, len, id, timestamp, freq_id, write_dxr2);
|
|
173 }
|
|
174
|
6069
|
175 // plays 'len' bytes of 'data'
|
|
176 // it should round it down to outburst*n
|
|
177 // return: number of bytes played
|
|
178 static int play(void* data,int len,int flags){
|
19151
|
179 extern int write_dxr2(unsigned char *data, int len);
|
|
180
|
6069
|
181 // MPEG and AC3 don't work :-(
|
14245
|
182 if(ao_data.format==AF_FORMAT_MPEG2)
|
19151
|
183 send_mpeg_ps_packet (data, len, 0xC0, ao_data.pts, 2, write_dxr2);
|
14245
|
184 else if(ao_data.format==AF_FORMAT_AC3)
|
19151
|
185 send_mpeg_ps_packet (data, len, 0x80, ao_data.pts, 2, write_dxr2);
|
6069
|
186 else {
|
|
187 int i;
|
|
188 //unsigned short *s=data;
|
|
189 uint16_t *s=data;
|
|
190 #ifndef WORDS_BIGENDIAN
|
6074
|
191 for(i=0;i<len/2;i++) s[i] = bswap_16(s[i]);
|
6069
|
192 #endif
|
|
193 dxr2_send_lpcm_packet(data,len,0xA0,ao_data.pts-10000,freq_id);
|
|
194 }
|
|
195 return len;
|
|
196 }
|
|
197
|
|
198 // return: delay in seconds between first and last sample in buffer
|
18915
|
199 static float get_delay(void){
|
6069
|
200
|
|
201 return 0.0;
|
|
202 }
|
|
203
|