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
fed0de37
Commit
fed0de37
authored
Mar 15, 2020
by
Paul B Mahol
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
avcodec: add CRI HCA decoder
parent
0bbc4914
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
639 additions
and
1 deletion
+639
-1
Changelog
Changelog
+1
-0
Makefile
libavcodec/Makefile
+1
-0
allcodecs.c
libavcodec/allcodecs.c
+1
-0
avcodec.h
libavcodec/avcodec.h
+1
-0
codec_desc.c
libavcodec/codec_desc.c
+7
-0
hca_data.h
libavcodec/hca_data.h
+174
-0
hcadec.c
libavcodec/hcadec.c
+453
-0
version.h
libavcodec/version.h
+1
-1
No files found.
Changelog
View file @
fed0de37
...
...
@@ -52,6 +52,7 @@ version <next>:
- FWSE demuxer
- DERF DPCM decoder
- DERF demuxer
- CRI HCA decoder
version 4.2:
...
...
libavcodec/Makefile
View file @
fed0de37
...
...
@@ -367,6 +367,7 @@ OBJS-$(CONFIG_H264_V4L2M2M_DECODER) += v4l2_m2m_dec.o
OBJS-$(CONFIG_H264_V4L2M2M_ENCODER)
+=
v4l2_m2m_enc.o
OBJS-$(CONFIG_HAP_DECODER)
+=
hapdec.o
hap.o
OBJS-$(CONFIG_HAP_ENCODER)
+=
hapenc.o
hap.o
OBJS-$(CONFIG_HCA_DECODER)
+=
hcadec.o
OBJS-$(CONFIG_HCOM_DECODER)
+=
hcom.o
OBJS-$(CONFIG_HEVC_DECODER)
+=
hevcdec.o
hevc_mvs.o
\
hevc_cabac.o
hevc_refs.o
hevcpred.o
\
...
...
libavcodec/allcodecs.c
View file @
fed0de37
...
...
@@ -432,6 +432,7 @@ extern AVCodec ff_g723_1_decoder;
extern
AVCodec
ff_g729_decoder
;
extern
AVCodec
ff_gsm_decoder
;
extern
AVCodec
ff_gsm_ms_decoder
;
extern
AVCodec
ff_hca_decoder
;
extern
AVCodec
ff_hcom_decoder
;
extern
AVCodec
ff_iac_decoder
;
extern
AVCodec
ff_ilbc_decoder
;
...
...
libavcodec/avcodec.h
View file @
fed0de37
...
...
@@ -668,6 +668,7 @@ enum AVCodecID {
AV_CODEC_ID_ACELP_KELVIN
,
AV_CODEC_ID_MPEGH_3D_AUDIO
,
AV_CODEC_ID_SIREN
,
AV_CODEC_ID_HCA
,
/* subtitle codecs */
AV_CODEC_ID_FIRST_SUBTITLE
=
0x17000
,
///< A dummy ID pointing at the start of subtitle codecs.
...
...
libavcodec/codec_desc.c
View file @
fed0de37
...
...
@@ -3079,6 +3079,13 @@ static const AVCodecDescriptor codec_descriptors[] = {
.
long_name
=
NULL_IF_CONFIG_SMALL
(
"Siren"
),
.
props
=
AV_CODEC_PROP_INTRA_ONLY
|
AV_CODEC_PROP_LOSSY
,
},
{
.
id
=
AV_CODEC_ID_HCA
,
.
type
=
AVMEDIA_TYPE_AUDIO
,
.
name
=
"hca"
,
.
long_name
=
NULL_IF_CONFIG_SMALL
(
"CRI HCA"
),
.
props
=
AV_CODEC_PROP_INTRA_ONLY
|
AV_CODEC_PROP_LOSSY
,
},
/* subtitle codecs */
{
...
...
libavcodec/hca_data.h
0 → 100644
View file @
fed0de37
/*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef AVCODEC_HCA_DATA_H
#define AVCODEC_HCA_DATA_H
#include <stdint.h>
static
const
uint8_t
max_bits_table
[]
=
{
0
,
2
,
3
,
3
,
4
,
4
,
4
,
4
,
5
,
6
,
7
,
8
,
9
,
10
,
11
,
12
,
};
static
const
uint8_t
quant_spectrum_bits
[]
=
{
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
1
,
1
,
2
,
2
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
2
,
2
,
2
,
2
,
2
,
2
,
3
,
3
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
2
,
2
,
3
,
3
,
3
,
3
,
3
,
3
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
3
,
3
,
3
,
3
,
3
,
3
,
3
,
3
,
3
,
3
,
3
,
3
,
3
,
3
,
4
,
4
,
3
,
3
,
3
,
3
,
3
,
3
,
3
,
3
,
3
,
3
,
4
,
4
,
4
,
4
,
4
,
4
,
3
,
3
,
3
,
3
,
3
,
3
,
4
,
4
,
4
,
4
,
4
,
4
,
4
,
4
,
4
,
4
,
3
,
3
,
4
,
4
,
4
,
4
,
4
,
4
,
4
,
4
,
4
,
4
,
4
,
4
,
4
,
4
,
};
static
const
int8_t
quant_spectrum_value
[]
=
{
+
0
,
+
0
,
+
0
,
+
0
,
+
0
,
+
0
,
+
0
,
+
0
,
+
0
,
+
0
,
+
0
,
+
0
,
+
0
,
+
0
,
+
0
,
+
0
,
+
0
,
+
0
,
+
1
,
-
1
,
+
0
,
+
0
,
+
0
,
+
0
,
+
0
,
+
0
,
+
0
,
+
0
,
+
0
,
+
0
,
+
0
,
+
0
,
+
0
,
+
0
,
+
1
,
+
1
,
-
1
,
-
1
,
+
2
,
-
2
,
+
0
,
+
0
,
+
0
,
+
0
,
+
0
,
+
0
,
+
0
,
+
0
,
+
0
,
+
0
,
+
1
,
-
1
,
+
2
,
-
2
,
+
3
,
-
3
,
+
0
,
+
0
,
+
0
,
+
0
,
+
0
,
+
0
,
+
0
,
+
0
,
+
0
,
+
0
,
+
1
,
+
1
,
-
1
,
-
1
,
+
2
,
+
2
,
-
2
,
-
2
,
+
3
,
+
3
,
-
3
,
-
3
,
+
4
,
-
4
,
+
0
,
+
0
,
+
1
,
+
1
,
-
1
,
-
1
,
+
2
,
+
2
,
-
2
,
-
2
,
+
3
,
-
3
,
+
4
,
-
4
,
+
5
,
-
5
,
+
0
,
+
0
,
+
1
,
+
1
,
-
1
,
-
1
,
+
2
,
-
2
,
+
3
,
-
3
,
+
4
,
-
4
,
+
5
,
-
5
,
+
6
,
-
6
,
+
0
,
+
0
,
+
1
,
-
1
,
+
2
,
-
2
,
+
3
,
-
3
,
+
4
,
-
4
,
+
5
,
-
5
,
+
6
,
-
6
,
+
7
,
-
7
,
};
static
const
uint8_t
scale_table
[]
=
{
15
,
14
,
14
,
14
,
14
,
14
,
14
,
13
,
13
,
13
,
13
,
13
,
13
,
12
,
12
,
12
,
12
,
12
,
12
,
11
,
11
,
11
,
11
,
11
,
11
,
10
,
10
,
10
,
10
,
10
,
10
,
10
,
9
,
9
,
9
,
9
,
9
,
9
,
8
,
8
,
8
,
8
,
8
,
8
,
7
,
6
,
6
,
5
,
4
,
4
,
4
,
3
,
3
,
3
,
2
,
2
,
2
,
2
,
1
,
};
static
const
float
window
[
128
]
=
{
0
.
0006
90534
,
0
.
001
97623
,
0
.
003673
86
,
0
.
00572424
,
0
.
00
80967
,
0
.
0107732
,
0
.
0137425
,
0
.
016
9979
,
0
.
0205353
,
0
.
024352
9
,
0
.
02
84505
,
0
.
032
8291
,
0
.
0374
906
,
0
.
042437
9
,
0
.
0476744
,
0
.
0532043
,
0
.
05
90321
,
0
.
065162
9
,
0
.
071602
,
0
.
07
83552
,
0
.
0854285
,
0
.
092828
,
0
.
10056
,
0
.
108631
,
0
.
117048
,
0
.
125817
,
0
.
134944
,
0
.
144437
,
0
.
1543
,
0
.
164539
,
0
.
175161
,
0
.
186169
,
0
.
197569
,
0
.
209363
,
0
.
221555
,
0
.
234145
,
0
.
247136
,
0
.
260526
,
0
.
274313
,
0
.
288493
,
0
.
303062
,
0
.
318012
,
0
.
333333
,
0
.
349015
,
0
.
365044
,
0
.
381403
,
0
.
398073
,
0
.
415034
,
0
.
43226
,
0
.
449725
,
0
.
4674
,
0
.
485251
,
0
.
503245
,
0
.
521344
,
0
.
539509
,
0
.
557698
,
0
.
575869
,
0
.
593978
,
0
.
611981
,
0
.
629831
,
0
.
647486
,
0
.
6649
,
0
.
682031
,
0
.
698838
,
0
.
71528
,
0
.
731323
,
0
.
746932
,
0
.
762077
,
0
.
776732
,
0
.
790873
,
0
.
804481
,
0
.
817542
,
0
.
830044
,
0
.
84198
,
0
.
853347
,
0
.
864144
,
0
.
874375
,
0
.
884046
,
0
.
893167
,
0
.
901749
,
0
.
909806
,
0
.
917354
,
0
.
924409
,
0
.
93099
,
0
.
937117
,
0
.
942809
,
0
.
948087
,
0
.
952971
,
0
.
957482
,
0
.
961641
,
0
.
965467
,
0
.
968981
,
0
.
972202
,
0
.
975148
,
0
.
977838
,
0
.
980289
,
0
.
982518
,
0
.
98454
,
0
.
986371
,
0
.
988024
,
0
.
989514
,
0
.
990853
,
0
.
992053
,
0
.
993126
,
0
.
994082
,
0
.
994931
,
0
.
995682
,
0
.
996344
,
0
.
996926
,
0
.
997433
,
0
.
997875
,
0
.
998256
,
0
.
998584
,
0
.
998863
,
0
.
999099
,
0
.
999297
,
0
.
999461
,
0
.
999595
,
0
.
999703
,
0
.
999789
,
0
.
999856
,
0
.
999906
,
0
.
999942
,
0
.
999967
,
0
.
999984
,
0
.
999993
,
0
.
999998
,
1
.
0
,
};
static
const
float
intensity_ratio_table
[]
=
{
2
.
0
,
1
.
85714
,
1
.
71429
,
1
.
57143
,
1
.
42857
,
1
.
28571
,
1
.
14286
,
1
.
0
,
0
.
857143
,
0
.
714286
,
0
.
571429
,
0
.
428571
,
0
.
285714
,
0
.
142857
,
0
.
0
,
0
.
0
,
0
,
1.87066e-08
,
2.49253e-08
,
3.32113e-08
,
4.42518e-08
,
5.89626e-08
,
7.85637e-08
,
1.04681e-07
,
1.3948e-07
,
1.85848e-07
,
2.4763e-07
,
3.2995e-07
,
4.39636e-07
,
5.85785e-07
,
7.80519e-07
,
1.03999e-06
,
1.38572e-06
,
1.84637e-06
,
2.46017e-06
,
3.27801e-06
,
4.36772e-06
,
5.8197e-06
,
7.75435e-06
,
1.03321e-05
,
1.37669e-05
,
1.83435e-05
,
2.44414e-05
,
3.25665e-05
,
4.33927e-05
,
5.78179e-05
,
7.70384e-05
,
0
.
00010264
8
,
0
.
000136772
,
0
.
0001
8224
,
0
.
000242
822
,
0
.
000323544
,
0
.
000431101
,
0
.
000574413
,
0
.
000765366
,
0
.
00101
98
,
0
.
00135
881
,
0
.
001
81053
,
0
.
0024124
,
0
.
00321437
,
0
.
0042
8293
,
0
.
00570671
,
0
.
007603
81
,
0
.
0101316
,
0
.
0134
996
,
0
.
017
9873
,
0
.
023
9669
,
0
.
031
9343
,
0
.
0425503
,
0
.
0566
954
,
0
.
075542
8
,
0
.
100656
,
0
.
134117
,
0
.
178702
,
0
.
238108
,
0
.
317263
,
0
.
422731
,
0
.
563261
,
0
.
750507
,
0
.
0
,
};
static
const
float
scale_conversion_table
[]
=
{
1
.
0
,
1
.
33243
,
1
.
77538
,
2
.
36557
,
3
.
15196
,
4
.
19978
,
5
.
59592
,
7
.
45618
,
9
.
93486
,
13
.
2375
,
17
.
6381
,
23
.
5016
,
31
.
3143
,
41
.
7242
,
55
.
5947
,
74
.
0762
,
98
.
7015
,
131
.
513
,
175
.
232
,
233
.
485
,
311
.
103
,
414
.
524
,
552
.
326
,
735
.
937
,
980
.
586
,
1306
.
56
,
1740
.
91
,
2319
.
64
,
3090
.
77
,
4118
.
24
,
5487
.
28
,
7311
.
43
,
9741
.
98
,
12980
.
5
,
17295
.
7
,
23045
.
3
,
30706
.
4
,
40914
.
2
,
54515
.
4
,
72638
,
96785
.
3
,
128960
,
171830
,
228952
,
305064
,
406477
,
541603
,
721649
,
961548
,
1.2812e+06
,
1.70711e+06
,
2.27461e+06
,
3.03076e+06
,
4.03829e+06
,
5.38075e+06
,
7.16948e+06
,
9.55285e+06
,
1.27285e+07
,
1.69599e+07
,
2.25979e+07
,
3.01102e+07
,
4.01198e+07
,
5.3457e+07
,
0
,
};
static
const
float
dequantizer_scaling_table
[]
=
{
1.58838e-07
,
2.11641e-07
,
2.81998e-07
,
3.75743e-07
,
5.00652e-07
,
6.67085e-07
,
8.88846e-07
,
1.18433e-06
,
1.57804e-06
,
2.10263e-06
,
2.80161e-06
,
3.73296e-06
,
4.97391e-06
,
6.6274e-06
,
8.83057e-06
,
1.17661e-05
,
1.56776e-05
,
2.08893e-05
,
2.78336e-05
,
3.70864e-05
,
4.94151e-05
,
6.58423e-05
,
8.77305e-05
,
0
.
000116
895
,
0
.
000155755
,
0
.
000207533
,
0
.
000276523
,
0
.
00036
8448
,
0
.
0004
90933
,
0
.
000654135
,
0
.
000
87159
,
0
.
00116134
,
0
.
0015474
,
0
.
002061
81
,
0
.
00274722
,
0
.
0036604
8
,
0
.
004
87735
,
0
.
0064
9874
,
0
.
00
865913
,
0
.
0115377
,
0
.
0153732
,
0
.
0204
838
,
0
.
0272
932
,
0
.
0363664
,
0
.
04
84558
,
0
.
0645641
,
0
.
0860272
,
0
.
114626
,
0
.
152731
,
0
.
203503
,
0
.
271155
,
0
.
361295
,
0
.
481401
,
0
.
641435
,
0
.
854669
,
1
.
13879
,
1
.
51736
,
2
.
0217
8
,
2
.
69388
,
3
.
58942
,
4
.
78266
,
6
.
37257
,
8
.
49102
,
11
.
3137
,
};
static
const
float
quant_step_size
[]
=
{
0
.
0
,
0
.
666667
,
0
.
4
,
0
.
285714
,
0
.
222222
,
0
.
181818
,
0
.
153846
,
0
.
133333
,
0
.
0645161
,
0
.
031746
,
0
.
01574
8
,
0
.
007
84314
,
0
.
003
91389
,
0
.
001
95503
,
0
.
000
97704
,
0
.
0004
88401
,
};
static
const
uint8_t
ath_base_curve
[
656
]
=
{
0x78
,
0x5F
,
0x56
,
0x51
,
0x4E
,
0x4C
,
0x4B
,
0x49
,
0x48
,
0x48
,
0x47
,
0x46
,
0x46
,
0x45
,
0x45
,
0x45
,
0x44
,
0x44
,
0x44
,
0x44
,
0x43
,
0x43
,
0x43
,
0x43
,
0x43
,
0x43
,
0x42
,
0x42
,
0x42
,
0x42
,
0x42
,
0x42
,
0x42
,
0x42
,
0x41
,
0x41
,
0x41
,
0x41
,
0x41
,
0x41
,
0x41
,
0x41
,
0x41
,
0x41
,
0x40
,
0x40
,
0x40
,
0x40
,
0x40
,
0x40
,
0x40
,
0x40
,
0x40
,
0x3F
,
0x3F
,
0x3F
,
0x3F
,
0x3F
,
0x3F
,
0x3F
,
0x3F
,
0x3F
,
0x3F
,
0x3F
,
0x3F
,
0x3F
,
0x3F
,
0x3E
,
0x3E
,
0x3E
,
0x3E
,
0x3E
,
0x3E
,
0x3D
,
0x3D
,
0x3D
,
0x3D
,
0x3D
,
0x3D
,
0x3D
,
0x3C
,
0x3C
,
0x3C
,
0x3C
,
0x3C
,
0x3C
,
0x3C
,
0x3C
,
0x3B
,
0x3B
,
0x3B
,
0x3B
,
0x3B
,
0x3B
,
0x3B
,
0x3B
,
0x3B
,
0x3B
,
0x3B
,
0x3B
,
0x3B
,
0x3B
,
0x3B
,
0x3B
,
0x3B
,
0x3B
,
0x3B
,
0x3B
,
0x3B
,
0x3B
,
0x3B
,
0x3B
,
0x3B
,
0x3B
,
0x3B
,
0x3B
,
0x3B
,
0x3B
,
0x3B
,
0x3B
,
0x3C
,
0x3C
,
0x3C
,
0x3C
,
0x3C
,
0x3C
,
0x3C
,
0x3C
,
0x3D
,
0x3D
,
0x3D
,
0x3D
,
0x3D
,
0x3D
,
0x3D
,
0x3D
,
0x3E
,
0x3E
,
0x3E
,
0x3E
,
0x3E
,
0x3E
,
0x3E
,
0x3F
,
0x3F
,
0x3F
,
0x3F
,
0x3F
,
0x3F
,
0x3F
,
0x3F
,
0x3F
,
0x3F
,
0x3F
,
0x3F
,
0x3F
,
0x3F
,
0x3F
,
0x3F
,
0x3F
,
0x3F
,
0x3F
,
0x3F
,
0x3F
,
0x40
,
0x40
,
0x40
,
0x40
,
0x40
,
0x40
,
0x40
,
0x40
,
0x40
,
0x40
,
0x40
,
0x40
,
0x40
,
0x40
,
0x40
,
0x40
,
0x40
,
0x40
,
0x40
,
0x40
,
0x40
,
0x41
,
0x41
,
0x41
,
0x41
,
0x41
,
0x41
,
0x41
,
0x41
,
0x41
,
0x41
,
0x41
,
0x41
,
0x41
,
0x41
,
0x41
,
0x41
,
0x41
,
0x41
,
0x41
,
0x41
,
0x41
,
0x41
,
0x41
,
0x41
,
0x41
,
0x41
,
0x41
,
0x41
,
0x41
,
0x41
,
0x42
,
0x42
,
0x42
,
0x42
,
0x42
,
0x42
,
0x42
,
0x42
,
0x42
,
0x42
,
0x42
,
0x42
,
0x42
,
0x42
,
0x42
,
0x42
,
0x42
,
0x42
,
0x42
,
0x42
,
0x42
,
0x42
,
0x43
,
0x43
,
0x43
,
0x43
,
0x43
,
0x43
,
0x43
,
0x43
,
0x43
,
0x43
,
0x43
,
0x43
,
0x43
,
0x43
,
0x43
,
0x43
,
0x43
,
0x44
,
0x44
,
0x44
,
0x44
,
0x44
,
0x44
,
0x44
,
0x44
,
0x44
,
0x44
,
0x44
,
0x44
,
0x44
,
0x44
,
0x45
,
0x45
,
0x45
,
0x45
,
0x45
,
0x45
,
0x45
,
0x45
,
0x45
,
0x45
,
0x45
,
0x45
,
0x46
,
0x46
,
0x46
,
0x46
,
0x46
,
0x46
,
0x46
,
0x46
,
0x46
,
0x46
,
0x47
,
0x47
,
0x47
,
0x47
,
0x47
,
0x47
,
0x47
,
0x47
,
0x47
,
0x47
,
0x48
,
0x48
,
0x48
,
0x48
,
0x48
,
0x48
,
0x48
,
0x48
,
0x49
,
0x49
,
0x49
,
0x49
,
0x49
,
0x49
,
0x49
,
0x49
,
0x4A
,
0x4A
,
0x4A
,
0x4A
,
0x4A
,
0x4A
,
0x4A
,
0x4A
,
0x4B
,
0x4B
,
0x4B
,
0x4B
,
0x4B
,
0x4B
,
0x4B
,
0x4C
,
0x4C
,
0x4C
,
0x4C
,
0x4C
,
0x4C
,
0x4D
,
0x4D
,
0x4D
,
0x4D
,
0x4D
,
0x4D
,
0x4E
,
0x4E
,
0x4E
,
0x4E
,
0x4E
,
0x4E
,
0x4F
,
0x4F
,
0x4F
,
0x4F
,
0x4F
,
0x4F
,
0x50
,
0x50
,
0x50
,
0x50
,
0x50
,
0x51
,
0x51
,
0x51
,
0x51
,
0x51
,
0x52
,
0x52
,
0x52
,
0x52
,
0x52
,
0x53
,
0x53
,
0x53
,
0x53
,
0x54
,
0x54
,
0x54
,
0x54
,
0x54
,
0x55
,
0x55
,
0x55
,
0x55
,
0x56
,
0x56
,
0x56
,
0x56
,
0x57
,
0x57
,
0x57
,
0x57
,
0x57
,
0x58
,
0x58
,
0x58
,
0x59
,
0x59
,
0x59
,
0x59
,
0x5A
,
0x5A
,
0x5A
,
0x5A
,
0x5B
,
0x5B
,
0x5B
,
0x5B
,
0x5C
,
0x5C
,
0x5C
,
0x5D
,
0x5D
,
0x5D
,
0x5D
,
0x5E
,
0x5E
,
0x5E
,
0x5F
,
0x5F
,
0x5F
,
0x60
,
0x60
,
0x60
,
0x61
,
0x61
,
0x61
,
0x61
,
0x62
,
0x62
,
0x62
,
0x63
,
0x63
,
0x63
,
0x64
,
0x64
,
0x64
,
0x65
,
0x65
,
0x66
,
0x66
,
0x66
,
0x67
,
0x67
,
0x67
,
0x68
,
0x68
,
0x68
,
0x69
,
0x69
,
0x6A
,
0x6A
,
0x6A
,
0x6B
,
0x6B
,
0x6B
,
0x6C
,
0x6C
,
0x6D
,
0x6D
,
0x6D
,
0x6E
,
0x6E
,
0x6F
,
0x6F
,
0x70
,
0x70
,
0x70
,
0x71
,
0x71
,
0x72
,
0x72
,
0x73
,
0x73
,
0x73
,
0x74
,
0x74
,
0x75
,
0x75
,
0x76
,
0x76
,
0x77
,
0x77
,
0x78
,
0x78
,
0x78
,
0x79
,
0x79
,
0x7A
,
0x7A
,
0x7B
,
0x7B
,
0x7C
,
0x7C
,
0x7D
,
0x7D
,
0x7E
,
0x7E
,
0x7F
,
0x7F
,
0x80
,
0x80
,
0x81
,
0x81
,
0x82
,
0x83
,
0x83
,
0x84
,
0x84
,
0x85
,
0x85
,
0x86
,
0x86
,
0x87
,
0x88
,
0x88
,
0x89
,
0x89
,
0x8A
,
0x8A
,
0x8B
,
0x8C
,
0x8C
,
0x8D
,
0x8D
,
0x8E
,
0x8F
,
0x8F
,
0x90
,
0x90
,
0x91
,
0x92
,
0x92
,
0x93
,
0x94
,
0x94
,
0x95
,
0x95
,
0x96
,
0x97
,
0x97
,
0x98
,
0x99
,
0x99
,
0x9A
,
0x9B
,
0x9B
,
0x9C
,
0x9D
,
0x9D
,
0x9E
,
0x9F
,
0xA0
,
0xA0
,
0xA1
,
0xA2
,
0xA2
,
0xA3
,
0xA4
,
0xA5
,
0xA5
,
0xA6
,
0xA7
,
0xA7
,
0xA8
,
0xA9
,
0xAA
,
0xAA
,
0xAB
,
0xAC
,
0xAD
,
0xAE
,
0xAE
,
0xAF
,
0xB0
,
0xB1
,
0xB1
,
0xB2
,
0xB3
,
0xB4
,
0xB5
,
0xB6
,
0xB6
,
0xB7
,
0xB8
,
0xB9
,
0xBA
,
0xBA
,
0xBB
,
0xBC
,
0xBD
,
0xBE
,
0xBF
,
0xC0
,
0xC1
,
0xC1
,
0xC2
,
0xC3
,
0xC4
,
0xC5
,
0xC6
,
0xC7
,
0xC8
,
0xC9
,
0xC9
,
0xCA
,
0xCB
,
0xCC
,
0xCD
,
0xCE
,
0xCF
,
0xD0
,
0xD1
,
0xD2
,
0xD3
,
0xD4
,
0xD5
,
0xD6
,
0xD7
,
0xD8
,
0xD9
,
0xDA
,
0xDB
,
0xDC
,
0xDD
,
0xDE
,
0xDF
,
0xE0
,
0xE1
,
0xE2
,
0xE3
,
0xE4
,
0xE5
,
0xE6
,
0xE7
,
0xE8
,
0xE9
,
0xEA
,
0xEB
,
0xED
,
0xEE
,
0xEF
,
0xF0
,
0xF1
,
0xF2
,
0xF3
,
0xF4
,
0xF5
,
0xF7
,
0xF8
,
0xF9
,
0xFA
,
0xFB
,
0xFC
,
0xFD
,
0xFF
,
0xFF
,
};
#endif
/* AVCODEC_HCA_DATA_H */
libavcodec/hcadec.c
0 → 100644
View file @
fed0de37
/*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "libavutil/crc.h"
#include "libavutil/float_dsp.h"
#include "libavutil/intreadwrite.h"
#include "libavutil/tx.h"
#include "avcodec.h"
#include "get_bits.h"
#include "internal.h"
#include "hca_data.h"
typedef
struct
ChannelContext
{
float
base
[
128
];
DECLARE_ALIGNED
(
32
,
float
,
imdct_in
)[
128
];
DECLARE_ALIGNED
(
32
,
float
,
imdct_out
)[
128
];
DECLARE_ALIGNED
(
32
,
float
,
imdct_prev
)[
128
];
int8_t
scale_factors
[
128
];
uint8_t
scale
[
128
];
int8_t
intensity
[
8
];
int8_t
*
hfr_scale
;
unsigned
count
;
int
chan_type
;
}
ChannelContext
;
typedef
struct
HCAContext
{
GetBitContext
gb
;
const
AVCRC
*
crc_table
;
ChannelContext
ch
[
16
];
uint8_t
ath
[
128
];
int
ath_type
;
unsigned
hfr_group_count
;
uint8_t
track_count
;
uint8_t
channel_config
;
uint8_t
total_band_count
;
uint8_t
base_band_count
;
uint8_t
stereo_band_count
;
uint8_t
bands_per_hfr_group
;
av_tx_fn
tx_fn
;
AVTXContext
*
tx_ctx
;
AVFloatDSPContext
*
fdsp
;
}
HCAContext
;
static
void
ath_init1
(
uint8_t
*
ath
,
int
sample_rate
)
{
unsigned
int
index
;
unsigned
int
acc
=
0
;
for
(
int
i
=
0
;
i
<
128
;
i
++
)
{
acc
+=
sample_rate
;
index
=
acc
>>
13
;
if
(
index
>=
654
)
{
memset
(
ath
+
i
,
0xFF
,
(
128
-
i
));
break
;
}
ath
[
i
]
=
ath_base_curve
[
index
];
}
}
static
int
ath_init
(
uint8_t
*
ath
,
int
type
,
int
sample_rate
)
{
switch
(
type
)
{
case
0
:
/* nothing to do */
break
;
case
1
:
ath_init1
(
ath
,
sample_rate
);
break
;
default:
return
AVERROR_INVALIDDATA
;
}
return
0
;
}
static
inline
unsigned
ceil2
(
unsigned
a
,
unsigned
b
)
{
return
(
b
>
0
)
?
(
a
/
b
+
((
a
%
b
)
?
1
:
0
))
:
0
;
}
static
av_cold
int
decode_init
(
AVCodecContext
*
avctx
)
{
HCAContext
*
c
=
avctx
->
priv_data
;
GetBitContext
*
gb
=
&
c
->
gb
;
int8_t
r
[
16
]
=
{
0
};
float
scale
=
1
.
f
/
8
.
f
;
unsigned
b
,
chunk
;
int
version
,
ret
;
avctx
->
sample_fmt
=
AV_SAMPLE_FMT_FLTP
;
c
->
crc_table
=
av_crc_get_table
(
AV_CRC_16_ANSI
);
if
(
avctx
->
channels
<=
0
||
avctx
->
channels
>
16
)
return
AVERROR
(
EINVAL
);
ret
=
init_get_bits8
(
gb
,
avctx
->
extradata
,
avctx
->
extradata_size
);
if
(
ret
<
0
)
return
ret
;
skip_bits_long
(
gb
,
32
);
version
=
get_bits
(
gb
,
16
);
skip_bits_long
(
gb
,
16
);
c
->
ath_type
=
version
>=
0x200
?
0
:
1
;
if
(
get_bits_long
(
gb
,
32
)
!=
MKBETAG
(
'f'
,
'm'
,
't'
,
0
))
return
AVERROR_INVALIDDATA
;
skip_bits_long
(
gb
,
32
);
skip_bits_long
(
gb
,
32
);
skip_bits_long
(
gb
,
32
);
chunk
=
get_bits_long
(
gb
,
32
);
if
(
chunk
==
MKBETAG
(
'c'
,
'o'
,
'm'
,
'p'
))
{
skip_bits_long
(
gb
,
16
);
skip_bits_long
(
gb
,
8
);
skip_bits_long
(
gb
,
8
);
c
->
track_count
=
get_bits
(
gb
,
8
);
c
->
channel_config
=
get_bits
(
gb
,
8
);
c
->
total_band_count
=
get_bits
(
gb
,
8
);
c
->
base_band_count
=
get_bits
(
gb
,
8
);
c
->
stereo_band_count
=
get_bits
(
gb
,
8
);
c
->
bands_per_hfr_group
=
get_bits
(
gb
,
8
);
}
else
if
(
chunk
==
MKBETAG
(
'd'
,
'e'
,
'c'
,
0
))
{
skip_bits_long
(
gb
,
16
);
skip_bits_long
(
gb
,
8
);
skip_bits_long
(
gb
,
8
);
c
->
total_band_count
=
get_bits
(
gb
,
8
)
+
1
;
c
->
base_band_count
=
get_bits
(
gb
,
8
)
+
1
;
c
->
track_count
=
get_bits
(
gb
,
4
);
c
->
channel_config
=
get_bits
(
gb
,
4
);
if
(
!
get_bits
(
gb
,
8
))
c
->
base_band_count
=
c
->
total_band_count
;
c
->
stereo_band_count
=
c
->
total_band_count
-
c
->
base_band_count
;
c
->
bands_per_hfr_group
=
0
;
}
else
return
AVERROR_INVALIDDATA
;
while
(
get_bits_left
(
gb
)
>=
32
)
{
chunk
=
get_bits_long
(
gb
,
32
);
if
(
chunk
==
MKBETAG
(
'v'
,
'b'
,
'r'
,
0
))
{
skip_bits_long
(
gb
,
16
);
skip_bits_long
(
gb
,
16
);
}
else
if
(
chunk
==
MKBETAG
(
'a'
,
't'
,
'h'
,
0
))
{
c
->
ath_type
=
get_bits
(
gb
,
16
);
}
else
if
(
chunk
==
MKBETAG
(
'r'
,
'v'
,
'a'
,
0
))
{
skip_bits_long
(
gb
,
32
);
}
else
if
(
chunk
==
MKBETAG
(
'c'
,
'o'
,
'm'
,
'm'
))
{
skip_bits_long
(
gb
,
get_bits
(
gb
,
8
)
*
8
);
}
else
if
(
chunk
==
MKBETAG
(
'c'
,
'i'
,
'p'
,
'h'
))
{
skip_bits_long
(
gb
,
16
);
}
else
if
(
chunk
==
MKBETAG
(
'l'
,
'o'
,
'o'
,
'p'
))
{
skip_bits_long
(
gb
,
32
);
skip_bits_long
(
gb
,
32
);
skip_bits_long
(
gb
,
16
);
skip_bits_long
(
gb
,
16
);
}
else
if
(
chunk
==
MKBETAG
(
'p'
,
'a'
,
'd'
,
0
))
{
break
;
}
else
{
break
;
}
}
ret
=
ath_init
(
c
->
ath
,
c
->
ath_type
,
avctx
->
sample_rate
);
if
(
ret
<
0
)
return
ret
;
if
(
!
c
->
track_count
)
c
->
track_count
=
1
;
b
=
avctx
->
channels
/
c
->
track_count
;
if
(
c
->
stereo_band_count
&&
b
>
1
)
{
int8_t
*
x
=
r
;
for
(
int
i
=
0
;
i
<
c
->
track_count
;
i
++
,
x
+=
b
)
{
switch
(
b
)
{
case
2
:
case
3
:
x
[
0
]
=
1
;
x
[
1
]
=
2
;
break
;
case
4
:
x
[
0
]
=
1
;
x
[
1
]
=
2
;
if
(
c
->
channel_config
==
0
)
{
x
[
2
]
=
1
;
x
[
3
]
=
2
;
}
break
;
case
5
:
x
[
0
]
=
1
;
x
[
1
]
=
2
;
if
(
c
->
channel_config
<=
2
)
{
x
[
3
]
=
1
;
x
[
4
]
=
2
;
}
break
;
case
6
:
case
7
:
x
[
0
]
=
1
;
x
[
1
]
=
2
;
x
[
4
]
=
1
;
x
[
5
]
=
2
;
break
;
case
8
:
x
[
0
]
=
1
;
x
[
1
]
=
2
;
x
[
4
]
=
1
;
x
[
5
]
=
2
;
x
[
6
]
=
1
;
x
[
7
]
=
2
;
break
;
}
}
}
if
(
c
->
total_band_count
<
c
->
base_band_count
)
return
AVERROR_INVALIDDATA
;
c
->
hfr_group_count
=
ceil2
(
c
->
total_band_count
-
(
c
->
base_band_count
+
c
->
stereo_band_count
),
c
->
bands_per_hfr_group
);
if
(
c
->
base_band_count
+
c
->
stereo_band_count
+
(
unsigned
long
)
c
->
hfr_group_count
>
128ULL
)
return
AVERROR_INVALIDDATA
;
for
(
int
i
=
0
;
i
<
avctx
->
channels
;
i
++
)
{
c
->
ch
[
i
].
chan_type
=
r
[
i
];
c
->
ch
[
i
].
count
=
c
->
base_band_count
+
((
r
[
i
]
!=
2
)
?
c
->
stereo_band_count
:
0
);
c
->
ch
[
i
].
hfr_scale
=
&
c
->
ch
[
i
].
scale_factors
[
c
->
base_band_count
+
c
->
stereo_band_count
];
if
(
c
->
ch
[
i
].
count
>
128
)
return
AVERROR_INVALIDDATA
;
}
c
->
fdsp
=
avpriv_float_dsp_alloc
(
avctx
->
flags
&
AV_CODEC_FLAG_BITEXACT
);
if
(
!
c
->
fdsp
)
return
AVERROR
(
ENOMEM
);
return
av_tx_init
(
&
c
->
tx_ctx
,
&
c
->
tx_fn
,
AV_TX_FLOAT_MDCT
,
1
,
128
,
&
scale
,
0
);
}
static
void
run_imdct
(
HCAContext
*
c
,
ChannelContext
*
ch
,
int
index
,
float
*
out
)
{
c
->
tx_fn
(
c
->
tx_ctx
,
ch
->
imdct_out
,
ch
->
imdct_in
,
sizeof
(
float
));
c
->
fdsp
->
vector_fmul_window
(
out
,
ch
->
imdct_prev
+
(
128
>>
1
),
ch
->
imdct_out
,
window
,
128
>>
1
);
memcpy
(
ch
->
imdct_prev
,
ch
->
imdct_out
,
128
*
sizeof
(
float
));
}
static
void
apply_intensity_stereo
(
HCAContext
*
s
,
ChannelContext
*
ch1
,
ChannelContext
*
ch2
,
int
index
,
unsigned
band_count
,
unsigned
base_band_count
,
unsigned
stereo_band_count
)
{
float
ratio_l
=
intensity_ratio_table
[
ch1
->
intensity
[
index
]];
float
ratio_r
=
ratio_l
-
2
.
0
f
;
float
*
c1
=
&
ch1
->
imdct_in
[
base_band_count
];
float
*
c2
=
&
ch2
->
imdct_in
[
base_band_count
];
if
(
ch1
->
chan_type
!=
1
||
!
stereo_band_count
)
return
;
for
(
int
i
=
0
;
i
<
band_count
;
i
++
)
{
*
(
c2
++
)
=
*
c1
*
ratio_r
;
*
(
c1
++
)
*=
ratio_l
;
}
}
static
void
reconstruct_hfr
(
HCAContext
*
s
,
ChannelContext
*
ch
,
unsigned
hfr_group_count
,
unsigned
bands_per_hfr_group
,
unsigned
start_band
,
unsigned
total_band_count
)
{
if
(
ch
->
chan_type
==
2
||
!
bands_per_hfr_group
)
return
;
for
(
int
i
=
0
,
k
=
start_band
,
l
=
start_band
-
1
;
i
<
hfr_group_count
;
i
++
){
for
(
int
j
=
0
;
j
<
bands_per_hfr_group
&&
k
<
total_band_count
;
j
++
,
k
++
,
l
--
){
ch
->
imdct_in
[
k
]
=
scale_conversion_table
[
ch
->
hfr_scale
[
i
]
-
ch
->
scale_factors
[
l
]]
*
ch
->
imdct_in
[
l
];
}
}
ch
->
imdct_in
[
127
]
=
0
;
}
static
void
dequantize_coefficients
(
HCAContext
*
c
,
ChannelContext
*
ch
)
{
GetBitContext
*
gb
=
&
c
->
gb
;
for
(
int
i
=
0
;
i
<
ch
->
count
;
i
++
)
{
unsigned
scale
=
ch
->
scale
[
i
];
int
nb_bits
=
max_bits_table
[
scale
];
int
value
=
get_bitsz
(
gb
,
nb_bits
);
float
factor
;
if
(
scale
>
7
)
{
value
=
(
1
-
((
value
&
1
)
<<
1
))
*
(
value
>>
1
);
if
(
!
value
)
skip_bits_long
(
gb
,
-
1
);
factor
=
value
;
}
else
{
value
+=
scale
<<
4
;
skip_bits_long
(
gb
,
quant_spectrum_bits
[
value
]
-
nb_bits
);
factor
=
quant_spectrum_value
[
value
];
}
ch
->
imdct_in
[
i
]
=
factor
*
ch
->
base
[
i
];
}
memset
(
ch
->
imdct_in
+
ch
->
count
,
0
,
sizeof
(
ch
->
imdct_in
)
-
ch
->
count
*
sizeof
(
ch
->
imdct_in
[
0
]));
}
static
void
unpack
(
HCAContext
*
c
,
ChannelContext
*
ch
,
unsigned
hfr_group_count
,
int
packed_noise_level
,
const
uint8_t
*
ath
)
{
GetBitContext
*
gb
=
&
c
->
gb
;
int
delta_bits
=
get_bits
(
gb
,
3
);
if
(
delta_bits
>
5
)
{
for
(
int
i
=
0
;
i
<
ch
->
count
;
i
++
)
ch
->
scale_factors
[
i
]
=
get_bits
(
gb
,
6
);
}
else
if
(
delta_bits
)
{
int
factor
=
get_bits
(
gb
,
6
);
int
max_value
=
(
1
<<
delta_bits
)
-
1
;
int
half_max
=
max_value
>>
1
;
ch
->
scale_factors
[
0
]
=
factor
;
for
(
int
i
=
1
;
i
<
ch
->
count
;
i
++
){
int
delta
=
get_bits
(
gb
,
delta_bits
);
if
(
delta
==
max_value
)
{
factor
=
get_bits
(
gb
,
6
);
}
else
{
factor
+=
delta
-
half_max
;
}
ch
->
scale_factors
[
i
]
=
factor
;
}
}
else
{
memset
(
ch
->
scale_factors
,
0
,
128
);
}
if
(
ch
->
chan_type
==
2
){
ch
->
intensity
[
0
]
=
get_bits
(
gb
,
4
);
if
(
ch
->
intensity
[
0
]
<
15
)
{
for
(
int
i
=
1
;
i
<
8
;
i
++
)
ch
->
intensity
[
i
]
=
get_bits
(
gb
,
4
);
}
}
else
{
for
(
int
i
=
0
;
i
<
hfr_group_count
;
i
++
)
ch
->
hfr_scale
[
i
]
=
get_bits
(
gb
,
6
);
}
for
(
int
i
=
0
;
i
<
ch
->
count
;
i
++
)
{
int
scale
=
ch
->
scale_factors
[
i
];
if
(
scale
)
{
scale
=
c
->
ath
[
i
]
+
((
packed_noise_level
+
i
)
>>
8
)
-
((
scale
*
5
)
>>
1
)
+
2
;
scale
=
scale_table
[
av_clip
(
scale
,
0
,
58
)];
}
ch
->
scale
[
i
]
=
scale
;
}
memset
(
ch
->
scale
+
ch
->
count
,
0
,
sizeof
(
ch
->
scale
)
-
ch
->
count
);
for
(
int
i
=
0
;
i
<
ch
->
count
;
i
++
)
ch
->
base
[
i
]
=
dequantizer_scaling_table
[
ch
->
scale_factors
[
i
]]
*
quant_step_size
[
ch
->
scale
[
i
]];
}
static
int
decode_frame
(
AVCodecContext
*
avctx
,
void
*
data
,
int
*
got_frame_ptr
,
AVPacket
*
avpkt
)
{
AVFrame
*
frame
=
data
;
HCAContext
*
c
=
avctx
->
priv_data
;
int
ch
,
ret
,
packed_noise_level
;
GetBitContext
*
gb
=
&
c
->
gb
;
float
**
samples
;
if
(
avctx
->
err_recognition
&
AV_EF_CRCCHECK
)
{
if
(
av_crc
(
c
->
crc_table
,
0
,
avpkt
->
data
,
avpkt
->
size
))
return
AVERROR_INVALIDDATA
;
}
if
((
ret
=
init_get_bits8
(
gb
,
avpkt
->
data
,
avpkt
->
size
))
<
0
)
return
ret
;
if
(
get_bits
(
gb
,
16
)
!=
0xFFFF
)
return
AVERROR_INVALIDDATA
;
frame
->
nb_samples
=
1024
;
if
((
ret
=
ff_get_buffer
(
avctx
,
frame
,
0
))
<
0
)
return
ret
;
samples
=
(
float
**
)
frame
->
extended_data
;
packed_noise_level
=
(
get_bits
(
gb
,
9
)
<<
8
)
-
get_bits
(
gb
,
7
);
for
(
ch
=
0
;
ch
<
avctx
->
channels
;
ch
++
)
unpack
(
c
,
&
c
->
ch
[
ch
],
c
->
hfr_group_count
,
packed_noise_level
,
c
->
ath
);
for
(
int
i
=
0
;
i
<
8
;
i
++
)
{
for
(
ch
=
0
;
ch
<
avctx
->
channels
;
ch
++
)
dequantize_coefficients
(
c
,
&
c
->
ch
[
ch
]);
for
(
ch
=
0
;
ch
<
avctx
->
channels
;
ch
++
)
reconstruct_hfr
(
c
,
&
c
->
ch
[
ch
],
c
->
hfr_group_count
,
c
->
bands_per_hfr_group
,
c
->
stereo_band_count
+
c
->
base_band_count
,
c
->
total_band_count
);
for
(
ch
=
0
;
ch
<
avctx
->
channels
-
1
;
ch
++
)
apply_intensity_stereo
(
c
,
&
c
->
ch
[
ch
],
&
c
->
ch
[
ch
+
1
],
i
,
c
->
total_band_count
-
c
->
base_band_count
,
c
->
base_band_count
,
c
->
stereo_band_count
);
for
(
ch
=
0
;
ch
<
avctx
->
channels
;
ch
++
)
run_imdct
(
c
,
&
c
->
ch
[
ch
],
i
,
samples
[
ch
]
+
i
*
128
);
}
*
got_frame_ptr
=
1
;
return
avpkt
->
size
;
}
static
av_cold
int
decode_close
(
AVCodecContext
*
avctx
)
{
HCAContext
*
c
=
avctx
->
priv_data
;
av_freep
(
&
c
->
fdsp
);
av_tx_uninit
(
&
c
->
tx_ctx
);
return
0
;
}
AVCodec
ff_hca_decoder
=
{
.
name
=
"hca"
,
.
long_name
=
NULL_IF_CONFIG_SMALL
(
"CRI HCA"
),
.
type
=
AVMEDIA_TYPE_AUDIO
,
.
id
=
AV_CODEC_ID_HCA
,
.
priv_data_size
=
sizeof
(
HCAContext
),
.
init
=
decode_init
,
.
decode
=
decode_frame
,
.
close
=
decode_close
,
.
capabilities
=
AV_CODEC_CAP_DR1
,
.
sample_fmts
=
(
const
enum
AVSampleFormat
[])
{
AV_SAMPLE_FMT_FLTP
,
AV_SAMPLE_FMT_NONE
},
};
libavcodec/version.h
View file @
fed0de37
...
...
@@ -28,7 +28,7 @@
#include "libavutil/version.h"
#define LIBAVCODEC_VERSION_MAJOR 58
#define LIBAVCODEC_VERSION_MINOR 7
5
#define LIBAVCODEC_VERSION_MINOR 7
6
#define LIBAVCODEC_VERSION_MICRO 100
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
...
...
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