From 1fc0f46b3f70b9eae5f124fcb3ca5a552f1cee9a Mon Sep 17 00:00:00 2001 From: Leandro Moreira Date: Wed, 31 Jan 2024 14:23:20 -0300 Subject: [PATCH] moving entities and controllers to the right place --- h264/h264.go | 114 ------------------ .../controllers/eia608_controller.go | 17 +-- internal/controllers/h264_controller.go | 59 +++++++++ internal/controllers/streaming_controller.go | 5 +- internal/entities/entities.go | 8 +- h264/types.go => internal/entities/h264.go | 59 ++++++++- 6 files changed, 130 insertions(+), 132 deletions(-) delete mode 100644 h264/h264.go rename eia608/eia608.go => internal/controllers/eia608_controller.go (82%) create mode 100644 internal/controllers/h264_controller.go rename h264/types.go => internal/entities/h264.go (78%) diff --git a/h264/h264.go b/h264/h264.go deleted file mode 100644 index 72bdec0..0000000 --- a/h264/h264.go +++ /dev/null @@ -1,114 +0,0 @@ -package h264 - -import ( - "bytes" - "fmt" -) - -func ParseNALUs(data []byte) (NALUs, error) { - var nalus NALUs - - rawNALUs := bytes.Split(data, []byte{0x00, 0x00, 0x01}) - - for _, rawNALU := range rawNALUs[1:] { - nal, err := ParseNAL(rawNALU) - if err != nil { - return NALUs{}, err - - } - nalus.Units = append(nalus.Units, nal) - } - - return nalus, nil -} - -func ParseNAL(data []byte) (NAL, error) { - index := 0 - n := NAL{} - if data[index]>>7&0x01 != 0 { - return NAL{}, fmt.Errorf("forbidden_zero_bit is not 0") - } - n.RefIDC = (data[index] >> 5) & 0x03 - n.UnitType = NALUnitType(data[index] & 0x1f) - numBytesInRBSP := 0 - nalUnitHeaderBytes := 1 - n.HeaderBytes = data[:nalUnitHeaderBytes] - - index += nalUnitHeaderBytes - - n.RBSPByte = make([]byte, 0, 16) - i := 0 - for i = index; i < len(data); i++ { - if (i+2) < len(data) && (data[i] == 0x00 && data[i+1] == 0x00 && data[i+2] == 0x03) { - n.RBSPByte = append(n.RBSPByte, data[i], data[i+1]) - i += 2 - numBytesInRBSP += 2 - // 0x03 - } else { - n.RBSPByte = append(n.RBSPByte, data[i]) - numBytesInRBSP++ - } - } - index += numBytesInRBSP - - n.ParseRBSP() - - return n, nil -} - -func (n *NAL) ParseRBSP() error { - switch n.UnitType { - case SupplementalEnhancementInformation: - err := n.parseSEI() - if err != nil { - return err - } - } - - return nil -} - -func (n *NAL) parseSEI() error { - numBits := 0 - byteOffset := 0 - n.SEI.PayloadType = 0 - n.SEI.PayloadSize = 0 - nextBits := n.RBSPByte[byteOffset] - - for { - if nextBits == 0xff { - n.PayloadType += 255 - numBits += 8 - byteOffset += numBits / 8 - numBits = numBits % 8 - nextBits = n.RBSPByte[byteOffset] - continue - } - break - } - - n.PayloadType += int(nextBits) - numBits += 8 - byteOffset += numBits / 8 - numBits = numBits % 8 - nextBits = n.RBSPByte[byteOffset] - - // read size - for { - if nextBits == 0xff { - n.PayloadSize += 255 - numBits += 8 - byteOffset += numBits / 8 - numBits = numBits % 8 - nextBits = n.RBSPByte[byteOffset] - continue - } - break - } - - n.PayloadSize += int(nextBits) - numBits += 8 - byteOffset += numBits / 8 - - return nil -} diff --git a/eia608/eia608.go b/internal/controllers/eia608_controller.go similarity index 82% rename from eia608/eia608.go rename to internal/controllers/eia608_controller.go index 3ec2873..dd86823 100644 --- a/eia608/eia608.go +++ b/internal/controllers/eia608_controller.go @@ -1,11 +1,10 @@ -package eia608 +package controllers import ( "encoding/json" - "github.com/flavioribeiro/donut/h264" - "github.com/asticode/go-astits" + "github.com/flavioribeiro/donut/internal/entities" gocaption "github.com/szatmary/gocaption" ) @@ -13,25 +12,19 @@ type EIA608Reader struct { frame gocaption.EIA608Frame } -type Cue struct { - Type string - StartTime int64 - Text string -} - func NewEIA608Reader() (r *EIA608Reader) { return &EIA608Reader{} } func (r *EIA608Reader) Parse(PES *astits.PESData) (string, error) { - nalus, err := h264.ParseNALUs(PES.Data) + 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 == h264.SupplementalEnhancementInformation && nal.SEI.PayloadType == 4 { + 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. @@ -55,7 +48,7 @@ func (r *EIA608Reader) Parse(PES *astits.PESData) (string, error) { } func BuildCaptionsMessage(pts *astits.ClockReference, captions string) (string, error) { - cue := Cue{ + cue := entities.Cue{ StartTime: pts.Base, Text: captions, Type: "captions", diff --git a/internal/controllers/h264_controller.go b/internal/controllers/h264_controller.go new file mode 100644 index 0000000..0306918 --- /dev/null +++ b/internal/controllers/h264_controller.go @@ -0,0 +1,59 @@ +package controllers + +import ( + "bytes" + "fmt" + + "github.com/flavioribeiro/donut/internal/entities" +) + +func ParseNALUs(data []byte) (entities.NALUs, error) { + var nalus entities.NALUs + + rawNALUs := bytes.Split(data, []byte{0x00, 0x00, 0x01}) + + for _, rawNALU := range rawNALUs[1:] { + nal, err := ParseNAL(rawNALU) + if err != nil { + return entities.NALUs{}, err + + } + nalus.Units = append(nalus.Units, nal) + } + + return nalus, nil +} + +func ParseNAL(data []byte) (entities.NAL, error) { + index := 0 + n := entities.NAL{} + if data[index]>>7&0x01 != 0 { + return entities.NAL{}, fmt.Errorf("forbidden_zero_bit is not 0") + } + n.RefIDC = (data[index] >> 5) & 0x03 + n.UnitType = entities.NALUnitType(data[index] & 0x1f) + numBytesInRBSP := 0 + nalUnitHeaderBytes := 1 + n.HeaderBytes = data[:nalUnitHeaderBytes] + + index += nalUnitHeaderBytes + + n.RBSPByte = make([]byte, 0, 16) + i := 0 + for i = index; i < len(data); i++ { + if (i+2) < len(data) && (data[i] == 0x00 && data[i+1] == 0x00 && data[i+2] == 0x03) { + n.RBSPByte = append(n.RBSPByte, data[i], data[i+1]) + i += 2 + numBytesInRBSP += 2 + // 0x03 + } else { + n.RBSPByte = append(n.RBSPByte, data[i]) + numBytesInRBSP++ + } + } + index += numBytesInRBSP + + n.ParseRBSP() + + return n, nil +} diff --git a/internal/controllers/streaming_controller.go b/internal/controllers/streaming_controller.go index 60e8eb9..4561940 100644 --- a/internal/controllers/streaming_controller.go +++ b/internal/controllers/streaming_controller.go @@ -8,7 +8,6 @@ import ( astisrt "github.com/asticode/go-astisrt/pkg" "github.com/asticode/go-astits" - "github.com/flavioribeiro/donut/eia608" "github.com/flavioribeiro/donut/internal/entities" "github.com/pion/webrtc/v3" "github.com/pion/webrtc/v3/pkg/media" @@ -43,7 +42,7 @@ func (c *StreamingController) Stream(sp entities.StreamParameters) { // reading from reader pipe into mpeg-ts demuxer mpegTSDemuxer := astits.NewDemuxer(sp.Ctx, r) - eia608Reader := eia608.NewEIA608Reader() + eia608Reader := NewEIA608Reader() h264PID := uint16(0) for { @@ -83,7 +82,7 @@ func (c *StreamingController) Stream(sp entities.StreamParameters) { return } if captions != "" { - captionsMsg, err := eia608.BuildCaptionsMessage(mpegTSDemuxData.PES.Header.OptionalHeader.PTS, captions) + captionsMsg, err := BuildCaptionsMessage(mpegTSDemuxData.PES.Header.OptionalHeader.PTS, captions) if err != nil { c.l.Sugar().Errorw("failed to build captions message", "error", err, diff --git a/internal/entities/entities.go b/internal/entities/entities.go index 084956a..0afb91e 100644 --- a/internal/entities/entities.go +++ b/internal/entities/entities.go @@ -12,8 +12,6 @@ const ( MetadataChannelID string = "metadata" ) -type Media struct{} - type RequestParams struct { SRTHost string SRTPort uint16 `json:",string"` @@ -69,6 +67,12 @@ type Track struct { Type TrackType } +type Cue struct { + Type string + StartTime int64 + Text string +} + type StreamParameters struct { WebRTCConn *webrtc.PeerConnection Cancel context.CancelFunc diff --git a/h264/types.go b/internal/entities/h264.go similarity index 78% rename from h264/types.go rename to internal/entities/h264.go index 43b277e..a69a95c 100644 --- a/h264/types.go +++ b/internal/entities/h264.go @@ -1,4 +1,4 @@ -package h264 +package entities type NALUs struct { Units []NAL @@ -56,3 +56,60 @@ const ( Unspecified31 = NALUnitType(31) // Unspecified ) + +func (n *NAL) ParseRBSP() error { + switch n.UnitType { + case SupplementalEnhancementInformation: + err := n.parseSEI() + if err != nil { + return err + } + } + + return nil +} + +func (n *NAL) parseSEI() error { + numBits := 0 + byteOffset := 0 + n.SEI.PayloadType = 0 + n.SEI.PayloadSize = 0 + nextBits := n.RBSPByte[byteOffset] + + for { + if nextBits == 0xff { + n.PayloadType += 255 + numBits += 8 + byteOffset += numBits / 8 + numBits = numBits % 8 + nextBits = n.RBSPByte[byteOffset] + continue + } + break + } + + n.PayloadType += int(nextBits) + numBits += 8 + byteOffset += numBits / 8 + numBits = numBits % 8 + nextBits = n.RBSPByte[byteOffset] + + // read size + for { + if nextBits == 0xff { + n.PayloadSize += 255 + numBits += 8 + byteOffset += numBits / 8 + numBits = numBits % 8 + nextBits = n.RBSPByte[byteOffset] + continue + } + break + } + + n.PayloadSize += int(nextBits) + numBits += 8 + byteOffset += numBits / 8 + + return nil +}