/src/vlc/modules/codec/avcodec/audio.c
Line | Count | Source |
1 | | /***************************************************************************** |
2 | | * audio.c: audio decoder using libavcodec library |
3 | | ***************************************************************************** |
4 | | * Copyright (C) 1999-2003 VLC authors and VideoLAN |
5 | | * |
6 | | * Authors: Laurent Aimar <fenrir@via.ecp.fr> |
7 | | * Gildas Bazin <gbazin@videolan.org> |
8 | | * |
9 | | * This program is free software; you can redistribute it and/or modify it |
10 | | * under the terms of the GNU Lesser General Public License as published by |
11 | | * the Free Software Foundation; either version 2.1 of the License, or |
12 | | * (at your option) any later version. |
13 | | * |
14 | | * This program is distributed in the hope that it will be useful, |
15 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
17 | | * GNU Lesser General Public License for more details. |
18 | | * |
19 | | * You should have received a copy of the GNU Lesser General Public License |
20 | | * along with this program; if not, write to the Free Software Foundation, |
21 | | * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. |
22 | | *****************************************************************************/ |
23 | | |
24 | | /***************************************************************************** |
25 | | * Preamble |
26 | | *****************************************************************************/ |
27 | | #ifdef HAVE_CONFIG_H |
28 | | # include "config.h" |
29 | | #endif |
30 | | |
31 | | #include <assert.h> |
32 | | |
33 | | #include <vlc_common.h> |
34 | | #include <vlc_aout.h> |
35 | | #include <vlc_codec.h> |
36 | | #include <vlc_avcodec.h> |
37 | | |
38 | | #include "avcodec.h" |
39 | | |
40 | | #include <libavcodec/avcodec.h> |
41 | | #include <libavutil/mem.h> |
42 | | |
43 | | #define API_CHANNEL_LAYOUT_STRUCT (LIBAVCODEC_VERSION_CHECK(59, 24, 100)) // AVCodecContext.ch_layout |
44 | | |
45 | | #include <libavutil/channel_layout.h> |
46 | | |
47 | | |
48 | | /***************************************************************************** |
49 | | * decoder_sys_t : decoder descriptor |
50 | | *****************************************************************************/ |
51 | | typedef struct |
52 | | { |
53 | | AVCodecContext *p_context; |
54 | | const AVCodec *p_codec; |
55 | | |
56 | | /* |
57 | | * Output properties |
58 | | */ |
59 | | audio_sample_format_t aout_format; |
60 | | date_t end_date; |
61 | | |
62 | | /* */ |
63 | | int i_reject_count; |
64 | | |
65 | | /* */ |
66 | | bool b_extract; |
67 | | bool discontinuity; |
68 | | int pi_extraction[AOUT_CHAN_MAX]; |
69 | | int i_previous_channels; |
70 | | uint64_t i_previous_layout; |
71 | | } decoder_sys_t; |
72 | | |
73 | 7.88M | #define BLOCK_FLAG_PRIVATE_REALLOCATED (1 << BLOCK_FLAG_PRIVATE_SHIFT) |
74 | | |
75 | | static void SetupOutputFormat( decoder_t *p_dec, bool b_trust ); |
76 | | static block_t * ConvertAVFrame( decoder_t *p_dec, AVFrame *frame ); |
77 | | static int DecodeAudio( decoder_t *, block_t * ); |
78 | | static void Flush( decoder_t * ); |
79 | | |
80 | | static void InitDecoderConfig( decoder_t *p_dec, AVCodecContext *p_context ) |
81 | 649k | { |
82 | 649k | if( p_dec->fmt_in->i_extra > 0 ) |
83 | 66.4k | { |
84 | 66.4k | const uint8_t * const p_src = p_dec->fmt_in->p_extra; |
85 | | |
86 | 66.4k | int i_offset = 0; |
87 | 66.4k | int i_size = p_dec->fmt_in->i_extra; |
88 | | |
89 | 66.4k | if( p_dec->fmt_in->i_codec == VLC_CODEC_ALAC ) |
90 | 1 | { |
91 | 1 | static const uint8_t p_pattern[] = { 0, 0, 0, 36, 'a', 'l', 'a', 'c' }; |
92 | | /* Find alac atom XXX it is a bit ugly */ |
93 | 21 | for( i_offset = 0; i_offset < i_size - (int)sizeof(p_pattern); i_offset++ ) |
94 | 21 | { |
95 | 21 | if( !memcmp( &p_src[i_offset], p_pattern, sizeof(p_pattern) ) ) |
96 | 1 | break; |
97 | 21 | } |
98 | 1 | i_size = __MIN( p_dec->fmt_in->i_extra - i_offset, 36 ); |
99 | 1 | if( i_size < 36 ) |
100 | 0 | i_size = 0; |
101 | 1 | } |
102 | | |
103 | 66.4k | if( i_size > 0 ) |
104 | 66.4k | { |
105 | 66.4k | p_context->extradata = |
106 | 66.4k | av_malloc( i_size + FF_INPUT_BUFFER_PADDING_SIZE ); |
107 | 66.4k | if( p_context->extradata ) |
108 | 66.4k | { |
109 | 66.4k | uint8_t *p_dst = p_context->extradata; |
110 | | |
111 | 66.4k | p_context->extradata_size = i_size; |
112 | | |
113 | 66.4k | memcpy( &p_dst[0], &p_src[i_offset], i_size ); |
114 | 66.4k | memset( &p_dst[i_size], 0, FF_INPUT_BUFFER_PADDING_SIZE ); |
115 | 66.4k | } |
116 | 66.4k | } |
117 | 66.4k | } |
118 | 583k | else |
119 | 583k | { |
120 | 583k | p_context->extradata_size = 0; |
121 | 583k | p_context->extradata = NULL; |
122 | 583k | } |
123 | 649k | } |
124 | | |
125 | | static int OpenAudioCodec( decoder_t *p_dec ) |
126 | 649k | { |
127 | 649k | decoder_sys_t *p_sys = p_dec->p_sys; |
128 | 649k | AVCodecContext *ctx = p_sys->p_context; |
129 | 649k | const AVCodec *codec = p_sys->p_codec; |
130 | | |
131 | 649k | if( ctx->extradata_size <= 0 ) |
132 | 583k | { |
133 | 583k | if( codec->id == AV_CODEC_ID_VORBIS || |
134 | 583k | ( codec->id == AV_CODEC_ID_AAC && |
135 | 4.85k | !p_dec->fmt_in->b_packetized ) ) |
136 | 0 | { |
137 | 0 | msg_Warn( p_dec, "waiting for extra data for codec %s", |
138 | 0 | codec->name ); |
139 | 0 | return 1; |
140 | 0 | } |
141 | 583k | } |
142 | | |
143 | 649k | ctx->sample_rate = p_dec->fmt_in->audio.i_rate; |
144 | 649k | #if API_CHANNEL_LAYOUT_STRUCT && LIBAVUTIL_VERSION_CHECK(57, 24, 100) |
145 | 649k | av_channel_layout_default( &ctx->ch_layout, p_dec->fmt_in->audio.i_channels ); |
146 | | #else |
147 | | ctx->channels = p_dec->fmt_in->audio.i_channels; |
148 | | #endif |
149 | 649k | ctx->block_align = p_dec->fmt_in->audio.i_blockalign; |
150 | 649k | ctx->bit_rate = p_dec->fmt_in->i_bitrate; |
151 | 649k | ctx->bits_per_coded_sample = p_dec->fmt_in->audio.i_bitspersample; |
152 | | |
153 | 649k | if( codec->id == AV_CODEC_ID_ADPCM_G726 && |
154 | 115 | ctx->bit_rate > 0 && |
155 | 115 | ctx->sample_rate > 0) |
156 | 41 | ctx->bits_per_coded_sample = ctx->bit_rate / ctx->sample_rate; |
157 | | |
158 | 649k | return ffmpeg_OpenCodec( p_dec, ctx, codec ); |
159 | 649k | } |
160 | | |
161 | | /** |
162 | | * Allocates decoded audio buffer for libavcodec to use. |
163 | | */ |
164 | | typedef struct |
165 | | { |
166 | | block_t self; |
167 | | AVFrame *frame; |
168 | | } vlc_av_frame_t; |
169 | | |
170 | | static void vlc_av_frame_Release(block_t *block) |
171 | 0 | { |
172 | 0 | vlc_av_frame_t *b = (void *)block; |
173 | |
|
174 | 0 | av_frame_free(&b->frame); |
175 | 0 | free(b); |
176 | 0 | } |
177 | | |
178 | | static const struct vlc_block_callbacks vlc_av_frame_cbs = |
179 | | { |
180 | | vlc_av_frame_Release, |
181 | | }; |
182 | | |
183 | | static block_t *vlc_av_frame_Wrap(AVFrame *frame) |
184 | 0 | { |
185 | 0 | for (unsigned i = 1; i < AV_NUM_DATA_POINTERS; i++) |
186 | 0 | assert(frame->linesize[i] == 0); /* only packed frame supported */ |
187 | |
|
188 | 0 | if (av_frame_make_writable(frame)) /* TODO: read-only block_t */ |
189 | 0 | return NULL; |
190 | | |
191 | 0 | vlc_av_frame_t *b = malloc(sizeof (*b)); |
192 | 0 | if (unlikely(b == NULL)) |
193 | 0 | return NULL; |
194 | | |
195 | 0 | block_t *block = &b->self; |
196 | |
|
197 | 0 | block_Init(block, &vlc_av_frame_cbs, |
198 | 0 | frame->extended_data[0], frame->linesize[0]); |
199 | 0 | block->i_nb_samples = frame->nb_samples; |
200 | 0 | b->frame = frame; |
201 | 0 | return block; |
202 | 0 | } |
203 | | |
204 | | /***************************************************************************** |
205 | | * EndAudio: decoder destruction |
206 | | ***************************************************************************** |
207 | | * This function is called when the thread ends after a successful |
208 | | * initialization. |
209 | | *****************************************************************************/ |
210 | | void EndAudioDec( vlc_object_t *obj ) |
211 | 584k | { |
212 | 584k | decoder_t *p_dec = (decoder_t *)obj; |
213 | 584k | decoder_sys_t *sys = p_dec->p_sys; |
214 | 584k | AVCodecContext *ctx = sys->p_context; |
215 | | |
216 | 584k | avcodec_free_context( &ctx ); |
217 | 584k | free( sys ); |
218 | 584k | } |
219 | | |
220 | | /***************************************************************************** |
221 | | * InitAudioDec: initialize audio decoder |
222 | | ***************************************************************************** |
223 | | * The avcodec codec will be opened, some memory allocated. |
224 | | *****************************************************************************/ |
225 | | int InitAudioDec( vlc_object_t *obj ) |
226 | 652k | { |
227 | 652k | decoder_t *p_dec = (decoder_t *)obj; |
228 | 652k | const AVCodec *codec; |
229 | 652k | AVCodecContext *avctx = ffmpeg_AllocContext( p_dec, &codec ); |
230 | 652k | if( avctx == NULL ) |
231 | 2.54k | return VLC_EGENERIC; |
232 | | |
233 | | /* Allocate the memory needed to store the decoder's structure */ |
234 | 649k | decoder_sys_t *p_sys = malloc(sizeof(*p_sys)); |
235 | 649k | if( unlikely(p_sys == NULL) ) |
236 | 0 | { |
237 | 0 | avcodec_free_context( &avctx ); |
238 | 0 | return VLC_ENOMEM; |
239 | 0 | } |
240 | | |
241 | 649k | p_dec->p_sys = p_sys; |
242 | 649k | p_sys->p_context = avctx; |
243 | 649k | p_sys->p_codec = codec; |
244 | | |
245 | | // Initialize decoder extradata |
246 | 649k | InitDecoderConfig( p_dec, avctx ); |
247 | | |
248 | | /* ***** Open the codec ***** */ |
249 | 649k | if( OpenAudioCodec( p_dec ) < 0 ) |
250 | 64.8k | { |
251 | 64.8k | free( p_sys ); |
252 | 64.8k | avcodec_free_context( &avctx ); |
253 | 64.8k | return VLC_EGENERIC; |
254 | 64.8k | } |
255 | | |
256 | 584k | p_sys->i_reject_count = 0; |
257 | 584k | p_sys->b_extract = false; |
258 | 584k | p_sys->i_previous_channels = 0; |
259 | 584k | p_sys->i_previous_layout = 0; |
260 | 584k | p_sys->discontinuity = false; |
261 | | |
262 | | /* */ |
263 | | /* Try to set as much information as possible but do not trust it */ |
264 | 584k | SetupOutputFormat( p_dec, false ); |
265 | | |
266 | 584k | if( !p_dec->fmt_out.audio.i_rate ) |
267 | 10.4k | p_dec->fmt_out.audio.i_rate = p_dec->fmt_in->audio.i_rate; |
268 | 584k | if( p_dec->fmt_out.audio.i_rate ) |
269 | 574k | date_Init( &p_sys->end_date, p_dec->fmt_out.audio.i_rate, 1 ); |
270 | 584k | p_dec->fmt_out.audio.i_chan_mode = p_dec->fmt_in->audio.i_chan_mode; |
271 | | |
272 | 584k | p_dec->pf_decode = DecodeAudio; |
273 | 584k | p_dec->pf_flush = Flush; |
274 | | |
275 | 584k | return VLC_SUCCESS; |
276 | 649k | } |
277 | | |
278 | | /***************************************************************************** |
279 | | * Flush: |
280 | | *****************************************************************************/ |
281 | | static void Flush( decoder_t *p_dec ) |
282 | 0 | { |
283 | 0 | decoder_sys_t *p_sys = p_dec->p_sys; |
284 | 0 | AVCodecContext *ctx = p_sys->p_context; |
285 | |
|
286 | 0 | if( avcodec_is_open( ctx ) ) |
287 | 0 | avcodec_flush_buffers( ctx ); |
288 | 0 | date_Set( &p_sys->end_date, VLC_TICK_INVALID ); |
289 | |
|
290 | 0 | if( ctx->codec_id == AV_CODEC_ID_MP2 || |
291 | 0 | ctx->codec_id == AV_CODEC_ID_MP3 ) |
292 | 0 | p_sys->i_reject_count = 3; |
293 | 0 | p_sys->discontinuity = false; |
294 | 0 | } |
295 | | |
296 | | /***************************************************************************** |
297 | | * DecodeBlock: Called to decode one frame |
298 | | *****************************************************************************/ |
299 | | static int DecodeBlock( decoder_t *p_dec, block_t **pp_block ) |
300 | 8.11M | { |
301 | 8.11M | decoder_sys_t *p_sys = p_dec->p_sys; |
302 | 8.11M | AVCodecContext *ctx = p_sys->p_context; |
303 | 8.11M | AVFrame *frame = NULL; |
304 | 8.11M | block_t *p_block = NULL; |
305 | 8.11M | bool b_error = false; |
306 | | |
307 | 8.11M | if( !ctx->extradata_size && p_dec->fmt_in->i_extra |
308 | 0 | && !avcodec_is_open( ctx ) ) |
309 | 0 | { |
310 | 0 | InitDecoderConfig( p_dec, ctx ); |
311 | 0 | if( OpenAudioCodec( p_dec ) < 0 ) |
312 | 0 | { |
313 | 0 | if( pp_block != NULL && *pp_block != NULL ) |
314 | 0 | block_Release( *pp_block ); |
315 | 0 | return VLCDEC_ECRITICAL; |
316 | 0 | } |
317 | 0 | } |
318 | | |
319 | 8.11M | if( !avcodec_is_open( ctx ) ) |
320 | 0 | { |
321 | 0 | if( pp_block ) |
322 | 0 | p_block = *pp_block; |
323 | 0 | goto drop; |
324 | 0 | } |
325 | | |
326 | 8.11M | if( pp_block == NULL ) /* Drain request */ |
327 | 4.17M | { |
328 | | /* we don't need to care about return val */ |
329 | 4.17M | (void) avcodec_send_packet( ctx, NULL ); |
330 | 4.17M | } |
331 | 3.94M | else |
332 | 3.94M | { |
333 | 3.94M | p_block = *pp_block; |
334 | 3.94M | } |
335 | | |
336 | 8.11M | if( p_block ) |
337 | 3.94M | { |
338 | 3.94M | if( p_block->i_flags & BLOCK_FLAG_CORRUPTED ) |
339 | 0 | { |
340 | 0 | Flush( p_dec ); |
341 | 0 | goto drop; |
342 | 0 | } |
343 | | |
344 | 3.94M | if( p_block->i_flags & BLOCK_FLAG_DISCONTINUITY ) |
345 | 9.20k | { |
346 | 9.20k | date_Set( &p_sys->end_date, VLC_TICK_INVALID ); |
347 | 9.20k | } |
348 | | |
349 | | /* We've just started the stream, wait for the first PTS. */ |
350 | 3.94M | if( p_block->i_pts == VLC_TICK_INVALID && |
351 | 1.15k | date_Get( &p_sys->end_date ) == VLC_TICK_INVALID ) |
352 | 1.15k | goto drop; |
353 | | |
354 | 3.94M | if( p_block->i_buffer <= 0 ) |
355 | 1.54k | goto drop; |
356 | | |
357 | 3.94M | if( (p_block->i_flags & BLOCK_FLAG_PRIVATE_REALLOCATED) == 0 ) |
358 | 3.94M | { |
359 | 3.94M | *pp_block = p_block = block_Realloc( p_block, 0, p_block->i_buffer + FF_INPUT_BUFFER_PADDING_SIZE ); |
360 | 3.94M | if( !p_block ) |
361 | 0 | goto end; |
362 | 3.94M | p_block->i_buffer -= FF_INPUT_BUFFER_PADDING_SIZE; |
363 | 3.94M | memset( &p_block->p_buffer[p_block->i_buffer], 0, FF_INPUT_BUFFER_PADDING_SIZE ); |
364 | | |
365 | 3.94M | p_block->i_flags |= BLOCK_FLAG_PRIVATE_REALLOCATED; |
366 | 3.94M | } |
367 | 3.94M | } |
368 | | |
369 | 8.11M | frame = av_frame_alloc(); |
370 | 8.11M | if (unlikely(frame == NULL)) |
371 | 0 | goto end; |
372 | | |
373 | 8.11M | bool send_failed = false; |
374 | 13.2M | for( int ret = 0; ret == 0; ) |
375 | 8.11M | { |
376 | | /* Feed in the loop as buffer could have been full on first iterations */ |
377 | 8.11M | if( p_block ) |
378 | 3.94M | { |
379 | 3.94M | AVPacket *pkt = av_packet_alloc(); |
380 | 3.94M | if( !pkt ) |
381 | 0 | goto end; |
382 | 3.94M | pkt->data = p_block->p_buffer; |
383 | 3.94M | pkt->size = p_block->i_buffer; |
384 | 3.94M | ret = avcodec_send_packet( ctx, pkt ); |
385 | 3.94M | av_packet_free(&pkt); |
386 | 3.94M | if( ret == 0 ) /* Block has been consumed */ |
387 | 2.96M | { |
388 | | /* Only set new pts from input block if it has been used, |
389 | | * otherwise let it be through interpolation */ |
390 | 2.96M | if( p_block->i_pts > date_Get( &p_sys->end_date ) ) |
391 | 2.62M | { |
392 | 2.62M | date_Set( &p_sys->end_date, p_block->i_pts ); |
393 | 2.62M | } |
394 | | |
395 | 2.96M | block_Release( p_block ); |
396 | 2.96M | *pp_block = p_block = NULL; |
397 | 2.96M | } |
398 | 976k | else if ( ret != AVERROR(EAGAIN) ) /* Errors other than buffer full */ |
399 | 967k | { |
400 | 967k | if( ret == AVERROR(ENOMEM) || ret == AVERROR(EINVAL) ) |
401 | 134 | goto end; |
402 | 967k | else |
403 | 967k | { |
404 | 967k | char errorstring[AV_ERROR_MAX_STRING_SIZE]; |
405 | 967k | if( !av_strerror( ret, errorstring, AV_ERROR_MAX_STRING_SIZE ) ) |
406 | 967k | msg_Err( p_dec, "%s", errorstring ); |
407 | | |
408 | | /* Signal an error, but continue to receive all output |
409 | | * frames. A discontinuity will be triggered for the |
410 | | * output frame coming right after the dropped one. */ |
411 | 967k | send_failed = true; |
412 | 967k | block_Release( p_block ); |
413 | 967k | *pp_block = p_block = NULL; |
414 | 967k | } |
415 | 967k | } |
416 | 3.94M | } |
417 | | |
418 | | /* Try to read one or multiple frames */ |
419 | 8.11M | ret = avcodec_receive_frame( ctx, frame ); |
420 | 8.11M | if( ret == 0 ) |
421 | 2.95M | { |
422 | 2.95M | #if LIBAVUTIL_VERSION_CHECK(57, 24, 100) |
423 | 2.95M | int channels = frame->ch_layout.nb_channels; |
424 | | #else |
425 | | int channels = ctx->channels; |
426 | | #endif |
427 | | /* checks and init from first decoded frame */ |
428 | 2.95M | if( channels <= 0 || channels > INPUT_CHAN_MAX |
429 | 2.94M | || ctx->sample_rate <= 0 ) |
430 | 13.9k | { |
431 | 13.9k | msg_Warn( p_dec, "invalid audio properties channels count %d, sample rate %d", |
432 | 13.9k | channels, ctx->sample_rate ); |
433 | 13.9k | goto drop; |
434 | 13.9k | } |
435 | 2.94M | else if( p_dec->fmt_out.audio.i_rate != (unsigned int)ctx->sample_rate ) |
436 | 281 | { |
437 | 281 | date_Init( &p_sys->end_date, ctx->sample_rate, 1 ); |
438 | 281 | } |
439 | | |
440 | 2.94M | SetupOutputFormat( p_dec, true ); |
441 | 2.94M | if( decoder_UpdateAudioFormat( p_dec ) ) |
442 | 2.94M | goto drop; |
443 | | |
444 | 0 | block_t *p_converted = ConvertAVFrame( p_dec, frame ); /* Consumes frame */ |
445 | 0 | if( p_converted ) |
446 | 0 | { |
447 | | /* Silent unwanted samples */ |
448 | 0 | if( p_sys->i_reject_count > 0 ) |
449 | 0 | { |
450 | 0 | memset( p_converted->p_buffer, 0, p_converted->i_buffer ); |
451 | 0 | p_sys->i_reject_count--; |
452 | 0 | } |
453 | 0 | p_converted->i_buffer = p_converted->i_nb_samples |
454 | 0 | * p_dec->fmt_out.audio.i_bytes_per_frame; |
455 | 0 | p_converted->i_pts = date_Get( &p_sys->end_date ); |
456 | 0 | p_converted->i_length = date_Increment( &p_sys->end_date, |
457 | 0 | p_converted->i_nb_samples ) - p_converted->i_pts; |
458 | |
|
459 | 0 | if (p_sys->discontinuity) |
460 | 0 | { |
461 | 0 | p_sys->discontinuity = false; |
462 | 0 | p_converted->i_flags |= BLOCK_FLAG_DISCONTINUITY; |
463 | 0 | } |
464 | 0 | decoder_QueueAudio( p_dec, p_converted ); |
465 | 0 | } |
466 | | |
467 | | /* Prepare new frame */ |
468 | 0 | frame = av_frame_alloc(); |
469 | 0 | if (unlikely(frame == NULL)) |
470 | 0 | break; |
471 | 0 | } |
472 | 5.16M | else |
473 | 5.16M | { |
474 | | /* After draining, we need to reset decoder with a flush */ |
475 | 5.16M | if( ret == AVERROR_EOF ) |
476 | 4.17M | avcodec_flush_buffers( p_sys->p_context ); |
477 | 5.16M | av_frame_free( &frame ); |
478 | 5.16M | } |
479 | 8.11M | }; |
480 | | |
481 | 5.16M | if (send_failed) |
482 | 967k | { |
483 | | /* Signal a discontinuity for the next output frame. */ |
484 | 967k | p_sys->discontinuity = true; |
485 | 967k | } |
486 | | |
487 | 5.16M | return VLCDEC_SUCCESS; |
488 | | |
489 | 134 | end: |
490 | 134 | b_error = true; |
491 | 2.95M | drop: |
492 | | /* Signal a discontinuity for the next output frame. */ |
493 | 2.95M | p_sys->discontinuity = true; |
494 | 2.95M | if( pp_block ) |
495 | 2.95M | { |
496 | 2.95M | assert( *pp_block == p_block ); |
497 | 2.95M | *pp_block = NULL; |
498 | 2.95M | } |
499 | 2.95M | if( p_block != NULL ) |
500 | 10.8k | block_Release(p_block); |
501 | 2.95M | if( frame != NULL ) |
502 | 2.95M | av_frame_free( &frame ); |
503 | | |
504 | 2.95M | return (b_error) ? VLCDEC_ECRITICAL : VLCDEC_SUCCESS; |
505 | 2.95M | } |
506 | | |
507 | | static int DecodeAudio( decoder_t *p_dec, block_t *p_block ) |
508 | 8.11M | { |
509 | 8.11M | block_t **pp_block = p_block ? &p_block : NULL; |
510 | 8.11M | int i_ret; |
511 | 8.11M | do |
512 | 8.11M | { |
513 | 8.11M | i_ret = DecodeBlock( p_dec, pp_block ); |
514 | 8.11M | } |
515 | 8.11M | while( i_ret == VLCDEC_SUCCESS && pp_block && *pp_block ); |
516 | | |
517 | 8.11M | return i_ret; |
518 | 8.11M | } |
519 | | |
520 | | static block_t * ConvertAVFrame( decoder_t *p_dec, AVFrame *frame ) |
521 | 0 | { |
522 | 0 | decoder_sys_t *p_sys = p_dec->p_sys; |
523 | 0 | AVCodecContext *ctx = p_sys->p_context; |
524 | 0 | block_t *p_block; |
525 | | |
526 | | /* Interleave audio if required */ |
527 | 0 | if( av_sample_fmt_is_planar( ctx->sample_fmt ) ) |
528 | 0 | { |
529 | 0 | p_block = block_Alloc(frame->linesize[0] * p_dec->fmt_out.audio.i_channels ); |
530 | 0 | if ( likely(p_block) ) |
531 | 0 | { |
532 | 0 | const void *planes[p_dec->fmt_out.audio.i_channels]; |
533 | 0 | for (int i = 0; i < p_dec->fmt_out.audio.i_channels; i++) |
534 | 0 | planes[i] = frame->extended_data[i]; |
535 | |
|
536 | 0 | aout_Interleave(p_block->p_buffer, planes, frame->nb_samples, |
537 | 0 | p_dec->fmt_out.audio.i_channels, p_dec->fmt_out.audio.i_format); |
538 | 0 | p_block->i_nb_samples = frame->nb_samples; |
539 | 0 | } |
540 | 0 | av_frame_free(&frame); |
541 | 0 | } |
542 | 0 | else |
543 | 0 | { |
544 | 0 | p_block = vlc_av_frame_Wrap(frame); |
545 | 0 | frame = NULL; |
546 | 0 | } |
547 | |
|
548 | 0 | if (p_sys->b_extract && p_block) |
549 | 0 | { /* TODO: do not drop channels... at least not here */ |
550 | 0 | block_t *p_buffer = block_Alloc( p_dec->fmt_out.audio.i_bytes_per_frame |
551 | 0 | * p_block->i_nb_samples ); |
552 | 0 | if( likely(p_buffer) ) |
553 | 0 | { |
554 | 0 | aout_ChannelExtract( p_buffer->p_buffer, |
555 | 0 | p_dec->fmt_out.audio.i_channels, |
556 | 0 | p_block->p_buffer, p_dec->fmt_out.audio.i_channels, |
557 | 0 | p_block->i_nb_samples, p_sys->pi_extraction, |
558 | 0 | p_dec->fmt_out.audio.i_bitspersample ); |
559 | 0 | p_buffer->i_nb_samples = p_block->i_nb_samples; |
560 | 0 | } |
561 | 0 | block_Release( p_block ); |
562 | 0 | p_block = p_buffer; |
563 | 0 | } |
564 | |
|
565 | 0 | return p_block; |
566 | 0 | } |
567 | | |
568 | | /***************************************************************************** |
569 | | * |
570 | | *****************************************************************************/ |
571 | | |
572 | | vlc_fourcc_t GetVlcAudioFormat( int fmt ) |
573 | 3.52M | { |
574 | 3.52M | static const vlc_fourcc_t fcc[] = { |
575 | 3.52M | [AV_SAMPLE_FMT_U8] = VLC_CODEC_U8, |
576 | 3.52M | [AV_SAMPLE_FMT_S16] = VLC_CODEC_S16N, |
577 | 3.52M | [AV_SAMPLE_FMT_S32] = VLC_CODEC_S32N, |
578 | 3.52M | [AV_SAMPLE_FMT_FLT] = VLC_CODEC_FL32, |
579 | 3.52M | [AV_SAMPLE_FMT_DBL] = VLC_CODEC_FL64, |
580 | 3.52M | [AV_SAMPLE_FMT_U8P] = VLC_CODEC_U8, |
581 | 3.52M | [AV_SAMPLE_FMT_S16P] = VLC_CODEC_S16N, |
582 | 3.52M | [AV_SAMPLE_FMT_S32P] = VLC_CODEC_S32N, |
583 | 3.52M | [AV_SAMPLE_FMT_FLTP] = VLC_CODEC_FL32, |
584 | 3.52M | [AV_SAMPLE_FMT_DBLP] = VLC_CODEC_FL64, |
585 | 3.52M | }; |
586 | 3.52M | if( ARRAY_SIZE(fcc) > (unsigned)fmt ) |
587 | 3.49M | return fcc[fmt]; |
588 | 30.5k | return VLC_CODEC_S16N; |
589 | 3.52M | } |
590 | | |
591 | | static const uint64_t pi_channels_map[][2] = |
592 | | { |
593 | | { AV_CH_FRONT_LEFT, AOUT_CHAN_LEFT }, |
594 | | { AV_CH_FRONT_RIGHT, AOUT_CHAN_RIGHT }, |
595 | | { AV_CH_FRONT_CENTER, AOUT_CHAN_CENTER }, |
596 | | { AV_CH_LOW_FREQUENCY, AOUT_CHAN_LFE }, |
597 | | { AV_CH_BACK_LEFT, AOUT_CHAN_REARLEFT }, |
598 | | { AV_CH_BACK_RIGHT, AOUT_CHAN_REARRIGHT }, |
599 | | { AV_CH_FRONT_LEFT_OF_CENTER, 0 }, |
600 | | { AV_CH_FRONT_RIGHT_OF_CENTER, 0 }, |
601 | | { AV_CH_BACK_CENTER, AOUT_CHAN_REARCENTER }, |
602 | | { AV_CH_SIDE_LEFT, AOUT_CHAN_MIDDLELEFT }, |
603 | | { AV_CH_SIDE_RIGHT, AOUT_CHAN_MIDDLERIGHT }, |
604 | | { AV_CH_TOP_CENTER, 0 }, |
605 | | { AV_CH_TOP_FRONT_LEFT, 0 }, |
606 | | { AV_CH_TOP_FRONT_CENTER, 0 }, |
607 | | { AV_CH_TOP_FRONT_RIGHT, 0 }, |
608 | | { AV_CH_TOP_BACK_LEFT, 0 }, |
609 | | { AV_CH_TOP_BACK_CENTER, 0 }, |
610 | | { AV_CH_TOP_BACK_RIGHT, 0 }, |
611 | | { AV_CH_STEREO_LEFT, 0 }, |
612 | | { AV_CH_STEREO_RIGHT, 0 }, |
613 | | { 0, 0 }, |
614 | | }; |
615 | | |
616 | | static void SetupOutputFormat( decoder_t *p_dec, bool b_trust ) |
617 | 3.52M | { |
618 | 3.52M | decoder_sys_t *p_sys = p_dec->p_sys; |
619 | | |
620 | 3.52M | p_dec->fmt_out.i_codec = GetVlcAudioFormat( p_sys->p_context->sample_fmt ); |
621 | 3.52M | p_dec->fmt_out.audio.channel_type = p_dec->fmt_in->audio.channel_type; |
622 | 3.52M | p_dec->fmt_out.audio.i_format = p_dec->fmt_out.i_codec; |
623 | 3.52M | p_dec->fmt_out.audio.i_rate = p_sys->p_context->sample_rate; |
624 | | |
625 | | /* */ |
626 | 3.52M | #if API_CHANNEL_LAYOUT_STRUCT |
627 | 3.52M | if( p_sys->i_previous_channels == p_sys->p_context->ch_layout.nb_channels && |
628 | 2.88M | p_sys->i_previous_layout == p_sys->p_context->ch_layout.u.mask ) |
629 | 2.88M | return; |
630 | 639k | if( b_trust ) |
631 | 85.3k | { |
632 | 85.3k | p_sys->i_previous_channels = p_sys->p_context->ch_layout.nb_channels; |
633 | 85.3k | p_sys->i_previous_layout = p_sys->p_context->ch_layout.u.mask; |
634 | 85.3k | } |
635 | | #else |
636 | | if( p_sys->i_previous_channels == p_sys->p_context->channels && |
637 | | p_sys->i_previous_layout == p_sys->p_context->channel_layout ) |
638 | | return; |
639 | | if( b_trust ) |
640 | | { |
641 | | p_sys->i_previous_channels = p_sys->p_context->channels; |
642 | | p_sys->i_previous_layout = p_sys->p_context->channel_layout; |
643 | | } |
644 | | #endif |
645 | | |
646 | 639k | int i_channels_src = 0; |
647 | 639k | #if API_CHANNEL_LAYOUT_STRUCT |
648 | 639k | uint64_t channel_layout_mask = p_sys->p_context->ch_layout.u.mask; |
649 | 639k | int channel_count = p_sys->p_context->ch_layout.nb_channels; |
650 | | #else |
651 | | uint64_t channel_layout_mask = |
652 | | p_sys->p_context->channel_layout ? p_sys->p_context->channel_layout : |
653 | | (uint64_t)av_get_default_channel_layout( p_sys->p_context->channels ); |
654 | | int channel_count = p_sys->p_context->channels; |
655 | | #endif |
656 | | |
657 | 639k | if( channel_layout_mask ) |
658 | 637k | { |
659 | 637k | uint32_t* pi_order_src = calloc(channel_count,sizeof(uint32_t)); |
660 | | |
661 | 637k | if( unlikely(pi_order_src == NULL) ) |
662 | 0 | { |
663 | 0 | p_dec->fmt_out.audio.i_physical_channels = 0; |
664 | 0 | p_dec->fmt_out.audio.i_channels = channel_count; |
665 | |
|
666 | 0 | aout_FormatPrepare(&p_dec->fmt_out.audio); |
667 | 0 | return; |
668 | 0 | } |
669 | | |
670 | 2.96M | for( unsigned i = 0; pi_channels_map[i][0] |
671 | 2.96M | && i_channels_src < channel_count; i++ ) |
672 | 2.33M | { |
673 | 2.33M | if( channel_layout_mask & pi_channels_map[i][0] ) |
674 | 1.17M | pi_order_src[i_channels_src++] = pi_channels_map[i][1]; |
675 | 2.33M | } |
676 | | |
677 | 637k | if( i_channels_src != channel_count && b_trust ) |
678 | 637k | msg_Err( p_dec, "Channel layout not understood" ); |
679 | | |
680 | | /* Detect special dual mono case */ |
681 | 637k | if( i_channels_src == 2 && pi_order_src[0] == AOUT_CHAN_CENTER |
682 | 2.44k | && pi_order_src[1] == AOUT_CHAN_CENTER ) |
683 | 0 | { |
684 | 0 | p_dec->fmt_out.audio.i_chan_mode |= AOUT_CHANMODE_DUALMONO; |
685 | 0 | pi_order_src[0] = AOUT_CHAN_LEFT; |
686 | 0 | pi_order_src[1] = AOUT_CHAN_RIGHT; |
687 | 0 | } |
688 | | |
689 | 637k | uint32_t i_layout_dst; |
690 | 637k | int i_channels_dst; |
691 | 637k | p_sys->b_extract = aout_CheckChannelExtraction( p_sys->pi_extraction, |
692 | 637k | &i_layout_dst, &i_channels_dst, |
693 | 637k | NULL, pi_order_src, i_channels_src ); |
694 | 637k | if( i_channels_dst != i_channels_src && b_trust ) |
695 | 637k | msg_Warn( p_dec, "%d channels are dropped", i_channels_src - i_channels_dst ); |
696 | | |
697 | | /* No reordering for Ambisonic order 1 channels encoded in AAC... */ |
698 | 637k | if (p_dec->fmt_out.audio.channel_type == AUDIO_CHANNEL_TYPE_AMBISONICS |
699 | 637k | && p_dec->fmt_in->i_codec == VLC_CODEC_MP4A |
700 | 0 | && i_channels_src == 4) |
701 | 0 | p_sys->b_extract = false; |
702 | | |
703 | 637k | p_dec->fmt_out.audio.i_physical_channels = i_layout_dst; |
704 | 637k | free(pi_order_src); |
705 | 637k | } |
706 | 1.93k | else |
707 | 1.93k | { |
708 | 1.93k | msg_Warn( p_dec, "no channel layout found"); |
709 | 1.93k | p_dec->fmt_out.audio.i_physical_channels = 0; |
710 | 1.93k | p_dec->fmt_out.audio.i_channels = channel_count; |
711 | 1.93k | } |
712 | | |
713 | 639k | aout_FormatPrepare( &p_dec->fmt_out.audio ); |
714 | 639k | } |
715 | | |