Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
VideoLAN
x264
Commits
25a02945
Commit
25a02945
authored
Nov 14, 2009
by
Kieran Kunhya
Committed by
Fiona Glaser
Nov 14, 2009
Browse files
FLV muxing support
parent
b9ce3a10
Changes
11
Hide whitespace changes
Inline
Side-by-side
Makefile
View file @
25a02945
...
...
@@ -13,7 +13,8 @@ SRCS = common/mc.c common/predict.c common/pixel.c common/macroblock.c \
encoder/cavlc.c encoder/encoder.c encoder/lookahead.c
SRCCLI
=
x264.c input/yuv.c input/y4m.c output/raw.c
\
output/matroska.c output/matroska_ebml.c
output/matroska.c output/matroska_ebml.c
\
output/flv.c output/flv_bytestream.c
MUXERS
:=
$(
shell
grep
-E
"(IN|OUT
)
PUT"
config.h
)
...
...
common/osdep.h
View file @
25a02945
...
...
@@ -151,6 +151,7 @@ static inline int x264_pthread_create( x264_pthread_t *t, void *a, void *(*f)(vo
#ifdef WORDS_BIGENDIAN
#define endian_fix(x) (x)
#define endian_fix64(x) (x)
#define endian_fix32(x) (x)
#define endian_fix16(x) (x)
#else
...
...
@@ -160,31 +161,34 @@ static ALWAYS_INLINE uint32_t endian_fix32( uint32_t x )
asm
(
"bswap %0"
:
"+r"
(
x
));
return
x
;
}
static
ALWAYS_INLINE
intptr_t
endian_fix
(
intptr_t
x
)
{
asm
(
"bswap %0"
:
"+r"
(
x
));
return
x
;
}
#elif defined(__GNUC__) && defined(HAVE_ARMV6)
static
ALWAYS_INLINE
int
ptr
_t
endian_fix
(
int
ptr
_t
x
)
static
ALWAYS_INLINE
u
int
32
_t
endian_fix
32
(
u
int
32
_t
x
)
{
asm
(
"rev %0, %0"
:
"+r"
(
x
));
return
x
;
}
#define endian_fix32 endian_fix
#else
static
ALWAYS_INLINE
uint32_t
endian_fix32
(
uint32_t
x
)
{
return
(
x
<<
24
)
+
((
x
<<
8
)
&
0xff0000
)
+
((
x
>>
8
)
&
0xff00
)
+
(
x
>>
24
);
}
static
ALWAYS_INLINE
intptr_t
endian_fix
(
intptr_t
x
)
#endif
#if defined(__GNUC__) && defined(ARCH_X86_64)
static
ALWAYS_INLINE
uint64_t
endian_fix64
(
uint64_t
x
)
{
if
(
WORD_SIZE
==
8
)
return
endian_fix32
(
x
>>
32
)
+
((
uint64_t
)
endian_fix32
(
x
)
<<
32
);
else
return
endian_fix32
(
x
);
asm
(
"bswap %0"
:
"+r"
(
x
));
return
x
;
}
#else
static
ALWAYS_INLINE
uint64_t
endian_fix64
(
uint64_t
x
)
{
return
endian_fix32
(
x
>>
32
)
+
((
uint64_t
)
endian_fix32
(
x
)
<<
32
);
}
#endif
static
ALWAYS_INLINE
intptr_t
endian_fix
(
intptr_t
x
)
{
return
WORD_SIZE
==
8
?
endian_fix64
(
x
)
:
endian_fix32
(
x
);
}
static
ALWAYS_INLINE
uint16_t
endian_fix16
(
uint16_t
x
)
{
return
(
x
<<
8
)
|
(
x
>>
8
);
...
...
configure
View file @
25a02945
...
...
@@ -348,9 +348,13 @@ fi
CFLAGS
=
"
$CFLAGS
-DARCH_
$ARCH
-DSYS_
$SYS
"
echo
"
unsigned int endian = 'B' << 24 | 'I' << 16 | 'G' << 8 | 'E'
;"
>
conftest.c
echo
"
int i = 0x42494745; double f = 0x1.0656e6469616ep+102
;"
>
conftest.c
$CC
$CFLAGS
conftest.c
-c
-o
conftest.o 2>
$DEVNULL
||
die
"endian test failed"
grep
-q
BIGE conftest.o
&&
CFLAGS
=
"
$CFLAGS
-DWORDS_BIGENDIAN"
if
grep
-q
BIGE conftest.o
&&
grep
-q
FPendian conftest.o
;
then
CFLAGS
=
"
$CFLAGS
-DWORDS_BIGENDIAN"
elif
!(
grep
-q
EGIB conftest.o
&&
grep
-q
naidnePF conftest.o
)
;
then
die
"endian test failed"
fi
# autodetect options that weren't forced nor disabled
...
...
output/flv.c
0 → 100644
View file @
25a02945
/*****************************************************************************
* flv.c:
*****************************************************************************
* Copyright (C) 2009 Kieran Kunhya
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA.
*****************************************************************************/
#include "muxers.h"
#include "flv_bytestream.h"
#define CHECK(x)\
do {\
if( (x) < 0 )\
return -1;\
} while( 0 )
typedef
struct
{
flv_buffer
*
c
;
uint8_t
b_sps
;
uint8_t
b_pps
;
uint8_t
*
sei
;
int
sei_len
;
int64_t
i_fps_num
;
int64_t
i_fps_den
;
int64_t
i_init_delay
;
int64_t
i_framenum
;
int64_t
i_mspf
;
uint64_t
i_duration_pos
;
uint64_t
i_filesize_pos
;
uint64_t
i_bitrate_pos
;
uint8_t
b_write_length
;
unsigned
start
;
}
flv_hnd_t
;
static
int
write_header
(
flv_buffer
*
c
)
{
put_tag
(
c
,
"FLV"
);
// Signature
put_byte
(
c
,
1
);
// Version
put_byte
(
c
,
1
);
// Video Only
put_be32
(
c
,
9
);
// DataOffset
put_be32
(
c
,
0
);
// PreviousTagSize0
return
flv_flush_data
(
c
);
}
static
int
open_file
(
char
*
psz_filename
,
hnd_t
*
p_handle
)
{
flv_hnd_t
*
p_flv
=
malloc
(
sizeof
(
*
p_flv
)
);
*
p_handle
=
NULL
;
if
(
!
p_flv
)
return
-
1
;
memset
(
p_flv
,
0
,
sizeof
(
*
p_flv
)
);
p_flv
->
c
=
flv_create_writer
(
psz_filename
);
if
(
!
p_flv
->
c
)
return
-
1
;
CHECK
(
write_header
(
p_flv
->
c
)
);
*
p_handle
=
p_flv
;
return
0
;
}
static
int
set_param
(
hnd_t
handle
,
x264_param_t
*
p_param
)
{
flv_hnd_t
*
p_flv
=
handle
;
flv_buffer
*
c
=
p_flv
->
c
;
put_byte
(
c
,
FLV_TAG_TYPE_META
);
// Tag Type "script data"
int
start
=
c
->
d_cur
;
put_be24
(
c
,
0
);
// data length
put_be24
(
c
,
0
);
// timestamp
put_be32
(
c
,
0
);
// reserved
put_byte
(
c
,
AMF_DATA_TYPE_STRING
);
put_amf_string
(
c
,
"onMetaData"
);
put_byte
(
c
,
AMF_DATA_TYPE_MIXEDARRAY
);
put_be32
(
c
,
7
);
put_amf_string
(
c
,
"width"
);
put_amf_double
(
c
,
p_param
->
i_width
);
put_amf_string
(
c
,
"height"
);
put_amf_double
(
c
,
p_param
->
i_height
);
put_amf_string
(
c
,
"framerate"
);
put_amf_double
(
c
,
p_param
->
i_fps_num
/
p_param
->
i_fps_den
);
put_amf_string
(
c
,
"videocodecid"
);
put_amf_double
(
c
,
FLV_CODECID_H264
);
put_amf_string
(
c
,
"duration"
);
p_flv
->
i_duration_pos
=
c
->
d_cur
+
c
->
d_total
+
1
;
// + 1 because of the following AMF_DATA_TYPE_NUMBER byte
put_amf_double
(
c
,
0
);
// written at end of encoding
put_amf_string
(
c
,
"filesize"
);
p_flv
->
i_filesize_pos
=
c
->
d_cur
+
c
->
d_total
+
1
;
put_amf_double
(
c
,
0
);
// written at end of encoding
put_amf_string
(
c
,
"videodatarate"
);
p_flv
->
i_bitrate_pos
=
c
->
d_cur
+
c
->
d_total
+
1
;
put_amf_double
(
c
,
0
);
// written at end of encoding
put_amf_string
(
c
,
""
);
put_byte
(
c
,
AMF_END_OF_OBJECT
);
unsigned
length
=
c
->
d_cur
-
start
;
rewrite_amf_be24
(
c
,
length
-
10
,
start
);
put_be32
(
c
,
length
+
1
);
// tag length
p_flv
->
i_fps_num
=
p_param
->
i_fps_num
;
p_flv
->
i_fps_den
=
p_param
->
i_fps_den
;
p_flv
->
i_init_delay
=
p_param
->
i_bframe
?
(
p_param
->
i_bframe_pyramid
?
2
:
1
)
:
0
;
p_flv
->
i_mspf
=
1000
*
p_flv
->
i_fps_den
/
p_flv
->
i_fps_num
;
fprintf
(
stderr
,
"flv [info]: initial delay %i frames
\n
"
,
(
int
)
p_flv
->
i_init_delay
);
return
0
;
}
static
int
write_nalu
(
hnd_t
handle
,
uint8_t
*
p_nalu
,
int
i_size
,
x264_picture_t
*
p_picture
)
{
flv_hnd_t
*
p_flv
=
handle
;
flv_buffer
*
c
=
p_flv
->
c
;
uint64_t
dts
=
(
uint64_t
)
p_flv
->
i_framenum
*
p_flv
->
i_mspf
;
uint64_t
pts
=
(
uint64_t
)
p_picture
->
i_pts
*
p_flv
->
i_mspf
/
p_flv
->
i_fps_den
;
uint64_t
timestamp
=
dts
+
p_flv
->
i_init_delay
*
p_flv
->
i_mspf
;
uint64_t
offset
=
p_flv
->
i_init_delay
*
p_flv
->
i_mspf
+
pts
-
dts
;
uint8_t
type
=
p_nalu
[
4
]
&
0x1f
;
switch
(
type
)
{
// sps
case
0x07
:
if
(
!
p_flv
->
b_sps
)
{
uint8_t
*
sps
=
p_nalu
+
4
;
put_byte
(
c
,
FLV_TAG_TYPE_VIDEO
);
put_be24
(
c
,
0
);
// rewrite later, pps size unknown
put_be24
(
c
,
0
);
// timestamp
put_byte
(
c
,
0
);
// timestamp extended
put_be24
(
c
,
0
);
// StreamID - Always 0
p_flv
->
start
=
c
->
d_cur
;
// needed for overwriting length
put_byte
(
c
,
7
|
FLV_FRAME_KEY
);
// Frametype and CodecID
put_byte
(
c
,
0
);
// AVC sequence header
put_be24
(
c
,
0
);
// composition time
put_byte
(
c
,
1
);
// version
put_byte
(
c
,
sps
[
1
]
);
// profile
put_byte
(
c
,
sps
[
2
]
);
// profile
put_byte
(
c
,
sps
[
3
]
);
// level
put_byte
(
c
,
0xff
);
// 6 bits reserved (111111) + 2 bits nal size length - 1 (11)
put_byte
(
c
,
0xe1
);
// 3 bits reserved (111) + 5 bits number of sps (00001)
put_be16
(
c
,
i_size
-
4
);
flv_append_data
(
c
,
sps
,
i_size
-
4
);
p_flv
->
b_sps
=
1
;
}
break
;
// pps
case
0x08
:
if
(
!
p_flv
->
b_pps
)
{
put_byte
(
c
,
1
);
// number of pps
put_be16
(
c
,
i_size
-
4
);
flv_append_data
(
c
,
p_nalu
+
4
,
i_size
-
4
);
// rewrite data length info
unsigned
length
=
c
->
d_cur
-
p_flv
->
start
;
rewrite_amf_be24
(
c
,
length
,
p_flv
->
start
-
10
);
put_be32
(
c
,
length
+
11
);
// Last tag size
p_flv
->
b_pps
=
1
;
}
break
;
// slice
case
0x1
:
case
0x5
:
if
(
!
p_flv
->
b_write_length
)
{
// A new frame - write packet header
put_byte
(
c
,
FLV_TAG_TYPE_VIDEO
);
put_be24
(
c
,
0
);
// calculated later
put_be24
(
c
,
timestamp
);
put_byte
(
c
,
timestamp
>>
24
);
put_be24
(
c
,
0
);
p_flv
->
start
=
c
->
d_cur
;
put_byte
(
c
,
p_picture
->
i_type
==
X264_TYPE_IDR
?
FLV_FRAME_KEY
:
FLV_FRAME_INTER
);
put_byte
(
c
,
1
);
// AVC NALU
put_be24
(
c
,
offset
);
p_flv
->
b_write_length
=
1
;
}
if
(
p_flv
->
sei
)
{
flv_append_data
(
c
,
p_flv
->
sei
,
p_flv
->
sei_len
);
free
(
p_flv
->
sei
);
p_flv
->
sei
=
NULL
;
}
flv_append_data
(
c
,
p_nalu
,
i_size
);
break
;
// sei
case
0x6
:
/* It is within the spec to write this as-is but for
* mplayer/ffmpeg playback this is deferred until before the first frame */
p_flv
->
sei
=
malloc
(
i_size
);
if
(
!
p_flv
->
sei
)
return
-
1
;
p_flv
->
sei_len
=
i_size
;
memcpy
(
p_flv
->
sei
,
p_nalu
,
i_size
);
break
;
}
return
i_size
;
}
static
int
set_eop
(
hnd_t
handle
,
x264_picture_t
*
p_picture
)
{
flv_hnd_t
*
p_flv
=
handle
;
flv_buffer
*
c
=
p_flv
->
c
;
if
(
p_flv
->
b_write_length
)
{
unsigned
length
=
c
->
d_cur
-
p_flv
->
start
;
rewrite_amf_be24
(
c
,
length
,
p_flv
->
start
-
10
);
put_be32
(
c
,
11
+
length
);
// Last tag size
CHECK
(
flv_flush_data
(
c
)
);
p_flv
->
b_write_length
=
0
;
}
p_flv
->
i_framenum
++
;
return
0
;
}
static
void
rewrite_amf_double
(
FILE
*
fp
,
uint64_t
position
,
double
value
)
{
uint64_t
x
=
endian_fix64
(
dbl2int
(
value
)
);
fseek
(
fp
,
position
,
SEEK_SET
);
fwrite
(
&
x
,
8
,
1
,
fp
);
}
static
int
close_file
(
hnd_t
handle
)
{
flv_hnd_t
*
p_flv
=
handle
;
flv_buffer
*
c
=
p_flv
->
c
;
CHECK
(
flv_flush_data
(
c
)
);
if
(
x264_is_regular_file
(
c
->
fp
)
)
{
double
duration
=
p_flv
->
i_fps_den
*
p_flv
->
i_framenum
/
p_flv
->
i_fps_num
;
uint64_t
filesize
=
ftell
(
c
->
fp
);
rewrite_amf_double
(
c
->
fp
,
p_flv
->
i_duration_pos
,
duration
);
rewrite_amf_double
(
c
->
fp
,
p_flv
->
i_filesize_pos
,
filesize
);
rewrite_amf_double
(
c
->
fp
,
p_flv
->
i_bitrate_pos
,
filesize
*
8
/
(
duration
*
1000
)
);
}
fclose
(
c
->
fp
);
free
(
p_flv
);
free
(
c
);
return
0
;
}
cli_output_t
flv_output
=
{
open_file
,
set_param
,
write_nalu
,
set_eop
,
close_file
};
output/flv_bytestream.c
0 → 100644
View file @
25a02945
/*****************************************************************************
* flv_bytestream.c:
*****************************************************************************
* Copyright (C) 2009 Kieran Kunhya
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA.
*****************************************************************************/
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "common/common.h"
#include "flv_bytestream.h"
uint64_t
dbl2int
(
double
value
)
{
return
(
union
{
double
f
;
uint64_t
i
;}){
value
}.
i
;
}
/* Put functions */
void
put_byte
(
flv_buffer
*
c
,
uint8_t
b
)
{
flv_append_data
(
c
,
&
b
,
1
);
}
void
put_be32
(
flv_buffer
*
c
,
uint32_t
val
)
{
put_byte
(
c
,
val
>>
24
);
put_byte
(
c
,
val
>>
16
);
put_byte
(
c
,
val
>>
8
);
put_byte
(
c
,
val
);
}
void
put_be64
(
flv_buffer
*
c
,
uint64_t
val
)
{
put_be32
(
c
,
val
>>
32
);
put_be32
(
c
,
val
);
}
void
put_be16
(
flv_buffer
*
c
,
uint16_t
val
)
{
put_byte
(
c
,
val
>>
8
);
put_byte
(
c
,
val
);
}
void
put_be24
(
flv_buffer
*
c
,
uint32_t
val
)
{
put_be16
(
c
,
val
>>
8
);
put_byte
(
c
,
val
);
}
void
put_tag
(
flv_buffer
*
c
,
const
char
*
tag
)
{
while
(
*
tag
)
put_byte
(
c
,
*
tag
++
);
}
void
put_amf_string
(
flv_buffer
*
c
,
const
char
*
str
)
{
uint16_t
len
=
strlen
(
str
);
put_be16
(
c
,
len
);
flv_append_data
(
c
,
(
uint8_t
*
)
str
,
len
);
}
void
put_amf_double
(
flv_buffer
*
c
,
double
d
)
{
put_byte
(
c
,
AMF_DATA_TYPE_NUMBER
);
put_be64
(
c
,
dbl2int
(
d
)
);
}
/* flv writing functions */
flv_buffer
*
flv_create_writer
(
const
char
*
filename
)
{
flv_buffer
*
c
=
malloc
(
sizeof
(
*
c
)
);
if
(
!
c
)
return
NULL
;
memset
(
c
,
0
,
sizeof
(
*
c
)
);
if
(
!
strcmp
(
filename
,
"-"
)
)
c
->
fp
=
stdout
;
else
c
->
fp
=
fopen
(
filename
,
"wb"
);
if
(
!
c
->
fp
)
{
free
(
c
);
return
NULL
;
}
return
c
;
}
int
flv_append_data
(
flv_buffer
*
c
,
uint8_t
*
data
,
unsigned
size
)
{
unsigned
ns
=
c
->
d_cur
+
size
;
if
(
ns
>
c
->
d_max
)
{
void
*
dp
;
unsigned
dn
=
16
;
while
(
ns
>
dn
)
dn
<<=
1
;
dp
=
realloc
(
c
->
data
,
dn
);
if
(
!
dp
)
return
-
1
;
c
->
data
=
dp
;
c
->
d_max
=
dn
;
}
memcpy
(
c
->
data
+
c
->
d_cur
,
data
,
size
);
c
->
d_cur
=
ns
;
return
0
;
}
void
rewrite_amf_be24
(
flv_buffer
*
c
,
unsigned
length
,
unsigned
start
)
{
*
(
c
->
data
+
start
+
0
)
=
length
>>
16
;
*
(
c
->
data
+
start
+
1
)
=
length
>>
8
;
*
(
c
->
data
+
start
+
2
)
=
length
>>
0
;
}
int
flv_flush_data
(
flv_buffer
*
c
)
{
if
(
!
c
->
d_cur
)
return
0
;
if
(
fwrite
(
c
->
data
,
c
->
d_cur
,
1
,
c
->
fp
)
!=
1
)
return
-
1
;
c
->
d_total
+=
c
->
d_cur
;
c
->
d_cur
=
0
;
return
0
;
}
output/flv_bytestream.h
0 → 100644
View file @
25a02945
/*****************************************************************************
* flv_bytestream.h:
*****************************************************************************
* Copyright (C) 2009 Kieran Kunhya
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA.
*****************************************************************************/
#ifndef X264_FLV_BYTESTREAM_H
#define X264_FLV_BYTESTREAM_H
/* offsets for packed values */
#define FLV_AUDIO_SAMPLESSIZE_OFFSET 1
#define FLV_AUDIO_SAMPLERATE_OFFSET 2
#define FLV_AUDIO_CODECID_OFFSET 4
#define FLV_VIDEO_FRAMETYPE_OFFSET 4
/* bitmasks to isolate specific values */
#define FLV_AUDIO_CHANNEL_MASK 0x01
#define FLV_AUDIO_SAMPLESIZE_MASK 0x02
#define FLV_AUDIO_SAMPLERATE_MASK 0x0c
#define FLV_AUDIO_CODECID_MASK 0xf0
#define FLV_VIDEO_CODECID_MASK 0x0f
#define FLV_VIDEO_FRAMETYPE_MASK 0xf0
#define AMF_END_OF_OBJECT 0x09
enum
{
FLV_HEADER_FLAG_HASVIDEO
=
1
,
FLV_HEADER_FLAG_HASAUDIO
=
4
,
};
enum
{
FLV_TAG_TYPE_AUDIO
=
0x08
,
FLV_TAG_TYPE_VIDEO
=
0x09
,
FLV_TAG_TYPE_META
=
0x12
,
};
enum
{
FLV_MONO
=
0
,
FLV_STEREO
=
1
,
};
enum
{
FLV_SAMPLESSIZE_8BIT
=
0
,
FLV_SAMPLESSIZE_16BIT
=
1
<<
FLV_AUDIO_SAMPLESSIZE_OFFSET
,
};
enum
{
FLV_SAMPLERATE_SPECIAL
=
0
,
/**< signifies 5512Hz and 8000Hz in the case of NELLYMOSER */
FLV_SAMPLERATE_11025HZ
=
1
<<
FLV_AUDIO_SAMPLERATE_OFFSET
,
FLV_SAMPLERATE_22050HZ
=
2
<<
FLV_AUDIO_SAMPLERATE_OFFSET
,
FLV_SAMPLERATE_44100HZ
=
3
<<
FLV_AUDIO_SAMPLERATE_OFFSET
,
};
enum
{
FLV_CODECID_MP3
=
2
<<
FLV_AUDIO_CODECID_OFFSET
,
FLV_CODECID_AAC
=
10
<<
FLV_AUDIO_CODECID_OFFSET
,
};
enum
{
FLV_CODECID_H264
=
7
,
};
enum
{
FLV_FRAME_KEY
=
1
<<
FLV_VIDEO_FRAMETYPE_OFFSET
|
7
,
FLV_FRAME_INTER
=
2
<<
FLV_VIDEO_FRAMETYPE_OFFSET
|
7
,
};
typedef
enum
{
AMF_DATA_TYPE_NUMBER
=
0x00
,
AMF_DATA_TYPE_BOOL
=
0x01
,
AM