1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
let address_increment =
[ ("1", 1); ("011", 2); ("010", 3); ("0011", 4); ("0010", 5); ("0001 1", 6); ("0001 0", 7);
("0000 111", 8); ("0000 110", 9); ("0000 1011", 10); ("0000 1010", 11); ("0000 1001", 12);
("0000 1000", 13); ("0000 0111", 14); ("0000 0110", 15); ("0000 0101 11", 16); ("0000 0101 10", 17);
("0000 0101 01", 18); ("0000 0101 00", 19); ("0000 0100 11", 20); ("0000 0100 10", 21);
("0000 0100 011", 22); ("0000 0100 010", 23); ("0000 0100 001", 24); ("0000 0100 000", 25);
("0000 0011 111", 26); ("0000 0011 110", 27); ("0000 0011 101", 28); ("0000 0011 100", 29);
("0000 0011 011", 30); ("0000 0011 010", 31); ("0000 0011 001", 32); ("0000 0011 000", 33);
("0000 0001 111", -1) ; ("0000 0001 000", -2) ]
type mb_type = { quant : bool; forward : bool; backward : bool; pattern : bool; intra : bool }
let mb ?(quant = false) ?(forward = false) ?(backward = false) ?(pattern = false) ?(intra = false) () = { quant; forward; backward; pattern; intra }
let mb_type_i = [ ("1", mb ~intra:true ()); ("01", mb ~intra:true ~quant:true ()) ]
let mb_type_p =
[ ("1", mb ~forward:true ~pattern:true ()); ("01", mb ~pattern:true ()); ("001", mb ~forward:true ());
("0001 1", mb ~intra:true ()); ("0001 0", mb ~forward:true ~pattern:true ~quant:true ());
("0000 1", mb ~pattern:true ~quant:true ()); ("0000 01", mb ~intra:true ~quant:true ()) ]
let mb_type_b =
[ ("10", mb ~forward:true ~backward:true ()); ("11", mb ~forward:true ~backward:true ~pattern:true ());
("010", mb ~backward:true ()); ("011", mb ~backward:true ~pattern:true ());
("0010", mb ~forward:true ()); ("0011", mb ~forward:true ~pattern:true ());
("0001 1", mb ~intra:true ()); ("0001 0", mb ~forward:true ~backward:true ~pattern:true ~quant:true ());
("0000 11", mb ~forward:true ~pattern:true ~quant:true ()); ("0000 10", mb ~backward:true ~pattern:true ~quant:true ());
("0000 01", mb ~intra:true ~quant:true ()) ]
let coded_block_pattern =
[ ("111", 60); ("1101", 4); ("1100", 8); ("1011", 16); ("1010", 32);
("1001 1", 12); ("1001 0", 48); ("1000 1", 20); ("1000 0", 40); ("0111 1", 28); ("0111 0", 44);
("0110 1", 52); ("0110 0", 56); ("0101 1", 1); ("0101 0", 61); ("0100 1", 2); ("0100 0", 62);
("0011 11", 24); ("0011 10", 36); ("0011 01", 3); ("0011 00", 63);
("0010 111", 5); ("0010 110", 9); ("0010 101", 17); ("0010 100", 33);
("0010 011", 6); ("0010 010", 10); ("0010 001", 18); ("0010 000", 34);
("0001 1111", 7); ("0001 1110", 11); ("0001 1101", 19); ("0001 1100", 35);
("0001 1011", 13); ("0001 1010", 49); ("0001 1001", 21); ("0001 1000", 41);
("0001 0111", 14); ("0001 0110", 50); ("0001 0101", 22); ("0001 0100", 42);
("0001 0011", 15); ("0001 0010", 51); ("0001 0001", 23); ("0001 0000", 43);
("0000 1111", 25); ("0000 1110", 37); ("0000 1101", 26); ("0000 1100", 38);
("0000 1011", 29); ("0000 1010", 45); ("0000 1001", 53); ("0000 1000", 57);
("0000 0111", 30); ("0000 0110", 46); ("0000 0101", 54); ("0000 0100", 58);
("0000 0011 1", 31); ("0000 0011 0", 47); ("0000 0010 1", 55); ("0000 0010 0", 59);
("0000 0001 1", 27); ("0000 0001 0", 39) ]
let motion_code =
("1", 0)
:: List.concat_map
(fun (code, m) -> [ (code ^ "0", m); (code ^ "1", -m) ])
[ ("01", 1); ("001", 2); ("0001", 3); ("0000 11", 4); ("0000 101", 5); ("0000 100", 6); ("0000 011", 7);
("0000 0101 1", 8); ("0000 0101 0", 9); ("0000 0100 1", 10); ("0000 0100 01", 11); ("0000 0100 00", 12);
("0000 0011 11", 13); ("0000 0011 10", 14); ("0000 0011 01", 15); ("0000 0011 00", 16) ]
let dc_size_luminance =
[ ("100", 0); ("00", 1); ("01", 2); ("101", 3); ("110", 4); ("1110", 5); ("1111 0", 6); ("1111 10", 7); ("1111 110", 8) ]
let dc_size_chrominance =
[ ("00", 0); ("01", 1); ("10", 2); ("110", 3); ("1110", 4); ("1111 0", 5); ("1111 10", 6); ("1111 110", 7); ("1111 1110", 8) ]
type coefficient = Coeff of int * int | Eob | Escape
let coefficients =
[ ("011", (1, 1)); ("0100", (0, 2)); ("0101", (2, 1)); ("0010 1", (0, 3)); ("0011 1", (3, 1)); ("0011 0", (4, 1));
("0001 10", (1, 2)); ("0001 11", (5, 1)); ("0001 01", (6, 1)); ("0001 00", (7, 1));
("0000 110", (0, 4)); ("0000 100", (2, 2)); ("0000 111", (8, 1)); ("0000 101", (9, 1));
("0010 0110", (0, 5)); ("0010 0001", (0, 6)); ("0010 0101", (1, 3)); ("0010 0100", (3, 2));
("0010 0111", (10, 1)); ("0010 0011", (11, 1)); ("0010 0010", (12, 1)); ("0010 0000", (13, 1));
("0000 0010 10", (0, 7)); ("0000 0011 00", (1, 4)); ("0000 0010 11", (2, 3)); ("0000 0011 11", (4, 2));
("0000 0010 01", (5, 2)); ("0000 0011 10", (14, 1)); ("0000 0011 01", (15, 1)); ("0000 0010 00", (16, 1));
("0000 0001 1101", (0, 8)); ("0000 0001 1000", (0, 9)); ("0000 0001 0011", (0, 10)); ("0000 0001 0000", (0, 11));
("0000 0001 1011", (1, 5)); ("0000 0001 0100", (2, 4)); ("0000 0001 1100", (3, 3)); ("0000 0001 0010", (4, 3));
("0000 0001 1110", (6, 2)); ("0000 0001 0101", (7, 2)); ("0000 0001 0001", (8, 2)); ("0000 0001 1111", (17, 1));
("0000 0001 1010", (18, 1)); ("0000 0001 1001", (19, 1)); ("0000 0001 0111", (20, 1)); ("0000 0001 0110", (21, 1));
("0000 0000 1101 0", (0, 12)); ("0000 0000 1100 1", (0, 13)); ("0000 0000 1100 0", (0, 14)); ("0000 0000 1011 1", (0, 15));
("0000 0000 1011 0", (1, 6)); ("0000 0000 1010 1", (1, 7)); ("0000 0000 1010 0", (2, 5)); ("0000 0000 1001 1", (3, 4));
("0000 0000 1001 0", (5, 3)); ("0000 0000 1000 1", (9, 2)); ("0000 0000 1000 0", (10, 2)); ("0000 0000 1111 1", (22, 1));
("0000 0000 1111 0", (23, 1)); ("0000 0000 1110 1", (24, 1)); ("0000 0000 1110 0", (25, 1)); ("0000 0000 1101 1", (26, 1));
("0000 0000 0111 11", (0, 16)); ("0000 0000 0111 10", (0, 17)); ("0000 0000 0111 01", (0, 18)); ("0000 0000 0111 00", (0, 19));
("0000 0000 0110 11", (0, 20)); ("0000 0000 0110 10", (0, 21)); ("0000 0000 0110 01", (0, 22)); ("0000 0000 0110 00", (0, 23));
("0000 0000 0101 11", (0, 24)); ("0000 0000 0101 10", (0, 25)); ("0000 0000 0101 01", (0, 26)); ("0000 0000 0101 00", (0, 27));
("0000 0000 0100 11", (0, 28)); ("0000 0000 0100 10", (0, 29)); ("0000 0000 0100 01", (0, 30)); ("0000 0000 0100 00", (0, 31));
("0000 0000 0011 000", (0, 32)); ("0000 0000 0010 111", (0, 33)); ("0000 0000 0010 110", (0, 34)); ("0000 0000 0010 101", (0, 35));
("0000 0000 0010 100", (0, 36)); ("0000 0000 0010 011", (0, 37)); ("0000 0000 0010 010", (0, 38)); ("0000 0000 0010 001", (0, 39));
("0000 0000 0010 000", (0, 40)); ("0000 0000 0011 111", (1, 8)); ("0000 0000 0011 110", (1, 9)); ("0000 0000 0011 101", (1, 10));
("0000 0000 0011 100", (1, 11)); ("0000 0000 0011 011", (1, 12)); ("0000 0000 0011 010", (1, 13)); ("0000 0000 0011 001", (1, 14));
("0000 0000 0001 0011", (1, 15)); ("0000 0000 0001 0010", (1, 16)); ("0000 0000 0001 0001", (1, 17)); ("0000 0000 0001 0000", (1, 18));
("0000 0000 0001 0100", (6, 3)); ("0000 0000 0001 1010", (11, 2)); ("0000 0000 0001 1001", (12, 2)); ("0000 0000 0001 1000", (13, 2));
("0000 0000 0001 0111", (14, 2)); ("0000 0000 0001 0110", (15, 2)); ("0000 0000 0001 0101", (16, 2)); ("0000 0000 0001 1111", (27, 1));
("0000 0000 0001 1110", (28, 1)); ("0000 0000 0001 1101", (29, 1)); ("0000 0000 0001 1100", (30, 1)); ("0000 0000 0001 1011", (31, 1)) ]
let shared = ("0000 01", Escape) :: List.map (fun (code, (run, level)) -> (code, Coeff (run, level))) coefficients
let dct_first = ("1", Coeff (0, 1)) :: shared
let dct_next = ("10", Eob) :: ("11", Coeff (0, 1)) :: shared