Mercurial > mplayer.hg
comparison stream/ai_alsa1x.c @ 19271:64d82a45a05d
introduce new 'stream' directory for all stream layer related components and split them from libmpdemux
author | ben |
---|---|
date | Mon, 31 Jul 2006 17:39:17 +0000 |
parents | libmpdemux/ai_alsa1x.c@d2d9d011203f |
children | 8fe8b0d9deec |
comparison
equal
deleted
inserted
replaced
19270:7d39b911f0bd | 19271:64d82a45a05d |
---|---|
1 #include <stdio.h> | |
2 #include <stdlib.h> | |
3 #include <sys/time.h> | |
4 | |
5 #include "config.h" | |
6 | |
7 #include <alsa/asoundlib.h> | |
8 #include "audio_in.h" | |
9 #include "mp_msg.h" | |
10 #include "help_mp.h" | |
11 | |
12 int ai_alsa_setup(audio_in_t *ai) | |
13 { | |
14 snd_pcm_hw_params_t *params; | |
15 snd_pcm_sw_params_t *swparams; | |
16 snd_pcm_uframes_t buffer_size, period_size; | |
17 int err; | |
18 int dir; | |
19 unsigned int rate; | |
20 | |
21 snd_pcm_hw_params_alloca(¶ms); | |
22 snd_pcm_sw_params_alloca(&swparams); | |
23 | |
24 err = snd_pcm_hw_params_any(ai->alsa.handle, params); | |
25 if (err < 0) { | |
26 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_PcmBrokenConfig); | |
27 return -1; | |
28 } | |
29 | |
30 err = snd_pcm_hw_params_set_access(ai->alsa.handle, params, | |
31 SND_PCM_ACCESS_RW_INTERLEAVED); | |
32 if (err < 0) { | |
33 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_UnavailableAccessType); | |
34 return -1; | |
35 } | |
36 | |
37 err = snd_pcm_hw_params_set_format(ai->alsa.handle, params, SND_PCM_FORMAT_S16_LE); | |
38 if (err < 0) { | |
39 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_UnavailableSampleFmt); | |
40 return -1; | |
41 } | |
42 | |
43 err = snd_pcm_hw_params_set_channels(ai->alsa.handle, params, ai->req_channels); | |
44 if (err < 0) { | |
45 snd_pcm_hw_params_get_channels(params, &ai->channels); | |
46 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_UnavailableChanCount, | |
47 ai->channels); | |
48 } else { | |
49 ai->channels = ai->req_channels; | |
50 } | |
51 | |
52 dir = 0; | |
53 rate = ai->req_samplerate; | |
54 err = snd_pcm_hw_params_set_rate_near(ai->alsa.handle, params, &rate, &dir); | |
55 if (err < 0) { | |
56 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA1X_CannotSetSamplerate); | |
57 } | |
58 ai->samplerate = rate; | |
59 | |
60 dir = 0; | |
61 ai->alsa.buffer_time = 1000000; | |
62 err = snd_pcm_hw_params_set_buffer_time_near(ai->alsa.handle, params, | |
63 &ai->alsa.buffer_time, &dir); | |
64 if (err < 0) { | |
65 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA1X_CannotSetBufferTime); | |
66 } | |
67 | |
68 dir = 0; | |
69 ai->alsa.period_time = ai->alsa.buffer_time / 4; | |
70 err = snd_pcm_hw_params_set_period_time_near(ai->alsa.handle, params, | |
71 &ai->alsa.period_time, &dir); | |
72 if (err < 0) { | |
73 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA1X_CannotSetPeriodTime); | |
74 } | |
75 | |
76 err = snd_pcm_hw_params(ai->alsa.handle, params); | |
77 if (err < 0) { | |
78 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_CannotInstallHWParams, snd_strerror(err)); | |
79 snd_pcm_hw_params_dump(params, ai->alsa.log); | |
80 return -1; | |
81 } | |
82 | |
83 dir = -1; | |
84 snd_pcm_hw_params_get_period_size(params, &period_size, &dir); | |
85 snd_pcm_hw_params_get_buffer_size(params, &buffer_size); | |
86 ai->alsa.chunk_size = period_size; | |
87 if (period_size == buffer_size) { | |
88 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_PeriodEqualsBufferSize, ai->alsa.chunk_size, (long)buffer_size); | |
89 return -1; | |
90 } | |
91 | |
92 snd_pcm_sw_params_current(ai->alsa.handle, swparams); | |
93 err = snd_pcm_sw_params_set_sleep_min(ai->alsa.handle, swparams,0); | |
94 assert(err >= 0); | |
95 err = snd_pcm_sw_params_set_avail_min(ai->alsa.handle, swparams, ai->alsa.chunk_size); | |
96 assert(err >= 0); | |
97 | |
98 err = snd_pcm_sw_params_set_start_threshold(ai->alsa.handle, swparams, 0); | |
99 assert(err >= 0); | |
100 err = snd_pcm_sw_params_set_stop_threshold(ai->alsa.handle, swparams, buffer_size); | |
101 assert(err >= 0); | |
102 | |
103 assert(err >= 0); | |
104 if (snd_pcm_sw_params(ai->alsa.handle, swparams) < 0) { | |
105 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_CannotInstallSWParams); | |
106 snd_pcm_sw_params_dump(swparams, ai->alsa.log); | |
107 return -1; | |
108 } | |
109 | |
110 if (mp_msg_test(MSGT_TV, MSGL_V)) { | |
111 snd_pcm_dump(ai->alsa.handle, ai->alsa.log); | |
112 } | |
113 | |
114 ai->alsa.bits_per_sample = snd_pcm_format_physical_width(SND_PCM_FORMAT_S16_LE); | |
115 ai->alsa.bits_per_frame = ai->alsa.bits_per_sample * ai->channels; | |
116 ai->blocksize = ai->alsa.chunk_size * ai->alsa.bits_per_frame / 8; | |
117 ai->samplesize = ai->alsa.bits_per_sample; | |
118 ai->bytes_per_sample = ai->alsa.bits_per_sample/8; | |
119 | |
120 return 0; | |
121 } | |
122 | |
123 int ai_alsa_init(audio_in_t *ai) | |
124 { | |
125 int err; | |
126 | |
127 err = snd_pcm_open(&ai->alsa.handle, ai->alsa.device, SND_PCM_STREAM_CAPTURE, 0); | |
128 if (err < 0) { | |
129 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_ErrorOpeningAudio, snd_strerror(err)); | |
130 return -1; | |
131 } | |
132 | |
133 err = snd_output_stdio_attach(&ai->alsa.log, stderr, 0); | |
134 | |
135 if (err < 0) { | |
136 return -1; | |
137 } | |
138 | |
139 err = ai_alsa_setup(ai); | |
140 | |
141 return err; | |
142 } | |
143 | |
144 #ifndef timersub | |
145 #define timersub(a, b, result) \ | |
146 do { \ | |
147 (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \ | |
148 (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \ | |
149 if ((result)->tv_usec < 0) { \ | |
150 --(result)->tv_sec; \ | |
151 (result)->tv_usec += 1000000; \ | |
152 } \ | |
153 } while (0) | |
154 #endif | |
155 | |
156 int ai_alsa_xrun(audio_in_t *ai) | |
157 { | |
158 snd_pcm_status_t *status; | |
159 int res; | |
160 | |
161 snd_pcm_status_alloca(&status); | |
162 if ((res = snd_pcm_status(ai->alsa.handle, status))<0) { | |
163 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_AlsaStatusError, snd_strerror(res)); | |
164 return -1; | |
165 } | |
166 if (snd_pcm_status_get_state(status) == SND_PCM_STATE_XRUN) { | |
167 struct timeval now, diff, tstamp; | |
168 gettimeofday(&now, 0); | |
169 snd_pcm_status_get_trigger_tstamp(status, &tstamp); | |
170 timersub(&now, &tstamp, &diff); | |
171 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_AlsaXRUN, | |
172 diff.tv_sec * 1000 + diff.tv_usec / 1000.0); | |
173 if (mp_msg_test(MSGT_TV, MSGL_V)) { | |
174 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_AlsaStatus); | |
175 snd_pcm_status_dump(status, ai->alsa.log); | |
176 } | |
177 if ((res = snd_pcm_prepare(ai->alsa.handle))<0) { | |
178 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_AlsaXRUNPrepareError, snd_strerror(res)); | |
179 return -1; | |
180 } | |
181 return 0; /* ok, data should be accepted again */ | |
182 } | |
183 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_AlsaReadWriteError); | |
184 return -1; | |
185 } |