Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
F
ffmpeg.wasm-core
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Linshizhi
ffmpeg.wasm-core
Commits
0a551cbe
Commit
0a551cbe
authored
Jul 11, 2015
by
Vesselin Bontchev
Committed by
Michael Niedermayer
Jul 19, 2015
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add support for Audible AAX (and AAX+) files
Signed-off-by:
Michael Niedermayer
<
michael@niedermayer.cc
>
parent
4df66c7c
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
145 additions
and
0 deletions
+145
-0
general.texi
doc/general.texi
+2
-0
muxers.texi
doc/muxers.texi
+7
-0
isom.h
libavformat/isom.h
+8
-0
mov.c
libavformat/mov.c
+128
-0
No files found.
doc/general.texi
View file @
0a551cbe
...
...
@@ -226,6 +226,8 @@ library:
@item 4xm @tab @tab X
@tab 4X Technologies format, used in some games.
@item 8088flex TMV @tab @tab X
@item AAX @tab @tab X
@tab Audible Enhanced Audio format, used in audiobooks.
@item ACT Voice @tab @tab X
@tab contains G.729 audio
@item Adobe Filmstrip @tab X @tab X
...
...
doc/muxers.texi
View file @
0a551cbe
...
...
@@ -667,6 +667,13 @@ point on IIS with this muxer. Example:
ffmpeg -re @var{<normal input/transcoding options>} -movflags isml+frag_keyframe -f ismv http://server/publishingpoint.isml/Streams(Encoder1)
@end example
@subsection Audible AAX
Audible AAX files are encrypted M4B files, and they can be decrypted by specifying a 4 byte activation secret.
@example
ffmpeg -activation_bytes 1CEB00DA -i test.aax -vn -c:a copy output.mp4
@end example
@section mp3
The MP3 muxer writes a raw MP3 stream with the following optional features:
...
...
libavformat/isom.h
View file @
0a551cbe
...
...
@@ -198,6 +198,14 @@ typedef struct MOVContext {
MOVFragmentIndex
**
fragment_index_data
;
unsigned
fragment_index_count
;
int
atom_depth
;
unsigned
int
aax_mode
;
///< 'aax' file has been detected
uint8_t
file_key
[
20
];
uint8_t
file_iv
[
20
];
void
*
activation_bytes
;
int
activation_bytes_size
;
void
*
audible_fixed_key
;
int
audible_fixed_key_size
;
struct
AVAES
*
aes_decrypt
;
}
MOVContext
;
int
ff_mp4_read_descr_len
(
AVIOContext
*
pb
);
...
...
libavformat/mov.c
View file @
0a551cbe
...
...
@@ -37,6 +37,8 @@
#include "libavutil/dict.h"
#include "libavutil/display.h"
#include "libavutil/opt.h"
#include "libavutil/aes.h"
#include "libavutil/sha.h"
#include "libavutil/timecode.h"
#include "libavcodec/ac3tab.h"
#include "avformat.h"
...
...
@@ -807,6 +809,120 @@ static int mov_read_mdat(MOVContext *c, AVIOContext *pb, MOVAtom atom)
return
0
;
/* now go for moov */
}
#define DRM_BLOB_SIZE 56
static
int
mov_read_adrm
(
MOVContext
*
c
,
AVIOContext
*
pb
,
MOVAtom
atom
)
{
uint8_t
intermediate_key
[
20
];
uint8_t
intermediate_iv
[
20
];
uint8_t
input
[
64
];
uint8_t
output
[
64
];
uint8_t
file_checksum
[
20
];
uint8_t
calculated_checksum
[
20
];
struct
AVSHA
*
sha
;
int
i
;
int
ret
=
0
;
uint8_t
*
activation_bytes
=
c
->
activation_bytes
;
uint8_t
*
fixed_key
=
c
->
audible_fixed_key
;
c
->
aax_mode
=
1
;
sha
=
av_sha_alloc
();
if
(
!
sha
)
return
AVERROR
(
ENOMEM
);
c
->
aes_decrypt
=
av_aes_alloc
();
if
(
!
c
->
aes_decrypt
)
{
ret
=
AVERROR
(
ENOMEM
);
goto
fail
;
}
/* drm blob processing */
avio_read
(
pb
,
output
,
8
);
// go to offset 8, absolute postion 0x251
avio_read
(
pb
,
input
,
DRM_BLOB_SIZE
);
avio_read
(
pb
,
output
,
4
);
// go to offset 4, absolute postion 0x28d
avio_read
(
pb
,
file_checksum
,
20
);
av_log
(
c
->
fc
,
AV_LOG_INFO
,
"[aax] file checksum == "
);
// required by external tools
for
(
i
=
0
;
i
<
20
;
i
++
)
av_log
(
sha
,
AV_LOG_INFO
,
"%02x"
,
file_checksum
[
i
]);
av_log
(
c
->
fc
,
AV_LOG_INFO
,
"
\n
"
);
/* verify activation data */
if
(
!
activation_bytes
||
c
->
activation_bytes_size
!=
4
)
{
av_log
(
c
->
fc
,
AV_LOG_FATAL
,
"[aax] activation_bytes option is missing!
\n
"
);
ret
=
AVERROR
(
EINVAL
);
goto
fail
;
}
if
(
c
->
activation_bytes_size
!=
4
)
{
av_log
(
c
->
fc
,
AV_LOG_FATAL
,
"[aax] activation_bytes value needs to be 4 bytes!
\n
"
);
ret
=
AVERROR
(
EINVAL
);
goto
fail
;
}
/* verify fixed key */
if
(
c
->
audible_fixed_key_size
!=
16
)
{
av_log
(
c
->
fc
,
AV_LOG_FATAL
,
"[aax] audible_fixed_key value needs to be 16 bytes!
\n
"
);
ret
=
AVERROR
(
EINVAL
);
goto
fail
;
}
/* AAX (and AAX+) key derivation */
av_sha_init
(
sha
,
160
);
av_sha_update
(
sha
,
fixed_key
,
16
);
av_sha_update
(
sha
,
activation_bytes
,
4
);
av_sha_final
(
sha
,
intermediate_key
);
av_sha_init
(
sha
,
160
);
av_sha_update
(
sha
,
fixed_key
,
16
);
av_sha_update
(
sha
,
intermediate_key
,
20
);
av_sha_update
(
sha
,
activation_bytes
,
4
);
av_sha_final
(
sha
,
intermediate_iv
);
av_sha_init
(
sha
,
160
);
av_sha_update
(
sha
,
intermediate_key
,
16
);
av_sha_update
(
sha
,
intermediate_iv
,
16
);
av_sha_final
(
sha
,
calculated_checksum
);
if
(
memcmp
(
calculated_checksum
,
file_checksum
,
20
))
{
// critical error
av_log
(
c
->
fc
,
AV_LOG_ERROR
,
"[aax] mismatch in checksums!
\n
"
);
ret
=
AVERROR_INVALIDDATA
;
goto
fail
;
}
av_aes_init
(
c
->
aes_decrypt
,
intermediate_key
,
128
,
1
);
av_aes_crypt
(
c
->
aes_decrypt
,
output
,
input
,
DRM_BLOB_SIZE
>>
4
,
intermediate_iv
,
1
);
for
(
i
=
0
;
i
<
4
;
i
++
)
{
// file data (in output) is stored in big-endian mode
if
(
activation_bytes
[
i
]
!=
output
[
3
-
i
])
{
// critical error
av_log
(
c
->
fc
,
AV_LOG_ERROR
,
"[aax] error in drm blob decryption!
\n
"
);
ret
=
AVERROR_INVALIDDATA
;
goto
fail
;
}
}
memcpy
(
c
->
file_key
,
output
+
8
,
16
);
memcpy
(
input
,
output
+
26
,
16
);
av_sha_init
(
sha
,
160
);
av_sha_update
(
sha
,
input
,
16
);
av_sha_update
(
sha
,
c
->
file_key
,
16
);
av_sha_update
(
sha
,
fixed_key
,
16
);
av_sha_final
(
sha
,
c
->
file_iv
);
fail:
av_free
(
sha
);
return
ret
;
}
// Audible AAX (and AAX+) bytestream decryption
static
int
aax_filter
(
uint8_t
*
input
,
int
size
,
MOVContext
*
c
)
{
int
blocks
=
0
;
unsigned
char
iv
[
16
];
memcpy
(
iv
,
c
->
file_iv
,
16
);
// iv is overwritten
blocks
=
size
>>
4
;
// trailing bytes are not encrypted!
av_aes_init
(
c
->
aes_decrypt
,
c
->
file_key
,
128
,
1
);
av_aes_crypt
(
c
->
aes_decrypt
,
input
,
input
,
blocks
,
iv
,
1
);
return
0
;
}
/* read major brand, minor version and compatible brands and store them as metadata */
static
int
mov_read_ftyp
(
MOVContext
*
c
,
AVIOContext
*
pb
,
MOVAtom
atom
)
{
...
...
@@ -3637,6 +3753,7 @@ static const MOVParseTableEntry mov_default_parse_table[] = {
{
MKTAG
(
'e'
,
'l'
,
's'
,
't'
),
mov_read_elst
},
{
MKTAG
(
'e'
,
'n'
,
'd'
,
'a'
),
mov_read_enda
},
{
MKTAG
(
'f'
,
'i'
,
'e'
,
'l'
),
mov_read_fiel
},
{
MKTAG
(
'a'
,
'd'
,
'r'
,
'm'
),
mov_read_adrm
},
{
MKTAG
(
'f'
,
't'
,
'y'
,
'p'
),
mov_read_ftyp
},
{
MKTAG
(
'g'
,
'l'
,
'b'
,
'l'
),
mov_read_glbl
},
{
MKTAG
(
'h'
,
'd'
,
'l'
,
'r'
),
mov_read_hdlr
},
...
...
@@ -4058,6 +4175,8 @@ static int mov_read_close(AVFormatContext *s)
}
av_freep
(
&
mov
->
fragment_index_data
);
av_freep
(
&
mov
->
aes_decrypt
);
return
0
;
}
...
...
@@ -4477,6 +4596,9 @@ static int mov_read_packet(AVFormatContext *s, AVPacket *pkt)
pkt
->
flags
|=
sample
->
flags
&
AVINDEX_KEYFRAME
?
AV_PKT_FLAG_KEY
:
0
;
pkt
->
pos
=
sample
->
pos
;
if
(
mov
->
aax_mode
)
aax_filter
(
pkt
->
data
,
pkt
->
size
,
mov
);
return
0
;
}
...
...
@@ -4590,6 +4712,12 @@ static const AVOption mov_options[] = {
AV_OPT_TYPE_INT
,
{
.
i64
=
0
},
0
,
1
,
.
flags
=
FLAGS
},
{
"export_xmp"
,
"Export full XMP metadata"
,
OFFSET
(
export_xmp
),
AV_OPT_TYPE_INT
,
{
.
i64
=
0
},
0
,
1
,
.
flags
=
FLAGS
},
{
"activation_bytes"
,
"Secret bytes for Audible AAX files"
,
OFFSET
(
activation_bytes
),
AV_OPT_TYPE_BINARY
,
.
flags
=
AV_OPT_FLAG_DECODING_PARAM
},
{
"audible_fixed_key"
,
// extracted from libAAX_SDK.so and AAXSDKWin.dll files!
"Fixed key used for handling Audible AAX files"
,
OFFSET
(
audible_fixed_key
),
AV_OPT_TYPE_BINARY
,
{.
str
=
"77214d4b196a87cd520045fd20a51d67"
},
.
flags
=
AV_OPT_FLAG_DECODING_PARAM
},
{
NULL
},
};
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment