DataHoarder
230d505377
All checks were successful
continuous-integration/drone/push Build is passing
114 lines
2.4 KiB
Go
114 lines
2.4 KiB
Go
package utilities
|
|
|
|
import (
|
|
"bufio"
|
|
"fmt"
|
|
"github.com/nethruster/go-fraction"
|
|
"io"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
// Timecodes Entries in milliseconds. First entry includes fallback duration, in time.Duration format
|
|
type Timecodes []int64
|
|
|
|
func (tc Timecodes) FallbackDuration() time.Duration {
|
|
return time.Duration(tc[0])
|
|
}
|
|
func (tc Timecodes) PTS(n int) int64 {
|
|
if n >= 0 && (n+1) < len(tc) {
|
|
return tc[n+1]
|
|
}
|
|
return -1
|
|
}
|
|
|
|
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
|
|
|
|
//fallback
|
|
tc = append(tc, (int64(time.Second)*assumedFraction.Numerator())/assumedFraction.Denominator())
|
|
|
|
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
|
|
}
|