draft-ietf-cellar-ffv1-v4-06.txt   draft-ietf-cellar-ffv1-v4-07.txt 
cellar M. Niedermayer cellar M. Niedermayer
Internet-Draft D. Rice Internet-Draft D. Rice
Intended status: Standards Track J. Martinez Intended status: Standards Track J. Martinez
Expires: March 19, 2020 September 16, 2019 Expires: 12 April 2020 10 October 2019
FFV1 Video Coding Format Version 4 FFV1 Video Coding Format Version 4
draft-ietf-cellar-ffv1-v4-06 draft-ietf-cellar-ffv1-v4-07
Abstract Abstract
This document defines FFV1, a lossless intra-frame video encoding This document defines FFV1, a lossless intra-frame video encoding
format. FFV1 is designed to efficiently compress video data in a format. FFV1 is designed to efficiently compress video data in a
variety of pixel formats. Compared to uncompressed video, FFV1 variety of pixel formats. Compared to uncompressed video, FFV1
offers storage compression, frame fixity, and self-description, which offers storage compression, frame fixity, and self-description, which
makes FFV1 useful as a preservation or intermediate video format. makes FFV1 useful as a preservation or intermediate video format.
Status of This Memo Status of This Memo
skipping to change at page 1, line 34 skipping to change at page 1, line 34
Internet-Drafts are working documents of the Internet Engineering Internet-Drafts are working documents of the Internet Engineering
Task Force (IETF). Note that other groups may also distribute Task Force (IETF). Note that other groups may also distribute
working documents as Internet-Drafts. The list of current Internet- working documents as Internet-Drafts. The list of current Internet-
Drafts is at https://datatracker.ietf.org/drafts/current/. Drafts is at https://datatracker.ietf.org/drafts/current/.
Internet-Drafts are draft documents valid for a maximum of six months Internet-Drafts are draft documents valid for a maximum of six months
and may be updated, replaced, or obsoleted by other documents at any and may be updated, replaced, or obsoleted by other documents at any
time. It is inappropriate to use Internet-Drafts as reference time. It is inappropriate to use Internet-Drafts as reference
material or to cite them other than as "work in progress." material or to cite them other than as "work in progress."
This Internet-Draft will expire on 19 March 2020. This Internet-Draft will expire on 12 April 2020.
Copyright Notice Copyright Notice
Copyright (c) 2019 IETF Trust and the persons identified as the Copyright (c) 2019 IETF Trust and the persons identified as the
document authors. All rights reserved. document authors. All rights reserved.
This document is subject to BCP 78 and the IETF Trust's Legal This document is subject to BCP 78 and the IETF Trust's Legal
Provisions Relating to IETF Documents (https://trustee.ietf.org/ Provisions Relating to IETF Documents (https://trustee.ietf.org/
license-info) in effect on the date of publication of this document. license-info) in effect on the date of publication of this document.
Please review these documents carefully, as they describe your rights Please review these documents carefully, as they describe your rights
skipping to change at page 2, line 32 skipping to change at page 2, line 32
3.2. Samples . . . . . . . . . . . . . . . . . . . . . . . . . 10 3.2. Samples . . . . . . . . . . . . . . . . . . . . . . . . . 10
3.3. Median Predictor . . . . . . . . . . . . . . . . . . . . 10 3.3. Median Predictor . . . . . . . . . . . . . . . . . . . . 10
3.4. Context . . . . . . . . . . . . . . . . . . . . . . . . . 11 3.4. Context . . . . . . . . . . . . . . . . . . . . . . . . . 11
3.5. Quantization Table Sets . . . . . . . . . . . . . . . . . 11 3.5. Quantization Table Sets . . . . . . . . . . . . . . . . . 11
3.6. Quantization Table Set Indexes . . . . . . . . . . . . . 12 3.6. Quantization Table Set Indexes . . . . . . . . . . . . . 12
3.7. Color spaces . . . . . . . . . . . . . . . . . . . . . . 12 3.7. Color spaces . . . . . . . . . . . . . . . . . . . . . . 12
3.7.1. YCbCr . . . . . . . . . . . . . . . . . . . . . . . . 12 3.7.1. YCbCr . . . . . . . . . . . . . . . . . . . . . . . . 12
3.7.2. RGB . . . . . . . . . . . . . . . . . . . . . . . . . 13 3.7.2. RGB . . . . . . . . . . . . . . . . . . . . . . . . . 13
3.8. Coding of the Sample Difference . . . . . . . . . . . . . 15 3.8. Coding of the Sample Difference . . . . . . . . . . . . . 15
3.8.1. Range Coding Mode . . . . . . . . . . . . . . . . . . 15 3.8.1. Range Coding Mode . . . . . . . . . . . . . . . . . . 15
3.8.2. Golomb Rice Mode . . . . . . . . . . . . . . . . . . 19 3.8.2. Golomb Rice Mode . . . . . . . . . . . . . . . . . . 20
4. Bitstream . . . . . . . . . . . . . . . . . . . . . . . . . . 22 4. Bitstream . . . . . . . . . . . . . . . . . . . . . . . . . . 25
4.1. Parameters . . . . . . . . . . . . . . . . . . . . . . . 23 4.1. Parameters . . . . . . . . . . . . . . . . . . . . . . . 26
4.1.1. version . . . . . . . . . . . . . . . . . . . . . . . 24 4.1.1. version . . . . . . . . . . . . . . . . . . . . . . . 28
4.1.2. micro_version . . . . . . . . . . . . . . . . . . . . 24 4.1.2. micro_version . . . . . . . . . . . . . . . . . . . . 28
4.1.3. coder_type . . . . . . . . . . . . . . . . . . . . . 25 4.1.3. coder_type . . . . . . . . . . . . . . . . . . . . . 29
4.1.4. state_transition_delta . . . . . . . . . . . . . . . 26 4.1.4. state_transition_delta . . . . . . . . . . . . . . . 30
4.1.5. colorspace_type . . . . . . . . . . . . . . . . . . . 26 4.1.5. colorspace_type . . . . . . . . . . . . . . . . . . . 30
4.1.6. chroma_planes . . . . . . . . . . . . . . . . . . . . 27 4.1.6. chroma_planes . . . . . . . . . . . . . . . . . . . . 31
4.1.7. bits_per_raw_sample . . . . . . . . . . . . . . . . . 27 4.1.7. bits_per_raw_sample . . . . . . . . . . . . . . . . . 31
4.1.8. log2_h_chroma_subsample . . . . . . . . . . . . . . . 27 4.1.8. log2_h_chroma_subsample . . . . . . . . . . . . . . . 31
4.1.9. log2_v_chroma_subsample . . . . . . . . . . . . . . . 28 4.1.9. log2_v_chroma_subsample . . . . . . . . . . . . . . . 32
4.1.10. extra_plane . . . . . . . . . . . . . . . . . . . . . 28 4.1.10. extra_plane . . . . . . . . . . . . . . . . . . . . . 32
4.1.11. num_h_slices . . . . . . . . . . . . . . . . . . . . 28 4.1.11. num_h_slices . . . . . . . . . . . . . . . . . . . . 32
4.1.12. num_v_slices . . . . . . . . . . . . . . . . . . . . 28 4.1.12. num_v_slices . . . . . . . . . . . . . . . . . . . . 32
4.1.13. quant_table_set_count . . . . . . . . . . . . . . . . 28 4.1.13. quant_table_set_count . . . . . . . . . . . . . . . . 32
4.1.14. states_coded . . . . . . . . . . . . . . . . . . . . 28 4.1.14. states_coded . . . . . . . . . . . . . . . . . . . . 32
4.1.15. initial_state_delta . . . . . . . . . . . . . . . . . 29 4.1.15. initial_state_delta . . . . . . . . . . . . . . . . . 33
4.1.16. ec . . . . . . . . . . . . . . . . . . . . . . . . . 29 4.1.16. ec . . . . . . . . . . . . . . . . . . . . . . . . . 33
4.1.17. intra . . . . . . . . . . . . . . . . . . . . . . . . 29 4.1.17. intra . . . . . . . . . . . . . . . . . . . . . . . . 33
4.2. Configuration Record . . . . . . . . . . . . . . . . . . 30 4.2. Configuration Record . . . . . . . . . . . . . . . . . . 34
4.2.1. reserved_for_future_use . . . . . . . . . . . . . . . 30 4.2.1. reserved_for_future_use . . . . . . . . . . . . . . . 34
4.2.2. configuration_record_crc_parity . . . . . . . . . . . 30 4.2.2. configuration_record_crc_parity . . . . . . . . . . . 34
4.2.3. Mapping FFV1 into Containers . . . . . . . . . . . . 31 4.2.3. Mapping FFV1 into Containers . . . . . . . . . . . . 35
4.3. Frame . . . . . . . . . . . . . . . . . . . . . . . . . . 32 4.3. Frame . . . . . . . . . . . . . . . . . . . . . . . . . . 36
4.4. Slice . . . . . . . . . . . . . . . . . . . . . . . . . . 33 4.4. Slice . . . . . . . . . . . . . . . . . . . . . . . . . . 37
4.5. Slice Header . . . . . . . . . . . . . . . . . . . . . . 33 4.5. Slice Header . . . . . . . . . . . . . . . . . . . . . . 38
4.5.1. slice_x . . . . . . . . . . . . . . . . . . . . . . . 33 4.5.1. slice_x . . . . . . . . . . . . . . . . . . . . . . . 39
4.5.2. slice_y . . . . . . . . . . . . . . . . . . . . . . . 34 4.5.2. slice_y . . . . . . . . . . . . . . . . . . . . . . . 39
4.5.3. slice_width . . . . . . . . . . . . . . . . . . . . . 34 4.5.3. slice_width . . . . . . . . . . . . . . . . . . . . . 39
4.5.4. slice_height . . . . . . . . . . . . . . . . . . . . 34 4.5.4. slice_height . . . . . . . . . . . . . . . . . . . . 39
4.5.5. quant_table_set_index_count . . . . . . . . . . . . . 34 4.5.5. quant_table_set_index_count . . . . . . . . . . . . . 40
4.5.6. quant_table_set_index . . . . . . . . . . . . . . . . 34 4.5.6. quant_table_set_index . . . . . . . . . . . . . . . . 40
4.5.7. picture_structure . . . . . . . . . . . . . . . . . . 34 4.5.7. picture_structure . . . . . . . . . . . . . . . . . . 40
4.5.8. sar_num . . . . . . . . . . . . . . . . . . . . . . . 35 4.5.8. sar_num . . . . . . . . . . . . . . . . . . . . . . . 40
4.5.9. sar_den . . . . . . . . . . . . . . . . . . . . . . . 35 4.5.9. sar_den . . . . . . . . . . . . . . . . . . . . . . . 41
4.5.10. reset_contexts . . . . . . . . . . . . . . . . . . . 35 4.5.10. reset_contexts . . . . . . . . . . . . . . . . . . . 41
4.5.11. slice_coding_mode . . . . . . . . . . . . . . . . . . 36 4.5.11. slice_coding_mode . . . . . . . . . . . . . . . . . . 41
4.6. Slice Content . . . . . . . . . . . . . . . . . . . . . . 36 4.6. Slice Content . . . . . . . . . . . . . . . . . . . . . . 41
4.6.1. primary_color_count . . . . . . . . . . . . . . . . . 36 4.6.1. primary_color_count . . . . . . . . . . . . . . . . . 42
4.6.2. plane_pixel_height . . . . . . . . . . . . . . . . . 36 4.6.2. plane_pixel_height . . . . . . . . . . . . . . . . . 42
4.6.3. slice_pixel_height . . . . . . . . . . . . . . . . . 36 4.6.3. slice_pixel_height . . . . . . . . . . . . . . . . . 42
4.6.4. slice_pixel_y . . . . . . . . . . . . . . . . . . . . 37 4.6.4. slice_pixel_y . . . . . . . . . . . . . . . . . . . . 42
4.7. Line . . . . . . . . . . . . . . . . . . . . . . . . . . 37 4.7. Line . . . . . . . . . . . . . . . . . . . . . . . . . . 43
4.7.1. plane_pixel_width . . . . . . . . . . . . . . . . . . 37 4.7.1. plane_pixel_width . . . . . . . . . . . . . . . . . . 43
4.7.2. slice_pixel_width . . . . . . . . . . . . . . . . . . 37 4.7.2. slice_pixel_width . . . . . . . . . . . . . . . . . . 43
4.7.3. slice_pixel_x . . . . . . . . . . . . . . . . . . . . 37 4.7.3. slice_pixel_x . . . . . . . . . . . . . . . . . . . . 43
4.7.4. sample_difference . . . . . . . . . . . . . . . . . . 37 4.7.4. sample_difference . . . . . . . . . . . . . . . . . . 44
4.8. Slice Footer . . . . . . . . . . . . . . . . . . . . . . 38 4.8. Slice Footer . . . . . . . . . . . . . . . . . . . . . . 44
4.8.1. slice_size . . . . . . . . . . . . . . . . . . . . . 38 4.8.1. slice_size . . . . . . . . . . . . . . . . . . . . . 44
4.8.2. error_status . . . . . . . . . . . . . . . . . . . . 38 4.8.2. error_status . . . . . . . . . . . . . . . . . . . . 44
4.8.3. slice_crc_parity . . . . . . . . . . . . . . . . . . 38 4.8.3. slice_crc_parity . . . . . . . . . . . . . . . . . . 45
4.9. Quantization Table Set . . . . . . . . . . . . . . . . . 39 4.9. Quantization Table Set . . . . . . . . . . . . . . . . . 45
4.9.1. quant_tables . . . . . . . . . . . . . . . . . . . . 39 4.9.1. quant_tables . . . . . . . . . . . . . . . . . . . . 46
4.9.2. context_count . . . . . . . . . . . . . . . . . . . . 39 4.9.2. context_count . . . . . . . . . . . . . . . . . . . . 46
5. Restrictions . . . . . . . . . . . . . . . . . . . . . . . . 39 5. Restrictions . . . . . . . . . . . . . . . . . . . . . . . . 47
6. Security Considerations . . . . . . . . . . . . . . . . . . . 40 6. Security Considerations . . . . . . . . . . . . . . . . . . . 47
7. Media Type Definition . . . . . . . . . . . . . . . . . . . . 41 7. Media Type Definition . . . . . . . . . . . . . . . . . . . . 48
8. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 42 8. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 50
9. Appendixes . . . . . . . . . . . . . . . . . . . . . . . . . 42 9. Appendixes . . . . . . . . . . . . . . . . . . . . . . . . . 50
9.1. Decoder implementation suggestions . . . . . . . . . . . 42 9.1. Decoder implementation suggestions . . . . . . . . . . . 50
9.1.1. Multi-threading Support and Independence of 9.1.1. Multi-threading Support and Independence of
Slices . . . . . . . . . . . . . . . . . . . . . . . 43 Slices . . . . . . . . . . . . . . . . . . . . . . . 50
10. Changelog . . . . . . . . . . . . . . . . . . . . . . . . . . 43 10. Changelog . . . . . . . . . . . . . . . . . . . . . . . . . . 50
11. Normative References . . . . . . . . . . . . . . . . . . . . 43 11. Normative References . . . . . . . . . . . . . . . . . . . . 50
12. Informative References . . . . . . . . . . . . . . . . . . . 44 12. Informative References . . . . . . . . . . . . . . . . . . . 51
Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . 45 Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . 52
1. Introduction 1. Introduction
This document describes FFV1, a lossless video encoding format. The This document describes FFV1, a lossless video encoding format. The
design of FFV1 considers the storage of image characteristics, data design of FFV1 considers the storage of image characteristics, data
fixity, and the optimized use of encoding time and storage fixity, and the optimized use of encoding time and storage
requirements. FFV1 is designed to support a wide range of lossless requirements. FFV1 is designed to support a wide range of lossless
video applications such as long-term audiovisual preservation, video applications such as long-term audiovisual preservation,
scientific imaging, screen recording, and other video encoding scientific imaging, screen recording, and other video encoding
scenarios that seek to avoid the generational loss of lossy video scenarios that seek to avoid the generational loss of lossy video
skipping to change at page 17, line 36 skipping to change at page 18, line 5
255 contexts per 8-bit symbol that is not only a waste of memory but 255 contexts per 8-bit symbol that is not only a waste of memory but
also requires more past data to reach a reasonably good estimate of also requires more past data to reach a reasonably good estimate of
the probabilities. Alternatively assuming a Laplacian distribution the probabilities. Alternatively assuming a Laplacian distribution
and only dealing with its variance and mean (as in Huffman coding) and only dealing with its variance and mean (as in Huffman coding)
would also be possible, however, for maximum flexibility and would also be possible, however, for maximum flexibility and
simplicity, the chosen method uses a single symbol to encode if a simplicity, the chosen method uses a single symbol to encode if a
number is 0, and if not, encodes the number using its exponent, number is 0, and if not, encodes the number using its exponent,
mantissa and sign. The exact contexts used are best described by the mantissa and sign. The exact contexts used are best described by the
following code, followed by some comments. following code, followed by some comments.
pseudo-code | type --------------------------------------------------------------|----- void put_symbol(RangeCoder *c, uint8_t *state, int v, int \ | is_signed) { | int i; | put_rac(c, state+0, !v); | if (v) { | int a= abs(v); | int e= log2(a); | | for (i = 0; i < e; i++) { | put_rac(c, state+1+min(i,9), 1); //1..10 | } | | put_rac(c, state+1+min(i,9), 0); | for (i = e-1; i >= 0; i--) { | put_rac(c, state+22+min(i,9), (a>>i)&1); //22..31 | } | | if (is_signed) { | put_rac(c, state+11 + min(e, 10), v < 0); //11..21| } | } | } | pseudo-code | type
--------------------------------------------------------------|-----
void put_symbol(RangeCoder *c, uint8_t *state, int v, int \ |
is_signed) { |
int i; |
put_rac(c, state+0, !v); |
if (v) { |
int a= abs(v); |
int e= log2(a); |
|
for (i = 0; i < e; i++) { |
put_rac(c, state+1+min(i,9), 1); //1..10 |
} |
|
put_rac(c, state+1+min(i,9), 0); |
for (i = e-1; i >= 0; i--) { |
put_rac(c, state+22+min(i,9), (a>>i)&1); //22..31 |
} |
|
if (is_signed) { |
put_rac(c, state+11 + min(e, 10), v < 0); //11..21|
} |
} |
} |
3.8.1.3. Initial Values for the Context Model 3.8.1.3. Initial Values for the Context Model
At keyframes all Range coder state variables are set to their initial At keyframes all Range coder state variables are set to their initial
state. state.
3.8.1.4. State Transition Table 3.8.1.4. State Transition Table
one_state_{i} = one_state_{i} =
default_state_transition_{i} + state_transition_delta_{i} default_state_transition_{i} + state_transition_delta_{i}
skipping to change at page 19, line 49 skipping to change at page 21, line 5
The end of the bitstream of the "Frame" is filled with 0-bits until The end of the bitstream of the "Frame" is filled with 0-bits until
that the bitstream contains a multiple of 8 bits. that the bitstream contains a multiple of 8 bits.
3.8.2.1. Signed Golomb Rice Codes 3.8.2.1. Signed Golomb Rice Codes
This coding mode uses Golomb Rice codes. The VLC is split into 2 This coding mode uses Golomb Rice codes. The VLC is split into 2
parts, the prefix stores the most significant bits and the suffix parts, the prefix stores the most significant bits and the suffix
stores the k least significant bits or stores the whole number in the stores the k least significant bits or stores the whole number in the
ESC case. ESC case.
pseudo-code | type --------------------------------------------------------------|----- 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); | } pseudo-code | type
--------------------------------------------------------------|-----
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); |
}
3.8.2.1.1. Prefix 3.8.2.1.1. Prefix
+----------------+-------+ +----------------+-------+
| bits | value | | bits | value |
+================+=======+ +================+=======+
| 1 | 0 | | 1 | 0 |
+----------------+-------+ +----------------+-------+
| 01 | 1 | | 01 | 1 |
+----------------+-------+ +----------------+-------+
skipping to change at page 21, line 40 skipping to change at page 23, line 5
3.8.2.2.1. Run Length Coding 3.8.2.2.1. Run Length Coding
The run value is encoded in 2 parts, the prefix part stores the more The run value is encoded in 2 parts, the prefix part stores the more
significant part of the run as well as adjusting the run_index that significant part of the run as well as adjusting the run_index that
determines the number of bits in the less significant part of the determines the number of bits in the less significant part of the
run. The 2nd part of the value stores the less significant part of run. The 2nd part of the value stores the less significant part of
the run as it is. The run_index is reset for each "Plane" and slice the run as it is. The run_index is reset for each "Plane" and slice
to 0. to 0.
pseudo-code | type --------------------------------------------------------------|----- 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; | } | } | pseudo-code | type
--------------------------------------------------------------|-----
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; |
} |
} |
The log2_run function is also used within [ISO.14495-1.1999]. The log2_run function is also used within [ISO.14495-1.1999].
3.8.2.2.2. Level Coding 3.8.2.2.2. Level Coding
Level coding is identical to the normal difference coding with the Level coding is identical to the normal difference coding with the
exception that the 0 value is removed as it cannot occur: exception that the 0 value is removed as it cannot occur:
diff = get_vlc_symbol(context_state); if (diff >= 0) { diff++; } diff = get_vlc_symbol(context_state);
if (diff >= 0) {
diff++;
}
Note, this is different from JPEG-LS, which doesn't use prediction in Note, this is different from JPEG-LS, which doesn't use prediction in
run mode and uses a different encoding and context model for the last run mode and uses a different encoding and context model for the last
difference On a small set of test "Samples" the use of prediction difference On a small set of test "Samples" the use of prediction
slightly improved the compression rate. slightly improved the compression rate.
3.8.2.3. Scalar Mode 3.8.2.3. Scalar Mode
Each difference is coded with the per context mean prediction removed Each difference is coded with the per context mean prediction removed
and a per context value for k. and a per context value for k.
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; } 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;
}
3.8.2.4. Initial Values for the VLC context state 3.8.2.4. Initial Values for the VLC context state
At keyframes all coder state variables are set to their initial At keyframes all coder state variables are set to their initial
state. state.
drift = 0; error_sum = 4; bias = 0; count = 1; drift = 0;
error_sum = 4;
bias = 0;
count = 1;
4. Bitstream 4. Bitstream
An FFV1 bitstream is composed of a series of 1 or more "Frames" and An FFV1 bitstream is composed of a series of 1 or more "Frames" and
(when required) a "Configuration Record". (when required) a "Configuration Record".
Within the following sub-sections, pseudo-code is used to explain the Within the following sub-sections, pseudo-code is used to explain the
structure of each FFV1 bitstream component, as described in the structure of each FFV1 bitstream component, as described in the
section on Pseudo-Code (#pseudocode). The following table lists section on Pseudo-Code (#pseudocode). The following table lists
symbols used to annotate that pseudo-code in order to define the symbols used to annotate that pseudo-code in order to define the
skipping to change at page 23, line 52 skipping to change at page 27, line 5
4.1. Parameters 4.1. Parameters
The "Parameters" section contains significant characteristics about The "Parameters" section contains significant characteristics about
the decoding configuration used for all instances of "Frame" (in FFV1 the decoding configuration used for all instances of "Frame" (in FFV1
version 0 and 1) or the whole FFV1 bitstream (other versions), version 0 and 1) or the whole FFV1 bitstream (other versions),
including the stream version, color configuration, and quantization including the stream version, color configuration, and quantization
tables. The pseudo-code below describes the contents of the tables. The pseudo-code below describes the contents of the
bitstream. bitstream.
pseudo-code | 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 } | } | pseudo-code | 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
} |
} |
CONTEXT_SIZE is 32.
4.1.1. version 4.1.1. version
"version" specifies the version of the FFV1 bitstream. "version" specifies the version of the FFV1 bitstream.
Each version is incompatible with other versions: decoders SHOULD Each version is incompatible with other versions: decoders SHOULD
reject a file due to an unknown version. reject a file due to an unknown version.
Decoders SHOULD reject a file with version <= 1 && Decoders SHOULD reject a file with version <= 1 &&
ConfigurationRecordIsPresent == 1. ConfigurationRecordIsPresent == 1.
skipping to change at page 28, line 42 skipping to change at page 32, line 42
4.1.12. num_v_slices 4.1.12. num_v_slices
"num_v_slices" indicates the number of vertical elements of the slice "num_v_slices" indicates the number of vertical elements of the slice
raster. raster.
Inferred to be 1 if not present. Inferred to be 1 if not present.
4.1.13. quant_table_set_count 4.1.13. quant_table_set_count
"quant_table_set_count" indicates the number of Quantization "quant_table_set_count" indicates the number of Quantization
Table Sets. Table Sets. "quant_table_set_count" MUST be less than or equal to 8.
Inferred to be 1 if not present. Inferred to be 1 if not present.
MUST NOT be 0. MUST NOT be 0.
4.1.14. states_coded 4.1.14. states_coded
"states_coded" indicates if the respective Quantization Table Set has "states_coded" indicates if the respective Quantization Table Set has
the initial states coded. the initial states coded.
skipping to change at page 30, line 27 skipping to change at page 34, line 27
Table 15 Table 15
4.2. Configuration Record 4.2. Configuration Record
In the case of a FFV1 bitstream with "version >= 3", a "Configuration In the case of a FFV1 bitstream with "version >= 3", a "Configuration
Record" is stored in the underlying "Container", at the track header Record" is stored in the underlying "Container", at the track header
level. It contains the "Parameters" used for all instances of level. It contains the "Parameters" used for all instances of
"Frame". The size of the "Configuration Record", "NumBytes", is "Frame". The size of the "Configuration Record", "NumBytes", is
supplied by the underlying "Container". supplied by the underlying "Container".
pseudo-code | 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) } | pseudo-code | 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)
} |
4.2.1. reserved_for_future_use 4.2.1. reserved_for_future_use
"reserved_for_future_use" has semantics that are reserved for future "reserved_for_future_use" has semantics that are reserved for future
use. use.
Encoders conforming to this version of this specification SHALL NOT Encoders conforming to this version of this specification SHALL NOT
write this value. write this value.
Decoders conforming to this version of this specification SHALL Decoders conforming to this version of this specification SHALL
skipping to change at page 32, line 17 skipping to change at page 36, line 25
4.3. Frame 4.3. Frame
A "Frame" is an encoded representation of a complete static image. A "Frame" is an encoded representation of a complete static image.
The whole "Frame" is provided by the underlaying container. The whole "Frame" is provided by the underlaying container.
A "Frame" consists of the keyframe field, "Parameters" (if version A "Frame" consists of the keyframe field, "Parameters" (if version
<=1), and a sequence of independent slices. The pseudo-code below <=1), and a sequence of independent slices. The pseudo-code below
describes the contents of a "Frame". describes the contents of a "Frame".
pseudo-code | type --------------------------------------------------------------|----- Frame( NumBytes ) { | keyframe | br if (keyframe && !ConfigurationRecordIsPresent { | Parameters( ) | } | while (remaining_bits_in_bitstream( NumBytes )) { | Slice( ) | } | } | pseudo-code | type
--------------------------------------------------------------|-----
Frame( NumBytes ) { |
keyframe | br
if (keyframe && !ConfigurationRecordIsPresent { |
Parameters( ) |
} |
while (remaining_bits_in_bitstream( NumBytes )) { |
Slice( ) |
} |
} |
Architecture overview of slices in a "Frame": Architecture overview of slices in a "Frame":
+-----------------------------------------------------------------+ +-----------------------------------------------------------------+
+=================================================================+ +=================================================================+
| first slice header | | first slice header |
+-----------------------------------------------------------------+ +-----------------------------------------------------------------+
| first slice content | | first slice content |
+-----------------------------------------------------------------+ +-----------------------------------------------------------------+
| first slice footer | | first slice footer |
skipping to change at page 33, line 17 skipping to change at page 38, line 5
A "Slice" is an independent spatial sub-section of a "Frame" that is A "Slice" is an independent spatial sub-section of a "Frame" that is
encoded separately from an other region of the same "Frame". The use encoded separately from an other region of the same "Frame". The use
of more than one "Slice" per "Frame" can be useful for taking of more than one "Slice" per "Frame" can be useful for taking
advantage of the opportunities of multithreaded encoding and advantage of the opportunities of multithreaded encoding and
decoding. decoding.
A "Slice" consists of a "Slice Header" (when relevant), a "Slice A "Slice" consists of a "Slice Header" (when relevant), a "Slice
Content", and a "Slice Footer" (when relevant). The pseudo-code Content", and a "Slice Footer" (when relevant). The pseudo-code
below describes the contents of a "Slice". below describes the contents of a "Slice".
pseudo-code | 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( ) | } | } | pseudo-code | 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( ) |
} |
} |
"padding" specifies a bit without any significance and used only for "padding" specifies a bit without any significance and used only for
byte alignment. MUST be 0. byte alignment. MUST be 0.
"reserved" specifies a bit without any significance in this revision "reserved" specifies a bit without any significance in this revision
of the specification and may have a significance in a later revision of the specification and may have a significance in a later revision
of this specification. of this specification.
Encoders SHOULD NOT fill these bits. Encoders SHOULD NOT fill these bits.
skipping to change at page 33, line 46 skipping to change at page 39, line 5
conforming to the revised specification could not do the difference conforming to the revised specification could not do the difference
between a revised bitstream and a buggy bitstream. between a revised bitstream and a buggy bitstream.
4.5. Slice Header 4.5. Slice Header
A "Slice Header" provides information about the decoding A "Slice Header" provides information about the decoding
configuration of the "Slice", such as its spatial position, size, and configuration of the "Slice", such as its spatial position, size, and
aspect ratio. The pseudo-code below describes the contents of the aspect ratio. The pseudo-code below describes the contents of the
"Slice Header". "Slice Header".
pseudo-code | 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 if (version >= 4) { | reset_contexts | br slice_coding_mode | ur } | } | pseudo-code | 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
if (version >= 4) { |
reset_contexts | br
slice_coding_mode | ur
} |
} |
4.5.1. slice_x 4.5.1. slice_x
"slice_x" indicates the x position on the slice raster formed by "slice_x" indicates the x position on the slice raster formed by
num_h_slices. num_h_slices.
Inferred to be 0 if not present. Inferred to be 0 if not present.
4.5.2. slice_y 4.5.2. slice_y
skipping to change at page 36, line 30 skipping to change at page 42, line 5
Table 18 Table 18
4.6. Slice Content 4.6. Slice Content
A "Slice Content" contains all "Line" elements part of the "Slice". A "Slice Content" contains all "Line" elements part of the "Slice".
Depending on the configuration, "Line" elements are ordered by Depending on the configuration, "Line" elements are ordered by
"Plane" then by row (YCbCr) or by row then by "Plane" (RGB). "Plane" then by row (YCbCr) or by row then by "Plane" (RGB).
pseudo-code | 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 ) | } | } | } | } | pseudo-code | 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 ) |
} |
} |
} |
} |
4.6.1. primary_color_count 4.6.1. primary_color_count
"primary_color_count" is defined as "1 + ( chroma_planes ? 2 : 0 ) + "primary_color_count" is defined as "1 + ( chroma_planes ? 2 : 0 ) +
( extra_plane ? 1 : 0 )". ( extra_plane ? 1 : 0 )".
4.6.2. plane_pixel_height 4.6.2. plane_pixel_height
"plane_pixel_height[ p ]" is the height in pixels of plane p of the "plane_pixel_height[ p ]" is the height in pixels of plane p of the
slice. slice.
skipping to change at page 37, line 20 skipping to change at page 43, line 11
"slice_pixel_y" is the slice vertical position in pixels. "slice_pixel_y" is the slice vertical position in pixels.
Its value is "floor( slice_y * frame_pixel_height / num_v_slices )". Its value is "floor( slice_y * frame_pixel_height / num_v_slices )".
4.7. Line 4.7. Line
A "Line" is a list of the sample differences (relative to the A "Line" is a list of the sample differences (relative to the
predictor) of primary color components. The pseudo-code below predictor) of primary color components. The pseudo-code below
describes the contents of the "Line". describes the contents of the "Line".
pseudo-code | type --------------------------------------------------------------|----- Line( p, y ) { | if (colorspace_type == 0) { | for (x = 0; x < plane_pixel_width[ p ]; x++) { | sample_difference[ p ][ y ][ x ] | } | } else if (colorspace_type == 1) { | for (x = 0; x < slice_pixel_width; x++) { | sample_difference[ p ][ y ][ x ] | } | } | } | pseudo-code | type
--------------------------------------------------------------|-----
Line( p, y ) { |
if (colorspace_type == 0) { |
for (x = 0; x < plane_pixel_width[ p ]; x++) { |
sample_difference[ p ][ y ][ x ] |
} |
} else if (colorspace_type == 1) { |
for (x = 0; x < slice_pixel_width; x++) { |
sample_difference[ p ][ y ][ x ] |
} |
} |
} |
4.7.1. plane_pixel_width 4.7.1. plane_pixel_width
"plane_pixel_width[ p ]" is the width in "Pixels" of "Plane" p of the "plane_pixel_width[ p ]" is the width in "Pixels" of "Plane" p of the
slice. slice.
"plane_pixel_width[ 0 ]" and "plane_pixel_width[ 1 + ( chroma_planes "plane_pixel_width[ 0 ]" and "plane_pixel_width[ 1 + ( chroma_planes
? 2 : 0 ) ]" value is "slice_pixel_width". ? 2 : 0 ) ]" value is "slice_pixel_width".
If "chroma_planes" is set to 1, "plane_pixel_width[ 1 ]" and If "chroma_planes" is set to 1, "plane_pixel_width[ 1 ]" and
skipping to change at page 38, line 13 skipping to change at page 44, line 20
described in the section on Samples (#samples). described in the section on Samples (#samples).
4.8. Slice Footer 4.8. Slice Footer
A "Slice Footer" provides information about slice size and A "Slice Footer" provides information about slice size and
(optionally) parity. The pseudo-code below describes the contents of (optionally) parity. The pseudo-code below describes the contents of
the "Slice Footer". the "Slice Footer".
Note: "Slice Footer" is always byte aligned. Note: "Slice Footer" is always byte aligned.
pseudo-code | type --------------------------------------------------------------|----- SliceFooter( ) { | slice_size | u(24) if (ec) { | error_status | u(8) slice_crc_parity | u(32) } | } | pseudo-code | type
--------------------------------------------------------------|-----
SliceFooter( ) { |
slice_size | u(24)
if (ec) { |
error_status | u(8)
slice_crc_parity | u(32)
} |
} |
4.8.1. slice_size 4.8.1. slice_size
"slice_size" indicates the size of the slice in bytes. "slice_size" indicates the size of the slice in bytes.
Note: this allows finding the start of slices before previous slices Note: this allows finding the start of slices before previous slices
have been fully decoded, and allows parallel decoding as well as have been fully decoded, and allows parallel decoding as well as
error resilience. error resilience.
4.8.2. error_status 4.8.2. error_status
skipping to change at page 39, line 21 skipping to change at page 46, line 4
need to be stored as it is identical to the first with flipped sign. need to be stored as it is identical to the first with flipped sign.
"scale" and "len_count[ i ][ j ]" are temporary values used for the "scale" and "len_count[ i ][ j ]" are temporary values used for the
computing of "context_count[ i ]" and are not used outside computing of "context_count[ i ]" and are not used outside
Quantization Table Set pseudo-code. Quantization Table Set pseudo-code.
Example: Example:
Table: 0 0 1 1 1 1 2 2 -2 -2 -2 -1 -1 -1 -1 0 Table: 0 0 1 1 1 1 2 2 -2 -2 -2 -1 -1 -1 -1 0
Stored values: 1, 3, 1 Stored values: 1, 3, 1
pseudo-code | type
pseudo-code | 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 ) | } | --------------------------------------------------------------|-----
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 ) |
} |
MAX_CONTEXT_INPUTS is 5. MAX_CONTEXT_INPUTS is 5.
pseudo-code | type --------------------------------------------------------------|----- QuantizationTable(i, j, scale) { | v = 0 | for (k = 0; k < 128;) { | len - 1 | ur for (a = 0; a < len; a++) { | 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 | } | pseudo-code | type
--------------------------------------------------------------|-----
QuantizationTable(i, j, scale) { |
v = 0 |
for (k = 0; k < 128;) { |
len - 1 | ur
for (a = 0; a < len; a++) { |
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 |
} |
4.9.1. quant_tables 4.9.1. quant_tables
"quant_tables[ i ][ j ][ k ]" indicates the quantification table "quant_tables[ i ][ j ][ k ]" indicates the quantification table
value of the Quantized Sample Difference "k" of the Quantization value of the Quantized Sample Difference "k" of the Quantization
Table "j" of the Set Quantization Table Set "i". Table "j" of the Set Quantization Table Set "i".
4.9.2. context_count 4.9.2. context_count
"context_count[ i ]" indicates the count of contexts for Quantization "context_count[ i ]" indicates the count of contexts for Quantization
Table Set "i". Table Set "i". "context_count[ i ]" MUST be less than or equal to
32768.
5. Restrictions 5. Restrictions
To ensure that fast multithreaded decoding is possible, starting with To ensure that fast multithreaded decoding is possible, starting with
version 3 and if "frame_pixel_width * frame_pixel_height" is more version 3 and if "frame_pixel_width * frame_pixel_height" is more
than 101376, "slice_width * slice_height" MUST be less or equal to than 101376, "slice_width * slice_height" MUST be less or equal to
"num_h_slices * num_v_slices / 4". Note: 101376 is the frame size in "num_h_slices * num_v_slices / 4". Note: 101376 is the frame size in
"Pixels" of a 352x288 frame also known as CIF ("Common Intermediate "Pixels" of a 352x288 frame also known as CIF ("Common Intermediate
Format") frame size format. Format") frame size format.
skipping to change at page 43, line 32 skipping to change at page 50, line 44
10. Changelog 10. Changelog
See https://github.com/FFmpeg/FFV1/commits/master See https://github.com/FFmpeg/FFV1/commits/master
(https://github.com/FFmpeg/FFV1/commits/master) (https://github.com/FFmpeg/FFV1/commits/master)
11. Normative References 11. Normative References
[I-D.ietf-cellar-ffv1] [I-D.ietf-cellar-ffv1]
Niedermayer, M., Rice, D., and J. Martinez, "FFV1 Video Niedermayer, M., Rice, D., and J. Martinez, "FFV1 Video
Coding Format Version 0, 1, and 3", Internet Draft, draft- Coding Format Version 0, 1, and 3", Internet-Draft, draft-
ietf-cellar-ffv1-08, August 13, 2019, ietf-cellar-ffv1-09, 6 September 2019,
<https://www.ietf.org/archive/id/draft-ietf-cellar- <https://tools.ietf.org/html/draft-ietf-cellar-ffv1-09>.
ffv1-08>.
[ISO.15444-1.2016] [ISO.15444-1.2016]
International Organization for Standardization, International Organization for Standardization,
"Information technology -- JPEG 2000 image coding system: "Information technology -- JPEG 2000 image coding system:
Core coding system", October 2016. Core coding system", October 2016.
[ISO.9899.1990] [ISO.9899.1990]
International Organization for Standardization, International Organization for Standardization,
"Programming languages - C", 1990. "Programming languages - C", 1990.
skipping to change at page 44, line 26 skipping to change at page 51, line 35
September 2012, <https://www.rfc-editor.org/info/rfc6716>. September 2012, <https://www.rfc-editor.org/info/rfc6716>.
[RFC6838] Freed, N., Klensin, J., and T. Hansen, "Media Type [RFC6838] Freed, N., Klensin, J., and T. Hansen, "Media Type
Specifications and Registration Procedures", BCP 13, Specifications and Registration Procedures", BCP 13,
RFC 6838, DOI 10.17487/RFC6838, January 2013, RFC 6838, DOI 10.17487/RFC6838, January 2013,
<https://www.rfc-editor.org/info/rfc6838>. <https://www.rfc-editor.org/info/rfc6838>.
12. Informative References 12. Informative References
[Address-Sanitizer] [Address-Sanitizer]
The Clang Team, "ASAN AddressSanitizer website", September The Clang Team, "ASAN AddressSanitizer website", undated,
2019, <https://clang.llvm.org/docs/AddressSanitizer.html>. <https://clang.llvm.org/docs/AddressSanitizer.html>.
[AVI] Microsoft, "AVI RIFF File Reference", September 2019, [AVI] Microsoft, "AVI RIFF File Reference", undated,
<https://msdn.microsoft.com/en-us/library/windows/desktop/ <https://msdn.microsoft.com/en-us/library/windows/desktop/
dd318189%28v=vs.85%29.aspx>. dd318189%28v=vs.85%29.aspx>.
[HuffYUV] Rudiak-Gould, B., "HuffYUV", December 2003, [HuffYUV] Rudiak-Gould, B., "HuffYUV", December 2003,
<https://web.archive.org/web/20040402121343/ <https://web.archive.org/web/20040402121343/
http://cultact-server.novi.dk/kpo/huffyuv/huffyuv.html>. http://cultact-server.novi.dk/kpo/huffyuv/huffyuv.html>.
[ISO.14495-1.1999] [ISO.14495-1.1999]
International Organization for Standardization, International Organization for Standardization,
"Information technology -- Lossless and near-lossless "Information technology -- Lossless and near-lossless
skipping to change at page 45, line 17 skipping to change at page 52, line 27
matroska/>. matroska/>.
[NUT] Niedermayer, M., "NUT Open Container Format", December [NUT] Niedermayer, M., "NUT Open Container Format", December
2013, <https://ffmpeg.org/~michael/nut.txt>. 2013, <https://ffmpeg.org/~michael/nut.txt>.
[range-coding] [range-coding]
Nigel, G. and N. Martin, "Range encoding: an algorithm for Nigel, G. and N. Martin, "Range encoding: an algorithm for
removing redundancy from a digitised message.", July 1979. removing redundancy from a digitised message.", July 1979.
[REFIMPL] Niedermayer, M., "The reference FFV1 implementation / the [REFIMPL] Niedermayer, M., "The reference FFV1 implementation / the
FFV1 codec in FFmpeg", September 2019, FFV1 codec in FFmpeg", undated, <https://ffmpeg.org>.
<https://ffmpeg.org>.
[VALGRIND] Valgrind Developers, "Valgrind website", September 2019, [VALGRIND] Valgrind Developers, "Valgrind website", undated,
<https://valgrind.org/>. <https://valgrind.org/>.
[YCbCr] Wikipedia, "YCbCr", September 2019, [YCbCr] Wikipedia, "YCbCr", undated,
<https://en.wikipedia.org/w/index.php?title=YCbCr>. <https://en.wikipedia.org/w/index.php?title=YCbCr>.
Authors' Addresses Authors' Addresses
Michael Niedermayer Michael Niedermayer
Email: michael@niedermayer.cc Email: michael@niedermayer.cc
Dave Rice Dave Rice
 End of changes. 29 change blocks. 
99 lines changed or deleted 371 lines changed or added

This html diff was produced by rfcdiff 1.47. The latest version is available from http://tools.ietf.org/tools/rfcdiff/