File npa/npa.c changed (mode: 100644) (index 177f23b..141a136) |
18 |
18 |
* cfg : ConFiGuration |
* cfg : ConFiGuration |
19 |
19 |
* ctx : ConTeX |
* ctx : ConTeX |
20 |
20 |
* dec : DECoder/DECoded |
* dec : DECoder/DECoded |
|
21 |
|
* desc : DESCription |
21 |
22 |
* dev : DEVice |
* dev : DEVice |
22 |
23 |
* e : End (usually a pointer on the byte past the last valid byte) |
* e : End (usually a pointer on the byte past the last valid byte) |
23 |
24 |
* eof : End Of File |
* eof : End Of File |
|
26 |
27 |
* evt(s) : EVenT(S) |
* evt(s) : EVenT(S) |
27 |
28 |
* err : ERRor |
* err : ERRor |
28 |
29 |
* fd : File Descriptor |
* fd : File Descriptor |
|
30 |
|
* ff : FFmpeg |
29 |
31 |
* filt : FILTer |
* filt : FILTer |
30 |
32 |
* fmt : ForMaT |
* fmt : ForMaT |
31 |
33 |
* fr(s) : FRame(S) |
* fr(s) : FRame(S) |
|
38 |
40 |
* nr : NumbeR |
* nr : NumbeR |
39 |
41 |
* out : OUTput |
* out : OUTput |
40 |
42 |
* pkt(s) : PacKeT(S) |
* pkt(s) : PacKeT(S) |
|
43 |
|
* pts : Presentation TimeStamp |
41 |
44 |
* rd : ReaD |
* rd : ReaD |
42 |
45 |
* ref(s) : REFerence(S) |
* ref(s) : REFerence(S) |
43 |
46 |
* s : Start |
* s : Start |
|
59 |
62 |
* and/or similar cleanup: we have a virtual machine with a garbage collector, |
* and/or similar cleanup: we have a virtual machine with a garbage collector, |
60 |
63 |
* it is linux. |
* it is linux. |
61 |
64 |
* |
* |
62 |
|
* we do presume we won't play more than 8 chans and ffmpeg chans layout will |
|
|
65 |
|
* we do presume we won't play more than 8 chans and ff chans layout will |
63 |
66 |
* fit alsa chans map |
* fit alsa chans map |
64 |
67 |
* |
* |
65 |
68 |
* XXX: we don't know how the alsa silence machinery works, then we use brutal |
* XXX: we don't know how the alsa silence machinery works, then we use brutal |
|
88 |
91 |
#include <sys/epoll.h> |
#include <sys/epoll.h> |
89 |
92 |
#include <sys/signalfd.h> |
#include <sys/signalfd.h> |
90 |
93 |
#include <sys/timerfd.h> |
#include <sys/timerfd.h> |
91 |
|
/* ffmpeg */ |
|
|
94 |
|
/* ff */ |
92 |
95 |
#include <libavformat/avformat.h> |
#include <libavformat/avformat.h> |
93 |
96 |
#include <libavcodec/avcodec.h> |
#include <libavcodec/avcodec.h> |
94 |
97 |
#include <libavfilter/avfilter.h> |
#include <libavfilter/avfilter.h> |
|
97 |
100 |
#include <libavutil/opt.h> |
#include <libavutil/opt.h> |
98 |
101 |
/* alsa */ |
/* alsa */ |
99 |
102 |
#include <alsa/asoundlib.h> |
#include <alsa/asoundlib.h> |
|
103 |
|
/*============================================================================*/ |
|
104 |
|
/* namespaces -- START */ |
100 |
105 |
/*----------------------------------------------------------------------------*/ |
/*----------------------------------------------------------------------------*/ |
101 |
|
/* fix C */ |
|
|
106 |
|
/* fix C -- START */ |
102 |
107 |
#define u8 uint8_t |
#define u8 uint8_t |
103 |
108 |
#define U8_MAX 255 |
#define U8_MAX 255 |
104 |
109 |
#define u32 uint32_t |
#define u32 uint32_t |
|
110 |
115 |
#else |
#else |
111 |
116 |
#error "unable to find the right atomic for a 8 bits byte, be sure to have __STDC_WANT_IEC_60559_BFP_EXT__ defined" |
#error "unable to find the right atomic for a 8 bits byte, be sure to have __STDC_WANT_IEC_60559_BFP_EXT__ defined" |
112 |
117 |
#endif |
#endif |
|
118 |
|
/* fix C -- END */ |
113 |
119 |
/*----------------------------------------------------------------------------*/ |
/*----------------------------------------------------------------------------*/ |
114 |
|
|
|
|
120 |
|
/* ff namespace -- START*/ |
|
121 |
|
#define AV_FR_FMT_NONE AV_SAMPLE_FMT_NONE |
|
122 |
|
#define av_bufsink_get_frs av_buffersink_get_frame |
|
123 |
|
#define av_bufsrc_add_frs_flags av_buffersrc_add_frame_flags |
|
124 |
|
#define AV_BUFSRC_FLAG_KEEP_REF AV_BUFFERSRC_FLAG_KEEP_REF |
|
125 |
|
#define AV_BUFSRC_FLAG_PUSH AV_BUFFERSRC_FLAG_PUSH |
|
126 |
|
#define av_codec AVCodec |
|
127 |
|
#define av_codec_ctx AVCodecContext |
|
128 |
|
#define av_dump_fmt av_dump_format |
|
129 |
|
#define av_duration_estimation_method AVDurationEstimationMethod |
|
130 |
|
#define av_filt AVFilter |
|
131 |
|
#define av_filt_ctx AVFilterContext |
|
132 |
|
#define av_filt_get_by_name avfilter_get_by_name |
|
133 |
|
#define av_filt_graph AVFilterGraph |
|
134 |
|
#define av_filt_graph_alloc avfilter_graph_alloc |
|
135 |
|
#define av_filt_graph_alloc_filt avfilter_graph_alloc_filter |
|
136 |
|
#define av_filt_graph_cfg avfilter_graph_config |
|
137 |
|
#define av_filt_graph_dump avfilter_graph_dump |
|
138 |
|
#define av_filt_graph_free avfilter_graph_free |
|
139 |
|
#define av_filt_graph_send_cmd avfilter_graph_send_command |
|
140 |
|
#define av_filt_init_str avfilter_init_str |
|
141 |
|
#define av_filt_link avfilter_link |
|
142 |
|
#define av_find_best_st av_find_best_stream |
|
143 |
|
#define av_flush_bufs avcodec_flush_buffers |
|
144 |
|
#define av_fmt_ctx AVFormatContext |
|
145 |
|
#define AV_FMT_DURATION_FROM_BITRATE AVFMT_DURATION_FROM_BITRATE |
|
146 |
|
#define AV_FMT_DURATION_FROM_PTS AVFMT_DURATION_FROM_PTS |
|
147 |
|
#define AV_FMT_DURATION_FROM_ST AVFMT_DURATION_FROM_STREAM |
|
148 |
|
#define av_fmt_find_st_info avformat_find_stream_info |
|
149 |
|
#define av_fmt_flush avformat_flush |
|
150 |
|
#define av_fmt_open_input avformat_open_input |
|
151 |
|
#define av_fr_fmt_is_planar av_sample_fmt_is_planar |
|
152 |
|
#define AV_FR_FMT_DBL AV_SAMPLE_FMT_DBL |
|
153 |
|
#define AV_FR_FMT_DBLP AV_SAMPLE_FMT_DBLP |
|
154 |
|
#define AV_FR_FMT_FLT AV_SAMPLE_FMT_FLT |
|
155 |
|
#define AV_FR_FMT_FLTP AV_SAMPLE_FMT_FLTP |
|
156 |
|
#define AV_FR_FMT_S16 AV_SAMPLE_FMT_S16 |
|
157 |
|
#define AV_FR_FMT_S16P AV_SAMPLE_FMT_S16P |
|
158 |
|
#define AV_FR_FMT_S32 AV_SAMPLE_FMT_S32 |
|
159 |
|
#define AV_FR_FMT_S32P AV_SAMPLE_FMT_S32P |
|
160 |
|
#define AV_FR_FMT_U8P AV_SAMPLE_FMT_U8P |
|
161 |
|
#define AV_FR_FMT_U8 AV_SAMPLE_FMT_U8 |
|
162 |
|
#define av_frs_alloc av_frame_alloc |
|
163 |
|
#define av_frs_set_silence av_samples_set_silence |
|
164 |
|
#define av_frs_unref av_frame_unref |
|
165 |
|
#define av_get_chan_layout_str av_get_channel_layout_string |
|
166 |
|
#define av_get_default_chans_layout av_get_default_channel_layout |
|
167 |
|
#define av_get_fr_fmt_name av_get_sample_fmt_name |
|
168 |
|
#define av_get_fr_fmt_str av_get_sample_fmt_string |
|
169 |
|
#define av_io_flush avio_flush |
|
170 |
|
#define AV_MEDIA_TYPE_AUDIO AVMEDIA_TYPE_AUDIO |
|
171 |
|
#define av_pkt AVPacket |
|
172 |
|
#define av_pkt_unref av_packet_unref |
|
173 |
|
#define av_read_pkt av_read_frame |
|
174 |
|
#define av_rational AVRational |
|
175 |
|
#define av_seek_pkt av_seek_frame |
|
176 |
|
#define av_receive_frs avcodec_receive_frame |
|
177 |
|
#define av_fr_fmt AVSampleFormat |
|
178 |
|
#define av_frs AVFrame |
|
179 |
|
#define av_sd_pkt avcodec_send_packet |
|
180 |
|
#define av_st AVStream |
|
181 |
|
#define chans_layout channel_layout |
|
182 |
|
#define chans_n channels |
|
183 |
|
#define fmt format |
|
184 |
|
#define fr_fmt sample_fmt |
|
185 |
|
#define fr_rate sample_rate |
|
186 |
|
#define frs_n nb_samples |
|
187 |
|
#define st_idx stream_index |
|
188 |
|
#define sts streams |
|
189 |
|
#define tb time_base |
|
190 |
|
/* ff namespace -- END */ |
|
191 |
|
/*----------------------------------------------------------------------------*/ |
|
192 |
|
/* alsa namespace -- START */ |
|
193 |
|
#define snd_pcm_fmt_desc snd_pcm_format_description |
|
194 |
|
#define snd_pcm_fmt_set_silence snd_pcm_format_set_silence |
|
195 |
|
#define SND_PCM_FMT_FLT SND_PCM_FORMAT_FLOAT |
|
196 |
|
#define SND_PCM_FMT_S16 SND_PCM_FORMAT_S16 |
|
197 |
|
#define SND_PCM_FMT_S24 SND_PCM_FORMAT_S24 |
|
198 |
|
#define SND_PCM_FMT_S32 SND_PCM_FORMAT_S32 |
|
199 |
|
#define SND_PCM_FMT_S8 SND_PCM_FORMAT_S8 |
|
200 |
|
#define snd_pcm_fmt_t snd_pcm_format_t |
|
201 |
|
#define SND_PCM_FMT_U16 SND_PCM_FORMAT_U16 |
|
202 |
|
#define SND_PCM_FMT_U24 SND_PCM_FORMAT_U24 |
|
203 |
|
#define SND_PCM_FMT_U32 SND_PCM_FORMAT_U32 |
|
204 |
|
#define SND_PCM_FMT_U8 SND_PCM_FORMAT_U8 |
|
205 |
|
#define snd_pcm_frs_to_bytes snd_pcm_frames_to_bytes |
|
206 |
|
#define snd_pcm_hw_params_get_buf_size snd_pcm_hw_params_get_buffer_size |
|
207 |
|
#define snd_pcm_hw_params_get_chans snd_pcm_hw_params_get_channels |
|
208 |
|
#define snd_pcm_hw_params_get_chans_max snd_pcm_hw_params_get_channels_max |
|
209 |
|
#define snd_pcm_hw_params_get_chans_min snd_pcm_hw_params_get_channels_min |
|
210 |
|
#define snd_pcm_hw_params_get_fmt snd_pcm_hw_params_get_format |
|
211 |
|
#define snd_pcm_hw_params_set_buf_size_near snd_pcm_hw_params_set_buffer_size_near |
|
212 |
|
#define snd_pcm_hw_params_set_chans snd_pcm_hw_params_set_channels |
|
213 |
|
#define snd_pcm_hw_params_set_fmt snd_pcm_hw_params_set_format |
|
214 |
|
#define snd_pcm_hw_params_test_chans snd_pcm_hw_params_test_channels |
|
215 |
|
#define snd_pcm_hw_params_test_fmt snd_pcm_hw_params_test_format |
|
216 |
|
#define snd_pcm_sfrs_t snd_pcm_sframes_t |
|
217 |
|
#define SND_PCM_ST_PLAYBACK SND_PCM_STREAM_PLAYBACK |
|
218 |
|
#define snd_pcm_ufrs_t snd_pcm_uframes_t |
|
219 |
|
/* alsa namespace -- END */ |
|
220 |
|
/* namespaces -- END */ |
|
221 |
|
/*============================================================================*/ |
115 |
222 |
#define ARRAY_N(x) (sizeof(x) / sizeof((x)[0])) |
#define ARRAY_N(x) (sizeof(x) / sizeof((x)[0])) |
116 |
|
|
|
117 |
|
#define POUT(fmt, ...) fprintf(stdout, fmt, ##__VA_ARGS__) |
|
118 |
|
#define PERR(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__) |
|
119 |
|
#define WARNING(fmt, ...) fprintf(stderr, "WARNING:" fmt, ##__VA_ARGS__) |
|
120 |
|
#define FATAL(fmt, ...) ({perr("FATAL:" fmt, ##__VA_ARGS__);stdin_flags_restore();stdin_tty_cfg_restore();exit(1);}) |
|
121 |
|
#define EXIT(fmt, ...) ({pout("EXITING:" fmt, ##__VA_ARGS__);stdin_flags_restore();stdin_tty_cfg_restore();exit(0);}) |
|
122 |
223 |
#define STR_SZ 255 /* sz and idx fit in 1 byte */ |
#define STR_SZ 255 /* sz and idx fit in 1 byte */ |
123 |
224 |
/*---------------------------------------------------------------------------*/ |
/*---------------------------------------------------------------------------*/ |
124 |
225 |
static u8 *current_url; |
static u8 *current_url; |
|
... |
... |
static int current_st_idx; |
127 |
228 |
static struct { |
static struct { |
128 |
229 |
struct { |
struct { |
129 |
230 |
int64_t duration; |
int64_t duration; |
130 |
|
enum AVDurationEstimationMethod m; |
|
|
231 |
|
enum av_duration_estimation_method m; |
131 |
232 |
} fmt; |
} fmt; |
132 |
233 |
struct { |
struct { |
133 |
|
AVRational tb; |
|
|
234 |
|
av_rational tb; |
134 |
235 |
int id; |
int id; |
135 |
236 |
int64_t duration; |
int64_t duration; |
136 |
237 |
} st; |
} st; |
|
... |
... |
static struct { |
140 |
241 |
static int ep_fd; |
static int ep_fd; |
141 |
242 |
static int sig_fd; |
static int sig_fd; |
142 |
243 |
/*---------------------------------------------------------------------------*/ |
/*---------------------------------------------------------------------------*/ |
143 |
|
/* linux alsa */ |
|
|
244 |
|
/* alsa */ |
144 |
245 |
static snd_pcm_t *pcm_g; |
static snd_pcm_t *pcm_g; |
145 |
246 |
static snd_output_t *pcm_pout; |
static snd_output_t *pcm_pout; |
146 |
247 |
static snd_output_t *pcm_perr; |
static snd_output_t *pcm_perr; |
|
... |
... |
static snd_output_t *pcm_perr; |
148 |
249 |
static struct pollfd pcm_pollfds[PCM_POLLFDS_N_MAX]; |
static struct pollfd pcm_pollfds[PCM_POLLFDS_N_MAX]; |
149 |
250 |
static u8 pcm_pollfds_n; |
static u8 pcm_pollfds_n; |
150 |
251 |
/*---------------------------------------------------------------------------*/ |
/*---------------------------------------------------------------------------*/ |
151 |
|
/* ffmpeg dec */ |
|
152 |
|
/* |
|
153 |
|
* XXX: a ffmpeg fr is not 1 audio fr but a collection of frs. |
|
154 |
|
* ffmpeg dec fr "nb_samples" is actually the number of audio frs |
|
155 |
|
* av_read_frame is actually av_read_pkt, like av_seek* |
|
156 |
|
* we personally did not like the resulting confusion. |
|
157 |
|
* we purposely "fix" the namespace even if some others won't like it. |
|
158 |
|
*/ |
|
159 |
|
#define AVFrames AVFrame |
|
160 |
|
#define frames_n nb_samples |
|
161 |
|
#define av_frames_alloc av_frame_alloc |
|
162 |
|
#define av_read_pkt av_read_frame |
|
163 |
|
#define av_seek_pkt av_seek_frame |
|
164 |
|
#define avcodec_receive_frames avcodec_receive_frame |
|
165 |
|
#define AVFrameFormat AVSampleFormat |
|
166 |
|
#define av_frames_set_silence av_samples_set_silence |
|
167 |
|
#define av_get_frame_fmt_name av_get_sample_fmt_name |
|
168 |
|
#define av_get_frame_fmt_string av_get_sample_fmt_string |
|
169 |
|
#define frame_rate sample_rate |
|
170 |
|
#define av_frame_fmt_is_planar av_sample_fmt_is_planar |
|
171 |
|
#define frame_fmt sample_fmt |
|
172 |
|
#define av_frames_unref av_frame_unref |
|
173 |
|
static AVPacket *rd_thd_pkt; |
|
174 |
|
static AVFormatContext *fmt_ctx; |
|
|
252 |
|
/* ff dec */ |
|
253 |
|
static av_pkt *rd_thd_pkt; |
|
254 |
|
static av_fmt_ctx *fmt_ctx; |
175 |
255 |
static pthread_mutex_t fmt_ctx_mutex; |
static pthread_mutex_t fmt_ctx_mutex; |
176 |
|
static AVCodec *dec; |
|
177 |
|
static AVCodecContext *dec_ctx; |
|
|
256 |
|
static av_codec *dec; |
|
257 |
|
static av_codec_ctx *dec_ctx; |
178 |
258 |
/*---------------------------------------------------------------------------*/ |
/*---------------------------------------------------------------------------*/ |
179 |
|
/* ffmpeg filter graph */ |
|
180 |
|
static AVFilterGraph *filter_graph; |
|
181 |
|
static AVFilterContext *abufsrc_ctx; |
|
182 |
|
static const AVFilter *abufsrc_filt; |
|
183 |
|
static AVFilterContext *vol_ctx; |
|
184 |
|
static const AVFilter *vol_filt; |
|
|
259 |
|
/* ff filt graph */ |
|
260 |
|
static av_filt_graph *filt_graph; |
|
261 |
|
static av_filt_ctx *abufsrc_ctx; |
|
262 |
|
static const av_filt *abufsrc_filt; |
|
263 |
|
static struct { /* used to detected reconfiguration */ |
|
264 |
|
int chans_n; |
|
265 |
|
uint64_t chans_layout; |
|
266 |
|
int rate; |
|
267 |
|
enum av_fr_fmt fmt; |
|
268 |
|
} abufsrc_key; |
|
269 |
|
static av_filt_ctx *vol_ctx; |
|
270 |
|
static const av_filt *vol_filt; |
185 |
271 |
static u8 double_zero_l10n_str[sizeof("xxx.xx")]; |
static u8 double_zero_l10n_str[sizeof("xxx.xx")]; |
186 |
|
static AVFilterContext *afmt_ctx; |
|
187 |
|
static const AVFilter *afmt_filt; |
|
188 |
|
static AVFilterContext *abufsink_ctx; |
|
189 |
|
static const AVFilter *abufsink_filt; |
|
|
272 |
|
static av_filt_ctx *afmt_ctx; |
|
273 |
|
static const av_filt *afmt_filt; |
|
274 |
|
static av_filt_ctx *abufsink_ctx; |
|
275 |
|
static const av_filt *abufsink_filt; |
190 |
276 |
/*---------------------------------------------------------------------------*/ |
/*---------------------------------------------------------------------------*/ |
191 |
277 |
/* a formally proven concurrently accessed lockless cb */ |
/* a formally proven concurrently accessed lockless cb */ |
192 |
278 |
struct { |
struct { |
193 |
279 |
atomic_u8 reset; |
atomic_u8 reset; |
|
280 |
|
atomic_u8 hold; |
194 |
281 |
|
|
195 |
282 |
atomic_int st_idx; |
atomic_int st_idx; |
196 |
|
AVPacket *pkts[U8_MAX + 1]; |
|
|
283 |
|
av_pkt *pkts[U8_MAX + 1]; |
197 |
284 |
atomic_u8 rd; |
atomic_u8 rd; |
198 |
285 |
atomic_u8 sd; |
atomic_u8 sd; |
199 |
286 |
} cb; |
} cb; |
200 |
287 |
/* running state */ |
/* running state */ |
201 |
288 |
struct { |
struct { |
202 |
|
AVFrames *av; |
|
|
289 |
|
av_frs *av; |
|
290 |
|
bool pushed_in_filt_graph; |
203 |
291 |
int64_t most_recent_ts; /* a very "coarse-grained" clock */ |
int64_t most_recent_ts; /* a very "coarse-grained" clock */ |
204 |
292 |
} dec_frs; |
} dec_frs; |
205 |
293 |
struct { |
struct { |
206 |
|
AVFrames *av; |
|
207 |
|
bool no_more_dec_frs; |
|
|
294 |
|
av_frs *av; |
208 |
295 |
float vol; |
float vol; |
209 |
296 |
bool muted; |
bool muted; |
210 |
|
snd_pcm_uframes_t pcm_written_ufrs_n; |
|
|
297 |
|
snd_pcm_ufrs_t pcm_written_ufrs_n; |
211 |
298 |
} filt_frs; |
} filt_frs; |
212 |
299 |
/* we will inject silence frs while paused */ |
/* we will inject silence frs while paused */ |
213 |
300 |
bool paused; |
bool paused; |
|
... |
... |
static void fmt_ctx_unlock(void) |
348 |
435 |
if (r != 0) |
if (r != 0) |
349 |
436 |
fatal("unable to unlock the format context\n"); |
fatal("unable to unlock the format context\n"); |
350 |
437 |
} |
} |
351 |
|
static u8 *duration_estimate_to_str(enum AVDurationEstimationMethod m) |
|
|
438 |
|
static u8 *duration_estimate_to_str(enum av_duration_estimation_method m) |
352 |
439 |
{ |
{ |
353 |
440 |
switch (m) { |
switch (m) { |
354 |
|
case AVFMT_DURATION_FROM_PTS: |
|
|
441 |
|
case AV_FMT_DURATION_FROM_PTS: |
355 |
442 |
return "from PTS(Presentation TimeStamp)"; |
return "from PTS(Presentation TimeStamp)"; |
356 |
|
case AVFMT_DURATION_FROM_STREAM: |
|
|
443 |
|
case AV_FMT_DURATION_FROM_ST: |
357 |
444 |
return "from stream"; |
return "from stream"; |
358 |
|
case AVFMT_DURATION_FROM_BITRATE: |
|
|
445 |
|
case AV_FMT_DURATION_FROM_BITRATE: |
359 |
446 |
return "from bitrate"; |
return "from bitrate"; |
360 |
447 |
default: |
default: |
361 |
448 |
return "unkwown"; |
return "unkwown"; |
362 |
449 |
} |
} |
363 |
450 |
} |
} |
364 |
451 |
/* meh... */ |
/* meh... */ |
365 |
|
static u8 *ts_to_str(int64_t ts, AVRational tb, int64_t *remaining) |
|
|
452 |
|
static u8 *ts_to_str(int64_t ts, av_rational tb, int64_t *remaining) |
366 |
453 |
{ |
{ |
367 |
454 |
static u8 str[sizeof("~S00:00:00.000 remains S9223372036854775807 time base units")]; |
static u8 str[sizeof("~S00:00:00.000 remains S9223372036854775807 time base units")]; |
368 |
455 |
bool is_neg; |
bool is_neg; |
|
... |
... |
static u8 *ts_to_str(int64_t ts, AVRational tb, int64_t *remaining) |
370 |
457 |
int64_t mins_n; |
int64_t mins_n; |
371 |
458 |
int64_t secs_n; |
int64_t secs_n; |
372 |
459 |
int64_t msecs_n; |
int64_t msecs_n; |
373 |
|
int64_t one_hour; /* in ffmpeg time_base units */ |
|
374 |
|
int64_t one_min; /* in ffmpeg time_base units */ |
|
375 |
|
int64_t one_sec; /* in ffmpeg time_base units */ |
|
376 |
|
int64_t one_msec; /* in ffmpeg time_base units */ |
|
|
460 |
|
int64_t one_hour; /* in ff tb units */ |
|
461 |
|
int64_t one_min; /* in ff tb units */ |
|
462 |
|
int64_t one_sec; /* in ff tb units */ |
|
463 |
|
int64_t one_msec; /* in ff tb units */ |
377 |
464 |
|
|
378 |
465 |
if (ts < 0) { |
if (ts < 0) { |
379 |
466 |
ts = -ts; |
ts = -ts; |
|
... |
... |
static void cmd_info(void) |
436 |
523 |
snprintf(duration_str, sizeof(duration_str), "%"PRId64, cmd_info_data.fmt.duration); |
snprintf(duration_str, sizeof(duration_str), "%"PRId64, cmd_info_data.fmt.duration); |
437 |
524 |
ts_str = ts_to_str(cmd_info_data.fmt.duration, AV_TIME_BASE_Q, |
ts_str = ts_to_str(cmd_info_data.fmt.duration, AV_TIME_BASE_Q, |
438 |
525 |
&remaining); |
&remaining); |
439 |
|
pout("duration=");RED;POUT("%s", ts_str);RESTORE; |
|
|
526 |
|
pout("duration=");RED;pout("%s", ts_str);RESTORE; |
440 |
527 |
if (remaining != 0) |
if (remaining != 0) |
441 |
528 |
pout(" remaining %"PRId64" av_time_base units\n", remaining); |
pout(" remaining %"PRId64" av_time_base units\n", remaining); |
442 |
529 |
else |
else |
|
... |
... |
static void cmd_info(void) |
449 |
536 |
} else { |
} else { |
450 |
537 |
snprintf(duration_str, sizeof(duration_str), "%"PRId64, cmd_info_data.st.duration); |
snprintf(duration_str, sizeof(duration_str), "%"PRId64, cmd_info_data.st.duration); |
451 |
538 |
ts_str = ts_to_str(cmd_info_data.st.duration, cmd_info_data.st.tb, &remaining); |
ts_str = ts_to_str(cmd_info_data.st.duration, cmd_info_data.st.tb, &remaining); |
452 |
|
pout(";duration=");RED;POUT("%s\n", ts_str);RESTORE; |
|
|
539 |
|
pout(";duration=");RED;pout("%s\n", ts_str);RESTORE; |
453 |
540 |
if (remaining != 0) |
if (remaining != 0) |
454 |
541 |
pout(" remaining %"PRId64" stream time base units\n", remaining); |
pout(" remaining %"PRId64" stream time base units\n", remaining); |
455 |
542 |
else |
else |
|
... |
... |
static void do_reset(void) |
499 |
586 |
u8 i; |
u8 i; |
500 |
587 |
|
|
501 |
588 |
fmt_ctx_lock(); |
fmt_ctx_lock(); |
502 |
|
avformat_flush(fmt_ctx); |
|
503 |
|
avio_flush(fmt_ctx->pb); |
|
|
589 |
|
av_fmt_flush(fmt_ctx); |
|
590 |
|
av_io_flush(fmt_ctx->pb); |
504 |
591 |
fmt_ctx_unlock(); |
fmt_ctx_unlock(); |
505 |
592 |
i = 0; |
i = 0; |
506 |
593 |
loop { |
loop { |
507 |
|
av_packet_unref(cb.pkts[i]); |
|
|
594 |
|
av_pkt_unref(cb.pkts[i]); |
508 |
595 |
if (i == U8_MAX) |
if (i == U8_MAX) |
509 |
596 |
break; |
break; |
510 |
597 |
++i; |
++i; |
|
... |
... |
static void do_reset(void) |
515 |
602 |
} |
} |
516 |
603 |
#undef RESET_DONE |
#undef RESET_DONE |
517 |
604 |
#define DO_RESET 1 |
#define DO_RESET 1 |
|
605 |
|
#define HOLD 1 |
518 |
606 |
static void rd_loop(void) { loop /* infinite loop */ |
static void rd_loop(void) { loop /* infinite loop */ |
519 |
607 |
{ |
{ |
520 |
608 |
int r; |
int r; |
|
... |
... |
static void rd_loop(void) { loop /* infinite loop */ |
523 |
611 |
u8 sd; |
u8 sd; |
524 |
612 |
u8 reset; |
u8 reset; |
525 |
613 |
int st_idx; |
int st_idx; |
|
614 |
|
u8 hold; |
526 |
615 |
/* |
/* |
527 |
616 |
* XXX: we actually perform reset on this thd, with a little lockfree |
* XXX: we actually perform reset on this thd, with a little lockfree |
528 |
617 |
* protocol and reasonable wait loops |
* protocol and reasonable wait loops |
|
... |
... |
static void rd_loop(void) { loop /* infinite loop */ |
531 |
620 |
if (reset == DO_RESET) |
if (reset == DO_RESET) |
532 |
621 |
do_reset(); |
do_reset(); |
533 |
622 |
/*--------------------------------------------------------------------*/ |
/*--------------------------------------------------------------------*/ |
|
623 |
|
hold = atomic_load(&cb.hold); |
|
624 |
|
if (hold == HOLD) { |
|
625 |
|
wait(1000000); /* 1ms */ |
|
626 |
|
continue; |
|
627 |
|
} |
|
628 |
|
/*--------------------------------------------------------------------*/ |
534 |
629 |
rd = atomic_load(&cb.rd); |
rd = atomic_load(&cb.rd); |
535 |
630 |
sd = atomic_load(&cb.sd); |
sd = atomic_load(&cb.sd); |
536 |
631 |
next_rd = rd + 1; |
next_rd = rd + 1; |
|
... |
... |
static void rd_loop(void) { loop /* infinite loop */ |
554 |
649 |
fatal("ffmpeg:error while demuxing coded/compressed data into packets\n"); |
fatal("ffmpeg:error while demuxing coded/compressed data into packets\n"); |
555 |
650 |
else { /* r == 0 */ |
else { /* r == 0 */ |
556 |
651 |
st_idx = atomic_load(&cb.st_idx); |
st_idx = atomic_load(&cb.st_idx); |
557 |
|
if (rd_thd_pkt->stream_index != st_idx) { /* sd_idx can be -1 */ |
|
558 |
|
av_packet_unref(rd_thd_pkt); |
|
|
652 |
|
if (rd_thd_pkt->st_idx != st_idx) { /* sd_idx can be -1 */ |
|
653 |
|
av_pkt_unref(rd_thd_pkt); |
559 |
654 |
continue; |
continue; |
560 |
655 |
} |
} |
561 |
656 |
av_packet_move_ref(cb.pkts[rd], rd_thd_pkt); |
av_packet_move_ref(cb.pkts[rd], rd_thd_pkt); |
|
... |
... |
static void rd_loop(void) { loop /* infinite loop */ |
563 |
658 |
atomic_store(&cb.rd, next_rd); |
atomic_store(&cb.rd, next_rd); |
564 |
659 |
}} |
}} |
565 |
660 |
#undef DO_RESET |
#undef DO_RESET |
|
661 |
|
#undef HOLD |
566 |
662 |
static void *rd_thd_entry(void *arg) |
static void *rd_thd_entry(void *arg) |
567 |
663 |
{ |
{ |
568 |
664 |
int r; |
int r; |
|
... |
... |
static uint64_t pcm_chmaps2ff_chans_layout(snd_pcm_t *pcm, |
646 |
742 |
pout("alsa:your pcm device support channel maps, but fine granularity wiring strategy is not implemented\n"); |
pout("alsa:your pcm device support channel maps, but fine granularity wiring strategy is not implemented\n"); |
647 |
743 |
free(pcm_chmap); |
free(pcm_chmap); |
648 |
744 |
} |
} |
649 |
|
ff_chans_layout = av_get_default_channel_layout((int)pcm_chans_n); |
|
650 |
|
av_get_channel_layout_string(chans_layout_str, sizeof(chans_layout_str), |
|
|
745 |
|
ff_chans_layout = av_get_default_chans_layout((int)pcm_chans_n); |
|
746 |
|
av_get_chan_layout_str(chans_layout_str, sizeof(chans_layout_str), |
651 |
747 |
(int)pcm_chans_n, ff_chans_layout); |
(int)pcm_chans_n, ff_chans_layout); |
652 |
748 |
if (print_info) |
if (print_info) |
653 |
749 |
pout("alsa channel map wired to ffmpeg channel layout:\"%s\" (%u pcm channels)\n", chans_layout_str, pcm_chans_n); |
pout("alsa channel map wired to ffmpeg channel layout:\"%s\" (%u pcm channels)\n", chans_layout_str, pcm_chans_n); |
654 |
750 |
return ff_chans_layout; |
return ff_chans_layout; |
655 |
751 |
} |
} |
656 |
752 |
/* fatal if the wiring cannot be done */ |
/* fatal if the wiring cannot be done */ |
657 |
|
static void pcm_layout2ff_fmt_strict(snd_pcm_format_t alsa_fmt, |
|
658 |
|
snd_pcm_access_t alsa_access, enum AVSampleFormat *ff_fmt, |
|
659 |
|
bool print_info) |
|
|
753 |
|
static void pcm_layout2ff_fmt_strict(snd_pcm_fmt_t alsa_fmt, |
|
754 |
|
snd_pcm_access_t alsa_access, enum av_fr_fmt *ff_fmt, bool print_info) |
660 |
755 |
{ |
{ |
661 |
756 |
/* |
/* |
662 |
757 |
* ff fmt byte order is always native. |
* ff fmt byte order is always native. |
663 |
758 |
* here we handle little endian only |
* here we handle little endian only |
664 |
759 |
*/ |
*/ |
665 |
760 |
switch (alsa_fmt) { |
switch (alsa_fmt) { |
666 |
|
case SND_PCM_FORMAT_FLOAT: |
|
|
761 |
|
case SND_PCM_FMT_FLT: |
667 |
762 |
if (alsa_access == SND_PCM_ACCESS_RW_INTERLEAVED) |
if (alsa_access == SND_PCM_ACCESS_RW_INTERLEAVED) |
668 |
|
*ff_fmt = AV_SAMPLE_FMT_FLT; |
|
|
763 |
|
*ff_fmt = AV_FR_FMT_FLT; |
669 |
764 |
else |
else |
670 |
|
*ff_fmt = AV_SAMPLE_FMT_FLTP; |
|
|
765 |
|
*ff_fmt = AV_FR_FMT_FLTP; |
671 |
766 |
break; |
break; |
672 |
|
case SND_PCM_FORMAT_S32: |
|
|
767 |
|
case SND_PCM_FMT_S32: |
673 |
768 |
if (alsa_access == SND_PCM_ACCESS_RW_INTERLEAVED) |
if (alsa_access == SND_PCM_ACCESS_RW_INTERLEAVED) |
674 |
|
*ff_fmt = AV_SAMPLE_FMT_S32; |
|
|
769 |
|
*ff_fmt = AV_FR_FMT_S32; |
675 |
770 |
else |
else |
676 |
|
*ff_fmt = AV_SAMPLE_FMT_S32P; |
|
|
771 |
|
*ff_fmt = AV_FR_FMT_S32P; |
677 |
772 |
break; |
break; |
678 |
|
case SND_PCM_FORMAT_S16: |
|
|
773 |
|
case SND_PCM_FMT_S16: |
679 |
774 |
if (alsa_access == SND_PCM_ACCESS_RW_INTERLEAVED) |
if (alsa_access == SND_PCM_ACCESS_RW_INTERLEAVED) |
680 |
|
*ff_fmt = AV_SAMPLE_FMT_S16; |
|
|
775 |
|
*ff_fmt = AV_FR_FMT_S16; |
681 |
776 |
else |
else |
682 |
|
*ff_fmt = AV_SAMPLE_FMT_S16P; |
|
|
777 |
|
*ff_fmt = AV_FR_FMT_S16P; |
683 |
778 |
break; |
break; |
684 |
|
case SND_PCM_FORMAT_U8: |
|
|
779 |
|
case SND_PCM_FMT_U8: |
685 |
780 |
if (alsa_access == SND_PCM_ACCESS_RW_INTERLEAVED) |
if (alsa_access == SND_PCM_ACCESS_RW_INTERLEAVED) |
686 |
|
*ff_fmt = AV_SAMPLE_FMT_U8; |
|
|
781 |
|
*ff_fmt = AV_FR_FMT_U8; |
687 |
782 |
else |
else |
688 |
|
*ff_fmt = AV_SAMPLE_FMT_U8P; |
|
|
783 |
|
*ff_fmt = AV_FR_FMT_U8P; |
689 |
784 |
break; |
break; |
690 |
785 |
default: |
default: |
691 |
|
fatal("unable to wire strictly alsa layout \"%s\"/\"%s\" to a ffmpeg format\n", snd_pcm_format_description(alsa_fmt), snd_pcm_access_name(alsa_access)); |
|
|
786 |
|
fatal("unable to wire strictly alsa layout \"%s\"/\"%s\" to a ffmpeg format\n", snd_pcm_fmt_desc(alsa_fmt), snd_pcm_access_name(alsa_access)); |
692 |
787 |
} |
} |
693 |
788 |
if (print_info) { |
if (print_info) { |
694 |
789 |
u8 ff_fmt_str[STR_SZ]; |
u8 ff_fmt_str[STR_SZ]; |
695 |
790 |
|
|
696 |
|
av_get_sample_fmt_string(ff_fmt_str, sizeof(ff_fmt_str), |
|
697 |
|
*ff_fmt); |
|
698 |
|
pout("alsa pcm layout \"%s\"/\"%s\" wired strictly to ffmpeg format \"%sbits\"\n", snd_pcm_format_description(alsa_fmt), snd_pcm_access_name(alsa_access), ff_fmt_str); |
|
|
791 |
|
av_get_fr_fmt_str(ff_fmt_str, sizeof(ff_fmt_str), *ff_fmt); |
|
792 |
|
pout("alsa pcm layout \"%s\"/\"%s\" wired strictly to ffmpeg format \"%sbits\"\n", snd_pcm_fmt_desc(alsa_fmt), snd_pcm_access_name(alsa_access), ff_fmt_str); |
699 |
793 |
} |
} |
700 |
794 |
} |
} |
701 |
|
static void pcm2ff(snd_pcm_t *pcm, enum AVSampleFormat *ff_fmt, |
|
|
795 |
|
static void pcm2ff(snd_pcm_t *pcm, enum av_fr_fmt *ff_fmt, |
702 |
796 |
int *ff_rate, int *ff_chans_n, uint64_t *ff_chans_layout, |
int *ff_rate, int *ff_chans_n, uint64_t *ff_chans_layout, |
703 |
797 |
bool print_info) |
bool print_info) |
704 |
798 |
{ |
{ |
705 |
799 |
int r; |
int r; |
706 |
800 |
snd_pcm_hw_params_t *hw_params; |
snd_pcm_hw_params_t *hw_params; |
707 |
801 |
snd_pcm_access_t pcm_access; |
snd_pcm_access_t pcm_access; |
708 |
|
snd_pcm_format_t pcm_fmt; |
|
|
802 |
|
snd_pcm_fmt_t pcm_fmt; |
709 |
803 |
unsigned int pcm_rate; |
unsigned int pcm_rate; |
710 |
804 |
unsigned int pcm_chans_n; |
unsigned int pcm_chans_n; |
711 |
805 |
|
|
|
... |
... |
static void pcm2ff(snd_pcm_t *pcm, enum AVSampleFormat *ff_fmt, |
718 |
812 |
r = snd_pcm_hw_params_get_access(hw_params, &pcm_access); |
r = snd_pcm_hw_params_get_access(hw_params, &pcm_access); |
719 |
813 |
if (r < 0) |
if (r < 0) |
720 |
814 |
fatal("alsa:unable to get the pcm access for ffmpeg filter wiring\n"); |
fatal("alsa:unable to get the pcm access for ffmpeg filter wiring\n"); |
721 |
|
r = snd_pcm_hw_params_get_format(hw_params, &pcm_fmt); |
|
|
815 |
|
r = snd_pcm_hw_params_get_fmt(hw_params, &pcm_fmt); |
722 |
816 |
if (r < 0) |
if (r < 0) |
723 |
817 |
fatal("alsa:unable to get the pcm format for ffmpeg filter wiring\n"); |
fatal("alsa:unable to get the pcm format for ffmpeg filter wiring\n"); |
724 |
818 |
/*--------------------------------------------------------------------*/ |
/*--------------------------------------------------------------------*/ |
725 |
819 |
pcm_layout2ff_fmt_strict(pcm_fmt, pcm_access, ff_fmt, print_info); |
pcm_layout2ff_fmt_strict(pcm_fmt, pcm_access, ff_fmt, print_info); |
726 |
820 |
/*--------------------------------------------------------------------*/ |
/*--------------------------------------------------------------------*/ |
727 |
821 |
r = snd_pcm_hw_params_get_rate(hw_params, &pcm_rate, |
r = snd_pcm_hw_params_get_rate(hw_params, &pcm_rate, |
728 |
|
SND_PCM_STREAM_PLAYBACK); |
|
|
822 |
|
SND_PCM_ST_PLAYBACK); |
729 |
823 |
if (r < 0) |
if (r < 0) |
730 |
824 |
fatal("alsa:unable to get the pcm rate for ffmpeg filter wiring\n"); |
fatal("alsa:unable to get the pcm rate for ffmpeg filter wiring\n"); |
731 |
825 |
*ff_rate = (int)pcm_rate; |
*ff_rate = (int)pcm_rate; |
732 |
|
r = snd_pcm_hw_params_get_channels(hw_params, &pcm_chans_n); |
|
|
826 |
|
r = snd_pcm_hw_params_get_chans(hw_params, &pcm_chans_n); |
733 |
827 |
if (r < 0) |
if (r < 0) |
734 |
828 |
fatal("alsa:unable to get the pcm count of channels for ffmpeg filter wiring\n"); |
fatal("alsa:unable to get the pcm count of channels for ffmpeg filter wiring\n"); |
735 |
829 |
*ff_chans_n = (int)pcm_chans_n; |
*ff_chans_n = (int)pcm_chans_n; |
|
... |
... |
static void pcm2ff(snd_pcm_t *pcm, enum AVSampleFormat *ff_fmt, |
739 |
833 |
/*--------------------------------------------------------------------*/ |
/*--------------------------------------------------------------------*/ |
740 |
834 |
snd_pcm_hw_params_free(hw_params); |
snd_pcm_hw_params_free(hw_params); |
741 |
835 |
} |
} |
742 |
|
static void abufsrc_cfg(enum AVFrameFormat fmt, int rate, int chans_n, |
|
|
836 |
|
/* XXX: we don't program the tb of the filter since it should not be used */ |
|
837 |
|
static void abufsrc_cfg(enum av_fr_fmt fmt, int rate, int chans_n, |
743 |
838 |
uint64_t chans_layout, bool print_info) |
uint64_t chans_layout, bool print_info) |
744 |
839 |
{ |
{ |
745 |
840 |
int r; |
int r; |
746 |
|
AVRational tb; |
|
747 |
841 |
u8 chans_layout_str[STR_SZ]; /* should be overkill */ |
u8 chans_layout_str[STR_SZ]; /* should be overkill */ |
748 |
842 |
|
|
749 |
|
abufsrc_filt = avfilter_get_by_name("abuffer"); |
|
|
843 |
|
abufsrc_filt = av_filt_get_by_name("abuffer"); |
750 |
844 |
if (abufsrc_filt == 0) |
if (abufsrc_filt == 0) |
751 |
845 |
fatal("audio buffer source:could not find the filter\n"); |
fatal("audio buffer source:could not find the filter\n"); |
752 |
|
abufsrc_ctx = avfilter_graph_alloc_filter(filter_graph, abufsrc_filt, |
|
|
846 |
|
abufsrc_ctx = av_filt_graph_alloc_filt(filt_graph, abufsrc_filt, |
753 |
847 |
"src_abuf"); |
"src_abuf"); |
754 |
848 |
if (abufsrc_ctx == 0) |
if (abufsrc_ctx == 0) |
755 |
849 |
fatal("audio buffer source context:could not allocate the instance in the filter graph\n"); |
fatal("audio buffer source context:could not allocate the instance in the filter graph\n"); |
756 |
|
r = av_opt_set(abufsrc_ctx, "sample_fmt", av_get_frame_fmt_name(fmt), |
|
|
850 |
|
r = av_opt_set(abufsrc_ctx, "sample_fmt", av_get_fr_fmt_name(fmt), |
757 |
851 |
AV_OPT_SEARCH_CHILDREN); |
AV_OPT_SEARCH_CHILDREN); |
758 |
852 |
if (r < 0) |
if (r < 0) |
759 |
853 |
fatal("audio buffer source context:unable to set the decoder frame format option\n"); |
fatal("audio buffer source context:unable to set the decoder frame format option\n"); |
|
... |
... |
static void abufsrc_cfg(enum AVFrameFormat fmt, int rate, int chans_n, |
761 |
855 |
AV_OPT_SEARCH_CHILDREN); |
AV_OPT_SEARCH_CHILDREN); |
762 |
856 |
if (r < 0) |
if (r < 0) |
763 |
857 |
fatal("audio buffer source context:unable to set the decoder rate option\n"); |
fatal("audio buffer source context:unable to set the decoder rate option\n"); |
764 |
|
av_get_channel_layout_string(chans_layout_str, sizeof(chans_layout_str), |
|
|
858 |
|
av_get_chan_layout_str(chans_layout_str, sizeof(chans_layout_str), |
765 |
859 |
chans_n, chans_layout); |
chans_n, chans_layout); |
766 |
860 |
if (print_info) |
if (print_info) |
767 |
861 |
pout("audio buffer source context:using channels layout \"%s\" (%d pcm channels)\n", chans_layout_str, chans_n); |
pout("audio buffer source context:using channels layout \"%s\" (%d pcm channels)\n", chans_layout_str, chans_n); |
|
... |
... |
static void abufsrc_cfg(enum AVFrameFormat fmt, int rate, int chans_n, |
769 |
863 |
AV_OPT_SEARCH_CHILDREN); |
AV_OPT_SEARCH_CHILDREN); |
770 |
864 |
if (r < 0) |
if (r < 0) |
771 |
865 |
fatal("audio buffer source context:unable to set the decoder channel layout option\n"); |
fatal("audio buffer source context:unable to set the decoder channel layout option\n"); |
772 |
|
r = avfilter_init_str(abufsrc_ctx, 0); |
|
|
866 |
|
r = av_filt_init_str(abufsrc_ctx, 0); |
773 |
867 |
if (r < 0) |
if (r < 0) |
774 |
868 |
fatal("audio buffer source context:unable to initialize\n"); |
fatal("audio buffer source context:unable to initialize\n"); |
775 |
869 |
} |
} |
|
... |
... |
static void vol_cfg(bool muted, double vol) |
779 |
873 |
u8 vol_l10n_str[sizeof("xxx.xx")]; /* should be overkill */ |
u8 vol_l10n_str[sizeof("xxx.xx")]; /* should be overkill */ |
780 |
874 |
int r; |
int r; |
781 |
875 |
|
|
782 |
|
vol_filt = avfilter_get_by_name("volume"); |
|
|
876 |
|
vol_filt = av_filt_get_by_name("volume"); |
783 |
877 |
if (vol_filt == 0) |
if (vol_filt == 0) |
784 |
878 |
fatal("volume:could not find the filter\n"); |
fatal("volume:could not find the filter\n"); |
785 |
|
vol_ctx = avfilter_graph_alloc_filter(filter_graph, vol_filt, "vol"); |
|
|
879 |
|
vol_ctx = av_filt_graph_alloc_filt(filt_graph, vol_filt, "vol"); |
786 |
880 |
if (vol_ctx == 0) |
if (vol_ctx == 0) |
787 |
881 |
fatal("volume context:could not allocate the instance in the filter graph\n"); |
fatal("volume context:could not allocate the instance in the filter graph\n"); |
788 |
882 |
if (muted) |
if (muted) |
|
... |
... |
static void vol_cfg(bool muted, double vol) |
794 |
888 |
r = av_opt_set(vol_ctx, "volume", vol_l10n_str, AV_OPT_SEARCH_CHILDREN); |
r = av_opt_set(vol_ctx, "volume", vol_l10n_str, AV_OPT_SEARCH_CHILDREN); |
795 |
889 |
if (r < 0) |
if (r < 0) |
796 |
890 |
fatal("volume context:unable to set the volume option\n"); |
fatal("volume context:unable to set the volume option\n"); |
797 |
|
r = avfilter_init_str(vol_ctx, 0); |
|
|
891 |
|
r = av_filt_init_str(vol_ctx, 0); |
798 |
892 |
if (r < 0) |
if (r < 0) |
799 |
893 |
fatal("volume buffer context:unable to initialize\n"); |
fatal("volume buffer context:unable to initialize\n"); |
800 |
894 |
} |
} |
801 |
|
static void afmt_cfg(enum AVFrameFormat fmt, int rate, int chans_n, |
|
|
895 |
|
static void afmt_cfg(enum av_fr_fmt fmt, int rate, int chans_n, |
802 |
896 |
uint64_t chans_layout, bool print_info) |
uint64_t chans_layout, bool print_info) |
803 |
897 |
{ |
{ |
804 |
898 |
int r; |
int r; |
805 |
899 |
u8 rate_str[sizeof("dddddd")]; |
u8 rate_str[sizeof("dddddd")]; |
806 |
900 |
u8 chans_layout_str[STR_SZ]; /* should be overkill */ |
u8 chans_layout_str[STR_SZ]; /* should be overkill */ |
807 |
901 |
|
|
808 |
|
afmt_filt = avfilter_get_by_name("aformat"); |
|
|
902 |
|
afmt_filt = av_filt_get_by_name("aformat"); |
809 |
903 |
if (afmt_filt == 0) |
if (afmt_filt == 0) |
810 |
904 |
fatal("audio format:could not find the filter"); |
fatal("audio format:could not find the filter"); |
811 |
|
afmt_ctx = avfilter_graph_alloc_filter(filter_graph, afmt_filt, "afmt"); |
|
|
905 |
|
afmt_ctx = av_filt_graph_alloc_filt(filt_graph, afmt_filt, "afmt"); |
812 |
906 |
if (afmt_ctx == 0) |
if (afmt_ctx == 0) |
813 |
907 |
fatal("audio format:could not allocate the instance in the filter graph\n"); |
fatal("audio format:could not allocate the instance in the filter graph\n"); |
814 |
|
r = av_opt_set(afmt_ctx, "sample_fmts", av_get_frame_fmt_name(fmt), |
|
|
908 |
|
r = av_opt_set(afmt_ctx, "sample_fmts", av_get_fr_fmt_name(fmt), |
815 |
909 |
AV_OPT_SEARCH_CHILDREN); |
AV_OPT_SEARCH_CHILDREN); |
816 |
910 |
if (r < 0) |
if (r < 0) |
817 |
911 |
fatal("audio format context:could to set the pcm sample format\n"); |
fatal("audio format context:could to set the pcm sample format\n"); |
|
... |
... |
static void afmt_cfg(enum AVFrameFormat fmt, int rate, int chans_n, |
820 |
914 |
AV_OPT_SEARCH_CHILDREN); |
AV_OPT_SEARCH_CHILDREN); |
821 |
915 |
if (r < 0) |
if (r < 0) |
822 |
916 |
fatal("audio format context:could not set the pcm rate\n"); |
fatal("audio format context:could not set the pcm rate\n"); |
823 |
|
av_get_channel_layout_string(chans_layout_str, sizeof(chans_layout_str), |
|
|
917 |
|
av_get_chan_layout_str(chans_layout_str, sizeof(chans_layout_str), |
824 |
918 |
chans_n, chans_layout); |
chans_n, chans_layout); |
825 |
919 |
r = av_opt_set(afmt_ctx, "channel_layouts", chans_layout_str, |
r = av_opt_set(afmt_ctx, "channel_layouts", chans_layout_str, |
826 |
920 |
AV_OPT_SEARCH_CHILDREN); |
AV_OPT_SEARCH_CHILDREN); |
|
... |
... |
static void afmt_cfg(enum AVFrameFormat fmt, int rate, int chans_n, |
828 |
922 |
fatal("audio format context:could not set the layout of channels\n"); |
fatal("audio format context:could not set the layout of channels\n"); |
829 |
923 |
if (print_info) |
if (print_info) |
830 |
924 |
pout("audio format context:channel layout is \"%s\"\n", chans_layout_str); |
pout("audio format context:channel layout is \"%s\"\n", chans_layout_str); |
831 |
|
r = avfilter_init_str(afmt_ctx, 0); |
|
|
925 |
|
r = av_filt_init_str(afmt_ctx, 0); |
832 |
926 |
if (r < 0) |
if (r < 0) |
833 |
927 |
fatal("audio format context:unable to initialize\n"); |
fatal("audio format context:unable to initialize\n"); |
834 |
928 |
} |
} |
|
... |
... |
static void abufsink_cfg(void) |
836 |
930 |
{ |
{ |
837 |
931 |
int r; |
int r; |
838 |
932 |
|
|
839 |
|
abufsink_filt = avfilter_get_by_name("abuffersink"); |
|
|
933 |
|
abufsink_filt = av_filt_get_by_name("abuffersink"); |
840 |
934 |
if (abufsink_filt == 0) |
if (abufsink_filt == 0) |
841 |
935 |
fatal("audio buffer sink:could not find the filter\n"); |
fatal("audio buffer sink:could not find the filter\n"); |
842 |
|
abufsink_ctx = avfilter_graph_alloc_filter(filter_graph, abufsink_filt, |
|
|
936 |
|
abufsink_ctx = av_filt_graph_alloc_filt(filt_graph, abufsink_filt, |
843 |
937 |
"sink_abuf"); |
"sink_abuf"); |
844 |
938 |
if (abufsink_ctx == 0) |
if (abufsink_ctx == 0) |
845 |
939 |
fatal("audio buffer sink context:could not allocate the instance in the filter graph\n"); |
fatal("audio buffer sink context:could not allocate the instance in the filter graph\n"); |
846 |
|
r = avfilter_init_str(abufsink_ctx, 0); |
|
|
940 |
|
r = av_filt_init_str(abufsink_ctx, 0); |
847 |
941 |
if (r < 0) |
if (r < 0) |
848 |
942 |
fatal("audio buffer sink context:unable to initialize\n"); |
fatal("audio buffer sink context:unable to initialize\n"); |
849 |
943 |
} |
} |
|
... |
... |
static void dec_ctx_cfg(AVCodecParameters *params) |
868 |
962 |
if (r < 0) |
if (r < 0) |
869 |
963 |
fatal("ffmpeg:unable to open the decoder context\n"); |
fatal("ffmpeg:unable to open the decoder context\n"); |
870 |
964 |
} |
} |
871 |
|
static void filter_graph_cfg( |
|
872 |
|
enum AVSampleFormat src_fmt, int src_rate, int src_chans_n, |
|
|
965 |
|
static void filt_graph_cfg( |
|
966 |
|
enum av_fr_fmt src_fmt, int src_rate, int src_chans_n, |
873 |
967 |
uint64_t src_chans_layout, |
uint64_t src_chans_layout, |
874 |
968 |
bool muted, double vol, |
bool muted, double vol, |
875 |
|
enum AVSampleFormat dst_fmt, int dst_rate, int dst_chans_n, |
|
|
969 |
|
enum av_fr_fmt dst_fmt, int dst_rate, int dst_chans_n, |
876 |
970 |
uint64_t dst_chans_layout, bool print_info) |
uint64_t dst_chans_layout, bool print_info) |
877 |
971 |
{ |
{ |
878 |
972 |
int r; |
int r; |
879 |
973 |
char *dump_str; |
char *dump_str; |
880 |
974 |
|
|
881 |
|
avfilter_graph_free(&filter_graph); |
|
|
975 |
|
av_filt_graph_free(&filt_graph); |
882 |
976 |
|
|
883 |
|
filter_graph = avfilter_graph_alloc(); |
|
884 |
|
if (filter_graph == 0) |
|
|
977 |
|
filt_graph = av_filt_graph_alloc(); |
|
978 |
|
if (filt_graph == 0) |
885 |
979 |
fatal("unable to create filter graph\n"); |
fatal("unable to create filter graph\n"); |
886 |
980 |
abufsrc_cfg(src_fmt, src_rate, src_chans_n, src_chans_layout, |
abufsrc_cfg(src_fmt, src_rate, src_chans_n, src_chans_layout, |
887 |
981 |
print_info); |
print_info); |
|
982 |
|
/*--------------------------------------------------------------------*/ |
|
983 |
|
abufsrc_key.chans_n = src_chans_n; |
|
984 |
|
abufsrc_key.chans_layout = src_chans_layout; |
|
985 |
|
abufsrc_key.rate = src_rate; |
|
986 |
|
abufsrc_key.fmt = src_fmt; |
|
987 |
|
/*--------------------------------------------------------------------*/ |
888 |
988 |
vol_cfg(muted, vol); |
vol_cfg(muted, vol); |
889 |
989 |
afmt_cfg(dst_fmt, dst_rate, dst_chans_n, dst_chans_layout, print_info); |
afmt_cfg(dst_fmt, dst_rate, dst_chans_n, dst_chans_layout, print_info); |
890 |
990 |
abufsink_cfg(); |
abufsink_cfg(); |
891 |
|
r = avfilter_link(abufsrc_ctx, 0, vol_ctx, 0); |
|
|
991 |
|
r = av_filt_link(abufsrc_ctx, 0, vol_ctx, 0); |
892 |
992 |
if (r < 0) |
if (r < 0) |
893 |
993 |
fatal("unable to connect the audio buffer source filter to the volume filter\n"); |
fatal("unable to connect the audio buffer source filter to the volume filter\n"); |
894 |
|
r = avfilter_link(vol_ctx, 0, afmt_ctx, 0); |
|
|
994 |
|
r = av_filt_link(vol_ctx, 0, afmt_ctx, 0); |
895 |
995 |
if (r < 0) |
if (r < 0) |
896 |
996 |
fatal("unable to connect the volume filter to the audio format filter\n"); |
fatal("unable to connect the volume filter to the audio format filter\n"); |
897 |
|
r = avfilter_link(afmt_ctx, 0, abufsink_ctx, 0); |
|
|
997 |
|
r = av_filt_link(afmt_ctx, 0, abufsink_ctx, 0); |
898 |
998 |
if (r < 0) |
if (r < 0) |
899 |
999 |
fatal("unable to connect the audio format filter to the audio buffer sink filter\n"); |
fatal("unable to connect the audio format filter to the audio buffer sink filter\n"); |
900 |
|
r = avfilter_graph_config(filter_graph, 0); |
|
|
1000 |
|
r = av_filt_graph_cfg(filt_graph, 0); |
901 |
1001 |
if (r < 0) |
if (r < 0) |
902 |
1002 |
fatal("unable to configure the filter graph\n"); |
fatal("unable to configure the filter graph\n"); |
903 |
1003 |
/*--------------------------------------------------------------------*/ |
/*--------------------------------------------------------------------*/ |
904 |
1004 |
if (!print_info) |
if (!print_info) |
905 |
1005 |
return; |
return; |
906 |
|
dump_str = avfilter_graph_dump(filter_graph, 0); |
|
|
1006 |
|
dump_str = av_filt_graph_dump(filt_graph, 0); |
907 |
1007 |
if (dump_str == 0) { |
if (dump_str == 0) { |
908 |
1008 |
warning("unable to get a filter graph description\n"); |
warning("unable to get a filter graph description\n"); |
909 |
1009 |
return; |
return; |
|
... |
... |
static void filter_graph_cfg( |
916 |
1016 |
#define DONT_PRINT_INFO false |
#define DONT_PRINT_INFO false |
917 |
1017 |
static void filt_flush(void) |
static void filt_flush(void) |
918 |
1018 |
{ |
{ |
919 |
|
enum AVSampleFormat dst_fmt; |
|
|
1019 |
|
enum av_fr_fmt dst_fmt; |
920 |
1020 |
int dst_rate; |
int dst_rate; |
921 |
1021 |
int dst_chans_n; |
int dst_chans_n; |
922 |
1022 |
uint64_t src_chans_layout; |
uint64_t src_chans_layout; |
923 |
1023 |
uint64_t dst_chans_layout; |
uint64_t dst_chans_layout; |
924 |
1024 |
|
|
925 |
|
av_frames_unref(filt_frs.av); |
|
|
1025 |
|
av_frs_unref(filt_frs.av); |
926 |
1026 |
filt_frs.pcm_written_ufrs_n = 0; |
filt_frs.pcm_written_ufrs_n = 0; |
927 |
1027 |
|
|
928 |
1028 |
pcm2ff(pcm_g, &dst_fmt, &dst_rate, &dst_chans_n, &dst_chans_layout, |
pcm2ff(pcm_g, &dst_fmt, &dst_rate, &dst_chans_n, &dst_chans_layout, |
929 |
1029 |
DONT_PRINT_INFO); |
DONT_PRINT_INFO); |
930 |
1030 |
/* the audio dec ctx may not have a valid chans layout */ |
/* the audio dec ctx may not have a valid chans layout */ |
931 |
|
if (dec_ctx->channel_layout == 0) { |
|
932 |
|
src_chans_layout = av_get_default_channel_layout( |
|
933 |
|
dec_ctx->channels); |
|
|
1031 |
|
if (dec_ctx->chans_layout == 0) { |
|
1032 |
|
src_chans_layout = av_get_default_chans_layout(dec_ctx->chans_n); |
934 |
1033 |
} else |
} else |
935 |
|
src_chans_layout = dec_ctx->channel_layout; |
|
936 |
|
filter_graph_cfg( |
|
937 |
|
dec_ctx->sample_fmt, dec_ctx->sample_rate, |
|
938 |
|
dec_ctx->channels, src_chans_layout, |
|
|
1034 |
|
src_chans_layout = dec_ctx->chans_layout; |
|
1035 |
|
filt_graph_cfg( |
|
1036 |
|
dec_ctx->fr_fmt, dec_ctx->fr_rate, |
|
1037 |
|
dec_ctx->chans_n, src_chans_layout, |
939 |
1038 |
filt_frs.muted, filt_frs.vol, |
filt_frs.muted, filt_frs.vol, |
940 |
1039 |
dst_fmt, dst_rate, dst_chans_n, dst_chans_layout, |
dst_fmt, dst_rate, dst_chans_n, dst_chans_layout, |
941 |
1040 |
DONT_PRINT_INFO); |
DONT_PRINT_INFO); |
|
... |
... |
static void dec_fill(void) { loop |
1297 |
1396 |
/* at start, we must read pkt before we can send one */ |
/* at start, we must read pkt before we can send one */ |
1298 |
1397 |
if (rd == sd) |
if (rd == sd) |
1299 |
1398 |
break; |
break; |
1300 |
|
r = avcodec_send_packet(dec_ctx, cb.pkts[sd]); |
|
|
1399 |
|
r = av_sd_pkt(dec_ctx, cb.pkts[sd]); |
1301 |
1400 |
/* dec is full and the pkt was rejected, or the decoder is in EOF */ |
/* dec is full and the pkt was rejected, or the decoder is in EOF */ |
1302 |
1401 |
if (r == AVERROR(EAGAIN) || r == AVERROR_EOF) |
if (r == AVERROR(EAGAIN) || r == AVERROR_EOF) |
1303 |
1402 |
break; |
break; |
1304 |
1403 |
else if (r != 0) |
else if (r != 0) |
1305 |
1404 |
fatal("ffmpeg:error while sending the packet to the decoder\n"); |
fatal("ffmpeg:error while sending the packet to the decoder\n"); |
1306 |
1405 |
/* r == 0 */ |
/* r == 0 */ |
1307 |
|
av_packet_unref(cb.pkts[sd]); |
|
|
1406 |
|
av_pkt_unref(cb.pkts[sd]); |
1308 |
1407 |
next_sd = sd + 1; |
next_sd = sd + 1; |
1309 |
1408 |
atomic_store(&cb.sd, next_sd); |
atomic_store(&cb.sd, next_sd); |
1310 |
1409 |
}} |
}} |
1311 |
|
/* |
|
1312 |
|
* return true if we have 1 dec_frs.av, false if no more dec_frs.av |
|
1313 |
|
* will come |
|
1314 |
|
*/ |
|
1315 |
|
static bool dec_frs_get(void) { loop |
|
|
1410 |
|
static void dec_frs_get(void) { loop |
1316 |
1411 |
{ |
{ |
1317 |
1412 |
int r; |
int r; |
1318 |
1413 |
|
|
1319 |
1414 |
dec_fill(); |
dec_fill(); |
1320 |
1415 |
|
|
1321 |
1416 |
/* will unref the dec_frs.av bufs for us */ |
/* will unref the dec_frs.av bufs for us */ |
1322 |
|
r = avcodec_receive_frames(dec_ctx, dec_frs.av); |
|
|
1417 |
|
r = av_receive_frs(dec_ctx, dec_frs.av); |
1323 |
1418 |
if (r == AVERROR(EAGAIN)) |
if (r == AVERROR(EAGAIN)) |
1324 |
1419 |
continue; |
continue; |
1325 |
1420 |
else if (r == 0) { |
else if (r == 0) { |
|
... |
... |
static bool dec_frs_get(void) { loop |
1329 |
1424 |
dec_frs.most_recent_ts = dec_frs.av->pkt_dts; |
dec_frs.most_recent_ts = dec_frs.av->pkt_dts; |
1330 |
1425 |
else |
else |
1331 |
1426 |
dec_frs.most_recent_ts = dec_frs.av->pkt_dts; |
dec_frs.most_recent_ts = dec_frs.av->pkt_dts; |
1332 |
|
return true; /* "return" the current dec_frs.av */ |
|
|
1427 |
|
dec_frs.pushed_in_filt_graph = false; |
|
1428 |
|
return; /* "return" the current dec_frs.av */ |
1333 |
1429 |
} else if (r == AVERROR_EOF) { |
} else if (r == AVERROR_EOF) { |
1334 |
1430 |
pout("ffmpeg:last decoder frames reached (receiving)\n"); |
pout("ffmpeg:last decoder frames reached (receiving)\n"); |
1335 |
|
return false; |
|
|
1431 |
|
loop { /* spinning */ |
|
1432 |
|
snd_pcm_state_t state; |
|
1433 |
|
|
|
1434 |
|
r = snd_pcm_drain(pcm_g); |
|
1435 |
|
if (r == 0) |
|
1436 |
|
break; |
|
1437 |
|
if (r == -EAGAIN) |
|
1438 |
|
continue; |
|
1439 |
|
/* |
|
1440 |
|
* the pcm state can change asynchronously. |
|
1441 |
|
* _old_ behavior: |
|
1442 |
|
* if the draining was successful, the pcm |
|
1443 |
|
* should be in SETUP state, and in this |
|
1444 |
|
* state, snd_pcm_drain will fail |
|
1445 |
|
* _new and fixed__ behavior: |
|
1446 |
|
* this won't happen because calling |
|
1447 |
|
* snd_pcm_drain while in the SETUP state |
|
1448 |
|
* won't return an error anymore |
|
1449 |
|
*/ |
|
1450 |
|
state = snd_pcm_state(pcm_g); |
|
1451 |
|
if (state == SND_PCM_STATE_SETUP) |
|
1452 |
|
break; |
|
1453 |
|
} |
|
1454 |
|
/**********************************************/ |
|
1455 |
|
exit_ok("finished playing\n"); |
|
1456 |
|
/**********************************************/ |
1336 |
1457 |
} |
} |
1337 |
1458 |
fatal("ffmpeg:error while receiving frames from the decoder\n"); |
fatal("ffmpeg:error while receiving frames from the decoder\n"); |
1338 |
1459 |
}} |
}} |
1339 |
|
static bool filt_frs_get(void) { loop |
|
|
1460 |
|
static bool is_recfg_required(av_frs *frs) |
|
1461 |
|
{ |
|
1462 |
|
if ( frs->chans_n != abufsrc_key.chans_n |
|
1463 |
|
|| frs->chans_layout != abufsrc_key.chans_layout |
|
1464 |
|
|| frs->fr_rate != abufsrc_key.rate |
|
1465 |
|
|| frs->fmt != abufsrc_key.fmt) |
|
1466 |
|
return true; |
|
1467 |
|
return false; |
|
1468 |
|
} |
|
1469 |
|
#define AGAIN 0 |
|
1470 |
|
#define PUSHED 1 |
|
1471 |
|
#define FILT_RECFG_REQUIRED 2 |
|
1472 |
|
static u8 filt_graph_push_dec_frs(int *new_chans_n, uint64_t *new_chans_layout, |
|
1473 |
|
int *new_fr_rate, enum av_fr_fmt *new_fmt) |
1340 |
1474 |
{ |
{ |
1341 |
1475 |
int r; |
int r; |
1342 |
1476 |
|
|
1343 |
|
if (!filt_frs.no_more_dec_frs) { |
|
1344 |
|
if(!dec_frs_get()) { |
|
1345 |
|
filt_frs.no_more_dec_frs = true; |
|
1346 |
|
|
|
1347 |
|
r = av_buffersrc_add_frame_flags(abufsrc_ctx, |
|
1348 |
|
0 , AV_BUFFERSRC_FLAG_PUSH |
|
1349 |
|
| AV_BUFFERSRC_FLAG_KEEP_REF); |
|
1350 |
|
if (r < 0) |
|
1351 |
|
fatal("ffmpeg:unable to notify the end of data to the filter source audio buffer context\n"); |
|
1352 |
|
} else { |
|
1353 |
|
/* |
|
1354 |
|
* the dec_frs bufs will be unref in |
|
1355 |
|
* avcodec_receive_frames |
|
1356 |
|
*/ |
|
1357 |
|
r = av_buffersrc_add_frame_flags(abufsrc_ctx, |
|
1358 |
|
dec_frs.av, AV_BUFFERSRC_FLAG_PUSH |
|
1359 |
|
| AV_BUFFERSRC_FLAG_KEEP_REF); |
|
1360 |
|
if (r < 0) |
|
1361 |
|
fatal("ffmpeg:unable to submit the decoder frames to the filter source audio buffer context\n"); |
|
1362 |
|
} |
|
|
1477 |
|
if (dec_frs.pushed_in_filt_graph) |
|
1478 |
|
dec_frs_get(); |
|
1479 |
|
if (dec_frs.av->chans_layout == 0) /* choose one for the filt */ |
|
1480 |
|
dec_frs.av->chans_layout = av_get_default_chans_layout( |
|
1481 |
|
dec_frs.av->chans_n); |
|
1482 |
|
if (is_recfg_required(dec_frs.av)) { |
|
1483 |
|
*new_chans_n = dec_frs.av->chans_n; |
|
1484 |
|
*new_chans_layout = dec_frs.av->chans_layout; |
|
1485 |
|
*new_fr_rate = dec_frs.av->fr_rate; |
|
1486 |
|
*new_fmt = dec_frs.av->fmt; |
|
1487 |
|
return FILT_RECFG_REQUIRED; |
1363 |
1488 |
} |
} |
1364 |
|
/* |
|
1365 |
|
* the last dec_frs should switch the filter in draining mode, |
|
1366 |
|
* and filt_frs.av won't matter. |
|
1367 |
|
*/ |
|
1368 |
|
r = av_buffersink_get_frame(abufsink_ctx, filt_frs.av); |
|
1369 |
|
if (r == AVERROR(EAGAIN)) { |
|
1370 |
|
/* |
|
1371 |
|
* won't happen if no more dec frs are available thanks |
|
1372 |
|
* to eof propagation along the processing graph, in theory |
|
1373 |
|
*/ |
|
1374 |
|
continue; |
|
1375 |
|
} else if (r >= 0) { |
|
|
1489 |
|
/* the dec_frs.av bufs will be unref in av_receive_frs */ |
|
1490 |
|
r = av_bufsrc_add_frs_flags(abufsrc_ctx, dec_frs.av, |
|
1491 |
|
AV_BUFSRC_FLAG_KEEP_REF); |
|
1492 |
|
if (r >= 0) { |
|
1493 |
|
dec_frs.pushed_in_filt_graph = true; |
|
1494 |
|
return PUSHED; |
|
1495 |
|
} else if (r == AVERROR(EAGAIN)) |
|
1496 |
|
return AGAIN; |
|
1497 |
|
fatal("ffmpeg:unable to submit a decoder set of frames to the filter source audio buffer context\n"); |
|
1498 |
|
} |
|
1499 |
|
#undef AGAIN |
|
1500 |
|
#undef PUSHED |
|
1501 |
|
#undef FILT_RECFG_REQUIRED |
|
1502 |
|
static void filt_frs_get(void) |
|
1503 |
|
{ |
|
1504 |
|
int r; |
|
1505 |
|
|
|
1506 |
|
r = av_bufsink_get_frs(abufsink_ctx, filt_frs.av); |
|
1507 |
|
if (r >= 0) { |
1376 |
1508 |
filt_frs.pcm_written_ufrs_n = 0; |
filt_frs.pcm_written_ufrs_n = 0; |
1377 |
|
return true; |
|
1378 |
|
} else if (r == AVERROR_EOF) { |
|
1379 |
|
pout("ffmpeg:last filter frs reached (getting)\n"); |
|
1380 |
|
return false; |
|
|
1509 |
|
return; |
1381 |
1510 |
} |
} |
1382 |
|
fatal("ffmpeg:error while getting frs from the filter\n"); |
|
1383 |
|
}} |
|
|
1511 |
|
fatal("ffmpeg:error while getting frames from the filter\n"); |
|
1512 |
|
} |
|
1513 |
|
#define FILT_RECFG_REQUIRED 2 |
|
1514 |
|
#define EOF_FILT 2 |
|
1515 |
|
#define DRAINING 3 |
|
1516 |
|
#define HAVE_FILT_SET 1 |
|
1517 |
|
#define PRINT_INFO true |
|
1518 |
|
/* synchronous filtering */ |
|
1519 |
|
static void dec_frs_filter(void) |
|
1520 |
|
{ |
|
1521 |
|
loop { |
|
1522 |
|
u8 r; |
|
1523 |
|
int new_chans_n; |
|
1524 |
|
uint64_t new_chans_layout; |
|
1525 |
|
int new_fr_rate; |
|
1526 |
|
enum av_fr_fmt new_fmt; |
|
1527 |
|
int dst_chans_n; |
|
1528 |
|
uint64_t dst_chans_layout; |
|
1529 |
|
int dst_rate; |
|
1530 |
|
enum av_fr_fmt dst_fmt; |
|
1531 |
|
|
|
1532 |
|
r = filt_graph_push_dec_frs(&new_chans_n, &new_chans_layout, |
|
1533 |
|
&new_fr_rate, &new_fmt); |
|
1534 |
|
if (r != FILT_RECFG_REQUIRED) { |
|
1535 |
|
/* PUSHED | AGAIN */ |
|
1536 |
|
break; |
|
1537 |
|
} |
|
1538 |
|
/* FILT_RECFG_REQUIRED */ |
|
1539 |
|
pcm2ff(pcm_g, &dst_fmt, &dst_rate, &dst_chans_n, |
|
1540 |
|
&dst_chans_layout, PRINT_INFO); |
|
1541 |
|
filt_graph_cfg( |
|
1542 |
|
new_fmt, new_fr_rate, new_chans_n, new_chans_layout, |
|
1543 |
|
filt_frs.muted, filt_frs.vol, |
|
1544 |
|
dst_fmt, dst_rate, dst_chans_n, dst_chans_layout, |
|
1545 |
|
PRINT_INFO); |
|
1546 |
|
} |
|
1547 |
|
filt_frs_get(); |
|
1548 |
|
} |
|
1549 |
|
#undef FILT_RECFG_REQUIRED |
|
1550 |
|
#undef EOF_FILT |
|
1551 |
|
#undef DRAINING |
|
1552 |
|
#undef HAVE_FILT_SET |
|
1553 |
|
#undef PRINT_INFO |
1384 |
1554 |
#define NO 0 |
#define NO 0 |
1385 |
1555 |
static void chans_buf_init(u8 **chans_buf, int start_fr_idx) |
static void chans_buf_init(u8 **chans_buf, int start_fr_idx) |
1386 |
1556 |
{ |
{ |
1387 |
1557 |
int is_planar_fmt; |
int is_planar_fmt; |
1388 |
1558 |
int sample_bytes_n; |
int sample_bytes_n; |
1389 |
1559 |
|
|
1390 |
|
sample_bytes_n = av_get_bytes_per_sample(filt_frs.av->format); |
|
|
1560 |
|
sample_bytes_n = av_get_bytes_per_sample(filt_frs.av->fmt); |
1391 |
1561 |
|
|
1392 |
|
is_planar_fmt = av_frame_fmt_is_planar(filt_frs.av->format); |
|
|
1562 |
|
is_planar_fmt = av_fr_fmt_is_planar(filt_frs.av->fmt); |
1393 |
1563 |
if (is_planar_fmt == NO) { /* or is pcm interleaved */ |
if (is_planar_fmt == NO) { /* or is pcm interleaved */ |
1394 |
1564 |
int fr_bytes_n; |
int fr_bytes_n; |
1395 |
1565 |
|
|
1396 |
|
fr_bytes_n = sample_bytes_n * filt_frs.av->channels; |
|
|
1566 |
|
fr_bytes_n = sample_bytes_n * filt_frs.av->chans_n; |
1397 |
1567 |
chans_buf[0] = (u8*)filt_frs.av->data[0] + start_fr_idx |
chans_buf[0] = (u8*)filt_frs.av->data[0] + start_fr_idx |
1398 |
1568 |
* fr_bytes_n; |
* fr_bytes_n; |
1399 |
|
} else { /* ffmpeg planar or pcm noninterleaved */ |
|
|
1569 |
|
} else { /* ff planar or pcm noninterleaved */ |
1400 |
1570 |
int p; |
int p; |
1401 |
1571 |
|
|
1402 |
1572 |
p = 0; |
p = 0; |
1403 |
1573 |
loop { |
loop { |
1404 |
|
if (p == filt_frs.av->channels) |
|
|
1574 |
|
if (p == filt_frs.av->chans_n) |
1405 |
1575 |
break; |
break; |
1406 |
1576 |
chans_buf[p] = (u8*)filt_frs.av->data[p] |
chans_buf[p] = (u8*)filt_frs.av->data[p] |
1407 |
1577 |
+ start_fr_idx * sample_bytes_n; |
+ start_fr_idx * sample_bytes_n; |
|
... |
... |
static void chans_buf_inc(u8 **chans_buf, int frs_inc) |
1416 |
1586 |
int is_planar_fmt; |
int is_planar_fmt; |
1417 |
1587 |
int sample_bytes_n; |
int sample_bytes_n; |
1418 |
1588 |
|
|
1419 |
|
sample_bytes_n = av_get_bytes_per_sample(filt_frs.av->format); |
|
|
1589 |
|
sample_bytes_n = av_get_bytes_per_sample(filt_frs.av->fmt); |
1420 |
1590 |
|
|
1421 |
|
is_planar_fmt = av_frame_fmt_is_planar(filt_frs.av->format); |
|
|
1591 |
|
is_planar_fmt = av_fr_fmt_is_planar(filt_frs.av->fmt); |
1422 |
1592 |
if (is_planar_fmt == NO) { /* or is pcm interleaved */ |
if (is_planar_fmt == NO) { /* or is pcm interleaved */ |
1423 |
1593 |
int fr_bytes_n; |
int fr_bytes_n; |
1424 |
1594 |
|
|
1425 |
|
fr_bytes_n = sample_bytes_n * filt_frs.av->channels; |
|
|
1595 |
|
fr_bytes_n = sample_bytes_n * filt_frs.av->chans_n; |
1426 |
1596 |
chans_buf[0] += frs_inc * fr_bytes_n; |
chans_buf[0] += frs_inc * fr_bytes_n; |
1427 |
|
} else { /* ffmpeg planar or pcm noninterleaved */ |
|
|
1597 |
|
} else { /* ff planar or pcm noninterleaved */ |
1428 |
1598 |
u8 p; |
u8 p; |
1429 |
1599 |
|
|
1430 |
1600 |
p = 0; |
p = 0; |
1431 |
1601 |
loop { |
loop { |
1432 |
|
if (p == filt_frs.av->channels) |
|
|
1602 |
|
if (p == filt_frs.av->chans_n) |
1433 |
1603 |
break; |
break; |
1434 |
1604 |
chans_buf[p] += frs_inc * sample_bytes_n; |
chans_buf[p] += frs_inc * sample_bytes_n; |
1435 |
1605 |
++p; |
++p; |
|
... |
... |
static void chans_buf_inc(u8 **chans_buf, int frs_inc) |
1438 |
1608 |
} |
} |
1439 |
1609 |
#undef NO |
#undef NO |
1440 |
1610 |
#define NO 0 |
#define NO 0 |
1441 |
|
static void pcm_silence_frs_write(snd_pcm_uframes_t ufrs_n) |
|
|
1611 |
|
static void pcm_silence_frs_write(snd_pcm_ufrs_t ufrs_n) |
1442 |
1612 |
{ |
{ |
1443 |
1613 |
int is_planar_fmt; |
int is_planar_fmt; |
1444 |
1614 |
|
|
1445 |
1615 |
if (ufrs_n == 0) |
if (ufrs_n == 0) |
1446 |
1616 |
return; |
return; |
1447 |
1617 |
|
|
1448 |
|
is_planar_fmt = av_frame_fmt_is_planar(filt_frs.av->format); |
|
|
1618 |
|
is_planar_fmt = av_fr_fmt_is_planar(filt_frs.av->fmt); |
1449 |
1619 |
if (is_planar_fmt == NO) |
if (is_planar_fmt == NO) |
1450 |
1620 |
(void)snd_pcm_writei(pcm_g, silence_bufs[0], ufrs_n); |
(void)snd_pcm_writei(pcm_g, silence_bufs[0], ufrs_n); |
1451 |
1621 |
else |
else |
|
... |
... |
static void pcm_silence_frs_write(snd_pcm_uframes_t ufrs_n) |
1453 |
1623 |
} |
} |
1454 |
1624 |
#undef NO |
#undef NO |
1455 |
1625 |
#define NO 0 |
#define NO 0 |
1456 |
|
static void pcm_filt_frs_write(snd_pcm_uframes_t ufrs_n) { loop |
|
|
1626 |
|
static void pcm_filt_frs_write(snd_pcm_ufrs_t ufrs_n) { loop |
1457 |
1627 |
{ |
{ |
1458 |
1628 |
u8 chan_buf; |
u8 chan_buf; |
1459 |
1629 |
u8 *chans_buf[AV_NUM_DATA_POINTERS]; |
u8 *chans_buf[AV_NUM_DATA_POINTERS]; |
1460 |
|
snd_pcm_sframes_t r0; |
|
1461 |
|
snd_pcm_uframes_t ufrs_to_write_n; |
|
1462 |
|
snd_pcm_uframes_t filt_frs_remaining_ufrs_n; /* for clarity */ |
|
|
1630 |
|
snd_pcm_sfrs_t r0; |
|
1631 |
|
snd_pcm_ufrs_t ufrs_to_write_n; |
|
1632 |
|
snd_pcm_ufrs_t filt_frs_remaining_ufrs_n; /* for clarity */ |
1463 |
1633 |
|
|
1464 |
1634 |
if (ufrs_n == 0) |
if (ufrs_n == 0) |
1465 |
1635 |
return; |
return; |
1466 |
|
|
|
|
1636 |
|
if (filt_frs.pcm_written_ufrs_n == (snd_pcm_ufrs_t)filt_frs.av->frs_n) { |
|
1637 |
|
av_frs_unref(filt_frs.av); |
|
1638 |
|
dec_frs_filter(); /* synchronous filtering */ |
|
1639 |
|
} |
1467 |
1640 |
/* create the chan buf pointers */ |
/* create the chan buf pointers */ |
1468 |
1641 |
chans_buf_init(chans_buf, (int)filt_frs.pcm_written_ufrs_n); |
chans_buf_init(chans_buf, (int)filt_frs.pcm_written_ufrs_n); |
1469 |
|
|
|
1470 |
|
filt_frs_remaining_ufrs_n = (snd_pcm_uframes_t)filt_frs.av->frames_n |
|
|
1642 |
|
filt_frs_remaining_ufrs_n = (snd_pcm_ufrs_t)filt_frs.av->frs_n |
1471 |
1643 |
- filt_frs.pcm_written_ufrs_n; |
- filt_frs.pcm_written_ufrs_n; |
1472 |
1644 |
if (filt_frs_remaining_ufrs_n > ufrs_n) |
if (filt_frs_remaining_ufrs_n > ufrs_n) |
1473 |
1645 |
ufrs_to_write_n = ufrs_n; |
ufrs_to_write_n = ufrs_n; |
|
... |
... |
static void pcm_filt_frs_write(snd_pcm_uframes_t ufrs_n) { loop |
1476 |
1648 |
|
|
1477 |
1649 |
loop { |
loop { |
1478 |
1650 |
int is_planar_fmt; |
int is_planar_fmt; |
1479 |
|
snd_pcm_uframes_t written_ufrs_n; |
|
|
1651 |
|
snd_pcm_ufrs_t written_ufrs_n; |
1480 |
1652 |
|
|
1481 |
|
is_planar_fmt = av_frame_fmt_is_planar(filt_frs.av->format); |
|
|
1653 |
|
is_planar_fmt = av_fr_fmt_is_planar(filt_frs.av->fmt); |
1482 |
1654 |
if (is_planar_fmt == NO) |
if (is_planar_fmt == NO) |
1483 |
1655 |
r0 = snd_pcm_writei(pcm_g, chans_buf[0], |
r0 = snd_pcm_writei(pcm_g, chans_buf[0], |
1484 |
1656 |
ufrs_to_write_n); |
ufrs_to_write_n); |
|
... |
... |
static void pcm_filt_frs_write(snd_pcm_uframes_t ufrs_n) { loop |
1502 |
1674 |
fatal("alsa:fatal/unhandled error while writing the frames\n"); |
fatal("alsa:fatal/unhandled error while writing the frames\n"); |
1503 |
1675 |
} |
} |
1504 |
1676 |
/* r0 >= 0 */ |
/* r0 >= 0 */ |
1505 |
|
written_ufrs_n = (snd_pcm_uframes_t)r0; |
|
|
1677 |
|
written_ufrs_n = (snd_pcm_ufrs_t)r0; |
1506 |
1678 |
filt_frs.pcm_written_ufrs_n += written_ufrs_n; |
filt_frs.pcm_written_ufrs_n += written_ufrs_n; |
1507 |
1679 |
ufrs_n -= written_ufrs_n; |
ufrs_n -= written_ufrs_n; |
1508 |
1680 |
ufrs_to_write_n -= written_ufrs_n; |
ufrs_to_write_n -= written_ufrs_n; |
1509 |
|
|
|
1510 |
1681 |
chans_buf_inc(chans_buf, (int)written_ufrs_n); |
chans_buf_inc(chans_buf, (int)written_ufrs_n); |
1511 |
|
|
|
1512 |
1682 |
if (ufrs_to_write_n == 0) |
if (ufrs_to_write_n == 0) |
1513 |
1683 |
break; |
break; |
1514 |
1684 |
} |
} |
1515 |
|
if (filt_frs.pcm_written_ufrs_n |
|
1516 |
|
== (snd_pcm_uframes_t)filt_frs.av->frames_n) { |
|
1517 |
|
av_frame_unref(filt_frs.av); |
|
1518 |
|
|
|
1519 |
|
if (!filt_frs_get()) { /* no more filt frs ? */ |
|
1520 |
|
loop { /* spinning */ |
|
1521 |
|
int r1; |
|
1522 |
|
snd_pcm_state_t state; |
|
1523 |
|
|
|
1524 |
|
r1 = snd_pcm_drain(pcm_g); |
|
1525 |
|
if (r1 == 0) |
|
1526 |
|
break; |
|
1527 |
|
if (r1 == -EAGAIN) |
|
1528 |
|
continue; |
|
1529 |
|
/* |
|
1530 |
|
* the pcm state can change asynchronously. |
|
1531 |
|
* _old_ behavior: |
|
1532 |
|
* if the draining was successful, the pcm |
|
1533 |
|
* should be in SETUP state, and in this |
|
1534 |
|
* state, snd_pcm_drain will fail |
|
1535 |
|
* _new and fixed__ behavior: |
|
1536 |
|
* this won't happen because calling |
|
1537 |
|
* snd_pcm_drain while in the SETUP state |
|
1538 |
|
* won't return an error anymore |
|
1539 |
|
*/ |
|
1540 |
|
state = snd_pcm_state(pcm_g); |
|
1541 |
|
if (state == SND_PCM_STATE_SETUP) |
|
1542 |
|
break; |
|
1543 |
|
} |
|
1544 |
|
/**********************************************/ |
|
1545 |
|
exit_ok("finished playing\n"); |
|
1546 |
|
/**********************************************/ |
|
1547 |
|
} |
|
1548 |
|
} |
|
1549 |
1685 |
}} |
}} |
1550 |
1686 |
#undef NO |
#undef NO |
1551 |
1687 |
static void evt_pcm_write(void) |
static void evt_pcm_write(void) |
1552 |
1688 |
{ |
{ |
1553 |
|
snd_pcm_sframes_t r0; |
|
|
1689 |
|
snd_pcm_sfrs_t r0; |
1554 |
1690 |
/* try only 2 times */ |
/* try only 2 times */ |
1555 |
1691 |
r0 = snd_pcm_avail(pcm_g); |
r0 = snd_pcm_avail(pcm_g); |
1556 |
1692 |
if (r0 < 0) { |
if (r0 < 0) { |
|
... |
... |
static void evt_pcm_write(void) |
1571 |
1707 |
} |
} |
1572 |
1708 |
|
|
1573 |
1709 |
if (paused) |
if (paused) |
1574 |
|
pcm_silence_frs_write((snd_pcm_uframes_t)r0); |
|
|
1710 |
|
pcm_silence_frs_write((snd_pcm_ufrs_t)r0); |
1575 |
1711 |
else |
else |
1576 |
|
pcm_filt_frs_write((snd_pcm_uframes_t)r0); |
|
|
1712 |
|
pcm_filt_frs_write((snd_pcm_ufrs_t)r0); |
1577 |
1713 |
} |
} |
1578 |
1714 |
#define EPOLL_EVTS_N 8 /* why not */ |
#define EPOLL_EVTS_N 8 /* why not */ |
1579 |
1715 |
static void evts_loop(void) |
static void evts_loop(void) |
|
... |
... |
static void silence_bufs_cfg(snd_pcm_t *pcm, bool print_info) |
1628 |
1764 |
{ |
{ |
1629 |
1765 |
int r; |
int r; |
1630 |
1766 |
snd_pcm_hw_params_t *hw_params; |
snd_pcm_hw_params_t *hw_params; |
1631 |
|
snd_pcm_uframes_t buf_ufrs_n; |
|
1632 |
|
snd_pcm_format_t fmt; |
|
|
1767 |
|
snd_pcm_ufrs_t buf_ufrs_n; |
|
1768 |
|
snd_pcm_fmt_t fmt; |
1633 |
1769 |
snd_pcm_access_t access; |
snd_pcm_access_t access; |
1634 |
1770 |
unsigned int chans_n; |
unsigned int chans_n; |
1635 |
1771 |
u8 c; |
u8 c; |
|
... |
... |
static void silence_bufs_cfg(snd_pcm_t *pcm, bool print_info) |
1640 |
1776 |
r = snd_pcm_hw_params_current(pcm, hw_params); |
r = snd_pcm_hw_params_current(pcm, hw_params); |
1641 |
1777 |
if (r != 0) |
if (r != 0) |
1642 |
1778 |
fatal("silence:alsa:unable to get the pcm hardware parameters\n"); |
fatal("silence:alsa:unable to get the pcm hardware parameters\n"); |
1643 |
|
r = snd_pcm_hw_params_get_buffer_size(hw_params, &buf_ufrs_n); |
|
|
1779 |
|
r = snd_pcm_hw_params_get_buf_size(hw_params, &buf_ufrs_n); |
1644 |
1780 |
if (r < 0) |
if (r < 0) |
1645 |
|
fatal("silence:alsa:unable to get the number of frames in the pcm buffer\n"); |
|
1646 |
|
r = snd_pcm_hw_params_get_format(hw_params, &fmt); |
|
|
1781 |
|
fatal("silence:alsa:unable to get the number of frs in the pcm buffer\n"); |
|
1782 |
|
r = snd_pcm_hw_params_get_fmt(hw_params, &fmt); |
1647 |
1783 |
if (r < 0) |
if (r < 0) |
1648 |
1784 |
fatal("silence:alsa:unable to get the pcm format\n"); |
fatal("silence:alsa:unable to get the pcm format\n"); |
1649 |
1785 |
r = snd_pcm_hw_params_get_access(hw_params, &access); |
r = snd_pcm_hw_params_get_access(hw_params, &access); |
1650 |
1786 |
if (r < 0) |
if (r < 0) |
1651 |
1787 |
fatal("silence:alsa:unable to get the pcm access mode\n"); |
fatal("silence:alsa:unable to get the pcm access mode\n"); |
1652 |
|
r = snd_pcm_hw_params_get_channels(hw_params, &chans_n); |
|
|
1788 |
|
r = snd_pcm_hw_params_get_chans(hw_params, &chans_n); |
1653 |
1789 |
if (r < 0) |
if (r < 0) |
1654 |
1790 |
fatal("silence:alsa:unable to get the pcm number of channels\n"); |
fatal("silence:alsa:unable to get the pcm number of channels\n"); |
1655 |
1791 |
/* wipe silence bufs first */ |
/* wipe silence bufs first */ |
|
... |
... |
static void silence_bufs_cfg(snd_pcm_t *pcm, bool print_info) |
1667 |
1803 |
|| access == SND_PCM_ACCESS_MMAP_INTERLEAVED) { |
|| access == SND_PCM_ACCESS_MMAP_INTERLEAVED) { |
1668 |
1804 |
ssize_t buf_bytes_n; |
ssize_t buf_bytes_n; |
1669 |
1805 |
|
|
1670 |
|
buf_bytes_n = snd_pcm_frames_to_bytes(pcm, |
|
1671 |
|
(snd_pcm_sframes_t)buf_ufrs_n); |
|
|
1806 |
|
buf_bytes_n = snd_pcm_frs_to_bytes(pcm, |
|
1807 |
|
(snd_pcm_sfrs_t)buf_ufrs_n); |
1672 |
1808 |
if (buf_bytes_n <= 0) |
if (buf_bytes_n <= 0) |
1673 |
1809 |
fatal("silence:alsa:interleaved:unable to get the pcm number of bytes of all buffer frames\n"); |
fatal("silence:alsa:interleaved:unable to get the pcm number of bytes of all buffer frames\n"); |
1674 |
1810 |
silence_bufs[0] = malloc((size_t)buf_bytes_n); |
silence_bufs[0] = malloc((size_t)buf_bytes_n); |
|
... |
... |
static void silence_bufs_cfg(snd_pcm_t *pcm, bool print_info) |
1676 |
1812 |
fatal("silence:interleaved:unable to allocate the silence buffer of %d bytes\n", (int)buf_bytes_n); |
fatal("silence:interleaved:unable to allocate the silence buffer of %d bytes\n", (int)buf_bytes_n); |
1677 |
1813 |
if (print_info) |
if (print_info) |
1678 |
1814 |
pout("silence:interleaved:buffer of %d bytes is allocated\n", (int)buf_bytes_n); |
pout("silence:interleaved:buffer of %d bytes is allocated\n", (int)buf_bytes_n); |
1679 |
|
r = snd_pcm_format_set_silence(fmt, silence_bufs[0], |
|
|
1815 |
|
r = snd_pcm_fmt_set_silence(fmt, silence_bufs[0], |
1680 |
1816 |
(unsigned int)buf_ufrs_n); |
(unsigned int)buf_ufrs_n); |
1681 |
1817 |
if (r < 0) |
if (r < 0) |
1682 |
1818 |
fatal("silence:interleaved:unable to fill with silence the buffer\n"); |
fatal("silence:interleaved:unable to fill with silence the buffer\n"); |
|
... |
... |
static void silence_bufs_cfg(snd_pcm_t *pcm, bool print_info) |
1697 |
1833 |
silence_bufs[c] = malloc((size_t)buf_bytes_n); |
silence_bufs[c] = malloc((size_t)buf_bytes_n); |
1698 |
1834 |
if (silence_bufs[c] == 0) |
if (silence_bufs[c] == 0) |
1699 |
1835 |
fatal("silence:non interleaved:unable to allocate silence buffer %u of %d bytes\n", c, (int)buf_bytes_n); |
fatal("silence:non interleaved:unable to allocate silence buffer %u of %d bytes\n", c, (int)buf_bytes_n); |
1700 |
|
r = snd_pcm_format_set_silence(fmt, silence_bufs[c], |
|
|
1836 |
|
r = snd_pcm_fmt_set_silence(fmt, silence_bufs[c], |
1701 |
1837 |
(unsigned int)buf_samples_n); |
(unsigned int)buf_samples_n); |
1702 |
1838 |
if (r < 0) |
if (r < 0) |
1703 |
1839 |
fatal("silence:non interleaved:unable to fill with silence the buffer\n"); |
fatal("silence:non interleaved:unable to fill with silence the buffer\n"); |
|
... |
... |
static void silence_bufs_cfg(snd_pcm_t *pcm, bool print_info) |
1711 |
1847 |
fatal("silence:the pcm access type is not supported\n"); |
fatal("silence:the pcm access type is not supported\n"); |
1712 |
1848 |
snd_pcm_hw_params_free(hw_params); |
snd_pcm_hw_params_free(hw_params); |
1713 |
1849 |
} |
} |
1714 |
|
static void ffmpeg_log_stdout(void *a, int b, const char *fmt, va_list ap) |
|
|
1850 |
|
static void ff_log_stdout(void *a, int b, const char *fmt, va_list ap) |
1715 |
1851 |
{ |
{ |
1716 |
1852 |
vprintf(fmt, ap); |
vprintf(fmt, ap); |
1717 |
1853 |
} |
} |
|
1854 |
|
struct ff_supported_fr_fmt_t { |
|
1855 |
|
u8 *str; |
|
1856 |
|
enum av_fr_fmt fmt; |
|
1857 |
|
}; |
|
1858 |
|
/* this is the intersection of ff audio fr fmt and alsa pcm fmt */ |
|
1859 |
|
static struct ff_supported_fr_fmt_t ff_supported_fr_fmts[] = { |
|
1860 |
|
{"u8", AV_FR_FMT_U8}, |
|
1861 |
|
{"u8planar", AV_FR_FMT_U8P}, |
|
1862 |
|
{"s16", AV_FR_FMT_S16}, |
|
1863 |
|
{"s16planar", AV_FR_FMT_S16P}, |
|
1864 |
|
{"s32", AV_FR_FMT_S32}, |
|
1865 |
|
{"s32planar", AV_FR_FMT_S32P}, |
|
1866 |
|
{"float32", AV_FR_FMT_FLT}, |
|
1867 |
|
{"float32planar", AV_FR_FMT_FLTP}, |
|
1868 |
|
{"float64", AV_FR_FMT_DBL}, |
|
1869 |
|
{"float64planar", AV_FR_FMT_DBLP}, |
|
1870 |
|
{0,0} |
|
1871 |
|
}; |
1718 |
1872 |
static void usage(void) |
static void usage(void) |
1719 |
1873 |
{ |
{ |
|
1874 |
|
struct ff_supported_fr_fmt_t *fmt; |
|
1875 |
|
|
1720 |
1876 |
pout("\ |
pout("\ |
1721 |
|
npa [-p alsa pcm] [-v volume(0..100)] [-h] url\n"); |
|
|
1877 |
|
npa [-p alsa pcm] [-v volume(0..100)]\n\ |
|
1878 |
|
[-fc override initial ffmpeg count of channels used to approximate the alsa\n\ |
|
1879 |
|
pcm configuration]\n\ |
|
1880 |
|
[-fr override initial ffmpeg rate(hz) used to approximate the alsa pcm\n\ |
|
1881 |
|
configuration]\n\ |
|
1882 |
|
[-ff override initial ffmpeg audio frame format used to approximate the alsa\n\ |
|
1883 |
|
pcm configuration, see below for a list]\n\ |
|
1884 |
|
[-h]\n\ |
|
1885 |
|
url\n\ |
|
1886 |
|
\n\ |
|
1887 |
|
the ffmpeg audio frame formats which intersect alsa pcm audio formats are:\n"); |
|
1888 |
|
|
|
1889 |
|
fmt = ff_supported_fr_fmts; |
|
1890 |
|
loop { |
|
1891 |
|
if (fmt->str == 0) |
|
1892 |
|
break; |
|
1893 |
|
pout("\t%s\n", fmt->str); |
|
1894 |
|
++fmt; |
|
1895 |
|
} |
1722 |
1896 |
} |
} |
1723 |
1897 |
static void opts_parse(int argc, u8 **args, u8 **url, u8 **pcm_str, |
static void opts_parse(int argc, u8 **args, u8 **url, u8 **pcm_str, |
1724 |
|
double *initial_vol) |
|
|
1898 |
|
double *initial_vol, int *override_initial_ff_chans_n, |
|
1899 |
|
int *override_initial_ff_rate, |
|
1900 |
|
enum av_fr_fmt *override_initial_ff_fr_fmt) |
1725 |
1901 |
{ |
{ |
1726 |
1902 |
int i; |
int i; |
1727 |
1903 |
int url_idx; |
int url_idx; |
|
... |
... |
static void opts_parse(int argc, u8 **args, u8 **url, u8 **pcm_str, |
1748 |
1924 |
*initial_vol = (double)vol_ul / 100.0; |
*initial_vol = (double)vol_ul / 100.0; |
1749 |
1925 |
pout("-v:using initial volume %f\n", *initial_vol); |
pout("-v:using initial volume %f\n", *initial_vol); |
1750 |
1926 |
i += 2; |
i += 2; |
|
1927 |
|
/*------------------------------------------------------------*/ |
|
1928 |
|
/* ff initial override for alsa pcm cfg -- start */ |
|
1929 |
|
} else if (strcmp("-fr", args[i]) == 0) { |
|
1930 |
|
if ((i + 1) == argc) { |
|
1931 |
|
perr("-fr:override initial ffmpeg rate(hz) is missing\n"); |
|
1932 |
|
usage(); |
|
1933 |
|
exit(1); |
|
1934 |
|
} |
|
1935 |
|
*override_initial_ff_rate = (int)strtol(args[i + 1], 0, |
|
1936 |
|
10); |
|
1937 |
|
pout("-fr:override initial ffmpeg audio rate to %dHz used for alsa pcm configuration\n", *override_initial_ff_rate); |
|
1938 |
|
i += 2; |
|
1939 |
|
} else if (strcmp("-fc", args[i]) == 0) { |
|
1940 |
|
if ((i + 1) == argc) { |
|
1941 |
|
perr("-fc:override initial ffmpeg channel count is missing\n"); |
|
1942 |
|
usage(); |
|
1943 |
|
exit(1); |
|
1944 |
|
} |
|
1945 |
|
*override_initial_ff_chans_n = (int)strtol(args[i + 1], |
|
1946 |
|
0, 10); |
|
1947 |
|
pout("-fc:override initial ffmpeg count of channels to %d used for alsa pcm configuration\n", *override_initial_ff_chans_n); |
|
1948 |
|
i += 2; |
|
1949 |
|
} else if (strcmp("-ff", args[i]) == 0) { |
|
1950 |
|
struct ff_supported_fr_fmt_t *fmt; |
|
1951 |
|
|
|
1952 |
|
if ((i + 1) == argc) { |
|
1953 |
|
perr("-fc:override initial ffmpeg audio frame format is missing\n"); |
|
1954 |
|
usage(); |
|
1955 |
|
exit(1); |
|
1956 |
|
} |
|
1957 |
|
fmt = ff_supported_fr_fmts; |
|
1958 |
|
loop { |
|
1959 |
|
if (fmt->str == 0) { |
|
1960 |
|
perr("-ff:unknown ffmpeg audio frame format\n"); |
|
1961 |
|
usage(); |
|
1962 |
|
exit(1); |
|
1963 |
|
} |
|
1964 |
|
if (strcmp(fmt->str, args[i + 1]) == 0) { |
|
1965 |
|
*override_initial_ff_fr_fmt = fmt->fmt; |
|
1966 |
|
break; |
|
1967 |
|
} |
|
1968 |
|
++fmt; |
|
1969 |
|
} |
|
1970 |
|
pout("-ff:override initial ffmpeg audio frame format is %s\n", av_get_fr_fmt_name(*override_initial_ff_fr_fmt)); |
|
1971 |
|
i += 2; |
|
1972 |
|
/* ff initial override for alsa pcm cfg -- end */ |
|
1973 |
|
/*------------------------------------------------------------*/ |
1751 |
1974 |
} else if (strcmp("-h", args[i]) == 0) { |
} else if (strcmp("-h", args[i]) == 0) { |
1752 |
1975 |
usage(); |
usage(); |
1753 |
1976 |
exit(0); |
exit(0); |
|
... |
... |
static void opts_parse(int argc, u8 **args, u8 **url, u8 **pcm_str, |
1762 |
1985 |
pout("playing ####%s####\n", *url); |
pout("playing ####%s####\n", *url); |
1763 |
1986 |
} |
} |
1764 |
1987 |
#define RESET_DONE 0 |
#define RESET_DONE 0 |
|
1988 |
|
#define DONT_HOLD 0 |
1765 |
1989 |
static void cb_init_once(void) |
static void cb_init_once(void) |
1766 |
1990 |
{ |
{ |
1767 |
1991 |
u8 i; |
u8 i; |
|
... |
... |
static void cb_init_once(void) |
1779 |
2003 |
atomic_store(&cb.sd, 0); |
atomic_store(&cb.sd, 0); |
1780 |
2004 |
atomic_store(&cb.st_idx, -1); |
atomic_store(&cb.st_idx, -1); |
1781 |
2005 |
atomic_store(&cb.reset, RESET_DONE); |
atomic_store(&cb.reset, RESET_DONE); |
|
2006 |
|
atomic_store(&cb.hold, DONT_HOLD); |
1782 |
2007 |
} |
} |
1783 |
2008 |
#undef RESET_DONE |
#undef RESET_DONE |
1784 |
|
static void filter_graph_init_once(void) |
|
|
2009 |
|
#undef DONT_HOLD |
|
2010 |
|
static void filt_graph_init_once(void) |
1785 |
2011 |
{ |
{ |
1786 |
|
filter_graph = 0; |
|
|
2012 |
|
filt_graph = 0; |
1787 |
2013 |
abufsrc_ctx = 0; |
abufsrc_ctx = 0; |
1788 |
2014 |
abufsrc_filt = 0; |
abufsrc_filt = 0; |
1789 |
2015 |
vol_ctx = 0; |
vol_ctx = 0; |
|
... |
... |
static void filter_graph_init_once(void) |
1795 |
2021 |
/* floating point strs are localized... */ |
/* floating point strs are localized... */ |
1796 |
2022 |
snprintf(double_zero_l10n_str, sizeof(double_zero_l10n_str), "%f", 0.); |
snprintf(double_zero_l10n_str, sizeof(double_zero_l10n_str), "%f", 0.); |
1797 |
2023 |
memset(&filt_frs, 0, sizeof(filt_frs)); |
memset(&filt_frs, 0, sizeof(filt_frs)); |
1798 |
|
filt_frs.av = av_frames_alloc(); |
|
|
2024 |
|
filt_frs.av = av_frs_alloc(); |
1799 |
2025 |
if (filt_frs.av == 0) |
if (filt_frs.av == 0) |
1800 |
2026 |
fatal("ffmpeg:unable to allocate a filtered frames structure\n"); |
fatal("ffmpeg:unable to allocate a filtered frames structure\n"); |
|
2027 |
|
filt_frs.pcm_written_ufrs_n = 0; |
1801 |
2028 |
} |
} |
1802 |
2029 |
static void dec_init_once(void) |
static void dec_init_once(void) |
1803 |
2030 |
{ |
{ |
1804 |
2031 |
dec = 0; |
dec = 0; |
1805 |
2032 |
dec_ctx = 0; |
dec_ctx = 0; |
1806 |
|
dec_frs.av = av_frames_alloc(); |
|
|
2033 |
|
dec_frs.av = av_frs_alloc(); |
1807 |
2034 |
if (dec_frs.av == 0) |
if (dec_frs.av == 0) |
1808 |
2035 |
fatal("ffmpeg:unable to allocate a decoded frames structure\n"); |
fatal("ffmpeg:unable to allocate a decoded frames structure\n"); |
|
2036 |
|
dec_frs.pushed_in_filt_graph = true; |
1809 |
2037 |
dec_frs.most_recent_ts = AV_NOPTS_VALUE; |
dec_frs.most_recent_ts = AV_NOPTS_VALUE; |
1810 |
2038 |
} |
} |
1811 |
2039 |
static void rd_thd_init_once(void) |
static void rd_thd_init_once(void) |
|
... |
... |
static void fmt_init_once(u8 *url) |
1819 |
2047 |
int r; |
int r; |
1820 |
2048 |
|
|
1821 |
2049 |
fmt_ctx = 0; |
fmt_ctx = 0; |
1822 |
|
r = avformat_open_input(&fmt_ctx, url, NULL, NULL); |
|
|
2050 |
|
r = av_fmt_open_input(&fmt_ctx, url, NULL, NULL); |
1823 |
2051 |
if (r < 0) |
if (r < 0) |
1824 |
2052 |
fatal("ffmpeg:unable to open \"%s\"\n", url); |
fatal("ffmpeg:unable to open \"%s\"\n", url); |
1825 |
2053 |
/* probe beyond the header, if any */ |
/* probe beyond the header, if any */ |
1826 |
|
r = avformat_find_stream_info(fmt_ctx, 0); |
|
|
2054 |
|
r = av_fmt_find_st_info(fmt_ctx, 0); |
1827 |
2055 |
if (r < 0) |
if (r < 0) |
1828 |
2056 |
fatal("ffmpeg:unable to probe \"%s\"\n", url); |
fatal("ffmpeg:unable to probe \"%s\"\n", url); |
1829 |
2057 |
r = pthread_mutex_init(&fmt_ctx_mutex, 0); |
r = pthread_mutex_init(&fmt_ctx_mutex, 0); |
|
... |
... |
static void pcm_init_once(u8 *pcm_str) |
1840 |
2068 |
r = snd_output_stdio_attach(&pcm_perr, stderr, 0); |
r = snd_output_stdio_attach(&pcm_perr, stderr, 0); |
1841 |
2069 |
if (r < 0) |
if (r < 0) |
1842 |
2070 |
fatal("alsa:unable to attach stderr\n"); |
fatal("alsa:unable to attach stderr\n"); |
1843 |
|
r = snd_pcm_open(&pcm_g, pcm_str, SND_PCM_STREAM_PLAYBACK, |
|
|
2071 |
|
r = snd_pcm_open(&pcm_g, pcm_str, SND_PCM_ST_PLAYBACK, |
1844 |
2072 |
SND_PCM_NONBLOCK); |
SND_PCM_NONBLOCK); |
1845 |
2073 |
if (r < 0) { |
if (r < 0) { |
1846 |
2074 |
if (r == -EAGAIN) |
if (r == -EAGAIN) |
|
... |
... |
static void init_once(u8 *url, u8 *pcm_str) |
1868 |
2096 |
stdout_init_once(); |
stdout_init_once(); |
1869 |
2097 |
input_state_init_once(); |
input_state_init_once(); |
1870 |
2098 |
cb_init_once(); |
cb_init_once(); |
1871 |
|
filter_graph_init_once(); |
|
|
2099 |
|
filt_graph_init_once(); |
1872 |
2100 |
silence_bufs_init_once(); |
silence_bufs_init_once(); |
1873 |
2101 |
dec_init_once(); |
dec_init_once(); |
1874 |
2102 |
pcm_init_once(pcm_str); |
pcm_init_once(pcm_str); |
|
... |
... |
static int find_best_st(void) |
1880 |
2108 |
{ |
{ |
1881 |
2109 |
int r; |
int r; |
1882 |
2110 |
|
|
1883 |
|
r = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_AUDIO, -1, -1, 0, 0); |
|
|
2111 |
|
r = av_find_best_st(fmt_ctx, AV_MEDIA_TYPE_AUDIO, -1, -1, 0, 0); |
1884 |
2112 |
if (r < 0) |
if (r < 0) |
1885 |
2113 |
fatal("ffmpeg:no audio stream found\n"); |
fatal("ffmpeg:no audio stream found\n"); |
1886 |
2114 |
return r; |
return r; |
|
... |
... |
static void pcm_hw_chans_n_decide(snd_pcm_t *pcm, |
1892 |
2120 |
unsigned int chans_n_max; |
unsigned int chans_n_max; |
1893 |
2121 |
unsigned int chans_n_min; |
unsigned int chans_n_min; |
1894 |
2122 |
|
|
1895 |
|
r = snd_pcm_hw_params_test_channels(pcm, pcm_hw_params, chans_n); |
|
|
2123 |
|
r = snd_pcm_hw_params_test_chans(pcm, pcm_hw_params, chans_n); |
1896 |
2124 |
if (r == 0) { |
if (r == 0) { |
1897 |
|
r = snd_pcm_hw_params_set_channels(pcm, pcm_hw_params, chans_n); |
|
|
2125 |
|
r = snd_pcm_hw_params_set_chans(pcm, pcm_hw_params, chans_n); |
1898 |
2126 |
if (r != 0) |
if (r != 0) |
1899 |
2127 |
fatal("alsa:unable to restrict pcm device to %u channels, count which was successfully tested\n", chans_n); |
fatal("alsa:unable to restrict pcm device to %u channels, count which was successfully tested\n", chans_n); |
1900 |
2128 |
pout("alsa:using %u channels\n", chans_n); |
pout("alsa:using %u channels\n", chans_n); |
|
... |
... |
static void pcm_hw_chans_n_decide(snd_pcm_t *pcm, |
1902 |
2130 |
} |
} |
1903 |
2131 |
pout("alsa:unable to use %u channels\n", chans_n); |
pout("alsa:unable to use %u channels\n", chans_n); |
1904 |
2132 |
/* try to use the max chans n the pcm can */ |
/* try to use the max chans n the pcm can */ |
1905 |
|
r = snd_pcm_hw_params_get_channels_max(pcm_hw_params, &chans_n_max); |
|
|
2133 |
|
r = snd_pcm_hw_params_get_chans_max(pcm_hw_params, &chans_n_max); |
1906 |
2134 |
if (r != 0) |
if (r != 0) |
1907 |
2135 |
fatal("alsa:unable to get the maximum count of pcm device channels\n"); |
fatal("alsa:unable to get the maximum count of pcm device channels\n"); |
1908 |
|
r = snd_pcm_hw_params_test_channels(pcm, pcm_hw_params, chans_n_max); |
|
|
2136 |
|
r = snd_pcm_hw_params_test_chans(pcm, pcm_hw_params, chans_n_max); |
1909 |
2137 |
if (r == 0) { |
if (r == 0) { |
1910 |
|
r = snd_pcm_hw_params_set_channels(pcm, pcm_hw_params, |
|
|
2138 |
|
r = snd_pcm_hw_params_set_chans(pcm, pcm_hw_params, |
1911 |
2139 |
chans_n_max); |
chans_n_max); |
1912 |
2140 |
if (r != 0) |
if (r != 0) |
1913 |
2141 |
fatal("alsa:unable to restrict pcm device to %u channels, count which was successfully tested\n", chans_n_max); |
fatal("alsa:unable to restrict pcm device to %u channels, count which was successfully tested\n", chans_n_max); |
|
... |
... |
static void pcm_hw_chans_n_decide(snd_pcm_t *pcm, |
1915 |
2143 |
return; |
return; |
1916 |
2144 |
} |
} |
1917 |
2145 |
/* ok... last try, the pcm dev min chans n */ |
/* ok... last try, the pcm dev min chans n */ |
1918 |
|
r = snd_pcm_hw_params_get_channels_min(pcm_hw_params, &chans_n_min); |
|
|
2146 |
|
r = snd_pcm_hw_params_get_chans_min(pcm_hw_params, &chans_n_min); |
1919 |
2147 |
if (r != 0) |
if (r != 0) |
1920 |
2148 |
fatal("alsa:unable to get the minimum count of pcm device channels\n"); |
fatal("alsa:unable to get the minimum count of pcm device channels\n"); |
1921 |
|
r = snd_pcm_hw_params_test_channels(pcm, pcm_hw_params, chans_n_min); |
|
|
2149 |
|
r = snd_pcm_hw_params_test_chans(pcm, pcm_hw_params, chans_n_min); |
1922 |
2150 |
if (r == 0) { |
if (r == 0) { |
1923 |
|
r = snd_pcm_hw_params_set_channels(pcm, pcm_hw_params, |
|
|
2151 |
|
r = snd_pcm_hw_params_set_chans(pcm, pcm_hw_params, |
1924 |
2152 |
chans_n_min); |
chans_n_min); |
1925 |
2153 |
if (r != 0) |
if (r != 0) |
1926 |
2154 |
fatal("alsa:unable to restrict pcm device to %u channels, count which was successfully tested\n", chans_n_min); |
fatal("alsa:unable to restrict pcm device to %u channels, count which was successfully tested\n", chans_n_min); |
|
... |
... |
static void pcm_hw_rate_decide(snd_pcm_t *pcm, |
1938 |
2166 |
unsigned int rate_min; |
unsigned int rate_min; |
1939 |
2167 |
|
|
1940 |
2168 |
r = snd_pcm_hw_params_test_rate(pcm, pcm_hw_params, rate, |
r = snd_pcm_hw_params_test_rate(pcm, pcm_hw_params, rate, |
1941 |
|
SND_PCM_STREAM_PLAYBACK); |
|
|
2169 |
|
SND_PCM_ST_PLAYBACK); |
1942 |
2170 |
if (r == 0) { |
if (r == 0) { |
1943 |
2171 |
r = snd_pcm_hw_params_set_rate(pcm, pcm_hw_params, rate, |
r = snd_pcm_hw_params_set_rate(pcm, pcm_hw_params, rate, |
1944 |
|
SND_PCM_STREAM_PLAYBACK); |
|
|
2172 |
|
SND_PCM_ST_PLAYBACK); |
1945 |
2173 |
if (r != 0) |
if (r != 0) |
1946 |
2174 |
fatal("alsa:unable to restrict pcm device to %uHz, which was successfully tested\n", rate); |
fatal("alsa:unable to restrict pcm device to %uHz, which was successfully tested\n", rate); |
1947 |
2175 |
pout("alsa:using %uHz\n", rate); |
pout("alsa:using %uHz\n", rate); |
|
... |
... |
static void pcm_hw_rate_decide(snd_pcm_t *pcm, |
1950 |
2178 |
pout("alsa:unable to use %uHz\n", rate); |
pout("alsa:unable to use %uHz\n", rate); |
1951 |
2179 |
/* try to use the max rate the pcm can */ |
/* try to use the max rate the pcm can */ |
1952 |
2180 |
r = snd_pcm_hw_params_get_rate_max(pcm_hw_params, &rate_max, |
r = snd_pcm_hw_params_get_rate_max(pcm_hw_params, &rate_max, |
1953 |
|
SND_PCM_STREAM_PLAYBACK); |
|
|
2181 |
|
SND_PCM_ST_PLAYBACK); |
1954 |
2182 |
if (r != 0) |
if (r != 0) |
1955 |
2183 |
fatal("alsa:unable to get the maximum rate of pcm device\n"); |
fatal("alsa:unable to get the maximum rate of pcm device\n"); |
1956 |
2184 |
r = snd_pcm_hw_params_test_rate(pcm, pcm_hw_params, rate_max, |
r = snd_pcm_hw_params_test_rate(pcm, pcm_hw_params, rate_max, |
1957 |
|
SND_PCM_STREAM_PLAYBACK); |
|
|
2185 |
|
SND_PCM_ST_PLAYBACK); |
1958 |
2186 |
if (r == 0) { |
if (r == 0) { |
1959 |
2187 |
r = snd_pcm_hw_params_set_rate(pcm, pcm_hw_params, rate_max, |
r = snd_pcm_hw_params_set_rate(pcm, pcm_hw_params, rate_max, |
1960 |
|
SND_PCM_STREAM_PLAYBACK); |
|
|
2188 |
|
SND_PCM_ST_PLAYBACK); |
1961 |
2189 |
if (r != 0) |
if (r != 0) |
1962 |
2190 |
fatal("alsa:unable to restrict pcm device to %uHz, which was successfully tested\n", rate_max); |
fatal("alsa:unable to restrict pcm device to %uHz, which was successfully tested\n", rate_max); |
1963 |
2191 |
pout("alsa:using pcm device %uHz\n", rate_max); |
pout("alsa:using pcm device %uHz\n", rate_max); |
|
... |
... |
static void pcm_hw_rate_decide(snd_pcm_t *pcm, |
1966 |
2194 |
/* try to use a rate "near" of what the pcm dev can */ |
/* try to use a rate "near" of what the pcm dev can */ |
1967 |
2195 |
rate_near = rate; |
rate_near = rate; |
1968 |
2196 |
r = snd_pcm_hw_params_set_rate_near(pcm, pcm_hw_params, &rate_near, |
r = snd_pcm_hw_params_set_rate_near(pcm, pcm_hw_params, &rate_near, |
1969 |
|
SND_PCM_STREAM_PLAYBACK); |
|
|
2197 |
|
SND_PCM_ST_PLAYBACK); |
1970 |
2198 |
if (r == 0) { |
if (r == 0) { |
1971 |
2199 |
pout("alsa:using pcm device %uHz\n", rate_near); |
pout("alsa:using pcm device %uHz\n", rate_near); |
1972 |
2200 |
return; |
return; |
1973 |
2201 |
} |
} |
1974 |
2202 |
/* even a "near" rate did failed... try the min */ |
/* even a "near" rate did failed... try the min */ |
1975 |
2203 |
r = snd_pcm_hw_params_get_rate_min(pcm_hw_params, &rate_min, |
r = snd_pcm_hw_params_get_rate_min(pcm_hw_params, &rate_min, |
1976 |
|
SND_PCM_STREAM_PLAYBACK); |
|
|
2204 |
|
SND_PCM_ST_PLAYBACK); |
1977 |
2205 |
if (r != 0) |
if (r != 0) |
1978 |
2206 |
fatal("alsa:unable to get the minimum rate of pcm device\n"); |
fatal("alsa:unable to get the minimum rate of pcm device\n"); |
1979 |
2207 |
r = snd_pcm_hw_params_test_rate(pcm, pcm_hw_params, rate_min, |
r = snd_pcm_hw_params_test_rate(pcm, pcm_hw_params, rate_min, |
1980 |
|
SND_PCM_STREAM_PLAYBACK); |
|
|
2208 |
|
SND_PCM_ST_PLAYBACK); |
1981 |
2209 |
if (r == 0) { |
if (r == 0) { |
1982 |
2210 |
r = snd_pcm_hw_params_set_rate(pcm, pcm_hw_params, rate_min, |
r = snd_pcm_hw_params_set_rate(pcm, pcm_hw_params, rate_min, |
1983 |
|
SND_PCM_STREAM_PLAYBACK); |
|
|
2211 |
|
SND_PCM_ST_PLAYBACK); |
1984 |
2212 |
if (r != 0) |
if (r != 0) |
1985 |
2213 |
fatal("alsa:unable to restrict pcm device to %uHz, which was successfully tested\n", rate_min); |
fatal("alsa:unable to restrict pcm device to %uHz, which was successfully tested\n", rate_min); |
1986 |
2214 |
pout("alsa:using pcm device %uHz\n", rate_min); |
pout("alsa:using pcm device %uHz\n", rate_min); |
|
... |
... |
static void pcm_hw_rate_decide(snd_pcm_t *pcm, |
1988 |
2216 |
} |
} |
1989 |
2217 |
fatal("alsa:unable to find a suitable rate\n"); |
fatal("alsa:unable to find a suitable rate\n"); |
1990 |
2218 |
} |
} |
1991 |
|
static bool ff_fmt2pcm_layout_best_effort(enum AVSampleFormat ff_fmt, |
|
1992 |
|
snd_pcm_format_t *alsa_fmt, snd_pcm_access_t *alsa_access) |
|
|
2219 |
|
static bool ff_fmt2pcm_layout_best_effort(enum av_fr_fmt ff_fmt, |
|
2220 |
|
snd_pcm_fmt_t *alsa_fmt, snd_pcm_access_t *alsa_access) |
1993 |
2221 |
{ |
{ |
1994 |
2222 |
static u8 ff_fmt_str[STR_SZ]; |
static u8 ff_fmt_str[STR_SZ]; |
1995 |
2223 |
|
|
1996 |
|
av_get_sample_fmt_string(ff_fmt_str, STR_SZ, ff_fmt); |
|
|
2224 |
|
av_get_fr_fmt_str(ff_fmt_str, STR_SZ, ff_fmt); |
1997 |
2225 |
/* XXX: only classic non-mmap ones */ |
/* XXX: only classic non-mmap ones */ |
1998 |
2226 |
switch (ff_fmt) { |
switch (ff_fmt) { |
1999 |
|
case AV_SAMPLE_FMT_U8: |
|
2000 |
|
*alsa_fmt = SND_PCM_FORMAT_U8; |
|
|
2227 |
|
case AV_FR_FMT_U8: |
|
2228 |
|
*alsa_fmt = SND_PCM_FMT_U8; |
2001 |
2229 |
*alsa_access = SND_PCM_ACCESS_RW_INTERLEAVED; |
*alsa_access = SND_PCM_ACCESS_RW_INTERLEAVED; |
2002 |
2230 |
break; |
break; |
2003 |
|
case AV_SAMPLE_FMT_S16: |
|
2004 |
|
*alsa_fmt = SND_PCM_FORMAT_S16; |
|
|
2231 |
|
case AV_FR_FMT_S16: |
|
2232 |
|
*alsa_fmt = SND_PCM_FMT_S16; |
2005 |
2233 |
*alsa_access = SND_PCM_ACCESS_RW_INTERLEAVED; |
*alsa_access = SND_PCM_ACCESS_RW_INTERLEAVED; |
2006 |
2234 |
break; |
break; |
2007 |
|
case AV_SAMPLE_FMT_S32: |
|
2008 |
|
*alsa_fmt = SND_PCM_FORMAT_S32; |
|
|
2235 |
|
case AV_FR_FMT_S32: |
|
2236 |
|
*alsa_fmt = SND_PCM_FMT_S32; |
2009 |
2237 |
*alsa_access = SND_PCM_ACCESS_RW_INTERLEAVED; |
*alsa_access = SND_PCM_ACCESS_RW_INTERLEAVED; |
2010 |
2238 |
break; |
break; |
2011 |
|
case AV_SAMPLE_FMT_FLT: |
|
2012 |
|
*alsa_fmt = SND_PCM_FORMAT_FLOAT; |
|
|
2239 |
|
case AV_FR_FMT_FLT: |
|
2240 |
|
*alsa_fmt = SND_PCM_FMT_FLT; |
2013 |
2241 |
*alsa_access = SND_PCM_ACCESS_RW_INTERLEAVED; |
*alsa_access = SND_PCM_ACCESS_RW_INTERLEAVED; |
2014 |
2242 |
break; |
break; |
2015 |
2243 |
/* ff "planar" fmts are actually non interleaved fmts */ |
/* ff "planar" fmts are actually non interleaved fmts */ |
2016 |
|
case AV_SAMPLE_FMT_U8P: |
|
2017 |
|
*alsa_fmt = SND_PCM_FORMAT_U8; |
|
|
2244 |
|
case AV_FR_FMT_U8P: |
|
2245 |
|
*alsa_fmt = SND_PCM_FMT_U8; |
2018 |
2246 |
*alsa_access = SND_PCM_ACCESS_RW_NONINTERLEAVED; |
*alsa_access = SND_PCM_ACCESS_RW_NONINTERLEAVED; |
2019 |
2247 |
break; |
break; |
2020 |
|
case AV_SAMPLE_FMT_S16P: |
|
2021 |
|
*alsa_fmt = SND_PCM_FORMAT_S16; |
|
|
2248 |
|
case AV_FR_FMT_S16P: |
|
2249 |
|
*alsa_fmt = SND_PCM_FMT_S16; |
2022 |
2250 |
*alsa_access = SND_PCM_ACCESS_RW_NONINTERLEAVED; |
*alsa_access = SND_PCM_ACCESS_RW_NONINTERLEAVED; |
2023 |
2251 |
break; |
break; |
2024 |
|
case AV_SAMPLE_FMT_S32P: |
|
2025 |
|
*alsa_fmt = SND_PCM_FORMAT_S32; |
|
|
2252 |
|
case AV_FR_FMT_S32P: |
|
2253 |
|
*alsa_fmt = SND_PCM_FMT_S32; |
2026 |
2254 |
*alsa_access = SND_PCM_ACCESS_RW_NONINTERLEAVED; |
*alsa_access = SND_PCM_ACCESS_RW_NONINTERLEAVED; |
2027 |
2255 |
break; |
break; |
2028 |
|
case AV_SAMPLE_FMT_FLTP: |
|
2029 |
|
*alsa_fmt = SND_PCM_FORMAT_FLOAT; |
|
|
2256 |
|
case AV_FR_FMT_FLTP: |
|
2257 |
|
*alsa_fmt = SND_PCM_FMT_FLT; |
2030 |
2258 |
*alsa_access = SND_PCM_ACCESS_RW_NONINTERLEAVED; |
*alsa_access = SND_PCM_ACCESS_RW_NONINTERLEAVED; |
2031 |
2259 |
break; |
break; |
2032 |
2260 |
default: |
default: |
2033 |
2261 |
pout("best effort:unable to wire ffmpeg sample format \"%sbits\" to alsa sample format, \n,", ff_fmt_str); |
pout("best effort:unable to wire ffmpeg sample format \"%sbits\" to alsa sample format, \n,", ff_fmt_str); |
2034 |
2262 |
return false; |
return false; |
2035 |
2263 |
} |
} |
2036 |
|
pout("best effort:ffmpeg format \"%sbits\" (%u bytes) to alsa layout \"%s\" and access \"%s\"\n", ff_fmt_str, av_get_bytes_per_sample(ff_fmt), snd_pcm_format_description(*alsa_fmt), snd_pcm_access_name(*alsa_access)); |
|
|
2264 |
|
pout("best effort:ffmpeg format \"%sbits\" (%u bytes) to alsa layout \"%s\" and access \"%s\"\n", ff_fmt_str, av_get_bytes_per_sample(ff_fmt), snd_pcm_fmt_desc(*alsa_fmt), snd_pcm_access_name(*alsa_access)); |
2037 |
2265 |
return true; |
return true; |
2038 |
2266 |
} |
} |
2039 |
2267 |
static bool pcm_hw_fmt_decide_x(snd_pcm_t *pcm, |
static bool pcm_hw_fmt_decide_x(snd_pcm_t *pcm, |
2040 |
|
snd_pcm_hw_params_t *pcm_hw_params, snd_pcm_format_t fmt) |
|
|
2268 |
|
snd_pcm_hw_params_t *pcm_hw_params, snd_pcm_fmt_t fmt) |
2041 |
2269 |
{ |
{ |
2042 |
2270 |
int r; |
int r; |
2043 |
2271 |
|
|
2044 |
|
r = snd_pcm_hw_params_test_format(pcm, pcm_hw_params, fmt); |
|
|
2272 |
|
r = snd_pcm_hw_params_test_fmt(pcm, pcm_hw_params, fmt); |
2045 |
2273 |
if (r != 0) |
if (r != 0) |
2046 |
2274 |
return false; |
return false; |
2047 |
|
r = snd_pcm_hw_params_set_format(pcm, pcm_hw_params, fmt); |
|
|
2275 |
|
r = snd_pcm_hw_params_set_fmt(pcm, pcm_hw_params, fmt); |
2048 |
2276 |
if (r != 0) |
if (r != 0) |
2049 |
|
fatal("alsa:unable to restrict pcm device to \"%s\", which was successfully tested\n", snd_pcm_format_description(fmt)); |
|
2050 |
|
pout("alsa:using \"%s\" format\n", snd_pcm_format_description(fmt)); |
|
|
2277 |
|
fatal("alsa:unable to restrict pcm device to \"%s\", which was successfully tested\n", snd_pcm_fmt_desc(fmt)); |
|
2278 |
|
pout("alsa:using \"%s\" format\n", snd_pcm_fmt_desc(fmt)); |
2051 |
2279 |
return true; |
return true; |
2052 |
2280 |
} |
} |
2053 |
2281 |
#define PCM_HW_FMT_DECIDE_X(fmt) pcm_hw_fmt_decide_x(pcm, pcm_hw_params, fmt) |
#define PCM_HW_FMT_DECIDE_X(fmt) pcm_hw_fmt_decide_x(pcm, pcm_hw_params, fmt) |
2054 |
2282 |
static void pcm_hw_fmt_decide(snd_pcm_t *pcm, |
static void pcm_hw_fmt_decide(snd_pcm_t *pcm, |
2055 |
2283 |
snd_pcm_hw_params_t *pcm_hw_params, bool force, |
snd_pcm_hw_params_t *pcm_hw_params, bool force, |
2056 |
|
snd_pcm_format_t forced_fmt) |
|
|
2284 |
|
snd_pcm_fmt_t forced_fmt) |
2057 |
2285 |
{ |
{ |
2058 |
2286 |
int r; |
int r; |
2059 |
|
snd_pcm_format_t *fmt; |
|
|
2287 |
|
snd_pcm_fmt_t *fmt; |
2060 |
2288 |
|
|
2061 |
2289 |
if (force) { |
if (force) { |
2062 |
|
r = snd_pcm_hw_params_test_format(pcm, pcm_hw_params, |
|
2063 |
|
forced_fmt); |
|
|
2290 |
|
r = snd_pcm_hw_params_test_fmt(pcm, pcm_hw_params, forced_fmt); |
2064 |
2291 |
if (r == 0) { |
if (r == 0) { |
2065 |
|
r = snd_pcm_hw_params_set_format(pcm, pcm_hw_params, |
|
|
2292 |
|
r = snd_pcm_hw_params_set_fmt(pcm, pcm_hw_params, |
2066 |
2293 |
forced_fmt); |
forced_fmt); |
2067 |
2294 |
if (r != 0) |
if (r != 0) |
2068 |
|
fatal("alsa:unable to restrict pcm device to \"%s\", which was successfully tested\n", snd_pcm_format_description(forced_fmt)); |
|
2069 |
|
pout("alsa:using forced \"%s\" format\n", snd_pcm_format_description(forced_fmt)); |
|
|
2295 |
|
fatal("alsa:unable to restrict pcm device to \"%s\", which was successfully tested\n", snd_pcm_fmt_desc(forced_fmt)); |
|
2296 |
|
pout("alsa:using forced \"%s\" format\n", snd_pcm_fmt_desc(forced_fmt)); |
2070 |
2297 |
return; |
return; |
2071 |
2298 |
} |
} |
2072 |
2299 |
} |
} |
2073 |
2300 |
/* then we try to select from the reasonable "best" to the lowest */ |
/* then we try to select from the reasonable "best" to the lowest */ |
2074 |
2301 |
/* prefer fmts we know supported by ff */ |
/* prefer fmts we know supported by ff */ |
2075 |
|
if (PCM_HW_FMT_DECIDE_X(SND_PCM_FORMAT_FLOAT)) |
|
|
2302 |
|
if (PCM_HW_FMT_DECIDE_X(SND_PCM_FMT_FLT)) |
2076 |
2303 |
return; |
return; |
2077 |
|
if (PCM_HW_FMT_DECIDE_X(SND_PCM_FORMAT_S32)) |
|
|
2304 |
|
if (PCM_HW_FMT_DECIDE_X(SND_PCM_FMT_S32)) |
2078 |
2305 |
return; |
return; |
2079 |
|
if (PCM_HW_FMT_DECIDE_X(SND_PCM_FORMAT_S16)) |
|
|
2306 |
|
if (PCM_HW_FMT_DECIDE_X(SND_PCM_FMT_S16)) |
2080 |
2307 |
return; |
return; |
2081 |
|
if (PCM_HW_FMT_DECIDE_X(SND_PCM_FORMAT_U8)) |
|
|
2308 |
|
if (PCM_HW_FMT_DECIDE_X(SND_PCM_FMT_U8)) |
2082 |
2309 |
return; |
return; |
2083 |
2310 |
/* |
/* |
2084 |
2311 |
* from here, at the time of writting, those fmts have no ff |
* from here, at the time of writting, those fmts have no ff |
2085 |
2312 |
* wiring, but we are alsa centric here, validate that later |
* wiring, but we are alsa centric here, validate that later |
2086 |
2313 |
*/ |
*/ |
2087 |
|
if (PCM_HW_FMT_DECIDE_X(SND_PCM_FORMAT_U32)) |
|
|
2314 |
|
if (PCM_HW_FMT_DECIDE_X(SND_PCM_FMT_U32)) |
2088 |
2315 |
return; |
return; |
2089 |
|
if (PCM_HW_FMT_DECIDE_X(SND_PCM_FORMAT_S24)) |
|
|
2316 |
|
if (PCM_HW_FMT_DECIDE_X(SND_PCM_FMT_S24)) |
2090 |
2317 |
return; |
return; |
2091 |
|
if (PCM_HW_FMT_DECIDE_X(SND_PCM_FORMAT_U24)) |
|
|
2318 |
|
if (PCM_HW_FMT_DECIDE_X(SND_PCM_FMT_U24)) |
2092 |
2319 |
return; |
return; |
2093 |
|
if (PCM_HW_FMT_DECIDE_X(SND_PCM_FORMAT_U16)) |
|
|
2320 |
|
if (PCM_HW_FMT_DECIDE_X(SND_PCM_FMT_U16)) |
2094 |
2321 |
return; |
return; |
2095 |
|
if (PCM_HW_FMT_DECIDE_X(SND_PCM_FORMAT_S8)) |
|
|
2322 |
|
if (PCM_HW_FMT_DECIDE_X(SND_PCM_FMT_S8)) |
2096 |
2323 |
return; |
return; |
2097 |
2324 |
fatal("alsa:unable to find a suitable format\n"); |
fatal("alsa:unable to find a suitable format\n"); |
2098 |
2325 |
} |
} |
|
... |
... |
static void pcm_hw_buf_sz_cfg(snd_pcm_t *pcm, |
2155 |
2382 |
snd_pcm_hw_params_t *pcm_hw_params) |
snd_pcm_hw_params_t *pcm_hw_params) |
2156 |
2383 |
{ |
{ |
2157 |
2384 |
int r; |
int r; |
2158 |
|
snd_pcm_uframes_t latency_control_target_buf_ufrs_n; |
|
2159 |
|
snd_pcm_uframes_t latency_control_buf_ufrs_n; |
|
|
2385 |
|
snd_pcm_ufrs_t latency_control_target_buf_ufrs_n; |
|
2386 |
|
snd_pcm_ufrs_t latency_control_buf_ufrs_n; |
2160 |
2387 |
unsigned int rate; |
unsigned int rate; |
2161 |
2388 |
|
|
2162 |
2389 |
r = snd_pcm_hw_params_get_rate(pcm_hw_params, &rate, 0); |
r = snd_pcm_hw_params_get_rate(pcm_hw_params, &rate, 0); |
|
... |
... |
static void pcm_hw_buf_sz_cfg(snd_pcm_t *pcm, |
2164 |
2391 |
warning("alsa:latency control:DISABLING LATENCY CONTROL:unable to get the decided rate from the current device parameters\n"); |
warning("alsa:latency control:DISABLING LATENCY CONTROL:unable to get the decided rate from the current device parameters\n"); |
2165 |
2392 |
return; |
return; |
2166 |
2393 |
} |
} |
2167 |
|
latency_control_target_buf_ufrs_n = (snd_pcm_uframes_t)rate; |
|
|
2394 |
|
latency_control_target_buf_ufrs_n = (snd_pcm_ufrs_t)rate; |
2168 |
2395 |
latency_control_target_buf_ufrs_n /= 4; |
latency_control_target_buf_ufrs_n /= 4; |
2169 |
2396 |
latency_control_buf_ufrs_n = latency_control_target_buf_ufrs_n; |
latency_control_buf_ufrs_n = latency_control_target_buf_ufrs_n; |
2170 |
|
r = snd_pcm_hw_params_set_buffer_size_near(pcm, pcm_hw_params, |
|
|
2397 |
|
r = snd_pcm_hw_params_set_buf_size_near(pcm, pcm_hw_params, |
2171 |
2398 |
&latency_control_buf_ufrs_n); |
&latency_control_buf_ufrs_n); |
2172 |
2399 |
if (r < 0) { |
if (r < 0) { |
2173 |
2400 |
warning("alsa:latency control:DISABLING_LATENCY_CONTROL:unable to set the audio buffer size (count of frames) to %u periods for the current device parameters\n", latency_control_buf_ufrs_n); |
warning("alsa:latency control:DISABLING_LATENCY_CONTROL:unable to set the audio buffer size (count of frames) to %u periods for the current device parameters\n", latency_control_buf_ufrs_n); |
|
... |
... |
static void pcm_cfg_sw(snd_pcm_t *pcm) |
2208 |
2435 |
* we try to use a sensible restrict order regarding audio props |
* we try to use a sensible restrict order regarding audio props |
2209 |
2436 |
*/ |
*/ |
2210 |
2437 |
static void pcm_cfg_hw_core(snd_pcm_t *pcm, snd_pcm_hw_params_t *pcm_hw_params, |
static void pcm_cfg_hw_core(snd_pcm_t *pcm, snd_pcm_hw_params_t *pcm_hw_params, |
2211 |
|
int chans_n, int rate, enum AVSampleFormat ff_fmt) |
|
|
2438 |
|
int chans_n, int rate, enum av_fr_fmt ff_fmt) |
2212 |
2439 |
{ |
{ |
2213 |
2440 |
int r; |
int r; |
2214 |
2441 |
bool best_effort_wiring_success; |
bool best_effort_wiring_success; |
2215 |
|
snd_pcm_format_t fmt_from_best_effort; |
|
|
2442 |
|
snd_pcm_fmt_t fmt_from_best_effort; |
2216 |
2443 |
snd_pcm_access_t access_from_best_effort; |
snd_pcm_access_t access_from_best_effort; |
2217 |
2444 |
|
|
2218 |
2445 |
/* the return value is from a first refine of the raw hw params */ |
/* the return value is from a first refine of the raw hw params */ |
|
... |
... |
static void pcm_cfg_hw_core(snd_pcm_t *pcm, snd_pcm_hw_params_t *pcm_hw_params, |
2231 |
2458 |
pcm_hw_buf_sz_cfg(pcm, pcm_hw_params); |
pcm_hw_buf_sz_cfg(pcm, pcm_hw_params); |
2232 |
2459 |
} |
} |
2233 |
2460 |
static void pcm_cfg_hw(snd_pcm_t *pcm, unsigned int chans_n, unsigned int rate, |
static void pcm_cfg_hw(snd_pcm_t *pcm, unsigned int chans_n, unsigned int rate, |
2234 |
|
enum AVSampleFormat ff_fmt) |
|
|
2461 |
|
enum av_fr_fmt ff_fmt) |
2235 |
2462 |
{ |
{ |
2236 |
2463 |
int r; |
int r; |
2237 |
2464 |
snd_pcm_access_t access; |
snd_pcm_access_t access; |
|
... |
... |
static void pcm_cfg_hw(snd_pcm_t *pcm, unsigned int chans_n, unsigned int rate, |
2253 |
2480 |
pout("ALSA:HW_PARAMS END--------------------------------------------------------------\n"); |
pout("ALSA:HW_PARAMS END--------------------------------------------------------------\n"); |
2254 |
2481 |
} |
} |
2255 |
2482 |
static void pcm_cfg(snd_pcm_t *pcm, unsigned int chans_n, unsigned int rate, |
static void pcm_cfg(snd_pcm_t *pcm, unsigned int chans_n, unsigned int rate, |
2256 |
|
enum AVSampleFormat ff_fmt) |
|
|
2483 |
|
enum av_fr_fmt ff_fmt) |
2257 |
2484 |
{ |
{ |
2258 |
2485 |
pcm_cfg_hw(pcm, chans_n, rate, ff_fmt); |
pcm_cfg_hw(pcm, chans_n, rate, ff_fmt); |
2259 |
2486 |
pcm_cfg_sw(pcm); |
pcm_cfg_sw(pcm); |
|
... |
... |
static void evt_pcm_install(void) |
2281 |
2508 |
} |
} |
2282 |
2509 |
pout("alsa:pcm events installed\n"); |
pout("alsa:pcm events installed\n"); |
2283 |
2510 |
} |
} |
2284 |
|
static void evt_pcm_uninstall(void) |
|
2285 |
|
{ |
|
2286 |
|
u8 i; |
|
2287 |
|
|
|
2288 |
|
i = 0; |
|
2289 |
|
loop { |
|
2290 |
|
if (i == pcm_pollfds_n) |
|
2291 |
|
break; |
|
2292 |
|
(void)epoll_ctl(ep_fd, EPOLL_CTL_DEL, pcm_pollfds[i].fd, 0); |
|
2293 |
|
++i; |
|
2294 |
|
} |
|
2295 |
|
pout("alsa:pcm events uninstalled\n"); |
|
2296 |
|
} |
|
2297 |
2511 |
#define PRINT_INFO true |
#define PRINT_INFO true |
2298 |
|
static void play(int st_idx, double initial_vol, bool do_rd_thd_reset) |
|
2299 |
|
{ |
|
2300 |
|
enum AVSampleFormat dst_fmt; |
|
|
2512 |
|
#define CHANS_N_NOT_OVERRIDDEN 0 |
|
2513 |
|
#define RATE_NOT_OVERRIDDEN 0 |
|
2514 |
|
#define FR_FMT_NOT_OVERRIDDEN AV_FR_FMT_NONE |
|
2515 |
|
static void prepare(int st_idx, double initial_vol, |
|
2516 |
|
int override_initial_ff_chans_n, int override_initial_ff_rate, |
|
2517 |
|
enum av_fr_fmt override_initial_ff_audio_fr_fmt) |
|
2518 |
|
{ |
|
2519 |
|
enum av_fr_fmt dst_fmt; |
2301 |
2520 |
int dst_rate; |
int dst_rate; |
2302 |
2521 |
int dst_chans_n; |
int dst_chans_n; |
2303 |
2522 |
uint64_t src_chans_layout; |
uint64_t src_chans_layout; |
2304 |
2523 |
uint64_t dst_chans_layout; |
uint64_t dst_chans_layout; |
|
2524 |
|
int initial_ff_chans_n; |
|
2525 |
|
int initial_ff_rate; |
|
2526 |
|
enum av_fr_fmt initial_ff_audio_fr_fmt; |
2305 |
2527 |
|
|
2306 |
2528 |
current_st_idx = st_idx; |
current_st_idx = st_idx; |
2307 |
|
/* XXX: reset will flush all pkts dmuxed by the the rd thd until now */ |
|
2308 |
|
if (do_rd_thd_reset) |
|
2309 |
|
rd_thd_reset(st_idx); |
|
2310 |
2529 |
fmt_ctx_lock(); |
fmt_ctx_lock(); |
2311 |
|
dec_ctx_cfg(fmt_ctx->streams[st_idx]->codecpar); |
|
2312 |
|
dec_frs.most_recent_ts = fmt_ctx->streams[st_idx]->start_time; |
|
|
2530 |
|
dec_ctx_cfg(fmt_ctx->sts[st_idx]->codecpar); |
|
2531 |
|
dec_frs.most_recent_ts = fmt_ctx->sts[st_idx]->start_time; |
2313 |
2532 |
cmd_info_data.fmt.duration = fmt_ctx->duration; |
cmd_info_data.fmt.duration = fmt_ctx->duration; |
2314 |
2533 |
cmd_info_data.fmt.m = fmt_ctx->duration_estimation_method; |
cmd_info_data.fmt.m = fmt_ctx->duration_estimation_method; |
2315 |
|
cmd_info_data.st.tb = fmt_ctx->streams[st_idx]->time_base; |
|
2316 |
|
cmd_info_data.st.id = fmt_ctx->streams[st_idx]->id; |
|
2317 |
|
cmd_info_data.st.duration = fmt_ctx->streams[st_idx]->duration; |
|
|
2534 |
|
cmd_info_data.st.tb = fmt_ctx->sts[st_idx]->tb; |
|
2535 |
|
cmd_info_data.st.id = fmt_ctx->sts[st_idx]->id; |
|
2536 |
|
cmd_info_data.st.duration = fmt_ctx->sts[st_idx]->duration; |
2318 |
2537 |
fmt_ctx_unlock(); |
fmt_ctx_unlock(); |
2319 |
2538 |
|
|
2320 |
|
evt_pcm_uninstall(); |
|
2321 |
|
/* |
|
2322 |
|
* do our best to match the pcm cfg to audio ff dec output, BUT we don't |
|
2323 |
|
* expect to match it "exactly": see right below why |
|
2324 |
|
*/ |
|
2325 |
|
pcm_cfg(pcm_g, dec_ctx->channels, dec_ctx->sample_rate, |
|
2326 |
|
dec_ctx->sample_fmt); |
|
2327 |
|
evt_pcm_install(); |
|
2328 |
|
/* use a ff filt to fill in the gap between the pcm and audio ff dec */ |
|
2329 |
|
pcm2ff(pcm_g, &dst_fmt, &dst_rate, &dst_chans_n, |
|
2330 |
|
&dst_chans_layout, PRINT_INFO); |
|
2331 |
|
/* the audio dec ctx may not have a valid chans layout */ |
|
2332 |
|
if (dec_ctx->channel_layout == 0) { |
|
2333 |
|
src_chans_layout = av_get_default_channel_layout( |
|
2334 |
|
dec_ctx->channels); |
|
2335 |
|
} else |
|
2336 |
|
src_chans_layout = dec_ctx->channel_layout; |
|
2337 |
|
filter_graph_cfg( |
|
2338 |
|
dec_ctx->sample_fmt, dec_ctx->sample_rate, |
|
2339 |
|
dec_ctx->channels, src_chans_layout, |
|
2340 |
|
false, initial_vol, |
|
2341 |
|
dst_fmt, dst_rate, dst_chans_n, dst_chans_layout, |
|
2342 |
|
PRINT_INFO); |
|
|
2539 |
|
if (override_initial_ff_chans_n == CHANS_N_NOT_OVERRIDDEN) |
|
2540 |
|
initial_ff_chans_n = dec_ctx->chans_n; |
|
2541 |
|
else |
|
2542 |
|
initial_ff_chans_n = override_initial_ff_chans_n; |
|
2543 |
|
if (override_initial_ff_rate == RATE_NOT_OVERRIDDEN) |
|
2544 |
|
initial_ff_rate = dec_ctx->fr_rate; |
|
2545 |
|
else |
|
2546 |
|
initial_ff_rate = override_initial_ff_rate; |
|
2547 |
|
if (override_initial_ff_audio_fr_fmt == FR_FMT_NOT_OVERRIDDEN) |
|
2548 |
|
initial_ff_audio_fr_fmt = dec_ctx->fr_fmt; |
|
2549 |
|
else |
|
2550 |
|
initial_ff_audio_fr_fmt = override_initial_ff_audio_fr_fmt; |
|
2551 |
|
/* best effort configuration of the pcm based on initial ff params */ |
|
2552 |
|
pcm_cfg(pcm_g, initial_ff_chans_n, initial_ff_rate, |
|
2553 |
|
initial_ff_audio_fr_fmt); |
2343 |
2554 |
silence_bufs_cfg(pcm_g, PRINT_INFO); |
silence_bufs_cfg(pcm_g, PRINT_INFO); |
|
2555 |
|
evt_pcm_install(); |
2344 |
2556 |
filt_frs.vol = initial_vol; |
filt_frs.vol = initial_vol; |
2345 |
2557 |
} |
} |
2346 |
2558 |
#undef PRINT_INFO |
#undef PRINT_INFO |
|
2559 |
|
#undef CHANS_N_NOT_OVERRIDDEN |
|
2560 |
|
#undef RATE_NOT_OVERRIDDEN |
|
2561 |
|
#undef AUDIO_FR_FMT_NOT_OVERRIDDEN |
|
2562 |
|
#define HOLD 1 |
|
2563 |
|
#define DONT_HOLD 0 |
2347 |
2564 |
static void seek_x(int64_t delta) |
static void seek_x(int64_t delta) |
2348 |
2565 |
{ |
{ |
2349 |
2566 |
int r; |
int r; |
2350 |
2567 |
int64_t new_ts; |
int64_t new_ts; |
2351 |
|
AVStream *st; |
|
2352 |
|
AVRational st_tb; |
|
|
2568 |
|
av_st *st; |
|
2569 |
|
av_rational st_tb; |
2353 |
2570 |
|
|
2354 |
2571 |
if (dec_frs.most_recent_ts == AV_NOPTS_VALUE) |
if (dec_frs.most_recent_ts == AV_NOPTS_VALUE) |
2355 |
2572 |
warning("unable to seek because no time stamp are currently available\n"); |
warning("unable to seek because no time stamp are currently available\n"); |
2356 |
2573 |
fmt_ctx_lock(); |
fmt_ctx_lock(); |
2357 |
|
st = fmt_ctx->streams[current_st_idx]; |
|
2358 |
|
st_tb = st->time_base; |
|
|
2574 |
|
st = fmt_ctx->sts[current_st_idx]; |
|
2575 |
|
st_tb = st->tb; |
2359 |
2576 |
fmt_ctx_unlock(); |
fmt_ctx_unlock(); |
2360 |
2577 |
|
|
2361 |
|
new_ts = dec_frs.most_recent_ts + delta * st_tb.den / st_tb.num; |
|
|
2578 |
|
new_ts = dec_frs.most_recent_ts + delta * (int64_t)st_tb.den |
|
2579 |
|
/ (int64_t)st_tb.num; |
2362 |
2580 |
/* rewind capping */ |
/* rewind capping */ |
2363 |
2581 |
pout("trying to seek to %"PRId64" stream time base units\n", new_ts); |
pout("trying to seek to %"PRId64" stream time base units\n", new_ts); |
|
2582 |
|
|
|
2583 |
|
atomic_store(&cb.hold, HOLD); |
|
2584 |
|
rd_thd_reset(current_st_idx); |
2364 |
2585 |
fmt_ctx_lock(); |
fmt_ctx_lock(); |
2365 |
2586 |
r = av_seek_pkt(fmt_ctx, st->id, new_ts, 0); |
r = av_seek_pkt(fmt_ctx, st->id, new_ts, 0); |
2366 |
2587 |
fmt_ctx_unlock(); |
fmt_ctx_unlock(); |
2367 |
2588 |
if (r < 0) |
if (r < 0) |
2368 |
2589 |
warning("unable to seek to %"PRId64" stream time base units\n", new_ts); |
warning("unable to seek to %"PRId64" stream time base units\n", new_ts); |
2369 |
2590 |
dec_frs.most_recent_ts = AV_NOPTS_VALUE; |
dec_frs.most_recent_ts = AV_NOPTS_VALUE; |
2370 |
|
rd_thd_reset(current_st_idx); |
|
2371 |
|
avcodec_flush_buffers(dec_ctx); |
|
2372 |
|
filt_frs.no_more_dec_frs = false; /* reset by the previous line */ |
|
|
2591 |
|
av_flush_bufs(dec_ctx); |
2373 |
2592 |
filt_flush(); |
filt_flush(); |
2374 |
|
if (!filt_frs_get()) |
|
2375 |
|
exit_ok("no more audio frames to play\n"); |
|
|
2593 |
|
atomic_store(&cb.hold, DONT_HOLD); |
2376 |
2594 |
} |
} |
|
2595 |
|
#undef HOLD |
|
2596 |
|
#undef DONT_HOLD |
2377 |
2597 |
static void cmd_rewind(void) |
static void cmd_rewind(void) |
2378 |
2598 |
{ |
{ |
2379 |
2599 |
pout("COMMAND:rewind\n"); |
pout("COMMAND:rewind\n"); |
|
... |
... |
static void cmd_vol_up(void) |
2417 |
2637 |
pout("COMMAND:volume up to value %s(%s)\n", vol_l10n_str, filt_frs.muted ? "muted" : "unmuted"); |
pout("COMMAND:volume up to value %s(%s)\n", vol_l10n_str, filt_frs.muted ? "muted" : "unmuted"); |
2418 |
2638 |
if (filt_frs.muted) |
if (filt_frs.muted) |
2419 |
2639 |
return; |
return; |
2420 |
|
r = avfilter_graph_send_command(filter_graph, "vol", "volume", |
|
2421 |
|
vol_l10n_str, response, sizeof(response), 0); |
|
|
2640 |
|
r = av_filt_graph_send_cmd(filt_graph, "vol", "volume", vol_l10n_str, |
|
2641 |
|
response, sizeof(response), 0); |
2422 |
2642 |
if (r < 0) |
if (r < 0) |
2423 |
2643 |
warning("ffmpeg:volume context:unable to set the volume up to \"%s\":response from volume filter:\"%s\"\n", response); |
warning("ffmpeg:volume context:unable to set the volume up to \"%s\":response from volume filter:\"%s\"\n", response); |
2424 |
2644 |
} |
} |
|
... |
... |
static void cmd_vol_down(void) |
2435 |
2655 |
pout("COMMAND:volume down to value %s(%s)\n", vol_l10n_str, filt_frs.muted ? "muted" : "unmuted"); |
pout("COMMAND:volume down to value %s(%s)\n", vol_l10n_str, filt_frs.muted ? "muted" : "unmuted"); |
2436 |
2656 |
if (filt_frs.muted) |
if (filt_frs.muted) |
2437 |
2657 |
return; |
return; |
2438 |
|
r = avfilter_graph_send_command(filter_graph, "vol", "volume", |
|
2439 |
|
vol_l10n_str, response, sizeof(response), 0); |
|
|
2658 |
|
r = av_filt_graph_send_cmd(filt_graph, "vol", "volume", vol_l10n_str, |
|
2659 |
|
response, sizeof(response), 0); |
2440 |
2660 |
if (r < 0) |
if (r < 0) |
2441 |
2661 |
warning("ffmpeg:volume context:unable to set the volume down to \"%s\":response from volume filter:\"%s\"\n", response); |
warning("ffmpeg:volume context:unable to set the volume down to \"%s\":response from volume filter:\"%s\"\n", response); |
2442 |
2662 |
} |
} |
|
... |
... |
static void cmd_mute(void) |
2451 |
2671 |
|
|
2452 |
2672 |
snprintf(vol_l10n_str, sizeof(vol_l10n_str), "%f", |
snprintf(vol_l10n_str, sizeof(vol_l10n_str), "%f", |
2453 |
2673 |
filt_frs.vol); |
filt_frs.vol); |
2454 |
|
r = avfilter_graph_send_command(filter_graph, "vol", "volume", |
|
|
2674 |
|
r = av_filt_graph_send_cmd(filt_graph, "vol", "volume", |
2455 |
2675 |
vol_l10n_str, response, sizeof(response), 0); |
vol_l10n_str, response, sizeof(response), 0); |
2456 |
2676 |
if (r < 0) { |
if (r < 0) { |
2457 |
2677 |
warning("ffmpeg:volume context:unable to mute the volume to 0:response from volume filter:%s\n", response); |
warning("ffmpeg:volume context:unable to mute the volume to 0:response from volume filter:%s\n", response); |
|
... |
... |
static void cmd_mute(void) |
2461 |
2681 |
} else { |
} else { |
2462 |
2682 |
pout("COMMAND:muting\n"); |
pout("COMMAND:muting\n"); |
2463 |
2683 |
|
|
2464 |
|
r = avfilter_graph_send_command(filter_graph, "vol", "volume", |
|
|
2684 |
|
r = av_filt_graph_send_cmd(filt_graph, "vol", "volume", |
2465 |
2685 |
double_zero_l10n_str, response, sizeof(response), 0); |
double_zero_l10n_str, response, sizeof(response), 0); |
2466 |
2686 |
if (r < 0) { |
if (r < 0) { |
2467 |
2687 |
warning("ffmpeg:volume context:unable to mute the volume to 0:response from volume filter:%s\n", response); |
warning("ffmpeg:volume context:unable to mute the volume to 0:response from volume filter:%s\n", response); |
|
... |
... |
static void cmd_mute(void) |
2470 |
2690 |
} |
} |
2471 |
2691 |
} |
} |
2472 |
2692 |
} |
} |
2473 |
|
#define NO_RD_THD_RESET false |
|
|
2693 |
|
#define CHANS_N_NOT_OVERRIDDEN 0 |
|
2694 |
|
#define RATE_NOT_OVERRIDDEN 0 |
|
2695 |
|
#define FR_FMT_NOT_OVERRIDDEN AV_FR_FMT_NONE |
2474 |
2696 |
int main(int argc, u8 **args) |
int main(int argc, u8 **args) |
2475 |
2697 |
{ |
{ |
2476 |
2698 |
u8 *url; |
u8 *url; |
2477 |
2699 |
u8 *pcm_str; |
u8 *pcm_str; |
2478 |
2700 |
double initial_vol; |
double initial_vol; |
2479 |
2701 |
int best_st_idx; |
int best_st_idx; |
|
2702 |
|
/* audio override -- start */ |
|
2703 |
|
/* |
|
2704 |
|
* we could have got direct parameters for alsa, but doing only an |
|
2705 |
|
* override triggers an autoconfiguration of any missing parameters |
|
2706 |
|
* based on initial codec params. In other words, the user is not |
|
2707 |
|
* required to provide all audio params, the code will try to fit the |
|
2708 |
|
* missing ones with the initial codec params, which is the default |
|
2709 |
|
* behavior. |
|
2710 |
|
*/ |
|
2711 |
|
int override_initial_ff_chans_n; |
|
2712 |
|
int override_initial_ff_rate; |
|
2713 |
|
enum av_fr_fmt override_initial_ff_audio_fr_fmt; |
|
2714 |
|
/* audio override -- end */ |
2480 |
2715 |
/* "turn on utf8" processing in used libs if any *AND* locale system */ |
/* "turn on utf8" processing in used libs if any *AND* locale system */ |
2481 |
2716 |
setlocale(LC_ALL, ""); |
setlocale(LC_ALL, ""); |
2482 |
2717 |
/* av_log_set_level(AV_LOG_VERBOSE); */ |
/* av_log_set_level(AV_LOG_VERBOSE); */ |
2483 |
2718 |
/* av_log_set_level(AV_LOG_DEBUG); */ |
/* av_log_set_level(AV_LOG_DEBUG); */ |
2484 |
2719 |
url = 0; |
url = 0; |
|
2720 |
|
override_initial_ff_chans_n = CHANS_N_NOT_OVERRIDDEN; |
|
2721 |
|
override_initial_ff_rate = RATE_NOT_OVERRIDDEN; |
|
2722 |
|
override_initial_ff_audio_fr_fmt = FR_FMT_NOT_OVERRIDDEN; |
2485 |
2723 |
pcm_str = "default"; |
pcm_str = "default"; |
2486 |
2724 |
initial_vol = 1.; |
initial_vol = 1.; |
2487 |
|
opts_parse(argc, args, &url, &pcm_str, &initial_vol); |
|
|
2725 |
|
opts_parse(argc, args, &url, &pcm_str, &initial_vol, |
|
2726 |
|
&override_initial_ff_chans_n, &override_initial_ff_rate, |
|
2727 |
|
&override_initial_ff_audio_fr_fmt); |
2488 |
2728 |
init_once(url, pcm_str); |
init_once(url, pcm_str); |
2489 |
2729 |
best_st_idx = find_best_st(); |
best_st_idx = find_best_st(); |
2490 |
2730 |
rd_thd_start(best_st_idx); |
rd_thd_start(best_st_idx); |
2491 |
|
/* play with reset will flush the already dmuxed pkts */ |
|
2492 |
|
play(best_st_idx, initial_vol, NO_RD_THD_RESET); |
|
2493 |
|
/* switch the ffmpeg log to stdout for metadata/etc dump */ |
|
2494 |
|
av_log_set_callback(ffmpeg_log_stdout); |
|
|
2731 |
|
prepare(best_st_idx, initial_vol, override_initial_ff_chans_n, |
|
2732 |
|
override_initial_ff_rate, override_initial_ff_audio_fr_fmt); |
|
2733 |
|
/* switch the ff log to stdout for metadata/etc dump */ |
|
2734 |
|
av_log_set_callback(ff_log_stdout); |
2495 |
2735 |
fmt_ctx_lock(); |
fmt_ctx_lock(); |
2496 |
|
av_dump_format(fmt_ctx, 0, url, 0); |
|
|
2736 |
|
av_dump_fmt(fmt_ctx, 0, url, 0); |
2497 |
2737 |
fmt_ctx_unlock(); |
fmt_ctx_unlock(); |
2498 |
2738 |
av_log_set_callback(av_log_default_callback); |
av_log_set_callback(av_log_default_callback); |
2499 |
|
if (!filt_frs_get()) /* must have some frames to play */ |
|
2500 |
|
exit_ok("no initial audio frames to play\n"); |
|
2501 |
2739 |
loop evts_loop(); |
loop evts_loop(); |
2502 |
2740 |
/* unreachable */ |
/* unreachable */ |
2503 |
2741 |
} |
} |
2504 |
|
#undef NO_RD_THD_RESET |
|
|
2742 |
|
#undef CHANS_N_NOT_OVERRIDDEN |
|
2743 |
|
#undef RATE_NOT_OVERRIDDEN |
|
2744 |
|
#undef AUDIO_FR_FMT_NOT_OVERRIDDEN |
2505 |
2745 |
/*----------------------------------------------------------------------------*/ |
/*----------------------------------------------------------------------------*/ |
2506 |
|
#undef ARRAY_N |
|
2507 |
|
#undef av_frames_alloc |
|
2508 |
|
#undef av_frame_fmt_is_planar |
|
2509 |
|
#undef av_frames_set_silence |
|
2510 |
|
#undef av_frames_unref |
|
2511 |
|
#undef av_get_frame_fmt_name |
|
2512 |
|
#undef av_get_frame_fmt_string |
|
|
2746 |
|
/* alsa */ |
|
2747 |
|
#undef snd_pcm_fmt_desc |
|
2748 |
|
#undef snd_pcm_fmt_set_silence |
|
2749 |
|
#undef SND_PCM_FMT_FLT |
|
2750 |
|
#undef SND_PCM_FMT_S16 |
|
2751 |
|
#undef SND_PCM_FMT_S24 |
|
2752 |
|
#undef SND_PCM_FMT_S32 |
|
2753 |
|
#undef SND_PCM_FMT_S8 |
|
2754 |
|
#undef snd_pcm_fmt_t |
|
2755 |
|
#undef SND_PCM_FMT_U16 |
|
2756 |
|
#undef SND_PCM_FMT_U24 |
|
2757 |
|
#undef SND_PCM_FMT_U32 |
|
2758 |
|
#undef SND_PCM_FMT_U8 |
|
2759 |
|
#undef SND_PCM_ST_PLAYBACK |
|
2760 |
|
#undef snd_pcm_frs_to_bytes |
|
2761 |
|
#undef snd_pcm_hw_params_get_chans |
|
2762 |
|
#undef snd_pcm_hw_params_get_chans_max |
|
2763 |
|
#undef snd_pcm_hw_params_get_chans_min |
|
2764 |
|
#undef snd_pcm_hw_params_get_buf_size |
|
2765 |
|
#undef snd_pcm_hw_params_get_fmt |
|
2766 |
|
#undef snd_pcm_hw_params_set_buf_size_near |
|
2767 |
|
#undef snd_pcm_hw_params_set_chans |
|
2768 |
|
#undef snd_pcm_hw_params_set_fmt |
|
2769 |
|
#undef snd_pcm_hw_params_test_chans |
|
2770 |
|
#undef snd_pcm_hw_params_test_fmt |
|
2771 |
|
#undef snd_pcm_sfrs_t |
|
2772 |
|
#undef snd_pcm_ufrs_t |
|
2773 |
|
/*----------------------------------------------------------------------------*/ |
|
2774 |
|
/* ff */ |
|
2775 |
|
#undef AV_AUDIO_FR_FMT_NONE |
|
2776 |
|
#undef av_bufsink_get_frs |
|
2777 |
|
#undef av_bufsrc_add_frs_flags |
|
2778 |
|
#undef AV_BUFSRC_FLAG_KEEP_REF |
|
2779 |
|
#undef AV_BUFSRC_FLAG_PUSH |
|
2780 |
|
#undef av_codec |
|
2781 |
|
#undef av_codec_ctx |
|
2782 |
|
#undef av_dump_fmt |
|
2783 |
|
#undef av_duration_estimation_method |
|
2784 |
|
#undef av_filt |
|
2785 |
|
#undef av_filt_ctx |
|
2786 |
|
#undef av_filt_get_by_name |
|
2787 |
|
#undef av_filt_graph |
|
2788 |
|
#undef av_filt_graph_alloc |
|
2789 |
|
#undef av_filt_graph_alloc_filt |
|
2790 |
|
#undef av_filt_graph_cfg |
|
2791 |
|
#undef av_filt_graph_dump |
|
2792 |
|
#undef av_filt_graph_free |
|
2793 |
|
#undef av_filt_graph_send_cmd |
|
2794 |
|
#undef av_filt_init_str |
|
2795 |
|
#undef av_filt_link |
|
2796 |
|
#undef av_find_best_st |
|
2797 |
|
#undef av_flush_bufs |
|
2798 |
|
#undef av_fmt_ctx |
|
2799 |
|
#undef AV_FMT_DURATION_FROM_BITRATE |
|
2800 |
|
#undef AV_FMT_DURATION_FROM_PTS |
|
2801 |
|
#undef AV_FMT_DURATION_FROM_ST |
|
2802 |
|
#undef av_fmt_find_st_info |
|
2803 |
|
#undef av_fmt_flush |
|
2804 |
|
#undef av_fmt_open_input |
|
2805 |
|
#undef av_fr_fmt_is_planar |
|
2806 |
|
#undef AV_FR_FMT_FLT |
|
2807 |
|
#undef AV_FR_FMT_FLTP |
|
2808 |
|
#undef AV_FR_FMT_S16 |
|
2809 |
|
#undef AV_FR_FMT_S16P |
|
2810 |
|
#undef AV_FR_FMT_S32 |
|
2811 |
|
#undef AV_FR_FMT_S32P |
|
2812 |
|
#undef AV_FR_FMT_U8P |
|
2813 |
|
#undef AV_FR_FMT_U8 |
|
2814 |
|
#undef av_frs_alloc |
|
2815 |
|
#undef av_frs_set_silence |
|
2816 |
|
#undef av_frs_unref |
|
2817 |
|
#undef av_get_chan_layout_str |
|
2818 |
|
#undef av_get_default_chans_layout |
|
2819 |
|
#undef av_get_fr_fmt_name |
|
2820 |
|
#undef av_get_fr_fmt_str |
|
2821 |
|
#undef av_io_flush |
|
2822 |
|
#undef AV_MEDIA_TYPE_AUDIO |
|
2823 |
|
#undef av_pkt |
|
2824 |
|
#undef av_pkt_unref |
2513 |
2825 |
#undef av_read_pkt |
#undef av_read_pkt |
|
2826 |
|
#undef av_rational |
2514 |
2827 |
#undef av_seek_pkt |
#undef av_seek_pkt |
2515 |
|
#undef avcodec_receive_frames |
|
2516 |
|
#undef AVFrameFormat |
|
2517 |
|
#undef AVFrames |
|
|
2828 |
|
#undef av_receive_frs |
|
2829 |
|
#undef av_fr_fmt |
|
2830 |
|
#undef av_frs |
|
2831 |
|
#undef av_sd_pkt |
|
2832 |
|
#undef av_st |
|
2833 |
|
#undef chan_layout |
|
2834 |
|
#undef chans_n |
|
2835 |
|
#undef format |
|
2836 |
|
#undef fr_fmt |
|
2837 |
|
#undef fr_rate |
|
2838 |
|
#undef frs_n |
|
2839 |
|
#undef st_idx |
|
2840 |
|
#undef sts |
|
2841 |
|
/*----------------------------------------------------------------------------*/ |
|
2842 |
|
#undef ARRAY_N |
2518 |
2843 |
#undef esc_seq_sz |
#undef esc_seq_sz |
2519 |
2844 |
#undef f32 |
#undef f32 |
2520 |
|
#undef frame_fmt |
|
2521 |
|
#undef frame_rate |
|
2522 |
|
#undef frames_n |
|
2523 |
2845 |
#undef INPUT_ESC_SEQ_TIMEOUT_SECS_N |
#undef INPUT_ESC_SEQ_TIMEOUT_SECS_N |
2524 |
2846 |
#undef loop |
#undef loop |
2525 |
2847 |
#undef PCM_POLLFDS_N_MAX |
#undef PCM_POLLFDS_N_MAX |