3 * Copyright (c) 2015 Vesselin Bontchev
5 * Header parsing is borrowed from https://github.com/jteeuwen/audible project.
6 * Copyright (c) 2001-2014, Jim Teeuwen
8 * Redistribution and use in source and binary forms, with or without modification,
9 * are permitted provided that the following conditions are met:
11 * 1. Redistributions of source code must retain the above copyright notice, this
12 * list of conditions and the following disclaimer.
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
18 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 #include "libavutil/intreadwrite.h"
29 #include "libavutil/tea.h"
30 #include "libavutil/opt.h"
32 #define AA_MAGIC 1469084982 /* this identifies an audible .aa file */
33 #define MAX_CODEC_SECOND_SIZE 3982
34 #define MAX_TOC_ENTRIES 16
35 #define MAX_DICTIONARY_ENTRIES 128
36 #define TEA_BLOCK_SIZE 8
38 typedef struct AADemuxContext
{
40 uint8_t *aa_fixed_key
;
42 int codec_second_size
;
43 int current_codec_second_size
;
45 struct AVTEA
*tea_ctx
;
47 int64_t current_chapter_size
;
50 static int get_second_size(char *codec_name
)
54 if (!strcmp(codec_name
, "mp332")) {
56 } else if (!strcmp(codec_name
, "acelp16")) {
58 } else if (!strcmp(codec_name
, "acelp85")) {
65 static int aa_read_header(AVFormatContext
*s
)
67 int i
, j
, idx
, largest_idx
= -1;
68 uint32_t nkey
, nval
, toc_size
, npairs
, header_seed
= 0, start
;
69 char key
[128], val
[128], codec_name
[64] = {0};
70 uint8_t output
[24], dst
[8], src
[8];
71 int64_t largest_size
= -1, current_size
= -1;
75 } TOC
[MAX_TOC_ENTRIES
];
76 uint32_t header_key_part
[4];
77 uint8_t header_key
[16] = {0};
78 AADemuxContext
*c
= s
->priv_data
;
79 AVIOContext
*pb
= s
->pb
;
83 /* parse .aa header */
84 avio_skip(pb
, 4); // file size
85 avio_skip(pb
, 4); // magic string
86 toc_size
= avio_rb32(pb
); // TOC size
87 avio_skip(pb
, 4); // unidentified integer
88 if (toc_size
> MAX_TOC_ENTRIES
|| toc_size
< 2)
89 return AVERROR_INVALIDDATA
;
90 for (i
= 0; i
< toc_size
; i
++) { // read TOC
91 avio_skip(pb
, 4); // TOC entry index
92 TOC
[i
].offset
= avio_rb32(pb
); // block offset
93 TOC
[i
].size
= avio_rb32(pb
); // block size
95 avio_skip(pb
, 24); // header termination block (ignored)
96 npairs
= avio_rb32(pb
); // read dictionary entries
97 if (npairs
> MAX_DICTIONARY_ENTRIES
)
98 return AVERROR_INVALIDDATA
;
99 for (i
= 0; i
< npairs
; i
++) {
100 memset(val
, 0, sizeof(val
));
101 memset(key
, 0, sizeof(key
));
102 avio_skip(pb
, 1); // unidentified integer
103 nkey
= avio_rb32(pb
); // key string length
104 nval
= avio_rb32(pb
); // value string length
105 if (nkey
> sizeof(key
)) {
108 avio_read(pb
, key
, nkey
); // key string
110 if (nval
> sizeof(val
)) {
113 avio_read(pb
, val
, nval
); // value string
115 if (!strcmp(key
, "codec")) {
116 av_log(s
, AV_LOG_DEBUG
, "Codec is <%s>\n", val
);
117 strncpy(codec_name
, val
, sizeof(codec_name
) - 1);
119 if (!strcmp(key
, "HeaderSeed")) {
120 av_log(s
, AV_LOG_DEBUG
, "HeaderSeed is <%s>\n", val
);
121 header_seed
= atoi(val
);
123 if (!strcmp(key
, "HeaderKey")) { // this looks like "1234567890 1234567890 1234567890 1234567890"
124 av_log(s
, AV_LOG_DEBUG
, "HeaderKey is <%s>\n", val
);
125 ret
= sscanf(val
, "%u%u%u%u", &header_key_part
[0], &header_key_part
[1], &header_key_part
[2], &header_key_part
[3]);
127 return AVERROR_INVALIDDATA
;
129 for (idx
= 0; idx
< 4; idx
++) {
130 AV_WB32(&header_key
[idx
* 4], header_key_part
[idx
]); // convert each part to BE!
132 av_log(s
, AV_LOG_DEBUG
, "Processed HeaderKey is ");
133 for (i
= 0; i
< 16; i
++)
134 av_log(s
, AV_LOG_DEBUG
, "%02x", header_key
[i
]);
135 av_log(s
, AV_LOG_DEBUG
, "\n");
139 /* verify fixed key */
140 if (c
->aa_fixed_key_len
!= 16) {
141 av_log(s
, AV_LOG_ERROR
, "aa_fixed_key value needs to be 16 bytes!\n");
142 return AVERROR(EINVAL
);
146 if ((c
->codec_second_size
= get_second_size(codec_name
)) == -1) {
147 av_log(s
, AV_LOG_ERROR
, "unknown codec <%s>!\n", codec_name
);
148 return AVERROR(EINVAL
);
151 /* decryption key derivation */
152 c
->tea_ctx
= av_tea_alloc();
154 return AVERROR(ENOMEM
);
155 av_tea_init(c
->tea_ctx
, c
->aa_fixed_key
, 16);
156 output
[0] = output
[1] = 0; // purely for padding purposes
157 memcpy(output
+ 2, header_key
, 16);
159 for (i
= 0; i
< 3; i
++) { // TEA CBC with weird mixed endianness
160 AV_WB32(src
, header_seed
);
161 AV_WB32(src
+ 4, header_seed
+ 1);
163 av_tea_crypt(c
->tea_ctx
, dst
, src
, 1, NULL
, 0); // TEA ECB encrypt
164 for (j
= 0; j
< TEA_BLOCK_SIZE
&& idx
< 18; j
+=1, idx
+=1) {
165 output
[idx
] = output
[idx
] ^ dst
[j
];
168 memcpy(c
->file_key
, output
+ 2, 16); // skip first 2 bytes of output
169 av_log(s
, AV_LOG_DEBUG
, "File key is ");
170 for (i
= 0; i
< 16; i
++)
171 av_log(s
, AV_LOG_DEBUG
, "%02x", c
->file_key
[i
]);
172 av_log(s
, AV_LOG_DEBUG
, "\n");
175 st
= avformat_new_stream(s
, NULL
);
177 av_freep(&c
->tea_ctx
);
178 return AVERROR(ENOMEM
);
180 st
->codecpar
->codec_type
= AVMEDIA_TYPE_AUDIO
;
181 if (!strcmp(codec_name
, "mp332")) {
182 st
->codecpar
->codec_id
= AV_CODEC_ID_MP3
;
183 st
->codecpar
->sample_rate
= 22050;
184 st
->need_parsing
= AVSTREAM_PARSE_FULL_RAW
;
186 } else if (!strcmp(codec_name
, "acelp85")) {
187 st
->codecpar
->codec_id
= AV_CODEC_ID_SIPR
;
188 st
->codecpar
->block_align
= 19;
189 st
->codecpar
->channels
= 1;
190 st
->codecpar
->sample_rate
= 8500;
191 } else if (!strcmp(codec_name
, "acelp16")) {
192 st
->codecpar
->codec_id
= AV_CODEC_ID_SIPR
;
193 st
->codecpar
->block_align
= 20;
194 st
->codecpar
->channels
= 1;
195 st
->codecpar
->sample_rate
= 16000;
198 /* determine, and jump to audio start offset */
199 for (i
= 1; i
< toc_size
; i
++) { // skip the first entry!
200 current_size
= TOC
[i
].size
;
201 if (current_size
> largest_size
) {
203 largest_size
= current_size
;
206 start
= TOC
[largest_idx
].offset
;
207 avio_seek(pb
, start
, SEEK_SET
);
208 c
->current_chapter_size
= 0;
213 static int aa_read_packet(AVFormatContext
*s
, AVPacket
*pkt
)
215 uint8_t dst
[TEA_BLOCK_SIZE
];
216 uint8_t src
[TEA_BLOCK_SIZE
];
220 uint8_t buf
[MAX_CODEC_SECOND_SIZE
* 2];
223 AADemuxContext
*c
= s
->priv_data
;
225 // are we at the start of a chapter?
226 if (c
->current_chapter_size
== 0) {
227 c
->current_chapter_size
= avio_rb32(s
->pb
);
228 if (c
->current_chapter_size
== 0) {
231 av_log(s
, AV_LOG_DEBUG
, "Chapter %d (%" PRId64
" bytes)\n", c
->chapter_idx
, c
->current_chapter_size
);
232 c
->chapter_idx
= c
->chapter_idx
+ 1;
233 avio_skip(s
->pb
, 4); // data start offset
234 c
->current_codec_second_size
= c
->codec_second_size
;
237 // is this the last block in this chapter?
238 if (c
->current_chapter_size
/ c
->current_codec_second_size
== 0) {
239 c
->current_codec_second_size
= c
->current_chapter_size
% c
->current_codec_second_size
;
242 // decrypt c->current_codec_second_size bytes
243 blocks
= c
->current_codec_second_size
/ TEA_BLOCK_SIZE
;
244 for (i
= 0; i
< blocks
; i
++) {
245 avio_read(s
->pb
, src
, TEA_BLOCK_SIZE
);
246 av_tea_init(c
->tea_ctx
, c
->file_key
, 16);
247 av_tea_crypt(c
->tea_ctx
, dst
, src
, 1, NULL
, 1);
248 memcpy(buf
+ written
, dst
, TEA_BLOCK_SIZE
);
249 written
= written
+ TEA_BLOCK_SIZE
;
251 trailing_bytes
= c
->current_codec_second_size
% TEA_BLOCK_SIZE
;
252 if (trailing_bytes
!= 0) { // trailing bytes are left unencrypted!
253 avio_read(s
->pb
, src
, trailing_bytes
);
254 memcpy(buf
+ written
, src
, trailing_bytes
);
255 written
= written
+ trailing_bytes
;
259 c
->current_chapter_size
= c
->current_chapter_size
- c
->current_codec_second_size
;
260 if (c
->current_chapter_size
<= 0)
261 c
->current_chapter_size
= 0;
263 ret
= av_new_packet(pkt
, written
);
266 memcpy(pkt
->data
, buf
, written
);
271 static int aa_probe(AVProbeData
*p
)
273 uint8_t *buf
= p
->buf
;
275 // first 4 bytes are file size, next 4 bytes are the magic
276 if (AV_RB32(buf
+4) != AA_MAGIC
)
279 return AVPROBE_SCORE_MAX
/ 2;
282 static int aa_read_close(AVFormatContext
*s
)
284 AADemuxContext
*c
= s
->priv_data
;
286 av_freep(&c
->tea_ctx
);
291 #define OFFSET(x) offsetof(AADemuxContext, x)
292 static const AVOption aa_options
[] = {
293 { "aa_fixed_key", // extracted from libAAX_SDK.so and AAXSDKWin.dll files!
294 "Fixed key used for handling Audible AA files", OFFSET(aa_fixed_key
),
295 AV_OPT_TYPE_BINARY
, {.str
="77214d4b196a87cd520045fd2a51d673"},
296 .flags
= AV_OPT_FLAG_DECODING_PARAM
},
300 static const AVClass aa_class
= {
302 .item_name
= av_default_item_name
,
303 .option
= aa_options
,
304 .version
= LIBAVUTIL_VERSION_INT
,
307 AVInputFormat ff_aa_demuxer
= {
309 .long_name
= NULL_IF_CONFIG_SMALL("Audible AA format files"),
310 .priv_class
= &aa_class
,
311 .priv_data_size
= sizeof(AADemuxContext
),
313 .read_probe
= aa_probe
,
314 .read_header
= aa_read_header
,
315 .read_packet
= aa_read_packet
,
316 .read_close
= aa_read_close
,
317 .flags
= AVFMT_GENERIC_INDEX
,