mirror of
https://github.com/IllusionMan1212/avif-odin.git
synced 2026-10-24 10:12:28 +00:00
OBU WIP
This commit is contained in:
@@ -7,7 +7,7 @@ import "core:encoding/endian"
|
|||||||
import "core:io"
|
import "core:io"
|
||||||
import "core:strings"
|
import "core:strings"
|
||||||
|
|
||||||
Error :: image.Error
|
//Error :: image.Error
|
||||||
//Image :: image.Image
|
//Image :: image.Image
|
||||||
Options :: image.Options
|
Options :: image.Options
|
||||||
|
|
||||||
@@ -130,14 +130,14 @@ read_box :: proc(img: ^Image, reader: ^Reader) -> (err: io.Error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// if the Box has a size 0 then it's the last Box, parse it and return EOF
|
// if the Box has a size 0 then it's the last Box, parse it and return EOF
|
||||||
if reader.size == 0 {
|
if reader.box.size == 0 {
|
||||||
err = .EOF
|
err = .EOF
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.println("box size:", reader.size)
|
fmt.println("box size:", reader.box.size)
|
||||||
fmt.println("type:", reader.type)
|
fmt.println("type:", reader.box.type)
|
||||||
|
|
||||||
#partial switch reader.type {
|
#partial switch reader.box.type {
|
||||||
case .FTYP:
|
case .FTYP:
|
||||||
read_ftyp(img, reader)
|
read_ftyp(img, reader)
|
||||||
case .META:
|
case .META:
|
||||||
@@ -164,6 +164,8 @@ read_box :: proc(img: ^Image, reader: ^Reader) -> (err: io.Error) {
|
|||||||
read_colr(reader)
|
read_colr(reader)
|
||||||
case .IPMA:
|
case .IPMA:
|
||||||
read_ipma(reader)
|
read_ipma(reader)
|
||||||
|
case .MDAT:
|
||||||
|
read_mdat(reader)
|
||||||
case:
|
case:
|
||||||
// Skip unknown boxes
|
// Skip unknown boxes
|
||||||
skip_box(reader)
|
skip_box(reader)
|
||||||
@@ -172,6 +174,15 @@ read_box :: proc(img: ^Image, reader: ^Reader) -> (err: io.Error) {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@(private)
|
||||||
|
read_mdat :: proc(reader: ^Reader) {
|
||||||
|
// TODO:
|
||||||
|
read_obu(reader)
|
||||||
|
read_obu(reader)
|
||||||
|
read_obu(reader)
|
||||||
|
read_obu(reader)
|
||||||
|
}
|
||||||
|
|
||||||
@(private)
|
@(private)
|
||||||
read_ipma :: proc(reader: ^Reader) {
|
read_ipma :: proc(reader: ^Reader) {
|
||||||
vaf, _ := read_bitfield(reader, VersionAndFlags)
|
vaf, _ := read_bitfield(reader, VersionAndFlags)
|
||||||
|
|||||||
@@ -3,12 +3,14 @@ package avif
|
|||||||
import "core:encoding/endian"
|
import "core:encoding/endian"
|
||||||
import "core:fmt"
|
import "core:fmt"
|
||||||
import "core:io"
|
import "core:io"
|
||||||
|
import "core:math"
|
||||||
|
import "core:image"
|
||||||
import "core:strings"
|
import "core:strings"
|
||||||
import "core:unicode/utf8"
|
import "core:unicode/utf8"
|
||||||
|
|
||||||
BOX_HEADER_SIZE :: 8 // 4 for box size, 4 for box type
|
BOX_HEADER_SIZE :: 8 // 4 for box size, 4 for box type
|
||||||
|
|
||||||
_BoxError :: enum {
|
BoxError :: enum {
|
||||||
ReadExceedsBox,
|
ReadExceedsBox,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,125 +35,151 @@ BoxType :: enum u32 {
|
|||||||
CLLI = 'c' << 24 | 'l' << 16 | 'l' << 8 | 'i', // Content Light Level Info
|
CLLI = 'c' << 24 | 'l' << 16 | 'l' << 8 | 'i', // Content Light Level Info
|
||||||
}
|
}
|
||||||
|
|
||||||
BoxError :: union {
|
Error :: union {
|
||||||
io.Error,
|
io.Error,
|
||||||
_BoxError,
|
BoxError,
|
||||||
|
OBUError,
|
||||||
|
image.General_Image_Error,
|
||||||
}
|
}
|
||||||
|
|
||||||
Box :: struct {
|
Box :: struct {
|
||||||
size: u32,
|
size: u32,
|
||||||
type: BoxType,
|
type: BoxType,
|
||||||
|
pos: i64,
|
||||||
}
|
}
|
||||||
|
|
||||||
Reader :: struct {
|
Reader :: struct {
|
||||||
using current_box: Box,
|
box: Box,
|
||||||
s: []byte, // read-only buffer
|
s: []byte, // read-only buffer
|
||||||
i: i64, // current reading index
|
i: i64, // current reading index
|
||||||
box_pos: i64, // Byte index for the Box
|
bits_read_in_byte: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
reader_init :: proc(r: ^Reader, s: []byte) {
|
reader_init :: proc(r: ^Reader, s: []byte) {
|
||||||
r.s = s
|
r.s = s
|
||||||
r.i = 0
|
r.i = 0
|
||||||
r.box_pos = 0
|
r.box.pos = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
read_header :: proc(r: ^Reader) -> (err: BoxError) {
|
read_header :: proc(r: ^Reader) -> (err: Error) {
|
||||||
r.box_pos = 0
|
r.box.pos = 0
|
||||||
r.size = read_u32be(r) or_return
|
r.box.size = read_u32be(r) or_return
|
||||||
type := read_u32be(r) or_return
|
type := read_u32be(r) or_return
|
||||||
r.type = transmute(BoxType)type
|
r.box.type = transmute(BoxType)type
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
read_byte :: proc(r: ^Reader) -> (byte, BoxError) {
|
read_bit :: proc(r: ^Reader) -> (bit: byte, err: Error) {
|
||||||
if r.i >= i64(len(r.s)) {
|
if r.i >= i64(len(r.s)) {
|
||||||
return 0, .EOF
|
return 0, .EOF
|
||||||
}
|
}
|
||||||
if r.box_pos >= i64(r.size) {
|
if r.box.size != 0 && r.box.pos >= i64(r.box.size) {
|
||||||
|
return 0, .ReadExceedsBox
|
||||||
|
}
|
||||||
|
byte := r.s[r.i]
|
||||||
|
|
||||||
|
// Get the bit that's after however many bits read starting from the MSB in the byte
|
||||||
|
bits := 8 - (r.bits_read_in_byte + 1)
|
||||||
|
b := (r.s[r.i:r.i+1][0] & auto_cast math.pow2_f32(bits)) >> bits
|
||||||
|
r.bits_read_in_byte += 1
|
||||||
|
|
||||||
|
if r.bits_read_in_byte == 8 {
|
||||||
|
r.i += 1
|
||||||
|
r.box.pos += 1
|
||||||
|
r.bits_read_in_byte = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
return b, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
read_byte :: proc(r: ^Reader) -> (byte, Error) {
|
||||||
|
if r.i >= i64(len(r.s)) {
|
||||||
|
return 0, .EOF
|
||||||
|
}
|
||||||
|
if r.box.size != 0 && r.box.pos >= i64(r.box.size) {
|
||||||
return 0, .ReadExceedsBox
|
return 0, .ReadExceedsBox
|
||||||
}
|
}
|
||||||
b := r.s[r.i]
|
b := r.s[r.i]
|
||||||
r.i += 1
|
r.i += 1
|
||||||
r.box_pos += 1
|
r.box.pos += 1
|
||||||
return b, nil
|
return b, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
read_u16be :: proc(r: ^Reader) -> (u16, BoxError) {
|
read_u16be :: proc(r: ^Reader) -> (u16, Error) {
|
||||||
if r.i >= i64(len(r.s)) {
|
if r.i >= i64(len(r.s)) {
|
||||||
return 0, .EOF
|
return 0, .EOF
|
||||||
}
|
}
|
||||||
if r.box_pos + 2 > i64(r.size) {
|
if r.box.size != 0 && r.box.pos + 2 > i64(r.box.size) {
|
||||||
return 0, .ReadExceedsBox
|
return 0, .ReadExceedsBox
|
||||||
}
|
}
|
||||||
b := endian.unchecked_get_u16be(r.s[r.i:])
|
b := endian.unchecked_get_u16be(r.s[r.i:])
|
||||||
r.i += 2
|
r.i += 2
|
||||||
r.box_pos += 2
|
r.box.pos += 2
|
||||||
return b, nil
|
return b, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
read_u32be :: proc(r: ^Reader) -> (u32, BoxError) {
|
read_u32be :: proc(r: ^Reader) -> (u32, Error) {
|
||||||
if r.i >= i64(len(r.s)) {
|
if r.i >= i64(len(r.s)) {
|
||||||
return 0, .EOF
|
return 0, .EOF
|
||||||
}
|
}
|
||||||
if r.size != 0 && r.box_pos + 4 > i64(r.size) {
|
if r.box.size != 0 && r.box.pos + 4 > i64(r.box.size) {
|
||||||
return 0, .ReadExceedsBox
|
return 0, .ReadExceedsBox
|
||||||
}
|
}
|
||||||
b := endian.unchecked_get_u32be(r.s[r.i:])
|
b := endian.unchecked_get_u32be(r.s[r.i:])
|
||||||
r.i += 4
|
r.i += 4
|
||||||
r.box_pos += 4
|
r.box.pos += 4
|
||||||
return b, nil
|
return b, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
read_u64be :: proc(r: ^Reader) -> (u64, BoxError) {
|
read_u64be :: proc(r: ^Reader) -> (u64, Error) {
|
||||||
if r.i >= i64(len(r.s)) {
|
if r.i >= i64(len(r.s)) {
|
||||||
return 0, .EOF
|
return 0, .EOF
|
||||||
}
|
}
|
||||||
if r.size != 0 && r.box_pos + 8 > i64(r.size) {
|
if r.box.size != 0 && r.box.pos + 8 > i64(r.box.size) {
|
||||||
return 0, .ReadExceedsBox
|
return 0, .ReadExceedsBox
|
||||||
}
|
}
|
||||||
b := endian.unchecked_get_u64be(r.s[r.i:])
|
b := endian.unchecked_get_u64be(r.s[r.i:])
|
||||||
r.i += 8
|
r.i += 8
|
||||||
r.box_pos += 8
|
r.box.pos += 8
|
||||||
return b, nil
|
return b, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
read_slice :: proc(r: ^Reader, s: []byte) -> (n: int, err: BoxError) {
|
read_slice :: proc(r: ^Reader, s: []byte) -> (n: int, err: Error) {
|
||||||
if r.i >= i64(len(r.s)) {
|
if r.i >= i64(len(r.s)) {
|
||||||
return 0, .EOF
|
return 0, .EOF
|
||||||
}
|
}
|
||||||
n = copy(s, r.s[r.i:])
|
n = copy(s, r.s[r.i:])
|
||||||
if r.box_pos + i64(n) > i64(r.size) {
|
if r.box.pos + i64(n) > i64(r.box.size) {
|
||||||
return 0, .ReadExceedsBox
|
return 0, .ReadExceedsBox
|
||||||
}
|
}
|
||||||
r.i += i64(n)
|
r.i += i64(n)
|
||||||
r.box_pos += i64(n)
|
r.box.pos += i64(n)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
read_rune :: proc(r: ^Reader) -> (ch: rune, size: int, err: BoxError) {
|
read_rune :: proc(r: ^Reader) -> (ch: rune, size: int, err: Error) {
|
||||||
if r.i >= i64(len(r.s)) {
|
if r.i >= i64(len(r.s)) {
|
||||||
return 0, 0, .EOF
|
return 0, 0, .EOF
|
||||||
}
|
}
|
||||||
if c := r.s[r.i]; c < utf8.RUNE_SELF {
|
if c := r.s[r.i]; c < utf8.RUNE_SELF {
|
||||||
if r.box_pos >= i64(r.size) {
|
if r.box.pos >= i64(r.box.size) {
|
||||||
return 0, 0, .ReadExceedsBox
|
return 0, 0, .ReadExceedsBox
|
||||||
}
|
}
|
||||||
r.i += 1
|
r.i += 1
|
||||||
r.box_pos += 1
|
r.box.pos += 1
|
||||||
return rune(c), 1, nil
|
return rune(c), 1, nil
|
||||||
}
|
}
|
||||||
ch, size = utf8.decode_rune(r.s[r.i:])
|
ch, size = utf8.decode_rune(r.s[r.i:])
|
||||||
if r.box_pos + i64(size) > i64(r.size) {
|
if r.box.pos + i64(size) > i64(r.box.size) {
|
||||||
return 0, 0, .ReadExceedsBox
|
return 0, 0, .ReadExceedsBox
|
||||||
}
|
}
|
||||||
r.i += i64(size)
|
r.i += i64(size)
|
||||||
r.box_pos += i64(size)
|
r.box.pos += i64(size)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
read_string :: proc(r: ^Reader) -> (str: string, err: BoxError) {
|
read_string :: proc(r: ^Reader) -> (str: string, err: Error) {
|
||||||
if r.i >= i64(len(r.s)) {
|
if r.i >= i64(len(r.s)) {
|
||||||
return "", .EOF
|
return "", .EOF
|
||||||
}
|
}
|
||||||
@@ -173,32 +201,39 @@ read_string :: proc(r: ^Reader) -> (str: string, err: BoxError) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@(private = "file")
|
@(private = "file")
|
||||||
read_bitfield_u32 :: proc(r: ^Reader, $T: typeid) -> (T, BoxError) where size_of(T) == 4 {
|
read_bitfield_u32 :: proc(r: ^Reader, $T: typeid) -> (T, Error) where size_of(T) == 4 {
|
||||||
b, err := read_u32be(r)
|
b, err := read_u32be(r)
|
||||||
return T(b), err
|
return T(b), err
|
||||||
}
|
}
|
||||||
|
|
||||||
@(private = "file")
|
@(private = "file")
|
||||||
read_bitfield_u16 :: proc(r: ^Reader, $T: typeid) -> (T, BoxError) where size_of(T) == 2 {
|
read_bitfield_u16 :: proc(r: ^Reader, $T: typeid) -> (T, Error) where size_of(T) == 2 {
|
||||||
b, err := read_u16be(r)
|
b, err := read_u16be(r)
|
||||||
return T(b), err
|
return T(b), err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@(private = "file")
|
||||||
|
read_bitfield_u8 :: proc(r: ^Reader, $T: typeid) -> (T, Error) where size_of(T) == 1 {
|
||||||
|
b, err := read_byte(r)
|
||||||
|
return T(b), err
|
||||||
|
}
|
||||||
|
|
||||||
read_bitfield :: proc {
|
read_bitfield :: proc {
|
||||||
|
read_bitfield_u8,
|
||||||
read_bitfield_u16,
|
read_bitfield_u16,
|
||||||
read_bitfield_u32,
|
read_bitfield_u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
skip_box :: proc(r: ^Reader) {
|
skip_box :: proc(r: ^Reader) {
|
||||||
fmt.printfln("SKIPPED! %v with size %d", r.type, r.size)
|
fmt.printfln("SKIPPED! %v with size %d", r.box.type, r.box.size)
|
||||||
reader_seek(r, auto_cast r.size - BOX_HEADER_SIZE, .Current)
|
reader_seek(r, auto_cast r.box.size - BOX_HEADER_SIZE, .Current)
|
||||||
}
|
}
|
||||||
|
|
||||||
remaining_box_size :: proc(r: ^Reader) -> i64 {
|
remaining_box_size :: proc(r: ^Reader) -> i64 {
|
||||||
return i64(r.size) - r.box_pos
|
return i64(r.box.size) - r.box.pos
|
||||||
}
|
}
|
||||||
|
|
||||||
reader_seek :: proc(r: ^Reader, offset: i64, whence: io.Seek_From) -> (i64, BoxError) {
|
reader_seek :: proc(r: ^Reader, offset: i64, whence: io.Seek_From) -> (i64, Error) {
|
||||||
abs: i64
|
abs: i64
|
||||||
switch whence {
|
switch whence {
|
||||||
case .Start:
|
case .Start:
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package avif
|
package avif
|
||||||
|
|
||||||
|
import "core:fmt"
|
||||||
import "core:io"
|
import "core:io"
|
||||||
|
|
||||||
OBUType :: enum u8 {
|
OBUType :: enum u8 {
|
||||||
@@ -14,17 +15,76 @@ OBUType :: enum u8 {
|
|||||||
PADDING = 15,
|
PADDING = 15,
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: write a nice bitstream reader
|
OBUError :: enum {
|
||||||
// ??? Still don't know how I want this to work
|
ReservedOBU,
|
||||||
BitstreamReader :: struct {
|
}
|
||||||
data: []byte,
|
|
||||||
pos: i64, // Number of bits read from the data slice
|
ColorPrimaries :: enum u8 {
|
||||||
|
BT_709 = 1,
|
||||||
|
UNSPECIFIED = 2,
|
||||||
|
BT_470_M = 4,
|
||||||
|
BT_470_B_G = 5,
|
||||||
|
BT_601 = 6,
|
||||||
|
SMPTE_240 = 7,
|
||||||
|
GENERIC_FILM = 8,
|
||||||
|
BT_2020 = 9,
|
||||||
|
XYZ = 10,
|
||||||
|
SMPTE_431 = 11,
|
||||||
|
SMPTE_432 = 12,
|
||||||
|
EBU_3213 = 22,
|
||||||
|
}
|
||||||
|
|
||||||
|
TransferCharacteristic :: enum u8 {
|
||||||
|
RESERVED_0 = 0,
|
||||||
|
BT_709 = 1,
|
||||||
|
UNSPECIFIED = 2,
|
||||||
|
RESERVED_3 = 3,
|
||||||
|
BT_470_M = 4,
|
||||||
|
BT_470_B_G = 5,
|
||||||
|
BT_601 = 6,
|
||||||
|
SMPTE_240 = 7,
|
||||||
|
LINEAR = 8,
|
||||||
|
LOG_100 = 9,
|
||||||
|
LOG_100_SQRT10 = 10,
|
||||||
|
IEC_61966 = 11,
|
||||||
|
BT_1361 = 12,
|
||||||
|
SRGB = 13,
|
||||||
|
BT_2020_10_BIT = 14,
|
||||||
|
BT_2020_12_BIT = 15,
|
||||||
|
SMPTE_2084 = 16,
|
||||||
|
SMPTE_428 = 17,
|
||||||
|
HLG = 18,
|
||||||
|
}
|
||||||
|
|
||||||
|
MatrixCoefficient :: enum u8 {
|
||||||
|
IDENTITY = 0,
|
||||||
|
BT_709 = 1,
|
||||||
|
UNSPECIFIED = 2,
|
||||||
|
RESERVED_3 = 3,
|
||||||
|
FCC = 4,
|
||||||
|
BT_470_B_G = 5,
|
||||||
|
BT_601 = 6,
|
||||||
|
SMPTE_240 = 7,
|
||||||
|
SMPTE_YCGCO = 8,
|
||||||
|
BT_2020_NCL = 9,
|
||||||
|
BT_2020_CL = 10,
|
||||||
|
SMPTE_2085 = 11,
|
||||||
|
CHROMAT_NCL = 12,
|
||||||
|
CHROMAT_CL = 13,
|
||||||
|
ICTCP = 14,
|
||||||
|
}
|
||||||
|
|
||||||
|
ChromeSamplePosition :: enum u8 {
|
||||||
|
UNKNOWN = 0,
|
||||||
|
VERTICAL = 1,
|
||||||
|
COLOCATED = 2,
|
||||||
|
RESERVED = 3,
|
||||||
}
|
}
|
||||||
|
|
||||||
OBUHeader :: bit_field u8 {
|
OBUHeader :: bit_field u8 {
|
||||||
obu_reserved: u8 | 1,
|
obu_reserved: u8 | 1,
|
||||||
obu_has_size_field: u8 | 1,
|
obu_has_size_field: b8 | 1,
|
||||||
obu_extension_flag: u8 | 1,
|
obu_extension_flag: b8 | 1,
|
||||||
obu_type: OBUType | 4,
|
obu_type: OBUType | 4,
|
||||||
obu_forbidden_bit: u8 | 1,
|
obu_forbidden_bit: u8 | 1,
|
||||||
}
|
}
|
||||||
@@ -35,29 +95,361 @@ OBUExtensionHeader :: bit_field u8 {
|
|||||||
temporal_id: u8 | 3,
|
temporal_id: u8 | 3,
|
||||||
}
|
}
|
||||||
|
|
||||||
read_bit :: proc() -> b8 {
|
read_obu :: proc(r: ^Reader) -> (err: Error) {
|
||||||
// TODO: idfk
|
header := read_bitfield(r, OBUHeader) or_return
|
||||||
// This should read a single bit from the bitstream and advance the bitstream position by 1
|
size: u64
|
||||||
|
|
||||||
return false
|
fmt.println(header)
|
||||||
|
|
||||||
|
if header.obu_extension_flag {
|
||||||
|
ext_header := read_bitfield(r, OBUExtensionHeader) or_return
|
||||||
|
|
||||||
|
fmt.println(ext_header)
|
||||||
|
}
|
||||||
|
|
||||||
|
if header.obu_has_size_field {
|
||||||
|
size = leb128(r)
|
||||||
|
} else {
|
||||||
|
// TODO: is this correct ???
|
||||||
|
// The spec is NOT clear about wtf sz is, so I assume it's the box size without the header.
|
||||||
|
// It's also possibly the remaining box size, we'll have to check how other decoders do it.
|
||||||
|
size = u64(r.box.size - BOX_HEADER_SIZE - 1 - u32(header.obu_extension_flag))
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: get bit position
|
||||||
|
//start_pos := get_position()
|
||||||
|
|
||||||
|
//// TODO:
|
||||||
|
//if header.obu_type != .SEQUENCE_HEADER && header.obu_type != .TEMPORAL_DELIMITER && OperatingPointIdc != 0 && header.obu_extension_flag == 1 {
|
||||||
|
// in_temporal_layer := (OperatingPointIdc >> temporal_id) & 1
|
||||||
|
// in_spatial_layer := (OperatingPointIdc >> (spatial_id + 8)) & 1
|
||||||
|
|
||||||
|
// if in_temporal_layer == 0 || in_spatial_layer == 0 {
|
||||||
|
// drop_obu()
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
|
fmt.println("OBU size:", size)
|
||||||
|
|
||||||
|
if header.obu_type != .SEQUENCE_HEADER &&
|
||||||
|
header.obu_type != .TEMPORAL_DELIMITER &&
|
||||||
|
header.obu_type != .FRAME_HEADER &&
|
||||||
|
header.obu_type != .TILE_GROUP &&
|
||||||
|
header.obu_type != .METADATA &&
|
||||||
|
header.obu_type != .FRAME &&
|
||||||
|
header.obu_type != .REDUNDANT_FRAME_HEADER &&
|
||||||
|
header.obu_type != .TILE_LIST &&
|
||||||
|
header.obu_type != .PADDING {
|
||||||
|
return .ReservedOBU
|
||||||
|
}
|
||||||
|
|
||||||
|
#partial switch header.obu_type {
|
||||||
|
case .TEMPORAL_DELIMITER:
|
||||||
|
// do nothing. the temporal OBU has an empty payload
|
||||||
|
case .SEQUENCE_HEADER:
|
||||||
|
parse_sequence_header_obu(r)
|
||||||
|
case .FRAME:
|
||||||
|
// TODO:
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO:
|
||||||
|
//current_pos := get_position()
|
||||||
|
//payload_bits := current_pos - start_pos
|
||||||
|
|
||||||
|
//if size > 0 && header.obu_type != .TILE_GROUP && header.obu_type != .TILE_LIST && header.obu_type != .FRAME {
|
||||||
|
// trailing_bits(size * 8 - payload_bits)
|
||||||
|
//}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
f :: proc(n: int) -> u64 {
|
//timing_info :: proc(r: ^Reader) {
|
||||||
|
// num_units_in_display_tick = f(r, 32)
|
||||||
|
// time_scale = f(r, 32)
|
||||||
|
// equal_picture_interval = f(r, 32)
|
||||||
|
// if equal_picture_interval == 1 {
|
||||||
|
// num_ticks_per_picture_minus_1 = uvlc(r)
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//decoder_model_info :: proc(r: ^Reader) {
|
||||||
|
// buffer_delay_length_minus_1 = f(r, 5)
|
||||||
|
// num_units_in_decoding_tick = f(r, 32)
|
||||||
|
// buffer_removal_time_length_minus_1 = f(r, 5)
|
||||||
|
// frame_presentation_time_length_minus_1 = f(r, 5)
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//operating_parameters_info :: proc(r: ^Reader, op: u8) {
|
||||||
|
// n = buffer_delay_length_minus_1 + 1
|
||||||
|
// decoder_buffer_delay[op] = f(r, n)
|
||||||
|
// encoder_buffer_delay[op] = f(r, n)
|
||||||
|
// low_delay_mode_flag[op] = f(r, 1)
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//color_config :: proc(r: ^Reader) {
|
||||||
|
// high_bitdepth = f(r, 1)
|
||||||
|
//
|
||||||
|
// if seq_profile == 2 && high_bitdepth == 1 {
|
||||||
|
// twelve_bit = f(r, 1)
|
||||||
|
// BitDepth = twelve_bit == 1 ? 12 : 10
|
||||||
|
// } else if seq_profile <= 2 {
|
||||||
|
// BitDepth = high_bitdepth == 1 ? 10 : 8
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if seq_profile == 1 {
|
||||||
|
// mono_chrome = 0
|
||||||
|
// } else {
|
||||||
|
// mono_chrome = f(r, 1)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// num_planes = mono_chrome == 1 ? 1 : 3
|
||||||
|
// color_description_present_flag = f(r, 1)
|
||||||
|
//
|
||||||
|
// if color_description_present_flag == 1 {
|
||||||
|
// color_primaries = auto_cast f(r, 8)
|
||||||
|
// transfer_characteristic = auto_cast f(r, 8)
|
||||||
|
// matrix_coefficients = auto_cast f(r, 8)
|
||||||
|
// } else {
|
||||||
|
// color_primaries = .UNSPECIFIED
|
||||||
|
// transfer_characteristic = .UNSPECIFIED
|
||||||
|
// matrix_coefficients = .UNSPECIFIED
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if mono_chrome == 1 {
|
||||||
|
// color_range = f(r, 1)
|
||||||
|
// subsampling_x = 1
|
||||||
|
// subsampling_y = 1
|
||||||
|
// chroma_sample_position = .UNKNOWN
|
||||||
|
// separate_uv_delta_q = 0
|
||||||
|
// return
|
||||||
|
// } else if color_primaries == .BT_709 && transfer_characteristic == .SRGB && matrix_coefficients == .IDENTITY {
|
||||||
|
// color_range = 1
|
||||||
|
// subsampling_x = 0
|
||||||
|
// subsampling_y = 0
|
||||||
|
// } else {
|
||||||
|
// color_range = f(r, 1)
|
||||||
|
//
|
||||||
|
// if seq_profile == 0 {
|
||||||
|
// subsampling_x = 1
|
||||||
|
// subsampling_y = 1
|
||||||
|
// } else if seq_profile == 1 {
|
||||||
|
// subsampling_x = 0
|
||||||
|
// subsampling_y = 0
|
||||||
|
// } else {
|
||||||
|
// if BitDepth == 12 {
|
||||||
|
// subsampling_x = f(r, 1)
|
||||||
|
//
|
||||||
|
// if subsampling_x == 1 {
|
||||||
|
// subsampling_y = f(r, 1)
|
||||||
|
// } else {
|
||||||
|
// subsampling_y = 0
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// subsampling_x = 1
|
||||||
|
// subsampling_y = 0
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if subsampling_x == 1 && subsampling_y == 1 {
|
||||||
|
// chroma_sample_position = auto_cast f(r, 2)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// separate_uv_delta_q = f(r, 1)
|
||||||
|
//}
|
||||||
|
|
||||||
|
parse_sequence_header_obu :: proc(r: ^Reader) {
|
||||||
|
seq_profile := f(r, 3)
|
||||||
|
still_picture := f(r, 1)
|
||||||
|
reduced_still_picture_header := f(r, 1)
|
||||||
|
|
||||||
|
timing_info_present_flag: u8
|
||||||
|
decoder_model_info_present_flag: u8
|
||||||
|
initial_display_delay_present_flag: u8
|
||||||
|
operating_points_cnt_minus_1: u8
|
||||||
|
|
||||||
|
if reduced_still_picture_header == 1 {
|
||||||
|
// TODO: should these be saved as state ??
|
||||||
|
timing_info_present_flag = 0
|
||||||
|
decoder_model_info_present_flag = 0
|
||||||
|
initial_display_delay_present_flag = 0
|
||||||
|
operating_points_cnt_minus_1 = 0
|
||||||
|
//operating_point_idc[ 0 ] = 0
|
||||||
|
//seq_level_idx[ 0 ]
|
||||||
|
//seq_tier[ 0 ] = 0
|
||||||
|
//decoder_model_present_for_this_op[ 0 ] = 0
|
||||||
|
//initial_display_delay_present_for_this_op[ 0 ] = 0
|
||||||
|
} else {
|
||||||
|
//timing_info_present_flag = auto_cast f(r, 1)
|
||||||
|
|
||||||
|
//if timing_info_present_flag == 1 {
|
||||||
|
// timing_info(r)
|
||||||
|
|
||||||
|
// decoder_model_info_present_flag = auto_cast f(r, 1)
|
||||||
|
// if decoder_model_info_present_flag == 1 {
|
||||||
|
// decoder_model_info(r)
|
||||||
|
// }
|
||||||
|
//} else {
|
||||||
|
// decoder_model_info_present_flag = 0
|
||||||
|
//}
|
||||||
|
|
||||||
|
//initial_display_delay_present_flag = auto_cast f(r, 1)
|
||||||
|
//operating_points_cnt_minus_1 = auto_cast f(r, 5)
|
||||||
|
|
||||||
|
//for i in 0 ..=operating_points_cnt_minus_1 {
|
||||||
|
// operating_point_idc[i] = f(r, 12)
|
||||||
|
// seq_level_idx[i] = f(r, 5)
|
||||||
|
|
||||||
|
// if seq_level_idx[i] > 7 {
|
||||||
|
// seq_tier[i] = f(r, 1)
|
||||||
|
// } else {
|
||||||
|
// seq_tier[i] = 0
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if decoder_model_info_present_flag == 1 {
|
||||||
|
// decoder_model_present_for_this_op[i] = f(r, 1)
|
||||||
|
// if decoder_model_present_for_this_op[i] == 1 {
|
||||||
|
// operating_parameters_info(r, i)
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// decoder_model_present_for_this_op[i] = 0
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if initial_display_delay_present_flag == 1 {
|
||||||
|
// initial_display_delay_present_for_this_op[i] = f(r, 1)
|
||||||
|
// if initial_display_delay_present_for_this_op[i] == 1 {
|
||||||
|
// initial_display_delay_minus_1[i] = f(r, 4)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.println("seq_profile:", seq_profile)
|
||||||
|
fmt.println("still_picture:", still_picture)
|
||||||
|
fmt.println("reduced_still_picture_header:", reduced_still_picture_header)
|
||||||
|
|
||||||
|
fmt.println("timing_info_present_flag:", timing_info_present_flag)
|
||||||
|
fmt.println("decoder_model_info_present_flag:", decoder_model_info_present_flag)
|
||||||
|
fmt.println("initial_display_delay_present_flag:", initial_display_delay_present_flag)
|
||||||
|
fmt.println("operating_points_cnt_minus_1:", operating_points_cnt_minus_1)
|
||||||
|
|
||||||
|
//operating_point := choose_operating_point()
|
||||||
|
//operating_point_idc_one := operating_point_idc[operating_point]
|
||||||
|
frame_width_bits_minus_1 := f(r, 4)
|
||||||
|
frame_height_bits_minus_1 := f(r, 4)
|
||||||
|
n := frame_width_bits_minus_1 + 1
|
||||||
|
max_frame_width_minus_1 := f(r, auto_cast n)
|
||||||
|
n = frame_height_bits_minus_1 + 1
|
||||||
|
max_frame_height_minus_1 := f(r, auto_cast n)
|
||||||
|
|
||||||
|
frame_id_numbers_present_flag: u8
|
||||||
|
delta_frame_id_length_minus_2: u8
|
||||||
|
additional_frame_id_length_minus_1: u8
|
||||||
|
|
||||||
|
if reduced_still_picture_header == 1 {
|
||||||
|
frame_id_numbers_present_flag = 0
|
||||||
|
} else {
|
||||||
|
frame_id_numbers_present_flag = auto_cast f(r, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if frame_id_numbers_present_flag == 1 {
|
||||||
|
delta_frame_id_length_minus_2 = auto_cast f(r, 4)
|
||||||
|
additional_frame_id_length_minus_1 = auto_cast f(r, 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
use_128x128_superblock := f(r, 1)
|
||||||
|
enable_filter_intra := f(r, 1)
|
||||||
|
enable_intra_edge_filter := f(r, 1)
|
||||||
|
|
||||||
|
fmt.println("frame_width_bits_minus_1:", frame_width_bits_minus_1)
|
||||||
|
fmt.println("frame_height_bits_minus_1:", frame_height_bits_minus_1)
|
||||||
|
fmt.println("max_frame_width_minus_1:", max_frame_width_minus_1)
|
||||||
|
fmt.println("max_frame_height_minus_1:", max_frame_height_minus_1)
|
||||||
|
|
||||||
|
fmt.println("frame_id_numbers_present_flag:", frame_id_numbers_present_flag)
|
||||||
|
fmt.println("delta_frame_id_length_minus_2:", delta_frame_id_length_minus_2)
|
||||||
|
fmt.println("additional_frame_id_length_minus_1:", additional_frame_id_length_minus_1)
|
||||||
|
|
||||||
|
fmt.println("use_128x128_superblock:", use_128x128_superblock)
|
||||||
|
fmt.println("enable_filter_intra:", enable_filter_intra)
|
||||||
|
fmt.println("enable_intra_edge_filter:", enable_intra_edge_filter)
|
||||||
|
|
||||||
|
//if reduced_still_picture_header == 1 {
|
||||||
|
// enable_interintra_compound = 0
|
||||||
|
// enable_masked_compound = 0
|
||||||
|
// enable_warped_motion = 0
|
||||||
|
// enable_dual_filter = 0
|
||||||
|
// enable_order_hint = 0
|
||||||
|
// enable_jnt_comp = 0
|
||||||
|
// enable_ref_frame_mvs = 0
|
||||||
|
// seq_force_screen_content_tools = SELECT_SCREEN_CONTENT_TOOLS
|
||||||
|
// seq_force_integer_mv = SELECT_INTEGER_MV
|
||||||
|
// OrderHintBits = 0
|
||||||
|
//} else {
|
||||||
|
// enable_interintra_compount = f(r, 1)
|
||||||
|
// enable_masked_compound = f(r, 1)
|
||||||
|
// enable_warped_motion = f(r, 1)
|
||||||
|
// enable_dual_filter = f(r, 1)
|
||||||
|
// enable_order_hint = f(r, 1)
|
||||||
|
// if enable_order_hint == 1 {
|
||||||
|
// enable_jnt_comp = f(r, 1)
|
||||||
|
// enable_ref_frame_mvs = f(r, 1)
|
||||||
|
// } else {
|
||||||
|
// enable_jnt_comp = 0
|
||||||
|
// enable_ref_frame_mvs = 0
|
||||||
|
// }
|
||||||
|
|
||||||
|
// seq_choose_screen_content_tools = f(r, 1)
|
||||||
|
// if seq_choose_screen_content_tools == 1 {
|
||||||
|
// seq_force_screen_content_tools = SELECT_SCREEN_CONTENT_TOOLS
|
||||||
|
// } else {
|
||||||
|
// seq_force_screen_content_tools = f(r, 1)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if seq_force_screen_content_tools > 0 {
|
||||||
|
// seq_choose_integer_mv = f(r, 1)
|
||||||
|
// if seq_choose_integer_mv == 1 {
|
||||||
|
// seq_force_integer_mv = SELECT_INTEGER_MV
|
||||||
|
// } else {
|
||||||
|
// seq_force_integer_mv = f(r, 1)
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// seq_force_integer_mv = SELECT_INTEGER_MV
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if enable_order_hint == 1 {
|
||||||
|
// order_hint_bits_minus_1 = f(r, 3)
|
||||||
|
// OrderHintBits = order_hint_bits_minus_1 + 1
|
||||||
|
// } else {
|
||||||
|
// OrderHintBits = 0
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
|
//enable_superres = f(r, 1)
|
||||||
|
//enable_cdef = f(r, 1)
|
||||||
|
//enable_restoration = f(r, 1)
|
||||||
|
//color_config()
|
||||||
|
//film_grain_params_present = f(r, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
f :: proc(r: ^Reader, n: int) -> u64 {
|
||||||
x: u64 = 0
|
x: u64 = 0
|
||||||
|
|
||||||
for i in 0 ..< n {
|
for i in 0 ..< n {
|
||||||
x = 2 * x + auto_cast read_bit()
|
// TODO: maybe get rid of or_break and propagate the error??
|
||||||
|
x = 2 * x + auto_cast read_bit(r) or_break
|
||||||
}
|
}
|
||||||
|
|
||||||
return x
|
return x
|
||||||
}
|
}
|
||||||
|
|
||||||
leb128 :: proc() -> u64 {
|
leb128 :: proc(r: ^Reader) -> u64 {
|
||||||
value: u64 = 0
|
value: u64 = 0
|
||||||
leb128_bytes := 0
|
leb128_bytes := 0
|
||||||
|
|
||||||
for i: u64 = 0; i < 8; i += 1 {
|
for i: u64 = 0; i < 8; i += 1 {
|
||||||
leb128_byte := f(8)
|
leb128_byte := f(r, 8)
|
||||||
value |= ((leb128_byte & 0x7f) << (i * 7))
|
value |= ((leb128_byte & 0x7f) << (i * 7))
|
||||||
leb128_bytes += 1
|
leb128_bytes += 1
|
||||||
|
|
||||||
@@ -68,3 +460,22 @@ leb128 :: proc() -> u64 {
|
|||||||
|
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uvlc :: proc(r: ^Reader) -> u64 {
|
||||||
|
leading_zeros: u64 = 0
|
||||||
|
|
||||||
|
for {
|
||||||
|
done := f(r, 1)
|
||||||
|
if done == 1 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
leading_zeros += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if leading_zeros >= 32 {
|
||||||
|
return (1 << 32) - 1
|
||||||
|
}
|
||||||
|
|
||||||
|
value := f(r, auto_cast leading_zeros)
|
||||||
|
return value + (1 << leading_zeros) - 1
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user