2023-09-22 21:59:56 +00:00
|
|
|
package video
|
|
|
|
|
2023-09-23 09:27:20 +00:00
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"errors"
|
|
|
|
"io"
|
|
|
|
|
|
|
|
"github.com/sunfish-shogi/bufseekio"
|
|
|
|
)
|
|
|
|
|
2023-09-22 21:59:56 +00:00
|
|
|
// Chunks represents a list of file chunks.
|
|
|
|
type Chunks []Chunk
|
|
|
|
|
2023-09-23 09:27:20 +00:00
|
|
|
// Contains tests if the chunk is contained in this list.
|
|
|
|
func (c Chunks) Contains(s [4]byte) bool {
|
|
|
|
if len(c) == 0 {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
// Find matches.
|
|
|
|
for i := range c {
|
|
|
|
if s == c[i] {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
// ContainsAny checks if at least one common chunk exists in this list.
|
2023-09-22 21:59:56 +00:00
|
|
|
func (c Chunks) ContainsAny(b [][4]byte) bool {
|
|
|
|
if len(c) == 0 || len(b) == 0 {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
// Find matches.
|
|
|
|
for i := range c {
|
|
|
|
for j := range b {
|
|
|
|
if b[j] == c[i] {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Not found.
|
|
|
|
return false
|
|
|
|
}
|
2023-09-23 09:27:20 +00:00
|
|
|
|
|
|
|
// FileTypeOffset returns the file type start offset in f, or -1 if it was not found.
|
|
|
|
func (c Chunks) FileTypeOffset(file io.ReadSeeker) (int, error) {
|
|
|
|
if file == nil {
|
|
|
|
return -1, errors.New("file is nil")
|
|
|
|
}
|
|
|
|
|
|
|
|
ftyp := ChunkFTYP.Bytes()
|
|
|
|
blockSize := 128 * 1024
|
|
|
|
buffer := make([]byte, blockSize)
|
|
|
|
|
|
|
|
// Create buffered read seeker.
|
|
|
|
r := bufseekio.NewReadSeeker(file, blockSize, 8)
|
|
|
|
|
|
|
|
// Index offset.
|
|
|
|
var offset int
|
|
|
|
|
|
|
|
// Search in batches.
|
|
|
|
for {
|
|
|
|
n, err := r.Read(buffer)
|
|
|
|
buffer = buffer[:n]
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
if err != io.EOF {
|
|
|
|
return -1, err
|
|
|
|
}
|
|
|
|
|
|
|
|
break
|
|
|
|
} else if n == 0 {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
|
|
|
|
// Find ftyp chunk.
|
|
|
|
if i := bytes.Index(buffer, ftyp); i < 0 {
|
|
|
|
// Not found.
|
|
|
|
} else if j := i + 4; j < 8 || len(buffer) < j+4 {
|
|
|
|
// Skip.
|
|
|
|
} else if k := j + 4; c.Contains(*(*[4]byte)(buffer[j:k])) {
|
|
|
|
return offset + i - 4, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
offset += n
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1, nil
|
|
|
|
}
|