move to new ffmpeg channel layout handling
[nyanmp.git] / npv / audio / public / code.frag.c
blob8d25d49fc7895f8277fbd15ff831b0ca5bce416f
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 fatal("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 fatal("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 fatal("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 fatal("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 #ifdef NPV_DEBUG
41 if (npv_debug_p)
42 npv_perr("DEBUG:audio:received set pts=%ld\n", dec_sets_p.a[last]->pts);
43 #endif
44 ++dec_sets_p.n;
45 return HAVE_DEC_SET;
46 } else if (r == AVUTIL_AVERROR_EOF) {
47 pout("ffmpeg:last decoder set of frames reached (receiving)\n");
48 dec_sets_p.eof_receive = true;
49 return EOF_DEC;
51 fatal("ffmpeg:error while receiving a set of frames from the decoder\n");
53 #undef AGAIN
54 #undef HAVE_DEC_SET
55 #undef EOF_DEC
56 #define AGAIN 0
57 #define HAVE_DEC_SET 1
58 #define EOF_DEC 2
60 * this can be long and we don't want to lock that long the q of audio frs
61 * for the alsa writer, then do finer-grained locking here
63 STATIC void dec_sets_receive_avail(void) { loop
65 u8 r;
67 dec_ctx_lock();
68 dec_sets_lock();
69 r = dec_set_try_receive();
70 dec_sets_unlock();
71 dec_ctx_unlock();
72 if (r == HAVE_DEC_SET)
73 continue;
74 else if (r == AGAIN || r == EOF_DEC)
75 break;
77 #undef AGAIN
78 #undef HAVE_DEC_SET
79 #undef EOF_DEC
80 STATIC void draining_state_evt(void)
82 int r;
83 uint64_t exps_n;
85 r = read(draining_timer_fd_p, &exps_n, sizeof(exps_n));
86 if (r == -1)
87 fatal("unable to read the number of draining state timer expirations\n");
88 draining_state_handle();
90 #define AGAIN 0
91 #define RECOVERED 1
92 #define INCOMPLETE_WRITE 1
93 #define NONE 0
94 STATIC void evt_pcm_write(void)
96 u8 pre_x;
97 snd_pcm_sfrs_t alsa_r;
98 snd_pcm_ufrs_t ufrs_n;
99 u8 r;
101 pre_x = atomic_load(&npv_pre_x_p);
102 if (pre_x != NONE) /* TODO: play silence here */
103 return;
104 alsa_r = snd_pcm_avail(pcm_p);
105 r = alsa_recover(alsa_r);
106 if (r == AGAIN || r == RECOVERED)
107 return;
108 /* r == CONTINUE */
109 ufrs_n = (snd_pcm_ufrs_t)alsa_r;
110 if (npv_paused_p) {
111 pcm_silence_frs_write(ufrs_n);
112 return;
114 r = pcm_filt_frs_write(&ufrs_n);
115 if (r == INCOMPLETE_WRITE)
116 pcm_silence_frs_write(ufrs_n);
117 /* DRAINING | ALL_FRS_WRITTEN | RECOVERED */
119 #undef AGAIN
120 #undef RECOVERED
121 #undef INCOMPLETE_WRITE
122 #undef NONE
123 STATIC void pcm_silence_bufs_cfg(snd_pcm_t *pcm, bool print_info)
125 int r;
126 snd_pcm_hw_params_t *hw_params;
127 snd_pcm_ufrs_t buf_ufrs_n;
128 snd_pcm_fmt_t fmt;
129 snd_pcm_access_t access;
130 unsigned int chans_n;
131 u8 c;
133 r = snd_pcm_hw_params_malloc(&hw_params);
134 if (r < 0)
135 fatal("silence:alsa:unable to allocate memory for a hardware parameters container\n");
136 r = snd_pcm_hw_params_current(pcm, hw_params);
137 if (r != 0)
138 fatal("silence:alsa:unable to get the pcm hardware parameters\n");
139 r = snd_pcm_hw_params_get_buf_sz(hw_params, &buf_ufrs_n);
140 if (r < 0)
141 fatal("silence:alsa:unable to get the number of frames in the pcm buffer\n");
142 r = snd_pcm_hw_params_get_format(hw_params, &fmt);
143 if (r < 0)
144 fatal("silence:alsa:unable to get the pcm format\n");
145 r = snd_pcm_hw_params_get_access(hw_params, &access);
146 if (r < 0)
147 fatal("silence:alsa:unable to get the pcm access mode\n");
148 r = snd_pcm_hw_params_get_channels(hw_params, &chans_n);
149 if (r < 0)
150 fatal("silence:alsa:unable to get the pcm number of channels\n");
152 /* wipe silence bufs first */
153 c = 0;
154 loop {
155 if (c == AVUTIL_DATA_PTRS_N)
156 break;
157 if (pcm_silence_bufs_l[c] != 0) {
158 free(pcm_silence_bufs_l[c]);
159 pcm_silence_bufs_l[c] = 0;
161 ++c;
163 if (access == SND_PCM_ACCESS_RW_INTERLEAVED
164 || access == SND_PCM_ACCESS_MMAP_INTERLEAVED) {
165 ssize_t buf_bytes_n;
167 buf_bytes_n = snd_pcm_frames_to_bytes(pcm,
168 (snd_pcm_sframes_t)buf_ufrs_n);
169 if (buf_bytes_n <= 0)
170 fatal("silence:alsa:interleaved:unable to get the pcm number of bytes of all buffer frames\n");
171 pcm_silence_bufs_l[0] = malloc((size_t)buf_bytes_n);
172 if (pcm_silence_bufs_l[0] == 0)
173 fatal("silence:interleaved:unable to allocate the silence buffer of %d bytes\n", (int)buf_bytes_n);
174 if (print_info)
175 pout("silence:interleaved:buffer of %d bytes is allocated\n", (int)buf_bytes_n);
176 r = snd_pcm_format_set_silence(fmt, pcm_silence_bufs_l[0],
177 (unsigned int)buf_ufrs_n);
178 if (r < 0)
179 fatal("silence:interleaved:unable to fill with silence the buffer\n");
180 pout("silence:interleaved:silence buffer filled with %u silence frames\n", buf_ufrs_n);
181 } else if (access == SND_PCM_ACCESS_RW_NONINTERLEAVED
182 || access == SND_PCM_ACCESS_MMAP_NONINTERLEAVED) {
183 ssize_t buf_bytes_n;
184 long buf_samples_n;
186 buf_samples_n = (long)buf_ufrs_n;
187 buf_bytes_n = snd_pcm_samples_to_bytes(pcm, buf_samples_n);
188 if (buf_bytes_n <= 0)
189 fatal("silence:alsa:non interleaved:unable to get the pcm number of total bytes of all buffer samples\n");
190 c = 0;
191 loop {
192 if (c == chans_n)
193 break;
194 pcm_silence_bufs_l[c] = malloc((size_t)buf_bytes_n);
195 if (pcm_silence_bufs_l[c] == 0)
196 fatal("silence:non interleaved:unable to allocate silence buffer %u of %d bytes\n", c, (int)buf_bytes_n);
197 r = snd_pcm_format_set_silence(fmt,
198 pcm_silence_bufs_l[c],
199 (unsigned int)buf_samples_n);
200 if (r < 0)
201 fatal("silence:non interleaved:unable to fill with silence the buffer\n");
202 if (print_info)
203 pout("silence:non interleaved:buffer[%u] of %d bytes is allocated\n", c, (int)buf_bytes_n);
204 ++c;
206 if (print_info)
207 pout("silence:non interleaved:allocated %u silence buffers for %u frames\n", chans_n, (unsigned int)buf_ufrs_n);
208 } else
209 fatal("silence:the pcm access type is not supported\n");
210 snd_pcm_hw_params_free(hw_params);
212 STATIC void init_once(u8 *pcm_str)
214 init_once_local();
215 init_once_public(pcm_str);
217 STATIC void dec_flush(void)
219 npv_pkt_q_unref_all(pkt_q_p);
220 dec_a_unref_all();
221 dec_sets_p.eof_receive = false;
222 avcodec_flush_bufs(dec_ctx_p);
224 STATIC void dec_ctx_lock(void)
226 int r;
228 r = pthread_mutex_lock(&dec_ctx_mutex_l);
229 if (r != 0)
230 fatal("%d:unable to lock the decoder context\n", r);
232 STATIC void dec_ctx_unlock(void)
234 int r;
236 r = pthread_mutex_unlock(&dec_ctx_mutex_l);
237 if (r != 0)
238 fatal("%d:unable to unlock the decoder context\n", r);
240 STATIC void dec_sets_lock(void)
242 int r;
244 r = pthread_mutex_lock(&dec_sets_p.mutex);
245 if (r != 0)
246 fatal("%d:unable to lock the array of decoder sets\n", r);
248 STATIC void dec_sets_unlock(void)
250 int r;
252 r = pthread_mutex_unlock(&dec_sets_p.mutex);
253 if (r != 0)
254 fatal("%d:unable to unlock the array of decoder sets\n", r);
256 STATIC void pcm_cfg_hw_best_effort(snd_pcm_t *pcm, int chans_n, int rate,
257 enum avutil_audio_fr_fmt_t ff_fmt)
259 int r;
260 s8 i;
261 snd_pcm_access_t access;
262 snd_pcm_hw_params_t *hw_params;
264 pout("ALSA:HW_PARAMS START------------------------------------------------------------\n");
265 r = snd_pcm_hw_params_malloc(&hw_params);
266 if (r < 0)
267 fatal("alsa:unable to allocate hardware parameters context\n");
268 pcm_cfg_hw_core_best_effort(pcm, hw_params, chans_n, rate, ff_fmt);
269 r = snd_pcm_hw_params(pcm, hw_params);
270 if (r != 0)
271 fatal("alsa:unable to install the hardware parameters\n");
272 r = snd_pcm_hw_params_current(pcm, hw_params);
273 if (r != 0)
274 fatal("alsa:unable to get current hardware parameters\n");
275 snd_pcm_hw_params_dump(hw_params, pcm_pout_l);
276 i = 0;
277 selected_ts_type_p = -1;
278 loop {
279 if (i == ARRAY_N(kernel_ts_types_str_l))
280 break;
281 r = snd_pcm_hw_params_supports_audio_ts_type(hw_params, i);
282 if (r == 1) {
283 selected_ts_type_p = i;
284 pout("kernel audio timestamp type \"%s\" is supported for the current configuration\n", kernel_ts_types_str_l[i]);
286 ++i;
289 * we selected the most accurate, namely with the highest idx, audio ts
290 * type
292 pout("%s will be used for the audio based clock\n", kernel_ts_types_str_l[selected_ts_type_p]);
293 snd_pcm_hw_params_free(hw_params);
294 pout("ALSA:HW_PARAMS END--------------------------------------------------------------\n");
296 STATIC void pcm_cfg_sw(snd_pcm_t *pcm)
298 int r;
299 snd_pcm_sw_params_t *sw_params;
301 pout("ALSA:SW_PARAMS START------------------------------------------------------------\n");
302 r = snd_pcm_sw_params_malloc(&sw_params);
303 if (r != 0)
304 fatal("alsa:unable to allocate software parameters structure\n");
305 r = snd_pcm_sw_params_current(pcm, sw_params);
306 if (r != 0)
307 fatal("alsa:unable to get current software parameters\n");
308 r = snd_pcm_sw_params_set_period_evt(pcm, sw_params, 1);
309 if (r != 0)
310 fatal("alsa:unable to enable period event\n");
311 /* enable ts to be sure */
312 r = snd_pcm_sw_params_set_tstamp_mode(pcm, sw_params,
313 SND_PCM_TSTAMP_ENABLE);
314 if (r < 0)
315 fatal("unable to set timestamp mode:%s\n", snd_strerror(r));
316 r = snd_pcm_sw_params(pcm, sw_params);
317 if (r != 0)
318 fatal("alsa:unable to install sotfware parameters\n");
319 snd_pcm_sw_params_dump(sw_params, pcm_pout_l);
320 snd_pcm_sw_params_free(sw_params);
321 pout("ALSA:SW_PARAMS END--------------------------------------------------------------\n");
323 /* we do per-loop fine-grained locking */
324 #define sz size
325 STATIC void pkts_send(void) { loop
327 int r;
328 avcodec_pkt_ref_t *pr;
330 npv_pkt_q_lock(pkt_q_p);
331 if (pkt_q_p->n == 0)
332 goto unlock_and_return;
333 pr = pkt_q_p->q[0];
334 dec_ctx_lock();
335 r = avcodec_send_pkt(dec_ctx_p, pr);
336 dec_ctx_unlock();
337 if (r == AVERROR(EAGAIN)) /* dec is full and the pkt is rejected */
338 goto unlock_and_return;
339 else if (r == AVUTIL_AVERROR_EOF) /* the dec is in draining mode */
340 goto unlock_and_return;
341 else if (r != 0)
342 fatal("error while sending a packet to the decoder\n");
343 /* r == 0 */
344 npv_pipeline_limits_lock();
345 npv_pipeline_limits_p.pkts.audio_bytes_n -= pr->sz;
346 npv_pipeline_limits_unlock();
348 npv_pkt_q_deq(pkt_q_p);
349 avcodec_pkt_unref(pr);
350 npv_pkt_q_unlock(pkt_q_p);
351 continue;
353 unlock_and_return:
354 npv_pkt_q_unlock(pkt_q_p);
355 return;
357 #undef sz
358 #define CHANS_N_NOT_OVERRIDDEN 0
359 #define RATE_NOT_OVERRIDDEN 0
360 #define AUDIO_FR_FMT_NOT_OVERRIDDEN AVUTIL_AUDIO_FR_FMT_NONE
361 #define PRINT_INFO true
362 STATIC void npv_audio_prepare(int override_initial_ff_chans_n,
363 int override_initial_ff_rate,
364 enum avutil_audio_fr_fmt_t override_initial_ff_fmt)
366 int dst_rate;
367 enum avutil_audio_fr_fmt_t dst_fmt;
368 int initial_ff_chans_n;
369 int initial_ff_rate;
370 enum avutil_audio_fr_fmt_t initial_ff_fmt;
371 int r;
374 * do our best to match the pcm cfg to audio ff dec output OR the user
375 * overrides, BUT we don't expect to match it "exactly": a ff filt
376 * will bridge the difference
378 if (override_initial_ff_chans_n == CHANS_N_NOT_OVERRIDDEN)
379 /* we presume the dec_ctx has at least a valid chans_n */
380 initial_ff_chans_n = dec_ctx_p->ch_layout.nb_channels;
381 else
382 initial_ff_chans_n = override_initial_ff_chans_n;
383 if (override_initial_ff_rate == RATE_NOT_OVERRIDDEN)
384 initial_ff_rate = dec_ctx_p->fr_rate;
385 else
386 initial_ff_rate = override_initial_ff_rate;
387 if (override_initial_ff_fmt == AUDIO_FR_FMT_NOT_OVERRIDDEN)
388 initial_ff_fmt = dec_ctx_p->fr_fmt;
389 else
390 initial_ff_fmt = override_initial_ff_fmt;
391 npv_audio_pcm_cfg_hw_best_effort(pcm_p, initial_ff_chans_n,
392 initial_ff_rate, initial_ff_fmt);
393 npv_audio_pcm_silence_bufs_cfg(pcm_p, PRINT_INFO);
394 npv_audio_pcm_cfg_sw(pcm_p);
395 pout("ALSA PCM DUMP START-------------------------------------------------------------\n");
396 snd_pcm_dump(pcm_p, pcm_pout_l);
397 pout("ALSA PCM DUMP END---------------------------------------------------------------\n");
399 #undef CHANS_N_NOT_OVERRIDDEN
400 #undef RATE_NOT_OVERRIDDEN
401 #undef AUDIO_FR_FMT_NOT_OVERRIDDEN
402 #undef PRINT_INFO