Files
donut/internal/controllers/eia608_controller.go
2024-01-31 14:23:20 -03:00

62 lines
1.5 KiB
Go

package controllers
import (
"encoding/json"
"github.com/asticode/go-astits"
"github.com/flavioribeiro/donut/internal/entities"
gocaption "github.com/szatmary/gocaption"
)
type EIA608Reader struct {
frame gocaption.EIA608Frame
}
func NewEIA608Reader() (r *EIA608Reader) {
return &EIA608Reader{}
}
func (r *EIA608Reader) Parse(PES *astits.PESData) (string, error) {
nalus, err := ParseNALUs(PES.Data)
if err != nil {
return "", err
}
for _, nal := range nalus.Units {
// ANSI/SCTE 128-1 2020
// Note that SEI payload is a SEI payloadType of 4 which contains the itu_t_t35_payload_byte for the terminal provider
if nal.UnitType == entities.SupplementalEnhancementInformation && nal.SEI.PayloadType == 4 {
// ANSI/SCTE 128-1 2020
// Caption, AFD and bar data shall be carried in the SEI raw byte sequence payload (RBSP)
// syntax of the video Elementary Stream.
cea708Data := nal.RBSPByte[2:] // skip payload type and length bytes
cea708, err := gocaption.CEA708ToCCData(cea708Data)
if err != nil {
return "", err
}
for _, c := range cea708 {
ready, err := r.frame.Decode(c)
if err != nil {
panic(err)
}
if ready {
return r.frame.String(), nil
}
}
}
}
return "", nil
}
func BuildCaptionsMessage(pts *astits.ClockReference, captions string) (string, error) {
cue := entities.Cue{
StartTime: pts.Base,
Text: captions,
Type: "captions",
}
c, err := json.Marshal(cue)
if err != nil {
return "", err
}
return string(c), nil
}