mirror of
https://github.com/langhuihui/monibuca.git
synced 2025-12-24 13:48:04 +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>
75 lines
2.0 KiB
Go
75 lines
2.0 KiB
Go
package mp4
|
||
|
||
import (
|
||
"fmt"
|
||
|
||
"m7s.live/v5/pkg"
|
||
"m7s.live/v5/pkg/codec"
|
||
"m7s.live/v5/pkg/util"
|
||
)
|
||
|
||
var _ pkg.IAVFrame = (*VideoFrame)(nil)
|
||
|
||
type VideoFrame struct {
|
||
pkg.Sample
|
||
}
|
||
|
||
func (v *VideoFrame) Demux() (err error) {
|
||
if v.Size == 0 {
|
||
return fmt.Errorf("no video data to demux")
|
||
}
|
||
|
||
reader := v.NewReader()
|
||
// 根据编解码器类型进行解复用
|
||
switch ctx := v.ICodecCtx.(type) {
|
||
case *codec.H264Ctx:
|
||
// 对于 H.264,解析 AVCC 格式的 NAL 单元
|
||
if err := v.ParseAVCC(&reader, int(ctx.RecordInfo.LengthSizeMinusOne)+1); err != nil {
|
||
return fmt.Errorf("failed to parse H.264 AVCC: %w", err)
|
||
}
|
||
case *codec.H265Ctx:
|
||
// 对于 H.265,解析 AVCC 格式的 NAL 单元
|
||
if err := v.ParseAVCC(&reader, int(ctx.RecordInfo.LengthSizeMinusOne)+1); err != nil {
|
||
return fmt.Errorf("failed to parse H.265 AVCC: %w", err)
|
||
}
|
||
default:
|
||
// 对于其他格式,尝试默认的 AVCC 解析(4字节长度前缀)
|
||
if err := v.ParseAVCC(&reader, 4); err != nil {
|
||
return fmt.Errorf("failed to parse AVCC with default settings: %w", err)
|
||
}
|
||
}
|
||
|
||
return
|
||
}
|
||
|
||
// Mux implements pkg.IAVFrame.
|
||
func (v *VideoFrame) Mux(sample *pkg.Sample) (err error) {
|
||
v.InitRecycleIndexes(0)
|
||
if v.ICodecCtx == nil {
|
||
v.ICodecCtx = sample.GetBase()
|
||
}
|
||
switch rawData := sample.Raw.(type) {
|
||
case *pkg.Nalus:
|
||
// 根据编解码器类型确定 NALU 长度字段的大小
|
||
var naluSizeLen int = 4 // 默认使用 4 字节
|
||
switch ctx := sample.ICodecCtx.(type) {
|
||
case *codec.H264Ctx:
|
||
naluSizeLen = int(ctx.RecordInfo.LengthSizeMinusOne) + 1
|
||
case *codec.H265Ctx:
|
||
naluSizeLen = int(ctx.RecordInfo.LengthSizeMinusOne) + 1
|
||
}
|
||
// 为每个 NALU 添加长度前缀
|
||
for nalu := range rawData.RangePoint {
|
||
util.PutBE(v.NextN(naluSizeLen), nalu.Size) // 写入 NALU 长度
|
||
v.Push(nalu.Buffers...)
|
||
}
|
||
}
|
||
return
|
||
}
|
||
|
||
// String implements pkg.IAVFrame.
|
||
func (v *VideoFrame) String() string {
|
||
return fmt.Sprintf("MP4Video[ts:%s, cts:%s, size:%d, keyframe:%t]",
|
||
v.Timestamp, v.CTS, v.Size, v.IDR)
|
||
}
|