1 /* Copyright (C) 2006 Andre Noll <maan@tuebingen.mpg.de>, see file COPYING. */
3 * based in parts on libfaad, Copyright (C) 2003-2005 M. Bakker,
7 /** \file aacdec_filter.c paraslash's aac (m4a) decoder. */
13 #include "portable_io.h"
16 #include "buffer_tree.h"
21 /** Give up decoding after that many errors. */
25 * data specific to the aacdec filter
27 * \sa \ref filter, \ref filter_node.
29 struct private_aacdec_data
{
30 /** the return value of aac_open */
31 NeAACDecHandle handle
;
32 /** whether this instance of the aac decoder is already initialized */
34 /** number of times the decoder returned an error */
36 /** number of bytes already consumed from the imput stream */
37 size_t consumed_total
;
38 /** The number of channels of the current stream. */
39 unsigned int channels
;
40 /** Current sample rate in Hz. */
41 unsigned int sample_rate
;
44 static int aacdec_execute(struct btr_node
*btrn
, const char *cmd
, char **result
)
46 struct filter_node
*fn
= btr_context(btrn
);
47 struct private_aacdec_data
*padd
= fn
->private_data
;
49 return decoder_execute(cmd
, padd
->sample_rate
, padd
->channels
, result
);
52 static void aacdec_open(struct filter_node
*fn
)
54 NeAACDecConfigurationPtr c
;
55 struct private_aacdec_data
*padd
= para_calloc(sizeof(*padd
));
57 padd
->handle
= NeAACDecOpen();
58 c
= NeAACDecGetCurrentConfiguration(padd
->handle
);
59 c
->defObjectType
= LC
;
60 c
->outputFormat
= FAAD_FMT_16BIT
;
62 NeAACDecSetConfiguration(padd
->handle
, c
);
64 fn
->private_data
= padd
;
68 static void aacdec_close(struct filter_node
*fn
)
70 struct private_aacdec_data
*padd
= fn
->private_data
;
72 NeAACDecClose(padd
->handle
);
74 fn
->private_data
= NULL
;
77 static int aacdec_post_select(__a_unused
struct sched
*s
, void *context
)
79 struct filter_node
*fn
= context
;
80 struct btr_node
*btrn
= fn
->btrn
;
81 struct private_aacdec_data
*padd
= fn
->private_data
;
83 char *inbuf
, *outbuf
, *btrbuf
;
84 size_t len
, consumed
, loaded
= 0;
85 NeAACDecFrameInfo frame_info
;
88 ret
= btr_node_status(btrn
, fn
->min_iqs
, BTR_NT_INTERNAL
);
93 btr_merge(btrn
, fn
->min_iqs
);
94 len
= btr_next_buffer(btrn
, &inbuf
);
95 len
= PARA_MIN(len
, (size_t)8192);
97 if (!padd
->initialized
) {
98 unsigned long rate
= 0;
99 unsigned char channels
= 0;
100 ret
= NeAACDecInit(padd
->handle
, (unsigned char *)inbuf
,
101 len
, &rate
, &channels
);
102 PARA_INFO_LOG("decoder init: %d\n", ret
);
104 ret
= -E_AACDEC_INIT
;
108 padd
->sample_rate
= rate
;
109 padd
->channels
= channels
;
110 PARA_INFO_LOG("rate: %u, channels: %u\n",
111 padd
->sample_rate
, padd
->channels
);
112 padd
->initialized
= true;
116 //PARA_CRIT_LOG("consumed: %zu (%zu + %zu), have: %zu\n", padd->consumed_total + consumed,
117 // padd->consumed_total, consumed, len - consumed);
118 outbuf
= NeAACDecDecode(padd
->handle
, &frame_info
,
119 (unsigned char *)inbuf
+ consumed
, len
- consumed
);
120 if (frame_info
.error
) {
121 int err
= frame_info
.error
;
123 if (padd
->error_count
++ > MAX_ERRORS
)
125 PARA_NOTICE_LOG("error #%u: (%s)\n", padd
->error_count
,
126 NeAACDecGetErrorMessage(err
));
127 PARA_NOTICE_LOG("consumed (total, buffer, frame): "
129 padd
->consumed_total
, consumed
,
130 frame_info
.bytesconsumed
);
131 consumed
++; /* just eat one byte and hope for the best */
134 padd
->error_count
= 0;
135 //PARA_CRIT_LOG("decoder ate %lu\n", frame_info.bytesconsumed);
136 consumed
+= frame_info
.bytesconsumed
;
137 if (!frame_info
.samples
)
139 btrbuf
= para_malloc(2 * frame_info
.samples
);
140 for (i
= 0; i
< frame_info
.samples
; i
++) {
141 short sh
= ((short *)outbuf
)[i
];
142 write_int16_host_endian(btrbuf
+ loaded
, sh
);
145 btr_add_output(btrbuf
, loaded
, btrn
);
147 btr_consume(btrn
, consumed
);
148 padd
->consumed_total
+= consumed
;
154 btr_remove_node(&fn
->btrn
);
158 const struct filter lsg_filter_cmd_com_aacdec_user_data
= {
160 .close
= aacdec_close
,
161 .pre_select
= generic_filter_pre_select
,
162 .post_select
= aacdec_post_select
,
163 .execute
= aacdec_execute