mirror of
https://github.com/cnotch/ipchub.git
synced 2025-09-26 19:41:18 +08:00
update Frame & Metadata
This commit is contained in:
@@ -4,15 +4,77 @@
|
|||||||
|
|
||||||
package codec
|
package codec
|
||||||
|
|
||||||
// 帧类型
|
import (
|
||||||
const (
|
"fmt"
|
||||||
FrameVideo = byte(iota)
|
"strings"
|
||||||
FrameAudio
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// MediaType 媒体类型
|
||||||
|
type MediaType int
|
||||||
|
|
||||||
|
// 媒体类型常量
|
||||||
|
const (
|
||||||
|
MediaTypeUnknown MediaType = iota - 1 // Usually treated as MediaTypeData
|
||||||
|
MediaTypeVideo
|
||||||
|
MediaTypeAudio
|
||||||
|
MediaTypeData // Opaque data information usually continuous
|
||||||
|
MediaTypeSubtitle
|
||||||
|
MediaTypeAttachment // Opaque data information usually sparse
|
||||||
|
MediaTypeNB
|
||||||
|
)
|
||||||
|
|
||||||
|
// String returns a lower-case ASCII representation of the media type.
|
||||||
|
func (mt MediaType) String() string {
|
||||||
|
switch mt {
|
||||||
|
case MediaTypeVideo:
|
||||||
|
return "video"
|
||||||
|
case MediaTypeAudio:
|
||||||
|
return "audio"
|
||||||
|
case MediaTypeData:
|
||||||
|
return "data"
|
||||||
|
case MediaTypeSubtitle:
|
||||||
|
return "subtitle"
|
||||||
|
case MediaTypeAttachment:
|
||||||
|
return "attachment"
|
||||||
|
default:
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalText marshals the MediaType to text.
|
||||||
|
func (mt *MediaType) MarshalText() ([]byte, error) {
|
||||||
|
return []byte(mt.String()), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalText unmarshals text to a MediaType.
|
||||||
|
func (mt *MediaType) UnmarshalText(text []byte) error {
|
||||||
|
if !mt.unmarshalText(string(text)) {
|
||||||
|
return fmt.Errorf("unrecognized media type: %q", text)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mt *MediaType) unmarshalText(text string) bool {
|
||||||
|
switch strings.ToLower(text) {
|
||||||
|
case "video":
|
||||||
|
*mt = MediaTypeVideo
|
||||||
|
case "audio":
|
||||||
|
*mt = MediaTypeAudio
|
||||||
|
case "data":
|
||||||
|
*mt = MediaTypeData
|
||||||
|
case "subtitle":
|
||||||
|
*mt = MediaTypeSubtitle
|
||||||
|
case "attachment":
|
||||||
|
*mt = MediaTypeAttachment
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// Frame 音视频完整帧
|
// Frame 音视频完整帧
|
||||||
type Frame struct {
|
type Frame struct {
|
||||||
FrameType byte // 帧类型
|
MediaType // 媒体类型
|
||||||
AbsTimestamp int64 // 绝对时间戳(主要用于表示 pts),单位为 ms 的 UNIX 时间
|
AbsTimestamp int64 // 绝对时间戳(主要用于表示 pts),单位为 ms 的 UNIX 时间
|
||||||
Payload []byte // 媒体数据载荷
|
Payload []byte // 媒体数据载荷
|
||||||
}
|
}
|
||||||
|
@@ -6,14 +6,16 @@ package codec
|
|||||||
|
|
||||||
// VideoMeta 视频元数据
|
// VideoMeta 视频元数据
|
||||||
type VideoMeta struct {
|
type VideoMeta struct {
|
||||||
Codec string `json:"codec"`
|
Codec string `json:"codec"`
|
||||||
Width int `json:"width,omitempty"`
|
Width int `json:"width,omitempty"`
|
||||||
Height int `json:"height,omitempty"`
|
Height int `json:"height,omitempty"`
|
||||||
FrameRate float64 `json:"framerate,omitempty"`
|
FixedFrameRate bool `json:"fixedframerate,omitempty"`
|
||||||
DataRate float64 `json:"datarate,omitempty"`
|
FrameRate float64 `json:"framerate,omitempty"`
|
||||||
Sps []byte `json:"-"`
|
DataRate float64 `json:"datarate,omitempty"`
|
||||||
Pps []byte `json:"-"`
|
ClockRate int `json:"clockrate,omitempty"`
|
||||||
Vps []byte `json:"-"`
|
Sps []byte `json:"-"`
|
||||||
|
Pps []byte `json:"-"`
|
||||||
|
Vps []byte `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// AudioMeta 音频元数据
|
// AudioMeta 音频元数据
|
||||||
|
@@ -116,7 +116,7 @@ func (muxer *MuxerAvcAac) process() {
|
|||||||
muxer.basePts = frame.AbsTimestamp
|
muxer.basePts = frame.AbsTimestamp
|
||||||
}
|
}
|
||||||
|
|
||||||
if frame.FrameType == codec.FrameVideo {
|
if frame.MediaType == codec.MediaTypeVideo {
|
||||||
if err := muxer.muxVideoTag(frame); err != nil {
|
if err := muxer.muxVideoTag(frame); err != nil {
|
||||||
muxer.logger.Errorf("flvmuxer: muxVideoTag error - %s", err.Error())
|
muxer.logger.Errorf("flvmuxer: muxVideoTag error - %s", err.Error())
|
||||||
}
|
}
|
||||||
|
@@ -131,7 +131,7 @@ func (muxer *MuxerAvcAac) process() {
|
|||||||
muxer.basePts = frame.AbsTimestamp
|
muxer.basePts = frame.AbsTimestamp
|
||||||
}
|
}
|
||||||
|
|
||||||
if frame.FrameType == codec.FrameVideo {
|
if frame.MediaType == codec.MediaTypeVideo {
|
||||||
if err := muxer.muxVideoTag(frame); err != nil {
|
if err := muxer.muxVideoTag(frame); err != nil {
|
||||||
muxer.logger.Errorf("tsmuxer: muxVideoFrame error - %s", err.Error())
|
muxer.logger.Errorf("tsmuxer: muxVideoFrame error - %s", err.Error())
|
||||||
}
|
}
|
||||||
|
@@ -75,7 +75,7 @@ func (aacdp *aacDepacketizer) depacketizeFor2ByteAUHeader(packet *Packet) (err e
|
|||||||
auHeader := uint16(0) | (uint16(auHeaders[0]) << 8) | uint16(auHeaders[1])
|
auHeader := uint16(0) | (uint16(auHeaders[0]) << 8) | uint16(auHeaders[1])
|
||||||
frameSize := auHeader >> aacdp.indexLength
|
frameSize := auHeader >> aacdp.indexLength
|
||||||
frame := &codec.Frame{
|
frame := &codec.Frame{
|
||||||
FrameType: codec.FrameAudio,
|
MediaType: codec.MediaTypeAudio,
|
||||||
AbsTimestamp: aacdp.rtp2ntp(frameTimeStamp),
|
AbsTimestamp: aacdp.rtp2ntp(frameTimeStamp),
|
||||||
Payload: framesPayload[:frameSize],
|
Payload: framesPayload[:frameSize],
|
||||||
}
|
}
|
||||||
@@ -109,7 +109,7 @@ func (aacdp *aacDepacketizer) depacketizeFor1ByteAUHeader(packet *Packet) (err e
|
|||||||
auHeader := auHeaders[0]
|
auHeader := auHeaders[0]
|
||||||
frameSize := auHeader >> aacdp.indexLength
|
frameSize := auHeader >> aacdp.indexLength
|
||||||
frame := &codec.Frame{
|
frame := &codec.Frame{
|
||||||
FrameType: codec.FrameAudio,
|
MediaType: codec.MediaTypeAudio,
|
||||||
AbsTimestamp: aacdp.rtp2ntp(frameTimeStamp),
|
AbsTimestamp: aacdp.rtp2ntp(frameTimeStamp),
|
||||||
Payload: framesPayload[:frameSize],
|
Payload: framesPayload[:frameSize],
|
||||||
}
|
}
|
||||||
|
@@ -77,7 +77,7 @@ type frameWriter struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (fw *frameWriter) WriteFrame(frame *codec.Frame) (err error) {
|
func (fw *frameWriter) WriteFrame(frame *codec.Frame) (err error) {
|
||||||
if frame.FrameType == codec.FrameVideo {
|
if frame.MediaType == codec.MediaTypeVideo {
|
||||||
fw.videoFrames++
|
fw.videoFrames++
|
||||||
if h264.IsSps(frame.Payload[0]) {
|
if h264.IsSps(frame.Payload[0]) {
|
||||||
fw.sps++
|
fw.sps++
|
||||||
|
@@ -67,7 +67,7 @@ func (h264dp *h264Depacketizer) Depacketize(packet *Packet) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
frame := &codec.Frame{
|
frame := &codec.Frame{
|
||||||
FrameType: codec.FrameVideo,
|
MediaType: codec.MediaTypeVideo,
|
||||||
AbsTimestamp: h264dp.rtp2ntp(packet.Timestamp),
|
AbsTimestamp: h264dp.rtp2ntp(packet.Timestamp),
|
||||||
Payload: payload,
|
Payload: payload,
|
||||||
}
|
}
|
||||||
@@ -113,7 +113,7 @@ func (h264dp *h264Depacketizer) depacketizeStapa(packet *Packet) (err error) {
|
|||||||
off += 2
|
off += 2
|
||||||
if payload[off]&0x1f != h264.NalFillerData {
|
if payload[off]&0x1f != h264.NalFillerData {
|
||||||
frame := &codec.Frame{
|
frame := &codec.Frame{
|
||||||
FrameType: codec.FrameVideo,
|
MediaType: codec.MediaTypeVideo,
|
||||||
AbsTimestamp: h264dp.rtp2ntp(packet.Timestamp),
|
AbsTimestamp: h264dp.rtp2ntp(packet.Timestamp),
|
||||||
Payload: make([]byte, nalSize),
|
Payload: make([]byte, nalSize),
|
||||||
}
|
}
|
||||||
@@ -176,7 +176,7 @@ func (h264dp *h264Depacketizer) depacketizeFuA(packet *Packet) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
frame := &codec.Frame{
|
frame := &codec.Frame{
|
||||||
FrameType: codec.FrameVideo,
|
MediaType: codec.MediaTypeVideo,
|
||||||
AbsTimestamp: h264dp.rtp2ntp(packet.Timestamp),
|
AbsTimestamp: h264dp.rtp2ntp(packet.Timestamp),
|
||||||
Payload: make([]byte, frameLen)}
|
Payload: make([]byte, frameLen)}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user