mirror of
https://github.com/ossrs/srs.git
synced 2025-02-14 20:31:56 +00:00
GB28181: Enable regression test for gb28181. v5.0.122
1. Build regression test tool for gb28181.
2. Run regression test for gb28181.
3. Format go code and eliminate logs.
4. Change base docker to ubuntu20.
PICK 7750bdae10
This commit is contained in:
parent
bc381a0242
commit
3f7c4a7ff4
32 changed files with 3882 additions and 9727 deletions
17
.github/workflows/test.yml
vendored
17
.github/workflows/test.yml
vendored
|
@ -171,16 +171,15 @@ jobs:
|
|||
uses: actions/checkout@v3
|
||||
# Tests
|
||||
- name: Build test image
|
||||
run: docker build --tag srs:test -f trunk/Dockerfile.test .
|
||||
run: docker build --tag srs:test --build-arg MAKEARGS='-j2' -f trunk/Dockerfile.test .
|
||||
# For utest
|
||||
- name: Run SRS utest
|
||||
run: docker run --rm srs:test bash -c 'make utest && ./objs/srs_utest'
|
||||
run: docker run --rm srs:test ./objs/srs_utest
|
||||
# For regression-test
|
||||
- name: Run SRS regression-test
|
||||
run: |
|
||||
docker run --rm srs:test bash -c 'make && \
|
||||
./objs/srs -c conf/regression-test.conf && \
|
||||
cd 3rdparty/srs-bench && make && ./objs/srs_test -test.v'
|
||||
docker run --rm srs:test bash -c './objs/srs -c conf/regression-test.conf && \
|
||||
cd 3rdparty/srs-bench && ./objs/srs_test -test.v && ./objs/srs_gb28181_test -test.v'
|
||||
runs-on: ubuntu-20.04
|
||||
|
||||
coverage:
|
||||
|
@ -192,7 +191,7 @@ jobs:
|
|||
uses: actions/checkout@v3
|
||||
# Tests
|
||||
- name: Build coverage image
|
||||
run: docker build --tag srs:cov -f trunk/Dockerfile.cov .
|
||||
run: docker build --tag srs:cov --build-arg MAKEARGS='-j2' -f trunk/Dockerfile.cov .
|
||||
# For coverage
|
||||
- name: Run SRS covergae
|
||||
if: ${{ startsWith(github.ref, 'refs/heads/') || startsWith(github.ref, 'refs/pull/') }}
|
||||
|
@ -210,9 +209,9 @@ jobs:
|
|||
#
|
||||
echo "For github.ref=${{ github.ref }}, github.sha=${{ github.sha }}"
|
||||
echo "SRS_BRANCH=$SRS_BRANCH, SRS_PR=$SRS_PR, SRS_SHA=$SRS_SHA, SRS_PROJECT=$SRS_PROJECT"
|
||||
docker run --rm --env CODECOV_TOKEN=$CODECOV_TOKEN \
|
||||
--env SRS_BRANCH=$SRS_BRANCH --env SRS_PR=$SRS_PR --env SRS_SHA=$SRS_SHA --env SRS_PROJECT=$SRS_PROJECT \
|
||||
srs:cov bash -c 'make utest && ./objs/srs_utest && bash auto/codecov.sh'
|
||||
docker run --rm --env CODECOV_TOKEN=$CODECOV_TOKEN --env SRS_BRANCH=$SRS_BRANCH \
|
||||
--env SRS_PR=$SRS_PR --env SRS_SHA=$SRS_SHA --env SRS_PROJECT=$SRS_PROJECT \
|
||||
srs:cov bash -c './objs/srs_utest && bash auto/codecov.sh'
|
||||
#
|
||||
runs-on: ubuntu-20.04
|
||||
|
||||
|
|
1
trunk/3rdparty/srs-bench/.gitignore
vendored
1
trunk/3rdparty/srs-bench/.gitignore
vendored
|
@ -7,3 +7,4 @@ objs
|
|||
|
||||
.format.txt
|
||||
.DS_Store
|
||||
*.log
|
10
trunk/3rdparty/srs-bench/Makefile
vendored
10
trunk/3rdparty/srs-bench/Makefile
vendored
|
@ -3,7 +3,7 @@
|
|||
default: bench test
|
||||
|
||||
clean:
|
||||
rm -f ./objs/srs_bench ./objs/srs_test
|
||||
rm -f ./objs/srs_bench ./objs/srs_test ./objs/srs_gb28181_test
|
||||
|
||||
.format.txt: *.go srs/*.go vnet/*.go janus/*.go gb28181/*.go
|
||||
gofmt -w .
|
||||
|
@ -14,12 +14,16 @@ bench: ./objs/srs_bench
|
|||
./objs/srs_bench: .format.txt *.go srs/*.go vnet/*.go janus/*.go gb28181/*.go Makefile
|
||||
go build -mod=vendor -o objs/srs_bench .
|
||||
|
||||
test: ./objs/srs_test
|
||||
test: ./objs/srs_test ./objs/srs_gb28181_test
|
||||
|
||||
./objs/srs_test: .format.txt *.go srs/*.go vnet/*.go Makefile
|
||||
go test ./srs -mod=vendor -c -o ./objs/srs_test
|
||||
|
||||
./objs/srs_gb28181_test: .format.txt *.go gb28181/*.go Makefile
|
||||
go test ./gb28181 -mod=vendor -c -o ./objs/srs_gb28181_test
|
||||
|
||||
help:
|
||||
@echo "Usage: make [bench|test]"
|
||||
@echo " bench Make the bench to ./objs/srs_bench"
|
||||
@echo " test Make the test tool to ./objs/srs_test"
|
||||
@echo " test Make the test tool to ./objs/srs_test and ./objs/srs_gb28181_test"
|
||||
|
||||
|
|
26
trunk/3rdparty/srs-bench/README.md
vendored
26
trunk/3rdparty/srs-bench/README.md
vendored
|
@ -7,10 +7,20 @@ WebRTC benchmark on [pion/webrtc](https://github.com/pion/webrtc) for [SRS](http
|
|||
编译和使用:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/ossrs/srs-bench.git && git checkout feature/rtc &&
|
||||
make && ./objs/srs_bench -h
|
||||
git clone -b feature/rtc https://github.com/ossrs/srs-bench.git &&
|
||||
cd srs-bench && make && ./objs/srs_bench -h
|
||||
```
|
||||
|
||||
编译和启动SRS:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/ossrs/srs.git &&
|
||||
cd srs/trunk && ./configure && make &&
|
||||
./objs/srs -c conf/console.conf
|
||||
```
|
||||
|
||||
请按下面的操作启动测试。
|
||||
|
||||
## Player for Live
|
||||
|
||||
直播播放压测,一个流,很多个播放。
|
||||
|
@ -102,11 +112,7 @@ ffmpeg -re -i doc/source.200kbps.768x320.flv -c copy -f flv -y rtmp://localhost/
|
|||
回归测试需要先启动[SRS](https://github.com/ossrs/srs/issues/307),支持WebRTC推拉流:
|
||||
|
||||
```bash
|
||||
if [[ ! -z $(ifconfig en0 inet| grep 'inet '|awk '{print $2}') ]]; then
|
||||
docker run -p 1935:1935 -p 8080:8080 -p 1985:1985 -p 8000:8000/udp \
|
||||
--rm --env CANDIDATE=$(ifconfig en0 inet| grep 'inet '|awk '{print $2}')\
|
||||
registry.cn-hangzhou.aliyuncs.com/ossrs/srs:4 objs/srs -c conf/rtc.conf
|
||||
fi
|
||||
./objs/srs -c conf/rtc.conf
|
||||
```
|
||||
|
||||
然后运行回归测试用例,如果只跑一次,可以直接运行:
|
||||
|
@ -235,6 +241,12 @@ make && ./objs/srs_bench -sfu gb28181 --help
|
|||
go test ./gb28181 -mod=vendor -v -count=1
|
||||
```
|
||||
|
||||
也可以用make编译出重复使用的二进制:
|
||||
|
||||
```bash
|
||||
make && ./objs/srs_gb28181_test -test.v
|
||||
```
|
||||
|
||||
支持的参数如下:
|
||||
|
||||
* `-srs-sip`,SIP服务器地址。默认值:`tcp://127.0.0.1:5060`
|
||||
|
|
3112
trunk/3rdparty/srs-bench/avatar.log
vendored
3112
trunk/3rdparty/srs-bench/avatar.log
vendored
File diff suppressed because it is too large
Load diff
2773
trunk/3rdparty/srs-bench/bbb.log
vendored
2773
trunk/3rdparty/srs-bench/bbb.log
vendored
File diff suppressed because it is too large
Load diff
2
trunk/3rdparty/srs-bench/gb28181/gb_test.go
vendored
2
trunk/3rdparty/srs-bench/gb28181/gb_test.go
vendored
|
@ -24,8 +24,8 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
"github.com/ghettovoice/gosip/sip"
|
||||
"github.com/ossrs/go-oryx-lib/logger"
|
||||
"github.com/ossrs/go-oryx-lib/errors"
|
||||
"github.com/ossrs/go-oryx-lib/logger"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
|
4
trunk/3rdparty/srs-bench/vendor/github.com/ghettovoice/gosip/sip/parser/error.go
generated
vendored
4
trunk/3rdparty/srs-bench/vendor/github.com/ghettovoice/gosip/sip/parser/error.go
generated
vendored
|
@ -11,7 +11,9 @@ type InvalidStartLineError string
|
|||
func (err InvalidStartLineError) Syntax() bool { return true }
|
||||
func (err InvalidStartLineError) Malformed() bool { return false }
|
||||
func (err InvalidStartLineError) Broken() bool { return true }
|
||||
func (err InvalidStartLineError) Error() string { return "parser.InvalidStartLineError: " + string(err) }
|
||||
func (err InvalidStartLineError) Error() string {
|
||||
return "parser.InvalidStartLineError: " + string(err)
|
||||
}
|
||||
|
||||
type InvalidMessageFormat string
|
||||
|
||||
|
|
1
trunk/3rdparty/srs-bench/vendor/github.com/sirupsen/logrus/terminal_check_bsd.go
generated
vendored
1
trunk/3rdparty/srs-bench/vendor/github.com/sirupsen/logrus/terminal_check_bsd.go
generated
vendored
|
@ -10,4 +10,3 @@ func isTerminal(fd int) bool {
|
|||
_, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
|
|
1
trunk/3rdparty/srs-bench/vendor/github.com/sirupsen/logrus/terminal_check_unix.go
generated
vendored
1
trunk/3rdparty/srs-bench/vendor/github.com/sirupsen/logrus/terminal_check_unix.go
generated
vendored
|
@ -10,4 +10,3 @@ func isTerminal(fd int) bool {
|
|||
_, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
|
|
|
@ -11,8 +11,8 @@ import (
|
|||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/mgutz/ansi"
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/crypto/ssh/terminal"
|
||||
)
|
||||
|
||||
|
|
274
trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/codec/aac.go
generated
vendored
274
trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/codec/aac.go
generated
vendored
|
@ -12,25 +12,25 @@ import "errors"
|
|||
type AAC_PROFILE int
|
||||
|
||||
const (
|
||||
MAIN AAC_PROFILE = iota
|
||||
LC
|
||||
SSR
|
||||
MAIN AAC_PROFILE = iota
|
||||
LC
|
||||
SSR
|
||||
)
|
||||
|
||||
type AAC_SAMPLING_FREQUENCY int
|
||||
|
||||
const (
|
||||
AAC_SAMPLE_96000 AAC_SAMPLING_FREQUENCY = iota
|
||||
AAC_SAMPLE_88200
|
||||
AAC_SAMPLE_64000
|
||||
AAC_SAMPLE_48000
|
||||
AAC_SAMPLE_44100
|
||||
AAC_SAMPLE_32000
|
||||
AAC_SAMPLE_24000
|
||||
AAC_SAMPLE_22050
|
||||
AAC_SAMPLE_16000
|
||||
AAC_SAMPLE_11025
|
||||
AAC_SAMPLE_8000
|
||||
AAC_SAMPLE_96000 AAC_SAMPLING_FREQUENCY = iota
|
||||
AAC_SAMPLE_88200
|
||||
AAC_SAMPLE_64000
|
||||
AAC_SAMPLE_48000
|
||||
AAC_SAMPLE_44100
|
||||
AAC_SAMPLE_32000
|
||||
AAC_SAMPLE_24000
|
||||
AAC_SAMPLE_22050
|
||||
AAC_SAMPLE_16000
|
||||
AAC_SAMPLE_11025
|
||||
AAC_SAMPLE_8000
|
||||
)
|
||||
|
||||
var AAC_Sampling_Idx [11]int = [11]int{96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 11025, 8000}
|
||||
|
@ -73,15 +73,15 @@ var AAC_Sampling_Idx [11]int = [11]int{96000, 88200, 64000, 48000, 44100, 32000,
|
|||
// }
|
||||
|
||||
type ADTS_Fix_Header struct {
|
||||
ID uint8
|
||||
Layer uint8
|
||||
Protection_absent uint8
|
||||
Profile uint8
|
||||
Sampling_frequency_index uint8
|
||||
Private_bit uint8
|
||||
Channel_configuration uint8
|
||||
Originalorcopy uint8
|
||||
Home uint8
|
||||
ID uint8
|
||||
Layer uint8
|
||||
Protection_absent uint8
|
||||
Profile uint8
|
||||
Sampling_frequency_index uint8
|
||||
Private_bit uint8
|
||||
Channel_configuration uint8
|
||||
Originalorcopy uint8
|
||||
Home uint8
|
||||
}
|
||||
|
||||
// adts_variable_header() {
|
||||
|
@ -93,91 +93,91 @@ type ADTS_Fix_Header struct {
|
|||
// }
|
||||
|
||||
type ADTS_Variable_Header struct {
|
||||
Copyright_identification_bit uint8
|
||||
copyright_identification_start uint8
|
||||
Frame_length uint16
|
||||
Adts_buffer_fullness uint16
|
||||
Number_of_raw_data_blocks_in_frame uint8
|
||||
Copyright_identification_bit uint8
|
||||
copyright_identification_start uint8
|
||||
Frame_length uint16
|
||||
Adts_buffer_fullness uint16
|
||||
Number_of_raw_data_blocks_in_frame uint8
|
||||
}
|
||||
|
||||
type ADTS_Frame_Header struct {
|
||||
Fix_Header ADTS_Fix_Header
|
||||
Variable_Header ADTS_Variable_Header
|
||||
Fix_Header ADTS_Fix_Header
|
||||
Variable_Header ADTS_Variable_Header
|
||||
}
|
||||
|
||||
func NewAdtsFrameHeader() *ADTS_Frame_Header {
|
||||
return &ADTS_Frame_Header{
|
||||
Fix_Header: ADTS_Fix_Header{
|
||||
ID: 0,
|
||||
Layer: 0,
|
||||
Protection_absent: 1,
|
||||
Profile: uint8(MAIN),
|
||||
Sampling_frequency_index: uint8(AAC_SAMPLE_44100),
|
||||
Private_bit: 0,
|
||||
Channel_configuration: 0,
|
||||
Originalorcopy: 0,
|
||||
Home: 0,
|
||||
},
|
||||
return &ADTS_Frame_Header{
|
||||
Fix_Header: ADTS_Fix_Header{
|
||||
ID: 0,
|
||||
Layer: 0,
|
||||
Protection_absent: 1,
|
||||
Profile: uint8(MAIN),
|
||||
Sampling_frequency_index: uint8(AAC_SAMPLE_44100),
|
||||
Private_bit: 0,
|
||||
Channel_configuration: 0,
|
||||
Originalorcopy: 0,
|
||||
Home: 0,
|
||||
},
|
||||
|
||||
Variable_Header: ADTS_Variable_Header{
|
||||
copyright_identification_start: 0,
|
||||
Copyright_identification_bit: 0,
|
||||
Frame_length: 0,
|
||||
Adts_buffer_fullness: 0,
|
||||
Number_of_raw_data_blocks_in_frame: 0,
|
||||
},
|
||||
}
|
||||
Variable_Header: ADTS_Variable_Header{
|
||||
copyright_identification_start: 0,
|
||||
Copyright_identification_bit: 0,
|
||||
Frame_length: 0,
|
||||
Adts_buffer_fullness: 0,
|
||||
Number_of_raw_data_blocks_in_frame: 0,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (frame *ADTS_Frame_Header) Decode(aac []byte) error {
|
||||
_ = aac[6]
|
||||
frame.Fix_Header.ID = aac[1] >> 3
|
||||
frame.Fix_Header.Layer = aac[1] >> 1 & 0x03
|
||||
frame.Fix_Header.Protection_absent = aac[1] & 0x01
|
||||
frame.Fix_Header.Profile = aac[2] >> 6 & 0x03
|
||||
frame.Fix_Header.Sampling_frequency_index = aac[2] >> 2 & 0x0F
|
||||
frame.Fix_Header.Private_bit = aac[2] >> 1 & 0x01
|
||||
frame.Fix_Header.Channel_configuration = (aac[2] & 0x01 << 2) | (aac[3] >> 6)
|
||||
frame.Fix_Header.Originalorcopy = aac[3] >> 5 & 0x01
|
||||
frame.Fix_Header.Home = aac[3] >> 4 & 0x01
|
||||
frame.Variable_Header.Copyright_identification_bit = aac[3] >> 3 & 0x01
|
||||
frame.Variable_Header.copyright_identification_start = aac[3] >> 2 & 0x01
|
||||
frame.Variable_Header.Frame_length = (uint16(aac[3]&0x03) << 11) | (uint16(aac[4]) << 3) | (uint16(aac[5]>>5) & 0x07)
|
||||
frame.Variable_Header.Adts_buffer_fullness = (uint16(aac[5]&0x1F) << 6) | uint16(aac[6]>>2)
|
||||
frame.Variable_Header.Number_of_raw_data_blocks_in_frame = aac[6] & 0x03
|
||||
return nil
|
||||
_ = aac[6]
|
||||
frame.Fix_Header.ID = aac[1] >> 3
|
||||
frame.Fix_Header.Layer = aac[1] >> 1 & 0x03
|
||||
frame.Fix_Header.Protection_absent = aac[1] & 0x01
|
||||
frame.Fix_Header.Profile = aac[2] >> 6 & 0x03
|
||||
frame.Fix_Header.Sampling_frequency_index = aac[2] >> 2 & 0x0F
|
||||
frame.Fix_Header.Private_bit = aac[2] >> 1 & 0x01
|
||||
frame.Fix_Header.Channel_configuration = (aac[2] & 0x01 << 2) | (aac[3] >> 6)
|
||||
frame.Fix_Header.Originalorcopy = aac[3] >> 5 & 0x01
|
||||
frame.Fix_Header.Home = aac[3] >> 4 & 0x01
|
||||
frame.Variable_Header.Copyright_identification_bit = aac[3] >> 3 & 0x01
|
||||
frame.Variable_Header.copyright_identification_start = aac[3] >> 2 & 0x01
|
||||
frame.Variable_Header.Frame_length = (uint16(aac[3]&0x03) << 11) | (uint16(aac[4]) << 3) | (uint16(aac[5]>>5) & 0x07)
|
||||
frame.Variable_Header.Adts_buffer_fullness = (uint16(aac[5]&0x1F) << 6) | uint16(aac[6]>>2)
|
||||
frame.Variable_Header.Number_of_raw_data_blocks_in_frame = aac[6] & 0x03
|
||||
return nil
|
||||
}
|
||||
|
||||
func (frame *ADTS_Frame_Header) Encode() []byte {
|
||||
var hdr []byte
|
||||
if frame.Fix_Header.Protection_absent == 1 {
|
||||
hdr = make([]byte, 7)
|
||||
} else {
|
||||
hdr = make([]byte, 9)
|
||||
}
|
||||
hdr[0] = 0xFF
|
||||
hdr[1] = 0xF0
|
||||
hdr[1] = hdr[1] | (frame.Fix_Header.ID << 3) | (frame.Fix_Header.Layer << 1) | frame.Fix_Header.Protection_absent
|
||||
hdr[2] = frame.Fix_Header.Profile<<6 | frame.Fix_Header.Sampling_frequency_index<<2 | frame.Fix_Header.Private_bit<<1 | frame.Fix_Header.Channel_configuration>>2
|
||||
hdr[3] = frame.Fix_Header.Channel_configuration<<6 | frame.Fix_Header.Originalorcopy<<5 | frame.Fix_Header.Home<<4
|
||||
hdr[3] = hdr[3] | frame.Variable_Header.copyright_identification_start<<3 | frame.Variable_Header.Copyright_identification_bit<<2 | byte(frame.Variable_Header.Frame_length<<11)
|
||||
hdr[4] = byte(frame.Variable_Header.Frame_length >> 3)
|
||||
hdr[5] = byte((frame.Variable_Header.Frame_length&0x07)<<5) | byte(frame.Variable_Header.Adts_buffer_fullness>>3)
|
||||
hdr[6] = byte(frame.Variable_Header.Adts_buffer_fullness&0x3F<<2) | frame.Variable_Header.Number_of_raw_data_blocks_in_frame
|
||||
return hdr
|
||||
var hdr []byte
|
||||
if frame.Fix_Header.Protection_absent == 1 {
|
||||
hdr = make([]byte, 7)
|
||||
} else {
|
||||
hdr = make([]byte, 9)
|
||||
}
|
||||
hdr[0] = 0xFF
|
||||
hdr[1] = 0xF0
|
||||
hdr[1] = hdr[1] | (frame.Fix_Header.ID << 3) | (frame.Fix_Header.Layer << 1) | frame.Fix_Header.Protection_absent
|
||||
hdr[2] = frame.Fix_Header.Profile<<6 | frame.Fix_Header.Sampling_frequency_index<<2 | frame.Fix_Header.Private_bit<<1 | frame.Fix_Header.Channel_configuration>>2
|
||||
hdr[3] = frame.Fix_Header.Channel_configuration<<6 | frame.Fix_Header.Originalorcopy<<5 | frame.Fix_Header.Home<<4
|
||||
hdr[3] = hdr[3] | frame.Variable_Header.copyright_identification_start<<3 | frame.Variable_Header.Copyright_identification_bit<<2 | byte(frame.Variable_Header.Frame_length<<11)
|
||||
hdr[4] = byte(frame.Variable_Header.Frame_length >> 3)
|
||||
hdr[5] = byte((frame.Variable_Header.Frame_length&0x07)<<5) | byte(frame.Variable_Header.Adts_buffer_fullness>>3)
|
||||
hdr[6] = byte(frame.Variable_Header.Adts_buffer_fullness&0x3F<<2) | frame.Variable_Header.Number_of_raw_data_blocks_in_frame
|
||||
return hdr
|
||||
}
|
||||
|
||||
func SampleToAACSampleIndex(sampling int) int {
|
||||
for i, v := range AAC_Sampling_Idx {
|
||||
if v == sampling {
|
||||
return i
|
||||
}
|
||||
}
|
||||
panic("not Found AAC Sample Index")
|
||||
for i, v := range AAC_Sampling_Idx {
|
||||
if v == sampling {
|
||||
return i
|
||||
}
|
||||
}
|
||||
panic("not Found AAC Sample Index")
|
||||
}
|
||||
|
||||
func AACSampleIdxToSample(idx int) int {
|
||||
return AAC_Sampling_Idx[idx]
|
||||
return AAC_Sampling_Idx[idx]
|
||||
}
|
||||
|
||||
// +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
|
@ -185,71 +185,71 @@ func AACSampleIdxToSample(idx int) int {
|
|||
// +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
|
||||
type AudioSpecificConfiguration struct {
|
||||
Audio_object_type uint8
|
||||
Sample_freq_index uint8
|
||||
Channel_configuration uint8
|
||||
GA_framelength_flag uint8
|
||||
GA_depends_on_core_coder uint8
|
||||
GA_extension_flag uint8
|
||||
Audio_object_type uint8
|
||||
Sample_freq_index uint8
|
||||
Channel_configuration uint8
|
||||
GA_framelength_flag uint8
|
||||
GA_depends_on_core_coder uint8
|
||||
GA_extension_flag uint8
|
||||
}
|
||||
|
||||
func NewAudioSpecificConfiguration() *AudioSpecificConfiguration {
|
||||
return &AudioSpecificConfiguration{
|
||||
Audio_object_type: 0,
|
||||
Sample_freq_index: 0,
|
||||
Channel_configuration: 0,
|
||||
GA_framelength_flag: 0,
|
||||
GA_depends_on_core_coder: 0,
|
||||
GA_extension_flag: 0,
|
||||
}
|
||||
return &AudioSpecificConfiguration{
|
||||
Audio_object_type: 0,
|
||||
Sample_freq_index: 0,
|
||||
Channel_configuration: 0,
|
||||
GA_framelength_flag: 0,
|
||||
GA_depends_on_core_coder: 0,
|
||||
GA_extension_flag: 0,
|
||||
}
|
||||
}
|
||||
|
||||
func (asc *AudioSpecificConfiguration) Encode() []byte {
|
||||
buf := make([]byte, 2)
|
||||
buf[0] = (asc.Audio_object_type & 0x1f << 3) | (asc.Sample_freq_index & 0x0F >> 1)
|
||||
buf[1] = (asc.Sample_freq_index & 0x0F << 7) | (asc.Channel_configuration & 0x0F << 3) | (asc.GA_framelength_flag & 0x01 << 2) | (asc.GA_depends_on_core_coder & 0x01 << 1) | (asc.GA_extension_flag & 0x01)
|
||||
return buf
|
||||
buf := make([]byte, 2)
|
||||
buf[0] = (asc.Audio_object_type & 0x1f << 3) | (asc.Sample_freq_index & 0x0F >> 1)
|
||||
buf[1] = (asc.Sample_freq_index & 0x0F << 7) | (asc.Channel_configuration & 0x0F << 3) | (asc.GA_framelength_flag & 0x01 << 2) | (asc.GA_depends_on_core_coder & 0x01 << 1) | (asc.GA_extension_flag & 0x01)
|
||||
return buf
|
||||
}
|
||||
|
||||
func (asc *AudioSpecificConfiguration) Decode(buf []byte) error {
|
||||
|
||||
if len(buf) < 2 {
|
||||
return errors.New("len of buf < 2 ")
|
||||
}
|
||||
if len(buf) < 2 {
|
||||
return errors.New("len of buf < 2 ")
|
||||
}
|
||||
|
||||
asc.Audio_object_type = buf[0] >> 3
|
||||
asc.Sample_freq_index = (buf[0] & 0x07 << 1) | (buf[1] >> 7)
|
||||
asc.Channel_configuration = buf[1] >> 3 & 0x0F
|
||||
asc.GA_framelength_flag = buf[1] >> 2 & 0x01
|
||||
asc.GA_depends_on_core_coder = buf[1] >> 1 & 0x01
|
||||
asc.GA_extension_flag = buf[1] & 0x01
|
||||
return nil
|
||||
asc.Audio_object_type = buf[0] >> 3
|
||||
asc.Sample_freq_index = (buf[0] & 0x07 << 1) | (buf[1] >> 7)
|
||||
asc.Channel_configuration = buf[1] >> 3 & 0x0F
|
||||
asc.GA_framelength_flag = buf[1] >> 2 & 0x01
|
||||
asc.GA_depends_on_core_coder = buf[1] >> 1 & 0x01
|
||||
asc.GA_extension_flag = buf[1] & 0x01
|
||||
return nil
|
||||
}
|
||||
|
||||
func ConvertADTSToASC(frame []byte) ([]byte, error) {
|
||||
|
||||
if len(frame) < 7 {
|
||||
return nil, errors.New("len of frame < 7")
|
||||
}
|
||||
if len(frame) < 7 {
|
||||
return nil, errors.New("len of frame < 7")
|
||||
}
|
||||
|
||||
adts := NewAdtsFrameHeader()
|
||||
adts.Decode(frame)
|
||||
asc := NewAudioSpecificConfiguration()
|
||||
asc.Audio_object_type = adts.Fix_Header.Profile + 1
|
||||
asc.Channel_configuration = adts.Fix_Header.Channel_configuration
|
||||
asc.Sample_freq_index = adts.Fix_Header.Sampling_frequency_index
|
||||
return asc.Encode(), nil
|
||||
adts := NewAdtsFrameHeader()
|
||||
adts.Decode(frame)
|
||||
asc := NewAudioSpecificConfiguration()
|
||||
asc.Audio_object_type = adts.Fix_Header.Profile + 1
|
||||
asc.Channel_configuration = adts.Fix_Header.Channel_configuration
|
||||
asc.Sample_freq_index = adts.Fix_Header.Sampling_frequency_index
|
||||
return asc.Encode(), nil
|
||||
}
|
||||
|
||||
func ConvertASCToADTS(asc []byte, aacbytes int) []byte {
|
||||
aac_asc := NewAudioSpecificConfiguration()
|
||||
aac_asc.Decode(asc)
|
||||
aac_adts := NewAdtsFrameHeader()
|
||||
aac_adts.Fix_Header.Profile = aac_asc.Audio_object_type - 1
|
||||
aac_adts.Fix_Header.Channel_configuration = aac_asc.Channel_configuration
|
||||
aac_adts.Fix_Header.Sampling_frequency_index = aac_asc.Sample_freq_index
|
||||
aac_adts.Fix_Header.Protection_absent = 1
|
||||
aac_adts.Variable_Header.Adts_buffer_fullness = 0x3F
|
||||
aac_adts.Variable_Header.Frame_length = uint16(aacbytes)
|
||||
return aac_adts.Encode()
|
||||
aac_asc := NewAudioSpecificConfiguration()
|
||||
aac_asc.Decode(asc)
|
||||
aac_adts := NewAdtsFrameHeader()
|
||||
aac_adts.Fix_Header.Profile = aac_asc.Audio_object_type - 1
|
||||
aac_adts.Fix_Header.Channel_configuration = aac_asc.Channel_configuration
|
||||
aac_adts.Fix_Header.Sampling_frequency_index = aac_asc.Sample_freq_index
|
||||
aac_adts.Fix_Header.Protection_absent = 1
|
||||
aac_adts.Variable_Header.Adts_buffer_fullness = 0x3F
|
||||
aac_adts.Variable_Header.Frame_length = uint16(aacbytes)
|
||||
return aac_adts.Encode()
|
||||
}
|
||||
|
|
454
trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/codec/bitstream.go
generated
vendored
454
trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/codec/bitstream.go
generated
vendored
|
@ -1,358 +1,358 @@
|
|||
package codec
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"encoding/binary"
|
||||
)
|
||||
|
||||
var BitMask [8]byte = [8]byte{0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF}
|
||||
|
||||
type BitStream struct {
|
||||
bits []byte
|
||||
bytesOffset int
|
||||
bitsOffset int
|
||||
bitsmark int
|
||||
bytemark int
|
||||
bits []byte
|
||||
bytesOffset int
|
||||
bitsOffset int
|
||||
bitsmark int
|
||||
bytemark int
|
||||
}
|
||||
|
||||
func NewBitStream(buf []byte) *BitStream {
|
||||
return &BitStream{
|
||||
bits: buf,
|
||||
bytesOffset: 0,
|
||||
bitsOffset: 0,
|
||||
bitsmark: 0,
|
||||
bytemark: 0,
|
||||
}
|
||||
return &BitStream{
|
||||
bits: buf,
|
||||
bytesOffset: 0,
|
||||
bitsOffset: 0,
|
||||
bitsmark: 0,
|
||||
bytemark: 0,
|
||||
}
|
||||
}
|
||||
|
||||
func (bs *BitStream) Uint8(n int) uint8 {
|
||||
return uint8(bs.GetBits(n))
|
||||
return uint8(bs.GetBits(n))
|
||||
}
|
||||
|
||||
func (bs *BitStream) Uint16(n int) uint16 {
|
||||
return uint16(bs.GetBits(n))
|
||||
return uint16(bs.GetBits(n))
|
||||
}
|
||||
|
||||
func (bs *BitStream) Uint32(n int) uint32 {
|
||||
return uint32(bs.GetBits(n))
|
||||
return uint32(bs.GetBits(n))
|
||||
}
|
||||
|
||||
func (bs *BitStream) GetBytes(n int) []byte {
|
||||
if bs.bytesOffset+n > len(bs.bits) {
|
||||
panic("OUT OF RANGE")
|
||||
}
|
||||
if bs.bitsOffset != 0 {
|
||||
panic("invaild operation")
|
||||
}
|
||||
data := make([]byte, n)
|
||||
copy(data, bs.bits[bs.bytesOffset:bs.bytesOffset+n])
|
||||
bs.bytesOffset += n
|
||||
return data
|
||||
if bs.bytesOffset+n > len(bs.bits) {
|
||||
panic("OUT OF RANGE")
|
||||
}
|
||||
if bs.bitsOffset != 0 {
|
||||
panic("invaild operation")
|
||||
}
|
||||
data := make([]byte, n)
|
||||
copy(data, bs.bits[bs.bytesOffset:bs.bytesOffset+n])
|
||||
bs.bytesOffset += n
|
||||
return data
|
||||
}
|
||||
|
||||
//n <= 64
|
||||
func (bs *BitStream) GetBits(n int) uint64 {
|
||||
if bs.bytesOffset >= len(bs.bits) {
|
||||
panic("OUT OF RANGE")
|
||||
}
|
||||
var ret uint64 = 0
|
||||
if 8-bs.bitsOffset >= n {
|
||||
ret = uint64((bs.bits[bs.bytesOffset] >> (8 - bs.bitsOffset - n)) & BitMask[n-1])
|
||||
bs.bitsOffset += n
|
||||
if bs.bitsOffset == 8 {
|
||||
bs.bytesOffset++
|
||||
bs.bitsOffset = 0
|
||||
}
|
||||
} else {
|
||||
ret = uint64(bs.bits[bs.bytesOffset] & BitMask[8-bs.bitsOffset-1])
|
||||
bs.bytesOffset++
|
||||
n -= 8 - bs.bitsOffset
|
||||
bs.bitsOffset = 0
|
||||
for n > 0 {
|
||||
if bs.bytesOffset >= len(bs.bits) {
|
||||
panic("OUT OF RANGE")
|
||||
}
|
||||
if n >= 8 {
|
||||
ret = ret<<8 | uint64(bs.bits[bs.bytesOffset])
|
||||
bs.bytesOffset++
|
||||
n -= 8
|
||||
} else {
|
||||
ret = (ret << n) | uint64((bs.bits[bs.bytesOffset]>>(8-n))&BitMask[n-1])
|
||||
bs.bitsOffset = n
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret
|
||||
if bs.bytesOffset >= len(bs.bits) {
|
||||
panic("OUT OF RANGE")
|
||||
}
|
||||
var ret uint64 = 0
|
||||
if 8-bs.bitsOffset >= n {
|
||||
ret = uint64((bs.bits[bs.bytesOffset] >> (8 - bs.bitsOffset - n)) & BitMask[n-1])
|
||||
bs.bitsOffset += n
|
||||
if bs.bitsOffset == 8 {
|
||||
bs.bytesOffset++
|
||||
bs.bitsOffset = 0
|
||||
}
|
||||
} else {
|
||||
ret = uint64(bs.bits[bs.bytesOffset] & BitMask[8-bs.bitsOffset-1])
|
||||
bs.bytesOffset++
|
||||
n -= 8 - bs.bitsOffset
|
||||
bs.bitsOffset = 0
|
||||
for n > 0 {
|
||||
if bs.bytesOffset >= len(bs.bits) {
|
||||
panic("OUT OF RANGE")
|
||||
}
|
||||
if n >= 8 {
|
||||
ret = ret<<8 | uint64(bs.bits[bs.bytesOffset])
|
||||
bs.bytesOffset++
|
||||
n -= 8
|
||||
} else {
|
||||
ret = (ret << n) | uint64((bs.bits[bs.bytesOffset]>>(8-n))&BitMask[n-1])
|
||||
bs.bitsOffset = n
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (bs *BitStream) GetBit() uint8 {
|
||||
if bs.bytesOffset >= len(bs.bits) {
|
||||
panic("OUT OF RANGE")
|
||||
}
|
||||
ret := bs.bits[bs.bytesOffset] >> (7 - bs.bitsOffset) & 0x01
|
||||
bs.bitsOffset++
|
||||
if bs.bitsOffset >= 8 {
|
||||
bs.bytesOffset++
|
||||
bs.bitsOffset = 0
|
||||
}
|
||||
return ret
|
||||
if bs.bytesOffset >= len(bs.bits) {
|
||||
panic("OUT OF RANGE")
|
||||
}
|
||||
ret := bs.bits[bs.bytesOffset] >> (7 - bs.bitsOffset) & 0x01
|
||||
bs.bitsOffset++
|
||||
if bs.bitsOffset >= 8 {
|
||||
bs.bytesOffset++
|
||||
bs.bitsOffset = 0
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (bs *BitStream) SkipBits(n int) {
|
||||
bytecount := n / 8
|
||||
bitscount := n % 8
|
||||
bs.bytesOffset += bytecount
|
||||
if bs.bitsOffset+bitscount < 8 {
|
||||
bs.bitsOffset += bitscount
|
||||
} else {
|
||||
bs.bytesOffset += 1
|
||||
bs.bitsOffset += bitscount - 8
|
||||
}
|
||||
bytecount := n / 8
|
||||
bitscount := n % 8
|
||||
bs.bytesOffset += bytecount
|
||||
if bs.bitsOffset+bitscount < 8 {
|
||||
bs.bitsOffset += bitscount
|
||||
} else {
|
||||
bs.bytesOffset += 1
|
||||
bs.bitsOffset += bitscount - 8
|
||||
}
|
||||
}
|
||||
|
||||
func (bs *BitStream) Markdot() {
|
||||
bs.bitsmark = bs.bitsOffset
|
||||
bs.bytemark = bs.bytesOffset
|
||||
bs.bitsmark = bs.bitsOffset
|
||||
bs.bytemark = bs.bytesOffset
|
||||
}
|
||||
|
||||
func (bs *BitStream) DistanceFromMarkDot() int {
|
||||
bytecount := bs.bytesOffset - bs.bytemark - 1
|
||||
bitscount := bs.bitsOffset + (8 - bs.bitsmark)
|
||||
return bytecount*8 + bitscount
|
||||
bytecount := bs.bytesOffset - bs.bytemark - 1
|
||||
bitscount := bs.bitsOffset + (8 - bs.bitsmark)
|
||||
return bytecount*8 + bitscount
|
||||
}
|
||||
|
||||
func (bs *BitStream) RemainBytes() int {
|
||||
if bs.bitsOffset > 0 {
|
||||
return len(bs.bits) - bs.bytesOffset - 1
|
||||
} else {
|
||||
return len(bs.bits) - bs.bytesOffset
|
||||
}
|
||||
if bs.bitsOffset > 0 {
|
||||
return len(bs.bits) - bs.bytesOffset - 1
|
||||
} else {
|
||||
return len(bs.bits) - bs.bytesOffset
|
||||
}
|
||||
}
|
||||
|
||||
func (bs *BitStream) RemainBits() int {
|
||||
if bs.bitsOffset > 0 {
|
||||
return bs.RemainBytes()*8 + 8 - bs.bitsOffset
|
||||
} else {
|
||||
return bs.RemainBytes() * 8
|
||||
}
|
||||
if bs.bitsOffset > 0 {
|
||||
return bs.RemainBytes()*8 + 8 - bs.bitsOffset
|
||||
} else {
|
||||
return bs.RemainBytes() * 8
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (bs *BitStream) Bits() []byte {
|
||||
return bs.bits
|
||||
return bs.bits
|
||||
}
|
||||
|
||||
func (bs *BitStream) RemainData() []byte {
|
||||
return bs.bits[bs.bytesOffset:]
|
||||
return bs.bits[bs.bytesOffset:]
|
||||
}
|
||||
|
||||
//无符号哥伦布熵编码
|
||||
func (bs *BitStream) ReadUE() uint64 {
|
||||
leadingZeroBits := 0
|
||||
for bs.GetBit() == 0 {
|
||||
leadingZeroBits++
|
||||
}
|
||||
if leadingZeroBits == 0 {
|
||||
return 0
|
||||
}
|
||||
info := bs.GetBits(leadingZeroBits)
|
||||
return uint64(1)<<leadingZeroBits - 1 + info
|
||||
leadingZeroBits := 0
|
||||
for bs.GetBit() == 0 {
|
||||
leadingZeroBits++
|
||||
}
|
||||
if leadingZeroBits == 0 {
|
||||
return 0
|
||||
}
|
||||
info := bs.GetBits(leadingZeroBits)
|
||||
return uint64(1)<<leadingZeroBits - 1 + info
|
||||
}
|
||||
|
||||
//有符号哥伦布熵编码
|
||||
func (bs *BitStream) ReadSE() int64 {
|
||||
v := bs.ReadUE()
|
||||
if v%2 == 0 {
|
||||
return -1 * int64(v/2)
|
||||
} else {
|
||||
return int64(v+1) / 2
|
||||
}
|
||||
v := bs.ReadUE()
|
||||
if v%2 == 0 {
|
||||
return -1 * int64(v/2)
|
||||
} else {
|
||||
return int64(v+1) / 2
|
||||
}
|
||||
}
|
||||
|
||||
func (bs *BitStream) ByteOffset() int {
|
||||
return bs.bytesOffset
|
||||
return bs.bytesOffset
|
||||
}
|
||||
|
||||
func (bs *BitStream) UnRead(n int) {
|
||||
if n-bs.bitsOffset <= 0 {
|
||||
bs.bitsOffset -= n
|
||||
} else {
|
||||
least := n - bs.bitsOffset
|
||||
for least >= 8 {
|
||||
bs.bytesOffset--
|
||||
least -= 8
|
||||
}
|
||||
if least > 0 {
|
||||
bs.bytesOffset--
|
||||
bs.bitsOffset = 8 - least
|
||||
}
|
||||
}
|
||||
if n-bs.bitsOffset <= 0 {
|
||||
bs.bitsOffset -= n
|
||||
} else {
|
||||
least := n - bs.bitsOffset
|
||||
for least >= 8 {
|
||||
bs.bytesOffset--
|
||||
least -= 8
|
||||
}
|
||||
if least > 0 {
|
||||
bs.bytesOffset--
|
||||
bs.bitsOffset = 8 - least
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (bs *BitStream) NextBits(n int) uint64 {
|
||||
r := bs.GetBits(n)
|
||||
bs.UnRead(n)
|
||||
return r
|
||||
r := bs.GetBits(n)
|
||||
bs.UnRead(n)
|
||||
return r
|
||||
}
|
||||
|
||||
func (bs *BitStream) EOS() bool {
|
||||
return bs.bytesOffset == len(bs.bits) && bs.bitsOffset == 0
|
||||
return bs.bytesOffset == len(bs.bits) && bs.bitsOffset == 0
|
||||
}
|
||||
|
||||
type BitStreamWriter struct {
|
||||
bits []byte
|
||||
byteoffset int
|
||||
bitsoffset int
|
||||
bitsmark int
|
||||
bytemark int
|
||||
bits []byte
|
||||
byteoffset int
|
||||
bitsoffset int
|
||||
bitsmark int
|
||||
bytemark int
|
||||
}
|
||||
|
||||
func NewBitStreamWriter(n int) *BitStreamWriter {
|
||||
return &BitStreamWriter{
|
||||
bits: make([]byte, n),
|
||||
byteoffset: 0,
|
||||
bitsoffset: 0,
|
||||
bitsmark: 0,
|
||||
bytemark: 0,
|
||||
}
|
||||
return &BitStreamWriter{
|
||||
bits: make([]byte, n),
|
||||
byteoffset: 0,
|
||||
bitsoffset: 0,
|
||||
bitsmark: 0,
|
||||
bytemark: 0,
|
||||
}
|
||||
}
|
||||
|
||||
func (bsw *BitStreamWriter) expandSpace(n int) {
|
||||
if (len(bsw.bits)-bsw.byteoffset-1)*8+8-bsw.bitsoffset < n {
|
||||
newlen := 0
|
||||
if len(bsw.bits)*8 < n {
|
||||
newlen = len(bsw.bits) + n/8 + 1
|
||||
} else {
|
||||
newlen = len(bsw.bits) * 2
|
||||
}
|
||||
tmp := make([]byte, newlen)
|
||||
copy(tmp, bsw.bits)
|
||||
bsw.bits = tmp
|
||||
}
|
||||
if (len(bsw.bits)-bsw.byteoffset-1)*8+8-bsw.bitsoffset < n {
|
||||
newlen := 0
|
||||
if len(bsw.bits)*8 < n {
|
||||
newlen = len(bsw.bits) + n/8 + 1
|
||||
} else {
|
||||
newlen = len(bsw.bits) * 2
|
||||
}
|
||||
tmp := make([]byte, newlen)
|
||||
copy(tmp, bsw.bits)
|
||||
bsw.bits = tmp
|
||||
}
|
||||
}
|
||||
|
||||
func (bsw *BitStreamWriter) ByteOffset() int {
|
||||
return bsw.byteoffset
|
||||
return bsw.byteoffset
|
||||
}
|
||||
|
||||
func (bsw *BitStreamWriter) BitOffset() int {
|
||||
return bsw.bitsoffset
|
||||
return bsw.bitsoffset
|
||||
}
|
||||
|
||||
func (bsw *BitStreamWriter) Markdot() {
|
||||
bsw.bitsmark = bsw.bitsoffset
|
||||
bsw.bytemark = bsw.byteoffset
|
||||
bsw.bitsmark = bsw.bitsoffset
|
||||
bsw.bytemark = bsw.byteoffset
|
||||
}
|
||||
|
||||
func (bsw *BitStreamWriter) DistanceFromMarkDot() int {
|
||||
bytecount := bsw.byteoffset - bsw.bytemark - 1
|
||||
bitscount := bsw.bitsoffset + (8 - bsw.bitsmark)
|
||||
return bytecount*8 + bitscount
|
||||
bytecount := bsw.byteoffset - bsw.bytemark - 1
|
||||
bitscount := bsw.bitsoffset + (8 - bsw.bitsmark)
|
||||
return bytecount*8 + bitscount
|
||||
}
|
||||
|
||||
func (bsw *BitStreamWriter) PutByte(v byte) {
|
||||
bsw.expandSpace(8)
|
||||
if bsw.bitsoffset == 0 {
|
||||
bsw.bits[bsw.byteoffset] = v
|
||||
bsw.byteoffset++
|
||||
} else {
|
||||
bsw.bits[bsw.byteoffset] |= v >> byte(bsw.bitsoffset)
|
||||
bsw.byteoffset++
|
||||
bsw.bits[bsw.byteoffset] = v & BitMask[bsw.bitsoffset-1]
|
||||
}
|
||||
bsw.expandSpace(8)
|
||||
if bsw.bitsoffset == 0 {
|
||||
bsw.bits[bsw.byteoffset] = v
|
||||
bsw.byteoffset++
|
||||
} else {
|
||||
bsw.bits[bsw.byteoffset] |= v >> byte(bsw.bitsoffset)
|
||||
bsw.byteoffset++
|
||||
bsw.bits[bsw.byteoffset] = v & BitMask[bsw.bitsoffset-1]
|
||||
}
|
||||
}
|
||||
|
||||
func (bsw *BitStreamWriter) PutBytes(v []byte) {
|
||||
if bsw.bitsoffset != 0 {
|
||||
panic("bsw.bitsoffset > 0")
|
||||
}
|
||||
bsw.expandSpace(8 * len(v))
|
||||
copy(bsw.bits[bsw.byteoffset:], v)
|
||||
bsw.byteoffset += len(v)
|
||||
if bsw.bitsoffset != 0 {
|
||||
panic("bsw.bitsoffset > 0")
|
||||
}
|
||||
bsw.expandSpace(8 * len(v))
|
||||
copy(bsw.bits[bsw.byteoffset:], v)
|
||||
bsw.byteoffset += len(v)
|
||||
}
|
||||
|
||||
func (bsw *BitStreamWriter) PutRepetValue(v byte, n int) {
|
||||
if bsw.bitsoffset != 0 {
|
||||
panic("bsw.bitsoffset > 0")
|
||||
}
|
||||
bsw.expandSpace(8 * n)
|
||||
for i := 0; i < n; i++ {
|
||||
bsw.bits[bsw.byteoffset] = v
|
||||
bsw.byteoffset++
|
||||
}
|
||||
if bsw.bitsoffset != 0 {
|
||||
panic("bsw.bitsoffset > 0")
|
||||
}
|
||||
bsw.expandSpace(8 * n)
|
||||
for i := 0; i < n; i++ {
|
||||
bsw.bits[bsw.byteoffset] = v
|
||||
bsw.byteoffset++
|
||||
}
|
||||
}
|
||||
|
||||
func (bsw *BitStreamWriter) PutUint8(v uint8, n int) {
|
||||
bsw.PutUint64(uint64(v), n)
|
||||
bsw.PutUint64(uint64(v), n)
|
||||
}
|
||||
|
||||
func (bsw *BitStreamWriter) PutUint16(v uint16, n int) {
|
||||
bsw.PutUint64(uint64(v), n)
|
||||
bsw.PutUint64(uint64(v), n)
|
||||
}
|
||||
|
||||
func (bsw *BitStreamWriter) PutUint32(v uint32, n int) {
|
||||
bsw.PutUint64(uint64(v), n)
|
||||
bsw.PutUint64(uint64(v), n)
|
||||
}
|
||||
|
||||
func (bsw *BitStreamWriter) PutUint64(v uint64, n int) {
|
||||
bsw.expandSpace(n)
|
||||
if 8-bsw.bitsoffset >= n {
|
||||
bsw.bits[bsw.byteoffset] |= uint8(v) & BitMask[n-1] << (8 - bsw.bitsoffset - n)
|
||||
bsw.bitsoffset += n
|
||||
if bsw.bitsoffset == 8 {
|
||||
bsw.bitsoffset = 0
|
||||
bsw.byteoffset++
|
||||
}
|
||||
} else {
|
||||
bsw.bits[bsw.byteoffset] |= uint8(v>>(n-int(8-bsw.bitsoffset))) & BitMask[8-bsw.bitsoffset-1]
|
||||
bsw.byteoffset++
|
||||
n -= 8 - bsw.bitsoffset
|
||||
for n-8 >= 0 {
|
||||
bsw.bits[bsw.byteoffset] = uint8(v>>(n-8)) & 0xFF
|
||||
bsw.byteoffset++
|
||||
n -= 8
|
||||
}
|
||||
bsw.bitsoffset = n
|
||||
if n > 0 {
|
||||
bsw.bits[bsw.byteoffset] |= (uint8(v) & BitMask[n-1]) << (8 - n)
|
||||
}
|
||||
}
|
||||
bsw.expandSpace(n)
|
||||
if 8-bsw.bitsoffset >= n {
|
||||
bsw.bits[bsw.byteoffset] |= uint8(v) & BitMask[n-1] << (8 - bsw.bitsoffset - n)
|
||||
bsw.bitsoffset += n
|
||||
if bsw.bitsoffset == 8 {
|
||||
bsw.bitsoffset = 0
|
||||
bsw.byteoffset++
|
||||
}
|
||||
} else {
|
||||
bsw.bits[bsw.byteoffset] |= uint8(v>>(n-int(8-bsw.bitsoffset))) & BitMask[8-bsw.bitsoffset-1]
|
||||
bsw.byteoffset++
|
||||
n -= 8 - bsw.bitsoffset
|
||||
for n-8 >= 0 {
|
||||
bsw.bits[bsw.byteoffset] = uint8(v>>(n-8)) & 0xFF
|
||||
bsw.byteoffset++
|
||||
n -= 8
|
||||
}
|
||||
bsw.bitsoffset = n
|
||||
if n > 0 {
|
||||
bsw.bits[bsw.byteoffset] |= (uint8(v) & BitMask[n-1]) << (8 - n)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (bsw *BitStreamWriter) SetByte(v byte, where int) {
|
||||
bsw.bits[where] = v
|
||||
bsw.bits[where] = v
|
||||
}
|
||||
|
||||
func (bsw *BitStreamWriter) SetUint16(v uint16, where int) {
|
||||
binary.BigEndian.PutUint16(bsw.bits[where:where+2], v)
|
||||
binary.BigEndian.PutUint16(bsw.bits[where:where+2], v)
|
||||
}
|
||||
|
||||
func (bsw *BitStreamWriter) Bits() []byte {
|
||||
if bsw.byteoffset == len(bsw.bits) {
|
||||
return bsw.bits
|
||||
}
|
||||
if bsw.bitsoffset > 0 {
|
||||
return bsw.bits[0 : bsw.byteoffset+1]
|
||||
} else {
|
||||
return bsw.bits[0:bsw.byteoffset]
|
||||
}
|
||||
if bsw.byteoffset == len(bsw.bits) {
|
||||
return bsw.bits
|
||||
}
|
||||
if bsw.bitsoffset > 0 {
|
||||
return bsw.bits[0 : bsw.byteoffset+1]
|
||||
} else {
|
||||
return bsw.bits[0:bsw.byteoffset]
|
||||
}
|
||||
}
|
||||
|
||||
//用v 填充剩余字节
|
||||
func (bsw *BitStreamWriter) FillRemainData(v byte) {
|
||||
for i := bsw.byteoffset; i < len(bsw.bits); i++ {
|
||||
bsw.bits[i] = v
|
||||
}
|
||||
bsw.byteoffset = len(bsw.bits)
|
||||
bsw.bitsoffset = 0
|
||||
for i := bsw.byteoffset; i < len(bsw.bits); i++ {
|
||||
bsw.bits[i] = v
|
||||
}
|
||||
bsw.byteoffset = len(bsw.bits)
|
||||
bsw.bitsoffset = 0
|
||||
}
|
||||
|
||||
func (bsw *BitStreamWriter) Reset() {
|
||||
for i := 0; i < len(bsw.bits); i++ {
|
||||
bsw.bits[i] = 0
|
||||
}
|
||||
bsw.bitsmark = 0
|
||||
bsw.bytemark = 0
|
||||
bsw.bitsoffset = 0
|
||||
bsw.byteoffset = 0
|
||||
for i := 0; i < len(bsw.bits); i++ {
|
||||
bsw.bits[i] = 0
|
||||
}
|
||||
bsw.bitsmark = 0
|
||||
bsw.bytemark = 0
|
||||
bsw.bitsoffset = 0
|
||||
bsw.byteoffset = 0
|
||||
}
|
||||
|
|
86
trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/codec/codec.go
generated
vendored
86
trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/codec/codec.go
generated
vendored
|
@ -3,62 +3,62 @@ package codec
|
|||
type CodecID int
|
||||
|
||||
const (
|
||||
CODECID_VIDEO_H264 CodecID = iota
|
||||
CODECID_VIDEO_H265
|
||||
CODECID_VIDEO_VP8
|
||||
CODECID_VIDEO_H264 CodecID = iota
|
||||
CODECID_VIDEO_H265
|
||||
CODECID_VIDEO_VP8
|
||||
|
||||
CODECID_AUDIO_AAC CodecID = iota + 98
|
||||
CODECID_AUDIO_G711A
|
||||
CODECID_AUDIO_G711U
|
||||
CODECID_AUDIO_OPUS
|
||||
CODECID_AUDIO_AAC CodecID = iota + 98
|
||||
CODECID_AUDIO_G711A
|
||||
CODECID_AUDIO_G711U
|
||||
CODECID_AUDIO_OPUS
|
||||
|
||||
CODECID_UNRECOGNIZED = 999
|
||||
CODECID_UNRECOGNIZED = 999
|
||||
)
|
||||
|
||||
type H264_NAL_TYPE int
|
||||
|
||||
const (
|
||||
H264_NAL_RESERVED H264_NAL_TYPE = iota
|
||||
H264_NAL_P_SLICE
|
||||
H264_NAL_SLICE_A
|
||||
H264_NAL_SLICE_B
|
||||
H264_NAL_SLICE_C
|
||||
H264_NAL_I_SLICE
|
||||
H264_NAL_SEI
|
||||
H264_NAL_SPS
|
||||
H264_NAL_PPS
|
||||
H264_NAL_AUD
|
||||
H264_NAL_RESERVED H264_NAL_TYPE = iota
|
||||
H264_NAL_P_SLICE
|
||||
H264_NAL_SLICE_A
|
||||
H264_NAL_SLICE_B
|
||||
H264_NAL_SLICE_C
|
||||
H264_NAL_I_SLICE
|
||||
H264_NAL_SEI
|
||||
H264_NAL_SPS
|
||||
H264_NAL_PPS
|
||||
H264_NAL_AUD
|
||||
)
|
||||
|
||||
type H265_NAL_TYPE int
|
||||
|
||||
const (
|
||||
H265_NAL_Slice_TRAIL_N H265_NAL_TYPE = iota
|
||||
H265_NAL_LICE_TRAIL_R
|
||||
H265_NAL_SLICE_TSA_N
|
||||
H265_NAL_SLICE_TSA_R
|
||||
H265_NAL_SLICE_STSA_N
|
||||
H265_NAL_SLICE_STSA_R
|
||||
H265_NAL_SLICE_RADL_N
|
||||
H265_NAL_SLICE_RADL_R
|
||||
H265_NAL_SLICE_RASL_N
|
||||
H265_NAL_SLICE_RASL_R
|
||||
H265_NAL_Slice_TRAIL_N H265_NAL_TYPE = iota
|
||||
H265_NAL_LICE_TRAIL_R
|
||||
H265_NAL_SLICE_TSA_N
|
||||
H265_NAL_SLICE_TSA_R
|
||||
H265_NAL_SLICE_STSA_N
|
||||
H265_NAL_SLICE_STSA_R
|
||||
H265_NAL_SLICE_RADL_N
|
||||
H265_NAL_SLICE_RADL_R
|
||||
H265_NAL_SLICE_RASL_N
|
||||
H265_NAL_SLICE_RASL_R
|
||||
|
||||
//IDR
|
||||
H265_NAL_SLICE_BLA_W_LP H265_NAL_TYPE = iota + 6
|
||||
H265_NAL_SLICE_BLA_W_RADL
|
||||
H265_NAL_SLICE_BLA_N_LP
|
||||
H265_NAL_SLICE_IDR_W_RADL
|
||||
H265_NAL_SLICE_IDR_N_LP
|
||||
H265_NAL_SLICE_CRA
|
||||
//IDR
|
||||
H265_NAL_SLICE_BLA_W_LP H265_NAL_TYPE = iota + 6
|
||||
H265_NAL_SLICE_BLA_W_RADL
|
||||
H265_NAL_SLICE_BLA_N_LP
|
||||
H265_NAL_SLICE_IDR_W_RADL
|
||||
H265_NAL_SLICE_IDR_N_LP
|
||||
H265_NAL_SLICE_CRA
|
||||
|
||||
//vps pps sps
|
||||
H265_NAL_VPS H265_NAL_TYPE = iota + 16
|
||||
H265_NAL_SPS
|
||||
H265_NAL_PPS
|
||||
H265_NAL_AUD
|
||||
//vps pps sps
|
||||
H265_NAL_VPS H265_NAL_TYPE = iota + 16
|
||||
H265_NAL_SPS
|
||||
H265_NAL_PPS
|
||||
H265_NAL_AUD
|
||||
|
||||
//SEI
|
||||
H265_NAL_SEI H265_NAL_TYPE = iota + 19
|
||||
H265_NAL_SEI_SUFFIX
|
||||
//SEI
|
||||
H265_NAL_SEI H265_NAL_TYPE = iota + 19
|
||||
H265_NAL_SEI_SUFFIX
|
||||
)
|
||||
|
|
500
trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/codec/h264.go
generated
vendored
500
trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/codec/h264.go
generated
vendored
|
@ -9,241 +9,241 @@ import "encoding/binary"
|
|||
// }
|
||||
|
||||
type H264NaluHdr struct {
|
||||
Forbidden_zero_bit uint8
|
||||
Nal_ref_idc uint8
|
||||
Nal_unit_type uint8
|
||||
Forbidden_zero_bit uint8
|
||||
Nal_ref_idc uint8
|
||||
Nal_unit_type uint8
|
||||
}
|
||||
|
||||
func (hdr *H264NaluHdr) Decode(bs *BitStream) {
|
||||
hdr.Forbidden_zero_bit = bs.GetBit()
|
||||
hdr.Nal_ref_idc = bs.Uint8(2)
|
||||
hdr.Nal_unit_type = bs.Uint8(5)
|
||||
hdr.Forbidden_zero_bit = bs.GetBit()
|
||||
hdr.Nal_ref_idc = bs.Uint8(2)
|
||||
hdr.Nal_unit_type = bs.Uint8(5)
|
||||
}
|
||||
|
||||
type SliceHeader struct {
|
||||
First_mb_in_slice uint64
|
||||
Slice_type uint64
|
||||
Pic_parameter_set_id uint64
|
||||
Frame_num uint64
|
||||
First_mb_in_slice uint64
|
||||
Slice_type uint64
|
||||
Pic_parameter_set_id uint64
|
||||
Frame_num uint64
|
||||
}
|
||||
|
||||
//调用方根据sps中的log2_max_frame_num_minus4的值来解析Frame_num
|
||||
func (sh *SliceHeader) Decode(bs *BitStream) {
|
||||
sh.First_mb_in_slice = bs.ReadUE()
|
||||
sh.Slice_type = bs.ReadUE()
|
||||
sh.Pic_parameter_set_id = bs.ReadUE()
|
||||
sh.First_mb_in_slice = bs.ReadUE()
|
||||
sh.Slice_type = bs.ReadUE()
|
||||
sh.Pic_parameter_set_id = bs.ReadUE()
|
||||
}
|
||||
|
||||
type SPS struct {
|
||||
Profile_idc uint8
|
||||
Constraint_set0_flag uint8
|
||||
Constraint_set1_flag uint8
|
||||
Constraint_set2_flag uint8
|
||||
Constraint_set3_flag uint8
|
||||
Constraint_set4_flag uint8
|
||||
Constraint_set5_flag uint8
|
||||
Reserved_zero_2bits uint8
|
||||
Level_idc uint8
|
||||
Seq_parameter_set_id uint64
|
||||
Chroma_format_idc uint64
|
||||
Separate_colour_plane_flag uint8
|
||||
Bit_depth_luma_minus8 uint64
|
||||
Bit_depth_chroma_minus8 uint64
|
||||
Log2_max_frame_num_minus4 uint64
|
||||
Pic_order_cnt_type uint64
|
||||
Max_num_ref_frames uint64
|
||||
Gaps_in_frame_num_value_allowed_flag uint8
|
||||
Pic_width_in_mbs_minus1 uint64
|
||||
Pic_height_in_map_units_minus1 uint64
|
||||
Frame_mbs_only_flag uint8
|
||||
Direct_8x8_inference_flag uint8
|
||||
Frame_cropping_flag uint8
|
||||
Frame_crop_left_offset uint64
|
||||
Frame_crop_right_offset uint64
|
||||
Frame_crop_top_offset uint64
|
||||
Frame_crop_bottom_offset uint64
|
||||
Vui_parameters_present_flag uint8
|
||||
Profile_idc uint8
|
||||
Constraint_set0_flag uint8
|
||||
Constraint_set1_flag uint8
|
||||
Constraint_set2_flag uint8
|
||||
Constraint_set3_flag uint8
|
||||
Constraint_set4_flag uint8
|
||||
Constraint_set5_flag uint8
|
||||
Reserved_zero_2bits uint8
|
||||
Level_idc uint8
|
||||
Seq_parameter_set_id uint64
|
||||
Chroma_format_idc uint64
|
||||
Separate_colour_plane_flag uint8
|
||||
Bit_depth_luma_minus8 uint64
|
||||
Bit_depth_chroma_minus8 uint64
|
||||
Log2_max_frame_num_minus4 uint64
|
||||
Pic_order_cnt_type uint64
|
||||
Max_num_ref_frames uint64
|
||||
Gaps_in_frame_num_value_allowed_flag uint8
|
||||
Pic_width_in_mbs_minus1 uint64
|
||||
Pic_height_in_map_units_minus1 uint64
|
||||
Frame_mbs_only_flag uint8
|
||||
Direct_8x8_inference_flag uint8
|
||||
Frame_cropping_flag uint8
|
||||
Frame_crop_left_offset uint64
|
||||
Frame_crop_right_offset uint64
|
||||
Frame_crop_top_offset uint64
|
||||
Frame_crop_bottom_offset uint64
|
||||
Vui_parameters_present_flag uint8
|
||||
}
|
||||
|
||||
func (sps *SPS) Decode(bs *BitStream) {
|
||||
sps.Profile_idc = bs.Uint8(8)
|
||||
sps.Constraint_set0_flag = bs.GetBit()
|
||||
sps.Constraint_set1_flag = bs.GetBit()
|
||||
sps.Constraint_set2_flag = bs.GetBit()
|
||||
sps.Constraint_set3_flag = bs.GetBit()
|
||||
sps.Constraint_set4_flag = bs.GetBit()
|
||||
sps.Constraint_set5_flag = bs.GetBit()
|
||||
sps.Reserved_zero_2bits = bs.Uint8(2)
|
||||
sps.Level_idc = bs.Uint8(8)
|
||||
sps.Seq_parameter_set_id = bs.ReadUE()
|
||||
if sps.Profile_idc == 100 || sps.Profile_idc == 110 ||
|
||||
sps.Profile_idc == 122 || sps.Profile_idc == 244 ||
|
||||
sps.Profile_idc == 44 || sps.Profile_idc == 83 ||
|
||||
sps.Profile_idc == 86 || sps.Profile_idc == 118 || sps.Profile_idc == 128 {
|
||||
sps.Chroma_format_idc = bs.ReadUE()
|
||||
if sps.Chroma_format_idc == 3 {
|
||||
sps.Separate_colour_plane_flag = bs.Uint8(1) //separate_colour_plane_flag
|
||||
}
|
||||
sps.Bit_depth_luma_minus8 = bs.ReadUE() //bit_depth_luma_minus8
|
||||
sps.Bit_depth_chroma_minus8 = bs.ReadUE() //bit_depth_chroma_minus8
|
||||
bs.SkipBits(1) //qpprime_y_zero_transform_bypass_flag
|
||||
seq_scaling_matrix_present_flag := bs.GetBit()
|
||||
if seq_scaling_matrix_present_flag == 1 {
|
||||
//seq_scaling_list_present_flag[i]
|
||||
if sps.Chroma_format_idc == 3 {
|
||||
bs.SkipBits(12)
|
||||
} else {
|
||||
bs.SkipBits(8)
|
||||
}
|
||||
}
|
||||
}
|
||||
sps.Log2_max_frame_num_minus4 = bs.ReadUE()
|
||||
sps.Pic_order_cnt_type = bs.ReadUE()
|
||||
if sps.Pic_order_cnt_type == 0 {
|
||||
bs.ReadUE() // log2_max_pic_order_cnt_lsb_minus4
|
||||
} else if sps.Pic_order_cnt_type == 1 {
|
||||
bs.SkipBits(1) //delta_pic_order_always_zero_flag
|
||||
bs.ReadSE() //offset_for_non_ref_pic
|
||||
bs.ReadSE() //offset_for_top_to_bottom_field
|
||||
num_ref_frames_in_pic_order_cnt_cycle := bs.ReadUE()
|
||||
for i := 0; i < int(num_ref_frames_in_pic_order_cnt_cycle); i++ {
|
||||
bs.ReadSE() //offset_for_ref_frame
|
||||
}
|
||||
}
|
||||
sps.Max_num_ref_frames = bs.ReadUE()
|
||||
sps.Gaps_in_frame_num_value_allowed_flag = bs.GetBit()
|
||||
sps.Pic_width_in_mbs_minus1 = bs.ReadUE()
|
||||
sps.Pic_height_in_map_units_minus1 = bs.ReadUE()
|
||||
sps.Frame_mbs_only_flag = bs.GetBit()
|
||||
if sps.Frame_mbs_only_flag == 0 {
|
||||
bs.SkipBits(1) // mb_adaptive_frame_field_flag
|
||||
}
|
||||
sps.Direct_8x8_inference_flag = bs.GetBit()
|
||||
sps.Frame_cropping_flag = bs.GetBit()
|
||||
if sps.Frame_cropping_flag == 1 {
|
||||
sps.Frame_crop_left_offset = bs.ReadUE() //frame_crop_left_offset
|
||||
sps.Frame_crop_right_offset = bs.ReadUE() //frame_crop_right_offset
|
||||
sps.Frame_crop_top_offset = bs.ReadUE() //frame_crop_top_offset
|
||||
sps.Frame_crop_bottom_offset = bs.ReadUE() //frame_crop_bottom_offset
|
||||
}
|
||||
sps.Vui_parameters_present_flag = bs.GetBit()
|
||||
sps.Profile_idc = bs.Uint8(8)
|
||||
sps.Constraint_set0_flag = bs.GetBit()
|
||||
sps.Constraint_set1_flag = bs.GetBit()
|
||||
sps.Constraint_set2_flag = bs.GetBit()
|
||||
sps.Constraint_set3_flag = bs.GetBit()
|
||||
sps.Constraint_set4_flag = bs.GetBit()
|
||||
sps.Constraint_set5_flag = bs.GetBit()
|
||||
sps.Reserved_zero_2bits = bs.Uint8(2)
|
||||
sps.Level_idc = bs.Uint8(8)
|
||||
sps.Seq_parameter_set_id = bs.ReadUE()
|
||||
if sps.Profile_idc == 100 || sps.Profile_idc == 110 ||
|
||||
sps.Profile_idc == 122 || sps.Profile_idc == 244 ||
|
||||
sps.Profile_idc == 44 || sps.Profile_idc == 83 ||
|
||||
sps.Profile_idc == 86 || sps.Profile_idc == 118 || sps.Profile_idc == 128 {
|
||||
sps.Chroma_format_idc = bs.ReadUE()
|
||||
if sps.Chroma_format_idc == 3 {
|
||||
sps.Separate_colour_plane_flag = bs.Uint8(1) //separate_colour_plane_flag
|
||||
}
|
||||
sps.Bit_depth_luma_minus8 = bs.ReadUE() //bit_depth_luma_minus8
|
||||
sps.Bit_depth_chroma_minus8 = bs.ReadUE() //bit_depth_chroma_minus8
|
||||
bs.SkipBits(1) //qpprime_y_zero_transform_bypass_flag
|
||||
seq_scaling_matrix_present_flag := bs.GetBit()
|
||||
if seq_scaling_matrix_present_flag == 1 {
|
||||
//seq_scaling_list_present_flag[i]
|
||||
if sps.Chroma_format_idc == 3 {
|
||||
bs.SkipBits(12)
|
||||
} else {
|
||||
bs.SkipBits(8)
|
||||
}
|
||||
}
|
||||
}
|
||||
sps.Log2_max_frame_num_minus4 = bs.ReadUE()
|
||||
sps.Pic_order_cnt_type = bs.ReadUE()
|
||||
if sps.Pic_order_cnt_type == 0 {
|
||||
bs.ReadUE() // log2_max_pic_order_cnt_lsb_minus4
|
||||
} else if sps.Pic_order_cnt_type == 1 {
|
||||
bs.SkipBits(1) //delta_pic_order_always_zero_flag
|
||||
bs.ReadSE() //offset_for_non_ref_pic
|
||||
bs.ReadSE() //offset_for_top_to_bottom_field
|
||||
num_ref_frames_in_pic_order_cnt_cycle := bs.ReadUE()
|
||||
for i := 0; i < int(num_ref_frames_in_pic_order_cnt_cycle); i++ {
|
||||
bs.ReadSE() //offset_for_ref_frame
|
||||
}
|
||||
}
|
||||
sps.Max_num_ref_frames = bs.ReadUE()
|
||||
sps.Gaps_in_frame_num_value_allowed_flag = bs.GetBit()
|
||||
sps.Pic_width_in_mbs_minus1 = bs.ReadUE()
|
||||
sps.Pic_height_in_map_units_minus1 = bs.ReadUE()
|
||||
sps.Frame_mbs_only_flag = bs.GetBit()
|
||||
if sps.Frame_mbs_only_flag == 0 {
|
||||
bs.SkipBits(1) // mb_adaptive_frame_field_flag
|
||||
}
|
||||
sps.Direct_8x8_inference_flag = bs.GetBit()
|
||||
sps.Frame_cropping_flag = bs.GetBit()
|
||||
if sps.Frame_cropping_flag == 1 {
|
||||
sps.Frame_crop_left_offset = bs.ReadUE() //frame_crop_left_offset
|
||||
sps.Frame_crop_right_offset = bs.ReadUE() //frame_crop_right_offset
|
||||
sps.Frame_crop_top_offset = bs.ReadUE() //frame_crop_top_offset
|
||||
sps.Frame_crop_bottom_offset = bs.ReadUE() //frame_crop_bottom_offset
|
||||
}
|
||||
sps.Vui_parameters_present_flag = bs.GetBit()
|
||||
}
|
||||
|
||||
type PPS struct {
|
||||
Pic_parameter_set_id uint64
|
||||
Seq_parameter_set_id uint64
|
||||
Entropy_coding_mode_flag uint8
|
||||
Bottom_field_pic_order_in_frame_present_flag uint8
|
||||
Num_slice_groups_minus1 uint64
|
||||
Pic_parameter_set_id uint64
|
||||
Seq_parameter_set_id uint64
|
||||
Entropy_coding_mode_flag uint8
|
||||
Bottom_field_pic_order_in_frame_present_flag uint8
|
||||
Num_slice_groups_minus1 uint64
|
||||
}
|
||||
|
||||
func (pps *PPS) Decode(bs *BitStream) {
|
||||
pps.Pic_parameter_set_id = bs.ReadUE()
|
||||
pps.Seq_parameter_set_id = bs.ReadUE()
|
||||
pps.Entropy_coding_mode_flag = bs.GetBit()
|
||||
pps.Bottom_field_pic_order_in_frame_present_flag = bs.GetBit()
|
||||
pps.Num_slice_groups_minus1 = bs.ReadUE()
|
||||
pps.Pic_parameter_set_id = bs.ReadUE()
|
||||
pps.Seq_parameter_set_id = bs.ReadUE()
|
||||
pps.Entropy_coding_mode_flag = bs.GetBit()
|
||||
pps.Bottom_field_pic_order_in_frame_present_flag = bs.GetBit()
|
||||
pps.Num_slice_groups_minus1 = bs.ReadUE()
|
||||
}
|
||||
|
||||
type SEIReaderWriter interface {
|
||||
Read(size uint16, bs *BitStream)
|
||||
Write(bsw *BitStreamWriter)
|
||||
Read(size uint16, bs *BitStream)
|
||||
Write(bsw *BitStreamWriter)
|
||||
}
|
||||
|
||||
type UserDataUnregistered struct {
|
||||
UUID []byte
|
||||
UserData []byte
|
||||
UUID []byte
|
||||
UserData []byte
|
||||
}
|
||||
|
||||
func (udu *UserDataUnregistered) Read(size uint16, bs *BitStream) {
|
||||
udu.UUID = bs.GetBytes(16)
|
||||
udu.UserData = bs.GetBytes(int(size - 16))
|
||||
udu.UUID = bs.GetBytes(16)
|
||||
udu.UserData = bs.GetBytes(int(size - 16))
|
||||
}
|
||||
|
||||
func (udu *UserDataUnregistered) Write(bsw *BitStreamWriter) {
|
||||
bsw.PutBytes(udu.UUID)
|
||||
bsw.PutBytes(udu.UserData)
|
||||
bsw.PutBytes(udu.UUID)
|
||||
bsw.PutBytes(udu.UserData)
|
||||
}
|
||||
|
||||
type SEI struct {
|
||||
PayloadType uint16
|
||||
PayloadSize uint16
|
||||
Sei_payload SEIReaderWriter
|
||||
PayloadType uint16
|
||||
PayloadSize uint16
|
||||
Sei_payload SEIReaderWriter
|
||||
}
|
||||
|
||||
func (sei *SEI) Decode(bs *BitStream) {
|
||||
for bs.NextBits(8) == 0xFF {
|
||||
sei.PayloadType += 255
|
||||
}
|
||||
sei.PayloadType += uint16(bs.Uint8(8))
|
||||
for bs.NextBits(8) == 0xFF {
|
||||
sei.PayloadSize += 255
|
||||
}
|
||||
sei.PayloadSize += uint16(bs.Uint8(8))
|
||||
if sei.PayloadType == 5 {
|
||||
sei.Sei_payload = new(UserDataUnregistered)
|
||||
sei.Sei_payload.Read(sei.PayloadSize, bs)
|
||||
}
|
||||
for bs.NextBits(8) == 0xFF {
|
||||
sei.PayloadType += 255
|
||||
}
|
||||
sei.PayloadType += uint16(bs.Uint8(8))
|
||||
for bs.NextBits(8) == 0xFF {
|
||||
sei.PayloadSize += 255
|
||||
}
|
||||
sei.PayloadSize += uint16(bs.Uint8(8))
|
||||
if sei.PayloadType == 5 {
|
||||
sei.Sei_payload = new(UserDataUnregistered)
|
||||
sei.Sei_payload.Read(sei.PayloadSize, bs)
|
||||
}
|
||||
}
|
||||
|
||||
func (sei *SEI) Encode(bsw *BitStreamWriter) []byte {
|
||||
payloadType := sei.PayloadType
|
||||
payloadSize := sei.PayloadSize
|
||||
for payloadType >= 0xFF {
|
||||
bsw.PutByte(0xFF)
|
||||
payloadType -= 255
|
||||
}
|
||||
bsw.PutByte(uint8(payloadType))
|
||||
for payloadSize >= 0xFF {
|
||||
bsw.PutByte(0xFF)
|
||||
payloadSize -= 255
|
||||
}
|
||||
bsw.PutByte(uint8(payloadSize))
|
||||
sei.Sei_payload.Write(bsw)
|
||||
return bsw.Bits()
|
||||
payloadType := sei.PayloadType
|
||||
payloadSize := sei.PayloadSize
|
||||
for payloadType >= 0xFF {
|
||||
bsw.PutByte(0xFF)
|
||||
payloadType -= 255
|
||||
}
|
||||
bsw.PutByte(uint8(payloadType))
|
||||
for payloadSize >= 0xFF {
|
||||
bsw.PutByte(0xFF)
|
||||
payloadSize -= 255
|
||||
}
|
||||
bsw.PutByte(uint8(payloadSize))
|
||||
sei.Sei_payload.Write(bsw)
|
||||
return bsw.Bits()
|
||||
}
|
||||
|
||||
func GetSPSIdWithStartCode(sps []byte) uint64 {
|
||||
start, sc := FindStartCode(sps, 0)
|
||||
return GetSPSId(sps[start+int(sc):])
|
||||
start, sc := FindStartCode(sps, 0)
|
||||
return GetSPSId(sps[start+int(sc):])
|
||||
}
|
||||
|
||||
func GetSPSId(sps []byte) uint64 {
|
||||
sps = sps[1:]
|
||||
bs := NewBitStream(sps)
|
||||
bs.SkipBits(24)
|
||||
return bs.ReadUE()
|
||||
sps = sps[1:]
|
||||
bs := NewBitStream(sps)
|
||||
bs.SkipBits(24)
|
||||
return bs.ReadUE()
|
||||
}
|
||||
|
||||
func GetPPSIdWithStartCode(pps []byte) uint64 {
|
||||
start, sc := FindStartCode(pps, 0)
|
||||
return GetPPSId(pps[start+int(sc):])
|
||||
start, sc := FindStartCode(pps, 0)
|
||||
return GetPPSId(pps[start+int(sc):])
|
||||
}
|
||||
|
||||
func GetPPSId(pps []byte) uint64 {
|
||||
pps = pps[1:]
|
||||
bs := NewBitStream(pps)
|
||||
return bs.ReadUE()
|
||||
pps = pps[1:]
|
||||
bs := NewBitStream(pps)
|
||||
return bs.ReadUE()
|
||||
}
|
||||
|
||||
//https://stackoverflow.com/questions/12018535/get-the-width-height-of-the-video-from-h-264-nalu
|
||||
//int Width = ((pic_width_in_mbs_minus1 +1)*16) - frame_crop_right_offset *2 - frame_crop_left_offset *2;
|
||||
//int Height = ((2 - frame_mbs_only_flag)* (pic_height_in_map_units_minus1 +1) * 16) - (frame_crop_bottom_offset* 2) - (frame_crop_top_offset* 2);
|
||||
func GetH264Resolution(sps []byte) (width uint32, height uint32) {
|
||||
start, sc := FindStartCode(sps, 0)
|
||||
bs := NewBitStream(sps[start+int(sc)+1:])
|
||||
var s SPS
|
||||
s.Decode(bs)
|
||||
start, sc := FindStartCode(sps, 0)
|
||||
bs := NewBitStream(sps[start+int(sc)+1:])
|
||||
var s SPS
|
||||
s.Decode(bs)
|
||||
|
||||
widthInSample := (uint32(s.Pic_width_in_mbs_minus1) + 1) * 16
|
||||
widthCrop := uint32(s.Frame_crop_left_offset)*2 - uint32(s.Frame_crop_right_offset)*2
|
||||
width = widthInSample - widthCrop
|
||||
widthInSample := (uint32(s.Pic_width_in_mbs_minus1) + 1) * 16
|
||||
widthCrop := uint32(s.Frame_crop_left_offset)*2 - uint32(s.Frame_crop_right_offset)*2
|
||||
width = widthInSample - widthCrop
|
||||
|
||||
heightInSample := ((2 - uint32(s.Frame_mbs_only_flag)) * (uint32(s.Pic_height_in_map_units_minus1) + 1) * 16)
|
||||
heightCrop := uint32(s.Frame_crop_bottom_offset)*2 - uint32(s.Frame_crop_top_offset)*2
|
||||
height = heightInSample - heightCrop
|
||||
heightInSample := ((2 - uint32(s.Frame_mbs_only_flag)) * (uint32(s.Pic_height_in_map_units_minus1) + 1) * 16)
|
||||
heightCrop := uint32(s.Frame_crop_bottom_offset)*2 - uint32(s.Frame_crop_top_offset)*2
|
||||
height = heightInSample - heightCrop
|
||||
|
||||
return
|
||||
return
|
||||
}
|
||||
|
||||
// aligned(8) class AVCDecoderConfigurationRecord {
|
||||
|
@ -302,95 +302,95 @@ func GetH264Resolution(sps []byte) (width uint32, height uint32) {
|
|||
// variable PPS NALU data
|
||||
|
||||
func CreateH264AVCCExtradata(spss [][]byte, ppss [][]byte) []byte {
|
||||
extradata := make([]byte, 6, 256)
|
||||
for i, sps := range spss {
|
||||
start, sc := FindStartCode(sps, 0)
|
||||
spss[i] = sps[start+int(sc):]
|
||||
}
|
||||
extradata := make([]byte, 6, 256)
|
||||
for i, sps := range spss {
|
||||
start, sc := FindStartCode(sps, 0)
|
||||
spss[i] = sps[start+int(sc):]
|
||||
}
|
||||
|
||||
for i, pps := range ppss {
|
||||
start, sc := FindStartCode(pps, 0)
|
||||
ppss[i] = pps[start+int(sc):]
|
||||
}
|
||||
for i, pps := range ppss {
|
||||
start, sc := FindStartCode(pps, 0)
|
||||
ppss[i] = pps[start+int(sc):]
|
||||
}
|
||||
|
||||
extradata[0] = 0x01
|
||||
extradata[1] = spss[0][1]
|
||||
extradata[2] = spss[0][2]
|
||||
extradata[3] = spss[0][3]
|
||||
extradata[4] = 0xFF
|
||||
extradata[5] = 0xE0 | uint8(len(spss))
|
||||
for _, sps := range spss {
|
||||
spssize := make([]byte, 2)
|
||||
binary.BigEndian.PutUint16(spssize, uint16(len(sps)))
|
||||
extradata = append(extradata, spssize...)
|
||||
extradata = append(extradata, sps...)
|
||||
}
|
||||
extradata = append(extradata, uint8(len(ppss)))
|
||||
for _, pps := range ppss {
|
||||
ppssize := make([]byte, 2)
|
||||
binary.BigEndian.PutUint16(ppssize, uint16(len(pps)))
|
||||
extradata = append(extradata, ppssize...)
|
||||
extradata = append(extradata, pps...)
|
||||
}
|
||||
var h264sps SPS
|
||||
h264sps.Decode(NewBitStream(spss[0][1:]))
|
||||
if h264sps.Profile_idc == 100 ||
|
||||
h264sps.Profile_idc == 110 ||
|
||||
h264sps.Profile_idc == 122 ||
|
||||
h264sps.Profile_idc == 144 {
|
||||
tmp := make([]byte, 4)
|
||||
tmp[0] = 0xFC | uint8(h264sps.Chroma_format_idc&0x03)
|
||||
tmp[1] = 0xF8 | uint8(h264sps.Bit_depth_luma_minus8&0x07)
|
||||
tmp[2] = 0xF8 | uint8(h264sps.Bit_depth_chroma_minus8&0x07)
|
||||
tmp[3] = 0
|
||||
extradata = append(extradata, tmp...)
|
||||
}
|
||||
extradata[0] = 0x01
|
||||
extradata[1] = spss[0][1]
|
||||
extradata[2] = spss[0][2]
|
||||
extradata[3] = spss[0][3]
|
||||
extradata[4] = 0xFF
|
||||
extradata[5] = 0xE0 | uint8(len(spss))
|
||||
for _, sps := range spss {
|
||||
spssize := make([]byte, 2)
|
||||
binary.BigEndian.PutUint16(spssize, uint16(len(sps)))
|
||||
extradata = append(extradata, spssize...)
|
||||
extradata = append(extradata, sps...)
|
||||
}
|
||||
extradata = append(extradata, uint8(len(ppss)))
|
||||
for _, pps := range ppss {
|
||||
ppssize := make([]byte, 2)
|
||||
binary.BigEndian.PutUint16(ppssize, uint16(len(pps)))
|
||||
extradata = append(extradata, ppssize...)
|
||||
extradata = append(extradata, pps...)
|
||||
}
|
||||
var h264sps SPS
|
||||
h264sps.Decode(NewBitStream(spss[0][1:]))
|
||||
if h264sps.Profile_idc == 100 ||
|
||||
h264sps.Profile_idc == 110 ||
|
||||
h264sps.Profile_idc == 122 ||
|
||||
h264sps.Profile_idc == 144 {
|
||||
tmp := make([]byte, 4)
|
||||
tmp[0] = 0xFC | uint8(h264sps.Chroma_format_idc&0x03)
|
||||
tmp[1] = 0xF8 | uint8(h264sps.Bit_depth_luma_minus8&0x07)
|
||||
tmp[2] = 0xF8 | uint8(h264sps.Bit_depth_chroma_minus8&0x07)
|
||||
tmp[3] = 0
|
||||
extradata = append(extradata, tmp...)
|
||||
}
|
||||
|
||||
return extradata
|
||||
return extradata
|
||||
}
|
||||
|
||||
func CovertExtradata(extraData []byte) ([][]byte, [][]byte) {
|
||||
spsnum := extraData[5] & 0x1F
|
||||
spss := make([][]byte, spsnum)
|
||||
offset := 6
|
||||
for i := 0; i < int(spsnum); i++ {
|
||||
spssize := binary.BigEndian.Uint16(extraData[offset:])
|
||||
sps := make([]byte, spssize+4)
|
||||
copy(sps, []byte{0x00, 0x00, 0x00, 0x01})
|
||||
copy(sps[4:], extraData[offset+2:offset+2+int(spssize)])
|
||||
offset += 2 + int(spssize)
|
||||
spss[i] = sps
|
||||
}
|
||||
ppsnum := extraData[offset]
|
||||
ppss := make([][]byte, ppsnum)
|
||||
offset++
|
||||
for i := 0; i < int(ppsnum); i++ {
|
||||
ppssize := binary.BigEndian.Uint16(extraData[offset:])
|
||||
pps := make([]byte, ppssize+4)
|
||||
copy(pps, []byte{0x00, 0x00, 0x00, 0x01})
|
||||
copy(pps[4:], extraData[offset+2:offset+2+int(ppssize)])
|
||||
offset += 2 + int(ppssize)
|
||||
ppss[i] = pps
|
||||
}
|
||||
return spss, ppss
|
||||
spsnum := extraData[5] & 0x1F
|
||||
spss := make([][]byte, spsnum)
|
||||
offset := 6
|
||||
for i := 0; i < int(spsnum); i++ {
|
||||
spssize := binary.BigEndian.Uint16(extraData[offset:])
|
||||
sps := make([]byte, spssize+4)
|
||||
copy(sps, []byte{0x00, 0x00, 0x00, 0x01})
|
||||
copy(sps[4:], extraData[offset+2:offset+2+int(spssize)])
|
||||
offset += 2 + int(spssize)
|
||||
spss[i] = sps
|
||||
}
|
||||
ppsnum := extraData[offset]
|
||||
ppss := make([][]byte, ppsnum)
|
||||
offset++
|
||||
for i := 0; i < int(ppsnum); i++ {
|
||||
ppssize := binary.BigEndian.Uint16(extraData[offset:])
|
||||
pps := make([]byte, ppssize+4)
|
||||
copy(pps, []byte{0x00, 0x00, 0x00, 0x01})
|
||||
copy(pps[4:], extraData[offset+2:offset+2+int(ppssize)])
|
||||
offset += 2 + int(ppssize)
|
||||
ppss[i] = pps
|
||||
}
|
||||
return spss, ppss
|
||||
}
|
||||
|
||||
func ConvertAnnexBToAVCC(annexb []byte) []byte {
|
||||
start, sc := FindStartCode(annexb, 0)
|
||||
if sc == START_CODE_4 {
|
||||
binary.BigEndian.PutUint32(annexb[start:], uint32(len(annexb)-4))
|
||||
return annexb
|
||||
} else {
|
||||
avcc := make([]byte, 1+len(annexb))
|
||||
binary.BigEndian.PutUint32(avcc, uint32(len(annexb)-3))
|
||||
copy(avcc[4:], annexb[start+3:])
|
||||
return avcc
|
||||
}
|
||||
start, sc := FindStartCode(annexb, 0)
|
||||
if sc == START_CODE_4 {
|
||||
binary.BigEndian.PutUint32(annexb[start:], uint32(len(annexb)-4))
|
||||
return annexb
|
||||
} else {
|
||||
avcc := make([]byte, 1+len(annexb))
|
||||
binary.BigEndian.PutUint32(avcc, uint32(len(annexb)-3))
|
||||
copy(avcc[4:], annexb[start+3:])
|
||||
return avcc
|
||||
}
|
||||
}
|
||||
|
||||
func CovertAVCCToAnnexB(avcc []byte) {
|
||||
avcc[0] = 0x00
|
||||
avcc[1] = 0x00
|
||||
avcc[2] = 0x00
|
||||
avcc[3] = 0x01
|
||||
avcc[0] = 0x00
|
||||
avcc[1] = 0x00
|
||||
avcc[2] = 0x00
|
||||
avcc[3] = 0x01
|
||||
}
|
||||
|
|
1652
trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/codec/h265.go
generated
vendored
1652
trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/codec/h265.go
generated
vendored
File diff suppressed because it is too large
Load diff
398
trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/codec/opus.go
generated
vendored
398
trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/codec/opus.go
generated
vendored
|
@ -1,8 +1,8 @@
|
|||
package codec
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
)
|
||||
|
||||
// rfc6716 https://datatracker.ietf.org/doc/html/rfc6716
|
||||
|
@ -157,169 +157,169 @@ import (
|
|||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
var (
|
||||
/// 10ms,20ms,40ms,60ms, samplerate 48000
|
||||
// sample num per millisecond
|
||||
// 48000 / 1000ms * 10 = 480 ...
|
||||
SLKOpusSampleSize [4]int = [4]int{480, 960, 1920, 2880}
|
||||
HybridOpusSampleSize [4]int = [4]int{480, 960}
|
||||
CELTOpusSampleSize [4]int = [4]int{120, 210, 480, 960}
|
||||
/// 10ms,20ms,40ms,60ms, samplerate 48000
|
||||
// sample num per millisecond
|
||||
// 48000 / 1000ms * 10 = 480 ...
|
||||
SLKOpusSampleSize [4]int = [4]int{480, 960, 1920, 2880}
|
||||
HybridOpusSampleSize [4]int = [4]int{480, 960}
|
||||
CELTOpusSampleSize [4]int = [4]int{120, 210, 480, 960}
|
||||
)
|
||||
|
||||
func OpusPacketDuration(packet []byte) uint64 {
|
||||
config := int(packet[0] >> 3)
|
||||
code := packet[0] & 0x03
|
||||
frameCount := 0
|
||||
var duration uint64
|
||||
if code == 0 {
|
||||
frameCount = 1
|
||||
} else if code == 1 || code == 2 {
|
||||
frameCount = 2
|
||||
} else if code == 3 {
|
||||
frameCount = int(packet[1] & 0x1F)
|
||||
} else {
|
||||
panic("code must <= 3")
|
||||
}
|
||||
config := int(packet[0] >> 3)
|
||||
code := packet[0] & 0x03
|
||||
frameCount := 0
|
||||
var duration uint64
|
||||
if code == 0 {
|
||||
frameCount = 1
|
||||
} else if code == 1 || code == 2 {
|
||||
frameCount = 2
|
||||
} else if code == 3 {
|
||||
frameCount = int(packet[1] & 0x1F)
|
||||
} else {
|
||||
panic("code must <= 3")
|
||||
}
|
||||
|
||||
switch {
|
||||
case config >= 0 && config < 12:
|
||||
duration = uint64(frameCount * SLKOpusSampleSize[config%4])
|
||||
case config >= 12 && config < 16:
|
||||
duration = uint64(frameCount * HybridOpusSampleSize[config%2])
|
||||
case config >= 16 && config < 32:
|
||||
duration = uint64(frameCount * CELTOpusSampleSize[config%4])
|
||||
default:
|
||||
panic("unkown opus config")
|
||||
}
|
||||
switch {
|
||||
case config >= 0 && config < 12:
|
||||
duration = uint64(frameCount * SLKOpusSampleSize[config%4])
|
||||
case config >= 12 && config < 16:
|
||||
duration = uint64(frameCount * HybridOpusSampleSize[config%2])
|
||||
case config >= 16 && config < 32:
|
||||
duration = uint64(frameCount * CELTOpusSampleSize[config%4])
|
||||
default:
|
||||
panic("unkown opus config")
|
||||
}
|
||||
|
||||
return duration
|
||||
return duration
|
||||
}
|
||||
|
||||
//ffmpeg opus.h OpusPacket
|
||||
type OpusPacket struct {
|
||||
Code int
|
||||
Config int
|
||||
Stereo int
|
||||
Vbr int
|
||||
FrameCount int
|
||||
FrameLen []uint16
|
||||
Frame []byte
|
||||
Duration uint64
|
||||
Code int
|
||||
Config int
|
||||
Stereo int
|
||||
Vbr int
|
||||
FrameCount int
|
||||
FrameLen []uint16
|
||||
Frame []byte
|
||||
Duration uint64
|
||||
}
|
||||
|
||||
func DecodeOpusPacket(packet []byte) *OpusPacket {
|
||||
pkt := &OpusPacket{}
|
||||
pkt.Code = int(packet[0] & 0x03)
|
||||
pkt.Stereo = int((packet[0] >> 2) & 0x01)
|
||||
pkt.Config = int(packet[0] >> 3)
|
||||
pkt := &OpusPacket{}
|
||||
pkt.Code = int(packet[0] & 0x03)
|
||||
pkt.Stereo = int((packet[0] >> 2) & 0x01)
|
||||
pkt.Config = int(packet[0] >> 3)
|
||||
|
||||
switch pkt.Code {
|
||||
case 0:
|
||||
pkt.FrameCount = 1
|
||||
pkt.FrameLen = make([]uint16, 1)
|
||||
pkt.FrameLen[0] = uint16(len(packet) - 1)
|
||||
pkt.Frame = packet[1:]
|
||||
case 1:
|
||||
pkt.FrameCount = 2
|
||||
pkt.FrameLen = make([]uint16, 1)
|
||||
pkt.FrameLen[0] = uint16(len(packet)-1) / 2
|
||||
pkt.Frame = packet[1:]
|
||||
case 2:
|
||||
pkt.FrameCount = 2
|
||||
hdr := 1
|
||||
N1 := int(packet[1])
|
||||
if N1 >= 252 {
|
||||
N1 = N1 + int(packet[2]*4)
|
||||
hdr = 2
|
||||
}
|
||||
pkt.FrameLen = make([]uint16, 2)
|
||||
pkt.FrameLen[0] = uint16(N1)
|
||||
pkt.FrameLen[1] = uint16(len(packet)-hdr) - uint16(N1)
|
||||
case 3:
|
||||
hdr := 2
|
||||
pkt.Vbr = int(packet[1] >> 7)
|
||||
padding := packet[1] >> 6
|
||||
pkt.FrameCount = int(packet[1] & 0x1F)
|
||||
paddingLen := 0
|
||||
if padding == 1 {
|
||||
for packet[hdr] == 255 {
|
||||
paddingLen += 254
|
||||
hdr++
|
||||
}
|
||||
paddingLen += int(packet[hdr])
|
||||
}
|
||||
switch pkt.Code {
|
||||
case 0:
|
||||
pkt.FrameCount = 1
|
||||
pkt.FrameLen = make([]uint16, 1)
|
||||
pkt.FrameLen[0] = uint16(len(packet) - 1)
|
||||
pkt.Frame = packet[1:]
|
||||
case 1:
|
||||
pkt.FrameCount = 2
|
||||
pkt.FrameLen = make([]uint16, 1)
|
||||
pkt.FrameLen[0] = uint16(len(packet)-1) / 2
|
||||
pkt.Frame = packet[1:]
|
||||
case 2:
|
||||
pkt.FrameCount = 2
|
||||
hdr := 1
|
||||
N1 := int(packet[1])
|
||||
if N1 >= 252 {
|
||||
N1 = N1 + int(packet[2]*4)
|
||||
hdr = 2
|
||||
}
|
||||
pkt.FrameLen = make([]uint16, 2)
|
||||
pkt.FrameLen[0] = uint16(N1)
|
||||
pkt.FrameLen[1] = uint16(len(packet)-hdr) - uint16(N1)
|
||||
case 3:
|
||||
hdr := 2
|
||||
pkt.Vbr = int(packet[1] >> 7)
|
||||
padding := packet[1] >> 6
|
||||
pkt.FrameCount = int(packet[1] & 0x1F)
|
||||
paddingLen := 0
|
||||
if padding == 1 {
|
||||
for packet[hdr] == 255 {
|
||||
paddingLen += 254
|
||||
hdr++
|
||||
}
|
||||
paddingLen += int(packet[hdr])
|
||||
}
|
||||
|
||||
if pkt.Vbr == 0 {
|
||||
pkt.FrameLen = make([]uint16, 1)
|
||||
pkt.FrameLen[0] = uint16(len(packet)-hdr-paddingLen) / uint16(pkt.FrameCount)
|
||||
pkt.Frame = packet[hdr : hdr+int(pkt.FrameLen[0]*uint16(pkt.FrameCount))]
|
||||
} else {
|
||||
n := 0
|
||||
for i := 0; i < int(pkt.FrameCount)-1; i++ {
|
||||
N1 := int(packet[hdr])
|
||||
hdr += 1
|
||||
if N1 >= 252 {
|
||||
N1 = N1 + int(packet[hdr]*4)
|
||||
hdr += 1
|
||||
}
|
||||
n += N1
|
||||
pkt.FrameLen = append(pkt.FrameLen, uint16(N1))
|
||||
}
|
||||
lastFrameLen := len(packet) - hdr - paddingLen - n
|
||||
pkt.FrameLen = append(pkt.FrameLen, uint16(lastFrameLen))
|
||||
pkt.Frame = packet[hdr : hdr+n+lastFrameLen]
|
||||
}
|
||||
default:
|
||||
panic("Error C must <= 3")
|
||||
}
|
||||
OpusPacketDuration(packet)
|
||||
return pkt
|
||||
if pkt.Vbr == 0 {
|
||||
pkt.FrameLen = make([]uint16, 1)
|
||||
pkt.FrameLen[0] = uint16(len(packet)-hdr-paddingLen) / uint16(pkt.FrameCount)
|
||||
pkt.Frame = packet[hdr : hdr+int(pkt.FrameLen[0]*uint16(pkt.FrameCount))]
|
||||
} else {
|
||||
n := 0
|
||||
for i := 0; i < int(pkt.FrameCount)-1; i++ {
|
||||
N1 := int(packet[hdr])
|
||||
hdr += 1
|
||||
if N1 >= 252 {
|
||||
N1 = N1 + int(packet[hdr]*4)
|
||||
hdr += 1
|
||||
}
|
||||
n += N1
|
||||
pkt.FrameLen = append(pkt.FrameLen, uint16(N1))
|
||||
}
|
||||
lastFrameLen := len(packet) - hdr - paddingLen - n
|
||||
pkt.FrameLen = append(pkt.FrameLen, uint16(lastFrameLen))
|
||||
pkt.Frame = packet[hdr : hdr+n+lastFrameLen]
|
||||
}
|
||||
default:
|
||||
panic("Error C must <= 3")
|
||||
}
|
||||
OpusPacketDuration(packet)
|
||||
return pkt
|
||||
}
|
||||
|
||||
const (
|
||||
LEFT_CHANNEL = 0
|
||||
RIGHT_CHANNEL = 1
|
||||
LEFT_CHANNEL = 0
|
||||
RIGHT_CHANNEL = 1
|
||||
)
|
||||
|
||||
var (
|
||||
vorbisChanLayoutOffset [8][8]byte = [8][8]byte{
|
||||
{0},
|
||||
{0, 1},
|
||||
{0, 2, 1},
|
||||
{0, 1, 2, 3},
|
||||
{0, 2, 1, 3, 4},
|
||||
{0, 2, 1, 5, 3, 4},
|
||||
{0, 2, 1, 6, 5, 3, 4},
|
||||
{0, 2, 1, 7, 5, 6, 3, 4},
|
||||
}
|
||||
vorbisChanLayoutOffset [8][8]byte = [8][8]byte{
|
||||
{0},
|
||||
{0, 1},
|
||||
{0, 2, 1},
|
||||
{0, 1, 2, 3},
|
||||
{0, 2, 1, 3, 4},
|
||||
{0, 2, 1, 5, 3, 4},
|
||||
{0, 2, 1, 6, 5, 3, 4},
|
||||
{0, 2, 1, 7, 5, 6, 3, 4},
|
||||
}
|
||||
)
|
||||
|
||||
type ChannelOrder func(channels int, idx int) int
|
||||
|
||||
func defalutOrder(channels int, idx int) int {
|
||||
return idx
|
||||
return idx
|
||||
}
|
||||
|
||||
func vorbisOrder(channels int, idx int) int {
|
||||
return int(vorbisChanLayoutOffset[channels-1][idx])
|
||||
return int(vorbisChanLayoutOffset[channels-1][idx])
|
||||
}
|
||||
|
||||
type ChannelMap struct {
|
||||
StreamIdx int
|
||||
ChannelIdx int
|
||||
Silence bool
|
||||
Copy bool
|
||||
CopyFrom int
|
||||
StreamIdx int
|
||||
ChannelIdx int
|
||||
Silence bool
|
||||
Copy bool
|
||||
CopyFrom int
|
||||
}
|
||||
|
||||
type OpusContext struct {
|
||||
Preskip int
|
||||
SampleRate int
|
||||
ChannelCount int
|
||||
StreamCount int
|
||||
StereoStreamCount int
|
||||
OutputGain uint16
|
||||
MapType uint8
|
||||
ChannelMaps []ChannelMap
|
||||
Preskip int
|
||||
SampleRate int
|
||||
ChannelCount int
|
||||
StreamCount int
|
||||
StereoStreamCount int
|
||||
OutputGain uint16
|
||||
MapType uint8
|
||||
ChannelMaps []ChannelMap
|
||||
}
|
||||
|
||||
// opus ID Head
|
||||
|
@ -348,83 +348,83 @@ type OpusContext struct {
|
|||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
//
|
||||
func (ctx *OpusContext) ParseExtranData(extraData []byte) error {
|
||||
if string(extraData[0:8]) != "OpusHead" {
|
||||
return errors.New("magic signature must equal OpusHead")
|
||||
}
|
||||
if string(extraData[0:8]) != "OpusHead" {
|
||||
return errors.New("magic signature must equal OpusHead")
|
||||
}
|
||||
|
||||
_ = extraData[8] // version
|
||||
ctx.ChannelCount = int(extraData[9])
|
||||
ctx.Preskip = int(binary.LittleEndian.Uint16(extraData[10:]))
|
||||
ctx.SampleRate = int(binary.LittleEndian.Uint32(extraData[12:]))
|
||||
ctx.OutputGain = binary.LittleEndian.Uint16(extraData[16:])
|
||||
ctx.MapType = extraData[18]
|
||||
var channel []byte
|
||||
var order ChannelOrder
|
||||
if ctx.MapType == 0 {
|
||||
ctx.StreamCount = 1
|
||||
ctx.StereoStreamCount = ctx.ChannelCount - 1
|
||||
channel = []byte{0, 1}
|
||||
order = defalutOrder
|
||||
} else if ctx.MapType == 1 || ctx.MapType == 2 || ctx.MapType == 255 {
|
||||
ctx.StreamCount = int(extraData[19])
|
||||
ctx.StereoStreamCount = int(extraData[20])
|
||||
if ctx.MapType == 1 {
|
||||
channel = extraData[21 : 21+ctx.ChannelCount]
|
||||
order = vorbisOrder
|
||||
}
|
||||
} else {
|
||||
return errors.New("unsupport map type 255")
|
||||
}
|
||||
_ = extraData[8] // version
|
||||
ctx.ChannelCount = int(extraData[9])
|
||||
ctx.Preskip = int(binary.LittleEndian.Uint16(extraData[10:]))
|
||||
ctx.SampleRate = int(binary.LittleEndian.Uint32(extraData[12:]))
|
||||
ctx.OutputGain = binary.LittleEndian.Uint16(extraData[16:])
|
||||
ctx.MapType = extraData[18]
|
||||
var channel []byte
|
||||
var order ChannelOrder
|
||||
if ctx.MapType == 0 {
|
||||
ctx.StreamCount = 1
|
||||
ctx.StereoStreamCount = ctx.ChannelCount - 1
|
||||
channel = []byte{0, 1}
|
||||
order = defalutOrder
|
||||
} else if ctx.MapType == 1 || ctx.MapType == 2 || ctx.MapType == 255 {
|
||||
ctx.StreamCount = int(extraData[19])
|
||||
ctx.StereoStreamCount = int(extraData[20])
|
||||
if ctx.MapType == 1 {
|
||||
channel = extraData[21 : 21+ctx.ChannelCount]
|
||||
order = vorbisOrder
|
||||
}
|
||||
} else {
|
||||
return errors.New("unsupport map type 255")
|
||||
}
|
||||
|
||||
for i := 0; i < ctx.ChannelCount; i++ {
|
||||
cm := ChannelMap{}
|
||||
index := channel[order(ctx.ChannelCount, i)]
|
||||
if index == 255 {
|
||||
cm.Silence = true
|
||||
continue
|
||||
} else if index > byte(ctx.StereoStreamCount)+byte(ctx.StreamCount) {
|
||||
return errors.New("index must < (streamcount + stereo streamcount)")
|
||||
}
|
||||
for i := 0; i < ctx.ChannelCount; i++ {
|
||||
cm := ChannelMap{}
|
||||
index := channel[order(ctx.ChannelCount, i)]
|
||||
if index == 255 {
|
||||
cm.Silence = true
|
||||
continue
|
||||
} else if index > byte(ctx.StereoStreamCount)+byte(ctx.StreamCount) {
|
||||
return errors.New("index must < (streamcount + stereo streamcount)")
|
||||
}
|
||||
|
||||
for j := 0; j < i; j++ {
|
||||
if channel[order(ctx.ChannelCount, i)] == index {
|
||||
cm.Copy = true
|
||||
cm.CopyFrom = j
|
||||
break
|
||||
}
|
||||
}
|
||||
for j := 0; j < i; j++ {
|
||||
if channel[order(ctx.ChannelCount, i)] == index {
|
||||
cm.Copy = true
|
||||
cm.CopyFrom = j
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if int(index) < 2*ctx.StereoStreamCount {
|
||||
cm.StreamIdx = int(index) / 2
|
||||
if index&1 == 0 {
|
||||
cm.ChannelIdx = LEFT_CHANNEL
|
||||
} else {
|
||||
cm.ChannelIdx = RIGHT_CHANNEL
|
||||
}
|
||||
} else {
|
||||
cm.StreamIdx = int(index) - ctx.StereoStreamCount
|
||||
cm.ChannelIdx = 0
|
||||
}
|
||||
ctx.ChannelMaps = append(ctx.ChannelMaps, cm)
|
||||
}
|
||||
if int(index) < 2*ctx.StereoStreamCount {
|
||||
cm.StreamIdx = int(index) / 2
|
||||
if index&1 == 0 {
|
||||
cm.ChannelIdx = LEFT_CHANNEL
|
||||
} else {
|
||||
cm.ChannelIdx = RIGHT_CHANNEL
|
||||
}
|
||||
} else {
|
||||
cm.StreamIdx = int(index) - ctx.StereoStreamCount
|
||||
cm.ChannelIdx = 0
|
||||
}
|
||||
ctx.ChannelMaps = append(ctx.ChannelMaps, cm)
|
||||
}
|
||||
|
||||
return nil
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ctx *OpusContext) WriteOpusExtraData() []byte {
|
||||
extraData := make([]byte, 19)
|
||||
copy(extraData, string("OpusHead"))
|
||||
extraData[8] = 0x01
|
||||
extraData[9] = byte(ctx.ChannelCount)
|
||||
binary.LittleEndian.PutUint16(extraData[10:], uint16(ctx.Preskip))
|
||||
binary.LittleEndian.PutUint32(extraData[12:], uint32(ctx.SampleRate))
|
||||
return extraData
|
||||
extraData := make([]byte, 19)
|
||||
copy(extraData, string("OpusHead"))
|
||||
extraData[8] = 0x01
|
||||
extraData[9] = byte(ctx.ChannelCount)
|
||||
binary.LittleEndian.PutUint16(extraData[10:], uint16(ctx.Preskip))
|
||||
binary.LittleEndian.PutUint32(extraData[12:], uint32(ctx.SampleRate))
|
||||
return extraData
|
||||
}
|
||||
|
||||
func WriteDefaultOpusExtraData() []byte {
|
||||
return []byte{
|
||||
'O', 'p', 'u', 's', 'H', 'e', 'a', 'd',
|
||||
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
}
|
||||
return []byte{
|
||||
'O', 'p', 'u', 's', 'H', 'e', 'a', 'd',
|
||||
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
}
|
||||
}
|
||||
|
|
370
trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/codec/util.go
generated
vendored
370
trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/codec/util.go
generated
vendored
|
@ -5,253 +5,253 @@ import "fmt"
|
|||
type START_CODE_TYPE int
|
||||
|
||||
const (
|
||||
START_CODE_3 START_CODE_TYPE = 3
|
||||
START_CODE_4 = 4
|
||||
START_CODE_3 START_CODE_TYPE = 3
|
||||
START_CODE_4 = 4
|
||||
)
|
||||
|
||||
func FindStartCode(nalu []byte, offset int) (int, START_CODE_TYPE) {
|
||||
for i := offset; i < len(nalu)-4; i++ {
|
||||
if nalu[i] == 0x00 && nalu[i+1] == 0x00 {
|
||||
if nalu[i+2] == 0x01 {
|
||||
return i, START_CODE_3
|
||||
} else if nalu[i+2] == 0x00 && nalu[i+3] == 0x01 {
|
||||
return i, START_CODE_4
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1, START_CODE_3
|
||||
for i := offset; i < len(nalu)-4; i++ {
|
||||
if nalu[i] == 0x00 && nalu[i+1] == 0x00 {
|
||||
if nalu[i+2] == 0x01 {
|
||||
return i, START_CODE_3
|
||||
} else if nalu[i+2] == 0x00 && nalu[i+3] == 0x01 {
|
||||
return i, START_CODE_4
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1, START_CODE_3
|
||||
}
|
||||
|
||||
func FindSyncword(aac []byte, offset int) int {
|
||||
for i := offset; i < len(aac); i++ {
|
||||
if aac[i] == 0xFF && aac[i+1]&0xF0 == 0xF0 {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return -1
|
||||
for i := offset; i < len(aac); i++ {
|
||||
if aac[i] == 0xFF && aac[i+1]&0xF0 == 0xF0 {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
func SplitFrame(frames []byte, onFrame func(nalu []byte) bool) {
|
||||
beg, sc := FindStartCode(frames, 0)
|
||||
for beg >= 0 {
|
||||
end, sc2 := FindStartCode(frames, beg+int(sc))
|
||||
if end == -1 {
|
||||
if onFrame != nil {
|
||||
onFrame(frames[beg+int(sc):])
|
||||
}
|
||||
break
|
||||
}
|
||||
if onFrame != nil && onFrame(frames[beg+int(sc):end]) == false {
|
||||
break
|
||||
}
|
||||
beg = end
|
||||
sc = sc2
|
||||
}
|
||||
beg, sc := FindStartCode(frames, 0)
|
||||
for beg >= 0 {
|
||||
end, sc2 := FindStartCode(frames, beg+int(sc))
|
||||
if end == -1 {
|
||||
if onFrame != nil {
|
||||
onFrame(frames[beg+int(sc):])
|
||||
}
|
||||
break
|
||||
}
|
||||
if onFrame != nil && onFrame(frames[beg+int(sc):end]) == false {
|
||||
break
|
||||
}
|
||||
beg = end
|
||||
sc = sc2
|
||||
}
|
||||
}
|
||||
|
||||
func SplitFrameWithStartCode(frames []byte, onFrame func(nalu []byte) bool) {
|
||||
beg, sc := FindStartCode(frames, 0)
|
||||
for beg >= 0 {
|
||||
end, sc2 := FindStartCode(frames, beg+int(sc))
|
||||
if end == -1 {
|
||||
if onFrame != nil {
|
||||
onFrame(frames[beg:])
|
||||
}
|
||||
break
|
||||
}
|
||||
if onFrame != nil && onFrame(frames[beg:end]) == false {
|
||||
break
|
||||
}
|
||||
beg = end
|
||||
sc = sc2
|
||||
}
|
||||
beg, sc := FindStartCode(frames, 0)
|
||||
for beg >= 0 {
|
||||
end, sc2 := FindStartCode(frames, beg+int(sc))
|
||||
if end == -1 {
|
||||
if onFrame != nil {
|
||||
onFrame(frames[beg:])
|
||||
}
|
||||
break
|
||||
}
|
||||
if onFrame != nil && onFrame(frames[beg:end]) == false {
|
||||
break
|
||||
}
|
||||
beg = end
|
||||
sc = sc2
|
||||
}
|
||||
}
|
||||
|
||||
func SplitAACFrame(frames []byte, onFrame func(aac []byte)) {
|
||||
var adts ADTS_Frame_Header
|
||||
start := FindSyncword(frames, 0)
|
||||
for start >= 0 {
|
||||
adts.Decode(frames[start:])
|
||||
onFrame(frames[start : start+int(adts.Variable_Header.Frame_length)])
|
||||
start = FindSyncword(frames, start+int(adts.Variable_Header.Frame_length))
|
||||
}
|
||||
var adts ADTS_Frame_Header
|
||||
start := FindSyncword(frames, 0)
|
||||
for start >= 0 {
|
||||
adts.Decode(frames[start:])
|
||||
onFrame(frames[start : start+int(adts.Variable_Header.Frame_length)])
|
||||
start = FindSyncword(frames, start+int(adts.Variable_Header.Frame_length))
|
||||
}
|
||||
}
|
||||
|
||||
func H264NaluType(h264 []byte) H264_NAL_TYPE {
|
||||
loc, sc := FindStartCode(h264, 0)
|
||||
return H264_NAL_TYPE(h264[loc+int(sc)] & 0x1F)
|
||||
loc, sc := FindStartCode(h264, 0)
|
||||
return H264_NAL_TYPE(h264[loc+int(sc)] & 0x1F)
|
||||
}
|
||||
|
||||
func H264NaluTypeWithoutStartCode(h264 []byte) H264_NAL_TYPE {
|
||||
return H264_NAL_TYPE(h264[0] & 0x1F)
|
||||
return H264_NAL_TYPE(h264[0] & 0x1F)
|
||||
}
|
||||
|
||||
func H265NaluType(h265 []byte) H265_NAL_TYPE {
|
||||
loc, sc := FindStartCode(h265, 0)
|
||||
return H265_NAL_TYPE((h265[loc+int(sc)] >> 1) & 0x3F)
|
||||
loc, sc := FindStartCode(h265, 0)
|
||||
return H265_NAL_TYPE((h265[loc+int(sc)] >> 1) & 0x3F)
|
||||
}
|
||||
|
||||
func H265NaluTypeWithoutStartCode(h265 []byte) H265_NAL_TYPE {
|
||||
return H265_NAL_TYPE((h265[0] >> 1) & 0x3F)
|
||||
return H265_NAL_TYPE((h265[0] >> 1) & 0x3F)
|
||||
}
|
||||
|
||||
func GetH264FirstMbInSlice(nalu []byte) uint64 {
|
||||
start, sc := FindStartCode(nalu, 0)
|
||||
bs := NewBitStream(nalu[start+int(sc)+1:])
|
||||
sliceHdr := &SliceHeader{}
|
||||
sliceHdr.Decode(bs)
|
||||
return sliceHdr.First_mb_in_slice
|
||||
start, sc := FindStartCode(nalu, 0)
|
||||
bs := NewBitStream(nalu[start+int(sc)+1:])
|
||||
sliceHdr := &SliceHeader{}
|
||||
sliceHdr.Decode(bs)
|
||||
return sliceHdr.First_mb_in_slice
|
||||
}
|
||||
|
||||
func GetH265FirstMbInSlice(nalu []byte) uint64 {
|
||||
start, sc := FindStartCode(nalu, 0)
|
||||
bs := NewBitStream(nalu[start+int(sc)+2:])
|
||||
sliceHdr := &SliceHeader{}
|
||||
sliceHdr.Decode(bs)
|
||||
return sliceHdr.First_mb_in_slice
|
||||
start, sc := FindStartCode(nalu, 0)
|
||||
bs := NewBitStream(nalu[start+int(sc)+2:])
|
||||
sliceHdr := &SliceHeader{}
|
||||
sliceHdr.Decode(bs)
|
||||
return sliceHdr.First_mb_in_slice
|
||||
}
|
||||
|
||||
func IsH264IDRFrame(h264 []byte) bool {
|
||||
|
||||
ret := false
|
||||
onnalu := func(nalu []byte) bool {
|
||||
nal_type := H264NaluTypeWithoutStartCode(nalu)
|
||||
if nal_type < 5 {
|
||||
return false
|
||||
} else if nal_type == 5 {
|
||||
ret = true
|
||||
return false
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
}
|
||||
SplitFrame(h264, onnalu)
|
||||
return ret
|
||||
ret := false
|
||||
onnalu := func(nalu []byte) bool {
|
||||
nal_type := H264NaluTypeWithoutStartCode(nalu)
|
||||
if nal_type < 5 {
|
||||
return false
|
||||
} else if nal_type == 5 {
|
||||
ret = true
|
||||
return false
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
}
|
||||
SplitFrame(h264, onnalu)
|
||||
return ret
|
||||
}
|
||||
|
||||
func IsH264VCLNaluType(nal_type H264_NAL_TYPE) bool {
|
||||
if nal_type <= H264_NAL_I_SLICE && nal_type > H264_NAL_RESERVED {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
if nal_type <= H264_NAL_I_SLICE && nal_type > H264_NAL_RESERVED {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func IsH265VCLNaluType(nal_type H265_NAL_TYPE) bool {
|
||||
if (nal_type <= H265_NAL_SLICE_CRA && nal_type >= H265_NAL_SLICE_BLA_W_LP) ||
|
||||
(nal_type <= H265_NAL_SLICE_RASL_R && nal_type >= H265_NAL_Slice_TRAIL_N) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
if (nal_type <= H265_NAL_SLICE_CRA && nal_type >= H265_NAL_SLICE_BLA_W_LP) ||
|
||||
(nal_type <= H265_NAL_SLICE_RASL_R && nal_type >= H265_NAL_Slice_TRAIL_N) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func IsH265IDRFrame(h265 []byte) bool {
|
||||
ret := false
|
||||
onnalu := func(nalu []byte) bool {
|
||||
nal_type := H264NaluTypeWithoutStartCode(nalu)
|
||||
if nal_type <= 9 && nal_type >= 0 {
|
||||
return false
|
||||
} else if nal_type >= 16 && nal_type <= 21 {
|
||||
ret = true
|
||||
return false
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
}
|
||||
SplitFrame(h265, onnalu)
|
||||
return ret
|
||||
ret := false
|
||||
onnalu := func(nalu []byte) bool {
|
||||
nal_type := H264NaluTypeWithoutStartCode(nalu)
|
||||
if nal_type <= 9 && nal_type >= 0 {
|
||||
return false
|
||||
} else if nal_type >= 16 && nal_type <= 21 {
|
||||
ret = true
|
||||
return false
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
}
|
||||
SplitFrame(h265, onnalu)
|
||||
return ret
|
||||
}
|
||||
|
||||
func Max(x, y int) int {
|
||||
if x > y {
|
||||
return x
|
||||
} else {
|
||||
return y
|
||||
}
|
||||
if x > y {
|
||||
return x
|
||||
} else {
|
||||
return y
|
||||
}
|
||||
}
|
||||
|
||||
func Min(x, y int) int {
|
||||
if x > y {
|
||||
return y
|
||||
} else {
|
||||
return x
|
||||
}
|
||||
if x > y {
|
||||
return y
|
||||
} else {
|
||||
return x
|
||||
}
|
||||
}
|
||||
|
||||
func ShowPacketHexdump(data []byte) {
|
||||
for k := 0; k < len(data); k++ {
|
||||
if k%8 == 0 && k != 0 {
|
||||
fmt.Printf("\n")
|
||||
}
|
||||
fmt.Printf("%02x ", data[k])
|
||||
}
|
||||
fmt.Printf("\n")
|
||||
for k := 0; k < len(data); k++ {
|
||||
if k%8 == 0 && k != 0 {
|
||||
fmt.Printf("\n")
|
||||
}
|
||||
fmt.Printf("%02x ", data[k])
|
||||
}
|
||||
fmt.Printf("\n")
|
||||
}
|
||||
|
||||
var crc32table [256]uint32 = [256]uint32{
|
||||
0x00000000, 0xB71DC104, 0x6E3B8209, 0xD926430D, 0xDC760413, 0x6B6BC517,
|
||||
0xB24D861A, 0x0550471E, 0xB8ED0826, 0x0FF0C922, 0xD6D68A2F, 0x61CB4B2B,
|
||||
0x649B0C35, 0xD386CD31, 0x0AA08E3C, 0xBDBD4F38, 0x70DB114C, 0xC7C6D048,
|
||||
0x1EE09345, 0xA9FD5241, 0xACAD155F, 0x1BB0D45B, 0xC2969756, 0x758B5652,
|
||||
0xC836196A, 0x7F2BD86E, 0xA60D9B63, 0x11105A67, 0x14401D79, 0xA35DDC7D,
|
||||
0x7A7B9F70, 0xCD665E74, 0xE0B62398, 0x57ABE29C, 0x8E8DA191, 0x39906095,
|
||||
0x3CC0278B, 0x8BDDE68F, 0x52FBA582, 0xE5E66486, 0x585B2BBE, 0xEF46EABA,
|
||||
0x3660A9B7, 0x817D68B3, 0x842D2FAD, 0x3330EEA9, 0xEA16ADA4, 0x5D0B6CA0,
|
||||
0x906D32D4, 0x2770F3D0, 0xFE56B0DD, 0x494B71D9, 0x4C1B36C7, 0xFB06F7C3,
|
||||
0x2220B4CE, 0x953D75CA, 0x28803AF2, 0x9F9DFBF6, 0x46BBB8FB, 0xF1A679FF,
|
||||
0xF4F63EE1, 0x43EBFFE5, 0x9ACDBCE8, 0x2DD07DEC, 0x77708634, 0xC06D4730,
|
||||
0x194B043D, 0xAE56C539, 0xAB068227, 0x1C1B4323, 0xC53D002E, 0x7220C12A,
|
||||
0xCF9D8E12, 0x78804F16, 0xA1A60C1B, 0x16BBCD1F, 0x13EB8A01, 0xA4F64B05,
|
||||
0x7DD00808, 0xCACDC90C, 0x07AB9778, 0xB0B6567C, 0x69901571, 0xDE8DD475,
|
||||
0xDBDD936B, 0x6CC0526F, 0xB5E61162, 0x02FBD066, 0xBF469F5E, 0x085B5E5A,
|
||||
0xD17D1D57, 0x6660DC53, 0x63309B4D, 0xD42D5A49, 0x0D0B1944, 0xBA16D840,
|
||||
0x97C6A5AC, 0x20DB64A8, 0xF9FD27A5, 0x4EE0E6A1, 0x4BB0A1BF, 0xFCAD60BB,
|
||||
0x258B23B6, 0x9296E2B2, 0x2F2BAD8A, 0x98366C8E, 0x41102F83, 0xF60DEE87,
|
||||
0xF35DA999, 0x4440689D, 0x9D662B90, 0x2A7BEA94, 0xE71DB4E0, 0x500075E4,
|
||||
0x892636E9, 0x3E3BF7ED, 0x3B6BB0F3, 0x8C7671F7, 0x555032FA, 0xE24DF3FE,
|
||||
0x5FF0BCC6, 0xE8ED7DC2, 0x31CB3ECF, 0x86D6FFCB, 0x8386B8D5, 0x349B79D1,
|
||||
0xEDBD3ADC, 0x5AA0FBD8, 0xEEE00C69, 0x59FDCD6D, 0x80DB8E60, 0x37C64F64,
|
||||
0x3296087A, 0x858BC97E, 0x5CAD8A73, 0xEBB04B77, 0x560D044F, 0xE110C54B,
|
||||
0x38368646, 0x8F2B4742, 0x8A7B005C, 0x3D66C158, 0xE4408255, 0x535D4351,
|
||||
0x9E3B1D25, 0x2926DC21, 0xF0009F2C, 0x471D5E28, 0x424D1936, 0xF550D832,
|
||||
0x2C769B3F, 0x9B6B5A3B, 0x26D61503, 0x91CBD407, 0x48ED970A, 0xFFF0560E,
|
||||
0xFAA01110, 0x4DBDD014, 0x949B9319, 0x2386521D, 0x0E562FF1, 0xB94BEEF5,
|
||||
0x606DADF8, 0xD7706CFC, 0xD2202BE2, 0x653DEAE6, 0xBC1BA9EB, 0x0B0668EF,
|
||||
0xB6BB27D7, 0x01A6E6D3, 0xD880A5DE, 0x6F9D64DA, 0x6ACD23C4, 0xDDD0E2C0,
|
||||
0x04F6A1CD, 0xB3EB60C9, 0x7E8D3EBD, 0xC990FFB9, 0x10B6BCB4, 0xA7AB7DB0,
|
||||
0xA2FB3AAE, 0x15E6FBAA, 0xCCC0B8A7, 0x7BDD79A3, 0xC660369B, 0x717DF79F,
|
||||
0xA85BB492, 0x1F467596, 0x1A163288, 0xAD0BF38C, 0x742DB081, 0xC3307185,
|
||||
0x99908A5D, 0x2E8D4B59, 0xF7AB0854, 0x40B6C950, 0x45E68E4E, 0xF2FB4F4A,
|
||||
0x2BDD0C47, 0x9CC0CD43, 0x217D827B, 0x9660437F, 0x4F460072, 0xF85BC176,
|
||||
0xFD0B8668, 0x4A16476C, 0x93300461, 0x242DC565, 0xE94B9B11, 0x5E565A15,
|
||||
0x87701918, 0x306DD81C, 0x353D9F02, 0x82205E06, 0x5B061D0B, 0xEC1BDC0F,
|
||||
0x51A69337, 0xE6BB5233, 0x3F9D113E, 0x8880D03A, 0x8DD09724, 0x3ACD5620,
|
||||
0xE3EB152D, 0x54F6D429, 0x7926A9C5, 0xCE3B68C1, 0x171D2BCC, 0xA000EAC8,
|
||||
0xA550ADD6, 0x124D6CD2, 0xCB6B2FDF, 0x7C76EEDB, 0xC1CBA1E3, 0x76D660E7,
|
||||
0xAFF023EA, 0x18EDE2EE, 0x1DBDA5F0, 0xAAA064F4, 0x738627F9, 0xC49BE6FD,
|
||||
0x09FDB889, 0xBEE0798D, 0x67C63A80, 0xD0DBFB84, 0xD58BBC9A, 0x62967D9E,
|
||||
0xBBB03E93, 0x0CADFF97, 0xB110B0AF, 0x060D71AB, 0xDF2B32A6, 0x6836F3A2,
|
||||
0x6D66B4BC, 0xDA7B75B8, 0x035D36B5, 0xB440F7B1,
|
||||
0x00000000, 0xB71DC104, 0x6E3B8209, 0xD926430D, 0xDC760413, 0x6B6BC517,
|
||||
0xB24D861A, 0x0550471E, 0xB8ED0826, 0x0FF0C922, 0xD6D68A2F, 0x61CB4B2B,
|
||||
0x649B0C35, 0xD386CD31, 0x0AA08E3C, 0xBDBD4F38, 0x70DB114C, 0xC7C6D048,
|
||||
0x1EE09345, 0xA9FD5241, 0xACAD155F, 0x1BB0D45B, 0xC2969756, 0x758B5652,
|
||||
0xC836196A, 0x7F2BD86E, 0xA60D9B63, 0x11105A67, 0x14401D79, 0xA35DDC7D,
|
||||
0x7A7B9F70, 0xCD665E74, 0xE0B62398, 0x57ABE29C, 0x8E8DA191, 0x39906095,
|
||||
0x3CC0278B, 0x8BDDE68F, 0x52FBA582, 0xE5E66486, 0x585B2BBE, 0xEF46EABA,
|
||||
0x3660A9B7, 0x817D68B3, 0x842D2FAD, 0x3330EEA9, 0xEA16ADA4, 0x5D0B6CA0,
|
||||
0x906D32D4, 0x2770F3D0, 0xFE56B0DD, 0x494B71D9, 0x4C1B36C7, 0xFB06F7C3,
|
||||
0x2220B4CE, 0x953D75CA, 0x28803AF2, 0x9F9DFBF6, 0x46BBB8FB, 0xF1A679FF,
|
||||
0xF4F63EE1, 0x43EBFFE5, 0x9ACDBCE8, 0x2DD07DEC, 0x77708634, 0xC06D4730,
|
||||
0x194B043D, 0xAE56C539, 0xAB068227, 0x1C1B4323, 0xC53D002E, 0x7220C12A,
|
||||
0xCF9D8E12, 0x78804F16, 0xA1A60C1B, 0x16BBCD1F, 0x13EB8A01, 0xA4F64B05,
|
||||
0x7DD00808, 0xCACDC90C, 0x07AB9778, 0xB0B6567C, 0x69901571, 0xDE8DD475,
|
||||
0xDBDD936B, 0x6CC0526F, 0xB5E61162, 0x02FBD066, 0xBF469F5E, 0x085B5E5A,
|
||||
0xD17D1D57, 0x6660DC53, 0x63309B4D, 0xD42D5A49, 0x0D0B1944, 0xBA16D840,
|
||||
0x97C6A5AC, 0x20DB64A8, 0xF9FD27A5, 0x4EE0E6A1, 0x4BB0A1BF, 0xFCAD60BB,
|
||||
0x258B23B6, 0x9296E2B2, 0x2F2BAD8A, 0x98366C8E, 0x41102F83, 0xF60DEE87,
|
||||
0xF35DA999, 0x4440689D, 0x9D662B90, 0x2A7BEA94, 0xE71DB4E0, 0x500075E4,
|
||||
0x892636E9, 0x3E3BF7ED, 0x3B6BB0F3, 0x8C7671F7, 0x555032FA, 0xE24DF3FE,
|
||||
0x5FF0BCC6, 0xE8ED7DC2, 0x31CB3ECF, 0x86D6FFCB, 0x8386B8D5, 0x349B79D1,
|
||||
0xEDBD3ADC, 0x5AA0FBD8, 0xEEE00C69, 0x59FDCD6D, 0x80DB8E60, 0x37C64F64,
|
||||
0x3296087A, 0x858BC97E, 0x5CAD8A73, 0xEBB04B77, 0x560D044F, 0xE110C54B,
|
||||
0x38368646, 0x8F2B4742, 0x8A7B005C, 0x3D66C158, 0xE4408255, 0x535D4351,
|
||||
0x9E3B1D25, 0x2926DC21, 0xF0009F2C, 0x471D5E28, 0x424D1936, 0xF550D832,
|
||||
0x2C769B3F, 0x9B6B5A3B, 0x26D61503, 0x91CBD407, 0x48ED970A, 0xFFF0560E,
|
||||
0xFAA01110, 0x4DBDD014, 0x949B9319, 0x2386521D, 0x0E562FF1, 0xB94BEEF5,
|
||||
0x606DADF8, 0xD7706CFC, 0xD2202BE2, 0x653DEAE6, 0xBC1BA9EB, 0x0B0668EF,
|
||||
0xB6BB27D7, 0x01A6E6D3, 0xD880A5DE, 0x6F9D64DA, 0x6ACD23C4, 0xDDD0E2C0,
|
||||
0x04F6A1CD, 0xB3EB60C9, 0x7E8D3EBD, 0xC990FFB9, 0x10B6BCB4, 0xA7AB7DB0,
|
||||
0xA2FB3AAE, 0x15E6FBAA, 0xCCC0B8A7, 0x7BDD79A3, 0xC660369B, 0x717DF79F,
|
||||
0xA85BB492, 0x1F467596, 0x1A163288, 0xAD0BF38C, 0x742DB081, 0xC3307185,
|
||||
0x99908A5D, 0x2E8D4B59, 0xF7AB0854, 0x40B6C950, 0x45E68E4E, 0xF2FB4F4A,
|
||||
0x2BDD0C47, 0x9CC0CD43, 0x217D827B, 0x9660437F, 0x4F460072, 0xF85BC176,
|
||||
0xFD0B8668, 0x4A16476C, 0x93300461, 0x242DC565, 0xE94B9B11, 0x5E565A15,
|
||||
0x87701918, 0x306DD81C, 0x353D9F02, 0x82205E06, 0x5B061D0B, 0xEC1BDC0F,
|
||||
0x51A69337, 0xE6BB5233, 0x3F9D113E, 0x8880D03A, 0x8DD09724, 0x3ACD5620,
|
||||
0xE3EB152D, 0x54F6D429, 0x7926A9C5, 0xCE3B68C1, 0x171D2BCC, 0xA000EAC8,
|
||||
0xA550ADD6, 0x124D6CD2, 0xCB6B2FDF, 0x7C76EEDB, 0xC1CBA1E3, 0x76D660E7,
|
||||
0xAFF023EA, 0x18EDE2EE, 0x1DBDA5F0, 0xAAA064F4, 0x738627F9, 0xC49BE6FD,
|
||||
0x09FDB889, 0xBEE0798D, 0x67C63A80, 0xD0DBFB84, 0xD58BBC9A, 0x62967D9E,
|
||||
0xBBB03E93, 0x0CADFF97, 0xB110B0AF, 0x060D71AB, 0xDF2B32A6, 0x6836F3A2,
|
||||
0x6D66B4BC, 0xDA7B75B8, 0x035D36B5, 0xB440F7B1,
|
||||
}
|
||||
|
||||
func CalcCrc32(crc uint32, buffer []byte) uint32 {
|
||||
var i int = 0
|
||||
for i = 0; i < len(buffer); i++ {
|
||||
crc = crc32table[(crc^uint32(buffer[i]))&0xff] ^ (crc >> 8)
|
||||
}
|
||||
return crc
|
||||
var i int = 0
|
||||
for i = 0; i < len(buffer); i++ {
|
||||
crc = crc32table[(crc^uint32(buffer[i]))&0xff] ^ (crc >> 8)
|
||||
}
|
||||
return crc
|
||||
}
|
||||
|
||||
func CovertRbspToSodb(rbsp []byte) []byte {
|
||||
bs := NewBitStream(rbsp)
|
||||
bsw := NewBitStreamWriter(len(rbsp))
|
||||
for !bs.EOS() {
|
||||
if bs.RemainBytes() > 3 && bs.NextBits(24) == 0x000003 {
|
||||
bsw.PutByte(bs.Uint8(8))
|
||||
bsw.PutByte(bs.Uint8(8))
|
||||
bs.SkipBits(8)
|
||||
} else {
|
||||
bsw.PutByte(bs.Uint8(8))
|
||||
}
|
||||
}
|
||||
return bsw.Bits()
|
||||
bs := NewBitStream(rbsp)
|
||||
bsw := NewBitStreamWriter(len(rbsp))
|
||||
for !bs.EOS() {
|
||||
if bs.RemainBytes() > 3 && bs.NextBits(24) == 0x000003 {
|
||||
bsw.PutByte(bs.Uint8(8))
|
||||
bsw.PutByte(bs.Uint8(8))
|
||||
bs.SkipBits(8)
|
||||
} else {
|
||||
bsw.PutByte(bs.Uint8(8))
|
||||
}
|
||||
}
|
||||
return bsw.Bits()
|
||||
}
|
||||
|
|
94
trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/codec/vp8.go
generated
vendored
94
trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/codec/vp8.go
generated
vendored
|
@ -3,70 +3,70 @@ package codec
|
|||
import "errors"
|
||||
|
||||
type VP8FrameTag struct {
|
||||
FrameType uint32 //0: I frame , 1: P frame
|
||||
Version uint32
|
||||
Display uint32
|
||||
FirstPartSize uint32
|
||||
FrameType uint32 //0: I frame , 1: P frame
|
||||
Version uint32
|
||||
Display uint32
|
||||
FirstPartSize uint32
|
||||
}
|
||||
|
||||
type VP8KeyFrameHead struct {
|
||||
Width int
|
||||
Height int
|
||||
HorizScale int
|
||||
VertScale int
|
||||
Width int
|
||||
Height int
|
||||
HorizScale int
|
||||
VertScale int
|
||||
}
|
||||
|
||||
func DecodeFrameTag(frame []byte) (*VP8FrameTag, error) {
|
||||
if len(frame) < 3 {
|
||||
return nil, errors.New("frame bytes < 3")
|
||||
}
|
||||
var tmp uint32 = (uint32(frame[2]) << 16) | (uint32(frame[1]) << 8) | uint32(frame[0])
|
||||
tag := &VP8FrameTag{}
|
||||
tag.FrameType = tmp & 0x01
|
||||
tag.Version = (tmp >> 1) & 0x07
|
||||
tag.Display = (tmp >> 4) & 0x01
|
||||
tag.FirstPartSize = (tmp >> 5) & 0x7FFFF
|
||||
return tag, nil
|
||||
if len(frame) < 3 {
|
||||
return nil, errors.New("frame bytes < 3")
|
||||
}
|
||||
var tmp uint32 = (uint32(frame[2]) << 16) | (uint32(frame[1]) << 8) | uint32(frame[0])
|
||||
tag := &VP8FrameTag{}
|
||||
tag.FrameType = tmp & 0x01
|
||||
tag.Version = (tmp >> 1) & 0x07
|
||||
tag.Display = (tmp >> 4) & 0x01
|
||||
tag.FirstPartSize = (tmp >> 5) & 0x7FFFF
|
||||
return tag, nil
|
||||
}
|
||||
|
||||
func DecodeKeyFrameHead(frame []byte) (*VP8KeyFrameHead, error) {
|
||||
if len(frame) < 7 {
|
||||
return nil, errors.New("frame bytes < 3")
|
||||
}
|
||||
if len(frame) < 7 {
|
||||
return nil, errors.New("frame bytes < 3")
|
||||
}
|
||||
|
||||
if frame[0] != 0x9d || frame[1] != 0x01 || frame[2] != 0x2a {
|
||||
return nil, errors.New("not find Start code")
|
||||
}
|
||||
if frame[0] != 0x9d || frame[1] != 0x01 || frame[2] != 0x2a {
|
||||
return nil, errors.New("not find Start code")
|
||||
}
|
||||
|
||||
head := &VP8KeyFrameHead{}
|
||||
head.Width = int(uint16(frame[4]&0x3f)<<8 | uint16(frame[3]))
|
||||
head.HorizScale = int(frame[4] >> 6)
|
||||
head.Height = int(uint16(frame[6]&0x3f)<<8 | uint16(frame[5]))
|
||||
head.VertScale = int(frame[6] >> 6)
|
||||
return head, nil
|
||||
head := &VP8KeyFrameHead{}
|
||||
head.Width = int(uint16(frame[4]&0x3f)<<8 | uint16(frame[3]))
|
||||
head.HorizScale = int(frame[4] >> 6)
|
||||
head.Height = int(uint16(frame[6]&0x3f)<<8 | uint16(frame[5]))
|
||||
head.VertScale = int(frame[6] >> 6)
|
||||
return head, nil
|
||||
}
|
||||
|
||||
func IsKeyFrame(frame []byte) bool {
|
||||
tag, err := DecodeFrameTag(frame)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
tag, err := DecodeFrameTag(frame)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if tag.FrameType == 0 {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
if tag.FrameType == 0 {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func GetResloution(frame []byte) (width int, height int, err error) {
|
||||
if !IsKeyFrame(frame) {
|
||||
return 0, 0, errors.New("the frame is not Key frame")
|
||||
}
|
||||
if !IsKeyFrame(frame) {
|
||||
return 0, 0, errors.New("the frame is not Key frame")
|
||||
}
|
||||
|
||||
head, err := DecodeKeyFrameHead(frame[3:])
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
return head.Width, head.Height, nil
|
||||
head, err := DecodeKeyFrameHead(frame[3:])
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
return head.Width, head.Height, nil
|
||||
}
|
||||
|
|
596
trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/mpeg2/pes-proto.go
generated
vendored
596
trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/mpeg2/pes-proto.go
generated
vendored
|
@ -1,10 +1,10 @@
|
|||
package mpeg2
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/yapingcat/gomedia/codec"
|
||||
"github.com/yapingcat/gomedia/codec"
|
||||
)
|
||||
|
||||
var H264_AUD_NALU []byte = []byte{0x00, 0x00, 0x00, 0x01, 0x09, 0xF0} //ffmpeg mpegtsenc.c mpegts_write_packet_internal
|
||||
|
@ -13,337 +13,337 @@ var H265_AUD_NALU []byte = []byte{0x00, 0x00, 0x00, 0x01, 0x46, 0x01, 0x50}
|
|||
type PES_STREMA_ID int
|
||||
|
||||
const (
|
||||
PES_STREAM_END PES_STREMA_ID = 0xB9
|
||||
PES_STREAM_START PES_STREMA_ID = 0xBA
|
||||
PES_STREAM_SYSTEM_HEAD PES_STREMA_ID = 0xBB
|
||||
PES_STREAM_MAP PES_STREMA_ID = 0xBC
|
||||
PES_STREAM_PRIVATE PES_STREMA_ID = 0xBD
|
||||
PES_STREAM_AUDIO PES_STREMA_ID = 0xC0
|
||||
PES_STREAM_VIDEO PES_STREMA_ID = 0xE0
|
||||
PES_STREAM_END PES_STREMA_ID = 0xB9
|
||||
PES_STREAM_START PES_STREMA_ID = 0xBA
|
||||
PES_STREAM_SYSTEM_HEAD PES_STREMA_ID = 0xBB
|
||||
PES_STREAM_MAP PES_STREMA_ID = 0xBC
|
||||
PES_STREAM_PRIVATE PES_STREMA_ID = 0xBD
|
||||
PES_STREAM_AUDIO PES_STREMA_ID = 0xC0
|
||||
PES_STREAM_VIDEO PES_STREMA_ID = 0xE0
|
||||
)
|
||||
|
||||
func findPESIDByStreamType(cid TS_STREAM_TYPE) PES_STREMA_ID {
|
||||
if cid == TS_STREAM_AAC {
|
||||
return PES_STREAM_AUDIO
|
||||
} else if cid == TS_STREAM_H264 || cid == TS_STREAM_H265 {
|
||||
return PES_STREAM_VIDEO
|
||||
} else {
|
||||
return PES_STREAM_PRIVATE
|
||||
}
|
||||
if cid == TS_STREAM_AAC {
|
||||
return PES_STREAM_AUDIO
|
||||
} else if cid == TS_STREAM_H264 || cid == TS_STREAM_H265 {
|
||||
return PES_STREAM_VIDEO
|
||||
} else {
|
||||
return PES_STREAM_PRIVATE
|
||||
}
|
||||
}
|
||||
|
||||
type PesPacket struct {
|
||||
Stream_id uint8
|
||||
PES_packet_length uint16
|
||||
PES_scrambling_control uint8
|
||||
PES_priority uint8
|
||||
Data_alignment_indicator uint8
|
||||
Copyright uint8
|
||||
Original_or_copy uint8
|
||||
PTS_DTS_flags uint8
|
||||
ESCR_flag uint8
|
||||
ES_rate_flag uint8
|
||||
DSM_trick_mode_flag uint8
|
||||
Additional_copy_info_flag uint8
|
||||
PES_CRC_flag uint8
|
||||
PES_extension_flag uint8
|
||||
PES_header_data_length uint8
|
||||
Pts uint64
|
||||
Dts uint64
|
||||
ESCR_base uint64
|
||||
ESCR_extension uint16
|
||||
ES_rate uint32
|
||||
Trick_mode_control uint8
|
||||
Trick_value uint8
|
||||
Additional_copy_info uint8
|
||||
Previous_PES_packet_CRC uint16
|
||||
Pes_payload []byte
|
||||
//TODO
|
||||
//if ( PES_extension_flag == '1')
|
||||
// PES_private_data_flag uint8
|
||||
// pack_header_field_flag uint8
|
||||
// program_packet_sequence_counter_flag uint8
|
||||
// P_STD_buffer_flag uint8
|
||||
// PES_extension_flag_2 uint8
|
||||
// PES_private_data [16]byte
|
||||
Stream_id uint8
|
||||
PES_packet_length uint16
|
||||
PES_scrambling_control uint8
|
||||
PES_priority uint8
|
||||
Data_alignment_indicator uint8
|
||||
Copyright uint8
|
||||
Original_or_copy uint8
|
||||
PTS_DTS_flags uint8
|
||||
ESCR_flag uint8
|
||||
ES_rate_flag uint8
|
||||
DSM_trick_mode_flag uint8
|
||||
Additional_copy_info_flag uint8
|
||||
PES_CRC_flag uint8
|
||||
PES_extension_flag uint8
|
||||
PES_header_data_length uint8
|
||||
Pts uint64
|
||||
Dts uint64
|
||||
ESCR_base uint64
|
||||
ESCR_extension uint16
|
||||
ES_rate uint32
|
||||
Trick_mode_control uint8
|
||||
Trick_value uint8
|
||||
Additional_copy_info uint8
|
||||
Previous_PES_packet_CRC uint16
|
||||
Pes_payload []byte
|
||||
//TODO
|
||||
//if ( PES_extension_flag == '1')
|
||||
// PES_private_data_flag uint8
|
||||
// pack_header_field_flag uint8
|
||||
// program_packet_sequence_counter_flag uint8
|
||||
// P_STD_buffer_flag uint8
|
||||
// PES_extension_flag_2 uint8
|
||||
// PES_private_data [16]byte
|
||||
}
|
||||
|
||||
func NewPesPacket() *PesPacket {
|
||||
return new(PesPacket)
|
||||
return new(PesPacket)
|
||||
}
|
||||
|
||||
func (pkg *PesPacket) PrettyPrint(file *os.File) {
|
||||
file.WriteString(fmt.Sprintf("stream_id:%d\n", pkg.Stream_id))
|
||||
file.WriteString(fmt.Sprintf("PES_packet_length:%d\n", pkg.PES_packet_length))
|
||||
file.WriteString(fmt.Sprintf("PES_scrambling_control:%d\n", pkg.PES_scrambling_control))
|
||||
file.WriteString(fmt.Sprintf("PES_priority:%d\n", pkg.PES_priority))
|
||||
file.WriteString(fmt.Sprintf("data_alignment_indicator:%d\n", pkg.Data_alignment_indicator))
|
||||
file.WriteString(fmt.Sprintf("copyright:%d\n", pkg.Copyright))
|
||||
file.WriteString(fmt.Sprintf("original_or_copy:%d\n", pkg.Original_or_copy))
|
||||
file.WriteString(fmt.Sprintf("PTS_DTS_flags:%d\n", pkg.PTS_DTS_flags))
|
||||
file.WriteString(fmt.Sprintf("ESCR_flag:%d\n", pkg.ESCR_flag))
|
||||
file.WriteString(fmt.Sprintf("ES_rate_flag:%d\n", pkg.ES_rate_flag))
|
||||
file.WriteString(fmt.Sprintf("DSM_trick_mode_flag:%d\n", pkg.DSM_trick_mode_flag))
|
||||
file.WriteString(fmt.Sprintf("additional_copy_info_flag:%d\n", pkg.Additional_copy_info_flag))
|
||||
file.WriteString(fmt.Sprintf("PES_CRC_flag:%d\n", pkg.PES_CRC_flag))
|
||||
file.WriteString(fmt.Sprintf("PES_extension_flag:%d\n", pkg.PES_extension_flag))
|
||||
file.WriteString(fmt.Sprintf("PES_header_data_length:%d\n", pkg.PES_header_data_length))
|
||||
if pkg.PTS_DTS_flags&0x02 == 0x02 {
|
||||
file.WriteString(fmt.Sprintf("PTS:%d\n", pkg.Pts))
|
||||
}
|
||||
if pkg.PTS_DTS_flags&0x03 == 0x03 {
|
||||
file.WriteString(fmt.Sprintf("DTS:%d\n", pkg.Dts))
|
||||
}
|
||||
file.WriteString(fmt.Sprintf("stream_id:%d\n", pkg.Stream_id))
|
||||
file.WriteString(fmt.Sprintf("PES_packet_length:%d\n", pkg.PES_packet_length))
|
||||
file.WriteString(fmt.Sprintf("PES_scrambling_control:%d\n", pkg.PES_scrambling_control))
|
||||
file.WriteString(fmt.Sprintf("PES_priority:%d\n", pkg.PES_priority))
|
||||
file.WriteString(fmt.Sprintf("data_alignment_indicator:%d\n", pkg.Data_alignment_indicator))
|
||||
file.WriteString(fmt.Sprintf("copyright:%d\n", pkg.Copyright))
|
||||
file.WriteString(fmt.Sprintf("original_or_copy:%d\n", pkg.Original_or_copy))
|
||||
file.WriteString(fmt.Sprintf("PTS_DTS_flags:%d\n", pkg.PTS_DTS_flags))
|
||||
file.WriteString(fmt.Sprintf("ESCR_flag:%d\n", pkg.ESCR_flag))
|
||||
file.WriteString(fmt.Sprintf("ES_rate_flag:%d\n", pkg.ES_rate_flag))
|
||||
file.WriteString(fmt.Sprintf("DSM_trick_mode_flag:%d\n", pkg.DSM_trick_mode_flag))
|
||||
file.WriteString(fmt.Sprintf("additional_copy_info_flag:%d\n", pkg.Additional_copy_info_flag))
|
||||
file.WriteString(fmt.Sprintf("PES_CRC_flag:%d\n", pkg.PES_CRC_flag))
|
||||
file.WriteString(fmt.Sprintf("PES_extension_flag:%d\n", pkg.PES_extension_flag))
|
||||
file.WriteString(fmt.Sprintf("PES_header_data_length:%d\n", pkg.PES_header_data_length))
|
||||
if pkg.PTS_DTS_flags&0x02 == 0x02 {
|
||||
file.WriteString(fmt.Sprintf("PTS:%d\n", pkg.Pts))
|
||||
}
|
||||
if pkg.PTS_DTS_flags&0x03 == 0x03 {
|
||||
file.WriteString(fmt.Sprintf("DTS:%d\n", pkg.Dts))
|
||||
}
|
||||
|
||||
if pkg.ESCR_flag == 1 {
|
||||
file.WriteString(fmt.Sprintf("ESCR_base:%d\n", pkg.ESCR_base))
|
||||
file.WriteString(fmt.Sprintf("ESCR_extension:%d\n", pkg.ESCR_extension))
|
||||
}
|
||||
if pkg.ESCR_flag == 1 {
|
||||
file.WriteString(fmt.Sprintf("ESCR_base:%d\n", pkg.ESCR_base))
|
||||
file.WriteString(fmt.Sprintf("ESCR_extension:%d\n", pkg.ESCR_extension))
|
||||
}
|
||||
|
||||
if pkg.ES_rate_flag == 1 {
|
||||
file.WriteString(fmt.Sprintf("ES_rate:%d\n", pkg.ES_rate))
|
||||
}
|
||||
if pkg.ES_rate_flag == 1 {
|
||||
file.WriteString(fmt.Sprintf("ES_rate:%d\n", pkg.ES_rate))
|
||||
}
|
||||
|
||||
if pkg.DSM_trick_mode_flag == 1 {
|
||||
file.WriteString(fmt.Sprintf("trick_mode_control:%d\n", pkg.Trick_mode_control))
|
||||
}
|
||||
if pkg.DSM_trick_mode_flag == 1 {
|
||||
file.WriteString(fmt.Sprintf("trick_mode_control:%d\n", pkg.Trick_mode_control))
|
||||
}
|
||||
|
||||
if pkg.Additional_copy_info_flag == 1 {
|
||||
file.WriteString(fmt.Sprintf("additional_copy_info:%d\n", pkg.Additional_copy_info))
|
||||
}
|
||||
if pkg.Additional_copy_info_flag == 1 {
|
||||
file.WriteString(fmt.Sprintf("additional_copy_info:%d\n", pkg.Additional_copy_info))
|
||||
}
|
||||
|
||||
if pkg.PES_CRC_flag == 1 {
|
||||
file.WriteString(fmt.Sprintf("previous_PES_packet_CRC:%d\n", pkg.Previous_PES_packet_CRC))
|
||||
}
|
||||
file.WriteString("PES_packet_data_byte:\n")
|
||||
file.WriteString(fmt.Sprintf(" Size: %d\n", len(pkg.Pes_payload)))
|
||||
file.WriteString(" data:")
|
||||
for i := 0; i < 12 && i < len(pkg.Pes_payload); i++ {
|
||||
if i%4 == 0 {
|
||||
file.WriteString("\n")
|
||||
file.WriteString(" ")
|
||||
}
|
||||
file.WriteString(fmt.Sprintf("0x%02x ", pkg.Pes_payload[i]))
|
||||
}
|
||||
file.WriteString("\n")
|
||||
if pkg.PES_CRC_flag == 1 {
|
||||
file.WriteString(fmt.Sprintf("previous_PES_packet_CRC:%d\n", pkg.Previous_PES_packet_CRC))
|
||||
}
|
||||
file.WriteString("PES_packet_data_byte:\n")
|
||||
file.WriteString(fmt.Sprintf(" Size: %d\n", len(pkg.Pes_payload)))
|
||||
file.WriteString(" data:")
|
||||
for i := 0; i < 12 && i < len(pkg.Pes_payload); i++ {
|
||||
if i%4 == 0 {
|
||||
file.WriteString("\n")
|
||||
file.WriteString(" ")
|
||||
}
|
||||
file.WriteString(fmt.Sprintf("0x%02x ", pkg.Pes_payload[i]))
|
||||
}
|
||||
file.WriteString("\n")
|
||||
}
|
||||
|
||||
func (pkg *PesPacket) Decode(bs *codec.BitStream) error {
|
||||
if bs.RemainBytes() < 9 {
|
||||
return errNeedMore
|
||||
}
|
||||
bs.SkipBits(24) //packet_start_code_prefix
|
||||
pkg.Stream_id = bs.Uint8(8) //stream_id
|
||||
pkg.PES_packet_length = bs.Uint16(16)
|
||||
bs.SkipBits(2) //'10'
|
||||
pkg.PES_scrambling_control = bs.Uint8(2)
|
||||
pkg.PES_priority = bs.Uint8(1)
|
||||
pkg.Data_alignment_indicator = bs.Uint8(1)
|
||||
pkg.Copyright = bs.Uint8(1)
|
||||
pkg.Original_or_copy = bs.Uint8(1)
|
||||
pkg.PTS_DTS_flags = bs.Uint8(2)
|
||||
pkg.ESCR_flag = bs.Uint8(1)
|
||||
pkg.ES_rate_flag = bs.Uint8(1)
|
||||
pkg.DSM_trick_mode_flag = bs.Uint8(1)
|
||||
pkg.Additional_copy_info_flag = bs.Uint8(1)
|
||||
pkg.PES_CRC_flag = bs.Uint8(1)
|
||||
pkg.PES_extension_flag = bs.Uint8(1)
|
||||
pkg.PES_header_data_length = bs.Uint8(8)
|
||||
if bs.RemainBytes() < int(pkg.PES_header_data_length) {
|
||||
bs.UnRead(9 * 8)
|
||||
return errNeedMore
|
||||
}
|
||||
bs.Markdot()
|
||||
if pkg.PTS_DTS_flags&0x02 == 0x02 {
|
||||
bs.SkipBits(4)
|
||||
pkg.Pts = bs.GetBits(3)
|
||||
bs.SkipBits(1)
|
||||
pkg.Pts = (pkg.Pts << 15) | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
pkg.Pts = (pkg.Pts << 15) | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
}
|
||||
if pkg.PTS_DTS_flags&0x03 == 0x03 {
|
||||
bs.SkipBits(4)
|
||||
pkg.Dts = bs.GetBits(3)
|
||||
bs.SkipBits(1)
|
||||
pkg.Dts = (pkg.Dts << 15) | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
pkg.Dts = (pkg.Dts << 15) | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
} else {
|
||||
pkg.Dts = pkg.Pts
|
||||
}
|
||||
if bs.RemainBytes() < 9 {
|
||||
return errNeedMore
|
||||
}
|
||||
bs.SkipBits(24) //packet_start_code_prefix
|
||||
pkg.Stream_id = bs.Uint8(8) //stream_id
|
||||
pkg.PES_packet_length = bs.Uint16(16)
|
||||
bs.SkipBits(2) //'10'
|
||||
pkg.PES_scrambling_control = bs.Uint8(2)
|
||||
pkg.PES_priority = bs.Uint8(1)
|
||||
pkg.Data_alignment_indicator = bs.Uint8(1)
|
||||
pkg.Copyright = bs.Uint8(1)
|
||||
pkg.Original_or_copy = bs.Uint8(1)
|
||||
pkg.PTS_DTS_flags = bs.Uint8(2)
|
||||
pkg.ESCR_flag = bs.Uint8(1)
|
||||
pkg.ES_rate_flag = bs.Uint8(1)
|
||||
pkg.DSM_trick_mode_flag = bs.Uint8(1)
|
||||
pkg.Additional_copy_info_flag = bs.Uint8(1)
|
||||
pkg.PES_CRC_flag = bs.Uint8(1)
|
||||
pkg.PES_extension_flag = bs.Uint8(1)
|
||||
pkg.PES_header_data_length = bs.Uint8(8)
|
||||
if bs.RemainBytes() < int(pkg.PES_header_data_length) {
|
||||
bs.UnRead(9 * 8)
|
||||
return errNeedMore
|
||||
}
|
||||
bs.Markdot()
|
||||
if pkg.PTS_DTS_flags&0x02 == 0x02 {
|
||||
bs.SkipBits(4)
|
||||
pkg.Pts = bs.GetBits(3)
|
||||
bs.SkipBits(1)
|
||||
pkg.Pts = (pkg.Pts << 15) | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
pkg.Pts = (pkg.Pts << 15) | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
}
|
||||
if pkg.PTS_DTS_flags&0x03 == 0x03 {
|
||||
bs.SkipBits(4)
|
||||
pkg.Dts = bs.GetBits(3)
|
||||
bs.SkipBits(1)
|
||||
pkg.Dts = (pkg.Dts << 15) | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
pkg.Dts = (pkg.Dts << 15) | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
} else {
|
||||
pkg.Dts = pkg.Pts
|
||||
}
|
||||
|
||||
if pkg.ESCR_flag == 1 {
|
||||
bs.SkipBits(2)
|
||||
pkg.ESCR_base = bs.GetBits(3)
|
||||
bs.SkipBits(1)
|
||||
pkg.ESCR_base = (pkg.Pts << 15) | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
pkg.ESCR_base = (pkg.Pts << 15) | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
pkg.ESCR_extension = bs.Uint16(9)
|
||||
bs.SkipBits(1)
|
||||
}
|
||||
if pkg.ESCR_flag == 1 {
|
||||
bs.SkipBits(2)
|
||||
pkg.ESCR_base = bs.GetBits(3)
|
||||
bs.SkipBits(1)
|
||||
pkg.ESCR_base = (pkg.Pts << 15) | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
pkg.ESCR_base = (pkg.Pts << 15) | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
pkg.ESCR_extension = bs.Uint16(9)
|
||||
bs.SkipBits(1)
|
||||
}
|
||||
|
||||
if pkg.ES_rate_flag == 1 {
|
||||
bs.SkipBits(1)
|
||||
pkg.ES_rate = bs.Uint32(22)
|
||||
bs.SkipBits(1)
|
||||
}
|
||||
if pkg.ES_rate_flag == 1 {
|
||||
bs.SkipBits(1)
|
||||
pkg.ES_rate = bs.Uint32(22)
|
||||
bs.SkipBits(1)
|
||||
}
|
||||
|
||||
if pkg.DSM_trick_mode_flag == 1 {
|
||||
pkg.Trick_mode_control = bs.Uint8(3)
|
||||
pkg.Trick_value = bs.Uint8(5)
|
||||
}
|
||||
if pkg.DSM_trick_mode_flag == 1 {
|
||||
pkg.Trick_mode_control = bs.Uint8(3)
|
||||
pkg.Trick_value = bs.Uint8(5)
|
||||
}
|
||||
|
||||
if pkg.Additional_copy_info_flag == 1 {
|
||||
pkg.Additional_copy_info = bs.Uint8(7)
|
||||
}
|
||||
if pkg.Additional_copy_info_flag == 1 {
|
||||
pkg.Additional_copy_info = bs.Uint8(7)
|
||||
}
|
||||
|
||||
if pkg.PES_CRC_flag == 1 {
|
||||
pkg.Previous_PES_packet_CRC = bs.Uint16(16)
|
||||
}
|
||||
if pkg.PES_CRC_flag == 1 {
|
||||
pkg.Previous_PES_packet_CRC = bs.Uint16(16)
|
||||
}
|
||||
|
||||
loc := bs.DistanceFromMarkDot()
|
||||
bs.SkipBits(int(pkg.PES_header_data_length)*8 - loc) // skip remaining header
|
||||
loc := bs.DistanceFromMarkDot()
|
||||
bs.SkipBits(int(pkg.PES_header_data_length)*8 - loc) // skip remaining header
|
||||
|
||||
// the -3 bytes are the combined lengths
|
||||
// of all fields between PES_packet_length and PES_header_data_length (2 bytes)
|
||||
// and the PES_header_data_length itself (1 byte)
|
||||
dataLen := int(pkg.PES_packet_length - 3 - uint16(pkg.PES_header_data_length))
|
||||
// the -3 bytes are the combined lengths
|
||||
// of all fields between PES_packet_length and PES_header_data_length (2 bytes)
|
||||
// and the PES_header_data_length itself (1 byte)
|
||||
dataLen := int(pkg.PES_packet_length - 3 - uint16(pkg.PES_header_data_length))
|
||||
|
||||
if bs.RemainBytes() < dataLen {
|
||||
pkg.Pes_payload = bs.RemainData()
|
||||
bs.UnRead((9 + int(pkg.PES_header_data_length)) * 8)
|
||||
return errNeedMore
|
||||
}
|
||||
if bs.RemainBytes() < dataLen {
|
||||
pkg.Pes_payload = bs.RemainData()
|
||||
bs.UnRead((9 + int(pkg.PES_header_data_length)) * 8)
|
||||
return errNeedMore
|
||||
}
|
||||
|
||||
if pkg.PES_packet_length == 0 || bs.RemainBytes() <= dataLen {
|
||||
pkg.Pes_payload = bs.RemainData()
|
||||
bs.SkipBits(bs.RemainBits())
|
||||
} else {
|
||||
pkg.Pes_payload = bs.RemainData()[:dataLen]
|
||||
bs.SkipBits(dataLen * 8)
|
||||
}
|
||||
if pkg.PES_packet_length == 0 || bs.RemainBytes() <= dataLen {
|
||||
pkg.Pes_payload = bs.RemainData()
|
||||
bs.SkipBits(bs.RemainBits())
|
||||
} else {
|
||||
pkg.Pes_payload = bs.RemainData()[:dataLen]
|
||||
bs.SkipBits(dataLen * 8)
|
||||
}
|
||||
|
||||
return nil
|
||||
return nil
|
||||
}
|
||||
|
||||
func (pkg *PesPacket) DecodeMpeg1(bs *codec.BitStream) error {
|
||||
if bs.RemainBytes() < 6 {
|
||||
return errNeedMore
|
||||
}
|
||||
bs.SkipBits(24) //packet_start_code_prefix
|
||||
pkg.Stream_id = bs.Uint8(8) //stream_id
|
||||
pkg.PES_packet_length = bs.Uint16(16)
|
||||
if pkg.PES_packet_length != 0 && bs.RemainBytes() < int(pkg.PES_packet_length) {
|
||||
bs.UnRead(6 * 8)
|
||||
return errNeedMore
|
||||
}
|
||||
bs.Markdot()
|
||||
for bs.NextBits(8) == 0xFF {
|
||||
bs.SkipBits(8)
|
||||
}
|
||||
if bs.NextBits(2) == 0x01 {
|
||||
bs.SkipBits(16)
|
||||
}
|
||||
if bs.NextBits(4) == 0x02 {
|
||||
bs.SkipBits(4)
|
||||
pkg.Pts = bs.GetBits(3)
|
||||
bs.SkipBits(1)
|
||||
pkg.Pts = pkg.Pts<<15 | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
pkg.Pts = pkg.Pts<<15 | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
} else if bs.NextBits(4) == 0x03 {
|
||||
bs.SkipBits(4)
|
||||
pkg.Pts = bs.GetBits(3)
|
||||
bs.SkipBits(1)
|
||||
pkg.Pts = pkg.Pts<<15 | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
pkg.Pts = pkg.Pts<<15 | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
pkg.Dts = bs.GetBits(3)
|
||||
bs.SkipBits(1)
|
||||
pkg.Dts = pkg.Pts<<15 | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
pkg.Dts = pkg.Pts<<15 | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
} else if bs.NextBits(8) == 0x0F {
|
||||
bs.SkipBits(8)
|
||||
} else {
|
||||
return errParser
|
||||
}
|
||||
loc := bs.DistanceFromMarkDot() / 8
|
||||
if pkg.PES_packet_length < uint16(loc) {
|
||||
return errParser
|
||||
}
|
||||
if pkg.PES_packet_length == 0 ||
|
||||
bs.RemainBits() <= int(pkg.PES_packet_length-uint16(loc))*8 {
|
||||
pkg.Pes_payload = bs.RemainData()
|
||||
bs.SkipBits(bs.RemainBits())
|
||||
} else {
|
||||
pkg.Pes_payload = bs.RemainData()[:pkg.PES_packet_length-uint16(loc)]
|
||||
bs.SkipBits(int(pkg.PES_packet_length-uint16(loc)) * 8)
|
||||
}
|
||||
return nil
|
||||
if bs.RemainBytes() < 6 {
|
||||
return errNeedMore
|
||||
}
|
||||
bs.SkipBits(24) //packet_start_code_prefix
|
||||
pkg.Stream_id = bs.Uint8(8) //stream_id
|
||||
pkg.PES_packet_length = bs.Uint16(16)
|
||||
if pkg.PES_packet_length != 0 && bs.RemainBytes() < int(pkg.PES_packet_length) {
|
||||
bs.UnRead(6 * 8)
|
||||
return errNeedMore
|
||||
}
|
||||
bs.Markdot()
|
||||
for bs.NextBits(8) == 0xFF {
|
||||
bs.SkipBits(8)
|
||||
}
|
||||
if bs.NextBits(2) == 0x01 {
|
||||
bs.SkipBits(16)
|
||||
}
|
||||
if bs.NextBits(4) == 0x02 {
|
||||
bs.SkipBits(4)
|
||||
pkg.Pts = bs.GetBits(3)
|
||||
bs.SkipBits(1)
|
||||
pkg.Pts = pkg.Pts<<15 | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
pkg.Pts = pkg.Pts<<15 | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
} else if bs.NextBits(4) == 0x03 {
|
||||
bs.SkipBits(4)
|
||||
pkg.Pts = bs.GetBits(3)
|
||||
bs.SkipBits(1)
|
||||
pkg.Pts = pkg.Pts<<15 | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
pkg.Pts = pkg.Pts<<15 | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
pkg.Dts = bs.GetBits(3)
|
||||
bs.SkipBits(1)
|
||||
pkg.Dts = pkg.Pts<<15 | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
pkg.Dts = pkg.Pts<<15 | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
} else if bs.NextBits(8) == 0x0F {
|
||||
bs.SkipBits(8)
|
||||
} else {
|
||||
return errParser
|
||||
}
|
||||
loc := bs.DistanceFromMarkDot() / 8
|
||||
if pkg.PES_packet_length < uint16(loc) {
|
||||
return errParser
|
||||
}
|
||||
if pkg.PES_packet_length == 0 ||
|
||||
bs.RemainBits() <= int(pkg.PES_packet_length-uint16(loc))*8 {
|
||||
pkg.Pes_payload = bs.RemainData()
|
||||
bs.SkipBits(bs.RemainBits())
|
||||
} else {
|
||||
pkg.Pes_payload = bs.RemainData()[:pkg.PES_packet_length-uint16(loc)]
|
||||
bs.SkipBits(int(pkg.PES_packet_length-uint16(loc)) * 8)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (pkg *PesPacket) Encode(bsw *codec.BitStreamWriter) {
|
||||
bsw.PutBytes([]byte{0x00, 0x00, 0x01})
|
||||
bsw.PutByte(pkg.Stream_id)
|
||||
bsw.PutUint16(pkg.PES_packet_length, 16)
|
||||
bsw.PutUint8(0x02, 2)
|
||||
bsw.PutUint8(pkg.PES_scrambling_control, 2)
|
||||
bsw.PutUint8(pkg.PES_priority, 1)
|
||||
bsw.PutUint8(pkg.Data_alignment_indicator, 1)
|
||||
bsw.PutUint8(pkg.Copyright, 1)
|
||||
bsw.PutUint8(pkg.Original_or_copy, 1)
|
||||
bsw.PutUint8(pkg.PTS_DTS_flags, 2)
|
||||
bsw.PutUint8(pkg.ESCR_flag, 1)
|
||||
bsw.PutUint8(pkg.ES_rate_flag, 1)
|
||||
bsw.PutUint8(pkg.DSM_trick_mode_flag, 1)
|
||||
bsw.PutUint8(pkg.Additional_copy_info_flag, 1)
|
||||
bsw.PutUint8(pkg.PES_CRC_flag, 1)
|
||||
bsw.PutUint8(pkg.PES_extension_flag, 1)
|
||||
bsw.PutByte(pkg.PES_header_data_length)
|
||||
if pkg.PTS_DTS_flags == 0x02 {
|
||||
bsw.PutUint8(0x02, 4)
|
||||
bsw.PutUint64(pkg.Pts>>30, 3)
|
||||
bsw.PutUint8(0x01, 1)
|
||||
bsw.PutUint64(pkg.Pts>>15, 15)
|
||||
bsw.PutUint8(0x01, 1)
|
||||
bsw.PutUint64(pkg.Pts, 15)
|
||||
bsw.PutUint8(0x01, 1)
|
||||
}
|
||||
bsw.PutBytes([]byte{0x00, 0x00, 0x01})
|
||||
bsw.PutByte(pkg.Stream_id)
|
||||
bsw.PutUint16(pkg.PES_packet_length, 16)
|
||||
bsw.PutUint8(0x02, 2)
|
||||
bsw.PutUint8(pkg.PES_scrambling_control, 2)
|
||||
bsw.PutUint8(pkg.PES_priority, 1)
|
||||
bsw.PutUint8(pkg.Data_alignment_indicator, 1)
|
||||
bsw.PutUint8(pkg.Copyright, 1)
|
||||
bsw.PutUint8(pkg.Original_or_copy, 1)
|
||||
bsw.PutUint8(pkg.PTS_DTS_flags, 2)
|
||||
bsw.PutUint8(pkg.ESCR_flag, 1)
|
||||
bsw.PutUint8(pkg.ES_rate_flag, 1)
|
||||
bsw.PutUint8(pkg.DSM_trick_mode_flag, 1)
|
||||
bsw.PutUint8(pkg.Additional_copy_info_flag, 1)
|
||||
bsw.PutUint8(pkg.PES_CRC_flag, 1)
|
||||
bsw.PutUint8(pkg.PES_extension_flag, 1)
|
||||
bsw.PutByte(pkg.PES_header_data_length)
|
||||
if pkg.PTS_DTS_flags == 0x02 {
|
||||
bsw.PutUint8(0x02, 4)
|
||||
bsw.PutUint64(pkg.Pts>>30, 3)
|
||||
bsw.PutUint8(0x01, 1)
|
||||
bsw.PutUint64(pkg.Pts>>15, 15)
|
||||
bsw.PutUint8(0x01, 1)
|
||||
bsw.PutUint64(pkg.Pts, 15)
|
||||
bsw.PutUint8(0x01, 1)
|
||||
}
|
||||
|
||||
if pkg.PTS_DTS_flags == 0x03 {
|
||||
bsw.PutUint8(0x03, 4)
|
||||
bsw.PutUint64(pkg.Pts>>30, 3)
|
||||
bsw.PutUint8(0x01, 1)
|
||||
bsw.PutUint64(pkg.Pts>>15, 15)
|
||||
bsw.PutUint8(0x01, 1)
|
||||
bsw.PutUint64(pkg.Pts, 15)
|
||||
bsw.PutUint8(0x01, 1)
|
||||
bsw.PutUint8(0x01, 4)
|
||||
bsw.PutUint64(pkg.Dts>>30, 3)
|
||||
bsw.PutUint8(0x01, 1)
|
||||
bsw.PutUint64(pkg.Dts>>15, 15)
|
||||
bsw.PutUint8(0x01, 1)
|
||||
bsw.PutUint64(pkg.Dts, 15)
|
||||
bsw.PutUint8(0x01, 1)
|
||||
}
|
||||
if pkg.PTS_DTS_flags == 0x03 {
|
||||
bsw.PutUint8(0x03, 4)
|
||||
bsw.PutUint64(pkg.Pts>>30, 3)
|
||||
bsw.PutUint8(0x01, 1)
|
||||
bsw.PutUint64(pkg.Pts>>15, 15)
|
||||
bsw.PutUint8(0x01, 1)
|
||||
bsw.PutUint64(pkg.Pts, 15)
|
||||
bsw.PutUint8(0x01, 1)
|
||||
bsw.PutUint8(0x01, 4)
|
||||
bsw.PutUint64(pkg.Dts>>30, 3)
|
||||
bsw.PutUint8(0x01, 1)
|
||||
bsw.PutUint64(pkg.Dts>>15, 15)
|
||||
bsw.PutUint8(0x01, 1)
|
||||
bsw.PutUint64(pkg.Dts, 15)
|
||||
bsw.PutUint8(0x01, 1)
|
||||
}
|
||||
|
||||
if pkg.ESCR_flag == 1 {
|
||||
bsw.PutUint8(0x03, 2)
|
||||
bsw.PutUint64(pkg.ESCR_base>>30, 3)
|
||||
bsw.PutUint8(0x01, 1)
|
||||
bsw.PutUint64(pkg.ESCR_base>>15, 15)
|
||||
bsw.PutUint8(0x01, 1)
|
||||
bsw.PutUint64(pkg.ESCR_base, 15)
|
||||
bsw.PutUint8(0x01, 1)
|
||||
}
|
||||
bsw.PutBytes(pkg.Pes_payload)
|
||||
if pkg.ESCR_flag == 1 {
|
||||
bsw.PutUint8(0x03, 2)
|
||||
bsw.PutUint64(pkg.ESCR_base>>30, 3)
|
||||
bsw.PutUint8(0x01, 1)
|
||||
bsw.PutUint64(pkg.ESCR_base>>15, 15)
|
||||
bsw.PutUint8(0x01, 1)
|
||||
bsw.PutUint64(pkg.ESCR_base, 15)
|
||||
bsw.PutUint8(0x01, 1)
|
||||
}
|
||||
bsw.PutBytes(pkg.Pes_payload)
|
||||
}
|
||||
|
|
482
trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/mpeg2/ps-demuxer.go
generated
vendored
482
trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/mpeg2/ps-demuxer.go
generated
vendored
|
@ -1,280 +1,280 @@
|
|||
package mpeg2
|
||||
|
||||
import (
|
||||
"github.com/yapingcat/gomedia/codec"
|
||||
"github.com/yapingcat/gomedia/codec"
|
||||
)
|
||||
|
||||
type psstream struct {
|
||||
sid uint8
|
||||
cid PS_STREAM_TYPE
|
||||
pts uint64
|
||||
dts uint64
|
||||
streamBuf []byte
|
||||
sid uint8
|
||||
cid PS_STREAM_TYPE
|
||||
pts uint64
|
||||
dts uint64
|
||||
streamBuf []byte
|
||||
}
|
||||
|
||||
func newpsstream(sid uint8, cid PS_STREAM_TYPE) *psstream {
|
||||
return &psstream{
|
||||
sid: sid,
|
||||
cid: cid,
|
||||
streamBuf: make([]byte, 0, 4096),
|
||||
}
|
||||
return &psstream{
|
||||
sid: sid,
|
||||
cid: cid,
|
||||
streamBuf: make([]byte, 0, 4096),
|
||||
}
|
||||
}
|
||||
|
||||
type PSDemuxer struct {
|
||||
streamMap map[uint8]*psstream
|
||||
pkg *PSPacket
|
||||
mpeg1 bool
|
||||
cache []byte
|
||||
OnFrame func(frame []byte, cid PS_STREAM_TYPE, pts uint64, dts uint64)
|
||||
//解ps包过程中,解码回调psm,system header,pes包等
|
||||
//decodeResult 解码ps包时的产生的错误
|
||||
//这个回调主要用于debug,查看是否ps包存在问题
|
||||
OnPacket func(pkg Display, decodeResult error)
|
||||
streamMap map[uint8]*psstream
|
||||
pkg *PSPacket
|
||||
mpeg1 bool
|
||||
cache []byte
|
||||
OnFrame func(frame []byte, cid PS_STREAM_TYPE, pts uint64, dts uint64)
|
||||
//解ps包过程中,解码回调psm,system header,pes包等
|
||||
//decodeResult 解码ps包时的产生的错误
|
||||
//这个回调主要用于debug,查看是否ps包存在问题
|
||||
OnPacket func(pkg Display, decodeResult error)
|
||||
}
|
||||
|
||||
func NewPSDemuxer() *PSDemuxer {
|
||||
return &PSDemuxer{
|
||||
streamMap: make(map[uint8]*psstream),
|
||||
pkg: new(PSPacket),
|
||||
cache: make([]byte, 0, 256),
|
||||
OnFrame: nil,
|
||||
OnPacket: nil,
|
||||
}
|
||||
return &PSDemuxer{
|
||||
streamMap: make(map[uint8]*psstream),
|
||||
pkg: new(PSPacket),
|
||||
cache: make([]byte, 0, 256),
|
||||
OnFrame: nil,
|
||||
OnPacket: nil,
|
||||
}
|
||||
}
|
||||
|
||||
func (psdemuxer *PSDemuxer) Input(data []byte) error {
|
||||
var bs *codec.BitStream
|
||||
if len(psdemuxer.cache) > 0 {
|
||||
psdemuxer.cache = append(psdemuxer.cache, data...)
|
||||
bs = codec.NewBitStream(psdemuxer.cache)
|
||||
} else {
|
||||
bs = codec.NewBitStream(data)
|
||||
}
|
||||
var bs *codec.BitStream
|
||||
if len(psdemuxer.cache) > 0 {
|
||||
psdemuxer.cache = append(psdemuxer.cache, data...)
|
||||
bs = codec.NewBitStream(psdemuxer.cache)
|
||||
} else {
|
||||
bs = codec.NewBitStream(data)
|
||||
}
|
||||
|
||||
saveReseved := func() {
|
||||
tmpcache := make([]byte, bs.RemainBytes())
|
||||
copy(tmpcache, bs.RemainData())
|
||||
psdemuxer.cache = tmpcache
|
||||
}
|
||||
saveReseved := func() {
|
||||
tmpcache := make([]byte, bs.RemainBytes())
|
||||
copy(tmpcache, bs.RemainData())
|
||||
psdemuxer.cache = tmpcache
|
||||
}
|
||||
|
||||
var ret error = nil
|
||||
for !bs.EOS() {
|
||||
if mpegerr, ok := ret.(Error); ok {
|
||||
if mpegerr.NeedMore() {
|
||||
saveReseved()
|
||||
}
|
||||
break
|
||||
}
|
||||
if bs.RemainBits() < 32 {
|
||||
ret = errNeedMore
|
||||
saveReseved()
|
||||
break
|
||||
}
|
||||
prefix_code := bs.NextBits(32)
|
||||
switch prefix_code {
|
||||
case 0x000001BA: //pack header
|
||||
if psdemuxer.pkg.Header == nil {
|
||||
psdemuxer.pkg.Header = new(PSPackHeader)
|
||||
}
|
||||
ret = psdemuxer.pkg.Header.Decode(bs)
|
||||
psdemuxer.mpeg1 = psdemuxer.pkg.Header.IsMpeg1
|
||||
if psdemuxer.OnPacket != nil {
|
||||
psdemuxer.OnPacket(psdemuxer.pkg.Header, ret)
|
||||
}
|
||||
case 0x000001BB: //system header
|
||||
if psdemuxer.pkg.Header == nil {
|
||||
panic("psdemuxer.pkg.Header must not be nil")
|
||||
}
|
||||
if psdemuxer.pkg.System == nil {
|
||||
psdemuxer.pkg.System = new(System_header)
|
||||
}
|
||||
ret = psdemuxer.pkg.System.Decode(bs)
|
||||
if psdemuxer.OnPacket != nil {
|
||||
psdemuxer.OnPacket(psdemuxer.pkg.System, ret)
|
||||
}
|
||||
case 0x000001BC: //program stream map
|
||||
if psdemuxer.pkg.Psm == nil {
|
||||
psdemuxer.pkg.Psm = new(Program_stream_map)
|
||||
}
|
||||
if ret = psdemuxer.pkg.Psm.Decode(bs); ret == nil {
|
||||
for _, streaminfo := range psdemuxer.pkg.Psm.Stream_map {
|
||||
if _, found := psdemuxer.streamMap[streaminfo.Elementary_stream_id]; !found {
|
||||
stream := newpsstream(streaminfo.Elementary_stream_id, PS_STREAM_TYPE(streaminfo.Stream_type))
|
||||
psdemuxer.streamMap[stream.sid] = stream
|
||||
}
|
||||
}
|
||||
}
|
||||
if psdemuxer.OnPacket != nil {
|
||||
psdemuxer.OnPacket(psdemuxer.pkg.Psm, ret)
|
||||
}
|
||||
case 0x000001BD, 0x000001BE, 0x000001BF, 0x000001F0, 0x000001F1,
|
||||
0x000001F2, 0x000001F3, 0x000001F4, 0x000001F5, 0x000001F6,
|
||||
0x000001F7, 0x000001F8, 0x000001F9, 0x000001FA, 0x000001FB:
|
||||
if psdemuxer.pkg.CommPes == nil {
|
||||
psdemuxer.pkg.CommPes = new(CommonPesPacket)
|
||||
}
|
||||
ret = psdemuxer.pkg.CommPes.Decode(bs)
|
||||
case 0x000001FF: //program stream directory
|
||||
if psdemuxer.pkg.Psd == nil {
|
||||
psdemuxer.pkg.Psd = new(Program_stream_directory)
|
||||
}
|
||||
ret = psdemuxer.pkg.Psd.Decode(bs)
|
||||
case 0x000001B9: //MPEG_program_end_code
|
||||
continue
|
||||
default:
|
||||
if prefix_code&0xFFFFFFE0 == 0x000001C0 || prefix_code&0xFFFFFFE0 == 0x000001E0 {
|
||||
if psdemuxer.pkg.Pes == nil {
|
||||
psdemuxer.pkg.Pes = NewPesPacket()
|
||||
}
|
||||
if psdemuxer.mpeg1 {
|
||||
ret = psdemuxer.pkg.Pes.DecodeMpeg1(bs)
|
||||
} else {
|
||||
ret = psdemuxer.pkg.Pes.Decode(bs)
|
||||
}
|
||||
if psdemuxer.OnPacket != nil {
|
||||
psdemuxer.OnPacket(psdemuxer.pkg.Pes, ret)
|
||||
}
|
||||
if ret == nil {
|
||||
if stream, found := psdemuxer.streamMap[psdemuxer.pkg.Pes.Stream_id]; found {
|
||||
if psdemuxer.mpeg1 && stream.cid == PS_STREAM_UNKNOW {
|
||||
psdemuxer.guessCodecid(stream)
|
||||
}
|
||||
psdemuxer.demuxPespacket(stream, psdemuxer.pkg.Pes)
|
||||
} else {
|
||||
if psdemuxer.mpeg1 {
|
||||
stream := newpsstream(psdemuxer.pkg.Pes.Stream_id, PS_STREAM_UNKNOW)
|
||||
psdemuxer.streamMap[stream.sid] = stream
|
||||
stream.streamBuf = append(stream.streamBuf, psdemuxer.pkg.Pes.Pes_payload...)
|
||||
stream.pts = psdemuxer.pkg.Pes.Pts
|
||||
stream.dts = psdemuxer.pkg.Pes.Dts
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
bs.SkipBits(8)
|
||||
}
|
||||
}
|
||||
}
|
||||
var ret error = nil
|
||||
for !bs.EOS() {
|
||||
if mpegerr, ok := ret.(Error); ok {
|
||||
if mpegerr.NeedMore() {
|
||||
saveReseved()
|
||||
}
|
||||
break
|
||||
}
|
||||
if bs.RemainBits() < 32 {
|
||||
ret = errNeedMore
|
||||
saveReseved()
|
||||
break
|
||||
}
|
||||
prefix_code := bs.NextBits(32)
|
||||
switch prefix_code {
|
||||
case 0x000001BA: //pack header
|
||||
if psdemuxer.pkg.Header == nil {
|
||||
psdemuxer.pkg.Header = new(PSPackHeader)
|
||||
}
|
||||
ret = psdemuxer.pkg.Header.Decode(bs)
|
||||
psdemuxer.mpeg1 = psdemuxer.pkg.Header.IsMpeg1
|
||||
if psdemuxer.OnPacket != nil {
|
||||
psdemuxer.OnPacket(psdemuxer.pkg.Header, ret)
|
||||
}
|
||||
case 0x000001BB: //system header
|
||||
if psdemuxer.pkg.Header == nil {
|
||||
panic("psdemuxer.pkg.Header must not be nil")
|
||||
}
|
||||
if psdemuxer.pkg.System == nil {
|
||||
psdemuxer.pkg.System = new(System_header)
|
||||
}
|
||||
ret = psdemuxer.pkg.System.Decode(bs)
|
||||
if psdemuxer.OnPacket != nil {
|
||||
psdemuxer.OnPacket(psdemuxer.pkg.System, ret)
|
||||
}
|
||||
case 0x000001BC: //program stream map
|
||||
if psdemuxer.pkg.Psm == nil {
|
||||
psdemuxer.pkg.Psm = new(Program_stream_map)
|
||||
}
|
||||
if ret = psdemuxer.pkg.Psm.Decode(bs); ret == nil {
|
||||
for _, streaminfo := range psdemuxer.pkg.Psm.Stream_map {
|
||||
if _, found := psdemuxer.streamMap[streaminfo.Elementary_stream_id]; !found {
|
||||
stream := newpsstream(streaminfo.Elementary_stream_id, PS_STREAM_TYPE(streaminfo.Stream_type))
|
||||
psdemuxer.streamMap[stream.sid] = stream
|
||||
}
|
||||
}
|
||||
}
|
||||
if psdemuxer.OnPacket != nil {
|
||||
psdemuxer.OnPacket(psdemuxer.pkg.Psm, ret)
|
||||
}
|
||||
case 0x000001BD, 0x000001BE, 0x000001BF, 0x000001F0, 0x000001F1,
|
||||
0x000001F2, 0x000001F3, 0x000001F4, 0x000001F5, 0x000001F6,
|
||||
0x000001F7, 0x000001F8, 0x000001F9, 0x000001FA, 0x000001FB:
|
||||
if psdemuxer.pkg.CommPes == nil {
|
||||
psdemuxer.pkg.CommPes = new(CommonPesPacket)
|
||||
}
|
||||
ret = psdemuxer.pkg.CommPes.Decode(bs)
|
||||
case 0x000001FF: //program stream directory
|
||||
if psdemuxer.pkg.Psd == nil {
|
||||
psdemuxer.pkg.Psd = new(Program_stream_directory)
|
||||
}
|
||||
ret = psdemuxer.pkg.Psd.Decode(bs)
|
||||
case 0x000001B9: //MPEG_program_end_code
|
||||
continue
|
||||
default:
|
||||
if prefix_code&0xFFFFFFE0 == 0x000001C0 || prefix_code&0xFFFFFFE0 == 0x000001E0 {
|
||||
if psdemuxer.pkg.Pes == nil {
|
||||
psdemuxer.pkg.Pes = NewPesPacket()
|
||||
}
|
||||
if psdemuxer.mpeg1 {
|
||||
ret = psdemuxer.pkg.Pes.DecodeMpeg1(bs)
|
||||
} else {
|
||||
ret = psdemuxer.pkg.Pes.Decode(bs)
|
||||
}
|
||||
if psdemuxer.OnPacket != nil {
|
||||
psdemuxer.OnPacket(psdemuxer.pkg.Pes, ret)
|
||||
}
|
||||
if ret == nil {
|
||||
if stream, found := psdemuxer.streamMap[psdemuxer.pkg.Pes.Stream_id]; found {
|
||||
if psdemuxer.mpeg1 && stream.cid == PS_STREAM_UNKNOW {
|
||||
psdemuxer.guessCodecid(stream)
|
||||
}
|
||||
psdemuxer.demuxPespacket(stream, psdemuxer.pkg.Pes)
|
||||
} else {
|
||||
if psdemuxer.mpeg1 {
|
||||
stream := newpsstream(psdemuxer.pkg.Pes.Stream_id, PS_STREAM_UNKNOW)
|
||||
psdemuxer.streamMap[stream.sid] = stream
|
||||
stream.streamBuf = append(stream.streamBuf, psdemuxer.pkg.Pes.Pes_payload...)
|
||||
stream.pts = psdemuxer.pkg.Pes.Pts
|
||||
stream.dts = psdemuxer.pkg.Pes.Dts
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
bs.SkipBits(8)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ret == nil && len(psdemuxer.cache) > 0 {
|
||||
psdemuxer.cache = nil
|
||||
}
|
||||
if ret == nil && len(psdemuxer.cache) > 0 {
|
||||
psdemuxer.cache = nil
|
||||
}
|
||||
|
||||
return ret
|
||||
return ret
|
||||
}
|
||||
|
||||
func (psdemuxer *PSDemuxer) Flush() {
|
||||
for _, stream := range psdemuxer.streamMap {
|
||||
if len(stream.streamBuf) == 0 {
|
||||
continue
|
||||
}
|
||||
if psdemuxer.OnFrame != nil {
|
||||
psdemuxer.OnFrame(stream.streamBuf, stream.cid, stream.pts/90, stream.dts/90)
|
||||
}
|
||||
}
|
||||
for _, stream := range psdemuxer.streamMap {
|
||||
if len(stream.streamBuf) == 0 {
|
||||
continue
|
||||
}
|
||||
if psdemuxer.OnFrame != nil {
|
||||
psdemuxer.OnFrame(stream.streamBuf, stream.cid, stream.pts/90, stream.dts/90)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (psdemuxer *PSDemuxer) guessCodecid(stream *psstream) {
|
||||
if stream.sid&0xE0 == uint8(PES_STREAM_AUDIO) {
|
||||
stream.cid = PS_STREAM_AAC
|
||||
} else if stream.sid&0xE0 == uint8(PES_STREAM_VIDEO) {
|
||||
h264score := 0
|
||||
h265score := 0
|
||||
codec.SplitFrame(stream.streamBuf, func(nalu []byte) bool {
|
||||
h264nalutype := codec.H264NaluTypeWithoutStartCode(nalu)
|
||||
h265nalutype := codec.H265NaluTypeWithoutStartCode(nalu)
|
||||
if h264nalutype == codec.H264_NAL_PPS ||
|
||||
h264nalutype == codec.H264_NAL_SPS ||
|
||||
h264nalutype == codec.H264_NAL_I_SLICE {
|
||||
h264score += 2
|
||||
} else if h264nalutype < 5 {
|
||||
h264score += 1
|
||||
} else if h264nalutype > 20 {
|
||||
h264score -= 1
|
||||
}
|
||||
if stream.sid&0xE0 == uint8(PES_STREAM_AUDIO) {
|
||||
stream.cid = PS_STREAM_AAC
|
||||
} else if stream.sid&0xE0 == uint8(PES_STREAM_VIDEO) {
|
||||
h264score := 0
|
||||
h265score := 0
|
||||
codec.SplitFrame(stream.streamBuf, func(nalu []byte) bool {
|
||||
h264nalutype := codec.H264NaluTypeWithoutStartCode(nalu)
|
||||
h265nalutype := codec.H265NaluTypeWithoutStartCode(nalu)
|
||||
if h264nalutype == codec.H264_NAL_PPS ||
|
||||
h264nalutype == codec.H264_NAL_SPS ||
|
||||
h264nalutype == codec.H264_NAL_I_SLICE {
|
||||
h264score += 2
|
||||
} else if h264nalutype < 5 {
|
||||
h264score += 1
|
||||
} else if h264nalutype > 20 {
|
||||
h264score -= 1
|
||||
}
|
||||
|
||||
if h265nalutype == codec.H265_NAL_PPS ||
|
||||
h265nalutype == codec.H265_NAL_SPS ||
|
||||
h265nalutype == codec.H265_NAL_VPS ||
|
||||
(h265nalutype >= codec.H265_NAL_SLICE_BLA_W_LP && h265nalutype <= codec.H265_NAL_SLICE_CRA) {
|
||||
h265score += 2
|
||||
} else if h265nalutype >= codec.H265_NAL_Slice_TRAIL_N && h265nalutype <= codec.H265_NAL_SLICE_RASL_R {
|
||||
h265score += 1
|
||||
} else if h265nalutype > 40 {
|
||||
h265score -= 1
|
||||
}
|
||||
if h264score > h265score && h264score >= 4 {
|
||||
stream.cid = PS_STREAM_H264
|
||||
} else if h264score < h265score && h265score >= 4 {
|
||||
stream.cid = PS_STREAM_H265
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
||||
if h265nalutype == codec.H265_NAL_PPS ||
|
||||
h265nalutype == codec.H265_NAL_SPS ||
|
||||
h265nalutype == codec.H265_NAL_VPS ||
|
||||
(h265nalutype >= codec.H265_NAL_SLICE_BLA_W_LP && h265nalutype <= codec.H265_NAL_SLICE_CRA) {
|
||||
h265score += 2
|
||||
} else if h265nalutype >= codec.H265_NAL_Slice_TRAIL_N && h265nalutype <= codec.H265_NAL_SLICE_RASL_R {
|
||||
h265score += 1
|
||||
} else if h265nalutype > 40 {
|
||||
h265score -= 1
|
||||
}
|
||||
if h264score > h265score && h264score >= 4 {
|
||||
stream.cid = PS_STREAM_H264
|
||||
} else if h264score < h265score && h265score >= 4 {
|
||||
stream.cid = PS_STREAM_H265
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (psdemuxer *PSDemuxer) demuxPespacket(stream *psstream, pes *PesPacket) error {
|
||||
switch stream.cid {
|
||||
case PS_STREAM_AAC, PS_STREAM_G711A, PS_STREAM_G711U:
|
||||
return psdemuxer.demuxAudio(stream, pes)
|
||||
case PS_STREAM_H264, PS_STREAM_H265:
|
||||
return psdemuxer.demuxH26x(stream, pes)
|
||||
case PS_STREAM_UNKNOW:
|
||||
if stream.pts != pes.Pts {
|
||||
stream.streamBuf = nil
|
||||
}
|
||||
stream.streamBuf = append(stream.streamBuf, pes.Pes_payload...)
|
||||
stream.pts = pes.Pts
|
||||
stream.dts = pes.Dts
|
||||
}
|
||||
return nil
|
||||
switch stream.cid {
|
||||
case PS_STREAM_AAC, PS_STREAM_G711A, PS_STREAM_G711U:
|
||||
return psdemuxer.demuxAudio(stream, pes)
|
||||
case PS_STREAM_H264, PS_STREAM_H265:
|
||||
return psdemuxer.demuxH26x(stream, pes)
|
||||
case PS_STREAM_UNKNOW:
|
||||
if stream.pts != pes.Pts {
|
||||
stream.streamBuf = nil
|
||||
}
|
||||
stream.streamBuf = append(stream.streamBuf, pes.Pes_payload...)
|
||||
stream.pts = pes.Pts
|
||||
stream.dts = pes.Dts
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (psdemuxer *PSDemuxer) demuxAudio(stream *psstream, pes *PesPacket) error {
|
||||
if stream.pts != pes.Pts && len(stream.streamBuf) > 0 {
|
||||
if psdemuxer.OnFrame != nil {
|
||||
psdemuxer.OnFrame(stream.streamBuf, stream.cid, stream.pts/90, stream.dts/90)
|
||||
}
|
||||
stream.streamBuf = stream.streamBuf[:0]
|
||||
}
|
||||
stream.streamBuf = append(stream.streamBuf, pes.Pes_payload...)
|
||||
stream.pts = pes.Pts
|
||||
stream.dts = pes.Dts
|
||||
return nil
|
||||
if stream.pts != pes.Pts && len(stream.streamBuf) > 0 {
|
||||
if psdemuxer.OnFrame != nil {
|
||||
psdemuxer.OnFrame(stream.streamBuf, stream.cid, stream.pts/90, stream.dts/90)
|
||||
}
|
||||
stream.streamBuf = stream.streamBuf[:0]
|
||||
}
|
||||
stream.streamBuf = append(stream.streamBuf, pes.Pes_payload...)
|
||||
stream.pts = pes.Pts
|
||||
stream.dts = pes.Dts
|
||||
return nil
|
||||
}
|
||||
|
||||
func (psdemuxer *PSDemuxer) demuxH26x(stream *psstream, pes *PesPacket) error {
|
||||
if len(stream.streamBuf) == 0 {
|
||||
stream.pts = pes.Pts
|
||||
stream.dts = pes.Dts
|
||||
}
|
||||
stream.streamBuf = append(stream.streamBuf, pes.Pes_payload...)
|
||||
start, sc := codec.FindStartCode(stream.streamBuf, 0)
|
||||
for start >= 0 {
|
||||
end, sc2 := codec.FindStartCode(stream.streamBuf, start+int(sc))
|
||||
if end < 0 {
|
||||
break
|
||||
}
|
||||
if stream.cid == PS_STREAM_H264 {
|
||||
naluType := codec.H264NaluType(stream.streamBuf[start:])
|
||||
if naluType != codec.H264_NAL_AUD {
|
||||
if psdemuxer.OnFrame != nil {
|
||||
psdemuxer.OnFrame(stream.streamBuf[start:end], stream.cid, stream.pts/90, stream.dts/90)
|
||||
}
|
||||
}
|
||||
} else if stream.cid == PS_STREAM_H265 {
|
||||
naluType := codec.H265NaluType(stream.streamBuf[start:])
|
||||
if naluType != codec.H265_NAL_AUD {
|
||||
if psdemuxer.OnFrame != nil {
|
||||
psdemuxer.OnFrame(stream.streamBuf[start:end], stream.cid, stream.pts/90, stream.dts/90)
|
||||
}
|
||||
}
|
||||
}
|
||||
start = end
|
||||
sc = sc2
|
||||
}
|
||||
stream.streamBuf = stream.streamBuf[start:]
|
||||
stream.pts = pes.Pts
|
||||
stream.dts = pes.Dts
|
||||
return nil
|
||||
if len(stream.streamBuf) == 0 {
|
||||
stream.pts = pes.Pts
|
||||
stream.dts = pes.Dts
|
||||
}
|
||||
stream.streamBuf = append(stream.streamBuf, pes.Pes_payload...)
|
||||
start, sc := codec.FindStartCode(stream.streamBuf, 0)
|
||||
for start >= 0 {
|
||||
end, sc2 := codec.FindStartCode(stream.streamBuf, start+int(sc))
|
||||
if end < 0 {
|
||||
break
|
||||
}
|
||||
if stream.cid == PS_STREAM_H264 {
|
||||
naluType := codec.H264NaluType(stream.streamBuf[start:])
|
||||
if naluType != codec.H264_NAL_AUD {
|
||||
if psdemuxer.OnFrame != nil {
|
||||
psdemuxer.OnFrame(stream.streamBuf[start:end], stream.cid, stream.pts/90, stream.dts/90)
|
||||
}
|
||||
}
|
||||
} else if stream.cid == PS_STREAM_H265 {
|
||||
naluType := codec.H265NaluType(stream.streamBuf[start:])
|
||||
if naluType != codec.H265_NAL_AUD {
|
||||
if psdemuxer.OnFrame != nil {
|
||||
psdemuxer.OnFrame(stream.streamBuf[start:end], stream.cid, stream.pts/90, stream.dts/90)
|
||||
}
|
||||
}
|
||||
}
|
||||
start = end
|
||||
sc = sc2
|
||||
}
|
||||
stream.streamBuf = stream.streamBuf[start:]
|
||||
stream.pts = pes.Pts
|
||||
stream.dts = pes.Dts
|
||||
return nil
|
||||
}
|
||||
|
|
264
trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/mpeg2/ps-muxer.go
generated
vendored
264
trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/mpeg2/ps-muxer.go
generated
vendored
|
@ -3,146 +3,146 @@ package mpeg2
|
|||
import "github.com/yapingcat/gomedia/codec"
|
||||
|
||||
type PSMuxer struct {
|
||||
system *System_header
|
||||
psm *Program_stream_map
|
||||
OnPacket func(pkg []byte)
|
||||
firstframe bool
|
||||
system *System_header
|
||||
psm *Program_stream_map
|
||||
OnPacket func(pkg []byte)
|
||||
firstframe bool
|
||||
}
|
||||
|
||||
func NewPsMuxer() *PSMuxer {
|
||||
muxer := new(PSMuxer)
|
||||
muxer.firstframe = true
|
||||
muxer.system = new(System_header)
|
||||
muxer.system.Rate_bound = 26234
|
||||
muxer.psm = new(Program_stream_map)
|
||||
muxer.psm.Current_next_indicator = 1
|
||||
muxer.psm.Program_stream_map_version = 1
|
||||
muxer.OnPacket = nil
|
||||
return muxer
|
||||
muxer := new(PSMuxer)
|
||||
muxer.firstframe = true
|
||||
muxer.system = new(System_header)
|
||||
muxer.system.Rate_bound = 26234
|
||||
muxer.psm = new(Program_stream_map)
|
||||
muxer.psm.Current_next_indicator = 1
|
||||
muxer.psm.Program_stream_map_version = 1
|
||||
muxer.OnPacket = nil
|
||||
return muxer
|
||||
}
|
||||
|
||||
func (muxer *PSMuxer) AddStream(cid PS_STREAM_TYPE) uint8 {
|
||||
if cid == PS_STREAM_H265 || cid == PS_STREAM_H264 {
|
||||
es := NewElementary_Stream(uint8(PES_STREAM_VIDEO) + muxer.system.Video_bound)
|
||||
es.P_STD_buffer_bound_scale = 1
|
||||
es.P_STD_buffer_size_bound = 400
|
||||
muxer.system.Streams = append(muxer.system.Streams, es)
|
||||
muxer.system.Video_bound++
|
||||
muxer.psm.Stream_map = append(muxer.psm.Stream_map, NewElementary_stream_elem(uint8(cid), es.Stream_id))
|
||||
muxer.psm.Program_stream_map_version++
|
||||
return es.Stream_id
|
||||
} else {
|
||||
es := NewElementary_Stream(uint8(PES_STREAM_AUDIO) + muxer.system.Audio_bound)
|
||||
es.P_STD_buffer_bound_scale = 0
|
||||
es.P_STD_buffer_size_bound = 32
|
||||
muxer.system.Streams = append(muxer.system.Streams, es)
|
||||
muxer.system.Audio_bound++
|
||||
muxer.psm.Stream_map = append(muxer.psm.Stream_map, NewElementary_stream_elem(uint8(cid), es.Stream_id))
|
||||
muxer.psm.Program_stream_map_version++
|
||||
return es.Stream_id
|
||||
}
|
||||
if cid == PS_STREAM_H265 || cid == PS_STREAM_H264 {
|
||||
es := NewElementary_Stream(uint8(PES_STREAM_VIDEO) + muxer.system.Video_bound)
|
||||
es.P_STD_buffer_bound_scale = 1
|
||||
es.P_STD_buffer_size_bound = 400
|
||||
muxer.system.Streams = append(muxer.system.Streams, es)
|
||||
muxer.system.Video_bound++
|
||||
muxer.psm.Stream_map = append(muxer.psm.Stream_map, NewElementary_stream_elem(uint8(cid), es.Stream_id))
|
||||
muxer.psm.Program_stream_map_version++
|
||||
return es.Stream_id
|
||||
} else {
|
||||
es := NewElementary_Stream(uint8(PES_STREAM_AUDIO) + muxer.system.Audio_bound)
|
||||
es.P_STD_buffer_bound_scale = 0
|
||||
es.P_STD_buffer_size_bound = 32
|
||||
muxer.system.Streams = append(muxer.system.Streams, es)
|
||||
muxer.system.Audio_bound++
|
||||
muxer.psm.Stream_map = append(muxer.psm.Stream_map, NewElementary_stream_elem(uint8(cid), es.Stream_id))
|
||||
muxer.psm.Program_stream_map_version++
|
||||
return es.Stream_id
|
||||
}
|
||||
}
|
||||
|
||||
func (muxer *PSMuxer) Write(sid uint8, frame []byte, pts uint64, dts uint64) error {
|
||||
var stream *Elementary_stream_elem = nil
|
||||
for _, es := range muxer.psm.Stream_map {
|
||||
if es.Elementary_stream_id == sid {
|
||||
stream = es
|
||||
break
|
||||
}
|
||||
}
|
||||
if stream == nil {
|
||||
return errNotFound
|
||||
}
|
||||
var withaud bool = false
|
||||
var idr_flag bool = false
|
||||
var first bool = true
|
||||
var vcl bool = false
|
||||
if stream.Stream_type == uint8(PS_STREAM_H264) || stream.Stream_type == uint8(PS_STREAM_H265) {
|
||||
codec.SplitFrame(frame, func(nalu []byte) bool {
|
||||
if stream.Stream_type == uint8(PS_STREAM_H264) {
|
||||
nalu_type := codec.H264NaluTypeWithoutStartCode(nalu)
|
||||
if nalu_type == codec.H264_NAL_AUD {
|
||||
withaud = true
|
||||
return false
|
||||
} else if codec.IsH264VCLNaluType(nalu_type) {
|
||||
if nalu_type == codec.H264_NAL_I_SLICE {
|
||||
idr_flag = true
|
||||
}
|
||||
vcl = true
|
||||
return false
|
||||
}
|
||||
return true
|
||||
} else {
|
||||
nalu_type := codec.H265NaluTypeWithoutStartCode(nalu)
|
||||
if nalu_type == codec.H265_NAL_AUD {
|
||||
withaud = true
|
||||
return false
|
||||
} else if codec.IsH265VCLNaluType(nalu_type) {
|
||||
if nalu_type >= codec.H265_NAL_SLICE_BLA_W_LP && nalu_type <= codec.H265_NAL_SLICE_CRA {
|
||||
idr_flag = true
|
||||
}
|
||||
vcl = true
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
})
|
||||
}
|
||||
var stream *Elementary_stream_elem = nil
|
||||
for _, es := range muxer.psm.Stream_map {
|
||||
if es.Elementary_stream_id == sid {
|
||||
stream = es
|
||||
break
|
||||
}
|
||||
}
|
||||
if stream == nil {
|
||||
return errNotFound
|
||||
}
|
||||
var withaud bool = false
|
||||
var idr_flag bool = false
|
||||
var first bool = true
|
||||
var vcl bool = false
|
||||
if stream.Stream_type == uint8(PS_STREAM_H264) || stream.Stream_type == uint8(PS_STREAM_H265) {
|
||||
codec.SplitFrame(frame, func(nalu []byte) bool {
|
||||
if stream.Stream_type == uint8(PS_STREAM_H264) {
|
||||
nalu_type := codec.H264NaluTypeWithoutStartCode(nalu)
|
||||
if nalu_type == codec.H264_NAL_AUD {
|
||||
withaud = true
|
||||
return false
|
||||
} else if codec.IsH264VCLNaluType(nalu_type) {
|
||||
if nalu_type == codec.H264_NAL_I_SLICE {
|
||||
idr_flag = true
|
||||
}
|
||||
vcl = true
|
||||
return false
|
||||
}
|
||||
return true
|
||||
} else {
|
||||
nalu_type := codec.H265NaluTypeWithoutStartCode(nalu)
|
||||
if nalu_type == codec.H265_NAL_AUD {
|
||||
withaud = true
|
||||
return false
|
||||
} else if codec.IsH265VCLNaluType(nalu_type) {
|
||||
if nalu_type >= codec.H265_NAL_SLICE_BLA_W_LP && nalu_type <= codec.H265_NAL_SLICE_CRA {
|
||||
idr_flag = true
|
||||
}
|
||||
vcl = true
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
dts = dts * 90
|
||||
pts = pts * 90
|
||||
bsw := codec.NewBitStreamWriter(1024)
|
||||
var pack PSPackHeader
|
||||
pack.System_clock_reference_base = dts - 3600
|
||||
pack.System_clock_reference_extension = 0
|
||||
pack.Program_mux_rate = 6106
|
||||
pack.Encode(bsw)
|
||||
if muxer.firstframe || idr_flag {
|
||||
muxer.system.Encode(bsw)
|
||||
muxer.psm.Encode(bsw)
|
||||
muxer.firstframe = false
|
||||
}
|
||||
if muxer.OnPacket != nil {
|
||||
muxer.OnPacket(bsw.Bits())
|
||||
}
|
||||
bsw.Reset()
|
||||
pespkg := NewPesPacket()
|
||||
for len(frame) > 0 {
|
||||
peshdrlen := 13
|
||||
pespkg.Stream_id = sid
|
||||
pespkg.PTS_DTS_flags = 0x03
|
||||
pespkg.PES_header_data_length = 10
|
||||
pespkg.Pts = pts
|
||||
pespkg.Dts = dts
|
||||
if idr_flag {
|
||||
pespkg.Data_alignment_indicator = 1
|
||||
}
|
||||
if first && !withaud && vcl {
|
||||
if stream.Stream_type == uint8(PS_STREAM_H264) {
|
||||
pespkg.Pes_payload = append(pespkg.Pes_payload, H264_AUD_NALU...)
|
||||
peshdrlen += 6
|
||||
} else if stream.Stream_type == uint8(PS_STREAM_H265) {
|
||||
pespkg.Pes_payload = append(pespkg.Pes_payload, H265_AUD_NALU...)
|
||||
peshdrlen += 7
|
||||
}
|
||||
}
|
||||
if peshdrlen+len(frame) >= 0xFFFF {
|
||||
pespkg.PES_packet_length = 0xFFFF
|
||||
pespkg.Pes_payload = append(pespkg.Pes_payload, frame[0:0xFFFF-peshdrlen]...)
|
||||
frame = frame[0xFFFF-peshdrlen:]
|
||||
} else {
|
||||
pespkg.PES_packet_length = uint16(peshdrlen + len(frame))
|
||||
pespkg.Pes_payload = append(pespkg.Pes_payload, frame[0:]...)
|
||||
frame = frame[:0]
|
||||
}
|
||||
pespkg.Encode(bsw)
|
||||
pespkg.Pes_payload = pespkg.Pes_payload[:0]
|
||||
if muxer.OnPacket != nil {
|
||||
muxer.OnPacket(bsw.Bits())
|
||||
}
|
||||
bsw.Reset()
|
||||
first = false
|
||||
}
|
||||
return nil
|
||||
dts = dts * 90
|
||||
pts = pts * 90
|
||||
bsw := codec.NewBitStreamWriter(1024)
|
||||
var pack PSPackHeader
|
||||
pack.System_clock_reference_base = dts - 3600
|
||||
pack.System_clock_reference_extension = 0
|
||||
pack.Program_mux_rate = 6106
|
||||
pack.Encode(bsw)
|
||||
if muxer.firstframe || idr_flag {
|
||||
muxer.system.Encode(bsw)
|
||||
muxer.psm.Encode(bsw)
|
||||
muxer.firstframe = false
|
||||
}
|
||||
if muxer.OnPacket != nil {
|
||||
muxer.OnPacket(bsw.Bits())
|
||||
}
|
||||
bsw.Reset()
|
||||
pespkg := NewPesPacket()
|
||||
for len(frame) > 0 {
|
||||
peshdrlen := 13
|
||||
pespkg.Stream_id = sid
|
||||
pespkg.PTS_DTS_flags = 0x03
|
||||
pespkg.PES_header_data_length = 10
|
||||
pespkg.Pts = pts
|
||||
pespkg.Dts = dts
|
||||
if idr_flag {
|
||||
pespkg.Data_alignment_indicator = 1
|
||||
}
|
||||
if first && !withaud && vcl {
|
||||
if stream.Stream_type == uint8(PS_STREAM_H264) {
|
||||
pespkg.Pes_payload = append(pespkg.Pes_payload, H264_AUD_NALU...)
|
||||
peshdrlen += 6
|
||||
} else if stream.Stream_type == uint8(PS_STREAM_H265) {
|
||||
pespkg.Pes_payload = append(pespkg.Pes_payload, H265_AUD_NALU...)
|
||||
peshdrlen += 7
|
||||
}
|
||||
}
|
||||
if peshdrlen+len(frame) >= 0xFFFF {
|
||||
pespkg.PES_packet_length = 0xFFFF
|
||||
pespkg.Pes_payload = append(pespkg.Pes_payload, frame[0:0xFFFF-peshdrlen]...)
|
||||
frame = frame[0xFFFF-peshdrlen:]
|
||||
} else {
|
||||
pespkg.PES_packet_length = uint16(peshdrlen + len(frame))
|
||||
pespkg.Pes_payload = append(pespkg.Pes_payload, frame[0:]...)
|
||||
frame = frame[:0]
|
||||
}
|
||||
pespkg.Encode(bsw)
|
||||
pespkg.Pes_payload = pespkg.Pes_payload[:0]
|
||||
if muxer.OnPacket != nil {
|
||||
muxer.OnPacket(bsw.Bits())
|
||||
}
|
||||
bsw.Reset()
|
||||
first = false
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
670
trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/mpeg2/ps-proto.go
generated
vendored
670
trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/mpeg2/ps-proto.go
generated
vendored
|
@ -1,17 +1,17 @@
|
|||
package mpeg2
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"os"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/yapingcat/gomedia/codec"
|
||||
"github.com/yapingcat/gomedia/codec"
|
||||
)
|
||||
|
||||
type Error interface {
|
||||
NeedMore() bool
|
||||
ParserError() bool
|
||||
StreamIdNotFound() bool
|
||||
NeedMore() bool
|
||||
ParserError() bool
|
||||
StreamIdNotFound() bool
|
||||
}
|
||||
|
||||
var errNeedMore error = &needmoreError{}
|
||||
|
@ -44,12 +44,12 @@ func (e *sidNotFoundError) StreamIdNotFound() bool { return true }
|
|||
type PS_STREAM_TYPE int
|
||||
|
||||
const (
|
||||
PS_STREAM_UNKNOW PS_STREAM_TYPE = 0xFF
|
||||
PS_STREAM_AAC PS_STREAM_TYPE = 0x0F
|
||||
PS_STREAM_H264 PS_STREAM_TYPE = 0x1B
|
||||
PS_STREAM_H265 PS_STREAM_TYPE = 0x24
|
||||
PS_STREAM_G711A PS_STREAM_TYPE = 0x90
|
||||
PS_STREAM_G711U PS_STREAM_TYPE = 0x91
|
||||
PS_STREAM_UNKNOW PS_STREAM_TYPE = 0xFF
|
||||
PS_STREAM_AAC PS_STREAM_TYPE = 0x0F
|
||||
PS_STREAM_H264 PS_STREAM_TYPE = 0x1B
|
||||
PS_STREAM_H265 PS_STREAM_TYPE = 0x24
|
||||
PS_STREAM_G711A PS_STREAM_TYPE = 0x90
|
||||
PS_STREAM_G711U PS_STREAM_TYPE = 0x91
|
||||
)
|
||||
|
||||
// Table 2-33 – Program Stream pack header
|
||||
|
@ -78,113 +78,113 @@ const (
|
|||
// }
|
||||
|
||||
type PSPackHeader struct {
|
||||
IsMpeg1 bool
|
||||
System_clock_reference_base uint64 //33 bits
|
||||
System_clock_reference_extension uint16 //9 bits
|
||||
Program_mux_rate uint32 //22 bits
|
||||
Pack_stuffing_length uint8 //3 bitss
|
||||
IsMpeg1 bool
|
||||
System_clock_reference_base uint64 //33 bits
|
||||
System_clock_reference_extension uint16 //9 bits
|
||||
Program_mux_rate uint32 //22 bits
|
||||
Pack_stuffing_length uint8 //3 bitss
|
||||
}
|
||||
|
||||
func (ps_pkg_hdr *PSPackHeader) PrettyPrint(file *os.File) {
|
||||
file.WriteString(fmt.Sprintf("IsMpeg1:%t\n", ps_pkg_hdr.IsMpeg1))
|
||||
file.WriteString(fmt.Sprintf("System_clock_reference_base:%d\n", ps_pkg_hdr.System_clock_reference_base))
|
||||
file.WriteString(fmt.Sprintf("System_clock_reference_extension:%d\n", ps_pkg_hdr.System_clock_reference_extension))
|
||||
file.WriteString(fmt.Sprintf("Program_mux_rate:%d\n", ps_pkg_hdr.Program_mux_rate))
|
||||
file.WriteString(fmt.Sprintf("Pack_stuffing_length:%d\n", ps_pkg_hdr.Pack_stuffing_length))
|
||||
file.WriteString(fmt.Sprintf("IsMpeg1:%t\n", ps_pkg_hdr.IsMpeg1))
|
||||
file.WriteString(fmt.Sprintf("System_clock_reference_base:%d\n", ps_pkg_hdr.System_clock_reference_base))
|
||||
file.WriteString(fmt.Sprintf("System_clock_reference_extension:%d\n", ps_pkg_hdr.System_clock_reference_extension))
|
||||
file.WriteString(fmt.Sprintf("Program_mux_rate:%d\n", ps_pkg_hdr.Program_mux_rate))
|
||||
file.WriteString(fmt.Sprintf("Pack_stuffing_length:%d\n", ps_pkg_hdr.Pack_stuffing_length))
|
||||
}
|
||||
|
||||
func (ps_pkg_hdr *PSPackHeader) Decode(bs *codec.BitStream) error {
|
||||
if bs.RemainBytes() < 5 {
|
||||
return errNeedMore
|
||||
}
|
||||
if bs.Uint32(32) != 0x000001BA {
|
||||
panic("ps header must start with 000001BA")
|
||||
}
|
||||
if bs.RemainBytes() < 5 {
|
||||
return errNeedMore
|
||||
}
|
||||
if bs.Uint32(32) != 0x000001BA {
|
||||
panic("ps header must start with 000001BA")
|
||||
}
|
||||
|
||||
if bs.NextBits(2) == 0x01 { //mpeg2
|
||||
if bs.RemainBytes() < 10 {
|
||||
return errNeedMore
|
||||
}
|
||||
return ps_pkg_hdr.decodeMpeg2(bs)
|
||||
} else if bs.NextBits(4) == 0x02 { //mpeg1
|
||||
if bs.RemainBytes() < 8 {
|
||||
return errNeedMore
|
||||
}
|
||||
ps_pkg_hdr.IsMpeg1 = true
|
||||
return ps_pkg_hdr.decodeMpeg1(bs)
|
||||
} else {
|
||||
return errParser
|
||||
}
|
||||
if bs.NextBits(2) == 0x01 { //mpeg2
|
||||
if bs.RemainBytes() < 10 {
|
||||
return errNeedMore
|
||||
}
|
||||
return ps_pkg_hdr.decodeMpeg2(bs)
|
||||
} else if bs.NextBits(4) == 0x02 { //mpeg1
|
||||
if bs.RemainBytes() < 8 {
|
||||
return errNeedMore
|
||||
}
|
||||
ps_pkg_hdr.IsMpeg1 = true
|
||||
return ps_pkg_hdr.decodeMpeg1(bs)
|
||||
} else {
|
||||
return errParser
|
||||
}
|
||||
}
|
||||
|
||||
func (ps_pkg_hdr *PSPackHeader) decodeMpeg2(bs *codec.BitStream) error {
|
||||
bs.SkipBits(2)
|
||||
ps_pkg_hdr.System_clock_reference_base = bs.GetBits(3)
|
||||
bs.SkipBits(1)
|
||||
ps_pkg_hdr.System_clock_reference_base = ps_pkg_hdr.System_clock_reference_base<<15 | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
ps_pkg_hdr.System_clock_reference_base = ps_pkg_hdr.System_clock_reference_base<<15 | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
ps_pkg_hdr.System_clock_reference_extension = bs.Uint16(9)
|
||||
bs.SkipBits(1)
|
||||
ps_pkg_hdr.Program_mux_rate = bs.Uint32(22)
|
||||
bs.SkipBits(1)
|
||||
bs.SkipBits(1)
|
||||
bs.SkipBits(5)
|
||||
ps_pkg_hdr.Pack_stuffing_length = bs.Uint8(3)
|
||||
if bs.RemainBytes() < int(ps_pkg_hdr.Pack_stuffing_length) {
|
||||
bs.UnRead(10 * 8)
|
||||
return errNeedMore
|
||||
}
|
||||
bs.SkipBits(int(ps_pkg_hdr.Pack_stuffing_length) * 8)
|
||||
return nil
|
||||
bs.SkipBits(2)
|
||||
ps_pkg_hdr.System_clock_reference_base = bs.GetBits(3)
|
||||
bs.SkipBits(1)
|
||||
ps_pkg_hdr.System_clock_reference_base = ps_pkg_hdr.System_clock_reference_base<<15 | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
ps_pkg_hdr.System_clock_reference_base = ps_pkg_hdr.System_clock_reference_base<<15 | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
ps_pkg_hdr.System_clock_reference_extension = bs.Uint16(9)
|
||||
bs.SkipBits(1)
|
||||
ps_pkg_hdr.Program_mux_rate = bs.Uint32(22)
|
||||
bs.SkipBits(1)
|
||||
bs.SkipBits(1)
|
||||
bs.SkipBits(5)
|
||||
ps_pkg_hdr.Pack_stuffing_length = bs.Uint8(3)
|
||||
if bs.RemainBytes() < int(ps_pkg_hdr.Pack_stuffing_length) {
|
||||
bs.UnRead(10 * 8)
|
||||
return errNeedMore
|
||||
}
|
||||
bs.SkipBits(int(ps_pkg_hdr.Pack_stuffing_length) * 8)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ps_pkg_hdr *PSPackHeader) decodeMpeg1(bs *codec.BitStream) error {
|
||||
bs.SkipBits(4)
|
||||
ps_pkg_hdr.System_clock_reference_base = bs.GetBits(3)
|
||||
bs.SkipBits(1)
|
||||
ps_pkg_hdr.System_clock_reference_base = ps_pkg_hdr.System_clock_reference_base<<15 | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
ps_pkg_hdr.System_clock_reference_base = ps_pkg_hdr.System_clock_reference_base<<15 | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
ps_pkg_hdr.System_clock_reference_extension = 1
|
||||
ps_pkg_hdr.Program_mux_rate = bs.Uint32(7)
|
||||
bs.SkipBits(1)
|
||||
ps_pkg_hdr.Program_mux_rate = ps_pkg_hdr.Program_mux_rate<<15 | bs.Uint32(15)
|
||||
bs.SkipBits(1)
|
||||
return nil
|
||||
bs.SkipBits(4)
|
||||
ps_pkg_hdr.System_clock_reference_base = bs.GetBits(3)
|
||||
bs.SkipBits(1)
|
||||
ps_pkg_hdr.System_clock_reference_base = ps_pkg_hdr.System_clock_reference_base<<15 | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
ps_pkg_hdr.System_clock_reference_base = ps_pkg_hdr.System_clock_reference_base<<15 | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
ps_pkg_hdr.System_clock_reference_extension = 1
|
||||
ps_pkg_hdr.Program_mux_rate = bs.Uint32(7)
|
||||
bs.SkipBits(1)
|
||||
ps_pkg_hdr.Program_mux_rate = ps_pkg_hdr.Program_mux_rate<<15 | bs.Uint32(15)
|
||||
bs.SkipBits(1)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ps_pkg_hdr *PSPackHeader) Encode(bsw *codec.BitStreamWriter) {
|
||||
bsw.PutBytes([]byte{0x00, 0x00, 0x01, 0xBA})
|
||||
bsw.PutUint8(1, 2)
|
||||
bsw.PutUint64(ps_pkg_hdr.System_clock_reference_base>>30, 3)
|
||||
bsw.PutUint8(1, 1)
|
||||
bsw.PutUint64(ps_pkg_hdr.System_clock_reference_base>>15, 15)
|
||||
bsw.PutUint8(1, 1)
|
||||
bsw.PutUint64(ps_pkg_hdr.System_clock_reference_base, 15)
|
||||
bsw.PutUint8(1, 1)
|
||||
bsw.PutUint16(ps_pkg_hdr.System_clock_reference_extension, 9)
|
||||
bsw.PutUint8(1, 1)
|
||||
bsw.PutUint32(ps_pkg_hdr.Program_mux_rate, 22)
|
||||
bsw.PutUint8(1, 1)
|
||||
bsw.PutUint8(1, 1)
|
||||
bsw.PutUint8(0x1F, 5)
|
||||
bsw.PutUint8(ps_pkg_hdr.Pack_stuffing_length, 3)
|
||||
bsw.PutRepetValue(0xFF, int(ps_pkg_hdr.Pack_stuffing_length))
|
||||
bsw.PutBytes([]byte{0x00, 0x00, 0x01, 0xBA})
|
||||
bsw.PutUint8(1, 2)
|
||||
bsw.PutUint64(ps_pkg_hdr.System_clock_reference_base>>30, 3)
|
||||
bsw.PutUint8(1, 1)
|
||||
bsw.PutUint64(ps_pkg_hdr.System_clock_reference_base>>15, 15)
|
||||
bsw.PutUint8(1, 1)
|
||||
bsw.PutUint64(ps_pkg_hdr.System_clock_reference_base, 15)
|
||||
bsw.PutUint8(1, 1)
|
||||
bsw.PutUint16(ps_pkg_hdr.System_clock_reference_extension, 9)
|
||||
bsw.PutUint8(1, 1)
|
||||
bsw.PutUint32(ps_pkg_hdr.Program_mux_rate, 22)
|
||||
bsw.PutUint8(1, 1)
|
||||
bsw.PutUint8(1, 1)
|
||||
bsw.PutUint8(0x1F, 5)
|
||||
bsw.PutUint8(ps_pkg_hdr.Pack_stuffing_length, 3)
|
||||
bsw.PutRepetValue(0xFF, int(ps_pkg_hdr.Pack_stuffing_length))
|
||||
}
|
||||
|
||||
type Elementary_Stream struct {
|
||||
Stream_id uint8
|
||||
P_STD_buffer_bound_scale uint8
|
||||
P_STD_buffer_size_bound uint16
|
||||
Stream_id uint8
|
||||
P_STD_buffer_bound_scale uint8
|
||||
P_STD_buffer_size_bound uint16
|
||||
}
|
||||
|
||||
func NewElementary_Stream(sid uint8) *Elementary_Stream {
|
||||
return &Elementary_Stream{
|
||||
Stream_id: sid,
|
||||
}
|
||||
return &Elementary_Stream{
|
||||
Stream_id: sid,
|
||||
}
|
||||
}
|
||||
|
||||
// system_header () {
|
||||
|
@ -211,118 +211,118 @@ func NewElementary_Stream(sid uint8) *Elementary_Stream {
|
|||
// }
|
||||
|
||||
type System_header struct {
|
||||
Header_length uint16
|
||||
Rate_bound uint32
|
||||
Audio_bound uint8
|
||||
Fixed_flag uint8
|
||||
CSPS_flag uint8
|
||||
System_audio_lock_flag uint8
|
||||
System_video_lock_flag uint8
|
||||
Video_bound uint8
|
||||
Packet_rate_restriction_flag uint8
|
||||
Streams []*Elementary_Stream
|
||||
Header_length uint16
|
||||
Rate_bound uint32
|
||||
Audio_bound uint8
|
||||
Fixed_flag uint8
|
||||
CSPS_flag uint8
|
||||
System_audio_lock_flag uint8
|
||||
System_video_lock_flag uint8
|
||||
Video_bound uint8
|
||||
Packet_rate_restriction_flag uint8
|
||||
Streams []*Elementary_Stream
|
||||
}
|
||||
|
||||
func (sh *System_header) PrettyPrint(file *os.File) {
|
||||
file.WriteString(fmt.Sprintf("Header_length:%d\n", sh.Header_length))
|
||||
file.WriteString(fmt.Sprintf("Rate_bound:%d\n", sh.Rate_bound))
|
||||
file.WriteString(fmt.Sprintf("Audio_bound:%d\n", sh.Audio_bound))
|
||||
file.WriteString(fmt.Sprintf("Fixed_flag:%d\n", sh.Fixed_flag))
|
||||
file.WriteString(fmt.Sprintf("CSPS_flag:%d\n", sh.CSPS_flag))
|
||||
file.WriteString(fmt.Sprintf("System_audio_lock_flag:%d\n", sh.System_audio_lock_flag))
|
||||
file.WriteString(fmt.Sprintf("System_video_lock_flag:%d\n", sh.System_video_lock_flag))
|
||||
file.WriteString(fmt.Sprintf("Video_bound:%d\n", sh.Video_bound))
|
||||
file.WriteString(fmt.Sprintf("Packet_rate_restriction_flag:%d\n", sh.Packet_rate_restriction_flag))
|
||||
for i, es := range sh.Streams {
|
||||
file.WriteString(fmt.Sprintf("----streams %d\n", i))
|
||||
file.WriteString(fmt.Sprintf(" Stream_id:%d\n", es.Stream_id))
|
||||
file.WriteString(fmt.Sprintf(" P_STD_buffer_bound_scale:%d\n", es.P_STD_buffer_bound_scale))
|
||||
file.WriteString(fmt.Sprintf(" P_STD_buffer_size_bound:%d\n", es.P_STD_buffer_size_bound))
|
||||
}
|
||||
file.WriteString(fmt.Sprintf("Header_length:%d\n", sh.Header_length))
|
||||
file.WriteString(fmt.Sprintf("Rate_bound:%d\n", sh.Rate_bound))
|
||||
file.WriteString(fmt.Sprintf("Audio_bound:%d\n", sh.Audio_bound))
|
||||
file.WriteString(fmt.Sprintf("Fixed_flag:%d\n", sh.Fixed_flag))
|
||||
file.WriteString(fmt.Sprintf("CSPS_flag:%d\n", sh.CSPS_flag))
|
||||
file.WriteString(fmt.Sprintf("System_audio_lock_flag:%d\n", sh.System_audio_lock_flag))
|
||||
file.WriteString(fmt.Sprintf("System_video_lock_flag:%d\n", sh.System_video_lock_flag))
|
||||
file.WriteString(fmt.Sprintf("Video_bound:%d\n", sh.Video_bound))
|
||||
file.WriteString(fmt.Sprintf("Packet_rate_restriction_flag:%d\n", sh.Packet_rate_restriction_flag))
|
||||
for i, es := range sh.Streams {
|
||||
file.WriteString(fmt.Sprintf("----streams %d\n", i))
|
||||
file.WriteString(fmt.Sprintf(" Stream_id:%d\n", es.Stream_id))
|
||||
file.WriteString(fmt.Sprintf(" P_STD_buffer_bound_scale:%d\n", es.P_STD_buffer_bound_scale))
|
||||
file.WriteString(fmt.Sprintf(" P_STD_buffer_size_bound:%d\n", es.P_STD_buffer_size_bound))
|
||||
}
|
||||
}
|
||||
|
||||
func (sh *System_header) Encode(bsw *codec.BitStreamWriter) {
|
||||
bsw.PutBytes([]byte{0x00, 0x00, 0x01, 0xBB})
|
||||
loc := bsw.ByteOffset()
|
||||
bsw.PutUint16(0, 16)
|
||||
bsw.Markdot()
|
||||
bsw.PutUint8(1, 1)
|
||||
bsw.PutUint32(sh.Rate_bound, 22)
|
||||
bsw.PutUint8(1, 1)
|
||||
bsw.PutUint8(sh.Audio_bound, 6)
|
||||
bsw.PutUint8(sh.Fixed_flag, 1)
|
||||
bsw.PutUint8(sh.CSPS_flag, 1)
|
||||
bsw.PutUint8(sh.System_audio_lock_flag, 1)
|
||||
bsw.PutUint8(sh.System_video_lock_flag, 1)
|
||||
bsw.PutUint8(1, 1)
|
||||
bsw.PutUint8(sh.Video_bound, 5)
|
||||
bsw.PutUint8(sh.Packet_rate_restriction_flag, 1)
|
||||
bsw.PutUint8(0x7F, 7)
|
||||
for _, stream := range sh.Streams {
|
||||
bsw.PutUint8(stream.Stream_id, 8)
|
||||
bsw.PutUint8(3, 2)
|
||||
bsw.PutUint8(stream.P_STD_buffer_bound_scale, 1)
|
||||
bsw.PutUint16(stream.P_STD_buffer_size_bound, 13)
|
||||
}
|
||||
length := bsw.DistanceFromMarkDot() / 8
|
||||
bsw.SetUint16(uint16(length), loc)
|
||||
bsw.PutBytes([]byte{0x00, 0x00, 0x01, 0xBB})
|
||||
loc := bsw.ByteOffset()
|
||||
bsw.PutUint16(0, 16)
|
||||
bsw.Markdot()
|
||||
bsw.PutUint8(1, 1)
|
||||
bsw.PutUint32(sh.Rate_bound, 22)
|
||||
bsw.PutUint8(1, 1)
|
||||
bsw.PutUint8(sh.Audio_bound, 6)
|
||||
bsw.PutUint8(sh.Fixed_flag, 1)
|
||||
bsw.PutUint8(sh.CSPS_flag, 1)
|
||||
bsw.PutUint8(sh.System_audio_lock_flag, 1)
|
||||
bsw.PutUint8(sh.System_video_lock_flag, 1)
|
||||
bsw.PutUint8(1, 1)
|
||||
bsw.PutUint8(sh.Video_bound, 5)
|
||||
bsw.PutUint8(sh.Packet_rate_restriction_flag, 1)
|
||||
bsw.PutUint8(0x7F, 7)
|
||||
for _, stream := range sh.Streams {
|
||||
bsw.PutUint8(stream.Stream_id, 8)
|
||||
bsw.PutUint8(3, 2)
|
||||
bsw.PutUint8(stream.P_STD_buffer_bound_scale, 1)
|
||||
bsw.PutUint16(stream.P_STD_buffer_size_bound, 13)
|
||||
}
|
||||
length := bsw.DistanceFromMarkDot() / 8
|
||||
bsw.SetUint16(uint16(length), loc)
|
||||
}
|
||||
|
||||
func (sh *System_header) Decode(bs *codec.BitStream) error {
|
||||
if bs.RemainBytes() < 12 {
|
||||
return errNeedMore
|
||||
}
|
||||
if bs.Uint32(32) != 0x000001BB {
|
||||
panic("system header must start with 000001BB")
|
||||
}
|
||||
sh.Header_length = bs.Uint16(16)
|
||||
if bs.RemainBytes() < int(sh.Header_length) {
|
||||
bs.UnRead(6 * 8)
|
||||
return errNeedMore
|
||||
}
|
||||
if sh.Header_length < 6 || (sh.Header_length-6)%3 != 0 {
|
||||
return errParser
|
||||
}
|
||||
bs.SkipBits(1)
|
||||
sh.Rate_bound = bs.Uint32(22)
|
||||
bs.SkipBits(1)
|
||||
sh.Audio_bound = bs.Uint8(6)
|
||||
sh.Fixed_flag = bs.Uint8(1)
|
||||
sh.CSPS_flag = bs.Uint8(1)
|
||||
sh.System_audio_lock_flag = bs.Uint8(1)
|
||||
sh.System_video_lock_flag = bs.Uint8(1)
|
||||
bs.SkipBits(1)
|
||||
sh.Video_bound = bs.Uint8(5)
|
||||
sh.Packet_rate_restriction_flag = bs.Uint8(1)
|
||||
bs.SkipBits(7)
|
||||
sh.Streams = sh.Streams[:0]
|
||||
least := sh.Header_length - 6
|
||||
for least > 0 && bs.NextBits(1) == 0x01 {
|
||||
es := new(Elementary_Stream)
|
||||
es.Stream_id = bs.Uint8(8)
|
||||
bs.SkipBits(2)
|
||||
es.P_STD_buffer_bound_scale = bs.GetBit()
|
||||
es.P_STD_buffer_size_bound = bs.Uint16(13)
|
||||
sh.Streams = append(sh.Streams, es)
|
||||
least -= 3
|
||||
}
|
||||
if least > 0 {
|
||||
return errParser
|
||||
}
|
||||
return nil
|
||||
if bs.RemainBytes() < 12 {
|
||||
return errNeedMore
|
||||
}
|
||||
if bs.Uint32(32) != 0x000001BB {
|
||||
panic("system header must start with 000001BB")
|
||||
}
|
||||
sh.Header_length = bs.Uint16(16)
|
||||
if bs.RemainBytes() < int(sh.Header_length) {
|
||||
bs.UnRead(6 * 8)
|
||||
return errNeedMore
|
||||
}
|
||||
if sh.Header_length < 6 || (sh.Header_length-6)%3 != 0 {
|
||||
return errParser
|
||||
}
|
||||
bs.SkipBits(1)
|
||||
sh.Rate_bound = bs.Uint32(22)
|
||||
bs.SkipBits(1)
|
||||
sh.Audio_bound = bs.Uint8(6)
|
||||
sh.Fixed_flag = bs.Uint8(1)
|
||||
sh.CSPS_flag = bs.Uint8(1)
|
||||
sh.System_audio_lock_flag = bs.Uint8(1)
|
||||
sh.System_video_lock_flag = bs.Uint8(1)
|
||||
bs.SkipBits(1)
|
||||
sh.Video_bound = bs.Uint8(5)
|
||||
sh.Packet_rate_restriction_flag = bs.Uint8(1)
|
||||
bs.SkipBits(7)
|
||||
sh.Streams = sh.Streams[:0]
|
||||
least := sh.Header_length - 6
|
||||
for least > 0 && bs.NextBits(1) == 0x01 {
|
||||
es := new(Elementary_Stream)
|
||||
es.Stream_id = bs.Uint8(8)
|
||||
bs.SkipBits(2)
|
||||
es.P_STD_buffer_bound_scale = bs.GetBit()
|
||||
es.P_STD_buffer_size_bound = bs.Uint16(13)
|
||||
sh.Streams = append(sh.Streams, es)
|
||||
least -= 3
|
||||
}
|
||||
if least > 0 {
|
||||
return errParser
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Elementary_stream_elem struct {
|
||||
Stream_type uint8
|
||||
Elementary_stream_id uint8
|
||||
Elementary_stream_info_length uint16
|
||||
Stream_type uint8
|
||||
Elementary_stream_id uint8
|
||||
Elementary_stream_info_length uint16
|
||||
}
|
||||
|
||||
func NewElementary_stream_elem(stype uint8, esid uint8) *Elementary_stream_elem {
|
||||
return &Elementary_stream_elem{
|
||||
Stream_type: stype,
|
||||
Elementary_stream_id: esid,
|
||||
}
|
||||
return &Elementary_stream_elem{
|
||||
Stream_type: stype,
|
||||
Elementary_stream_id: esid,
|
||||
}
|
||||
}
|
||||
|
||||
// program_stream_map() {
|
||||
|
@ -351,171 +351,171 @@ func NewElementary_stream_elem(stype uint8, esid uint8) *Elementary_stream_elem
|
|||
// }
|
||||
|
||||
type Program_stream_map struct {
|
||||
Map_stream_id uint8
|
||||
Program_stream_map_length uint16
|
||||
Current_next_indicator uint8
|
||||
Program_stream_map_version uint8
|
||||
Program_stream_info_length uint16
|
||||
Elementary_stream_map_length uint16
|
||||
Stream_map []*Elementary_stream_elem
|
||||
Map_stream_id uint8
|
||||
Program_stream_map_length uint16
|
||||
Current_next_indicator uint8
|
||||
Program_stream_map_version uint8
|
||||
Program_stream_info_length uint16
|
||||
Elementary_stream_map_length uint16
|
||||
Stream_map []*Elementary_stream_elem
|
||||
}
|
||||
|
||||
func (psm *Program_stream_map) PrettyPrint(file *os.File) {
|
||||
file.WriteString(fmt.Sprintf("map_stream_id:%d\n", psm.Map_stream_id))
|
||||
file.WriteString(fmt.Sprintf("program_stream_map_length:%d\n", psm.Program_stream_map_length))
|
||||
file.WriteString(fmt.Sprintf("current_next_indicator:%d\n", psm.Current_next_indicator))
|
||||
file.WriteString(fmt.Sprintf("program_stream_map_version:%d\n", psm.Program_stream_map_version))
|
||||
file.WriteString(fmt.Sprintf("program_stream_info_length:%d\n", psm.Program_stream_info_length))
|
||||
file.WriteString(fmt.Sprintf("elementary_stream_map_length:%d\n", psm.Elementary_stream_map_length))
|
||||
for i, es := range psm.Stream_map {
|
||||
file.WriteString(fmt.Sprintf("----ES stream %d\n", i))
|
||||
if es.Stream_type == uint8(PS_STREAM_AAC) {
|
||||
file.WriteString(" stream_type:AAC\n")
|
||||
} else if es.Stream_type == uint8(PS_STREAM_G711A) {
|
||||
file.WriteString(" stream_type:G711A\n")
|
||||
} else if es.Stream_type == uint8(PS_STREAM_G711U) {
|
||||
file.WriteString(" stream_type:G711U\n")
|
||||
} else if es.Stream_type == uint8(PS_STREAM_H264) {
|
||||
file.WriteString(" stream_type:H264\n")
|
||||
} else if es.Stream_type == uint8(PS_STREAM_H265) {
|
||||
file.WriteString(" stream_type:H265\n")
|
||||
}
|
||||
file.WriteString(fmt.Sprintf(" elementary_stream_id:%d\n", es.Elementary_stream_id))
|
||||
file.WriteString(fmt.Sprintf(" elementary_stream_info_length:%d\n", es.Elementary_stream_info_length))
|
||||
}
|
||||
file.WriteString(fmt.Sprintf("map_stream_id:%d\n", psm.Map_stream_id))
|
||||
file.WriteString(fmt.Sprintf("program_stream_map_length:%d\n", psm.Program_stream_map_length))
|
||||
file.WriteString(fmt.Sprintf("current_next_indicator:%d\n", psm.Current_next_indicator))
|
||||
file.WriteString(fmt.Sprintf("program_stream_map_version:%d\n", psm.Program_stream_map_version))
|
||||
file.WriteString(fmt.Sprintf("program_stream_info_length:%d\n", psm.Program_stream_info_length))
|
||||
file.WriteString(fmt.Sprintf("elementary_stream_map_length:%d\n", psm.Elementary_stream_map_length))
|
||||
for i, es := range psm.Stream_map {
|
||||
file.WriteString(fmt.Sprintf("----ES stream %d\n", i))
|
||||
if es.Stream_type == uint8(PS_STREAM_AAC) {
|
||||
file.WriteString(" stream_type:AAC\n")
|
||||
} else if es.Stream_type == uint8(PS_STREAM_G711A) {
|
||||
file.WriteString(" stream_type:G711A\n")
|
||||
} else if es.Stream_type == uint8(PS_STREAM_G711U) {
|
||||
file.WriteString(" stream_type:G711U\n")
|
||||
} else if es.Stream_type == uint8(PS_STREAM_H264) {
|
||||
file.WriteString(" stream_type:H264\n")
|
||||
} else if es.Stream_type == uint8(PS_STREAM_H265) {
|
||||
file.WriteString(" stream_type:H265\n")
|
||||
}
|
||||
file.WriteString(fmt.Sprintf(" elementary_stream_id:%d\n", es.Elementary_stream_id))
|
||||
file.WriteString(fmt.Sprintf(" elementary_stream_info_length:%d\n", es.Elementary_stream_info_length))
|
||||
}
|
||||
}
|
||||
|
||||
func (psm *Program_stream_map) Encode(bsw *codec.BitStreamWriter) {
|
||||
bsw.PutBytes([]byte{0x00, 0x00, 0x01, 0xBC})
|
||||
loc := bsw.ByteOffset()
|
||||
bsw.PutUint16(psm.Program_stream_map_length, 16)
|
||||
bsw.Markdot()
|
||||
bsw.PutUint8(psm.Current_next_indicator, 1)
|
||||
bsw.PutUint8(3, 2)
|
||||
bsw.PutUint8(psm.Program_stream_map_version, 5)
|
||||
bsw.PutUint8(0x7F, 7)
|
||||
bsw.PutUint8(1, 1)
|
||||
bsw.PutUint16(0, 16)
|
||||
psm.Elementary_stream_map_length = uint16(len(psm.Stream_map) * 4)
|
||||
bsw.PutUint16(psm.Elementary_stream_map_length, 16)
|
||||
for _, streaminfo := range psm.Stream_map {
|
||||
bsw.PutUint8(streaminfo.Stream_type, 8)
|
||||
bsw.PutUint8(streaminfo.Elementary_stream_id, 8)
|
||||
bsw.PutUint16(0, 16)
|
||||
}
|
||||
length := bsw.DistanceFromMarkDot()/8 + 4
|
||||
bsw.SetUint16(uint16(length), loc)
|
||||
crc := codec.CalcCrc32(0xffffffff, bsw.Bits()[bsw.ByteOffset()-int(length-4)-4:bsw.ByteOffset()])
|
||||
tmpcrc := make([]byte, 4)
|
||||
binary.LittleEndian.PutUint32(tmpcrc, crc)
|
||||
bsw.PutBytes(tmpcrc)
|
||||
bsw.PutBytes([]byte{0x00, 0x00, 0x01, 0xBC})
|
||||
loc := bsw.ByteOffset()
|
||||
bsw.PutUint16(psm.Program_stream_map_length, 16)
|
||||
bsw.Markdot()
|
||||
bsw.PutUint8(psm.Current_next_indicator, 1)
|
||||
bsw.PutUint8(3, 2)
|
||||
bsw.PutUint8(psm.Program_stream_map_version, 5)
|
||||
bsw.PutUint8(0x7F, 7)
|
||||
bsw.PutUint8(1, 1)
|
||||
bsw.PutUint16(0, 16)
|
||||
psm.Elementary_stream_map_length = uint16(len(psm.Stream_map) * 4)
|
||||
bsw.PutUint16(psm.Elementary_stream_map_length, 16)
|
||||
for _, streaminfo := range psm.Stream_map {
|
||||
bsw.PutUint8(streaminfo.Stream_type, 8)
|
||||
bsw.PutUint8(streaminfo.Elementary_stream_id, 8)
|
||||
bsw.PutUint16(0, 16)
|
||||
}
|
||||
length := bsw.DistanceFromMarkDot()/8 + 4
|
||||
bsw.SetUint16(uint16(length), loc)
|
||||
crc := codec.CalcCrc32(0xffffffff, bsw.Bits()[bsw.ByteOffset()-int(length-4)-4:bsw.ByteOffset()])
|
||||
tmpcrc := make([]byte, 4)
|
||||
binary.LittleEndian.PutUint32(tmpcrc, crc)
|
||||
bsw.PutBytes(tmpcrc)
|
||||
}
|
||||
|
||||
func (psm *Program_stream_map) Decode(bs *codec.BitStream) error {
|
||||
if bs.RemainBytes() < 16 {
|
||||
return errNeedMore
|
||||
}
|
||||
if bs.Uint32(24) != 0x000001 {
|
||||
panic("program stream map must startwith 0x000001")
|
||||
}
|
||||
psm.Map_stream_id = bs.Uint8(8)
|
||||
if psm.Map_stream_id != 0xBC {
|
||||
panic("map stream id must be 0xBC")
|
||||
}
|
||||
psm.Program_stream_map_length = bs.Uint16(16)
|
||||
if bs.RemainBytes() < int(psm.Program_stream_map_length) {
|
||||
bs.UnRead(6 * 8)
|
||||
return errNeedMore
|
||||
}
|
||||
psm.Current_next_indicator = bs.Uint8(1)
|
||||
bs.SkipBits(2)
|
||||
psm.Program_stream_map_version = bs.Uint8(5)
|
||||
bs.SkipBits(8)
|
||||
psm.Program_stream_info_length = bs.Uint16(16)
|
||||
if bs.RemainBytes() < int(psm.Program_stream_info_length)+2 {
|
||||
bs.UnRead(10 * 8)
|
||||
return errNeedMore
|
||||
}
|
||||
bs.SkipBits(int(psm.Program_stream_info_length) * 8)
|
||||
psm.Elementary_stream_map_length = bs.Uint16(16)
|
||||
if psm.Program_stream_map_length != 6+psm.Program_stream_info_length+psm.Elementary_stream_map_length+4 {
|
||||
return errParser
|
||||
}
|
||||
if bs.RemainBytes() < int(psm.Elementary_stream_map_length)+4 {
|
||||
bs.UnRead(12*8 + int(psm.Program_stream_info_length)*8)
|
||||
return errNeedMore
|
||||
}
|
||||
if bs.RemainBytes() < 16 {
|
||||
return errNeedMore
|
||||
}
|
||||
if bs.Uint32(24) != 0x000001 {
|
||||
panic("program stream map must startwith 0x000001")
|
||||
}
|
||||
psm.Map_stream_id = bs.Uint8(8)
|
||||
if psm.Map_stream_id != 0xBC {
|
||||
panic("map stream id must be 0xBC")
|
||||
}
|
||||
psm.Program_stream_map_length = bs.Uint16(16)
|
||||
if bs.RemainBytes() < int(psm.Program_stream_map_length) {
|
||||
bs.UnRead(6 * 8)
|
||||
return errNeedMore
|
||||
}
|
||||
psm.Current_next_indicator = bs.Uint8(1)
|
||||
bs.SkipBits(2)
|
||||
psm.Program_stream_map_version = bs.Uint8(5)
|
||||
bs.SkipBits(8)
|
||||
psm.Program_stream_info_length = bs.Uint16(16)
|
||||
if bs.RemainBytes() < int(psm.Program_stream_info_length)+2 {
|
||||
bs.UnRead(10 * 8)
|
||||
return errNeedMore
|
||||
}
|
||||
bs.SkipBits(int(psm.Program_stream_info_length) * 8)
|
||||
psm.Elementary_stream_map_length = bs.Uint16(16)
|
||||
if psm.Program_stream_map_length != 6+psm.Program_stream_info_length+psm.Elementary_stream_map_length+4 {
|
||||
return errParser
|
||||
}
|
||||
if bs.RemainBytes() < int(psm.Elementary_stream_map_length)+4 {
|
||||
bs.UnRead(12*8 + int(psm.Program_stream_info_length)*8)
|
||||
return errNeedMore
|
||||
}
|
||||
|
||||
i := 0
|
||||
psm.Stream_map = psm.Stream_map[:0]
|
||||
for i < int(psm.Elementary_stream_map_length) {
|
||||
elem := new(Elementary_stream_elem)
|
||||
elem.Stream_type = bs.Uint8(8)
|
||||
elem.Elementary_stream_id = bs.Uint8(8)
|
||||
elem.Elementary_stream_info_length = bs.Uint16(16)
|
||||
//TODO Parser descriptor
|
||||
if bs.RemainBytes() < int(elem.Elementary_stream_info_length) {
|
||||
return errParser
|
||||
}
|
||||
bs.SkipBits(int(elem.Elementary_stream_info_length) * 8)
|
||||
i += int(4 + elem.Elementary_stream_info_length)
|
||||
psm.Stream_map = append(psm.Stream_map, elem)
|
||||
}
|
||||
i := 0
|
||||
psm.Stream_map = psm.Stream_map[:0]
|
||||
for i < int(psm.Elementary_stream_map_length) {
|
||||
elem := new(Elementary_stream_elem)
|
||||
elem.Stream_type = bs.Uint8(8)
|
||||
elem.Elementary_stream_id = bs.Uint8(8)
|
||||
elem.Elementary_stream_info_length = bs.Uint16(16)
|
||||
//TODO Parser descriptor
|
||||
if bs.RemainBytes() < int(elem.Elementary_stream_info_length) {
|
||||
return errParser
|
||||
}
|
||||
bs.SkipBits(int(elem.Elementary_stream_info_length) * 8)
|
||||
i += int(4 + elem.Elementary_stream_info_length)
|
||||
psm.Stream_map = append(psm.Stream_map, elem)
|
||||
}
|
||||
|
||||
if i != int(psm.Elementary_stream_map_length) {
|
||||
return errParser
|
||||
}
|
||||
if i != int(psm.Elementary_stream_map_length) {
|
||||
return errParser
|
||||
}
|
||||
|
||||
bs.SkipBits(32)
|
||||
return nil
|
||||
bs.SkipBits(32)
|
||||
return nil
|
||||
}
|
||||
|
||||
type Program_stream_directory struct {
|
||||
PES_packet_length uint16
|
||||
PES_packet_length uint16
|
||||
}
|
||||
|
||||
func (psd *Program_stream_directory) Decode(bs *codec.BitStream) error {
|
||||
if bs.RemainBytes() < 6 {
|
||||
return errNeedMore
|
||||
}
|
||||
if bs.Uint32(32) != 0x000001FF {
|
||||
panic("program stream directory 000001FF")
|
||||
}
|
||||
psd.PES_packet_length = bs.Uint16(16)
|
||||
if bs.RemainBytes() < int(psd.PES_packet_length) {
|
||||
bs.UnRead(6 * 8)
|
||||
return errNeedMore
|
||||
}
|
||||
//TODO Program Stream directory
|
||||
bs.SkipBits(int(psd.PES_packet_length) * 8)
|
||||
return nil
|
||||
if bs.RemainBytes() < 6 {
|
||||
return errNeedMore
|
||||
}
|
||||
if bs.Uint32(32) != 0x000001FF {
|
||||
panic("program stream directory 000001FF")
|
||||
}
|
||||
psd.PES_packet_length = bs.Uint16(16)
|
||||
if bs.RemainBytes() < int(psd.PES_packet_length) {
|
||||
bs.UnRead(6 * 8)
|
||||
return errNeedMore
|
||||
}
|
||||
//TODO Program Stream directory
|
||||
bs.SkipBits(int(psd.PES_packet_length) * 8)
|
||||
return nil
|
||||
}
|
||||
|
||||
type CommonPesPacket struct {
|
||||
Stream_id uint8
|
||||
PES_packet_length uint16
|
||||
Stream_id uint8
|
||||
PES_packet_length uint16
|
||||
}
|
||||
|
||||
func (compes *CommonPesPacket) Decode(bs *codec.BitStream) error {
|
||||
if bs.RemainBytes() < 6 {
|
||||
return errNeedMore
|
||||
}
|
||||
bs.SkipBits(24)
|
||||
compes.Stream_id = bs.Uint8(8)
|
||||
compes.PES_packet_length = bs.Uint16(16)
|
||||
if bs.RemainBytes() < int(compes.PES_packet_length) {
|
||||
bs.UnRead(6 * 8)
|
||||
return errNeedMore
|
||||
}
|
||||
bs.SkipBits(int(compes.PES_packet_length) * 8)
|
||||
return nil
|
||||
if bs.RemainBytes() < 6 {
|
||||
return errNeedMore
|
||||
}
|
||||
bs.SkipBits(24)
|
||||
compes.Stream_id = bs.Uint8(8)
|
||||
compes.PES_packet_length = bs.Uint16(16)
|
||||
if bs.RemainBytes() < int(compes.PES_packet_length) {
|
||||
bs.UnRead(6 * 8)
|
||||
return errNeedMore
|
||||
}
|
||||
bs.SkipBits(int(compes.PES_packet_length) * 8)
|
||||
return nil
|
||||
}
|
||||
|
||||
type PSPacket struct {
|
||||
Header *PSPackHeader
|
||||
System *System_header
|
||||
Psm *Program_stream_map
|
||||
Psd *Program_stream_directory
|
||||
CommPes *CommonPesPacket
|
||||
Pes *PesPacket
|
||||
Header *PSPackHeader
|
||||
System *System_header
|
||||
Psm *Program_stream_map
|
||||
Psd *Program_stream_directory
|
||||
CommPes *CommonPesPacket
|
||||
Pes *PesPacket
|
||||
}
|
||||
|
|
356
trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/mpeg2/ts-demuxer.go
generated
vendored
356
trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/mpeg2/ts-demuxer.go
generated
vendored
|
@ -1,218 +1,218 @@
|
|||
package mpeg2
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"errors"
|
||||
"io"
|
||||
|
||||
"github.com/yapingcat/gomedia/codec"
|
||||
"github.com/yapingcat/gomedia/codec"
|
||||
)
|
||||
|
||||
type pakcet_t struct {
|
||||
payload []byte
|
||||
pts uint64
|
||||
dts uint64
|
||||
payload []byte
|
||||
pts uint64
|
||||
dts uint64
|
||||
}
|
||||
|
||||
func newPacket_t(size uint32) *pakcet_t {
|
||||
return &pakcet_t{
|
||||
payload: make([]byte, 0, size),
|
||||
pts: 0,
|
||||
dts: 0,
|
||||
}
|
||||
return &pakcet_t{
|
||||
payload: make([]byte, 0, size),
|
||||
pts: 0,
|
||||
dts: 0,
|
||||
}
|
||||
}
|
||||
|
||||
type tsstream struct {
|
||||
cid TS_STREAM_TYPE
|
||||
pes_sid PES_STREMA_ID
|
||||
pes_pkg *PesPacket
|
||||
pkg *pakcet_t
|
||||
cid TS_STREAM_TYPE
|
||||
pes_sid PES_STREMA_ID
|
||||
pes_pkg *PesPacket
|
||||
pkg *pakcet_t
|
||||
}
|
||||
|
||||
type tsprogram struct {
|
||||
pn uint16
|
||||
streams map[uint16]*tsstream
|
||||
pn uint16
|
||||
streams map[uint16]*tsstream
|
||||
}
|
||||
|
||||
type TSDemuxer struct {
|
||||
programs map[uint16]*tsprogram
|
||||
OnFrame func(cid TS_STREAM_TYPE, frame []byte, pts uint64, dts uint64)
|
||||
OnTSPacket func(pkg *TSPacket)
|
||||
programs map[uint16]*tsprogram
|
||||
OnFrame func(cid TS_STREAM_TYPE, frame []byte, pts uint64, dts uint64)
|
||||
OnTSPacket func(pkg *TSPacket)
|
||||
}
|
||||
|
||||
func NewTSDemuxer() *TSDemuxer {
|
||||
return &TSDemuxer{
|
||||
programs: make(map[uint16]*tsprogram),
|
||||
OnFrame: nil,
|
||||
OnTSPacket: nil,
|
||||
}
|
||||
return &TSDemuxer{
|
||||
programs: make(map[uint16]*tsprogram),
|
||||
OnFrame: nil,
|
||||
OnTSPacket: nil,
|
||||
}
|
||||
}
|
||||
|
||||
func (demuxer *TSDemuxer) Input(r io.Reader) error {
|
||||
buf := make([]byte, TS_PAKCET_SIZE)
|
||||
_, err := io.ReadFull(r, buf)
|
||||
if err != nil {
|
||||
return errNeedMore
|
||||
}
|
||||
for {
|
||||
bs := codec.NewBitStream(buf)
|
||||
var pkg TSPacket
|
||||
if err := pkg.DecodeHeader(bs); err != nil {
|
||||
return err
|
||||
}
|
||||
if pkg.PID == uint16(TS_PID_PAT) {
|
||||
if pkg.Payload_unit_start_indicator == 1 {
|
||||
bs.SkipBits(8)
|
||||
}
|
||||
pat := NewPat()
|
||||
if err := pat.Decode(bs); err != nil {
|
||||
return err
|
||||
}
|
||||
pkg.Payload = pat
|
||||
if pat.Table_id != uint8(TS_TID_PAS) {
|
||||
return errors.New("pat table id is wrong")
|
||||
}
|
||||
for _, pmt := range pat.Pmts {
|
||||
if pmt.Program_number != 0x0000 {
|
||||
if _, found := demuxer.programs[pmt.PID]; !found {
|
||||
demuxer.programs[pmt.PID] = &tsprogram{pn: 0, streams: make(map[uint16]*tsstream)}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for p, s := range demuxer.programs {
|
||||
if p == pkg.PID { // pmt table
|
||||
if pkg.Payload_unit_start_indicator == 1 {
|
||||
bs.SkipBits(8) //pointer filed
|
||||
}
|
||||
pmt := NewPmt()
|
||||
if err := pmt.Decode(bs); err != nil {
|
||||
return err
|
||||
}
|
||||
pkg.Payload = pmt
|
||||
s.pn = pmt.Program_number
|
||||
for _, ps := range pmt.Streams {
|
||||
if _, found := s.streams[ps.Elementary_PID]; !found {
|
||||
s.streams[ps.Elementary_PID] = &tsstream{
|
||||
cid: TS_STREAM_TYPE(ps.StreamType),
|
||||
pes_sid: findPESIDByStreamType(TS_STREAM_TYPE(ps.StreamType)),
|
||||
pes_pkg: NewPesPacket(),
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for sid, stream := range s.streams {
|
||||
if sid != pkg.PID {
|
||||
continue
|
||||
}
|
||||
if pkg.Payload_unit_start_indicator == 1 {
|
||||
err := stream.pes_pkg.Decode(bs)
|
||||
// ignore error if it was a short payload read, next ts packet should append missing data
|
||||
if err != nil && !(errors.Is(err, errNeedMore) && stream.pes_pkg.Pes_payload != nil) {
|
||||
return err
|
||||
}
|
||||
pkg.Payload = stream.pes_pkg
|
||||
} else {
|
||||
stream.pes_pkg.Pes_payload = bs.RemainData()
|
||||
pkg.Payload = bs.RemainData()
|
||||
}
|
||||
stype := findPESIDByStreamType(stream.cid)
|
||||
if stype == PES_STREAM_AUDIO {
|
||||
demuxer.doAudioPesPacket(stream, pkg.Payload_unit_start_indicator)
|
||||
} else if stype == PES_STREAM_VIDEO {
|
||||
demuxer.doVideoPesPacket(stream, pkg.Payload_unit_start_indicator)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if demuxer.OnTSPacket != nil {
|
||||
demuxer.OnTSPacket(&pkg)
|
||||
}
|
||||
_, err := io.ReadFull(r, buf)
|
||||
if err != nil {
|
||||
if errors.Is(err, io.EOF) {
|
||||
break
|
||||
} else {
|
||||
return errNeedMore
|
||||
}
|
||||
}
|
||||
}
|
||||
demuxer.flush()
|
||||
return nil
|
||||
buf := make([]byte, TS_PAKCET_SIZE)
|
||||
_, err := io.ReadFull(r, buf)
|
||||
if err != nil {
|
||||
return errNeedMore
|
||||
}
|
||||
for {
|
||||
bs := codec.NewBitStream(buf)
|
||||
var pkg TSPacket
|
||||
if err := pkg.DecodeHeader(bs); err != nil {
|
||||
return err
|
||||
}
|
||||
if pkg.PID == uint16(TS_PID_PAT) {
|
||||
if pkg.Payload_unit_start_indicator == 1 {
|
||||
bs.SkipBits(8)
|
||||
}
|
||||
pat := NewPat()
|
||||
if err := pat.Decode(bs); err != nil {
|
||||
return err
|
||||
}
|
||||
pkg.Payload = pat
|
||||
if pat.Table_id != uint8(TS_TID_PAS) {
|
||||
return errors.New("pat table id is wrong")
|
||||
}
|
||||
for _, pmt := range pat.Pmts {
|
||||
if pmt.Program_number != 0x0000 {
|
||||
if _, found := demuxer.programs[pmt.PID]; !found {
|
||||
demuxer.programs[pmt.PID] = &tsprogram{pn: 0, streams: make(map[uint16]*tsstream)}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for p, s := range demuxer.programs {
|
||||
if p == pkg.PID { // pmt table
|
||||
if pkg.Payload_unit_start_indicator == 1 {
|
||||
bs.SkipBits(8) //pointer filed
|
||||
}
|
||||
pmt := NewPmt()
|
||||
if err := pmt.Decode(bs); err != nil {
|
||||
return err
|
||||
}
|
||||
pkg.Payload = pmt
|
||||
s.pn = pmt.Program_number
|
||||
for _, ps := range pmt.Streams {
|
||||
if _, found := s.streams[ps.Elementary_PID]; !found {
|
||||
s.streams[ps.Elementary_PID] = &tsstream{
|
||||
cid: TS_STREAM_TYPE(ps.StreamType),
|
||||
pes_sid: findPESIDByStreamType(TS_STREAM_TYPE(ps.StreamType)),
|
||||
pes_pkg: NewPesPacket(),
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for sid, stream := range s.streams {
|
||||
if sid != pkg.PID {
|
||||
continue
|
||||
}
|
||||
if pkg.Payload_unit_start_indicator == 1 {
|
||||
err := stream.pes_pkg.Decode(bs)
|
||||
// ignore error if it was a short payload read, next ts packet should append missing data
|
||||
if err != nil && !(errors.Is(err, errNeedMore) && stream.pes_pkg.Pes_payload != nil) {
|
||||
return err
|
||||
}
|
||||
pkg.Payload = stream.pes_pkg
|
||||
} else {
|
||||
stream.pes_pkg.Pes_payload = bs.RemainData()
|
||||
pkg.Payload = bs.RemainData()
|
||||
}
|
||||
stype := findPESIDByStreamType(stream.cid)
|
||||
if stype == PES_STREAM_AUDIO {
|
||||
demuxer.doAudioPesPacket(stream, pkg.Payload_unit_start_indicator)
|
||||
} else if stype == PES_STREAM_VIDEO {
|
||||
demuxer.doVideoPesPacket(stream, pkg.Payload_unit_start_indicator)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if demuxer.OnTSPacket != nil {
|
||||
demuxer.OnTSPacket(&pkg)
|
||||
}
|
||||
_, err := io.ReadFull(r, buf)
|
||||
if err != nil {
|
||||
if errors.Is(err, io.EOF) {
|
||||
break
|
||||
} else {
|
||||
return errNeedMore
|
||||
}
|
||||
}
|
||||
}
|
||||
demuxer.flush()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (demuxer *TSDemuxer) flush() {
|
||||
for _, pm := range demuxer.programs {
|
||||
for _, stream := range pm.streams {
|
||||
if stream.pkg == nil || len(stream.pkg.payload) == 0 {
|
||||
continue
|
||||
}
|
||||
if demuxer.OnFrame != nil {
|
||||
demuxer.OnFrame(stream.cid, stream.pkg.payload, stream.pkg.pts/90, stream.pkg.dts/90)
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, pm := range demuxer.programs {
|
||||
for _, stream := range pm.streams {
|
||||
if stream.pkg == nil || len(stream.pkg.payload) == 0 {
|
||||
continue
|
||||
}
|
||||
if demuxer.OnFrame != nil {
|
||||
demuxer.OnFrame(stream.cid, stream.pkg.payload, stream.pkg.pts/90, stream.pkg.dts/90)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (demuxer *TSDemuxer) doVideoPesPacket(stream *tsstream, start uint8) {
|
||||
if stream.cid != TS_STREAM_H264 && stream.cid != TS_STREAM_H265 {
|
||||
return
|
||||
}
|
||||
if stream.pkg == nil {
|
||||
stream.pkg = newPacket_t(1024)
|
||||
stream.pkg.pts = stream.pes_pkg.Pts
|
||||
stream.pkg.dts = stream.pes_pkg.Dts
|
||||
}
|
||||
stream.pkg.payload = append(stream.pkg.payload, stream.pes_pkg.Pes_payload...)
|
||||
demuxer.splitH26XFrame(stream)
|
||||
stream.pkg.pts = stream.pes_pkg.Pts
|
||||
stream.pkg.dts = stream.pes_pkg.Dts
|
||||
if stream.cid != TS_STREAM_H264 && stream.cid != TS_STREAM_H265 {
|
||||
return
|
||||
}
|
||||
if stream.pkg == nil {
|
||||
stream.pkg = newPacket_t(1024)
|
||||
stream.pkg.pts = stream.pes_pkg.Pts
|
||||
stream.pkg.dts = stream.pes_pkg.Dts
|
||||
}
|
||||
stream.pkg.payload = append(stream.pkg.payload, stream.pes_pkg.Pes_payload...)
|
||||
demuxer.splitH26XFrame(stream)
|
||||
stream.pkg.pts = stream.pes_pkg.Pts
|
||||
stream.pkg.dts = stream.pes_pkg.Dts
|
||||
}
|
||||
|
||||
func (demuxer *TSDemuxer) doAudioPesPacket(stream *tsstream, start uint8) {
|
||||
if stream.cid != TS_STREAM_AAC {
|
||||
return
|
||||
}
|
||||
if stream.cid != TS_STREAM_AAC {
|
||||
return
|
||||
}
|
||||
|
||||
if stream.pkg == nil {
|
||||
stream.pkg = newPacket_t(1024)
|
||||
stream.pkg.pts = stream.pes_pkg.Pts
|
||||
stream.pkg.dts = stream.pes_pkg.Dts
|
||||
}
|
||||
if stream.pkg == nil {
|
||||
stream.pkg = newPacket_t(1024)
|
||||
stream.pkg.pts = stream.pes_pkg.Pts
|
||||
stream.pkg.dts = stream.pes_pkg.Dts
|
||||
}
|
||||
|
||||
if len(stream.pkg.payload) > 0 && (start == 1 || stream.pes_pkg.Pts != stream.pkg.pts) {
|
||||
if demuxer.OnFrame != nil {
|
||||
demuxer.OnFrame(stream.cid, stream.pkg.payload, stream.pkg.pts/90, stream.pkg.dts/90)
|
||||
}
|
||||
stream.pkg.payload = stream.pkg.payload[:0]
|
||||
}
|
||||
stream.pkg.payload = append(stream.pkg.payload, stream.pes_pkg.Pes_payload...)
|
||||
stream.pkg.pts = stream.pes_pkg.Pts
|
||||
stream.pkg.dts = stream.pes_pkg.Dts
|
||||
if len(stream.pkg.payload) > 0 && (start == 1 || stream.pes_pkg.Pts != stream.pkg.pts) {
|
||||
if demuxer.OnFrame != nil {
|
||||
demuxer.OnFrame(stream.cid, stream.pkg.payload, stream.pkg.pts/90, stream.pkg.dts/90)
|
||||
}
|
||||
stream.pkg.payload = stream.pkg.payload[:0]
|
||||
}
|
||||
stream.pkg.payload = append(stream.pkg.payload, stream.pes_pkg.Pes_payload...)
|
||||
stream.pkg.pts = stream.pes_pkg.Pts
|
||||
stream.pkg.dts = stream.pes_pkg.Dts
|
||||
}
|
||||
|
||||
func (demuxer *TSDemuxer) splitH26XFrame(stream *tsstream) {
|
||||
data := stream.pkg.payload
|
||||
start, _ := codec.FindStartCode(data, 0)
|
||||
datalen := len(data)
|
||||
for start < datalen {
|
||||
end, _ := codec.FindStartCode(data, start+3)
|
||||
if end < 0 {
|
||||
break
|
||||
}
|
||||
if (stream.cid == TS_STREAM_H264 && codec.H264NaluTypeWithoutStartCode(data[start:end]) == codec.H264_NAL_AUD) ||
|
||||
(stream.cid == TS_STREAM_H265 && codec.H265NaluTypeWithoutStartCode(data[start:end]) == codec.H265_NAL_AUD) {
|
||||
start = end
|
||||
continue
|
||||
}
|
||||
if demuxer.OnFrame != nil {
|
||||
demuxer.OnFrame(stream.cid, data[start:end], stream.pkg.pts/90, stream.pkg.dts/90)
|
||||
}
|
||||
start = end
|
||||
}
|
||||
if start == 0 {
|
||||
return
|
||||
}
|
||||
copy(stream.pkg.payload, data[start:datalen])
|
||||
stream.pkg.payload = stream.pkg.payload[0 : datalen-start]
|
||||
data := stream.pkg.payload
|
||||
start, _ := codec.FindStartCode(data, 0)
|
||||
datalen := len(data)
|
||||
for start < datalen {
|
||||
end, _ := codec.FindStartCode(data, start+3)
|
||||
if end < 0 {
|
||||
break
|
||||
}
|
||||
if (stream.cid == TS_STREAM_H264 && codec.H264NaluTypeWithoutStartCode(data[start:end]) == codec.H264_NAL_AUD) ||
|
||||
(stream.cid == TS_STREAM_H265 && codec.H265NaluTypeWithoutStartCode(data[start:end]) == codec.H265_NAL_AUD) {
|
||||
start = end
|
||||
continue
|
||||
}
|
||||
if demuxer.OnFrame != nil {
|
||||
demuxer.OnFrame(stream.cid, data[start:end], stream.pkg.pts/90, stream.pkg.dts/90)
|
||||
}
|
||||
start = end
|
||||
}
|
||||
if start == 0 {
|
||||
return
|
||||
}
|
||||
copy(stream.pkg.payload, data[start:datalen])
|
||||
stream.pkg.payload = stream.pkg.payload[0 : datalen-start]
|
||||
}
|
||||
|
|
548
trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/mpeg2/ts-muxer.go
generated
vendored
548
trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/mpeg2/ts-muxer.go
generated
vendored
|
@ -1,93 +1,93 @@
|
|||
package mpeg2
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"errors"
|
||||
|
||||
"github.com/yapingcat/gomedia/codec"
|
||||
"github.com/yapingcat/gomedia/codec"
|
||||
)
|
||||
|
||||
type pes_stream struct {
|
||||
pid uint16
|
||||
cc uint8
|
||||
streamtype TS_STREAM_TYPE
|
||||
pid uint16
|
||||
cc uint8
|
||||
streamtype TS_STREAM_TYPE
|
||||
}
|
||||
|
||||
func NewPESStream(pid uint16, cid TS_STREAM_TYPE) *pes_stream {
|
||||
return &pes_stream{
|
||||
pid: pid,
|
||||
cc: 0,
|
||||
streamtype: cid,
|
||||
}
|
||||
return &pes_stream{
|
||||
pid: pid,
|
||||
cc: 0,
|
||||
streamtype: cid,
|
||||
}
|
||||
}
|
||||
|
||||
type table_pmt struct {
|
||||
pid uint16
|
||||
cc uint8
|
||||
pcr_pid uint16
|
||||
version_number uint8
|
||||
pm uint16
|
||||
streams []*pes_stream
|
||||
pid uint16
|
||||
cc uint8
|
||||
pcr_pid uint16
|
||||
version_number uint8
|
||||
pm uint16
|
||||
streams []*pes_stream
|
||||
}
|
||||
|
||||
func NewTablePmt() *table_pmt {
|
||||
return &table_pmt{
|
||||
pid: 0,
|
||||
cc: 0,
|
||||
pcr_pid: 0,
|
||||
version_number: 0,
|
||||
pm: 0,
|
||||
streams: make([]*pes_stream, 0, 2),
|
||||
}
|
||||
return &table_pmt{
|
||||
pid: 0,
|
||||
cc: 0,
|
||||
pcr_pid: 0,
|
||||
version_number: 0,
|
||||
pm: 0,
|
||||
streams: make([]*pes_stream, 0, 2),
|
||||
}
|
||||
}
|
||||
|
||||
type table_pat struct {
|
||||
cc uint8
|
||||
version_number uint8
|
||||
pmts []*table_pmt
|
||||
cc uint8
|
||||
version_number uint8
|
||||
pmts []*table_pmt
|
||||
}
|
||||
|
||||
func NewTablePat() *table_pat {
|
||||
return &table_pat{
|
||||
cc: 0,
|
||||
version_number: 0,
|
||||
pmts: make([]*table_pmt, 0, 8),
|
||||
}
|
||||
return &table_pat{
|
||||
cc: 0,
|
||||
version_number: 0,
|
||||
pmts: make([]*table_pmt, 0, 8),
|
||||
}
|
||||
}
|
||||
|
||||
type TSMuxer struct {
|
||||
pat *table_pat
|
||||
stream_pid uint16
|
||||
pmt_pid uint16
|
||||
pat_period uint64
|
||||
OnPacket func(pkg []byte)
|
||||
pat *table_pat
|
||||
stream_pid uint16
|
||||
pmt_pid uint16
|
||||
pat_period uint64
|
||||
OnPacket func(pkg []byte)
|
||||
}
|
||||
|
||||
func NewTSMuxer() *TSMuxer {
|
||||
return &TSMuxer{
|
||||
pat: NewTablePat(),
|
||||
stream_pid: 0x100,
|
||||
pmt_pid: 0x200,
|
||||
pat_period: 0,
|
||||
OnPacket: nil,
|
||||
}
|
||||
return &TSMuxer{
|
||||
pat: NewTablePat(),
|
||||
stream_pid: 0x100,
|
||||
pmt_pid: 0x200,
|
||||
pat_period: 0,
|
||||
OnPacket: nil,
|
||||
}
|
||||
}
|
||||
|
||||
func (mux *TSMuxer) AddStream(cid TS_STREAM_TYPE) uint16 {
|
||||
if mux.pat == nil {
|
||||
mux.pat = NewTablePat()
|
||||
}
|
||||
if len(mux.pat.pmts) == 0 {
|
||||
tmppmt := NewTablePmt()
|
||||
tmppmt.pid = mux.pmt_pid
|
||||
tmppmt.pm = 1
|
||||
mux.pmt_pid++
|
||||
mux.pat.pmts = append(mux.pat.pmts, tmppmt)
|
||||
}
|
||||
sid := mux.stream_pid
|
||||
tmpstream := NewPESStream(sid, cid)
|
||||
mux.stream_pid++
|
||||
mux.pat.pmts[0].streams = append(mux.pat.pmts[0].streams, tmpstream)
|
||||
return sid
|
||||
if mux.pat == nil {
|
||||
mux.pat = NewTablePat()
|
||||
}
|
||||
if len(mux.pat.pmts) == 0 {
|
||||
tmppmt := NewTablePmt()
|
||||
tmppmt.pid = mux.pmt_pid
|
||||
tmppmt.pm = 1
|
||||
mux.pmt_pid++
|
||||
mux.pat.pmts = append(mux.pat.pmts, tmppmt)
|
||||
}
|
||||
sid := mux.stream_pid
|
||||
tmpstream := NewPESStream(sid, cid)
|
||||
mux.stream_pid++
|
||||
mux.pat.pmts[0].streams = append(mux.pat.pmts[0].streams, tmpstream)
|
||||
return sid
|
||||
}
|
||||
|
||||
/// Muxer audio/video stream data
|
||||
|
@ -95,239 +95,239 @@ func (mux *TSMuxer) AddStream(cid TS_STREAM_TYPE) uint16 {
|
|||
/// pts: audio/video stream timestamp in ms
|
||||
/// dts: audio/video stream timestamp in ms
|
||||
func (mux *TSMuxer) Write(pid uint16, data []byte, pts uint64, dts uint64) error {
|
||||
var whichpmt *table_pmt = nil
|
||||
var whichstream *pes_stream = nil
|
||||
for _, pmt := range mux.pat.pmts {
|
||||
for _, stream := range pmt.streams {
|
||||
if stream.pid == pid {
|
||||
whichpmt = pmt
|
||||
whichstream = stream
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if whichpmt == nil || whichstream == nil {
|
||||
return errors.New("not Found pid stream")
|
||||
}
|
||||
if whichpmt.pcr_pid == 0 || (findPESIDByStreamType(whichstream.streamtype) == PES_STREAM_VIDEO && whichpmt.pcr_pid != pid) {
|
||||
whichpmt.pcr_pid = pid
|
||||
}
|
||||
var whichpmt *table_pmt = nil
|
||||
var whichstream *pes_stream = nil
|
||||
for _, pmt := range mux.pat.pmts {
|
||||
for _, stream := range pmt.streams {
|
||||
if stream.pid == pid {
|
||||
whichpmt = pmt
|
||||
whichstream = stream
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if whichpmt == nil || whichstream == nil {
|
||||
return errors.New("not Found pid stream")
|
||||
}
|
||||
if whichpmt.pcr_pid == 0 || (findPESIDByStreamType(whichstream.streamtype) == PES_STREAM_VIDEO && whichpmt.pcr_pid != pid) {
|
||||
whichpmt.pcr_pid = pid
|
||||
}
|
||||
|
||||
var withaud bool = false
|
||||
var withaud bool = false
|
||||
|
||||
if whichstream.streamtype == TS_STREAM_H264 || whichstream.streamtype == TS_STREAM_H265 {
|
||||
codec.SplitFrame(data, func(nalu []byte) bool {
|
||||
if whichstream.streamtype == TS_STREAM_H264 {
|
||||
nalu_type := codec.H264NaluTypeWithoutStartCode(nalu)
|
||||
if nalu_type == codec.H264_NAL_AUD {
|
||||
withaud = true
|
||||
return false
|
||||
} else if codec.IsH264VCLNaluType(nalu_type) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
} else {
|
||||
nalu_type := codec.H265NaluTypeWithoutStartCode(nalu)
|
||||
if nalu_type == codec.H265_NAL_AUD {
|
||||
withaud = true
|
||||
return false
|
||||
} else if codec.IsH265VCLNaluType(nalu_type) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
})
|
||||
}
|
||||
if whichstream.streamtype == TS_STREAM_H264 || whichstream.streamtype == TS_STREAM_H265 {
|
||||
codec.SplitFrame(data, func(nalu []byte) bool {
|
||||
if whichstream.streamtype == TS_STREAM_H264 {
|
||||
nalu_type := codec.H264NaluTypeWithoutStartCode(nalu)
|
||||
if nalu_type == codec.H264_NAL_AUD {
|
||||
withaud = true
|
||||
return false
|
||||
} else if codec.IsH264VCLNaluType(nalu_type) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
} else {
|
||||
nalu_type := codec.H265NaluTypeWithoutStartCode(nalu)
|
||||
if nalu_type == codec.H265_NAL_AUD {
|
||||
withaud = true
|
||||
return false
|
||||
} else if codec.IsH265VCLNaluType(nalu_type) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
if mux.pat_period == 0 || mux.pat_period+400 < dts {
|
||||
mux.pat_period = dts
|
||||
if mux.pat_period == 0 {
|
||||
mux.pat_period = 1 //avoid write pat twice
|
||||
}
|
||||
tmppat := NewPat()
|
||||
tmppat.Version_number = mux.pat.version_number
|
||||
for _, pmt := range mux.pat.pmts {
|
||||
tmppm := PmtPair{
|
||||
Program_number: pmt.pm,
|
||||
PID: pmt.pid,
|
||||
}
|
||||
tmppat.Pmts = append(tmppat.Pmts, tmppm)
|
||||
}
|
||||
mux.writePat(tmppat)
|
||||
if mux.pat_period == 0 || mux.pat_period+400 < dts {
|
||||
mux.pat_period = dts
|
||||
if mux.pat_period == 0 {
|
||||
mux.pat_period = 1 //avoid write pat twice
|
||||
}
|
||||
tmppat := NewPat()
|
||||
tmppat.Version_number = mux.pat.version_number
|
||||
for _, pmt := range mux.pat.pmts {
|
||||
tmppm := PmtPair{
|
||||
Program_number: pmt.pm,
|
||||
PID: pmt.pid,
|
||||
}
|
||||
tmppat.Pmts = append(tmppat.Pmts, tmppm)
|
||||
}
|
||||
mux.writePat(tmppat)
|
||||
|
||||
for _, pmt := range mux.pat.pmts {
|
||||
tmppmt := NewPmt()
|
||||
tmppmt.Program_number = pmt.pm
|
||||
tmppmt.Version_number = pmt.version_number
|
||||
tmppmt.PCR_PID = pmt.pcr_pid
|
||||
for _, stream := range pmt.streams {
|
||||
var sp StreamPair
|
||||
sp.StreamType = uint8(stream.streamtype)
|
||||
sp.Elementary_PID = stream.pid
|
||||
sp.ES_Info_Length = 0
|
||||
tmppmt.Streams = append(tmppmt.Streams, sp)
|
||||
}
|
||||
mux.writePmt(tmppmt, pmt)
|
||||
}
|
||||
}
|
||||
for _, pmt := range mux.pat.pmts {
|
||||
tmppmt := NewPmt()
|
||||
tmppmt.Program_number = pmt.pm
|
||||
tmppmt.Version_number = pmt.version_number
|
||||
tmppmt.PCR_PID = pmt.pcr_pid
|
||||
for _, stream := range pmt.streams {
|
||||
var sp StreamPair
|
||||
sp.StreamType = uint8(stream.streamtype)
|
||||
sp.Elementary_PID = stream.pid
|
||||
sp.ES_Info_Length = 0
|
||||
tmppmt.Streams = append(tmppmt.Streams, sp)
|
||||
}
|
||||
mux.writePmt(tmppmt, pmt)
|
||||
}
|
||||
}
|
||||
|
||||
flag := false
|
||||
switch whichstream.streamtype {
|
||||
case TS_STREAM_H264:
|
||||
flag = codec.IsH264IDRFrame(data)
|
||||
case TS_STREAM_H265:
|
||||
flag = codec.IsH265IDRFrame(data)
|
||||
}
|
||||
flag := false
|
||||
switch whichstream.streamtype {
|
||||
case TS_STREAM_H264:
|
||||
flag = codec.IsH264IDRFrame(data)
|
||||
case TS_STREAM_H265:
|
||||
flag = codec.IsH265IDRFrame(data)
|
||||
}
|
||||
|
||||
mux.writePES(whichstream, whichpmt, data, pts*90, dts*90, flag, withaud)
|
||||
return nil
|
||||
mux.writePES(whichstream, whichpmt, data, pts*90, dts*90, flag, withaud)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (mux *TSMuxer) writePat(pat *Pat) {
|
||||
var tshdr TSPacket
|
||||
tshdr.Payload_unit_start_indicator = 1
|
||||
tshdr.PID = 0
|
||||
tshdr.Adaptation_field_control = 0x01
|
||||
tshdr.Continuity_counter = mux.pat.cc
|
||||
mux.pat.cc++
|
||||
mux.pat.cc = (mux.pat.cc + 1) % 16
|
||||
bsw := codec.NewBitStreamWriter(TS_PAKCET_SIZE)
|
||||
tshdr.EncodeHeader(bsw)
|
||||
bsw.PutByte(0x00) //pointer
|
||||
pat.Encode(bsw)
|
||||
bsw.FillRemainData(0xff)
|
||||
if mux.OnPacket != nil {
|
||||
mux.OnPacket(bsw.Bits())
|
||||
}
|
||||
var tshdr TSPacket
|
||||
tshdr.Payload_unit_start_indicator = 1
|
||||
tshdr.PID = 0
|
||||
tshdr.Adaptation_field_control = 0x01
|
||||
tshdr.Continuity_counter = mux.pat.cc
|
||||
mux.pat.cc++
|
||||
mux.pat.cc = (mux.pat.cc + 1) % 16
|
||||
bsw := codec.NewBitStreamWriter(TS_PAKCET_SIZE)
|
||||
tshdr.EncodeHeader(bsw)
|
||||
bsw.PutByte(0x00) //pointer
|
||||
pat.Encode(bsw)
|
||||
bsw.FillRemainData(0xff)
|
||||
if mux.OnPacket != nil {
|
||||
mux.OnPacket(bsw.Bits())
|
||||
}
|
||||
}
|
||||
|
||||
func (mux *TSMuxer) writePmt(pmt *Pmt, t_pmt *table_pmt) {
|
||||
var tshdr TSPacket
|
||||
tshdr.Payload_unit_start_indicator = 1
|
||||
tshdr.PID = t_pmt.pid
|
||||
tshdr.Adaptation_field_control = 0x01
|
||||
tshdr.Continuity_counter = t_pmt.cc
|
||||
t_pmt.cc = (t_pmt.cc + 1) % 16
|
||||
bsw := codec.NewBitStreamWriter(TS_PAKCET_SIZE)
|
||||
tshdr.EncodeHeader(bsw)
|
||||
bsw.PutByte(0x00) //pointer
|
||||
pmt.Encode(bsw)
|
||||
bsw.FillRemainData(0xff)
|
||||
if mux.OnPacket != nil {
|
||||
mux.OnPacket(bsw.Bits())
|
||||
}
|
||||
var tshdr TSPacket
|
||||
tshdr.Payload_unit_start_indicator = 1
|
||||
tshdr.PID = t_pmt.pid
|
||||
tshdr.Adaptation_field_control = 0x01
|
||||
tshdr.Continuity_counter = t_pmt.cc
|
||||
t_pmt.cc = (t_pmt.cc + 1) % 16
|
||||
bsw := codec.NewBitStreamWriter(TS_PAKCET_SIZE)
|
||||
tshdr.EncodeHeader(bsw)
|
||||
bsw.PutByte(0x00) //pointer
|
||||
pmt.Encode(bsw)
|
||||
bsw.FillRemainData(0xff)
|
||||
if mux.OnPacket != nil {
|
||||
mux.OnPacket(bsw.Bits())
|
||||
}
|
||||
}
|
||||
|
||||
func (mux *TSMuxer) writePES(pes *pes_stream, pmt *table_pmt, data []byte, pts uint64, dts uint64, idr_flag bool, withaud bool) {
|
||||
var firstPesPacket bool = true
|
||||
bsw := codec.NewBitStreamWriter(TS_PAKCET_SIZE)
|
||||
for {
|
||||
bsw.Reset()
|
||||
var tshdr TSPacket
|
||||
if firstPesPacket {
|
||||
tshdr.Payload_unit_start_indicator = 1
|
||||
}
|
||||
tshdr.PID = pes.pid
|
||||
tshdr.Adaptation_field_control = 0x01
|
||||
tshdr.Continuity_counter = pes.cc
|
||||
headlen := 4
|
||||
pes.cc = (pes.cc + 1) % 16
|
||||
var adaptation *Adaptation_field = nil
|
||||
if firstPesPacket && idr_flag {
|
||||
adaptation = new(Adaptation_field)
|
||||
tshdr.Adaptation_field_control = tshdr.Adaptation_field_control | 0x20
|
||||
adaptation.Random_access_indicator = 1
|
||||
headlen += 2
|
||||
}
|
||||
var firstPesPacket bool = true
|
||||
bsw := codec.NewBitStreamWriter(TS_PAKCET_SIZE)
|
||||
for {
|
||||
bsw.Reset()
|
||||
var tshdr TSPacket
|
||||
if firstPesPacket {
|
||||
tshdr.Payload_unit_start_indicator = 1
|
||||
}
|
||||
tshdr.PID = pes.pid
|
||||
tshdr.Adaptation_field_control = 0x01
|
||||
tshdr.Continuity_counter = pes.cc
|
||||
headlen := 4
|
||||
pes.cc = (pes.cc + 1) % 16
|
||||
var adaptation *Adaptation_field = nil
|
||||
if firstPesPacket && idr_flag {
|
||||
adaptation = new(Adaptation_field)
|
||||
tshdr.Adaptation_field_control = tshdr.Adaptation_field_control | 0x20
|
||||
adaptation.Random_access_indicator = 1
|
||||
headlen += 2
|
||||
}
|
||||
|
||||
if firstPesPacket && pes.pid == pmt.pcr_pid {
|
||||
if adaptation == nil {
|
||||
adaptation = new(Adaptation_field)
|
||||
headlen += 2
|
||||
}
|
||||
tshdr.Adaptation_field_control = tshdr.Adaptation_field_control | 0x20
|
||||
adaptation.PCR_flag = 1
|
||||
var pcr_base uint64 = 0
|
||||
var pcr_ext uint16 = 0
|
||||
if dts == 0 {
|
||||
pcr_base = pts * 300 / 300
|
||||
pcr_ext = uint16(pts * 300 % 300)
|
||||
} else {
|
||||
pcr_base = dts * 300 / 300
|
||||
pcr_ext = uint16(dts * 300 % 300)
|
||||
}
|
||||
adaptation.Program_clock_reference_base = pcr_base
|
||||
adaptation.Program_clock_reference_extension = pcr_ext
|
||||
headlen += 6
|
||||
}
|
||||
if firstPesPacket && pes.pid == pmt.pcr_pid {
|
||||
if adaptation == nil {
|
||||
adaptation = new(Adaptation_field)
|
||||
headlen += 2
|
||||
}
|
||||
tshdr.Adaptation_field_control = tshdr.Adaptation_field_control | 0x20
|
||||
adaptation.PCR_flag = 1
|
||||
var pcr_base uint64 = 0
|
||||
var pcr_ext uint16 = 0
|
||||
if dts == 0 {
|
||||
pcr_base = pts * 300 / 300
|
||||
pcr_ext = uint16(pts * 300 % 300)
|
||||
} else {
|
||||
pcr_base = dts * 300 / 300
|
||||
pcr_ext = uint16(dts * 300 % 300)
|
||||
}
|
||||
adaptation.Program_clock_reference_base = pcr_base
|
||||
adaptation.Program_clock_reference_extension = pcr_ext
|
||||
headlen += 6
|
||||
}
|
||||
|
||||
var payload []byte
|
||||
var pespkg *PesPacket = nil
|
||||
if firstPesPacket {
|
||||
oldheadlen := headlen
|
||||
headlen += 19
|
||||
if !withaud && pes.streamtype == TS_STREAM_H264 {
|
||||
headlen += 6
|
||||
payload = append(payload, H264_AUD_NALU...)
|
||||
} else if !withaud && pes.streamtype == TS_STREAM_H265 {
|
||||
payload = append(payload, H265_AUD_NALU...)
|
||||
headlen += 7
|
||||
}
|
||||
pespkg = NewPesPacket()
|
||||
pespkg.PTS_DTS_flags = 0x03
|
||||
pespkg.PES_header_data_length = 10
|
||||
pespkg.Pts = pts
|
||||
pespkg.Dts = dts
|
||||
pespkg.Stream_id = uint8(findPESIDByStreamType(pes.streamtype))
|
||||
if idr_flag {
|
||||
pespkg.Data_alignment_indicator = 1
|
||||
}
|
||||
if headlen-oldheadlen-6+len(data) > 0xFFFF {
|
||||
pespkg.PES_packet_length = 0
|
||||
} else {
|
||||
pespkg.PES_packet_length = uint16(len(data) + headlen - oldheadlen - 6)
|
||||
}
|
||||
var payload []byte
|
||||
var pespkg *PesPacket = nil
|
||||
if firstPesPacket {
|
||||
oldheadlen := headlen
|
||||
headlen += 19
|
||||
if !withaud && pes.streamtype == TS_STREAM_H264 {
|
||||
headlen += 6
|
||||
payload = append(payload, H264_AUD_NALU...)
|
||||
} else if !withaud && pes.streamtype == TS_STREAM_H265 {
|
||||
payload = append(payload, H265_AUD_NALU...)
|
||||
headlen += 7
|
||||
}
|
||||
pespkg = NewPesPacket()
|
||||
pespkg.PTS_DTS_flags = 0x03
|
||||
pespkg.PES_header_data_length = 10
|
||||
pespkg.Pts = pts
|
||||
pespkg.Dts = dts
|
||||
pespkg.Stream_id = uint8(findPESIDByStreamType(pes.streamtype))
|
||||
if idr_flag {
|
||||
pespkg.Data_alignment_indicator = 1
|
||||
}
|
||||
if headlen-oldheadlen-6+len(data) > 0xFFFF {
|
||||
pespkg.PES_packet_length = 0
|
||||
} else {
|
||||
pespkg.PES_packet_length = uint16(len(data) + headlen - oldheadlen - 6)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if len(data)+headlen < TS_PAKCET_SIZE {
|
||||
if adaptation == nil {
|
||||
adaptation = new(Adaptation_field)
|
||||
headlen += 1
|
||||
if TS_PAKCET_SIZE-len(data)-headlen >= 1 {
|
||||
headlen += 1
|
||||
} else {
|
||||
adaptation.SingleStuffingByte = true
|
||||
}
|
||||
}
|
||||
adaptation.Stuffing_byte = uint8(TS_PAKCET_SIZE - len(data) - headlen)
|
||||
payload = append(payload, data...)
|
||||
data = data[:0]
|
||||
} else {
|
||||
payload = append(payload, data[0:TS_PAKCET_SIZE-headlen]...)
|
||||
data = data[TS_PAKCET_SIZE-headlen:]
|
||||
}
|
||||
if len(data)+headlen < TS_PAKCET_SIZE {
|
||||
if adaptation == nil {
|
||||
adaptation = new(Adaptation_field)
|
||||
headlen += 1
|
||||
if TS_PAKCET_SIZE-len(data)-headlen >= 1 {
|
||||
headlen += 1
|
||||
} else {
|
||||
adaptation.SingleStuffingByte = true
|
||||
}
|
||||
}
|
||||
adaptation.Stuffing_byte = uint8(TS_PAKCET_SIZE - len(data) - headlen)
|
||||
payload = append(payload, data...)
|
||||
data = data[:0]
|
||||
} else {
|
||||
payload = append(payload, data[0:TS_PAKCET_SIZE-headlen]...)
|
||||
data = data[TS_PAKCET_SIZE-headlen:]
|
||||
}
|
||||
|
||||
if adaptation != nil {
|
||||
tshdr.Field = adaptation
|
||||
tshdr.Adaptation_field_control |= 0x02
|
||||
}
|
||||
tshdr.EncodeHeader(bsw)
|
||||
if pespkg != nil {
|
||||
pespkg.Pes_payload = payload
|
||||
pespkg.Encode(bsw)
|
||||
} else {
|
||||
bsw.PutBytes(payload)
|
||||
}
|
||||
firstPesPacket = false
|
||||
if mux.OnPacket != nil {
|
||||
if len(bsw.Bits()) != TS_PAKCET_SIZE {
|
||||
panic("packet ts packet failed")
|
||||
}
|
||||
mux.OnPacket(bsw.Bits())
|
||||
}
|
||||
if len(data) == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if adaptation != nil {
|
||||
tshdr.Field = adaptation
|
||||
tshdr.Adaptation_field_control |= 0x02
|
||||
}
|
||||
tshdr.EncodeHeader(bsw)
|
||||
if pespkg != nil {
|
||||
pespkg.Pes_payload = payload
|
||||
pespkg.Encode(bsw)
|
||||
} else {
|
||||
bsw.PutBytes(payload)
|
||||
}
|
||||
firstPesPacket = false
|
||||
if mux.OnPacket != nil {
|
||||
if len(bsw.Bits()) != TS_PAKCET_SIZE {
|
||||
panic("packet ts packet failed")
|
||||
}
|
||||
mux.OnPacket(bsw.Bits())
|
||||
}
|
||||
if len(data) == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
864
trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/mpeg2/ts-proto.go
generated
vendored
864
trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/mpeg2/ts-proto.go
generated
vendored
|
@ -1,50 +1,50 @@
|
|||
package mpeg2
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/yapingcat/gomedia/codec"
|
||||
"github.com/yapingcat/gomedia/codec"
|
||||
)
|
||||
|
||||
//PID
|
||||
type TS_PID int
|
||||
|
||||
const (
|
||||
TS_PID_PAT TS_PID = 0x0000
|
||||
TS_PID_CAT
|
||||
TS_PID_TSDT
|
||||
TS_PID_IPMP
|
||||
TS_PID_Nil = 0x1FFFF
|
||||
TS_PID_PAT TS_PID = 0x0000
|
||||
TS_PID_CAT
|
||||
TS_PID_TSDT
|
||||
TS_PID_IPMP
|
||||
TS_PID_Nil = 0x1FFFF
|
||||
)
|
||||
|
||||
//Table id
|
||||
type PAT_TID int
|
||||
|
||||
const (
|
||||
TS_TID_PAS PAT_TID = 0x00 // program_association_section
|
||||
TS_TID_CAS = 0x01 // conditional_access_section(CA_section)
|
||||
TS_TID_PMS = 0x02 // TS_program_map_section
|
||||
TS_TID_SDS = 0x03 //TS_description_section
|
||||
TS_TID_FORBIDDEN PAT_TID = 0xFF
|
||||
TS_TID_PAS PAT_TID = 0x00 // program_association_section
|
||||
TS_TID_CAS = 0x01 // conditional_access_section(CA_section)
|
||||
TS_TID_PMS = 0x02 // TS_program_map_section
|
||||
TS_TID_SDS = 0x03 //TS_description_section
|
||||
TS_TID_FORBIDDEN PAT_TID = 0xFF
|
||||
)
|
||||
|
||||
type TS_STREAM_TYPE int
|
||||
|
||||
const (
|
||||
TS_STREAM_AAC TS_STREAM_TYPE = 0x0F
|
||||
TS_STREAM_H264 TS_STREAM_TYPE = 0x1B
|
||||
TS_STREAM_H265 TS_STREAM_TYPE = 0x24
|
||||
TS_STREAM_AAC TS_STREAM_TYPE = 0x0F
|
||||
TS_STREAM_H264 TS_STREAM_TYPE = 0x1B
|
||||
TS_STREAM_H265 TS_STREAM_TYPE = 0x24
|
||||
)
|
||||
|
||||
const (
|
||||
TS_PAKCET_SIZE = 188
|
||||
TS_PAKCET_SIZE = 188
|
||||
)
|
||||
|
||||
type Display interface {
|
||||
PrettyPrint(file *os.File)
|
||||
PrettyPrint(file *os.File)
|
||||
}
|
||||
|
||||
// transport_packet(){
|
||||
|
@ -67,63 +67,63 @@ type Display interface {
|
|||
// }
|
||||
|
||||
type TSPacket struct {
|
||||
Transport_error_indicator uint8
|
||||
Payload_unit_start_indicator uint8
|
||||
Transport_priority uint8
|
||||
PID uint16
|
||||
Transport_scrambling_control uint8
|
||||
Adaptation_field_control uint8
|
||||
Continuity_counter uint8
|
||||
Field *Adaptation_field
|
||||
Payload interface{}
|
||||
Transport_error_indicator uint8
|
||||
Payload_unit_start_indicator uint8
|
||||
Transport_priority uint8
|
||||
PID uint16
|
||||
Transport_scrambling_control uint8
|
||||
Adaptation_field_control uint8
|
||||
Continuity_counter uint8
|
||||
Field *Adaptation_field
|
||||
Payload interface{}
|
||||
}
|
||||
|
||||
func (pkg *TSPacket) PrettyPrint(file *os.File) {
|
||||
file.WriteString(fmt.Sprintf("Transport_error_indicator:%d\n", pkg.Transport_error_indicator))
|
||||
file.WriteString(fmt.Sprintf("Payload_unit_start_indicator:%d\n", pkg.Payload_unit_start_indicator))
|
||||
file.WriteString(fmt.Sprintf("Transport_priority:%d\n", pkg.Transport_priority))
|
||||
file.WriteString(fmt.Sprintf("PID:%d\n", pkg.PID))
|
||||
file.WriteString(fmt.Sprintf("Transport_scrambling_control:%d\n", pkg.Transport_scrambling_control))
|
||||
file.WriteString(fmt.Sprintf("Adaptation_field_control:%d\n", pkg.Adaptation_field_control))
|
||||
file.WriteString(fmt.Sprintf("Continuity_counter:%d\n", pkg.Continuity_counter))
|
||||
file.WriteString(fmt.Sprintf("Transport_error_indicator:%d\n", pkg.Transport_error_indicator))
|
||||
file.WriteString(fmt.Sprintf("Payload_unit_start_indicator:%d\n", pkg.Payload_unit_start_indicator))
|
||||
file.WriteString(fmt.Sprintf("Transport_priority:%d\n", pkg.Transport_priority))
|
||||
file.WriteString(fmt.Sprintf("PID:%d\n", pkg.PID))
|
||||
file.WriteString(fmt.Sprintf("Transport_scrambling_control:%d\n", pkg.Transport_scrambling_control))
|
||||
file.WriteString(fmt.Sprintf("Adaptation_field_control:%d\n", pkg.Adaptation_field_control))
|
||||
file.WriteString(fmt.Sprintf("Continuity_counter:%d\n", pkg.Continuity_counter))
|
||||
}
|
||||
|
||||
func (pkg *TSPacket) EncodeHeader(bsw *codec.BitStreamWriter) {
|
||||
bsw.PutByte(0x47)
|
||||
bsw.PutUint8(pkg.Transport_error_indicator, 1)
|
||||
bsw.PutUint8(pkg.Payload_unit_start_indicator, 1)
|
||||
bsw.PutUint8(pkg.Transport_priority, 1)
|
||||
bsw.PutUint16(pkg.PID, 13)
|
||||
bsw.PutUint8(pkg.Transport_scrambling_control, 2)
|
||||
bsw.PutUint8(pkg.Adaptation_field_control, 2)
|
||||
bsw.PutUint8(pkg.Continuity_counter, 4)
|
||||
if pkg.Field != nil && (pkg.Adaptation_field_control&0x02) != 0 {
|
||||
pkg.Field.Encode(bsw)
|
||||
}
|
||||
bsw.PutByte(0x47)
|
||||
bsw.PutUint8(pkg.Transport_error_indicator, 1)
|
||||
bsw.PutUint8(pkg.Payload_unit_start_indicator, 1)
|
||||
bsw.PutUint8(pkg.Transport_priority, 1)
|
||||
bsw.PutUint16(pkg.PID, 13)
|
||||
bsw.PutUint8(pkg.Transport_scrambling_control, 2)
|
||||
bsw.PutUint8(pkg.Adaptation_field_control, 2)
|
||||
bsw.PutUint8(pkg.Continuity_counter, 4)
|
||||
if pkg.Field != nil && (pkg.Adaptation_field_control&0x02) != 0 {
|
||||
pkg.Field.Encode(bsw)
|
||||
}
|
||||
}
|
||||
|
||||
func (pkg *TSPacket) DecodeHeader(bs *codec.BitStream) error {
|
||||
sync_byte := bs.Uint8(8)
|
||||
if sync_byte != 0x47 {
|
||||
return errors.New("ts packet must start with 0x47")
|
||||
}
|
||||
pkg.Transport_error_indicator = bs.GetBit()
|
||||
pkg.Payload_unit_start_indicator = bs.GetBit()
|
||||
pkg.Transport_priority = bs.GetBit()
|
||||
pkg.PID = bs.Uint16(13)
|
||||
pkg.Transport_scrambling_control = bs.Uint8(2)
|
||||
pkg.Adaptation_field_control = bs.Uint8(2)
|
||||
pkg.Continuity_counter = bs.Uint8(4)
|
||||
if pkg.Adaptation_field_control == 0x02 || pkg.Adaptation_field_control == 0x03 {
|
||||
if pkg.Field == nil {
|
||||
pkg.Field = new(Adaptation_field)
|
||||
}
|
||||
err := pkg.Field.Decode(bs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
sync_byte := bs.Uint8(8)
|
||||
if sync_byte != 0x47 {
|
||||
return errors.New("ts packet must start with 0x47")
|
||||
}
|
||||
pkg.Transport_error_indicator = bs.GetBit()
|
||||
pkg.Payload_unit_start_indicator = bs.GetBit()
|
||||
pkg.Transport_priority = bs.GetBit()
|
||||
pkg.PID = bs.Uint16(13)
|
||||
pkg.Transport_scrambling_control = bs.Uint8(2)
|
||||
pkg.Adaptation_field_control = bs.Uint8(2)
|
||||
pkg.Continuity_counter = bs.Uint8(4)
|
||||
if pkg.Adaptation_field_control == 0x02 || pkg.Adaptation_field_control == 0x03 {
|
||||
if pkg.Field == nil {
|
||||
pkg.Field = new(Adaptation_field)
|
||||
}
|
||||
err := pkg.Field.Decode(bs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -189,414 +189,414 @@ func (pkg *TSPacket) DecodeHeader(bs *codec.BitStream) error {
|
|||
// }
|
||||
|
||||
type Adaptation_field struct {
|
||||
SingleStuffingByte bool // The value 0 is for inserting a single stuffing byte in a Transport Stream packet
|
||||
Adaptation_field_length uint8 //8 uimsbf
|
||||
Discontinuity_indicator uint8 //1 bslbf
|
||||
Random_access_indicator uint8 //1 bslbf
|
||||
Elementary_stream_priority_indicator uint8 //1 bslbf
|
||||
PCR_flag uint8 //1 bslbf
|
||||
OPCR_flag uint8 //1 bslbf
|
||||
Splicing_point_flag uint8 //1 bslbf
|
||||
Transport_private_data_flag uint8 //1 bslbf
|
||||
Adaptation_field_extension_flag uint8 //1 bslbf
|
||||
Program_clock_reference_base uint64 //33 uimsbf
|
||||
Program_clock_reference_extension uint16 //9 uimsbf
|
||||
Original_program_clock_reference_base uint64 //33 uimsbf
|
||||
Original_program_clock_reference_extension uint16 //9 uimsbf
|
||||
Splice_countdown uint8 //8 uimsbf
|
||||
Transport_private_data_length uint8 //8 uimsbf
|
||||
Adaptation_field_extension_length uint8 //8 uimsbf
|
||||
Ltw_flag uint8 //1 bslbf
|
||||
Piecewise_rate_flag uint8 //1 bslbf
|
||||
Seamless_splice_flag uint8 //1 bslbf
|
||||
Ltw_valid_flag uint8 //1 bslbf
|
||||
Ltw_offset uint16 //15 uimsbf
|
||||
Piecewise_rate uint32 //22 uimsbf
|
||||
Splice_type uint8 //4 uimsbf
|
||||
DTS_next_AU uint64
|
||||
Stuffing_byte uint8
|
||||
SingleStuffingByte bool // The value 0 is for inserting a single stuffing byte in a Transport Stream packet
|
||||
Adaptation_field_length uint8 //8 uimsbf
|
||||
Discontinuity_indicator uint8 //1 bslbf
|
||||
Random_access_indicator uint8 //1 bslbf
|
||||
Elementary_stream_priority_indicator uint8 //1 bslbf
|
||||
PCR_flag uint8 //1 bslbf
|
||||
OPCR_flag uint8 //1 bslbf
|
||||
Splicing_point_flag uint8 //1 bslbf
|
||||
Transport_private_data_flag uint8 //1 bslbf
|
||||
Adaptation_field_extension_flag uint8 //1 bslbf
|
||||
Program_clock_reference_base uint64 //33 uimsbf
|
||||
Program_clock_reference_extension uint16 //9 uimsbf
|
||||
Original_program_clock_reference_base uint64 //33 uimsbf
|
||||
Original_program_clock_reference_extension uint16 //9 uimsbf
|
||||
Splice_countdown uint8 //8 uimsbf
|
||||
Transport_private_data_length uint8 //8 uimsbf
|
||||
Adaptation_field_extension_length uint8 //8 uimsbf
|
||||
Ltw_flag uint8 //1 bslbf
|
||||
Piecewise_rate_flag uint8 //1 bslbf
|
||||
Seamless_splice_flag uint8 //1 bslbf
|
||||
Ltw_valid_flag uint8 //1 bslbf
|
||||
Ltw_offset uint16 //15 uimsbf
|
||||
Piecewise_rate uint32 //22 uimsbf
|
||||
Splice_type uint8 //4 uimsbf
|
||||
DTS_next_AU uint64
|
||||
Stuffing_byte uint8
|
||||
}
|
||||
|
||||
func (adaptation *Adaptation_field) PrettyPrint(file *os.File) {
|
||||
file.WriteString(fmt.Sprintf("Adaptation_field_length:%d\n", adaptation.Adaptation_field_length))
|
||||
file.WriteString(fmt.Sprintf("Discontinuity_indicator:%d\n", adaptation.Discontinuity_indicator))
|
||||
file.WriteString(fmt.Sprintf("Random_access_indicator:%d\n", adaptation.Random_access_indicator))
|
||||
file.WriteString(fmt.Sprintf("Elementary_stream_priority_indicator:%d\n", adaptation.Elementary_stream_priority_indicator))
|
||||
file.WriteString(fmt.Sprintf("PCR_flag:%d\n", adaptation.PCR_flag))
|
||||
file.WriteString(fmt.Sprintf("OPCR_flag:%d\n", adaptation.OPCR_flag))
|
||||
file.WriteString(fmt.Sprintf("Splicing_point_flag:%d\n", adaptation.Splicing_point_flag))
|
||||
file.WriteString(fmt.Sprintf("Transport_private_data_flag:%d\n", adaptation.Transport_private_data_flag))
|
||||
file.WriteString(fmt.Sprintf("Adaptation_field_extension_flag:%d\n", adaptation.Adaptation_field_extension_flag))
|
||||
if adaptation.PCR_flag == 1 {
|
||||
file.WriteString(fmt.Sprintf("Program_clock_reference_base:%d\n", adaptation.Program_clock_reference_base))
|
||||
file.WriteString(fmt.Sprintf("Program_clock_reference_extension:%d\n", adaptation.Program_clock_reference_extension))
|
||||
}
|
||||
if adaptation.OPCR_flag == 1 {
|
||||
file.WriteString(fmt.Sprintf("Original_program_clock_reference_base:%d\n", adaptation.Original_program_clock_reference_base))
|
||||
file.WriteString(fmt.Sprintf("Original_program_clock_reference_extension:%d\n", adaptation.Original_program_clock_reference_extension))
|
||||
}
|
||||
if adaptation.Splicing_point_flag == 1 {
|
||||
file.WriteString(fmt.Sprintf("Splice_countdown:%d\n", adaptation.Splice_countdown))
|
||||
}
|
||||
if adaptation.Transport_private_data_flag == 1 {
|
||||
file.WriteString(fmt.Sprintf("Transport_private_data_length:%d\n", adaptation.Transport_private_data_length))
|
||||
}
|
||||
if adaptation.Adaptation_field_extension_flag == 1 {
|
||||
file.WriteString(fmt.Sprintf("Adaptation_field_extension_length:%d\n", adaptation.Adaptation_field_extension_length))
|
||||
file.WriteString(fmt.Sprintf("Ltw_flag:%d\n", adaptation.Ltw_flag))
|
||||
file.WriteString(fmt.Sprintf("Piecewise_rate_flag:%d\n", adaptation.Piecewise_rate_flag))
|
||||
file.WriteString(fmt.Sprintf("Seamless_splice_flag:%d\n", adaptation.Seamless_splice_flag))
|
||||
if adaptation.Ltw_flag == 1 {
|
||||
file.WriteString(fmt.Sprintf("Ltw_valid_flag:%d\n", adaptation.Ltw_valid_flag))
|
||||
file.WriteString(fmt.Sprintf("Ltw_offset:%d\n", adaptation.Ltw_offset))
|
||||
}
|
||||
if adaptation.Piecewise_rate_flag == 1 {
|
||||
file.WriteString(fmt.Sprintf("Piecewise_rate:%d\n", adaptation.Piecewise_rate))
|
||||
}
|
||||
if adaptation.Seamless_splice_flag == 1 {
|
||||
file.WriteString(fmt.Sprintf("Splice_type:%d\n", adaptation.Splice_type))
|
||||
file.WriteString(fmt.Sprintf("DTS_next_AU:%d\n", adaptation.DTS_next_AU))
|
||||
}
|
||||
}
|
||||
file.WriteString(fmt.Sprintf("Adaptation_field_length:%d\n", adaptation.Adaptation_field_length))
|
||||
file.WriteString(fmt.Sprintf("Discontinuity_indicator:%d\n", adaptation.Discontinuity_indicator))
|
||||
file.WriteString(fmt.Sprintf("Random_access_indicator:%d\n", adaptation.Random_access_indicator))
|
||||
file.WriteString(fmt.Sprintf("Elementary_stream_priority_indicator:%d\n", adaptation.Elementary_stream_priority_indicator))
|
||||
file.WriteString(fmt.Sprintf("PCR_flag:%d\n", adaptation.PCR_flag))
|
||||
file.WriteString(fmt.Sprintf("OPCR_flag:%d\n", adaptation.OPCR_flag))
|
||||
file.WriteString(fmt.Sprintf("Splicing_point_flag:%d\n", adaptation.Splicing_point_flag))
|
||||
file.WriteString(fmt.Sprintf("Transport_private_data_flag:%d\n", adaptation.Transport_private_data_flag))
|
||||
file.WriteString(fmt.Sprintf("Adaptation_field_extension_flag:%d\n", adaptation.Adaptation_field_extension_flag))
|
||||
if adaptation.PCR_flag == 1 {
|
||||
file.WriteString(fmt.Sprintf("Program_clock_reference_base:%d\n", adaptation.Program_clock_reference_base))
|
||||
file.WriteString(fmt.Sprintf("Program_clock_reference_extension:%d\n", adaptation.Program_clock_reference_extension))
|
||||
}
|
||||
if adaptation.OPCR_flag == 1 {
|
||||
file.WriteString(fmt.Sprintf("Original_program_clock_reference_base:%d\n", adaptation.Original_program_clock_reference_base))
|
||||
file.WriteString(fmt.Sprintf("Original_program_clock_reference_extension:%d\n", adaptation.Original_program_clock_reference_extension))
|
||||
}
|
||||
if adaptation.Splicing_point_flag == 1 {
|
||||
file.WriteString(fmt.Sprintf("Splice_countdown:%d\n", adaptation.Splice_countdown))
|
||||
}
|
||||
if adaptation.Transport_private_data_flag == 1 {
|
||||
file.WriteString(fmt.Sprintf("Transport_private_data_length:%d\n", adaptation.Transport_private_data_length))
|
||||
}
|
||||
if adaptation.Adaptation_field_extension_flag == 1 {
|
||||
file.WriteString(fmt.Sprintf("Adaptation_field_extension_length:%d\n", adaptation.Adaptation_field_extension_length))
|
||||
file.WriteString(fmt.Sprintf("Ltw_flag:%d\n", adaptation.Ltw_flag))
|
||||
file.WriteString(fmt.Sprintf("Piecewise_rate_flag:%d\n", adaptation.Piecewise_rate_flag))
|
||||
file.WriteString(fmt.Sprintf("Seamless_splice_flag:%d\n", adaptation.Seamless_splice_flag))
|
||||
if adaptation.Ltw_flag == 1 {
|
||||
file.WriteString(fmt.Sprintf("Ltw_valid_flag:%d\n", adaptation.Ltw_valid_flag))
|
||||
file.WriteString(fmt.Sprintf("Ltw_offset:%d\n", adaptation.Ltw_offset))
|
||||
}
|
||||
if adaptation.Piecewise_rate_flag == 1 {
|
||||
file.WriteString(fmt.Sprintf("Piecewise_rate:%d\n", adaptation.Piecewise_rate))
|
||||
}
|
||||
if adaptation.Seamless_splice_flag == 1 {
|
||||
file.WriteString(fmt.Sprintf("Splice_type:%d\n", adaptation.Splice_type))
|
||||
file.WriteString(fmt.Sprintf("DTS_next_AU:%d\n", adaptation.DTS_next_AU))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (adaptation *Adaptation_field) Encode(bsw *codec.BitStreamWriter) {
|
||||
loc := bsw.ByteOffset()
|
||||
bsw.PutUint8(adaptation.Adaptation_field_length, 8)
|
||||
if adaptation.SingleStuffingByte {
|
||||
return
|
||||
}
|
||||
bsw.Markdot()
|
||||
bsw.PutUint8(adaptation.Discontinuity_indicator, 1)
|
||||
bsw.PutUint8(adaptation.Random_access_indicator, 1)
|
||||
bsw.PutUint8(adaptation.Elementary_stream_priority_indicator, 1)
|
||||
bsw.PutUint8(adaptation.PCR_flag, 1)
|
||||
bsw.PutUint8(adaptation.OPCR_flag, 1)
|
||||
bsw.PutUint8(adaptation.Splicing_point_flag, 1)
|
||||
bsw.PutUint8(0 /*adaptation.Transport_private_data_flag*/, 1)
|
||||
bsw.PutUint8(0 /*adaptation.Adaptation_field_extension_flag*/, 1)
|
||||
if adaptation.PCR_flag == 1 {
|
||||
bsw.PutUint64(adaptation.Program_clock_reference_base, 33)
|
||||
bsw.PutUint8(0, 6)
|
||||
bsw.PutUint16(adaptation.Program_clock_reference_extension, 9)
|
||||
}
|
||||
if adaptation.OPCR_flag == 1 {
|
||||
bsw.PutUint64(adaptation.Original_program_clock_reference_base, 33)
|
||||
bsw.PutUint8(0, 6)
|
||||
bsw.PutUint16(adaptation.Original_program_clock_reference_extension, 9)
|
||||
}
|
||||
if adaptation.Splicing_point_flag == 1 {
|
||||
bsw.PutUint8(adaptation.Splice_countdown, 8)
|
||||
}
|
||||
//TODO
|
||||
// if adaptation.Transport_private_data_flag == 0 {
|
||||
// }
|
||||
// if adaptation.Adaptation_field_extension_flag == 0 {
|
||||
// }
|
||||
adaptation.Adaptation_field_length = uint8(bsw.DistanceFromMarkDot() / 8)
|
||||
bsw.PutRepetValue(0xff, int(adaptation.Stuffing_byte))
|
||||
adaptation.Adaptation_field_length += adaptation.Stuffing_byte
|
||||
bsw.SetByte(adaptation.Adaptation_field_length, loc)
|
||||
loc := bsw.ByteOffset()
|
||||
bsw.PutUint8(adaptation.Adaptation_field_length, 8)
|
||||
if adaptation.SingleStuffingByte {
|
||||
return
|
||||
}
|
||||
bsw.Markdot()
|
||||
bsw.PutUint8(adaptation.Discontinuity_indicator, 1)
|
||||
bsw.PutUint8(adaptation.Random_access_indicator, 1)
|
||||
bsw.PutUint8(adaptation.Elementary_stream_priority_indicator, 1)
|
||||
bsw.PutUint8(adaptation.PCR_flag, 1)
|
||||
bsw.PutUint8(adaptation.OPCR_flag, 1)
|
||||
bsw.PutUint8(adaptation.Splicing_point_flag, 1)
|
||||
bsw.PutUint8(0 /*adaptation.Transport_private_data_flag*/, 1)
|
||||
bsw.PutUint8(0 /*adaptation.Adaptation_field_extension_flag*/, 1)
|
||||
if adaptation.PCR_flag == 1 {
|
||||
bsw.PutUint64(adaptation.Program_clock_reference_base, 33)
|
||||
bsw.PutUint8(0, 6)
|
||||
bsw.PutUint16(adaptation.Program_clock_reference_extension, 9)
|
||||
}
|
||||
if adaptation.OPCR_flag == 1 {
|
||||
bsw.PutUint64(adaptation.Original_program_clock_reference_base, 33)
|
||||
bsw.PutUint8(0, 6)
|
||||
bsw.PutUint16(adaptation.Original_program_clock_reference_extension, 9)
|
||||
}
|
||||
if adaptation.Splicing_point_flag == 1 {
|
||||
bsw.PutUint8(adaptation.Splice_countdown, 8)
|
||||
}
|
||||
//TODO
|
||||
// if adaptation.Transport_private_data_flag == 0 {
|
||||
// }
|
||||
// if adaptation.Adaptation_field_extension_flag == 0 {
|
||||
// }
|
||||
adaptation.Adaptation_field_length = uint8(bsw.DistanceFromMarkDot() / 8)
|
||||
bsw.PutRepetValue(0xff, int(adaptation.Stuffing_byte))
|
||||
adaptation.Adaptation_field_length += adaptation.Stuffing_byte
|
||||
bsw.SetByte(adaptation.Adaptation_field_length, loc)
|
||||
}
|
||||
|
||||
func (adaptation *Adaptation_field) Decode(bs *codec.BitStream) error {
|
||||
if bs.RemainBytes() < 1 {
|
||||
return errors.New("len of data < 1 byte")
|
||||
}
|
||||
adaptation.Adaptation_field_length = bs.Uint8(8)
|
||||
startoffset := bs.ByteOffset()
|
||||
//fmt.Printf("Adaptation_field_length=%d\n", adaptation.Adaptation_field_length)
|
||||
if bs.RemainBytes() < int(adaptation.Adaptation_field_length) {
|
||||
return errors.New("len of data < Adaptation_field_length")
|
||||
}
|
||||
if adaptation.Adaptation_field_length == 0 {
|
||||
return nil
|
||||
}
|
||||
adaptation.Discontinuity_indicator = bs.GetBit()
|
||||
adaptation.Random_access_indicator = bs.GetBit()
|
||||
adaptation.Elementary_stream_priority_indicator = bs.GetBit()
|
||||
adaptation.PCR_flag = bs.GetBit()
|
||||
adaptation.OPCR_flag = bs.GetBit()
|
||||
adaptation.Splicing_point_flag = bs.GetBit()
|
||||
adaptation.Transport_private_data_flag = bs.GetBit()
|
||||
adaptation.Adaptation_field_extension_flag = bs.GetBit()
|
||||
if adaptation.PCR_flag == 1 {
|
||||
adaptation.Program_clock_reference_base = bs.GetBits(33)
|
||||
bs.SkipBits(6)
|
||||
adaptation.Program_clock_reference_extension = uint16(bs.GetBits(9))
|
||||
}
|
||||
if adaptation.OPCR_flag == 1 {
|
||||
adaptation.Original_program_clock_reference_base = bs.GetBits(33)
|
||||
bs.SkipBits(6)
|
||||
adaptation.Original_program_clock_reference_extension = uint16(bs.GetBits(9))
|
||||
}
|
||||
if adaptation.Splicing_point_flag == 1 {
|
||||
adaptation.Splice_countdown = bs.Uint8(8)
|
||||
}
|
||||
if adaptation.Transport_private_data_flag == 1 {
|
||||
adaptation.Transport_private_data_length = bs.Uint8(8)
|
||||
bs.SkipBits(8 * int(adaptation.Transport_private_data_length))
|
||||
}
|
||||
if adaptation.Adaptation_field_extension_flag == 1 {
|
||||
adaptation.Adaptation_field_extension_length = bs.Uint8(8)
|
||||
bs.Markdot()
|
||||
adaptation.Ltw_flag = bs.GetBit()
|
||||
adaptation.Piecewise_rate_flag = bs.GetBit()
|
||||
adaptation.Seamless_splice_flag = bs.GetBit()
|
||||
bs.SkipBits(5)
|
||||
if adaptation.Ltw_flag == 1 {
|
||||
adaptation.Ltw_valid_flag = bs.GetBit()
|
||||
adaptation.Ltw_offset = uint16(bs.GetBits(15))
|
||||
}
|
||||
if adaptation.Piecewise_rate_flag == 1 {
|
||||
bs.SkipBits(2)
|
||||
adaptation.Piecewise_rate = uint32(bs.GetBits(22))
|
||||
}
|
||||
if adaptation.Seamless_splice_flag == 1 {
|
||||
adaptation.Splice_type = uint8(bs.GetBits(4))
|
||||
adaptation.DTS_next_AU = bs.GetBits(3)
|
||||
bs.SkipBits(1)
|
||||
adaptation.DTS_next_AU = adaptation.DTS_next_AU<<15 | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
adaptation.DTS_next_AU = adaptation.DTS_next_AU<<15 | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
}
|
||||
bitscount := bs.DistanceFromMarkDot()
|
||||
if bitscount%8 > 0 {
|
||||
panic("maybe parser ts file failed")
|
||||
}
|
||||
bs.SkipBits(int(adaptation.Adaptation_field_extension_length*8 - uint8(bitscount)))
|
||||
}
|
||||
endoffset := bs.ByteOffset()
|
||||
bs.SkipBits((int(adaptation.Adaptation_field_length) - (endoffset - startoffset)) * 8)
|
||||
return nil
|
||||
if bs.RemainBytes() < 1 {
|
||||
return errors.New("len of data < 1 byte")
|
||||
}
|
||||
adaptation.Adaptation_field_length = bs.Uint8(8)
|
||||
startoffset := bs.ByteOffset()
|
||||
//fmt.Printf("Adaptation_field_length=%d\n", adaptation.Adaptation_field_length)
|
||||
if bs.RemainBytes() < int(adaptation.Adaptation_field_length) {
|
||||
return errors.New("len of data < Adaptation_field_length")
|
||||
}
|
||||
if adaptation.Adaptation_field_length == 0 {
|
||||
return nil
|
||||
}
|
||||
adaptation.Discontinuity_indicator = bs.GetBit()
|
||||
adaptation.Random_access_indicator = bs.GetBit()
|
||||
adaptation.Elementary_stream_priority_indicator = bs.GetBit()
|
||||
adaptation.PCR_flag = bs.GetBit()
|
||||
adaptation.OPCR_flag = bs.GetBit()
|
||||
adaptation.Splicing_point_flag = bs.GetBit()
|
||||
adaptation.Transport_private_data_flag = bs.GetBit()
|
||||
adaptation.Adaptation_field_extension_flag = bs.GetBit()
|
||||
if adaptation.PCR_flag == 1 {
|
||||
adaptation.Program_clock_reference_base = bs.GetBits(33)
|
||||
bs.SkipBits(6)
|
||||
adaptation.Program_clock_reference_extension = uint16(bs.GetBits(9))
|
||||
}
|
||||
if adaptation.OPCR_flag == 1 {
|
||||
adaptation.Original_program_clock_reference_base = bs.GetBits(33)
|
||||
bs.SkipBits(6)
|
||||
adaptation.Original_program_clock_reference_extension = uint16(bs.GetBits(9))
|
||||
}
|
||||
if adaptation.Splicing_point_flag == 1 {
|
||||
adaptation.Splice_countdown = bs.Uint8(8)
|
||||
}
|
||||
if adaptation.Transport_private_data_flag == 1 {
|
||||
adaptation.Transport_private_data_length = bs.Uint8(8)
|
||||
bs.SkipBits(8 * int(adaptation.Transport_private_data_length))
|
||||
}
|
||||
if adaptation.Adaptation_field_extension_flag == 1 {
|
||||
adaptation.Adaptation_field_extension_length = bs.Uint8(8)
|
||||
bs.Markdot()
|
||||
adaptation.Ltw_flag = bs.GetBit()
|
||||
adaptation.Piecewise_rate_flag = bs.GetBit()
|
||||
adaptation.Seamless_splice_flag = bs.GetBit()
|
||||
bs.SkipBits(5)
|
||||
if adaptation.Ltw_flag == 1 {
|
||||
adaptation.Ltw_valid_flag = bs.GetBit()
|
||||
adaptation.Ltw_offset = uint16(bs.GetBits(15))
|
||||
}
|
||||
if adaptation.Piecewise_rate_flag == 1 {
|
||||
bs.SkipBits(2)
|
||||
adaptation.Piecewise_rate = uint32(bs.GetBits(22))
|
||||
}
|
||||
if adaptation.Seamless_splice_flag == 1 {
|
||||
adaptation.Splice_type = uint8(bs.GetBits(4))
|
||||
adaptation.DTS_next_AU = bs.GetBits(3)
|
||||
bs.SkipBits(1)
|
||||
adaptation.DTS_next_AU = adaptation.DTS_next_AU<<15 | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
adaptation.DTS_next_AU = adaptation.DTS_next_AU<<15 | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
}
|
||||
bitscount := bs.DistanceFromMarkDot()
|
||||
if bitscount%8 > 0 {
|
||||
panic("maybe parser ts file failed")
|
||||
}
|
||||
bs.SkipBits(int(adaptation.Adaptation_field_extension_length*8 - uint8(bitscount)))
|
||||
}
|
||||
endoffset := bs.ByteOffset()
|
||||
bs.SkipBits((int(adaptation.Adaptation_field_length) - (endoffset - startoffset)) * 8)
|
||||
return nil
|
||||
}
|
||||
|
||||
type PmtPair struct {
|
||||
Program_number uint16
|
||||
PID uint16
|
||||
Program_number uint16
|
||||
PID uint16
|
||||
}
|
||||
|
||||
type Pat struct {
|
||||
Table_id uint8 //8 uimsbf
|
||||
Section_syntax_indicator uint8 //1 bslbf
|
||||
Section_length uint16 //12 uimsbf
|
||||
Transport_stream_id uint16 //16 uimsbf
|
||||
Version_number uint8 //5 uimsbf
|
||||
Current_next_indicator uint8 //1 bslbf
|
||||
Section_number uint8 //8 uimsbf
|
||||
Last_section_number uint8 //8 uimsbf
|
||||
Pmts []PmtPair
|
||||
Table_id uint8 //8 uimsbf
|
||||
Section_syntax_indicator uint8 //1 bslbf
|
||||
Section_length uint16 //12 uimsbf
|
||||
Transport_stream_id uint16 //16 uimsbf
|
||||
Version_number uint8 //5 uimsbf
|
||||
Current_next_indicator uint8 //1 bslbf
|
||||
Section_number uint8 //8 uimsbf
|
||||
Last_section_number uint8 //8 uimsbf
|
||||
Pmts []PmtPair
|
||||
}
|
||||
|
||||
func NewPat() *Pat {
|
||||
return &Pat{
|
||||
Table_id: uint8(TS_TID_PAS),
|
||||
Pmts: make([]PmtPair, 0, 8),
|
||||
}
|
||||
return &Pat{
|
||||
Table_id: uint8(TS_TID_PAS),
|
||||
Pmts: make([]PmtPair, 0, 8),
|
||||
}
|
||||
}
|
||||
|
||||
func (pat *Pat) PrettyPrint(file *os.File) {
|
||||
file.WriteString(fmt.Sprintf("Table id:%d\n", pat.Table_id))
|
||||
file.WriteString(fmt.Sprintf("Section_syntax_indicator:%d\n", pat.Section_syntax_indicator))
|
||||
file.WriteString(fmt.Sprintf("Section_length:%d\n", pat.Section_length))
|
||||
file.WriteString(fmt.Sprintf("Transport_stream_id:%d\n", pat.Transport_stream_id))
|
||||
file.WriteString(fmt.Sprintf("Version_number:%d\n", pat.Version_number))
|
||||
file.WriteString(fmt.Sprintf("Current_next_indicator:%d\n", pat.Current_next_indicator))
|
||||
file.WriteString(fmt.Sprintf("Section_number:%d\n", pat.Section_number))
|
||||
file.WriteString(fmt.Sprintf("Last_section_number:%d\n", pat.Last_section_number))
|
||||
for i, pmt := range pat.Pmts {
|
||||
file.WriteString(fmt.Sprintf("----pmt %d\n", i))
|
||||
file.WriteString(fmt.Sprintf(" program_number:%d\n", pmt.Program_number))
|
||||
if pmt.Program_number == 0x0000 {
|
||||
file.WriteString(fmt.Sprintf(" network_PID:%d\n", pmt.PID))
|
||||
} else {
|
||||
file.WriteString(fmt.Sprintf(" program_map_PID:%d\n", pmt.PID))
|
||||
}
|
||||
}
|
||||
file.WriteString(fmt.Sprintf("Table id:%d\n", pat.Table_id))
|
||||
file.WriteString(fmt.Sprintf("Section_syntax_indicator:%d\n", pat.Section_syntax_indicator))
|
||||
file.WriteString(fmt.Sprintf("Section_length:%d\n", pat.Section_length))
|
||||
file.WriteString(fmt.Sprintf("Transport_stream_id:%d\n", pat.Transport_stream_id))
|
||||
file.WriteString(fmt.Sprintf("Version_number:%d\n", pat.Version_number))
|
||||
file.WriteString(fmt.Sprintf("Current_next_indicator:%d\n", pat.Current_next_indicator))
|
||||
file.WriteString(fmt.Sprintf("Section_number:%d\n", pat.Section_number))
|
||||
file.WriteString(fmt.Sprintf("Last_section_number:%d\n", pat.Last_section_number))
|
||||
for i, pmt := range pat.Pmts {
|
||||
file.WriteString(fmt.Sprintf("----pmt %d\n", i))
|
||||
file.WriteString(fmt.Sprintf(" program_number:%d\n", pmt.Program_number))
|
||||
if pmt.Program_number == 0x0000 {
|
||||
file.WriteString(fmt.Sprintf(" network_PID:%d\n", pmt.PID))
|
||||
} else {
|
||||
file.WriteString(fmt.Sprintf(" program_map_PID:%d\n", pmt.PID))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (pat *Pat) Encode(bsw *codec.BitStreamWriter) {
|
||||
bsw.PutUint8(0x00, 8)
|
||||
loc := bsw.ByteOffset()
|
||||
bsw.PutUint8(pat.Section_syntax_indicator, 1)
|
||||
bsw.PutUint8(0x00, 1)
|
||||
bsw.PutUint8(0x03, 2)
|
||||
bsw.PutUint16(0, 12)
|
||||
bsw.Markdot()
|
||||
bsw.PutUint16(pat.Transport_stream_id, 16)
|
||||
bsw.PutUint8(0x03, 2)
|
||||
bsw.PutUint8(pat.Version_number, 5)
|
||||
bsw.PutUint8(pat.Current_next_indicator, 1)
|
||||
bsw.PutUint8(pat.Section_number, 8)
|
||||
bsw.PutUint8(pat.Last_section_number, 8)
|
||||
for _, pms := range pat.Pmts {
|
||||
bsw.PutUint16(pms.Program_number, 16)
|
||||
bsw.PutUint8(0x07, 3)
|
||||
bsw.PutUint16(pms.PID, 13)
|
||||
}
|
||||
length := bsw.DistanceFromMarkDot()
|
||||
//|Section_syntax_indicator|'0'|reserved|Section_length|
|
||||
pat.Section_length = uint16(length)/8 + 4
|
||||
bsw.SetUint16(pat.Section_length&0x0FFF|(uint16(pat.Section_syntax_indicator)<<15)|0x3000, loc)
|
||||
crc := codec.CalcCrc32(0xffffffff, bsw.Bits()[bsw.ByteOffset()-int(pat.Section_length-4)-3:bsw.ByteOffset()])
|
||||
tmpcrc := make([]byte, 4)
|
||||
binary.LittleEndian.PutUint32(tmpcrc, crc)
|
||||
bsw.PutBytes(tmpcrc)
|
||||
bsw.PutUint8(0x00, 8)
|
||||
loc := bsw.ByteOffset()
|
||||
bsw.PutUint8(pat.Section_syntax_indicator, 1)
|
||||
bsw.PutUint8(0x00, 1)
|
||||
bsw.PutUint8(0x03, 2)
|
||||
bsw.PutUint16(0, 12)
|
||||
bsw.Markdot()
|
||||
bsw.PutUint16(pat.Transport_stream_id, 16)
|
||||
bsw.PutUint8(0x03, 2)
|
||||
bsw.PutUint8(pat.Version_number, 5)
|
||||
bsw.PutUint8(pat.Current_next_indicator, 1)
|
||||
bsw.PutUint8(pat.Section_number, 8)
|
||||
bsw.PutUint8(pat.Last_section_number, 8)
|
||||
for _, pms := range pat.Pmts {
|
||||
bsw.PutUint16(pms.Program_number, 16)
|
||||
bsw.PutUint8(0x07, 3)
|
||||
bsw.PutUint16(pms.PID, 13)
|
||||
}
|
||||
length := bsw.DistanceFromMarkDot()
|
||||
//|Section_syntax_indicator|'0'|reserved|Section_length|
|
||||
pat.Section_length = uint16(length)/8 + 4
|
||||
bsw.SetUint16(pat.Section_length&0x0FFF|(uint16(pat.Section_syntax_indicator)<<15)|0x3000, loc)
|
||||
crc := codec.CalcCrc32(0xffffffff, bsw.Bits()[bsw.ByteOffset()-int(pat.Section_length-4)-3:bsw.ByteOffset()])
|
||||
tmpcrc := make([]byte, 4)
|
||||
binary.LittleEndian.PutUint32(tmpcrc, crc)
|
||||
bsw.PutBytes(tmpcrc)
|
||||
}
|
||||
|
||||
func (pat *Pat) Decode(bs *codec.BitStream) error {
|
||||
pat.Table_id = bs.Uint8(8)
|
||||
pat.Table_id = bs.Uint8(8)
|
||||
|
||||
if pat.Table_id != uint8(TS_TID_PAS) {
|
||||
return errors.New("table id is Not TS_TID_PAS")
|
||||
}
|
||||
pat.Section_syntax_indicator = bs.Uint8(1)
|
||||
bs.SkipBits(3)
|
||||
pat.Section_length = bs.Uint16(12)
|
||||
pat.Transport_stream_id = bs.Uint16(16)
|
||||
bs.SkipBits(2)
|
||||
pat.Version_number = bs.Uint8(5)
|
||||
pat.Current_next_indicator = bs.Uint8(1)
|
||||
pat.Section_number = bs.Uint8(8)
|
||||
pat.Last_section_number = bs.Uint8(8)
|
||||
for i := 0; i+4 <= int(pat.Section_length)-5-4; i = i + 4 {
|
||||
tmp := PmtPair{
|
||||
Program_number: 0,
|
||||
PID: 0,
|
||||
}
|
||||
tmp.Program_number = bs.Uint16(16)
|
||||
bs.SkipBits(3)
|
||||
tmp.PID = bs.Uint16(13)
|
||||
pat.Pmts = append(pat.Pmts, tmp)
|
||||
}
|
||||
return nil
|
||||
if pat.Table_id != uint8(TS_TID_PAS) {
|
||||
return errors.New("table id is Not TS_TID_PAS")
|
||||
}
|
||||
pat.Section_syntax_indicator = bs.Uint8(1)
|
||||
bs.SkipBits(3)
|
||||
pat.Section_length = bs.Uint16(12)
|
||||
pat.Transport_stream_id = bs.Uint16(16)
|
||||
bs.SkipBits(2)
|
||||
pat.Version_number = bs.Uint8(5)
|
||||
pat.Current_next_indicator = bs.Uint8(1)
|
||||
pat.Section_number = bs.Uint8(8)
|
||||
pat.Last_section_number = bs.Uint8(8)
|
||||
for i := 0; i+4 <= int(pat.Section_length)-5-4; i = i + 4 {
|
||||
tmp := PmtPair{
|
||||
Program_number: 0,
|
||||
PID: 0,
|
||||
}
|
||||
tmp.Program_number = bs.Uint16(16)
|
||||
bs.SkipBits(3)
|
||||
tmp.PID = bs.Uint16(13)
|
||||
pat.Pmts = append(pat.Pmts, tmp)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type StreamPair struct {
|
||||
StreamType uint8 //8 uimsbf
|
||||
Elementary_PID uint16 //13 uimsbf
|
||||
ES_Info_Length uint16 //12 uimsbf
|
||||
StreamType uint8 //8 uimsbf
|
||||
Elementary_PID uint16 //13 uimsbf
|
||||
ES_Info_Length uint16 //12 uimsbf
|
||||
}
|
||||
|
||||
type Pmt struct {
|
||||
Table_id uint8 //8 uimsbf
|
||||
Section_syntax_indicator uint8 //1 bslbf
|
||||
Section_length uint16 //12 uimsbf
|
||||
Program_number uint16 //16 uimsbf
|
||||
Version_number uint8 //5 uimsbf
|
||||
Current_next_indicator uint8 //1 bslbf
|
||||
Section_number uint8 //8 uimsbf
|
||||
Last_section_number uint8 //8 uimsbf
|
||||
PCR_PID uint16 //13 uimsbf
|
||||
Program_info_length uint16 //12 uimsbf
|
||||
Streams []StreamPair
|
||||
Table_id uint8 //8 uimsbf
|
||||
Section_syntax_indicator uint8 //1 bslbf
|
||||
Section_length uint16 //12 uimsbf
|
||||
Program_number uint16 //16 uimsbf
|
||||
Version_number uint8 //5 uimsbf
|
||||
Current_next_indicator uint8 //1 bslbf
|
||||
Section_number uint8 //8 uimsbf
|
||||
Last_section_number uint8 //8 uimsbf
|
||||
PCR_PID uint16 //13 uimsbf
|
||||
Program_info_length uint16 //12 uimsbf
|
||||
Streams []StreamPair
|
||||
}
|
||||
|
||||
func NewPmt() *Pmt {
|
||||
return &Pmt{
|
||||
Table_id: uint8(TS_TID_PMS),
|
||||
Streams: make([]StreamPair, 0, 8),
|
||||
}
|
||||
return &Pmt{
|
||||
Table_id: uint8(TS_TID_PMS),
|
||||
Streams: make([]StreamPair, 0, 8),
|
||||
}
|
||||
}
|
||||
|
||||
func (pmt *Pmt) PrettyPrint(file *os.File) {
|
||||
file.WriteString(fmt.Sprintf("Table id:%d\n", pmt.Table_id))
|
||||
file.WriteString(fmt.Sprintf("Section_syntax_indicator:%d\n", pmt.Section_syntax_indicator))
|
||||
file.WriteString(fmt.Sprintf("Section_length:%d\n", pmt.Section_length))
|
||||
file.WriteString(fmt.Sprintf("Program_number:%d\n", pmt.Program_number))
|
||||
file.WriteString(fmt.Sprintf("Version_number:%d\n", pmt.Version_number))
|
||||
file.WriteString(fmt.Sprintf("Current_next_indicator:%d\n", pmt.Current_next_indicator))
|
||||
file.WriteString(fmt.Sprintf("Section_number:%d\n", pmt.Section_number))
|
||||
file.WriteString(fmt.Sprintf("Last_section_number:%d\n", pmt.Last_section_number))
|
||||
file.WriteString(fmt.Sprintf("PCR_PID:%d\n", pmt.PCR_PID))
|
||||
file.WriteString(fmt.Sprintf("program_info_length:%d\n", pmt.Program_info_length))
|
||||
for i, stream := range pmt.Streams {
|
||||
file.WriteString(fmt.Sprintf("----stream %d\n", i))
|
||||
if stream.StreamType == uint8(TS_STREAM_AAC) {
|
||||
file.WriteString(" stream_type:AAC\n")
|
||||
} else if stream.StreamType == uint8(TS_STREAM_H264) {
|
||||
file.WriteString(" stream_type:H264\n")
|
||||
} else if stream.StreamType == uint8(TS_STREAM_H265) {
|
||||
file.WriteString(" stream_type:H265\n")
|
||||
}
|
||||
file.WriteString(fmt.Sprintf(" elementary_PID:%d\n", stream.Elementary_PID))
|
||||
file.WriteString(fmt.Sprintf(" ES_info_length:%d\n", stream.ES_Info_Length))
|
||||
}
|
||||
file.WriteString(fmt.Sprintf("Table id:%d\n", pmt.Table_id))
|
||||
file.WriteString(fmt.Sprintf("Section_syntax_indicator:%d\n", pmt.Section_syntax_indicator))
|
||||
file.WriteString(fmt.Sprintf("Section_length:%d\n", pmt.Section_length))
|
||||
file.WriteString(fmt.Sprintf("Program_number:%d\n", pmt.Program_number))
|
||||
file.WriteString(fmt.Sprintf("Version_number:%d\n", pmt.Version_number))
|
||||
file.WriteString(fmt.Sprintf("Current_next_indicator:%d\n", pmt.Current_next_indicator))
|
||||
file.WriteString(fmt.Sprintf("Section_number:%d\n", pmt.Section_number))
|
||||
file.WriteString(fmt.Sprintf("Last_section_number:%d\n", pmt.Last_section_number))
|
||||
file.WriteString(fmt.Sprintf("PCR_PID:%d\n", pmt.PCR_PID))
|
||||
file.WriteString(fmt.Sprintf("program_info_length:%d\n", pmt.Program_info_length))
|
||||
for i, stream := range pmt.Streams {
|
||||
file.WriteString(fmt.Sprintf("----stream %d\n", i))
|
||||
if stream.StreamType == uint8(TS_STREAM_AAC) {
|
||||
file.WriteString(" stream_type:AAC\n")
|
||||
} else if stream.StreamType == uint8(TS_STREAM_H264) {
|
||||
file.WriteString(" stream_type:H264\n")
|
||||
} else if stream.StreamType == uint8(TS_STREAM_H265) {
|
||||
file.WriteString(" stream_type:H265\n")
|
||||
}
|
||||
file.WriteString(fmt.Sprintf(" elementary_PID:%d\n", stream.Elementary_PID))
|
||||
file.WriteString(fmt.Sprintf(" ES_info_length:%d\n", stream.ES_Info_Length))
|
||||
}
|
||||
}
|
||||
|
||||
func (pmt *Pmt) Encode(bsw *codec.BitStreamWriter) {
|
||||
bsw.PutUint8(pmt.Table_id, 8)
|
||||
loc := bsw.ByteOffset()
|
||||
bsw.PutUint8(pmt.Section_syntax_indicator, 1)
|
||||
bsw.PutUint8(0x00, 1)
|
||||
bsw.PutUint8(0x03, 2)
|
||||
bsw.PutUint16(pmt.Section_length, 12)
|
||||
bsw.Markdot()
|
||||
bsw.PutUint16(pmt.Program_number, 16)
|
||||
bsw.PutUint8(0x03, 2)
|
||||
bsw.PutUint8(pmt.Version_number, 5)
|
||||
bsw.PutUint8(pmt.Current_next_indicator, 1)
|
||||
bsw.PutUint8(pmt.Section_number, 8)
|
||||
bsw.PutUint8(pmt.Last_section_number, 8)
|
||||
bsw.PutUint8(0x07, 3)
|
||||
bsw.PutUint16(pmt.PCR_PID, 13)
|
||||
bsw.PutUint8(0x0f, 4)
|
||||
//TODO Program info length
|
||||
bsw.PutUint16(0x0000 /*pmt.Program_info_length*/, 12)
|
||||
for _, stream := range pmt.Streams {
|
||||
bsw.PutUint8(stream.StreamType, 8)
|
||||
bsw.PutUint8(0x00, 3)
|
||||
bsw.PutUint16(stream.Elementary_PID, 13)
|
||||
bsw.PutUint8(0x00, 4)
|
||||
//TODO ES_info
|
||||
bsw.PutUint8(0 /*ES_info_length*/, 12)
|
||||
}
|
||||
length := bsw.DistanceFromMarkDot()
|
||||
pmt.Section_length = uint16(length)/8 + 4
|
||||
bsw.SetUint16(pmt.Section_length&0x0FFF|(uint16(pmt.Section_syntax_indicator)<<15)|0x3000, loc)
|
||||
crc := codec.CalcCrc32(0xffffffff, bsw.Bits()[bsw.ByteOffset()-int(pmt.Section_length-4)-3:bsw.ByteOffset()])
|
||||
tmpcrc := make([]byte, 4)
|
||||
binary.LittleEndian.PutUint32(tmpcrc, crc)
|
||||
bsw.PutBytes(tmpcrc)
|
||||
bsw.PutUint8(pmt.Table_id, 8)
|
||||
loc := bsw.ByteOffset()
|
||||
bsw.PutUint8(pmt.Section_syntax_indicator, 1)
|
||||
bsw.PutUint8(0x00, 1)
|
||||
bsw.PutUint8(0x03, 2)
|
||||
bsw.PutUint16(pmt.Section_length, 12)
|
||||
bsw.Markdot()
|
||||
bsw.PutUint16(pmt.Program_number, 16)
|
||||
bsw.PutUint8(0x03, 2)
|
||||
bsw.PutUint8(pmt.Version_number, 5)
|
||||
bsw.PutUint8(pmt.Current_next_indicator, 1)
|
||||
bsw.PutUint8(pmt.Section_number, 8)
|
||||
bsw.PutUint8(pmt.Last_section_number, 8)
|
||||
bsw.PutUint8(0x07, 3)
|
||||
bsw.PutUint16(pmt.PCR_PID, 13)
|
||||
bsw.PutUint8(0x0f, 4)
|
||||
//TODO Program info length
|
||||
bsw.PutUint16(0x0000 /*pmt.Program_info_length*/, 12)
|
||||
for _, stream := range pmt.Streams {
|
||||
bsw.PutUint8(stream.StreamType, 8)
|
||||
bsw.PutUint8(0x00, 3)
|
||||
bsw.PutUint16(stream.Elementary_PID, 13)
|
||||
bsw.PutUint8(0x00, 4)
|
||||
//TODO ES_info
|
||||
bsw.PutUint8(0 /*ES_info_length*/, 12)
|
||||
}
|
||||
length := bsw.DistanceFromMarkDot()
|
||||
pmt.Section_length = uint16(length)/8 + 4
|
||||
bsw.SetUint16(pmt.Section_length&0x0FFF|(uint16(pmt.Section_syntax_indicator)<<15)|0x3000, loc)
|
||||
crc := codec.CalcCrc32(0xffffffff, bsw.Bits()[bsw.ByteOffset()-int(pmt.Section_length-4)-3:bsw.ByteOffset()])
|
||||
tmpcrc := make([]byte, 4)
|
||||
binary.LittleEndian.PutUint32(tmpcrc, crc)
|
||||
bsw.PutBytes(tmpcrc)
|
||||
}
|
||||
|
||||
func (pmt *Pmt) Decode(bs *codec.BitStream) error {
|
||||
pmt.Table_id = bs.Uint8(8)
|
||||
if pmt.Table_id != uint8(TS_TID_PMS) {
|
||||
return errors.New("table id is Not TS_TID_PAS")
|
||||
}
|
||||
pmt.Section_syntax_indicator = bs.Uint8(1)
|
||||
bs.SkipBits(3)
|
||||
pmt.Section_length = bs.Uint16(12)
|
||||
pmt.Program_number = bs.Uint16(16)
|
||||
bs.SkipBits(2)
|
||||
pmt.Version_number = bs.Uint8(5)
|
||||
pmt.Current_next_indicator = bs.Uint8(1)
|
||||
pmt.Section_number = bs.Uint8(8)
|
||||
pmt.Last_section_number = bs.Uint8(8)
|
||||
bs.SkipBits(3)
|
||||
pmt.PCR_PID = bs.Uint16(13)
|
||||
bs.SkipBits(4)
|
||||
pmt.Program_info_length = bs.Uint16(12)
|
||||
//TODO N loop descriptors
|
||||
bs.SkipBits(int(pmt.Program_info_length) * 8)
|
||||
//fmt.Printf("section length %d pmt.Pogram_info_length=%d\n", pmt.Section_length, pmt.Pogram_info_length)
|
||||
for i := 0; i < int(pmt.Section_length)-9-int(pmt.Program_info_length)-4; {
|
||||
tmp := StreamPair{
|
||||
StreamType: 0,
|
||||
Elementary_PID: 0,
|
||||
ES_Info_Length: 0,
|
||||
}
|
||||
tmp.StreamType = bs.Uint8(8)
|
||||
bs.SkipBits(3)
|
||||
tmp.Elementary_PID = bs.Uint16(13)
|
||||
bs.SkipBits(4)
|
||||
tmp.ES_Info_Length = bs.Uint16(12)
|
||||
//TODO N loop descriptors
|
||||
bs.SkipBits(int(tmp.ES_Info_Length) * 8)
|
||||
pmt.Streams = append(pmt.Streams, tmp)
|
||||
i += 5 + int(tmp.ES_Info_Length)
|
||||
}
|
||||
return nil
|
||||
pmt.Table_id = bs.Uint8(8)
|
||||
if pmt.Table_id != uint8(TS_TID_PMS) {
|
||||
return errors.New("table id is Not TS_TID_PAS")
|
||||
}
|
||||
pmt.Section_syntax_indicator = bs.Uint8(1)
|
||||
bs.SkipBits(3)
|
||||
pmt.Section_length = bs.Uint16(12)
|
||||
pmt.Program_number = bs.Uint16(16)
|
||||
bs.SkipBits(2)
|
||||
pmt.Version_number = bs.Uint8(5)
|
||||
pmt.Current_next_indicator = bs.Uint8(1)
|
||||
pmt.Section_number = bs.Uint8(8)
|
||||
pmt.Last_section_number = bs.Uint8(8)
|
||||
bs.SkipBits(3)
|
||||
pmt.PCR_PID = bs.Uint16(13)
|
||||
bs.SkipBits(4)
|
||||
pmt.Program_info_length = bs.Uint16(12)
|
||||
//TODO N loop descriptors
|
||||
bs.SkipBits(int(pmt.Program_info_length) * 8)
|
||||
//fmt.Printf("section length %d pmt.Pogram_info_length=%d\n", pmt.Section_length, pmt.Pogram_info_length)
|
||||
for i := 0; i < int(pmt.Section_length)-9-int(pmt.Program_info_length)-4; {
|
||||
tmp := StreamPair{
|
||||
StreamType: 0,
|
||||
Elementary_PID: 0,
|
||||
ES_Info_Length: 0,
|
||||
}
|
||||
tmp.StreamType = bs.Uint8(8)
|
||||
bs.SkipBits(3)
|
||||
tmp.Elementary_PID = bs.Uint16(13)
|
||||
bs.SkipBits(4)
|
||||
tmp.ES_Info_Length = bs.Uint16(12)
|
||||
//TODO N loop descriptors
|
||||
bs.SkipBits(int(tmp.ES_Info_Length) * 8)
|
||||
pmt.Streams = append(pmt.Streams, tmp)
|
||||
i += 5 + int(tmp.ES_Info_Length)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -1,12 +1,21 @@
|
|||
FROM ossrs/srs:dev-gcc7-cache
|
||||
FROM ossrs/srs:ubuntu20-cache
|
||||
|
||||
# Install depends tools.
|
||||
RUN yum install -y gcc make gcc-c++ patch unzip perl git
|
||||
ARG MAKEARGS
|
||||
RUN echo "MAKEARGS: ${MAKEARGS}"
|
||||
|
||||
# https://serverfault.com/questions/949991/how-to-install-tzdata-on-a-ubuntu-docker-image
|
||||
ENV DEBIAN_FRONTEND noninteractive
|
||||
|
||||
# For go to build and run utest.
|
||||
ENV PATH $PATH:/usr/local/go/bin
|
||||
|
||||
RUN apt update -y && apt install -y gcc make g++ patch unzip perl git libasan5
|
||||
|
||||
# Build and install SRS.
|
||||
COPY . /srs
|
||||
WORKDIR /srs/trunk
|
||||
|
||||
# Note that we must enable the gcc7 or link failed.
|
||||
RUN scl enable devtoolset-7 -- ./configure --srt=on --gb28181=on --apm=on --h265=on --utest=on --gcov=on --sanitizer=off
|
||||
RUN scl enable devtoolset-7 -- make utest
|
||||
RUN ./configure --srt=on --gb28181=on --apm=on --h265=on --utest=on --gcov=on --sanitizer=off
|
||||
RUN make utest ${MAKEARGS}
|
||||
|
||||
|
|
|
@ -1,16 +1,24 @@
|
|||
FROM ossrs/srs:dev-gcc7-cache
|
||||
RUN yum install -y gcc make gcc-c++ patch unzip perl git
|
||||
FROM ossrs/srs:ubuntu20-cache
|
||||
|
||||
ARG MAKEARGS
|
||||
RUN echo "MAKEARGS: ${MAKEARGS}"
|
||||
|
||||
# https://serverfault.com/questions/949991/how-to-install-tzdata-on-a-ubuntu-docker-image
|
||||
ENV DEBIAN_FRONTEND noninteractive
|
||||
|
||||
# For go to build and run utest.
|
||||
ENV PATH $PATH:/usr/local/go/bin
|
||||
|
||||
RUN apt update -y && apt install -y gcc make g++ patch unzip perl git libasan5
|
||||
|
||||
# Build and install SRS.
|
||||
COPY . /srs
|
||||
WORKDIR /srs/trunk
|
||||
|
||||
# Note that we must enable the gcc7 or link failed.
|
||||
RUN scl enable devtoolset-7 -- ./configure --srt=on --gb28181=on --apm=on --h265=on --utest=on
|
||||
RUN scl enable devtoolset-7 -- make utest
|
||||
RUN ./configure --srt=on --gb28181=on --srt=on --gb28181=on --apm=on --h265=on --utest=on
|
||||
RUN make utest ${MAKEARGS}
|
||||
|
||||
# Build benchmark tool.
|
||||
RUN cd 3rdparty/srs-bench && make
|
||||
RUN cd 3rdparty/srs-bench && make ${MAKEARGS}
|
||||
|
||||
# Run utest
|
||||
RUN ./objs/srs_utest
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
|
||||
listen 1935;
|
||||
max_connections 1000;
|
||||
|
||||
# For clion, use console as output.
|
||||
daemon off;
|
||||
srs_log_tank console;
|
||||
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
|
||||
listen 1935;
|
||||
max_connections 1000;
|
||||
daemon on; disable_daemon_for_docker off; srs_log_tank file;
|
||||
|
||||
# Force to daemon and write logs to file.
|
||||
daemon on;
|
||||
disable_daemon_for_docker off;
|
||||
srs_log_tank file;
|
||||
|
||||
stream_caster {
|
||||
enabled on;
|
||||
|
|
|
@ -24,6 +24,7 @@ The changelog for SRS.
|
|||
|
||||
## SRS 5.0 Changelog
|
||||
|
||||
* v5.0, 2022-12-31, GB28181: Enable regression test for gb28181. v5.0.122
|
||||
* v5.0, 2022-12-31, Refine configure to guess OS automatically. v5.0.121
|
||||
* v5.0, 2022-12-31, Refine default config file for SRS. v5.0.120
|
||||
* v5.0, 2022-12-26, For [#939](https://github.com/ossrs/srs/issues/939): FLV: Fix bug for header flag gussing. v5.0.119
|
||||
|
|
|
@ -9,6 +9,6 @@
|
|||
|
||||
#define VERSION_MAJOR 5
|
||||
#define VERSION_MINOR 0
|
||||
#define VERSION_REVISION 121
|
||||
#define VERSION_REVISION 122
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue