Ignite/utilities/timecodes.go

100 lines
2.1 KiB
Go

package utilities
import (
"bufio"
"fmt"
"github.com/nethruster/go-fraction"
"io"
"strings"
)
// Timecodes Entries in milliseconds
type Timecodes []int64
const timecodesv1Header = "# timecode format v1"
func ParseTimecodesV1(reader io.Reader) (Timecodes, error) {
var tc Timecodes
scanner := bufio.NewScanner(reader)
// Read header
if !scanner.Scan() {
return nil, io.ErrUnexpectedEOF
}
switch strings.TrimSpace(scanner.Text()) {
case timecodesv1Header:
default:
return nil, fmt.Errorf("unexpected line: %s", strings.TrimSpace(scanner.Text()))
}
// Read assume line
if !scanner.Scan() {
return nil, io.ErrUnexpectedEOF
}
var fps float64
var from, to int64
_, err := fmt.Sscanf(strings.ToLower(strings.TrimSpace(scanner.Text())), "assume %f", &fps)
if err != nil {
return nil, err
}
assumed := FPSToRatio(fps)
assumedFraction, err := fraction.New(assumed.Denominator, assumed.Numerator)
if err != nil {
return nil, err
}
if assumed.Denominator == 1000 {
assumedFraction, err = fraction.FromFloat64(1 / fps)
if err != nil {
return nil, err
}
}
running, err := fraction.New(0, 1000)
if err != nil {
return nil, err
}
var currentFrame int64
for scanner.Scan() {
line := strings.ReplaceAll(strings.TrimSpace(scanner.Text()), " ", "")
if line == "" || line[0] == '#' {
continue
}
_, err := fmt.Sscanf(strings.ReplaceAll(strings.TrimSpace(scanner.Text()), " ", ""), "%d,%d,%f", &from, &to, &fps)
if err != nil {
return nil, err
}
ratio := FPSToRatio(fps)
frac, err := fraction.New(ratio.Denominator, ratio.Numerator)
if err != nil {
return nil, err
}
if ratio.Denominator == 1000 {
frac, err = fraction.FromFloat64(1 / fps)
if err != nil {
return nil, err
}
}
for ; currentFrame < from; currentFrame++ {
tc = append(tc, (running.Numerator()*1000)/running.Denominator())
running = running.Add(assumedFraction)
}
for ; currentFrame <= to; currentFrame++ {
tc = append(tc, (running.Numerator()*1000)/running.Denominator())
running = running.Add(frac)
}
}
return tc, nil
}