Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 11 additions & 6 deletions matchers/image.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,21 +152,26 @@ func Exr(buf []byte) bool {
buf[2] == 0x31 && buf[3] == 0x01
}

func avifBrand(brand string) bool {
return brand == "avif" || brand == "avis"
}

func Avif(buf []byte) bool {
if !isobmff.IsISOBMFF(buf) {
return false
}

majorBrand, _, compatibleBrands := isobmff.GetFtyp(buf)
if majorBrand == "avif" {
if avifBrand(majorBrand) {
return true
}

if majorBrand == "mif1" || majorBrand == "msf1" {
for _, compatibleBrand := range compatibleBrands {
if compatibleBrand == "avif" {
return true
}
// libavif commonly writes major brand miaf/mif1/msf1 with avif
// in compatible_brands. Restricting the major brand to mif1/msf1
// missed those files.
for _, compatibleBrand := range compatibleBrands {
if avifBrand(compatibleBrand) {
return true
}
}

Expand Down
54 changes: 54 additions & 0 deletions matchers/image_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package matchers

import (
"encoding/binary"
"testing"
)

func ftypBox(major string, brands ...string) []byte {
n := 16 + 4*len(brands)
buf := make([]byte, n)
binary.BigEndian.PutUint32(buf[0:4], uint32(n))
copy(buf[4:8], "ftyp")
copy(buf[8:12], major)
for i, b := range brands {
copy(buf[16+4*i:], b)
}
return buf
}

func TestAvifBrands(t *testing.T) {
cases := []struct {
name string
buf []byte
want bool
}{
{"major avif", ftypBox("avif", "avif", "mif1", "miaf"), true},
{"mif1 + avif", ftypBox("mif1", "mif1", "avif"), true},
{"msf1 + avif", ftypBox("msf1", "msf1", "avif"), true},
{"miaf + avif", ftypBox("miaf", "miaf", "avif", "mif1"), true},
{"major avis", ftypBox("avis", "avis", "avif"), true},
{"miaf + avis", ftypBox("miaf", "miaf", "avis"), true},
{"miaf without avif", ftypBox("miaf", "miaf", "mif1"), false},
{"heic", ftypBox("heic", "mif1", "heic"), false},
{"mif1 + heic", ftypBox("mif1", "mif1", "heic"), false},
{"not isobmff", []byte("not a media box"), false},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
if got := Avif(tc.buf); got != tc.want {
t.Fatalf("Avif() = %v, want %v", got, tc.want)
}
})
}
}

func TestHeifNotAvif(t *testing.T) {
buf := ftypBox("miaf", "miaf", "avif", "mif1")
if !Avif(buf) {
t.Fatal("miaf+avif should match Avif")
}
if Heif(buf) {
t.Fatal("miaf+avif should not match Heif")
}
}