npv: media pipeline
[nyanmp.git] / npv / audio / public / code.frag.c
blob370e80f52fef0ce7c71967197a9173b84315f2be
1 static void dec_ctx_cfg(avcodec_params_t *params)
3 int r;
5 dec_l = avcodec_find_dec(params->codec_id);
6 if (dec_l == 0)
7 FATALA("ffmpeg:unable to find a proper decoder\n");
8 avcodec_free_context(&dec_ctx_p);
9 dec_ctx_p = avcodec_alloc_ctx(dec_l);
10 if (dec_ctx_p == 0)
11 FATALA("ffmpeg:unable to allocate a decoder context\n");
12 /* XXX: useless ? */
13 r = avcodec_params_to_ctx(dec_ctx_p, params);
14 if (r < 0)
15 FATALA("ffmpeg:unable to apply stream codec parameters in codec context\n");
16 /* XXX: ffmpeg thread count default is 1, set to 0 = auto */
17 dec_ctx_p->thread_count = 0;
18 r = avcodec_open2(dec_ctx_p, dec_l, 0);
19 if (r < 0)
20 FATALA("ffmpeg:unable to open the decoder context\n");
22 #define AGAIN 0
23 #define HAVE_DEC_SET 1
24 #define EOF_DEC 2
25 static u8 dec_set_try_receive(void)
27 int r;
28 u32 last;
30 if (dec_sets_p.eof_receive)
31 return EOF_DEC;
32 if (dec_sets_p.n == dec_sets_p.n_max)
33 dec_a_grow();
34 last = dec_sets_p.n;
35 /* will unref any previous dec_sets_p.a[x] bufs for us */
36 r = avcodec_receive_audio_set(dec_ctx_p, dec_sets_p.a[last]);
37 if (r == AVUTIL_AVERROR(EAGAIN))
38 return AGAIN;
39 else if (r == 0) {
40 ++dec_sets_p.n;
41 return HAVE_DEC_SET;
42 } else if (r == AVUTIL_AVERROR_EOF) {
43 POUTA("ffmpeg:last decoder set of frames reached (receiving)\n");
44 dec_sets_p.eof_receive = true;
45 return EOF_DEC;
47 FATALA("ffmpeg:error while receiving a set of frames from the decoder\n");
49 #undef AGAIN
50 #undef HAVE_DEC_SET
51 #undef EOF_DEC
52 #define AGAIN 0
53 #define HAVE_DEC_SET 1
54 #define EOF_DEC 2
56 * this can be long and we don't want to lock that long the q of audio frs
57 * for the alsa writer, then do finer-grained locking here
59 static void dec_sets_receive_avail(void) { loop
61 u8 r;
63 dec_ctx_lock();
64 dec_sets_lock();
65 r = dec_set_try_receive();
66 dec_sets_unlock();
67 dec_ctx_unlock();
68 if (r == HAVE_DEC_SET)
69 continue;
70 else if (r == AGAIN || r == EOF_DEC)
71 break;
73 #undef AGAIN
74 #undef HAVE_DEC_SET
75 #undef EOF_DEC
76 static void draining_state_evt(void)
78 int r;
79 uint64_t exps_n;
81 r = read(draining_timer_fd_p, &exps_n, sizeof(exps_n));
82 if (r == -1)
83 FATALA("unable to read the number of draining state timer expirations\n");
84 draining_state_handle();
86 #define AGAIN 0
87 #define RECOVERED 1
88 static void evt_pcm_write(void)
90 snd_pcm_sfrs_t alsa_r;
91 snd_pcm_ufrs_t ufrs_n;
92 u8 r_recover;
94 alsa_r = snd_pcm_avail(pcm_p);
95 r_recover = alsa_recover(alsa_r);
96 if (r_recover == AGAIN || r_recover == RECOVERED)
97 return;
98 /* r_recover == CONTINUE */
99 ufrs_n = (snd_pcm_ufrs_t)alsa_r;
100 if (npv_paused_p)
101 pcm_silence_frs_write(ufrs_n);
102 else
103 pcm_filt_frs_write(ufrs_n);
105 #undef AGAIN
106 #undef RECOVERED
107 static void pcm_silence_bufs_cfg(bool print_info)
109 int r;
110 snd_pcm_hw_params_t *hw_params;
111 snd_pcm_ufrs_t buf_ufrs_n;
112 snd_pcm_fmt_t fmt;
113 snd_pcm_access_t access;
114 unsigned int chans_n;
115 u8 c;
117 r = snd_pcm_hw_params_malloc(&hw_params);
118 if (r < 0)
119 FATALA("silence:alsa:unable to allocate memory for a hardware parameters container\n");
120 r = snd_pcm_hw_params_current(pcm_p, hw_params);
121 if (r != 0)
122 FATALA("silence:alsa:unable to get the pcm hardware parameters\n");
123 r = snd_pcm_hw_params_get_buf_sz(hw_params, &buf_ufrs_n);
124 if (r < 0)
125 FATALA("silence:alsa:unable to get the number of frames in the pcm buffer\n");
126 r = snd_pcm_hw_params_get_format(hw_params, &fmt);
127 if (r < 0)
128 FATALA("silence:alsa:unable to get the pcm format\n");
129 r = snd_pcm_hw_params_get_access(hw_params, &access);
130 if (r < 0)
131 FATALA("silence:alsa:unable to get the pcm access mode\n");
132 r = snd_pcm_hw_params_get_channels(hw_params, &chans_n);
133 if (r < 0)
134 FATALA("silence:alsa:unable to get the pcm number of channels\n");
136 /* wipe silence bufs first */
137 c = 0;
138 loop {
139 if (c == AVUTIL_DATA_PTRS_N)
140 break;
141 if (pcm_silence_bufs_l[c] != 0) {
142 free(pcm_silence_bufs_l[c]);
143 pcm_silence_bufs_l[c] = 0;
145 ++c;
147 if (access == SND_PCM_ACCESS_RW_INTERLEAVED
148 || access == SND_PCM_ACCESS_MMAP_INTERLEAVED) {
149 ssize_t buf_bytes_n;
151 buf_bytes_n = snd_pcm_frames_to_bytes(pcm_p,
152 (snd_pcm_sframes_t)buf_ufrs_n);
153 if (buf_bytes_n <= 0)
154 FATALA("silence:alsa:interleaved:unable to get the pcm number of bytes of all buffer frames\n");
155 pcm_silence_bufs_l[0] = malloc((size_t)buf_bytes_n);
156 if (pcm_silence_bufs_l[0] == 0)
157 FATALA("silence:interleaved:unable to allocate the silence buffer of %d bytes\n", (int)buf_bytes_n);
158 if (print_info)
159 POUTA("silence:interleaved:buffer of %d bytes is allocated\n", (int)buf_bytes_n);
160 r = snd_pcm_format_set_silence(fmt, pcm_silence_bufs_l[0],
161 (unsigned int)buf_ufrs_n);
162 if (r < 0)
163 FATALA("silence:non interleaved:unable to fill with silence the buffer\n");
164 POUTA("silence:non planar format:silence buffer filled with %u silence frames\n", buf_ufrs_n);
165 } else if (access == SND_PCM_ACCESS_RW_NONINTERLEAVED
166 || access == SND_PCM_ACCESS_MMAP_NONINTERLEAVED) {
167 ssize_t buf_bytes_n;
168 long buf_samples_n;
170 buf_samples_n = (long)buf_ufrs_n;
171 buf_bytes_n = snd_pcm_samples_to_bytes(pcm_p, buf_samples_n);
172 if (buf_bytes_n <= 0)
173 FATALA("silence:alsa:non interleaved:unable to get the pcm number of total bytes of all buffer samples\n");
174 c = 0;
175 loop {
176 if (c == chans_n)
177 break;
178 pcm_silence_bufs_l[c] = malloc((size_t)buf_bytes_n);
179 if (pcm_silence_bufs_l[c] == 0)
180 FATALA("silence:non interleaved:unable to allocate silence buffer %u of %d bytes\n", c, (int)buf_bytes_n);
181 r = snd_pcm_format_set_silence(fmt,
182 pcm_silence_bufs_l[c],
183 (unsigned int)buf_samples_n);
184 if (r < 0)
185 FATALA("silence:non interleaved:unable to fill with silence the buffer\n");
186 if (print_info)
187 POUTA("silence:non interleaved:buffer[%u] of %d bytes is allocated\n", c, (int)buf_bytes_n);
188 ++c;
190 if (print_info)
191 POUTA("silence:non interleaved:allocated %u silence buffers for %u frames\n", chans_n, (unsigned int)buf_ufrs_n);
192 } else
193 FATALA("silence:the pcm access type is not supported\n");
194 snd_pcm_hw_params_free(hw_params);
196 static void init_once(u8 *pcm_str)
198 init_once_local();
199 init_once_public(pcm_str);
201 static void dec_flush(void)
203 pkt_q_unref_all(pkt_q_p);
204 dec_a_unref_all();
205 dec_sets_p.eof_receive = false;
206 avcodec_flush_bufs(dec_ctx_p);
208 static void dec_ctx_lock(void)
210 int r;
212 r = pthread_mutex_lock(&dec_ctx_mutex_l);
213 if (r != 0)
214 FATALA("%d:unable to lock the decoder context\n", r);
216 static void dec_ctx_unlock(void)
218 int r;
220 r = pthread_mutex_unlock(&dec_ctx_mutex_l);
221 if (r != 0)
222 FATALA("%d:unable to unlock the decoder context\n", r);
224 static void dec_sets_lock(void)
226 int r;
228 r = pthread_mutex_lock(&dec_sets_p.mutex);
229 if (r != 0)
230 FATALA("%d:unable to lock the array of decoder sets\n", r);
232 static void dec_sets_unlock(void)
234 int r;
236 r = pthread_mutex_unlock(&dec_sets_p.mutex);
237 if (r != 0)
238 FATALA("%d:unable to unlock the array of decoder sets\n", r);
240 static void pcm_cfg(snd_pcm_t *pcm, unsigned int chans_n, unsigned int rate,
241 enum avutil_audio_fr_fmt_t ff_fmt)
243 pcm_cfg_hw(pcm, chans_n, rate, ff_fmt);
244 pcm_cfg_sw(pcm);
245 POUTA("ALSA PCM DUMP START-------------------------------------------------------------\n");
246 snd_pcm_dump(pcm, pcm_pout_l);
247 POUTA("ALSA PCM DUMP END---------------------------------------------------------------\n");
249 static void pcm2ff(snd_pcm_t *pcm, enum avutil_audio_fr_fmt_t *ff_fmt,
250 int *ff_rate, int *ff_chans_n, uint64_t *ff_chans_layout,
251 bool print_info)
253 int r;
254 snd_pcm_hw_params_t *hw_params;
255 snd_pcm_access_t pcm_access;
256 snd_pcm_fmt_t pcm_fmt;
257 unsigned int pcm_rate;
258 unsigned int pcm_chans_n;
260 r = snd_pcm_hw_params_malloc(&hw_params);
261 if (r < 0)
262 FATALA("alsa:unable to allocate hardware parameters context for ffmpeg filter wiring\n");
263 r = snd_pcm_hw_params_current(pcm, hw_params);
264 if (r != 0)
265 FATALA("alsa:unable to get current hardware parameters for ffmpeg filter wiring\n");
266 r = snd_pcm_hw_params_get_access(hw_params, &pcm_access);
267 if (r < 0)
268 FATALA("alsa:unable to get the pcm access for ffmpeg filter wiring\n");
269 r = snd_pcm_hw_params_get_fmt(hw_params, &pcm_fmt);
270 if (r < 0)
271 FATALA("alsa:unable to get the pcm format for ffmpeg filter wiring\n");
272 /*--------------------------------------------------------------------*/
273 pcm_layout2ff_fmt_strict(pcm_fmt, pcm_access, ff_fmt, print_info);
274 /*--------------------------------------------------------------------*/
275 r = snd_pcm_hw_params_get_rate(hw_params, &pcm_rate,
276 SND_PCM_ST_PLAYBACK);
277 if (r < 0)
278 FATALA("alsa:unable to get the pcm rate for ffmpeg filter wiring\n");
279 *ff_rate = (int)pcm_rate;
280 r = snd_pcm_hw_params_get_chans_n(hw_params, &pcm_chans_n);
281 if (r < 0)
282 FATALA("alsa:unable to get the pcm count of channels for ffmpeg filter wiring\n");
283 *ff_chans_n = (int)pcm_chans_n;
284 /*--------------------------------------------------------------------*/
285 *ff_chans_layout = pcm_chmaps2ff_chans_layout(pcm, pcm_chans_n,
286 print_info);
287 /*--------------------------------------------------------------------*/
288 snd_pcm_hw_params_free(hw_params);
290 /* we do per-loop fine-grained locking */
291 #define sz size
292 static void pkts_send(void) { loop
294 int r;
295 avcodec_pkt_ref_t *pr;
297 pkt_q_lock(pkt_q_p);
298 if (pkt_q_p->n == 0)
299 goto unlock_and_return;
300 pr = pkt_q_p->q[0];
301 dec_ctx_lock();
302 r = avcodec_send_pkt(dec_ctx_p, pr);
303 dec_ctx_unlock();
304 if (r == AVERROR(EAGAIN)) /* dec is full and the pkt is rejected */
305 goto unlock_and_return;
306 else if (r == AVUTIL_AVERROR_EOF) /* the dec is in draining mode */
307 goto unlock_and_return;
308 else if (r != 0)
309 FATALA("error while sending a packet to the decoder\n");
310 /* r == 0 */
311 pipeline_limits_lock();
312 pipeline_limits_p.pkts.audio_bytes_n -= pr->sz;
313 pipeline_limits_unlock();
315 pkt_q_deq(pkt_q_p);
316 avcodec_pkt_unref(pr);
317 pkt_q_unlock(pkt_q_p);
318 continue;
320 unlock_and_return:
321 pkt_q_unlock(pkt_q_p);
322 return;
324 #undef sz