mirror of
https://github.com/langhuihui/monibuca.git
synced 2025-09-27 05:35:57 +08:00

- Refactor frame converter implementation - Update mp4 track to use ICodex - General refactoring and code improvements 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
132 lines
3.0 KiB
Go
132 lines
3.0 KiB
Go
package format
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
|
|
"github.com/deepch/vdk/codec/h264parser"
|
|
"github.com/deepch/vdk/codec/h265parser"
|
|
"m7s.live/v5/pkg"
|
|
"m7s.live/v5/pkg/codec"
|
|
"m7s.live/v5/pkg/util"
|
|
)
|
|
|
|
var _ pkg.IAVFrame = (*RawAudio)(nil)
|
|
|
|
type RawAudio struct {
|
|
pkg.Sample
|
|
}
|
|
|
|
func (r *RawAudio) GetSize() int {
|
|
return r.Raw.(*util.Memory).Size
|
|
}
|
|
|
|
func (r *RawAudio) Demux() error {
|
|
r.Raw = &r.Memory
|
|
return nil
|
|
}
|
|
|
|
func (r *RawAudio) Mux(from *pkg.Sample) (err error) {
|
|
r.InitRecycleIndexes(0)
|
|
r.Memory = *from.Raw.(*util.Memory)
|
|
r.ICodecCtx = from.GetBase()
|
|
return
|
|
}
|
|
|
|
func (r *RawAudio) String() string {
|
|
return fmt.Sprintf("RawAudio{FourCC: %s, Timestamp: %s, Size: %d}", r.FourCC(), r.Timestamp, r.Size)
|
|
}
|
|
|
|
var _ pkg.IAVFrame = (*H26xFrame)(nil)
|
|
|
|
type H26xFrame struct {
|
|
pkg.Sample
|
|
}
|
|
|
|
func (h *H26xFrame) CheckCodecChange() (err error) {
|
|
if h.ICodecCtx == nil {
|
|
return pkg.ErrUnsupportCodec
|
|
}
|
|
var hasVideoFrame bool
|
|
switch ctx := h.GetBase().(type) {
|
|
case *codec.H264Ctx:
|
|
var sps, pps []byte
|
|
for nalu := range h.Raw.(*pkg.Nalus).RangePoint {
|
|
switch codec.ParseH264NALUType(nalu.Buffers[0][0]) {
|
|
case codec.NALU_SPS:
|
|
sps = nalu.ToBytes()
|
|
case codec.NALU_PPS:
|
|
pps = nalu.ToBytes()
|
|
case codec.NALU_IDR_Picture:
|
|
h.IDR = true
|
|
case codec.NALU_Non_IDR_Picture:
|
|
hasVideoFrame = true
|
|
}
|
|
}
|
|
if sps != nil && pps != nil {
|
|
var codecData h264parser.CodecData
|
|
codecData, err = h264parser.NewCodecDataFromSPSAndPPS(sps, pps)
|
|
if err != nil {
|
|
return
|
|
}
|
|
if !bytes.Equal(codecData.Record, ctx.Record) {
|
|
h.ICodecCtx = &codec.H264Ctx{
|
|
CodecData: codecData,
|
|
}
|
|
}
|
|
}
|
|
case *codec.H265Ctx:
|
|
var vps, sps, pps []byte
|
|
for nalu := range h.Raw.(*pkg.Nalus).RangePoint {
|
|
switch codec.ParseH265NALUType(nalu.Buffers[0][0]) {
|
|
case h265parser.NAL_UNIT_VPS:
|
|
vps = nalu.ToBytes()
|
|
case h265parser.NAL_UNIT_SPS:
|
|
sps = nalu.ToBytes()
|
|
case h265parser.NAL_UNIT_PPS:
|
|
pps = nalu.ToBytes()
|
|
case h265parser.NAL_UNIT_CODED_SLICE_BLA_W_LP,
|
|
h265parser.NAL_UNIT_CODED_SLICE_BLA_W_RADL,
|
|
h265parser.NAL_UNIT_CODED_SLICE_BLA_N_LP,
|
|
h265parser.NAL_UNIT_CODED_SLICE_IDR_W_RADL,
|
|
h265parser.NAL_UNIT_CODED_SLICE_IDR_N_LP,
|
|
h265parser.NAL_UNIT_CODED_SLICE_CRA:
|
|
h.IDR = true
|
|
case 1, 2, 3, 4, 5, 6, 7, 8, 9:
|
|
hasVideoFrame = true
|
|
}
|
|
}
|
|
if vps != nil && sps != nil && pps != nil {
|
|
var codecData h265parser.CodecData
|
|
codecData, err = h265parser.NewCodecDataFromVPSAndSPSAndPPS(vps, sps, pps)
|
|
if err != nil {
|
|
return
|
|
}
|
|
if !bytes.Equal(codecData.Record, ctx.Record) {
|
|
h.ICodecCtx = &codec.H265Ctx{
|
|
CodecData: codecData,
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// Return ErrSkip if no video frames are present (only metadata NALUs)
|
|
if !hasVideoFrame && !h.IDR {
|
|
return pkg.ErrSkip
|
|
}
|
|
return
|
|
}
|
|
|
|
func (r *H26xFrame) GetSize() (ret int) {
|
|
switch raw := r.Raw.(type) {
|
|
case *pkg.Nalus:
|
|
for nalu := range raw.RangePoint {
|
|
ret += nalu.Size
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func (h *H26xFrame) String() string {
|
|
return fmt.Sprintf("H26xFrame{FourCC: %s, Timestamp: %s, CTS: %s}", h.FourCC, h.Timestamp, h.CTS)
|
|
}
|