mirror of
https://github.com/ossrs/srs.git
synced 2025-03-09 15:49:59 +00:00
GB: Support HEVC for regression test and load tool for GB. (#3416)
Co-authored-by: Winlin <winlin@vip.126.com> Co-authored-by: chundonglinlin <chundonglinlin@163.com>
This commit is contained in:
parent
733aeaa641
commit
67867242fc
9 changed files with 382 additions and 51 deletions
2
trunk/3rdparty/srs-bench/README.md
vendored
2
trunk/3rdparty/srs-bench/README.md
vendored
|
@ -215,7 +215,7 @@ make && ./objs/srs_gb28181_test -test.v
|
||||||
* `-srs-stream`,GB的user,即流名称,一般会加上随机的后缀。默认值:`3402000000`
|
* `-srs-stream`,GB的user,即流名称,一般会加上随机的后缀。默认值:`3402000000`
|
||||||
* `-srs-timeout`,每个Case的超时时间,毫秒。默认值:`11000`,即11秒。
|
* `-srs-timeout`,每个Case的超时时间,毫秒。默认值:`11000`,即11秒。
|
||||||
* `-srs-publish-audio`,推流时,使用的音频文件。默认值:`avatar.aac`
|
* `-srs-publish-audio`,推流时,使用的音频文件。默认值:`avatar.aac`
|
||||||
* `-srs-publish-video`,推流时,使用的视频文件。默认值:`avatar.h264`
|
* `-srs-publish-video`,推流时,使用的视频文件,注意:扩展名`.h264`表明编码格式为`AVC`,`.h265`表明编码格式为`HEVC`。默认值:`avatar.h264`
|
||||||
* `-srs-publish-video-fps`,推流时,视频文件的FPS。默认值:`25`
|
* `-srs-publish-video-fps`,推流时,视频文件的FPS。默认值:`25`
|
||||||
|
|
||||||
其他不常用参数:
|
其他不常用参数:
|
||||||
|
|
BIN
trunk/3rdparty/srs-bench/avatar.h265
vendored
Normal file
BIN
trunk/3rdparty/srs-bench/avatar.h265
vendored
Normal file
Binary file not shown.
32
trunk/3rdparty/srs-bench/gb28181/gb_test.go
vendored
32
trunk/3rdparty/srs-bench/gb28181/gb_test.go
vendored
|
@ -1,6 +1,6 @@
|
||||||
// The MIT License (MIT)
|
// The MIT License (MIT)
|
||||||
//
|
//
|
||||||
// Copyright (c) 2022 Winlin
|
// # Copyright (c) 2022 Winlin
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
// this software and associated documentation files (the "Software"), to deal in
|
// this software and associated documentation files (the "Software"), to deal in
|
||||||
|
@ -47,6 +47,36 @@ func TestGbPublishRegularly(t *testing.T) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
t.ingester.conf.psConfig.video = "avatar.h264"
|
||||||
|
if err := t.Run(ctx); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}()
|
||||||
|
if err := filterTestError(ctx.Err(), err); err != nil {
|
||||||
|
t.Errorf("err %+v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGbPublishRegularlyH265(t *testing.T) {
|
||||||
|
ctx := logger.WithContext(context.Background())
|
||||||
|
ctx, cancel := context.WithTimeout(ctx, time.Duration(*srsTimeout)*time.Millisecond)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
err := func() error {
|
||||||
|
t := NewGBTestPublisher()
|
||||||
|
defer t.Close()
|
||||||
|
|
||||||
|
var nnPackets int
|
||||||
|
t.ingester.onSendPacket = func(pack *PSPackStream) error {
|
||||||
|
if nnPackets += 1; nnPackets > 10 {
|
||||||
|
cancel()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
t.ingester.conf.psConfig.video = "avatar.h265"
|
||||||
if err := t.Run(ctx); err != nil {
|
if err := t.Run(ctx); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
226
trunk/3rdparty/srs-bench/gb28181/h265reader.go
vendored
Normal file
226
trunk/3rdparty/srs-bench/gb28181/h265reader.go
vendored
Normal file
|
@ -0,0 +1,226 @@
|
||||||
|
// Package h265reader implements a H265 Annex-B Reader
|
||||||
|
package gb28181
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
type NalUnitType uint8
|
||||||
|
|
||||||
|
// Enums for NalUnitTypes
|
||||||
|
const (
|
||||||
|
NaluTypeSliceTrailN NalUnitType = 0 // 0x0
|
||||||
|
NaluTypeSliceTrailR NalUnitType = 1 // 0x01
|
||||||
|
NaluTypeSliceTsaN NalUnitType = 2 // 0x02
|
||||||
|
NaluTypeSliceTsaR NalUnitType = 3 // 0x03
|
||||||
|
NaluTypeSliceStsaN NalUnitType = 4 // 0x04
|
||||||
|
NaluTypeSliceStsaR NalUnitType = 5 // 0x05
|
||||||
|
NaluTypeSliceRadlN NalUnitType = 6 // 0x06
|
||||||
|
NaluTypeSliceRadlR NalUnitType = 7 // 0x07
|
||||||
|
NaluTypeSliceRaslN NalUnitType = 8 // 0x06
|
||||||
|
NaluTypeSliceRaslR NalUnitType = 9 // 0x09
|
||||||
|
|
||||||
|
NaluTypeSliceBlaWlp NalUnitType = 16 // 0x10
|
||||||
|
NaluTypeSliceBlaWradl NalUnitType = 17 // 0x11
|
||||||
|
NaluTypeSliceBlaNlp NalUnitType = 18 // 0x12
|
||||||
|
NaluTypeSliceIdr NalUnitType = 19 // 0x13
|
||||||
|
NaluTypeSliceIdrNlp NalUnitType = 20 // 0x14
|
||||||
|
NaluTypeSliceCranut NalUnitType = 21 // 0x15
|
||||||
|
NaluTypeSliceRsvIrapVcl22 NalUnitType = 22 // 0x16
|
||||||
|
NaluTypeSliceRsvIrapVcl23 NalUnitType = 23 // 0x17
|
||||||
|
|
||||||
|
NaluTypeVps NalUnitType = 32 // 0x20
|
||||||
|
NaluTypeSps NalUnitType = 33 // 0x21
|
||||||
|
NaluTypePps NalUnitType = 34 // 0x22
|
||||||
|
NaluTypeAud NalUnitType = 35 // 0x23
|
||||||
|
NaluTypeSei NalUnitType = 39 // 0x27
|
||||||
|
NaluTypeSeiSuffix NalUnitType = 40 // 0x28
|
||||||
|
|
||||||
|
NaluTypeUnspecified NalUnitType = 48 // 0x30
|
||||||
|
)
|
||||||
|
|
||||||
|
// H265Reader reads data from stream and constructs h265 nal units
|
||||||
|
type H265Reader struct {
|
||||||
|
stream io.Reader
|
||||||
|
nalBuffer []byte
|
||||||
|
countOfConsecutiveZeroBytes int
|
||||||
|
nalPrefixParsed bool
|
||||||
|
readBuffer []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
errNilReader = errors.New("stream is nil")
|
||||||
|
errDataIsNotH265Stream = errors.New("data is not a H265 bitstream")
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewReader creates new H265Reader
|
||||||
|
func NewReader(in io.Reader) (*H265Reader, error) {
|
||||||
|
if in == nil {
|
||||||
|
return nil, errNilReader
|
||||||
|
}
|
||||||
|
|
||||||
|
reader := &H265Reader{
|
||||||
|
stream: in,
|
||||||
|
nalBuffer: make([]byte, 0),
|
||||||
|
nalPrefixParsed: false,
|
||||||
|
readBuffer: make([]byte, 0),
|
||||||
|
}
|
||||||
|
|
||||||
|
return reader, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NAL H.265 Network Abstraction Layer
|
||||||
|
type NAL struct {
|
||||||
|
PictureOrderCount uint32
|
||||||
|
|
||||||
|
// NAL header
|
||||||
|
ForbiddenZeroBit bool
|
||||||
|
UnitType NalUnitType
|
||||||
|
NuhLayerId uint8
|
||||||
|
NuhTemporalIdPlus1 uint8
|
||||||
|
|
||||||
|
Data []byte // header byte + rbsp
|
||||||
|
}
|
||||||
|
|
||||||
|
func (reader *H265Reader) read(numToRead int) (data []byte) {
|
||||||
|
for len(reader.readBuffer) < numToRead {
|
||||||
|
buf := make([]byte, 4096)
|
||||||
|
n, err := reader.stream.Read(buf)
|
||||||
|
if n == 0 || err != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
buf = buf[0:n]
|
||||||
|
reader.readBuffer = append(reader.readBuffer, buf...)
|
||||||
|
}
|
||||||
|
var numShouldRead int
|
||||||
|
if numToRead <= len(reader.readBuffer) {
|
||||||
|
numShouldRead = numToRead
|
||||||
|
} else {
|
||||||
|
numShouldRead = len(reader.readBuffer)
|
||||||
|
}
|
||||||
|
data = reader.readBuffer[0:numShouldRead]
|
||||||
|
reader.readBuffer = reader.readBuffer[numShouldRead:]
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
func (reader *H265Reader) bitStreamStartsWithH265Prefix() (prefixLength int, e error) {
|
||||||
|
nalPrefix3Bytes := []byte{0, 0, 1}
|
||||||
|
nalPrefix4Bytes := []byte{0, 0, 0, 1}
|
||||||
|
|
||||||
|
prefixBuffer := reader.read(4)
|
||||||
|
|
||||||
|
n := len(prefixBuffer)
|
||||||
|
|
||||||
|
if n == 0 {
|
||||||
|
return 0, io.EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
if n < 3 {
|
||||||
|
return 0, errDataIsNotH265Stream
|
||||||
|
}
|
||||||
|
|
||||||
|
nalPrefix3BytesFound := bytes.Equal(nalPrefix3Bytes, prefixBuffer[:3])
|
||||||
|
if n == 3 {
|
||||||
|
if nalPrefix3BytesFound {
|
||||||
|
return 0, io.EOF
|
||||||
|
}
|
||||||
|
return 0, errDataIsNotH265Stream
|
||||||
|
}
|
||||||
|
|
||||||
|
// n == 4
|
||||||
|
if nalPrefix3BytesFound {
|
||||||
|
reader.nalBuffer = append(reader.nalBuffer, prefixBuffer[3])
|
||||||
|
return 3, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
nalPrefix4BytesFound := bytes.Equal(nalPrefix4Bytes, prefixBuffer)
|
||||||
|
if nalPrefix4BytesFound {
|
||||||
|
return 4, nil
|
||||||
|
}
|
||||||
|
return 0, errDataIsNotH265Stream
|
||||||
|
}
|
||||||
|
|
||||||
|
// NextNAL reads from stream and returns then next NAL,
|
||||||
|
// and an error if there is incomplete frame data.
|
||||||
|
// Returns all nil values when no more NALs are available.
|
||||||
|
func (reader *H265Reader) NextNAL() (*NAL, error) {
|
||||||
|
if !reader.nalPrefixParsed {
|
||||||
|
_, err := reader.bitStreamStartsWithH265Prefix()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.nalPrefixParsed = true
|
||||||
|
}
|
||||||
|
|
||||||
|
for {
|
||||||
|
buffer := reader.read(1)
|
||||||
|
n := len(buffer)
|
||||||
|
|
||||||
|
if n != 1 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
readByte := buffer[0]
|
||||||
|
nalFound := reader.processByte(readByte)
|
||||||
|
if nalFound {
|
||||||
|
nal := newNal(reader.nalBuffer)
|
||||||
|
nal.parseHeader()
|
||||||
|
if nal.UnitType == NaluTypeSeiSuffix || nal.UnitType == NaluTypeSei {
|
||||||
|
reader.nalBuffer = nil
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.nalBuffer = append(reader.nalBuffer, readByte)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(reader.nalBuffer) == 0 {
|
||||||
|
return nil, io.EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
nal := newNal(reader.nalBuffer)
|
||||||
|
reader.nalBuffer = nil
|
||||||
|
nal.parseHeader()
|
||||||
|
|
||||||
|
return nal, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (reader *H265Reader) processByte(readByte byte) (nalFound bool) {
|
||||||
|
nalFound = false
|
||||||
|
|
||||||
|
switch readByte {
|
||||||
|
case 0:
|
||||||
|
reader.countOfConsecutiveZeroBytes++
|
||||||
|
case 1:
|
||||||
|
if reader.countOfConsecutiveZeroBytes >= 2 {
|
||||||
|
countOfConsecutiveZeroBytesInPrefix := 2
|
||||||
|
if reader.countOfConsecutiveZeroBytes > 2 {
|
||||||
|
countOfConsecutiveZeroBytesInPrefix = 3
|
||||||
|
}
|
||||||
|
nalUnitLength := len(reader.nalBuffer) - countOfConsecutiveZeroBytesInPrefix
|
||||||
|
reader.nalBuffer = reader.nalBuffer[0:nalUnitLength]
|
||||||
|
reader.countOfConsecutiveZeroBytes = 0
|
||||||
|
nalFound = true
|
||||||
|
} else {
|
||||||
|
reader.countOfConsecutiveZeroBytes = 0
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
reader.countOfConsecutiveZeroBytes = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
return nalFound
|
||||||
|
}
|
||||||
|
|
||||||
|
func newNal(data []byte) *NAL {
|
||||||
|
return &NAL{PictureOrderCount: 0, ForbiddenZeroBit: false, UnitType: NaluTypeUnspecified, Data: data}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *NAL) parseHeader() {
|
||||||
|
firstByte := h.Data[0]
|
||||||
|
h.ForbiddenZeroBit = (((firstByte & 0x80) >> 7) == 1) // 0x80 = 0b10000000
|
||||||
|
h.UnitType = NalUnitType((firstByte & 0x7E) >> 1) // 0x1F = 0b01111110
|
||||||
|
}
|
155
trunk/3rdparty/srs-bench/gb28181/ingester.go
vendored
155
trunk/3rdparty/srs-bench/gb28181/ingester.go
vendored
|
@ -1,6 +1,6 @@
|
||||||
// The MIT License (MIT)
|
// The MIT License (MIT)
|
||||||
//
|
//
|
||||||
// Copyright (c) 2022 Winlin
|
// # Copyright (c) 2022 Winlin
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
// this software and associated documentation files (the "Software"), to deal in
|
// this software and associated documentation files (the "Software"), to deal in
|
||||||
|
@ -26,8 +26,10 @@ import (
|
||||||
"github.com/ossrs/go-oryx-lib/errors"
|
"github.com/ossrs/go-oryx-lib/errors"
|
||||||
"github.com/ossrs/go-oryx-lib/logger"
|
"github.com/ossrs/go-oryx-lib/logger"
|
||||||
"github.com/pion/webrtc/v3/pkg/media/h264reader"
|
"github.com/pion/webrtc/v3/pkg/media/h264reader"
|
||||||
|
"github.com/yapingcat/gomedia/mpeg2"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
"path"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
@ -293,9 +295,16 @@ func (v *PSIngester) Ingest(ctx context.Context) error {
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
|
||||||
h264, err := h264reader.NewReader(videoFile)
|
fileSuffix := path.Ext(v.conf.psConfig.video)
|
||||||
|
var h264 *h264reader.H264Reader
|
||||||
|
var h265 *H265Reader
|
||||||
|
if fileSuffix == ".h265" {
|
||||||
|
h265, err = NewReader(videoFile)
|
||||||
|
} else {
|
||||||
|
h264, err = h264reader.NewReader(videoFile)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrapf(err, "Open h264 %v", v.conf.psConfig.video)
|
return errors.Wrapf(err, "Open %v", v.conf.psConfig.video)
|
||||||
}
|
}
|
||||||
|
|
||||||
audio, err := NewAACReader(f)
|
audio, err := NewAACReader(f)
|
||||||
|
@ -328,47 +337,13 @@ func (v *PSIngester) Ingest(ctx context.Context) error {
|
||||||
|
|
||||||
// One pack should only contains one video frame.
|
// One pack should only contains one video frame.
|
||||||
if !pack.hasVideo {
|
if !pack.hasVideo {
|
||||||
var sps, pps *h264reader.NAL
|
if fileSuffix == ".h265" {
|
||||||
var videoFrames []*h264reader.NAL
|
err = v.writeH265(ctx, pack, h265, videoSampleRate, &avcSamples, &videoDTS)
|
||||||
for ctx.Err() == nil {
|
|
||||||
frame, err := h264.NextNAL()
|
|
||||||
if err == io.EOF {
|
|
||||||
return io.EOF
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrapf(err, "Read h264")
|
|
||||||
}
|
|
||||||
|
|
||||||
videoFrames = append(videoFrames, frame)
|
|
||||||
logger.If(ctx, "NALU %v PictureOrderCount=%v, ForbiddenZeroBit=%v, RefIdc=%v, %v bytes",
|
|
||||||
frame.UnitType.String(), frame.PictureOrderCount, frame.ForbiddenZeroBit, frame.RefIdc, len(frame.Data))
|
|
||||||
|
|
||||||
if frame.UnitType == h264reader.NalUnitTypeSPS {
|
|
||||||
sps = frame
|
|
||||||
} else if frame.UnitType == h264reader.NalUnitTypePPS {
|
|
||||||
pps = frame
|
|
||||||
} else {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// We convert the video sample rate to be based over 1024, that is 1024 samples means one video frame.
|
|
||||||
avcSamples += 1024
|
|
||||||
videoDTS = uint64(v.conf.clockRate*avcSamples) / uint64(videoSampleRate)
|
|
||||||
|
|
||||||
if sps != nil || pps != nil {
|
|
||||||
err = pack.WriteHeader(videoDTS)
|
|
||||||
} else {
|
} else {
|
||||||
err = pack.WritePackHeader(videoDTS)
|
err = v.writeH264(ctx, pack, h264, videoSampleRate, &avcSamples, &videoDTS)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "pack header")
|
return errors.Wrap(err, "WriteVideo")
|
||||||
}
|
|
||||||
|
|
||||||
for _, frame := range videoFrames {
|
|
||||||
if err = pack.WriteVideo(frame.Data, videoDTS); err != nil {
|
|
||||||
return errors.Wrapf(err, "write video %v", len(frame.Data))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -416,3 +391,101 @@ func (v *PSIngester) Ingest(ctx context.Context) error {
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (v *PSIngester) writeH264(ctx context.Context, pack *PSPackStream, h264 *h264reader.H264Reader,
|
||||||
|
videoSampleRate int, avcSamples, videoDTS *uint64) error {
|
||||||
|
var sps, pps *h264reader.NAL
|
||||||
|
var videoFrames []*h264reader.NAL
|
||||||
|
for ctx.Err() == nil {
|
||||||
|
frame, err := h264.NextNAL()
|
||||||
|
if err == io.EOF {
|
||||||
|
return io.EOF
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "Read h264")
|
||||||
|
}
|
||||||
|
|
||||||
|
videoFrames = append(videoFrames, frame)
|
||||||
|
logger.If(ctx, "NALU %v PictureOrderCount=%v, ForbiddenZeroBit=%v, RefIdc=%v, %v bytes",
|
||||||
|
frame.UnitType.String(), frame.PictureOrderCount, frame.ForbiddenZeroBit, frame.RefIdc, len(frame.Data))
|
||||||
|
|
||||||
|
if frame.UnitType == h264reader.NalUnitTypeSPS {
|
||||||
|
sps = frame
|
||||||
|
} else if frame.UnitType == h264reader.NalUnitTypePPS {
|
||||||
|
pps = frame
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We convert the video sample rate to be based over 1024, that is 1024 samples means one video frame.
|
||||||
|
*avcSamples += 1024
|
||||||
|
*videoDTS = uint64(v.conf.clockRate*(*avcSamples)) / uint64(videoSampleRate)
|
||||||
|
|
||||||
|
var err error
|
||||||
|
if sps != nil || pps != nil {
|
||||||
|
err = pack.WriteHeader(mpeg2.PS_STREAM_H264, *videoDTS)
|
||||||
|
} else {
|
||||||
|
err = pack.WritePackHeader(*videoDTS)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "pack header")
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, frame := range videoFrames {
|
||||||
|
if err = pack.WriteVideo(frame.Data, *videoDTS); err != nil {
|
||||||
|
return errors.Wrapf(err, "write video %v", len(frame.Data))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *PSIngester) writeH265(ctx context.Context, pack *PSPackStream, h265 *H265Reader,
|
||||||
|
videoSampleRate int, avcSamples, videoDTS *uint64) error {
|
||||||
|
var vps, sps, pps *NAL
|
||||||
|
var videoFrames []*NAL
|
||||||
|
for ctx.Err() == nil {
|
||||||
|
frame, err := h265.NextNAL()
|
||||||
|
if err == io.EOF {
|
||||||
|
return io.EOF
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "Read h265")
|
||||||
|
}
|
||||||
|
|
||||||
|
videoFrames = append(videoFrames, frame)
|
||||||
|
logger.If(ctx, "NALU %v PictureOrderCount=%v, ForbiddenZeroBit=%v, %v bytes",
|
||||||
|
frame.UnitType, frame.PictureOrderCount, frame.ForbiddenZeroBit, len(frame.Data))
|
||||||
|
|
||||||
|
if frame.UnitType == NaluTypeVps {
|
||||||
|
vps = frame
|
||||||
|
} else if frame.UnitType == NaluTypeSps {
|
||||||
|
sps = frame
|
||||||
|
} else if frame.UnitType == NaluTypePps {
|
||||||
|
pps = frame
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We convert the video sample rate to be based over 1024, that is 1024 samples means one video frame.
|
||||||
|
*avcSamples += 1024
|
||||||
|
*videoDTS = uint64(v.conf.clockRate*(*avcSamples)) / uint64(videoSampleRate)
|
||||||
|
|
||||||
|
var err error
|
||||||
|
if vps != nil || sps != nil || pps != nil {
|
||||||
|
err = pack.WriteHeader(mpeg2.PS_STREAM_H265, *videoDTS)
|
||||||
|
} else {
|
||||||
|
err = pack.WritePackHeader(*videoDTS)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "pack header")
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, frame := range videoFrames {
|
||||||
|
if err = pack.WriteVideo(frame.Data, *videoDTS); err != nil {
|
||||||
|
return errors.Wrapf(err, "write video %v", len(frame.Data))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
11
trunk/3rdparty/srs-bench/gb28181/ps.go
vendored
11
trunk/3rdparty/srs-bench/gb28181/ps.go
vendored
|
@ -1,6 +1,6 @@
|
||||||
// The MIT License (MIT)
|
// The MIT License (MIT)
|
||||||
//
|
//
|
||||||
// Copyright (c) 2022 Winlin
|
// # Copyright (c) 2022 Winlin
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
// this software and associated documentation files (the "Software"), to deal in
|
// this software and associated documentation files (the "Software"), to deal in
|
||||||
|
@ -162,14 +162,14 @@ func NewPSPackStream(pt uint8) *PSPackStream {
|
||||||
return &PSPackStream{ideaPesLength: 1400, pt: pt}
|
return &PSPackStream{ideaPesLength: 1400, pt: pt}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *PSPackStream) WriteHeader(dts uint64) error {
|
func (v *PSPackStream) WriteHeader(videoCodec mpeg2.PS_STREAM_TYPE, dts uint64) error {
|
||||||
if err := v.WritePackHeader(dts); err != nil {
|
if err := v.WritePackHeader(dts); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := v.WriteSystemHeader(dts); err != nil {
|
if err := v.WriteSystemHeader(dts); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := v.WriteProgramStreamMap(dts); err != nil {
|
if err := v.WriteProgramStreamMap(videoCodec, dts); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -215,18 +215,19 @@ func (v *PSPackStream) WriteSystemHeader(dts uint64) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *PSPackStream) WriteProgramStreamMap(dts uint64) error {
|
func (v *PSPackStream) WriteProgramStreamMap(videoCodec mpeg2.PS_STREAM_TYPE, dts uint64) error {
|
||||||
w := codec.NewBitStreamWriter(1500)
|
w := codec.NewBitStreamWriter(1500)
|
||||||
|
|
||||||
psm := &mpeg2.Program_stream_map{
|
psm := &mpeg2.Program_stream_map{
|
||||||
Stream_map: []*mpeg2.Elementary_stream_elem{
|
Stream_map: []*mpeg2.Elementary_stream_elem{
|
||||||
// SrsTsPESStreamIdVideoCommon = 0xe0
|
// SrsTsPESStreamIdVideoCommon = 0xe0
|
||||||
mpeg2.NewElementary_stream_elem(uint8(mpeg2.PS_STREAM_H264), 0xe0),
|
mpeg2.NewElementary_stream_elem(uint8(videoCodec), 0xe0),
|
||||||
// SrsTsPESStreamIdAudioCommon = 0xc0
|
// SrsTsPESStreamIdAudioCommon = 0xc0
|
||||||
mpeg2.NewElementary_stream_elem(uint8(mpeg2.PS_STREAM_AAC), 0xc0),
|
mpeg2.NewElementary_stream_elem(uint8(mpeg2.PS_STREAM_AAC), 0xc0),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
psm.Current_next_indicator = 1
|
||||||
psm.Encode(w)
|
psm.Encode(w)
|
||||||
|
|
||||||
v.packets = append(v.packets, NewPSPacket(PSPacketTypeProgramStramMap, w.Bits(), dts, v.pt))
|
v.packets = append(v.packets, NewPSPacket(PSPacketTypeProgramStramMap, w.Bits(), dts, v.pt))
|
||||||
|
|
4
trunk/3rdparty/srs-bench/gb28181/util.go
vendored
4
trunk/3rdparty/srs-bench/gb28181/util.go
vendored
|
@ -1,6 +1,6 @@
|
||||||
// The MIT License (MIT)
|
// The MIT License (MIT)
|
||||||
//
|
//
|
||||||
// Copyright (c) 2022 Winlin
|
// # Copyright (c) 2022 Winlin
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
// this software and associated documentation files (the "Software"), to deal in
|
// this software and associated documentation files (the "Software"), to deal in
|
||||||
|
@ -65,7 +65,7 @@ func prepareTest() (err error) {
|
||||||
srsMediaTimeout = flag.Int("srs-media-timeout", 2100, "PS media disconnect timeout in ms")
|
srsMediaTimeout = flag.Int("srs-media-timeout", 2100, "PS media disconnect timeout in ms")
|
||||||
srsReinviteTimeout = flag.Int("srs-reinvite-timeout", 1200, "When disconnect, SIP re-invite timeout in ms")
|
srsReinviteTimeout = flag.Int("srs-reinvite-timeout", 1200, "When disconnect, SIP re-invite timeout in ms")
|
||||||
srsPublishAudio = flag.String("srs-publish-audio", "avatar.aac", "The audio file for publisher.")
|
srsPublishAudio = flag.String("srs-publish-audio", "avatar.aac", "The audio file for publisher.")
|
||||||
srsPublishVideo = flag.String("srs-publish-video", "avatar.h264", "The video file for publisher.")
|
srsPublishVideo = flag.String("srs-publish-video", "avatar.h264", "The video file for publisher. Note that *.h264 is for AVC, *.h265 is for HEVC.")
|
||||||
srsPublishVideoFps = flag.Int("srs-publish-video-fps", 25, "The video fps for publisher.")
|
srsPublishVideoFps = flag.Int("srs-publish-video-fps", 25, "The video fps for publisher.")
|
||||||
|
|
||||||
// Should parse it first.
|
// Should parse it first.
|
||||||
|
|
|
@ -8,6 +8,7 @@ The changelog for SRS.
|
||||||
|
|
||||||
## SRS 6.0 Changelog
|
## SRS 6.0 Changelog
|
||||||
|
|
||||||
|
* v6.0, 2023-02-25, Merge [#3416](https://github.com/ossrs/srs/pull/3416): GB: Support HEVC for regression test and load tool for GB. v6.0.29 (#3416)
|
||||||
* v6.0, 2023-02-25, Merge [#3424](https://github.com/ossrs/srs/pull/3424): API: Add service_id for http_hooks, which identify the process. v6.0.28 (#3424)
|
* v6.0, 2023-02-25, Merge [#3424](https://github.com/ossrs/srs/pull/3424): API: Add service_id for http_hooks, which identify the process. v6.0.28 (#3424)
|
||||||
* v6.0, 2023-02-22, Compatible with legacy RTMP URL. v6.0.27
|
* v6.0, 2023-02-22, Compatible with legacy RTMP URL. v6.0.27
|
||||||
* v6.0, 2023-02-16, Merge [#3411](https://github.com/ossrs/srs/pull/3411): HEVC: Fix nalu vec duplicate when h265 vps/sps/pps demux. v6.0.26 (#3411)
|
* v6.0, 2023-02-16, Merge [#3411](https://github.com/ossrs/srs/pull/3411): HEVC: Fix nalu vec duplicate when h265 vps/sps/pps demux. v6.0.26 (#3411)
|
||||||
|
|
|
@ -9,6 +9,6 @@
|
||||||
|
|
||||||
#define VERSION_MAJOR 6
|
#define VERSION_MAJOR 6
|
||||||
#define VERSION_MINOR 0
|
#define VERSION_MINOR 0
|
||||||
#define VERSION_REVISION 28
|
#define VERSION_REVISION 29
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue