pseudocode | type --------------------------------------------------------------|----- ExamplePseudoCode( ) { | value | ur } |
a++, a-- !a, -a a ^ b a * b, a / b a + b, a - b a << b, a >> b a < b, a <= b, a > b, a >= b a == b, a != b a & b a | b a && b a || b a ? b : c a = b, a += b, a -= b, a *= b
+---+---+---+---+---+---+---+---+ | 0 | 0 | | 0 | 0 | 0 | | 0 | +---+---+---+---+---+---+---+---+ | 0 | 0 | | 0 | 0 | 0 | | 0 | +---+---+---+---+---+---+---+---+ | | | | | | | | | +---+---+---+---+---+---+---+---+ | 0 | 0 | | a | b | c | | c | +---+---+---+---+---+---+---+---+ | 0 | a | | d | e | f | | f | +---+---+---+---+---+---+---+---+ | 0 | d | | g | h | i | | i | +---+---+---+---+---+---+---+---+
+---+---+---+---+ | | | T | | +---+---+---+---+ | |tl | t |tr | +---+---+---+---+ | L | l | X | | +---+---+---+---+
median(l, t, l + t - tl)
median(left16s, top16s, left16s + top16s - diag16s)
left16s = l >= 32768 ? ( l - 65536 ) : l top16s = t >= 32768 ? ( t - 65536 ) : t diag16s = tl >= 32768 ? ( tl - 65536 ) : tl
Q_j[k] = quant_tables[i][j][k&255]
context = Q_0[l - tl] + Q_1[tl - t] + Q_2[t - tr] + Q_3[L - l] + Q_4[T - t]
Cb = b - g Cr = r - g Y = g + (Cb + Cr) >> 2
g = Y - (Cb + Cr) >> 2 r = Cr + g b = Cb + g
+------------------------+------------------------+ | Pixel(1,1) | Pixel(2,1) | | Y(1,1) Cb(1,1) Cr(1,1) | Y(2,1) Cb(2,1) Cr(2,1) | +------------------------+------------------------+ | Pixel(1,2) | Pixel(2,2) | | Y(1,2) Cb(1,2) Cr(1,2) | Y(2,2) Cb(2,2) Cr(2,2) | +------------------------+------------------------+
Cb = g - b Cr = r - b Y = b + (Cb + Cr) >> 2
b = Y - (Cb + Cr) >> 2 r = Cr + b g = Cb + b
coder_input = ((sample_difference + 2 ^ (bits - 1)) & (2 ^ bits - 1)) - 2 ^ (bits - 1)
R_0 = 65280
L_0 = 2 ^ 8 * B_0 + B_1
j_0 = 2
r_i = floor( ( R_i * S_(i, C_i) ) / 2 ^ 8 )
b_i = 0 <==> L_i < R_i - r_i ==> S_(i+1,C_i) = zero_state_(S_(i, C_i)) AND l_i = L_i AND t_i = R_i - r_i b_i = 1 <==> L_i >= R_i - r_i ==> S_(i+1,C_i) = one_state_(S_(i, C_i)) AND l_i = L_i - R_i + r_i AND t_i = r_i
C_i != k ==> S_(i + 1, k) = S_(i, k)
t_i < 2 ^ 8 ==> R_(i + 1) = 2 ^ 8 * t_i AND L_(i + 1) = 2 ^ 8 * l_i + B_(j_i) AND j_(i + 1) = j_i + 1 t_i >= 2 ^ 8 ==> R_(i + 1) = t_i AND L_(i + 1) = l_i AND j_(i + 1) = j_i
range = 0xFF00; end = 0; low = get_bits(16); if (low >= range) { low = range; end = 1; }
refill() { if (range < 256) { range = range * 256; low = low * 256; if (!end) { c.low += get_bits(8); if (remaining_bits_in_bitstream( NumBytes ) == 0) { end = 1; } } } }
get_rac(state) { rangeoff = (range * state) / 256; range -= rangeoff; if (low < range) { state = zero_state[state]; refill(); return 0; } else { low -= range; state = one_state[state]; range = rangeoff; refill(); return 1; } }
int get_symbol(RangeCoder *c, uint8_t *state, int is_signed) { if (get_rac(c, state + 0) { return 0; } int e = 0; while (get_rac(c, state + 1 + min(e, 9)) { //1..10 e++; } int a = 1; for (int i = e - 1; i >= 0; i--) { a = a * 2 + get_rac(c, state + 22 + min(i, 9)); // 22..31 } if (!is_signed) { return a; } if (get_rac(c, state + 11 + min(e, 10))) { //11..21 return -a; } else { return a; } }
one_state_i = default_state_transition_i + state_transition_delta_i
zero_state_i = 256 - one_state_(256-i)
0, 0, 0, 0, 0, 0, 0, 0, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 94, 95, 96, 97, 98, 99,100,101,102,103, 104,105,106,107,108,109,110,111,112,113,114,114,115,116,117,118, 119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,133, 134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149, 150,151,152,152,153,154,155,156,157,158,159,160,161,162,163,164, 165,166,167,168,169,170,171,171,172,173,174,175,176,177,178,179, 180,181,182,183,184,185,186,187,188,189,190,190,191,192,194,194, 195,196,197,198,199,200,201,202,202,204,205,206,207,208,209,209, 210,211,212,213,215,215,216,217,218,219,220,220,222,223,224,225, 226,227,227,229,229,230,231,232,234,234,235,236,237,238,239,240, 241,242,243,244,245,246,247,248,248, 0, 0, 0, 0, 0, 0, 0,
0, 10, 10, 10, 10, 16, 16, 16, 28, 16, 16, 29, 42, 49, 20, 49, 59, 25, 26, 26, 27, 31, 33, 33, 33, 34, 34, 37, 67, 38, 39, 39, 40, 40, 41, 79, 43, 44, 45, 45, 48, 48, 64, 50, 51, 52, 88, 52, 53, 74, 55, 57, 58, 58, 74, 60,101, 61, 62, 84, 66, 66, 68, 69, 87, 82, 71, 97, 73, 73, 82, 75,111, 77, 94, 78, 87, 81, 83, 97, 85, 83, 94, 86, 99, 89, 90, 99,111, 92, 93,134, 95, 98,105, 98, 105,110,102,108,102,118,103,106,106,113,109,112,114,112,116,125, 115,116,117,117,126,119,125,121,121,123,145,124,126,131,127,129, 165,130,132,138,133,135,145,136,137,139,146,141,143,142,144,148, 147,155,151,149,151,150,152,157,153,154,156,168,158,162,161,160, 172,163,169,164,166,184,167,170,177,174,171,173,182,176,180,178, 175,189,179,181,186,183,192,185,200,187,191,188,190,197,193,196, 197,194,195,196,198,202,199,201,210,203,207,204,205,206,208,214, 209,211,221,212,213,215,224,216,217,218,219,220,222,228,223,225, 226,224,227,229,240,230,231,232,233,234,235,236,238,239,237,242, 241,243,242,244,245,246,247,248,249,250,251,252,252,253,254,255,
int get_ur_golomb(k) { for (prefix = 0; prefix < 12; prefix++) { if (get_bits(1)) { return get_bits(k) + (prefix << k); } } return get_bits(bits) + 11; }
int get_sr_golomb(k) { v = get_ur_golomb(k); if (v & 1) return - (v >> 1) - 1; else return (v >> 1); }
bits | value |
---|---|
1 | 0 |
01 | 1 |
... | ... |
0000 0000 01 | 9 |
0000 0000 001 | 10 |
0000 0000 0001 | 11 |
0000 0000 0000 | ESC |
non-ESC | the k least significant bits MSB first |
ESC | the value - 11, in MSB first order |
k | bits | value |
---|---|---|
0 | 1 | 0 |
0 | 001 | 2 |
2 | 1 00 | 0 |
2 | 1 10 | 2 |
2 | 01 01 | 5 |
any | 000000000000 10000000 | 139 |
log2_run[41] = { 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 9,10,11,12,13,14,15, 16,17,18,19,20,21,22,23, 24, }; if (run_count == 0 && run_mode == 1) { if (get_bits(1)) { run_count = 1 << log2_run[run_index]; if (x + run_count <= w) { run_index++; } } else { if (log2_run[run_index]) { run_count = get_bits(log2_run[run_index]); } else { run_count = 0; } if (run_index) { run_index--; } run_mode = 2; } }
sign_extend(input_number, input_bits) { negative_bias = 1 << (input_bits - 1); bits_mask = negative_bias - 1; output_number = input_number & bits_mask; // Remove negative bit is_negative = input_number & negative_bias; // Test negative bit if (is_negative) output_number -= negative_bias; return output_number }
get_vlc_symbol(state) { i = state->count; k = 0; while (i < state->error_sum) { k++; i += i; } v = get_sr_golomb(k); if (2 * state->drift < -state->count) { v = -1 - v; } ret = sign_extend(v + state->bias, bits); state->error_sum += abs(v); state->drift += v; if (state->count == 128) { state->count >>= 1; state->drift >>= 1; state->error_sum >>= 1; } state->count++; if (state->drift <= -state->count) { state->bias = max(state->bias - 1, -128); state->drift = max(state->drift + state->count, -state->count + 1); } else if (state->drift > 0) { state->bias = min(state->bias + 1, 127); state->drift = min(state->drift - state->count, 0); } return ret; }
diff = get_vlc_symbol(context_state); if (diff >= 0) { diff++; }
drift = 0; error_sum = 4; bias = 0; count = 1;
symbol | definition |
---|---|
u(n) | Unsigned, big-endian integer symbol using n bits |
br | Boolean (1-bit) symbol that is range coded with the method described in Section 3.8.1.1 |
ur | Unsigned scalar symbol that is range coded with the method described in Section 3.8.1.2 |
sr | Signed scalar symbol that is range coded with the method described in Section 3.8.1.2 |
sd | Sample Difference symbol that is coded with the method described in Section 3.8 |
pseudocode | type --------------------------------------------------------------|----- QuantizationTableSet( i ) { | scale = 1 | for (j = 0; j < MAX_CONTEXT_INPUTS; j++) { | QuantizationTable( i, j, scale ) | scale *= 2 * len_count[ i ][ j ] - 1 | } | context_count[ i ] = ceil( scale / 2 ) | } |
pseudocode | type --------------------------------------------------------------|----- QuantizationTable(i, j, scale) { | v = 0 | for (k = 0; k < 128;) { | len - 1 | ur for (n = 0; n < len; n++) { | quant_tables[ i ][ j ][ k ] = scale * v | k++ | } | v++ | } | for (k = 1; k < 128; k++) { | quant_tables[ i ][ j ][ 256 - k ] = \ | -quant_tables[ i ][ j ][ k ] | } | quant_tables[ i ][ j ][ 128 ] = \ | -quant_tables[ i ][ j ][ 127 ] | len_count[ i ][ j ] = v | } |
pseudocode | type --------------------------------------------------------------|----- Parameters( ) { | version | ur if (version >= 3) { | micro_version | ur } | coder_type | ur if (coder_type > 1) { | for (i = 1; i < 256; i++) { | state_transition_delta[ i ] | sr } | } | colorspace_type | ur if (version >= 1) { | bits_per_raw_sample | ur } | chroma_planes | br log2_h_chroma_subsample | ur log2_v_chroma_subsample | ur extra_plane | br if (version >= 3) { | num_h_slices - 1 | ur num_v_slices - 1 | ur quant_table_set_count | ur } | for (i = 0; i < quant_table_set_count; i++) { | QuantizationTableSet( i ) | } | if (version >= 3) { | for (i = 0; i < quant_table_set_count; i++) { | states_coded | br if (states_coded) { | for (j = 0; j < context_count[ i ]; j++) { | for (k = 0; k < CONTEXT_SIZE; k++) { | initial_state_delta[ i ][ j ][ k ] | sr } | } | } | } | ec | ur intra | ur } | } |
value | version |
---|---|
0 | FFV1 version 0 |
1 | FFV1 version 1 |
2 | reserved* |
3 | FFV1 version 3 |
Other | reserved for future use |
value | micro_version |
---|---|
0...3 | reserved* |
4 | first stable variant |
Other | reserved for future use |
value | coder used |
---|---|
0 | Golomb Rice |
1 | Range coder with default state transition table |
2 | Range coder with custom state transition table |
Other | reserved for future use |
value | color space encoded | pixel transformation | extra Plane content | interleave method |
---|---|---|---|---|
0 | YCbCr | None | Transparency | Plane then Line |
1 | RGB | JPEG 2000 RCT | Transparency | Line then Plane |
Other | reserved for future use | reserved for future use | reserved for future use | reserved for future use |
value | presence |
---|---|
0 | chroma Planes are not present |
1 | chroma Planes are present |
value | bits for each Sample |
---|---|
0 | reserved* |
Other | the actual bits for each Sample |
value | presence |
---|---|
0 | extra Plane is not present |
1 | extra Plane is present |
value | initial states |
---|---|
0 | initial states are not present and are assumed to be all 128 |
1 | initial states are present |
pred = j ? initial_states[ i ][j - 1][ k ] : 128
initial_state[ i ][ j ][ k ] = ( pred + initial_state_delta[ i ][ j ][ k ] ) & 255
value | error detection/correction type |
---|---|
0 | 32-bit CRC in ConfigurationRecord |
1 | 32-bit CRC in Slice and ConfigurationRecord |
Other | reserved for future use |
value | relationship |
---|---|
0 | keyframe can be 0 or 1 (non keyframes or keyframes) |
1 | keyframe MUST be 1 (keyframes only) |
Other | reserved for future use |
pseudocode | type -----------------------------------------------------------|----- ConfigurationRecord( NumBytes ) { | ConfigurationRecordIsPresent = 1 | Parameters( ) | while (remaining_symbols_in_syntax(NumBytes - 4)) { | reserved_for_future_use | br/ur/sr } | configuration_record_crc_parity | u(32) } |
pseudocode | type --------------------------------------------------------------|----- Frame( NumBytes ) { | keyframe | br if (keyframe && !ConfigurationRecordIsPresent { | Parameters( ) | } | while (remaining_bits_in_bitstream( NumBytes )) { | Slice( ) | } | } |
+-----------------------------------------------------------------+ | first Slice header | +-----------------------------------------------------------------+ | first Slice content | +-----------------------------------------------------------------+ | first Slice footer | +-----------------------------------------------------------------+ | --------------------------------------------------------------- | +-----------------------------------------------------------------+ | second Slice header | +-----------------------------------------------------------------+ | second Slice content | +-----------------------------------------------------------------+ | second Slice footer | +-----------------------------------------------------------------+ | --------------------------------------------------------------- | +-----------------------------------------------------------------+ | ... | +-----------------------------------------------------------------+ | --------------------------------------------------------------- | +-----------------------------------------------------------------+ | last Slice header | +-----------------------------------------------------------------+ | last Slice content | +-----------------------------------------------------------------+ | last Slice footer | +-----------------------------------------------------------------+
pseudocode | type --------------------------------------------------------------|----- Slice( ) { | if (version >= 3) { | SliceHeader( ) | } | SliceContent( ) | if (coder_type == 0) { | while (!byte_aligned()) { | padding | u(1) } | } | if (version <= 1) { | while (remaining_bits_in_bitstream( NumBytes ) != 0) {| reserved | u(1) } | } | if (version >= 3) { | SliceFooter( ) | } | } |
pseudocode | type --------------------------------------------------------------|----- SliceHeader( ) { | slice_x | ur slice_y | ur slice_width - 1 | ur slice_height - 1 | ur for (i = 0; i < quant_table_set_index_count; i++) { | quant_table_set_index[ i ] | ur } | picture_structure | ur sar_num | ur sar_den | ur } |
1 + ( ( chroma_planes || version <= 3 ) ? 1 : 0 ) + ( extra_plane ? 1 : 0 )
value | picture structure used |
---|---|
0 | unknown |
1 | top field first |
2 | bottom field first |
3 | progressive |
Other | reserved for future use |
pseudocode | type --------------------------------------------------------------|----- SliceContent( ) { | if (colorspace_type == 0) { | for (p = 0; p < primary_color_count; p++) { | for (y = 0; y < plane_pixel_height[ p ]; y++) { | Line( p, y ) | } | } | } else if (colorspace_type == 1) { | for (y = 0; y < slice_pixel_height; y++) { | for (p = 0; p < primary_color_count; p++) { | Line( p, y ) | } | } | } | } |
1 + ( chroma_planes ? 2 : 0 ) + ( extra_plane ? 1 : 0 )
chroma_planes == 1 && (p == 1 || p == 2) ? ceil(slice_pixel_height / (1 << log2_v_chroma_subsample)) : slice_pixel_height
floor( ( slice_y + slice_height ) * slice_pixel_height / num_v_slices ) - slice_pixel_y.
floor( slice_y * frame_pixel_height / num_v_slices )
pseudocode | type --------------------------------------------------------------|----- Line( p, y ) { | if (colorspace_type == 0) { | for (x = 0; x < plane_pixel_width[ p ]; x++) { | sample_difference[ p ][ y ][ x ] | sd } | } else if (colorspace_type == 1) { | for (x = 0; x < slice_pixel_width; x++) { | sample_difference[ p ][ y ][ x ] | sd } | } | } |
chroma_planes == 1 && (p == 1 || p == 2) ? ceil( slice_pixel_width / (1 << log2_h_chroma_subsample) ) : slice_pixel_width.
floor( ( slice_x + slice_width ) * slice_pixel_width / num_h_slices ) - slice_pixel_x
floor( slice_x * frame_pixel_width / num_h_slices )
pseudocode | type --------------------------------------------------------------|----- SliceFooter( ) { | slice_size | u(24) if (ec) { | error_status | u(8) slice_crc_parity | u(32) } | } |
value | error status |
---|---|
0 | no error |
1 | Slice contains a correctable error |
2 | Slice contains an uncorrectable error |
Other | reserved for future use |