Fast prefix decoding

The method optimizes prefix coded bitstream decoding by using a multi-tiered approach with lookup tables to decode multiple symbols efficiently, addressing inefficiencies in existing methods and enhancing decoding speed for diverse data types.

GB2644033APending Publication Date: 2026-03-18V NOVA INT LTD
View PDF 2 Cites 0 Cited by

Patent Information

Authority / Receiving Office
GB · GB
Patent Type
Applications
Current Assignee / Owner
Filing Date
2024-09-11
Publication Date
2026-03-18

AI Technical Summary

Technical Problem

Existing methods for decoding prefix coded bitstreams are computationally inefficient and resource-intensive due to the need for multiple comparisons and lookups to decode symbols of different types, particularly in contexts like Low Complexity Enhancement Video Coding (LCEVC) residuals.

Method used

A method that decodes multiple prefix codes in a single operation using a multi-tiered approach with a first lookup table to decode multiple symbols and falls back to secondary operations if necessary, optimizing decoding speed and efficiency by using smaller lookup tables for remaining symbols.

Benefits of technology

This method significantly reduces computational operations and improves decoding speed by efficiently handling heterogeneous data types, particularly in Huffman and canonical Huffman coded bitstreams, with a disproportionate increase in speed for decoding common and uncommon codes.

✦ Generated by Eureka AI based on patent content.

Smart Images

  • Figure 00000000_0000_ABST
    Figure 00000000_0000_ABST
  • Figure 00000000_0002_ABST
    Figure 00000000_0002_ABST
  • Figure 00000000_0001_ABST
    Figure 00000000_0001_ABST
Patent Text Reader

Abstract

Decoding bitstream comprising prefix coded symbols of multiple different types, comprising obtaining first set of N bits of bitstream, N > 2, wherein first set contains (part) of prefix code which is
Need to check novelty before this filing date? Find Prior Art

Description

BACKGROUND A dataset is said to be sparse when a large percentage of data within the data set is equal to zero, or is missing. Data within the dataset may be referred to as sparse data. Various means of compressing sparse data exist, and various coding schemes can be used. One example coding scheme is a prefix coding scheme, or Huffman coding scheme, or a canonical Huffman coding scheme. Since sparse data contains many values which are the same, e.g. zero, when compressing sparse data, data values may be coded using a run-length coding scheme whereby runs of values are encoded instead of the individual values. Sparse data tends to be made up of small data values separated by a number of consecutive zeros. Run-length coding is therefore a useful way to compress and encode sparse data. It is also known that run-length coded data may further be compressed using a prefix coding scheme, which can further compress the data depending on if the run-length coded data includes repeat values with high probability. Generally, run-length encoded data is represented by two types of symbols, sent as bytes, which correspond to two different types of value in the data being encoded. In some applications, additional types of symbols may be used to encode the data. One example of sparse data is residual data in image or video coding. Various kinds of residual data exist, depending on the coding scheme being used, for example Low Complexity Enhancement Video Coding (LCEVC) residuals are one type of residual. When LCEVC residuals are encoded using run-length encoding, the run-length encoded residual data is typically represented by three types of symbol each sent or stored as a byte, each type is also referred to as a context. To be clear, when referring to a symbol, we intend to mean a number of bits grouped together to represent a value, and thus, in the context of this disclosure, a symbol may also be referred to as a byte. However, it is known to persons skilled in the art that a symbol is a data structure that an encoder feeds into an encoding scheme and which a decoder extracts from a decoding scheme. Symbols may have variable bit length depending on an encoding scheme. The context of a symbol refers to the type of the symbol, and depends on the kind of data encoded into the symbol. Still in the example of LCEVC, a first type of symbol is a least significant byte (LSB). This type of symbol encodes a data value or part of a data value. In some cases, the data value may be too large to be encoded with one LSB, in which case, a second type of symbol that immediately follows the LSB symbol is used to encode the remaining part of the data value. This type of symbol is known as a most significant byte (MSB). An LSB symbol contains a bit that indicates if it forms part of an LSB and MSB pair. A third type of symbol is referred to as a run length (RL). This symbol encodes the number of consecutive zeros in the data until the next LSB. An LSB also contains a bit which indicates if the next coded symbol is a RL. In other words, each LSB symbol indicates if the next type is an MSB or an RL, those symbols together forming a pair or set. In implementation, the LCEVC run-length data may be in the form of a triplet, each triplet forming a complete set. LCEVC data is typically a series of small values, separated by lots of zeroes. Therefore, the data may be treated as triplets, which take the following form. One byte stores the 6 least significant bits (“LSB”), and two bits to indicate if the next byte is an MSB byte, an RL byte, or neither. This first byte always present. One optional byte stores the 7 most significant bits (“MSB”). The presence of this byte is indicated by the LSB. This also has 1 bit, to indicate if the next byte is an RL or not. The MSB may also be referred to as an “overflow” byte, since it stores any data that could not fit in the LSB. 0 to 3 bytes encode the run-length (“RL”) of zeroes, i.e. how many zeroes there are before the next non-zero piece of data. Each of these bytes contains 7 bits to indicate a value, and 1 bit to indicate whether or not there is another run-length coming up. In implementations, each of these 3 triplets gets its own Huffman “dictionary” (or Huffman tree), because they have very different data sets, and the values are distributed very differently. Run-length coded symbols may be further encoded using a prefix coding scheme. Various prefix coding schemes exist, such as Huffman coding, and canonical Huffman coding. It may be desirable to perform prefix coding on sparse data or run-length coded sparse data as performing prefix coding can sometimes further compress the data depending if the run-length coded data or the sparse data has commonly repeating values. Methods of performing prefix coding, Huffman coding, and canonical Huffman coding are known, and at a high-level prefix coding associates each symbol with a corresponding codeword, and requires that there is no whole codeword in the system that is a prefix (initial segment) of any other code word in the system. Huffman coding is a specific kind of prefix coding and further requires that the most common symbols are given the shortest codewords. For example, a common value x may be given the Huffman code 1. In contrast, a rare residual value y may be given the Huffman code 0111. Canonical Huffman coding is a specific kind of Huffman coding according to which canonical Huffman codes are ordered in such a way that it suffices to only store the lengths of the codewords, which reduces the overhead of the codebook. When decoding prefix codes, a common approach is to obtain one bit of the prefix code at a time and compare the obtained bits to a dictionary until the obtained bits match a symbol in the dictionary. In the example of Huffman coding, it will be appreciated that the shortest and most common Huffman codes will be decoded quickly, while the longest, and rarest codes will require several lookup operations to decode. When referring to a lookup operation, we intend to mean that each comparison of obtained bit or bits to a lookup table is one operation. A bit-by-bit approach is computationally inefficient and resource intensive, since multiple comparisons may need to be made to entries in the dictionary before a match is found. Another prior art approach that has been considered is the use of a table that stores multiple codeword-symbol associations per row. The table is indexed by a 16 bit value. When a prefix coded bitstream is to be decoded, 16 bits are obtained from the bitstream and compared to the indexes of the table to find a matching index. The 16 bits are then decoded into the symbols associated with the codewords in the 16 bits. In the process of performing the decoding, it can be said that the bits corresponding to the codewords that are decoded are “consumed”. The bitstream to be decoded is then advanced by the number of bits consumed by the found codewords. The prior art method also proposed a fallback method wherein the bit-by-bit approach discussed above is used as a fallback to decode a codeword when the length of codeword is too large to be decoded using the table, or when the codeword is not a valid codeword. It is an object of this disclosure to refine implementations of prefix coding to reduce the time to decode the original symbols and make the decoding process more efficient. SUMMARY OF INVENTION According to an aspect of the disclosure, there is provided a method of decoding a prefix coded bitstream, the bitstream comprising prefix coded symbols, the symbols being of multiple different types, the method comprising: obtaining a first set of N bits of a prefix coded bitstream, wherein N >2, wherein the first set of N bits contains at least part of a prefix code, wherein a prefix code is associated with a symbol, wherein a plurality of symbols form a set of symbols, the set of symbols comprising a leading symbol of a first type and at least one symbol of a second type, the second type different to the first type, wherein each symbol indicates a type of the following symbol, wherein a final symbol in the set of symbols indicates that the following symbol is of the first type; performing a first coding operation on the first set of N bits, wherein the first coding operation associates multiple prefix codes with multiple symbols, wherein if the first coding operation obtains the leading symbol and final symbol in the set of symbols, then the method further comprises: obtaining a second set of N bits of the prefix coded stream, wherein the second set of N bits includes any undecoded bits of the first set of N bits; if the first coding operation does not obtain the final symbol in the set of symbols, then the method further comprises: iteratively performing a second coding operation until the final symbol in the set of symbols is obtained, wherein the second coding operation comprises obtaining a first set of P bits of the prefix coded stream, wherein 1 <P <N, wherein the first set of P bits includes any undecoded bits of the first N bits, wherein the second coding operation associates one prefix code in the first set of P bits with one symbol. When mentioning that the first set of N bits “contains” at least part of a prefix code for a set of symbols, we intend to mean that the first set of N bits represents or associates or corresponds to or resolves to at least part of a prefix code for a set of symbols. The present disclosure relates to a faster, more versatile and more efficient method of decoding a prefix encoded bitstream that decodes multiple prefix codes associated with multiple symbols of different types or contexts in one coding operation. Methods described herein decode multiple or at least one prefix code in a single coding operation with the aim of obtaining every symbol in a set of symbols. If every symbol in the set of symbols is obtained, which is determined by obtaining a symbol that indicates that the next symbol has the first type, then the next set of prefix coded bits to be decoded is obtained and the process is repeated. A prefix coded bitstream encoding symbols of different types can therefore be decoded with few computational operations such as searches of a table and comparing bits to be decoded to entries in a table. However, if not every symbol in the set of symbols is decoded, then the method makes use of a second coding operation to decode any remaining symbols in the set of symbols. That is, when some but not all of the symbols in the set of symbols are decoded, then the second coding operation is used. This is determined, for example, if the final symbol that is obtained by the first coding operation indicates that the following symbol is of the second type. To be clear, as mentioned above, when referring to a symbol, we intend to mean a number of bits grouped together, and thus a symbol may be sent or stored as a byte. When referring to a set of symbols, it is intended to communicate that the decoded data is typically arranged in groups of symbols of different types or contexts with a first symbol having a known context, i.e. being of the first type. By defining that the leading symbols of a set is a symbol of known context, the method may determine when every symbol in a set of symbols has been obtained. That is, every symbol in a set of symbols is known to have been obtained when the next symbol in the stream is indicated to have the first type. If the next symbol is indicated to be of another type, then a complete set of symbols has not yet been obtained. To put it another way, the final symbol in a set of symbols indicates that the next symbol occurring in the bitstream has the same type as the first symbol in the set of symbols, i.e. the first type. When referring to a bitstream, the term bytestream could also be used interchangeably. In some implementations, the first coding operation comprises: comparing the first set of N bits to indexes in a first lookup table, LUT, wherein the first LUT associates multiple prefix codes with multiple symbols, and either: matching the first set of N bits to a first index in the first LUT, wherein an entry in the first LUT corresponding to the first index comprises a decoding of the N bits; or determining that the first set of N bits do not match any index in the first LUT; wherein when the N bits match the first index, the method further comprises: decoding M bits of the N bits based on an entry in the first LUT corresponding to the first index to obtain a decoding of the M bits, wherein M <N, wherein the M bits represent at least two symbols in the set of symbols, and a bit of the M bits indicates a type of the following symbol in the prefix coded bitstream; determining, based on the type of the following symbol, whether the leading symbol and the final symbol in the set of symbols has been decoded, wherein if the leading symbol and the final symbol in the set of symbols has been decoded, then the method comprises the obtaining a second set of N bits of the Huffman coded stream, and if the final symbol in the set of symbols has not been decoded, then the method further comprises the iteratively performing a second coding operation. The lookup table mentioned above, and as generally discussed herein, is to be understood as a data structure that associates a prefix code with a symbol, such that the lookup table is used to decode a prefix code and obtain the corresponding symbol. The first lookup table mentioned above associates multiple prefix codes with multiple different types. As such, any kind of suitable data structure could be used, such as a linked list, a sorted list, or a key-value pair. A lookup table is an array, where the indexes of the array represent prefix codes, and the entries at each index are a decoding of that code, i.e. a symbol. Additional information, such as the number of bits that correspond to the symbol and the type of the symbol may also be stored in the lookup table. The use of the first lookup table in the context of decoding a prefix encoded bitstream facilitates multiple symbols of different contexts being obtained in one operation by comparing an obtained set of bits with indexes or indices of a lookup table. The aim of the lookup is to find as many symbols as possible at once, so that a relatively large number of bits can be decoded in one operation. It is noted that each symbol, once decoded, includes a bit which indicates the next type of symbol that will occur in the stream. For example, in the context of run-length coded LCEVC residual data a symbol may include a run bit or an overflow bit. When the run bit is set to 1, this indicates that the next symbol is a run length, and if the overflow bit is set to 1 then this indicates that the next symbol is an MSB. If the run bit and / or the overflow bit are set to 0, then this indicates that the next symbol is an LSB. It is possible to determine when the set of symbols has been decoded when the next symbol in the bitstream has a particular type. For example, a set of symbols may be decoded when the next symbol in the stream is an LSB symbol, as indicated by the run bit and / or the overflow bit being set to zero. In some cases, the first set of N bits may not match any index in the first LUT, the method further comprises: performing a third coding operation, wherein the third coding operation comprises: obtaining one or more additional bits from the prefix coded stream; comparing the obtained bits and the one or more additional bits to entries in a sorted list; and either: matching the obtained bits and the one or more additional bits to an entry in the sorted list, and decoding the obtained bits and the one or more additional bits based on the entry in the sorted list, wherein the obtained bits and one or more additional bits represent one symbol in the set of symbols; or: determining that the obtained bits and the one or more additional bits do not match any entry in the sorted list; and obtaining one or more further additional bits from the prefix coded stream. The first coding operation, second coding operation and third coding operation are intended to be different coding operations, rather than the second and third coding operations being a repetition of the first coding operation. This is already reflected by the requirement that the first coding operation associates multiple prefix codes with multiple symbols, whereas the second coding operation associates one prefix code with one symbol. The coding operations described herein, such as the first coding operation, the second coding operation, and the third coding operation may also be referred to as a first decoding operation, a second decoding operation, and a third decoding operation respectively. In some cases, a prefix code will exceed the length of the index of the first lookup table. Further, because any prefix code never starts with what would appear to be another prefix code, no match will be found amongst the first indexes. To ensure that such symbols can continue to be obtained, the present method falls back to a third coding method, where additional bits are repeatedly picked from the stream and compared, together with the first set of N bits, to entries in a sorted list until a symbol corresponding to the prefix code is found. Further, the third coding operation is also used in situations where the second Huffman decoding operation is unable to decode a set of bits. For example, as discussed in detail below, this could occur when the bits being decoded are not a valid prefix code. Another approach that might be considered is to set the size of the first lookup table so that the longest prefix code in a data set can be decoded using the first lookup table. However, such an approach typically results in a net loss of decoding efficiency since the first lookup table becomes too large, and requires additional time and resources to search. Therefore, falling back to performing the third coding operation provides increased decoding speed and efficiency. In some examples, if the third coding operation decodes the final symbol in the set of symbols, then the method further comprises: the obtaining the second set of N bits of the prefix coded stream. In other words, once every symbol in the set of symbols is obtained, the method reverts back to using the first coding operation, for example using the first lookup table, thereby ensuring that the third coding operation is used only to the extent it is necessary to decode exceedingly long and / or rare codes. This optimisation allows for the benefits of the first lookup table in terms of decoding speed to be combined with the benefit of using a sorted list for decoding very long codes that do not appear in the first lookup table. Moreover, if the third coding operation does not decode the final symbol in the set of symbols, then the method further comprises: performing the second coding operation. In some further examples, the second coding operation comprises: comparing the first set of P bits to indexes in a second lookup table, LUT, wherein indexes of the second LUT comprise fewer bits than indexes in the first LUT, wherein the second LUT associates one prefix code with one symbol; and either: matching the first set of P bits to a first index in the second LUT, wherein an entry in the second LUT corresponding to the first index comprises a decoding of the P bits; or: determining that the first set of P bits do not match any index in the second LUT; when the P bits match the first index in the second LUT, the method further comprises: decoding Q bits of the P bits based on the entry in the second LUT corresponding to the first index in the second LUT to obtain a decoding of the Q bits, wherein Q is less than or equal to P, wherein the Q bits represent one symbol in the set of symbols, and a bit of the Q bits indicates a type of the following symbol in the prefix coded bitstream; determining, based on the type of the following symbol, whether the final symbol in the set of symbols has been decoded, wherein if the final symbol in the set of symbols has been decoded, then the method comprises the obtaining a second set of N bits of the prefix coded stream, and if the final symbol in the set of symbols has not been decoded, then the method comprises obtaining a second set of P bits, wherein the second set of P bits comprises any undecoded bits in the first set of P bits. The advantages of the present approach are magnified when the second lookup table is used in combination with the first lookup table. That is, it has been found that when some but not all symbols in a set of symbols have been decoded, it is more efficient to fall back to a second lookup table rather than persisting with the first lookup table. This is because if the leading symbol of the first type in the set of symbols has been decoded the other remaining symbol or symbols in the set of symbols will have a different type. When different types of prefix contexts are shuffled together in this way, this is referred to as heterogenous data. Each type of data, i.e. the symbols of the first type and the symbols of the second type, each have their own prefix encodings, so it is possible that the same prefix code could be used for different symbols of different types. In this case, the first lookup table would require at least two entries in the same location. One entry represents a combination of the leading symbol and another symbol of a different type, and the other entry represents only the other symbol of a different type. This would essentially require two first lookup tables to be constructed, which introduces significant additional resource usage without providing a corresponding additional benefit in most cases. Hence, it is typically more efficient to use the second lookup table, which is constructed to decode a symbol of the second type. Compared to the first lookup table, which was used to attempt decoding multiple prefix codes at a time, indexes of the second lookup table preferably have fewer bits, such that the second lookup table is used to decode one symbol having a type different to the first type at a time until every symbol in the set of symbols has been obtained. However, the second lookup table still attempts to decode multiple bits of the prefix coded stream in one operation, thereby providing a fallback with increased decoding speed compared to approaches that decode one bit at a time. Notably, once the set of symbols has been decoded, the method reverts to obtaining the next N undecoded bits in the bitstream, so that the first lookup table can again be used. In some cases the first set of P bits do not match any index in the second LUT, hence the method may further comprises: performing a third coding operation. Further, some examples of the disclosure provide a method where prefix codes of symbols of the first type are modified to obtain a modified prefix code, wherein the modifying comprises: encoding a number of leading zeros of a prefix code as L leading bits of the modified prefix code. Modifying a prefix code in this way has a particular benefit when Huffman coding is used, since the longest and therefore rarest codes will be decoded quicker than they otherwise would be. In some examples the prefix coded bitstream is decoded to generate run-length encoded sparse data. In such cases, the method may further involve decoding the run-length encoded sparse data to generate sparse data. In some examples the prefix coded bitstream is decoded to generate run-length encoded symbols. For example, the method may further comprise decoding the run-length encoded symbols to generate sparse data In some advantageous examples, the sparse data can comprise residual data. In examples, the residual data may comprise LCEVC residual data. In some specific examples, for example where the residual data is LCEVC residual data, L, that is the number of leading zeros added to a modified prefix code, may equal 4. Other values of L are possible, but a value of 4 has been found to provide the best benefit for decoding the longest prefix codes, without imposing too great a cost on decoding shorter codes. That is, short codes will typically still be decoded using the first lookup table, so the benefit of decoding the longest and least common codes more quickly outweighs the cost. The first lookup table can be efficiently stored by using 4 bytes to communicate 6 pieces of information. Specifically, 3 bytes can be used to store data values for the LSB symbol and up to two additional symbols. The fourth byte stores 3 pieces of data. Five bits are used to store a value indicating the number of bits consumed by obtaining the symbols associated with given prefix codes. Five bits are used since the maximum possible number of bits is 15 leading zeroes and 8 bits, the total being 23 bit, and five bits can store numbers 0 to 31. One bit is left vacant to accommodate even larger lookup tables in the future, one bit is used to indicate if there is an MSB that did not fit in the lookup table, and one bit is used to indicate if there is an RL that did not fit in the lookup table. This is a dense way of storing the information needed to construct the first lookup table. In the examples above, where the residual data is LCEVC data, N may equal 12. This allows for up to three prefix codes to be decoded in one operation when using the first lookup table. Further, when attempting to decode 12 bits in one operation, even if some but not all symbols in the set of symbols are decoded, this still provides a considerable improvement compared to a bit-by-bit approach. In some examples where the residual data is LCEVC data, P may equal 10. By attempting to decode 10 bits in one operation, the prefix codes of remaining undecoded symbols in the set of symbols can be quickly decoded by the second coding operation. The set of symbols may comprise three symbols. Further, the three symbols may comprise a leading symbol of the first type, one symbol of the second type, and one symbol of a third type, the third type of symbol being different to the first type of symbol and second type of symbol. In other words, taking LECVC residuals as an example, one symbol may represent part of a data value, another symbol may represent a second part of the data value, and still another symbol may represent a run of consecutive zeros. In still other words, the set of symbols may comprise an LSB + MSB + RL triplet of symbols. However, it must be remembered that the underlying concept is that each symbol in the set of symbols is unique. Alternatively, the leading symbol has the first type, and the two symbols following the leading symbol have the second type. In other words, the leading symbol that occurs in the set of symbols may have a first type, and the second and third symbols in the set of symbols may have a second type, the second type being different to the first type. Taking LCEVC residuals as an example, one symbol, such as the first symbol in the set of symbols, may represent part of a data value, and two symbols may represent consecutive runs of zeros. In other words, the set of symbols may comprise an LSB + RL + RL triplet of symbols. As noted, data of this type is referred to as heterogenous data, since three types of prefix contexts are shuffled together. As a result, the decoding of the same prefix code could be different depending on the context of the prefix code. That is, again taking LCEVC residuals as an example, the code “1” could represent a symbol “1” if it is an LSB, “0” if it is an MSB, or “255” if it is a run length. The context of a prefix code should therefore be known before it can be decoded, so that the correct prefix dictionary can be used. With reference to the above LCEVC examples of the types of symbols in the set of symbols, it has been found that LCEVC residual data includes very few data values that are so large that they have to be encoded into two data symbols. The most common set of three symbols in LCEVC residual data was found to be a symbol encoding part of a data value and two symbols that encode respective runs of consecutive zeros, that is an LSB + RL + RL triplet. The decoding method therefore takes advantage of the underlying distribution of LCEVC residual data. In some examples the prefix coded bitstream comprises a Huffman coded bitstream. Further, the Huffman coded bitstream may comprise a canonical Huffman coded bitstream. When the above approaches are applied to Huffman coded data, a particular advantage is that the shortest and most common Huffman codes are decoded quicker, which provides a disproportionate improvement to the speed of decoding, since the shortest Huffman codes are the most common. In examples the bitstream comprises a set of prefix codes and metadata from generating a prefix codebook, each unique prefix code in the codebook resolving to a symbol in the set of symbols. Alternatively, instead of the codebook being retrieved from the bitstream, the codebook may be predetermined. The prefix dictionary may be generated a priori from the codebook, the codebook being known to a decoder before decoding begins, either from the bitstream or by being predetermined. In examples, the method may further comprise constructing a lookup table, for example the first lookup table or the second lookup table, from multiple codebooks, each codebook relating to a different context. An aspect of the disclosure provides a decoder comprising a processor, the processor being configured to perform a Huffman coded bitstream using a method according to the first aspect or any example of the first aspect. An aspect of the disclosure further provides a computer readable medium comprising instructions, which when executed by a processor, cause the processor to perform a method according to the first aspect or any example of the first aspect. BRIEF DESCRIPTION OF DRAWINGS The disclosure will be discussed with reference to the drawings, in which: Figure 1 is a flowchart relating to a method of performing Huffman decoding; Figure 2 is a flowchart relating to a method of performing Huffman decoding using a first lookup table; Figure 3 is a flowchart relating to a method of performing Huffman decoding using a second lookup table; Figure 4 is a flowchart relating to a method of performing Huffman decoding using a sorted list; and Figures 5A, 5B and 5C respectively provide an example of a first lookup table, a second lookup table and a sorted list. DETAILED DESCRIPTION The present disclosure relates to an improved method of decoding a prefix coded bitstream, or bytestream, that attempts to decode multiple prefix codes in one coding operation. The method attempts to decode multiple prefix codes substantially simultaneously by associating multiple prefix codes with multiple symbols of different types. The concepts described herein can be applied to many kinds of data, such as sparse data, image data and video frame data, as well as residual data. When referring to a video frame, we intend to mean a video frame, video surface or video plane. The data may or may not be run-length coded and then prefix coded. That is, in some examples, the prefix coded bitstream is decoded to obtain run-length coded symbols, whereas in other examples, the prefix coded bitstream is decoded to obtain the sparse data. As such, it will be appreciated that concepts described herein apply broadly to prefix coded bitstreams or bytestreams, and that the advantageous effects of the disclosed method are realised by applying the method to prefix coded sparse data. A multi-tiered or multi-staged approach to prefix decoding is provided. In a first tier or stage, a plurality of prefix coded bits are obtained, and it is attempted to decode the bits, for example by using a first lookup table (LUT). Using the first LUT, multiple symbols can be obtained in one decoding operation. This is achieved by constructing the first LUT such that an index resolves multiple codes to multiple symbols of different types i.e., different contexts. If every symbol in a set of symbols is decoded, then the next set of undecoded bits is obtained, otherwise the method falls back to a second tier or stage which attempts to decode a smaller number of bits with the aim of obtaining one symbol in a set of symbols until the final symbol in the set of symbols has been obtained. Each obtained symbol indicates the type of the next symbol in the bitstream, and the leading symbol in the set of symbols is always a symbol of the first type. In this way it can be determined that every symbol in a set of symbols has been decoded when the next symbol is indicated to have the same type as the leading symbol in the set of symbols, i.e. the first type, e.g. an LSB symbol. In some cases, the prefix code being decoded will exceed the length of the prefix codes that can be decoded using the first coding operation or will otherwise not be decodable using a lookup table. In this case, the method falls back to a third tier, in which further bits are obtained from the stream one at a time and compared, together with the already obtained bits, to entries in a sorted list until a match is found, thereby allowing for the symbol corresponding to the bits to be obtained. The high-level concept described above allows for multiple prefix codes associated with multiple symbols of different types to be decoded in one decoding operation, reduces the number of comparisons that need to be performed to obtain a symbol and therefore improves decoding efficiency and speed. The disclosures discussed herein can be applied generally to sparse data that has been prefix coded. However, to contextualise the disclosure, the discussion below typically refers to residual data or Low Complexity Enhancement Video Coding (LCEVC) residual data. However, it is to be understood that the concepts and methods of the disclosure are generally applicable to any kind of sparse data having been prefix coded, and which may optionally have been run-length coded. It may be especially advantageous to apply methods described herein to Huffman coded bitstreams and canonical Huffman coded bitstreams, as they have the property that the shortest codes are the most common, leading to a disproportionate increase in decoding speed. We note that the first coding operation and likewise the second coding operation may not use utilise a lookup table, but instead use another data structure, for example a key-value pair where the key includes multiple prefix codes and the value comprises multiple symbols of different types. Further, when stating that the bitstream comprises prefix coded symbols, this could mean that the sparse data may be run-length coded before prefix coding or Huffman coding or canonical Huffman coding is applied. It is to be understood that the involvement of run-length coding is optional. Various aspects of run-length coding and Huffman decoding are discussed in PCT / GB2019 / 052166, published as WO2020 / 025964 which is incorporated herein by reference. Residual data in image or video data typically takes the form of values separated by runs of consecutive zeros. In the context of LCEVC run-length encoded residual data occurs in three types of symbol or context, i.e. a least significant byte (LSB), stores the 6 least significant bits of a value, and two bits which indicate the type of the next byte or symbol, these being a run bit and an overflow bit. When a stream of residual data is being decoded, the first byte is assumed to be an LSB, as this allows the decoder to start on a known context. A further optional byte is referred to as a most significant byte (MSB) stores the 6 most significant bits of a data value. These are rare in LCEVC residual data. The presence of this byte is indicated by the immediately preceding LSB when the overflow bit of that LSB is set to 1. An MSB also has 1 bit to indicate the type or context of the next byte. An MSB may also be referred to as an “overflow” byte, since it stores any data that could not fit in the LSB. Another type of symbol or byte encodes the run-length (RL) of consecutive zeroes, i.e. how many zeroes there are before the next non-zero piece of data. Each of these bytes contains 7 bits to of a value, and 1 bit relating to whether or not the next byte is an RL. The present disclosure attempts to decode every symbol in a set of set of symbols of different types in one decoding operation. Each set of symbols may be assumed to include an LSB, and MSB and an RL, in that order. However, a set of symbols may be assumed to include an LSB, an RL and an RL, in that order. It can be appreciated that a set of symbols starts with a known context, which in this example is the LSB. The context of a symbol refers to the type of the symbol, and depends on the kind of data encoded into the symbol. This allows the method to know when every symbol in a set of symbols has been obtained, because each symbol also indicates the type of the next symbol. When the next symbol is indicated to be a symbol of a certain type, this means that every symbol, i.e. the final symbol in the set of symbols, has been decoded. It is to be noted that when decoding each different type of symbol, a different codebook is used for each type of symbol. This is because the distribution of values of each type of symbol varies significantly. The method therefore switches between multiple decoding contexts depending on the context of the current symbol being decoded. More specific examples of the disclosure will now be discussed with reference to the drawings. Referring to Figure 1, a method 100 of performing Huffman decoding in accordance with the disclosure is shown. In step 110 N bits of a prefix coded bitstream are obtained, wherein N is greater than 2, and wherein the N bits comprise the prefix code for part or all of a set of symbols. That is, the N bits could comprise the code for every symbol in a set of symbols, or they could comprise the code for some but not all symbols in a set of symbols. However, at this stage of the decoding process, it is generally not known if the obtained bits represent a code for all or some symbols in a set of symbols. The set of symbols may include one or multiple symbols, and in some cases may include 3 symbols. At step 200, a first coding operation is performed on the first set of N bits. An example first coding operation is discussed below with reference to Figure 2. In any case, the first coding operation acts on the N bits and either obtains a every symbol in the set of symbols or obtains some but not all symbols in a set of symbols or does not obtain any symbols. If a every symbol in a set of symbols is obtained, i.e. if the leading and final symbol in the set of symbols is obtained, then the method proceeds to step 130 by obtaining a second set of N bits, and performing a further first coding operation on the second set of N bits until all bits have been consumed and the stream has been completely decoded. It is to be noted that the second set of N bits will include any undecoded bits from the first set of N bits. That is, the first Huffman decoding operation may decode some, but not all of the first set of N bits. For example, if 8 bits have been obtained, 6 of these bits may correspond to 3 prefix codes, and 2 bits may not be decoded. In this case, the second set of N bits includes those undecoded bits from the first set of N bits. If some but not all symbols in the set of symbols is obtained by the first coding operation, or in other words, the first coding operation obtains the leading symbol but not the final symbol in the set of symbols, then the method proceed to step 300, where a second coding operation is performed until the final symbol in the set of symbols is decoded. Further details relating to the second coding operation are discussed below with reference to Figure 3. In accordance with the above, by performing a coding operation on multiple prefix coded bits, the speed and efficiency of prefix decoding is increased and multiple symbols of different contexts can be obtained. Further, a versatile method is provided by switching to the second coding operation if some but not all symbols in a set of symbols are obtained by the first coding operation, thereby using an appropriate coding operation depending on the effectiveness of the first coding operation. The bitstream is advanced by a number of bits, depending on the number of bits that are decoded, or consumed by the first coding method. Turning now to Figure 2, the first coding operation 200 is described in more detail. In a first step 210, the obtained N bits in the first set of N bits is compared to indexes or indices of a first lookup table (LUT). The first LUT used in the first coding operation stores longer indexes than a second LUT which is used in the second coding operation, as will be discussed below. The indexes of the first LUT typically have a fixed size which is predetermined. However, in one example, the size of the first LUT may be determined dynamically so that the longest prefix code in a coding system can be decoded using the first LUT, thereby guaranteeing that the method never falls back to a third coding method, which will be discussed below. Following the comparison in step 210, the method proceeds differently depending on if the obtained N bits match an index in the first LUT. If no match is found, then the method proceeds to step 400 in which a third coding operation is performed. Further details of the third coding operation are discussed below with reference to Figure 4. The first LUT table can be searched for a match using any known or yet to be discovered searching algorithm. The skilled person would be aware that different searching algorithms have different benefits depending on use-case, and it would be obvious to the skilled person to use a suitable searching algorithm, or seek an improved searching algorithm depending on the size of nature of the first LUT. If the first set of N bits do match an index in the first LUT, then the method proceeds to step 220 where M bits of the N bits are decoded based on an entry in the first LUT corresponding to the matching index. M is less than or equal to N, meaning that all N bits can be decoded, but this need not be the case, and fewer than N bits can be decoded to obtain the symbols comprised in the code of the M bits. However, the M decoded bits correspond to at least two symbols in the set of symbols. Ideally, all symbols in a set of symbols are obtained by decoding the M bits. In any case, in line with the above discussion, the obtained symbol includes at least one bit indicating the type or context of the next symbol in the stream. If it is determined, based on the next type of symbol in the prefix coded bitstream that every symbol in the set of symbols has been obtained, and the stream includes further bits to be decoded, then the method proceeds with step 130 as discussed above. However, if not every symbol in the set of symbols has been decoded, then the second coding operation is performed at step 300. To elaborate, the method determines if every symbol in the set of symbols has been obtained based on the type of the following symbol. For example, and in the context of LCEVC residuals, it may be determined that if the next symbol is an LSB, then every symbol in the set of symbols has been obtained, and the following symbol in the bitstream or bytestream starts a new or another or different or next set of symbols. Still referring to LCEVC residuals, depending on the context of the last symbol that was obtained, there are different ways of determining if the next symbol is an LSB. If the last symbol was an MSB, then the next symbol will be determined as an LSB if the run bit is 0. If the last symbol was a RL, then the next symbol is determined to be an LSB if the run bit is 0. If the last symbol was an LSB, then the next symbol is determined to be an LSB if the run bit and overflow bit are both zero. The underlying concept is that it can be learnt that every symbol in a set of symbols has been obtained by identifying that the next symbol occurring in the bitstream or bytestream has a specific type. It will be appreciated that the assumption that the run-length coded symbols follow the pattern LSB + MSB + RL or LSB + RL + RL applies generally, but exceptions will occur in any real data set. Further advantages may be realised by modifying prefix codes of LSBs so that they include a number of leading bits that encode the number of leading zeros of the unmodified prefix code. For example, in the context of LCEVC residual data, 4 leading zeros may be added to an LSB. To give an example of modifying a prefix code, the code 0000 0001 would be modified to be [0111 ]1 because 0111 is the binary representation of 7, and the code 0000 0001 starts with 7 leading zeros. To give another example, the prefix code 1 would be modified to be

[0000] 1. Evidently, modifying prefix codes in this way saves on the number of bits used to represent the longest prefix codes, while introducing a cost on the number of bits needed to represent the smallest prefix codes. Nevertheless, modifying LSBs in this way has been found to provide a net benefit. Turning now to Figure 3, the second coding operation 300 is described in more detail. The second coding operation is performed after the first Huffman decoding operation obtains some but not all symbols in a complete set of symbols. This also means that at least some bits of the first set of N bits have been decoded. The second coding operation proceeds with step 310, in which a first set of P bits are obtained. The value of P is greater than 1, but less than N, which allows for the second coding operation to also operate on multiple bits, thereby providing additional speed compared to a comparative approach of performing prefix decoding. The first set of P bits also usually includes any undecoded bits from the first set of N bits. The second coding operation proceeds in a similar manner to the first coding operation, with differences. For example, at step 320, the P bits are compared to indexes in a second LUT, rather than a first LUT. The second LUT of the second coding operation is small in the sense that the indexes have a smaller length, and therefore the second LUT has fewer entries compared to the first LUT. At step 340, Q bits of the P bits are decoded based on the entry of the second LUT matching the matched index, where Q is less than or equal to P. Another difference between the second coding operation and the first coding operation is that whereas the first coding operation seeks to obtain multiple symbols in one operation (facilitated by the length of the indexes in the first LUT), the second coding operation seeks to obtain one symbol at a time. Even so, by operating on multiple bits, the second coding operation provides a considerable increase in decoding speed when compared to a comparative bit-by-bit approach. After decoding the Q bits, the method diverges depending on if a complete set of symbols has been obtained. As noted above, the method determines if every symbol in the set of symbols has been obtained based on the type of the following symbol. For example, it may be determined that if the next symbol is an LSB, then every symbol in the set of symbols has been obtained, and the following symbol starts a new or different or another or next set of symbols. If every symbol in the set of symbols has not been obtained, then the method proceeds to step 350 where a second set of P bits are obtained. The second set of P bits includes undecoded bits from the first set of P bits, and the next undecoded bits in the prefix coded stream. The second set of P bits are then compared to indexes in the second look up table, and the second coding operation is repeated in accordance with the steps described above. The second coding operation is iterated until the final symbol in the set of symbols has been obtained. As discussed above, the heterogenous nature of the prefix coded data renders it more efficient to utilise the second coding operation, rather than persist with using the first coding operation. This is because without the second coding operation, two first lookup tables would have to be constructed to account for the different type of symbols that would be associated with the leading prefix code in the set on N bits, depending on if the leading symbol in the set of symbols has or has not been obtained. Such an approach results in resource wastage in most cases, and hence the second lookup table is constructed to avoid resource wastage and improve efficiency. To elaborate, the first lookup table is typically 8 to 32 times larger than the second lookup table, owing to the longer length and large number of entries in the first lookup table. Additionally, the number of entries in the first lookup table scales exponentially with the number of symbols in the coding system. Hence, constructing a second version of the first lookup table to results in higher fixed cost with low ongoing benefits. However, in certain cases it may be feasible to construct a second version of the first lookup table. In the context of LCEVC encoded residual data, these are when the prefix coded stream: is at 4K resolution (or higher) with a direct decomposition (DD) transform, or at an 8K resolution (or higher) with direct decomposition squared (DDS) transform; is not very detailed in the visual sense; has a high bit-depth, for example a bit-depth greater than or equal to 10 bits per colour sample; and is encoded with a small step-width parameter, entailing that the residuals are precise. However, if every symbol in the set of symbols has been obtained, and the prefix coded stream includes further bits to be decoded, then the method proceeds to step 130, where the second set of N bits is obtained, so that the method can revert to the first coding operation. Referring now to Figure 4, the third coding operation is shown in greater detail. As noted above, the third coding operation is performed if, during the first coding operation, the first set of N bits is found not to match any of the indexes in the first LUT. This typically happens because the prefix code being decoded is longer than the longest index in the first LUT, and because a prefix code does not start with what appears to be another prefix code. Equally, the third Huffman coding operation may be performed if the obtained set of P bits in the second coding operation does not match any of the indexes in the second LUT. Examples of both scenarios are provided below. Accordingly, in a step 410, an additional bit is retrieved from the prefix coded bitstream, and compared, together with the previously obtained bits to entries in a sorted list at step 420. When referring to the previously obtained bits, these could be a set of N bits from the first coding operation or a set of P bits from the second coding operation. If no match is found in the sorted list, then another additional bit is repeatedly obtained and with each new obtained bit all of the obtained bits are compared to entries in the sorted list until a match is found at step 430. The obtained bits and additional bits are subsequently decoded at step 450, at which point the method proceeds differently depending on if decoding step 450 results in every symbol in a set of symbols being obtained. If not every symbol in the set of symbols has been obtained, then the method proceeds to step 300, where a second coding operation, as described above with reference to Figure 3, is performed. Otherwise, if it is determined that every symbol in the set of symbols has been obtained, then the method proceeds back to step 130 (see Figure 1) by obtaining the second set of N bits. The sorted list described above could be any data structure that stores a prefix code and its decoding, such as a table, a key-value or any other suitable data structure. Based on the above discussion, it will be understood that the advantages provided by the present disclosure include improved decoding efficiency and speed by reducing the number of computational operations required to decode a prefix coded bitstream or bytestream to obtain a set of symbols. It was discussed that multiple bits are obtained and decoded substantially simultaneously to obtain every symbol in a set of symbols. Even if every symbol in a set of symbols is not obtained, then a fallback decoding operation is utilised to obtain every symbol in the set of symbols, so that the distribution of data in the underlying data can be exploited to improve decoding efficiency. Specific examples will now be discussed with reference to Figures 5A to 5C. Figure 5A shows an example of a first lookup table 500. A first column of the first lookup table 500 stores indexes 510. The example given in Figure 5A shows that the indexes are 6 bit indexes. However, this is purely for the sake of example, and it will be understood that the indexes 510 could be made up of more or fewer bits. For example, in the context of LCEVC residual data, 12 bits will typically be used to represent the indexes of the first lookup table. A second column of the first lookup table 500 stores symbols 520 which correspond to the indexes. Note that some indexes correspond to 3 symbols, some indexes correspond to 2 symbols, and some indexes correspond to 1 symbol. It will be appreciated that in some implementation more than 3 prefix codes may be decodable from one index. Further, the symbols are represented by letters in this example, so that they are easier to distinguish from the prefix codes. However, the symbols may be represented in any suitable way, for example as a set of bits. In the first or topmost row of first LUT 500, it is shown that codes 0000 00 to 0000 11 are NULL. This means that these codes are not valid prefix codes. This is because, as can be seen in Figure 5C, codes 0000 00 to 0000 11 could also be interpreted as the beginning of a number of 8 bit prefix codes. A prefix code cannot match the beginning of another prefix code, and therefore codes 0000 00 to 0000 11 are not valid prefix codes in this scenario. Further, although this is not shown for the sake of preventing the drawings from becoming unwieldy, every permutation of 6 bits will be stored as an index in the first LUT 500. Figure 5B shows an example of a second lookup table 540. Similar to the first lookup table 500, the second lookup table 540 is shown to have two columns. A first column stores indexes 550 and a second column stores decoded symbols 560. Unlike the first LUT 500, indexes 550 of the second LUT 540 comprise 4 bits, and correspond to 1 symbol. Further, every permutation of 4 bits is included in the second LUT 540, but this is not shown. It is noted that code 0000 is NULL. This means that 0000 is not a valid prefix code. Figure 5C shows an example of a sorted list 580. Sorted list 580 contains 8 bit prefix codes and their corresponding decoding. The sorted list 280 differs from a normal dictionary in that not all codes are stored in the sorted list 580, rather only the codes which cannot be decoded by the first LUT or the second LUT are stored. The 8 bit codes are too long to be stored as indexes in the first lookup table, and expanding the first lookup table to fit the longest prefix codes would result in a net loss of efficiency due to the increased size of the first lookup table, and the corresponding increased time it would take to search. This is especially true in the case of a Huffman coded bitstream or bytestream since the longest Huffman codes are the rarest, and so the cost of expanding the first lookup table to include the longest codes outweighs the benefits of making it marginally quicker to decode the longest codes. The sorted list may be constructed by looping through all possible value for LSBs that can occur, then looping through all values that could come after the LSB, and then looping through all possible values that could occur the values that could occur after the LSB. We now discuss worked examples setting out how a prefix coded bitstream is decoded using the method discussed above. We emphasise at the juncture that the examples discussed below relate generally to sparse data which has been prefix coded. Example 1 - Decoding Using First and Second Lookup Tables We will now provide a worked example showing how a bitstream is decoded according to the methods discussed above using the example data structures shown in Figures 5A to 5C. The purpose of this example is to show how the first and second lookup tables can be used to efficiently decode a prefix coded bitstream. Consider a bitstream to be decoded 000111 000100 010001. The first 6 bits of the bitstream are obtained: 000111. In this example, 6 bits are obtained because the indexes 510 of the first lookup table 500 comprise 6 bits. If the indexes 510 of the first lookup table 500 were of a different length, then the obtained number of bits would be correspondingly the same. That is, the obtained number of bits is selected to match the number of bits used by the indexes 510 of the first lookup table 500. This is to facilitate comparison between the obtained bits and the first indexes 510. The 6 obtained bits are compared to the indexes 510 in the first lookup table 500. In this case, the obtained bits match index 512, 0001 11. The decoded symbols corresponding to index 512 are “d a a”. In this way, 6 bits have been decoded at once and 3 symbols have been obtained by making 1 comparison to indexes 510 of the first lookup table 500. Although this is not shown in Figure 5A to avoid overcomplicating the diagram, each decoded symbol will also indicate the next type of symbol in the bitstream. For the sake of example, it is assumed that the second “a” in the set of decoded symbols indicates that the next symbol will encode a data value. For example, in the context of LCEVC residual data, it may be indicated that the next symbol in the bitstream is an LSB. The method also notes the number of bits that have been decoded based on information included in the lookup table. In this example, 6 bits have been decoded, and so the stream is advanced by 6 bits. Accordingly, the next set of 6 bits is then obtained: 000100. This set of bits is compared to the indexes 510 of the first lookup table 500, where it is found that the bits match index 516. Index 516 corresponds to symbol “c”. The method notes that 4 bits have been decoded to obtain the symbol c. At this point, the method may proceed differently depending on the next type of symbol in the stream. If the symbol c indicates that it is by itself every symbol in a set of symbols, then the decoding proceeds by advancing the stream by 4 bits, and obtaining the next 3 undecoded bits, so that the next set of 6 bits can be decoded by the first LUT 500. However, for the purpose of this example, let us assume that obtaining the symbol c does result in every symbol in a set of symbols being obtained, and so the method proceeds to perform the second coding operation, for example by referring to the second LUT 540. Of the 6 bits that were to be decoded in the previous step, 0001 has been decoded, and 00 remains. The stream is advanced, and 00 is supplemented by the next two undecoded bits in the stream: 01. That is, the method attempts to decode 0001 using the second LUT 540. The bits 0001 are compared to the indexes 550 of the second LUT 540. It is found that 0001 corresponds to the symbol “d”. For the sake of this example, we also assume that obtaining the symbol “d” does not result in every symbol in the set of symbols being obtained. The stream is advanced by the number of bits that have been decoded (in this case 4 bits), and the remaining bits in the bitstream are 0001. In a similar fashion to the previous step, 0001 is compared to the indexes in the second LUT 540, and it is found that 0001 corresponds to “d”. Depending on if this obtained symbol indicates that every symbol in the set of symbols has been obtained, the method may proceed with decoding further prefix codes using the second LUT 240, or revert back to the first coding operation, for example using the first LUT 500. However, in the present example, no bits remain to be decoded and hence the method is concluded. As an aside, it is to be noted that if less than 4 bits remained in the stream, then the remaining bits would be supplemented with trailing zeros so that 4 bits could be used with the second lookup table. This applies generally to all of the lookup tables, lists and examples of the present disclosure. In summary, by using the first LUT 500 and the second LUT 540, the Huffman coded bitstream 000111 000100 010001 is decoded to obtain symbols d a a c d d. In total, 4 comparisons were needed to perform the decoding, which is a significant reduction compared to other comparative methods. For example, a bit-by-bit approach would require 18 comparisons to decode the above bitstream. Example 2- Decoding Using First and Second Lookup Tables and Sorted List Consider a second worked example using the prefix coded stream: 000100 000001 001011. The purpose of this example is to show a scenario where the method proceeds from the first coding operation to the second coding operation, and then to the third coding operation. The first 6 bits are obtained: 000100. These are compared to the indexes 510 of the first lookup table 500, and found to correspond to “d”, and further found not to be every symbol in a set of symbols. By decoding “d”, 4 bits are decoded, and hence the next 2 bits are obtained from the bitstream for comparison with indexes 550 of the second LUT 540. That is, the bits 0000 are compared to indexes 550 in the second LUT. In this case, it is found that 0000 corresponds to NULL. Hence, the method proceeds to use the third coding operation to obtain the next symbol. For example, the next undecoded bit is obtained and compared to entries in the sorted list 580. Specifically, the bits 00000 are compared to entries in the sorted list. It is found that this does not match any of the entries in the sorted list. Additional bits are added to the bits being decoded, and compared to entries in the sorted list 580 until a match is found in the sorted list. In this example, a match is found when the code 0000 0001 is compared to entries in the sorted list. The bits 0000 0001 correspond to the symbol “f”. It is also assumed that obtaining the symbol “f” does result in every symbol in the set of symbols being obtained. Accordingly, 8 bits are decoded, and because every symbol in the set of symbols has been obtained, the method reverts to the first coding operation to decode the remaining 6 undecoded bits. In this example, 001011 is decoded to “d a a” using the first coding operation. Example 3- Decoding Using First Lookup Table and Sorted List Consider a third worked example of decoding a prefix coded bitstream according to the methods discussed above. The purpose of this example is to show a scenario where the method proceeds to the third coding operation from the first coding operation. The bitstream to be decoded in this example is 000000 010001. The first 6 bits are obtained from the bitstream, which in this example are 000000. Comparing this to the indexes 510 in the first LUT 500, it is found that 000000 is a NULL code. In this case, the prefix code being decoding is too long to be stored as an index of the first LUT, and so the method proceeds to use the third coding operation to decode the bits and obtain the corresponding symbol. Additional bits are repeatedly obtained from the bitstream, used to supplement the already obtained bits and compared to entries in sorted list 580. When the set of bits 0000 0001 is obtained, it is found that the symbol to be decoded is “f”. As with the above examples, the method diverges at this point depending on if obtaining “f” results in every symbol in a set of symbols being obtained. If obtaining “f” does not result in every symbol in a set of symbols being obtained, then the method proceeds by attempting to decode the next set of bits by using the second coding method. If obtaining T does result in every symbol in a set of symbols being obtained, then the method proceeds by attempting to decode the next set of bits by using the first coding method. For the purpose of this example, let us assume that obtaining the symbol “f” does not result in every symbol in a set of symbols being obtained, and so the method proceeds by obtaining the next 4 undecoded bits and comparing the obtained bits to indexes 550 of the second LUT 540. The next 4 bits are 0001, which on comparison with the indexes 550 of the second LUT 540, is found to decode to “d”. In decoding “d”, all 4 of the obtained bits are decoded, and so the bitstream is advanced by 4 bits. No undecoded bits remain in the bitstream, and so the method reaches a natural conclusion. The above examples show how the methods discussed herein are applied in various circumstances to efficiently decode prefix coded data. It will also be appreciated that the ability to switch between two or three coding operations at need provides a highly versatile method that is suitable for decoding all kinds of prefix data in a faster manner than can be achieved by the cited art. Comparative Example We now discuss a comparative example. In an attempt to increase the speed of prefix decoding, it has been considered that a set of nested lookup tables (LUTs) could be used. According to the nested lookup table approach, several bits are obtained from a bitstream and then used, after optional manipulation, as an index of a lookup table. When a code obtained from a bitstream points to another lookup table, then the next set of bits in the stream is obtained, and the other lookup table is retrieved and searched to find a decoding of the next set of bits. The approach of using nested lookup tables provides some improvement to the speed to decoding prefix codes because multiple bits are retrieved from the bitstream and decoded with one comparison. However, an issue with using nested lookup tables is that searching several lookup tables is computational inefficient due to the need to load and traverse different tables. Further, the nested lookup table approach is still limited to being able to decode one symbol at a time, even if more symbols could be decoded. For example, consider an example where 8 bits are read from a prefix coded bitstream, these being 0101 0101. This could be a 2-bit code, 01, repeated 4 times. However, when entry 0101 0101 is checked in the lookup table, only one decoding of the symbol is returned. Therefore, two bits are decoded rather than the 8 bits that could be decoded. Analogy To further explain the method discussed above, consider an analogy using letters and words in the place of bits and symbols. The analogy uses the specific setting of Huffman coded LCEVC data. However, this does not limit he above disclosure to the specific example of Huffman coded LCEVC data. Rather, the analogy is provided to aid understanding. Huffman decoding an LCEVC stream is a bit like turning this: johnsitsjohnordersfoodpersephonebringsveryverymuchfoodjohneatsithappily Into this: “John sits. John orders food. Persephone brings very very much food. John eats it happily.” These sentences can be seen as a series of mandatory nouns, followed by up to 1 verb, and 0-3 adverbs / adjectives. In other words, the analogy looks like this: John sits = LSB + MSB John orders = LSB + MSB food = LSB Persephone brings very very much = LSB + MSB + RL + RL + RL food = LSB John eats = LSB + MSB it happily = LSB + RL 5 With this analogy available, consider three ways to decode the above. Method 1: Form a dictionary. Then, read one letter at a time until you find a word that’s in the dictionary. We use “john” (all lowercase) as code for “John”, and so on. In other words, in the analogy, the “translation” of “johnsits” is simply “John sits”. Therefore, the 10 dictionary would look like this: brings eats food happily it john much orders persephone sits very brings eats food happily it John much orders Persephone sits very Then, we’d take the full story, and decode it by consuming one bit at a time, as below: Encoded stream / story Candidate word Decoded stream / story § johnsitsjohnordersfoodpersephon... j ohnsitsjohnordersfoodpersephone... jo -----------------------------------___...................---------------------; hnsitsjohnordersfoodpersephoneb... joh J nsitsjohnordersfoodpersephonebr... john John_____ § sitsjohnordersfoodpersephonebri... s John_____ § itsjohnordersfoodpersephonebrin... si John____ tsjohnordersfoodpersephonebring... sit John____ sjohnordersfoodpersephonebrings... sits John sits. johnordersfoodpersephonebringsv... j John sits. This is non-optimal because the dictionary can be very large, and because the method performs 1 search per bit. Even if the method binary-searches through the dictionary, a large number of searches are required. Method 2: Form a lookup table. Lookup tables (LUTs) are a popular optimisation in general. A LUT is, generally speaking, a list of “answers”, listed in order. Generally, a lookup table will specify a maximum code length that it can handle. For example, we might stipulate that 10 codes longer than 8 letters (such as “persephone”) are handled separately, so that our LUT can stay nice and small. The LUT would look a bit like the dictionary from before, but it will handle any possible combination of 8 letters. For example: aaaaa aaa brinqr zz bring saa bring sab bring szz bringt aa eatrz zzz eatsa aaa [nothi ng] [nothi ng] brings brings bring s [nothi ng] [nothi ng] eats In addition, for example, some special case to handle longer codes. For simplicity, let’s suppose that longer codes default to Method 1, so we have a simple back-up dictionary like this: persephone Persephone In other words, the method considers of every combination of 8 bits, and then defines it based on the word that it starts with. At this juncture we note that this analogy is slightly inaccurate in two ways. Firstly, we’d actually need THREE lookup tables: one for nouns, one for verbs, and one for adverbs and adjectives. This has been ignored that for simplicity. Secondly, as question may be “why doesn’t bringtaa get translated as ‘bring’, seeing as ‘bring’ is also a word?” The answer here is that Huffman codes never start with any other Huffman codes; in that sense, an English dictionary is not like a Huffman dictionary. Anyway, armed with this lookup table, the method attempts to decode 8 letters at a time. This drastically speeds up the decode for 2 reasons. Firstly, the method can decode up to 8 letters at a time (although in practice, you’ll only decode 6 letters for “brings”, 4 letters for “eats”, and so on). Secondly, lookups in the lookup table are a single operation (0(1)), whereas a binary search is typically log2(N) operations, where N is the number of words (O(logN)). Here's what that looks like. Emphasis has been added to rows where the dictionary is used. The other lines are decoded using the lookup table. Encoded stream / story Candidate Length Decoded stream / story johnsitsjohnordersfoodpersephon... johnsits 4 John___ sitsjohnordersfoodpersephonebri... sitsjohn 4 John sits. johnordersfoodpersephonebringsv... johnorde 4 John sits. John ordersfoodpersephonebringsveryv... foodpersephonebringsveryverymuc... ordersfo foodpers 6 4 John sits. John orders ... sits. John orders food. persephonebringsveryverymuchfoo... persepho 8... ... sits. John orders food. nebringsveryverymuchfoodjohneat... persephon +1 ... sits. John orders food. ebringsveryverymuchfoodjohneats... persephone +1 food. Persephone______ bringsveryverymuchfoodjohneatsi... And so on. bringsve 5 ... food. Persephone brings As you can see, the method gets through the stream much faster, and only get stuck on very long codes. This is fine, because Huffman coding guarantees that 5 the longest codes are also the rarest. However, further improvements can be made Method 3: Form a multi-lookup table. The key to this method is the realisation that any set of N bits will sometimes contain multiple codes. In fact, in our first step above, the first 8 letters were “johnsits” and yet we only decoded “John”, rather than the full “John sits”. This situation is not that common, when you think of all possible combinations of 8 letters (or 8 bits). However, it is quite common in a Huffman-encoded stream, because the shortest codes are the most common. In particular, recall the earlier breakdown of our story into noun-based phrases: John sits = LSB + MSB John orders = LSB + MSB food = LSB Persephone brings very very much = LSB + MSB + RL + RL +RL food = LSB John eats = LSB + MSB it happily = LSB + RL Method 2 sought to decode whole words at a time. Method 3 tries to decode whole phrases at a time. This would typically require a larger lookup table, so consider a 9-letter lookup table. We won’t attempt to list every possible combination, but as before, there are several entries (like aaaaaaaaaa, i.e.10 “a”s) which contain nothing. However, our LUT will contain, among other things: johneatsa - johneatsz = John eats (full phrase) ithappily = it happily (full phrase) As well as combinations that are possible (but may not actually be used) such as foodsitsa - foodsitsz = food sits (unused full phrase) iteatsaaa - iteatszzz = it eats (unused, possibly incomplete phrase) Lastly, it will NOT contain the following invalid noun phrases: eatsfooda - eatsfoodz: wrong, because it starts with a verb. sitssitsa - sitssitsz: wrong, because verbs cannot follow other verbs. and so on. Additionally, recall that, in Method 2, the method needed some fallback-case for 5 codes that were too long, and we simply used Method 1 (which was easier to use, because it now had a 1-word dictionary). Likewise, in Method 3, we can use Method 2 as our fallback (but note that it will be made easier because “john” never requires a back-up entry: it’s always present in our multi-LUT). Our Method 2 list should get MOST of the more challenging 10 cases, leaving a tiny number of cases to the Method 3 list. Encoded stream / story Candidate Length § Decoded | stream / story johnsitsjohnordersfoodpersephon... johnsitsj n 4+4 : John sits. : johnordersfoodpersephonebringsv... johnorder 4+? ] John sits. ] § John________ § ordersfoodpersephonebringsveryv... ordersfo n 6 § John sits. John § § orders § foodpersephonebringsveryverymuc... foodperse 0 4 L.. sits. John orders j § food. § persephonebringsveryverymuchfoo... persephon 9... L.. sits. John orders § | food. | ebringsveryverymuchfoodjohneats... persephone + 1 food. Persephone_____ bringsveryverymuchfoodjohneatsi... bringsve 6 Persephone brings_____ veryverymuchfoodjohneatsithappi... veryvery 4 brings very verymuchfoodjohneatsithappily verymuch 4 ... brings very very muchfoodjohneatsithappily muchfood 0 4 ... brings very very much foodjohneatsithappily foodjohne 0 4 ... very very much food. johneatsithappily johneatsi 0 4+4 ... much food. John eats ithappily ithappily 0 2+7 ... John eats it happily. In other words: the methods attempts to decode one phrase at a time. If the phrase is too big, the method tries to decode one word at a time. If a word is too big, the method attempts to decode one letter at a time. The a symbol has been used to 5 indicate when we successfully finish a whole phrase. Linking the analogy to reality Here are the main ways that the real algorithm is slightly different from the analogy discussed above. 1. In the real algorithm, the LSB, MSB, and RL have separate Huffman encodings. To put it another way, it’s like they’re in different languages. It’s like decoding “johnmistmeta”, meaning “John (john) misses (“mist”, in Dutch) the target (“meta”, in Portuguese)”. This is why our Method 3 LUT always starts on the noun: if you start on the verb, or on an adjective, you’ll see “mist” and think it’s the English noun, when it’s actually the Dutch verb, or see “meta” and think it’s the English adjective, when it’s actually the Portuguese noun. Likewise, in the real algorithm, our Method 3 LUT always starts with the LSB, because many MSB and RL codes will also be LSB codes (in fact, the number “1” is very common in all three codes). 2. In the real code, the LSB will tell you whether it’s followed be an MSB or an RL, and the MSB and RL will tell you whether they’re followed by an RL. It’s a bit like if the code actually said: john1sits.john1orders.food.persephone1brings2very2very2much.food. These details were omitted hitherto for the sake of simplicity. Methods and processes described herein can be implemented by a decoder device comprising suitable components for performing steps of the methods described above. For example, the decoder may comprise a processor and a storage module. The storage module is suitable for storing the data structures discussed above, for example the first LUT 500, the second LUT 540 and the sorted list 580. Storage module may also be used to store prefix coded data and symbols the prefix decoding has been performed. The methods and processes described above can be implemented as code (e.g., software code). The decoder discussed above may be implemented in hardware or software as is well-known in the art. For example, hardware acceleration using a specifically designed Field Programmable Gate Array (FPGA) may provide certain efficiencies. For completeness, such code can be stored on one or more computer-readable media, which may include any device or medium that can store code and / or data for use by a computer system. When a computer system reads and executes the code stored on a computer-readable medium, the computer system performs the methods 5 and processes embodied as code stored within the computer-readable storage medium. In certain embodiments, one or more of the steps of the methods and processes described herein can be performed by a processor (e.g., a processor of a computer system or data storage system). In summary, a method of efficiently decoding a prefix coded bitstream has been 10 provided, wherein a set of more than 2 bits are substantially simultaneously decoded using a first coding operation to obtain at least some symbols in a set of symbols. If only some symbols, but not all symbols in a set of symbols is obtained, then a second coding operation is used to obtain the rest of the symbols in the set of symbols, whereas if every symbol in the set of symbols is obtained, then the next set of bits are 15 obtained. The first and second coding operations can make use of first and second lookup tables to provide multiple decoding speeds, which ultimately provides faster prefix decoding.

Claims

1. A method of decoding a prefix coded bitstream, the bitstream comprising prefix coded symbols, the symbols being of multiple different types, the method comprising:obtaining a first set of N bits of a prefix coded bitstream, wherein N >2, wherein the first set of N bits contains at least part of a prefix code,wherein a prefix code is associated with a symbol,wherein a plurality of symbols form a set of symbols, the set of symbols comprising a leading symbol of a first type and at least one symbol of a second type, the second type different to the first type,wherein each symbol indicates a type of the following symbol,wherein a final symbol in the set of symbols indicates that the following symbol is of the first type;performing a first coding operation on the first set of N bits, wherein the first coding operation associates multiple prefix codes with multiple symbols, whereinif the first coding operation obtains the leading symbol and final symbol in the set of symbols, then the method further comprises:obtaining a second set of N bits of the prefix coded stream, wherein the second set of N bits includes any undecoded bits of the first set of N bits;if the first coding operation does not obtain the final symbol in the set of symbols, then the method further comprises:iteratively performing a second coding operation until the final symbol in the set of symbols is obtained, wherein the second coding operation comprises obtaining a first set of P bits of the prefix coded stream, wherein 1 <P <N, wherein the first set of P bits includes any undecoded bits of the first N bits, wherein the second coding operation associates one prefix code in the first set of P bits with one symbol.

2. A method according to claim 1, wherein the first coding operation comprises:comparing the first set of N bits to indexes in a first lookup table, LUT, wherein the first LUT associates multiple prefix codes with multiple symbols, and either:matching the first set of N bits to a first index in the first LUT, wherein an entry in the first LUT corresponding to the first index comprises a decoding of the N bits; ordetermining that the first set of N bits do not match any index in the first LUT;wherein when the N bits match the first index, the method further comprises:decoding M bits of the N bits based on an entry in the first LUT corresponding to the first index to obtain a decoding of the M bits, wherein M <N, wherein the M bits represent at least two symbols in the set of symbols, and a bit of the M bits indicates a type of the following symbol in the prefix coded bitstream;determining, based on the type of the following symbol, whether the first symbol and final symbol in the set of symbols has been decoded, whereinif the leading symbol and the final symbol in the set of symbols has been decoded, then the method comprises the obtaining a second set of N bits of the Huffman coded stream, andif the final symbol in the set of symbols has not been decoded, then the method further comprises the iteratively performing a second coding operation.

3. A method according to claim 2, wherein when the first set of N bits do not match any index in the first LUT, the method further comprises:performing a third coding operation, wherein the third coding operation comprises:obtaining one or more additional bits from the prefix coded stream;comparing the obtained bits and the one or more additional bits to entries in a sorted list; andeither:matching the obtained bits and the one or more additional bits to an entry in the sorted list, anddecoding the obtained bits and the one or more additional bits based on the entry in the sorted list, wherein the obtained bits and one or more additional bits represent one symbol in the set of symbols;or:determining that the obtained bits and the one or more additional bits do not match any entry in the sorted list; andobtaining one or more further additional bits from the prefix coded stream.

4. A method according to claim 3, wherein if the third coding operation decodes the final symbol in the set of symbols, then the method further comprises: the obtaining the second set of N bits of the prefix coded stream.

5. A method according to any one of claims 3 to 4, wherein if the third coding operation does not decode the final symbol in the set of symbols, then the method further comprises:performing the second coding operation.

6. A method according to any preceding claim, wherein the second coding operation comprises:comparing the first set of P bits to indexes in a second lookup table, LUT, wherein indexes of the second LUT comprise fewer bits than indexes in the first LUT, wherein the second LUT associates one prefix code with one symbol; and either:matching the first set of P bits to a first index in the second LUT, wherein an entry in the second LUT corresponding to the first index comprises a decoding of the P bits;or:determining that the first set of P bits do not match any index in the second LUT;when the P bits match the first index in the second LUT, the method further comprises:decoding Q bits of the P bits based on the entry in the second LUT corresponding to the first index in the second LUT to obtain a decoding of the Q bits, wherein Q is less than or equal to P,wherein the Q bits represent one symbol in the set of symbols, and a bit of the Q bits indicates a type of the following symbol in the prefix coded bitstream;determining, based on the type of the following symbol, whether the final symbol in the set of symbols has been decoded, whereinif the final symbol in the set of symbols has been decoded, then the method comprises the obtaining a second set of N bits of the prefix coded stream, andif the final symbol in the set of symbols has not been decoded, then the method comprises obtaining a second set of P bits, wherein the second set of P bits comprises any undecoded bits in the first set of P bits.

7. A method according to claim 6, wherein when the first set of P bits do not match any index in the second LUT, the method further comprises:performing a third coding operation.

8. A method according to any preceding claim, wherein prefix codes of symbols of the first type are modified to obtain a modified prefix code, wherein the modifying comprises:encoding a number of leading zeros of a prefix code as L leading bits of the modified prefix code.

9. A method according to any preceding claim wherein the prefix coded bitstream is decoded to generate run-length encoded symbols.

10. A method according to claim 9 further comprising decoding the run-length encoded symbols to generate sparse data.

11. A method according to claim 10 wherein the sparse data comprises residual data.

12. A method according to claim 11 wherein the residual data comprises LCEVC residual data.

13. A method according to claims 8 and 12, wherein L = 414. A method according to claim 12, wherein N = 12.

15. A method according to claims 6 or 7 and 12, wherein P = 10.

16. A method according to any of claims 13 to 15, wherein the set of symbolscomprises three symbols.

17. A method according to claim 16 wherein the three symbols comprise the leading symbol of the first type, one symbol of the second type, and one symbol of a third type, the third type of symbol being different to the first type of symbol and second type of symbol.

18. A method according to claim 16, wherein the leading symbol has the first type, and the two symbols following the leading symbol have the second type.

19. A method according to any preceding claim wherein the prefix coded bitstream comprises a Huffman coded bitstream.

20. A decoder comprising a processor, the processor being configured to perform a Huffman coded bitstream using a method according to any preceding claim.

21. A computer readable medium comprising instructions, which when executed by a processor, cause the processor to perform a method according to any of claims 1 to 19.

Citation Information

Patent Citations

  • Circuitry for decoding huffman codes

    CA2126551A1

  • Entropy coding grouping method and system during display interface compression

    JP2020017956A