1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-03-09 15:49:59 +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:
winlin 2022-12-31 17:15:07 +08:00
parent bc381a0242
commit 3f7c4a7ff4
32 changed files with 3882 additions and 9727 deletions

View file

@ -171,16 +171,15 @@ jobs:
uses: actions/checkout@v3 uses: actions/checkout@v3
# Tests # Tests
- name: Build test image - 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 # For utest
- name: Run SRS 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 # For regression-test
- name: Run SRS regression-test - name: Run SRS regression-test
run: | run: |
docker run --rm srs:test bash -c 'make && \ docker run --rm srs:test bash -c './objs/srs -c conf/regression-test.conf && \
./objs/srs -c conf/regression-test.conf && \ cd 3rdparty/srs-bench && ./objs/srs_test -test.v && ./objs/srs_gb28181_test -test.v'
cd 3rdparty/srs-bench && make && ./objs/srs_test -test.v'
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
coverage: coverage:
@ -192,7 +191,7 @@ jobs:
uses: actions/checkout@v3 uses: actions/checkout@v3
# Tests # Tests
- name: Build coverage image - 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 # For coverage
- name: Run SRS covergae - name: Run SRS covergae
if: ${{ startsWith(github.ref, 'refs/heads/') || startsWith(github.ref, 'refs/pull/') }} 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 "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" 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 \ docker run --rm --env CODECOV_TOKEN=$CODECOV_TOKEN --env SRS_BRANCH=$SRS_BRANCH \
--env SRS_BRANCH=$SRS_BRANCH --env SRS_PR=$SRS_PR --env SRS_SHA=$SRS_SHA --env SRS_PROJECT=$SRS_PROJECT \ --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' srs:cov bash -c './objs/srs_utest && bash auto/codecov.sh'
# #
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04

View file

@ -7,3 +7,4 @@ objs
.format.txt .format.txt
.DS_Store .DS_Store
*.log

View file

@ -3,7 +3,7 @@
default: bench test default: bench test
clean: 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 .format.txt: *.go srs/*.go vnet/*.go janus/*.go gb28181/*.go
gofmt -w . 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 ./objs/srs_bench: .format.txt *.go srs/*.go vnet/*.go janus/*.go gb28181/*.go Makefile
go build -mod=vendor -o objs/srs_bench . 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 ./objs/srs_test: .format.txt *.go srs/*.go vnet/*.go Makefile
go test ./srs -mod=vendor -c -o ./objs/srs_test 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: help:
@echo "Usage: make [bench|test]" @echo "Usage: make [bench|test]"
@echo " bench Make the bench to ./objs/srs_bench" @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"

View file

@ -7,10 +7,20 @@ WebRTC benchmark on [pion/webrtc](https://github.com/pion/webrtc) for [SRS](http
编译和使用: 编译和使用:
```bash ```bash
git clone https://github.com/ossrs/srs-bench.git && git checkout feature/rtc && git clone -b feature/rtc https://github.com/ossrs/srs-bench.git &&
make && ./objs/srs_bench -h 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 ## 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推拉流 回归测试需要先启动[SRS](https://github.com/ossrs/srs/issues/307)支持WebRTC推拉流
```bash ```bash
if [[ ! -z $(ifconfig en0 inet| grep 'inet '|awk '{print $2}') ]]; then ./objs/srs -c conf/rtc.conf
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
``` ```
然后运行回归测试用例,如果只跑一次,可以直接运行: 然后运行回归测试用例,如果只跑一次,可以直接运行:
@ -235,6 +241,12 @@ make && ./objs/srs_bench -sfu gb28181 --help
go test ./gb28181 -mod=vendor -v -count=1 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` * `-srs-sip`SIP服务器地址。默认值`tcp://127.0.0.1:5060`

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -24,8 +24,8 @@ import (
"context" "context"
"fmt" "fmt"
"github.com/ghettovoice/gosip/sip" "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/errors"
"github.com/ossrs/go-oryx-lib/logger"
"testing" "testing"
"time" "time"
) )

View file

@ -11,7 +11,9 @@ type InvalidStartLineError string
func (err InvalidStartLineError) Syntax() bool { return true } func (err InvalidStartLineError) Syntax() bool { return true }
func (err InvalidStartLineError) Malformed() bool { return false } func (err InvalidStartLineError) Malformed() bool { return false }
func (err InvalidStartLineError) Broken() bool { return true } 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 type InvalidMessageFormat string

View file

@ -10,4 +10,3 @@ func isTerminal(fd int) bool {
_, err := unix.IoctlGetTermios(fd, ioctlReadTermios) _, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
return err == nil return err == nil
} }

View file

@ -10,4 +10,3 @@ func isTerminal(fd int) bool {
_, err := unix.IoctlGetTermios(fd, ioctlReadTermios) _, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
return err == nil return err == nil
} }

View file

@ -11,8 +11,8 @@ import (
"sync" "sync"
"time" "time"
"github.com/sirupsen/logrus"
"github.com/mgutz/ansi" "github.com/mgutz/ansi"
"github.com/sirupsen/logrus"
"golang.org/x/crypto/ssh/terminal" "golang.org/x/crypto/ssh/terminal"
) )

View file

@ -12,25 +12,25 @@ import "errors"
type AAC_PROFILE int type AAC_PROFILE int
const ( const (
MAIN AAC_PROFILE = iota MAIN AAC_PROFILE = iota
LC LC
SSR SSR
) )
type AAC_SAMPLING_FREQUENCY int type AAC_SAMPLING_FREQUENCY int
const ( const (
AAC_SAMPLE_96000 AAC_SAMPLING_FREQUENCY = iota AAC_SAMPLE_96000 AAC_SAMPLING_FREQUENCY = iota
AAC_SAMPLE_88200 AAC_SAMPLE_88200
AAC_SAMPLE_64000 AAC_SAMPLE_64000
AAC_SAMPLE_48000 AAC_SAMPLE_48000
AAC_SAMPLE_44100 AAC_SAMPLE_44100
AAC_SAMPLE_32000 AAC_SAMPLE_32000
AAC_SAMPLE_24000 AAC_SAMPLE_24000
AAC_SAMPLE_22050 AAC_SAMPLE_22050
AAC_SAMPLE_16000 AAC_SAMPLE_16000
AAC_SAMPLE_11025 AAC_SAMPLE_11025
AAC_SAMPLE_8000 AAC_SAMPLE_8000
) )
var AAC_Sampling_Idx [11]int = [11]int{96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 11025, 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 { type ADTS_Fix_Header struct {
ID uint8 ID uint8
Layer uint8 Layer uint8
Protection_absent uint8 Protection_absent uint8
Profile uint8 Profile uint8
Sampling_frequency_index uint8 Sampling_frequency_index uint8
Private_bit uint8 Private_bit uint8
Channel_configuration uint8 Channel_configuration uint8
Originalorcopy uint8 Originalorcopy uint8
Home uint8 Home uint8
} }
// adts_variable_header() { // adts_variable_header() {
@ -93,91 +93,91 @@ type ADTS_Fix_Header struct {
// } // }
type ADTS_Variable_Header struct { type ADTS_Variable_Header struct {
Copyright_identification_bit uint8 Copyright_identification_bit uint8
copyright_identification_start uint8 copyright_identification_start uint8
Frame_length uint16 Frame_length uint16
Adts_buffer_fullness uint16 Adts_buffer_fullness uint16
Number_of_raw_data_blocks_in_frame uint8 Number_of_raw_data_blocks_in_frame uint8
} }
type ADTS_Frame_Header struct { type ADTS_Frame_Header struct {
Fix_Header ADTS_Fix_Header Fix_Header ADTS_Fix_Header
Variable_Header ADTS_Variable_Header Variable_Header ADTS_Variable_Header
} }
func NewAdtsFrameHeader() *ADTS_Frame_Header { func NewAdtsFrameHeader() *ADTS_Frame_Header {
return &ADTS_Frame_Header{ return &ADTS_Frame_Header{
Fix_Header: ADTS_Fix_Header{ Fix_Header: ADTS_Fix_Header{
ID: 0, ID: 0,
Layer: 0, Layer: 0,
Protection_absent: 1, Protection_absent: 1,
Profile: uint8(MAIN), Profile: uint8(MAIN),
Sampling_frequency_index: uint8(AAC_SAMPLE_44100), Sampling_frequency_index: uint8(AAC_SAMPLE_44100),
Private_bit: 0, Private_bit: 0,
Channel_configuration: 0, Channel_configuration: 0,
Originalorcopy: 0, Originalorcopy: 0,
Home: 0, Home: 0,
}, },
Variable_Header: ADTS_Variable_Header{ Variable_Header: ADTS_Variable_Header{
copyright_identification_start: 0, copyright_identification_start: 0,
Copyright_identification_bit: 0, Copyright_identification_bit: 0,
Frame_length: 0, Frame_length: 0,
Adts_buffer_fullness: 0, Adts_buffer_fullness: 0,
Number_of_raw_data_blocks_in_frame: 0, Number_of_raw_data_blocks_in_frame: 0,
}, },
} }
} }
func (frame *ADTS_Frame_Header) Decode(aac []byte) error { func (frame *ADTS_Frame_Header) Decode(aac []byte) error {
_ = aac[6] _ = aac[6]
frame.Fix_Header.ID = aac[1] >> 3 frame.Fix_Header.ID = aac[1] >> 3
frame.Fix_Header.Layer = aac[1] >> 1 & 0x03 frame.Fix_Header.Layer = aac[1] >> 1 & 0x03
frame.Fix_Header.Protection_absent = aac[1] & 0x01 frame.Fix_Header.Protection_absent = aac[1] & 0x01
frame.Fix_Header.Profile = aac[2] >> 6 & 0x03 frame.Fix_Header.Profile = aac[2] >> 6 & 0x03
frame.Fix_Header.Sampling_frequency_index = aac[2] >> 2 & 0x0F frame.Fix_Header.Sampling_frequency_index = aac[2] >> 2 & 0x0F
frame.Fix_Header.Private_bit = aac[2] >> 1 & 0x01 frame.Fix_Header.Private_bit = aac[2] >> 1 & 0x01
frame.Fix_Header.Channel_configuration = (aac[2] & 0x01 << 2) | (aac[3] >> 6) frame.Fix_Header.Channel_configuration = (aac[2] & 0x01 << 2) | (aac[3] >> 6)
frame.Fix_Header.Originalorcopy = aac[3] >> 5 & 0x01 frame.Fix_Header.Originalorcopy = aac[3] >> 5 & 0x01
frame.Fix_Header.Home = aac[3] >> 4 & 0x01 frame.Fix_Header.Home = aac[3] >> 4 & 0x01
frame.Variable_Header.Copyright_identification_bit = aac[3] >> 3 & 0x01 frame.Variable_Header.Copyright_identification_bit = aac[3] >> 3 & 0x01
frame.Variable_Header.copyright_identification_start = aac[3] >> 2 & 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.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.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 frame.Variable_Header.Number_of_raw_data_blocks_in_frame = aac[6] & 0x03
return nil return nil
} }
func (frame *ADTS_Frame_Header) Encode() []byte { func (frame *ADTS_Frame_Header) Encode() []byte {
var hdr []byte var hdr []byte
if frame.Fix_Header.Protection_absent == 1 { if frame.Fix_Header.Protection_absent == 1 {
hdr = make([]byte, 7) hdr = make([]byte, 7)
} else { } else {
hdr = make([]byte, 9) hdr = make([]byte, 9)
} }
hdr[0] = 0xFF hdr[0] = 0xFF
hdr[1] = 0xF0 hdr[1] = 0xF0
hdr[1] = hdr[1] | (frame.Fix_Header.ID << 3) | (frame.Fix_Header.Layer << 1) | frame.Fix_Header.Protection_absent 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[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] = 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[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[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[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 hdr[6] = byte(frame.Variable_Header.Adts_buffer_fullness&0x3F<<2) | frame.Variable_Header.Number_of_raw_data_blocks_in_frame
return hdr return hdr
} }
func SampleToAACSampleIndex(sampling int) int { func SampleToAACSampleIndex(sampling int) int {
for i, v := range AAC_Sampling_Idx { for i, v := range AAC_Sampling_Idx {
if v == sampling { if v == sampling {
return i return i
} }
} }
panic("not Found AAC Sample Index") panic("not Found AAC Sample Index")
} }
func AACSampleIdxToSample(idx int) int { 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 { type AudioSpecificConfiguration struct {
Audio_object_type uint8 Audio_object_type uint8
Sample_freq_index uint8 Sample_freq_index uint8
Channel_configuration uint8 Channel_configuration uint8
GA_framelength_flag uint8 GA_framelength_flag uint8
GA_depends_on_core_coder uint8 GA_depends_on_core_coder uint8
GA_extension_flag uint8 GA_extension_flag uint8
} }
func NewAudioSpecificConfiguration() *AudioSpecificConfiguration { func NewAudioSpecificConfiguration() *AudioSpecificConfiguration {
return &AudioSpecificConfiguration{ return &AudioSpecificConfiguration{
Audio_object_type: 0, Audio_object_type: 0,
Sample_freq_index: 0, Sample_freq_index: 0,
Channel_configuration: 0, Channel_configuration: 0,
GA_framelength_flag: 0, GA_framelength_flag: 0,
GA_depends_on_core_coder: 0, GA_depends_on_core_coder: 0,
GA_extension_flag: 0, GA_extension_flag: 0,
} }
} }
func (asc *AudioSpecificConfiguration) Encode() []byte { func (asc *AudioSpecificConfiguration) Encode() []byte {
buf := make([]byte, 2) buf := make([]byte, 2)
buf[0] = (asc.Audio_object_type & 0x1f << 3) | (asc.Sample_freq_index & 0x0F >> 1) 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) 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 return buf
} }
func (asc *AudioSpecificConfiguration) Decode(buf []byte) error { func (asc *AudioSpecificConfiguration) Decode(buf []byte) error {
if len(buf) < 2 { if len(buf) < 2 {
return errors.New("len of buf < 2 ") return errors.New("len of buf < 2 ")
} }
asc.Audio_object_type = buf[0] >> 3 asc.Audio_object_type = buf[0] >> 3
asc.Sample_freq_index = (buf[0] & 0x07 << 1) | (buf[1] >> 7) asc.Sample_freq_index = (buf[0] & 0x07 << 1) | (buf[1] >> 7)
asc.Channel_configuration = buf[1] >> 3 & 0x0F asc.Channel_configuration = buf[1] >> 3 & 0x0F
asc.GA_framelength_flag = buf[1] >> 2 & 0x01 asc.GA_framelength_flag = buf[1] >> 2 & 0x01
asc.GA_depends_on_core_coder = buf[1] >> 1 & 0x01 asc.GA_depends_on_core_coder = buf[1] >> 1 & 0x01
asc.GA_extension_flag = buf[1] & 0x01 asc.GA_extension_flag = buf[1] & 0x01
return nil return nil
} }
func ConvertADTSToASC(frame []byte) ([]byte, error) { func ConvertADTSToASC(frame []byte) ([]byte, error) {
if len(frame) < 7 { if len(frame) < 7 {
return nil, errors.New("len of frame < 7") return nil, errors.New("len of frame < 7")
} }
adts := NewAdtsFrameHeader() adts := NewAdtsFrameHeader()
adts.Decode(frame) adts.Decode(frame)
asc := NewAudioSpecificConfiguration() asc := NewAudioSpecificConfiguration()
asc.Audio_object_type = adts.Fix_Header.Profile + 1 asc.Audio_object_type = adts.Fix_Header.Profile + 1
asc.Channel_configuration = adts.Fix_Header.Channel_configuration asc.Channel_configuration = adts.Fix_Header.Channel_configuration
asc.Sample_freq_index = adts.Fix_Header.Sampling_frequency_index asc.Sample_freq_index = adts.Fix_Header.Sampling_frequency_index
return asc.Encode(), nil return asc.Encode(), nil
} }
func ConvertASCToADTS(asc []byte, aacbytes int) []byte { func ConvertASCToADTS(asc []byte, aacbytes int) []byte {
aac_asc := NewAudioSpecificConfiguration() aac_asc := NewAudioSpecificConfiguration()
aac_asc.Decode(asc) aac_asc.Decode(asc)
aac_adts := NewAdtsFrameHeader() aac_adts := NewAdtsFrameHeader()
aac_adts.Fix_Header.Profile = aac_asc.Audio_object_type - 1 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.Channel_configuration = aac_asc.Channel_configuration
aac_adts.Fix_Header.Sampling_frequency_index = aac_asc.Sample_freq_index aac_adts.Fix_Header.Sampling_frequency_index = aac_asc.Sample_freq_index
aac_adts.Fix_Header.Protection_absent = 1 aac_adts.Fix_Header.Protection_absent = 1
aac_adts.Variable_Header.Adts_buffer_fullness = 0x3F aac_adts.Variable_Header.Adts_buffer_fullness = 0x3F
aac_adts.Variable_Header.Frame_length = uint16(aacbytes) aac_adts.Variable_Header.Frame_length = uint16(aacbytes)
return aac_adts.Encode() return aac_adts.Encode()
} }

View file

@ -1,358 +1,358 @@
package codec package codec
import ( import (
"encoding/binary" "encoding/binary"
) )
var BitMask [8]byte = [8]byte{0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF} var BitMask [8]byte = [8]byte{0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF}
type BitStream struct { type BitStream struct {
bits []byte bits []byte
bytesOffset int bytesOffset int
bitsOffset int bitsOffset int
bitsmark int bitsmark int
bytemark int bytemark int
} }
func NewBitStream(buf []byte) *BitStream { func NewBitStream(buf []byte) *BitStream {
return &BitStream{ return &BitStream{
bits: buf, bits: buf,
bytesOffset: 0, bytesOffset: 0,
bitsOffset: 0, bitsOffset: 0,
bitsmark: 0, bitsmark: 0,
bytemark: 0, bytemark: 0,
} }
} }
func (bs *BitStream) Uint8(n int) uint8 { func (bs *BitStream) Uint8(n int) uint8 {
return uint8(bs.GetBits(n)) return uint8(bs.GetBits(n))
} }
func (bs *BitStream) Uint16(n int) uint16 { func (bs *BitStream) Uint16(n int) uint16 {
return uint16(bs.GetBits(n)) return uint16(bs.GetBits(n))
} }
func (bs *BitStream) Uint32(n int) uint32 { func (bs *BitStream) Uint32(n int) uint32 {
return uint32(bs.GetBits(n)) return uint32(bs.GetBits(n))
} }
func (bs *BitStream) GetBytes(n int) []byte { func (bs *BitStream) GetBytes(n int) []byte {
if bs.bytesOffset+n > len(bs.bits) { if bs.bytesOffset+n > len(bs.bits) {
panic("OUT OF RANGE") panic("OUT OF RANGE")
} }
if bs.bitsOffset != 0 { if bs.bitsOffset != 0 {
panic("invaild operation") panic("invaild operation")
} }
data := make([]byte, n) data := make([]byte, n)
copy(data, bs.bits[bs.bytesOffset:bs.bytesOffset+n]) copy(data, bs.bits[bs.bytesOffset:bs.bytesOffset+n])
bs.bytesOffset += n bs.bytesOffset += n
return data return data
} }
//n <= 64 //n <= 64
func (bs *BitStream) GetBits(n int) uint64 { func (bs *BitStream) GetBits(n int) uint64 {
if bs.bytesOffset >= len(bs.bits) { if bs.bytesOffset >= len(bs.bits) {
panic("OUT OF RANGE") panic("OUT OF RANGE")
} }
var ret uint64 = 0 var ret uint64 = 0
if 8-bs.bitsOffset >= n { if 8-bs.bitsOffset >= n {
ret = uint64((bs.bits[bs.bytesOffset] >> (8 - bs.bitsOffset - n)) & BitMask[n-1]) ret = uint64((bs.bits[bs.bytesOffset] >> (8 - bs.bitsOffset - n)) & BitMask[n-1])
bs.bitsOffset += n bs.bitsOffset += n
if bs.bitsOffset == 8 { if bs.bitsOffset == 8 {
bs.bytesOffset++ bs.bytesOffset++
bs.bitsOffset = 0 bs.bitsOffset = 0
} }
} else { } else {
ret = uint64(bs.bits[bs.bytesOffset] & BitMask[8-bs.bitsOffset-1]) ret = uint64(bs.bits[bs.bytesOffset] & BitMask[8-bs.bitsOffset-1])
bs.bytesOffset++ bs.bytesOffset++
n -= 8 - bs.bitsOffset n -= 8 - bs.bitsOffset
bs.bitsOffset = 0 bs.bitsOffset = 0
for n > 0 { for n > 0 {
if bs.bytesOffset >= len(bs.bits) { if bs.bytesOffset >= len(bs.bits) {
panic("OUT OF RANGE") panic("OUT OF RANGE")
} }
if n >= 8 { if n >= 8 {
ret = ret<<8 | uint64(bs.bits[bs.bytesOffset]) ret = ret<<8 | uint64(bs.bits[bs.bytesOffset])
bs.bytesOffset++ bs.bytesOffset++
n -= 8 n -= 8
} else { } else {
ret = (ret << n) | uint64((bs.bits[bs.bytesOffset]>>(8-n))&BitMask[n-1]) ret = (ret << n) | uint64((bs.bits[bs.bytesOffset]>>(8-n))&BitMask[n-1])
bs.bitsOffset = n bs.bitsOffset = n
break break
} }
} }
} }
return ret return ret
} }
func (bs *BitStream) GetBit() uint8 { func (bs *BitStream) GetBit() uint8 {
if bs.bytesOffset >= len(bs.bits) { if bs.bytesOffset >= len(bs.bits) {
panic("OUT OF RANGE") panic("OUT OF RANGE")
} }
ret := bs.bits[bs.bytesOffset] >> (7 - bs.bitsOffset) & 0x01 ret := bs.bits[bs.bytesOffset] >> (7 - bs.bitsOffset) & 0x01
bs.bitsOffset++ bs.bitsOffset++
if bs.bitsOffset >= 8 { if bs.bitsOffset >= 8 {
bs.bytesOffset++ bs.bytesOffset++
bs.bitsOffset = 0 bs.bitsOffset = 0
} }
return ret return ret
} }
func (bs *BitStream) SkipBits(n int) { func (bs *BitStream) SkipBits(n int) {
bytecount := n / 8 bytecount := n / 8
bitscount := n % 8 bitscount := n % 8
bs.bytesOffset += bytecount bs.bytesOffset += bytecount
if bs.bitsOffset+bitscount < 8 { if bs.bitsOffset+bitscount < 8 {
bs.bitsOffset += bitscount bs.bitsOffset += bitscount
} else { } else {
bs.bytesOffset += 1 bs.bytesOffset += 1
bs.bitsOffset += bitscount - 8 bs.bitsOffset += bitscount - 8
} }
} }
func (bs *BitStream) Markdot() { func (bs *BitStream) Markdot() {
bs.bitsmark = bs.bitsOffset bs.bitsmark = bs.bitsOffset
bs.bytemark = bs.bytesOffset bs.bytemark = bs.bytesOffset
} }
func (bs *BitStream) DistanceFromMarkDot() int { func (bs *BitStream) DistanceFromMarkDot() int {
bytecount := bs.bytesOffset - bs.bytemark - 1 bytecount := bs.bytesOffset - bs.bytemark - 1
bitscount := bs.bitsOffset + (8 - bs.bitsmark) bitscount := bs.bitsOffset + (8 - bs.bitsmark)
return bytecount*8 + bitscount return bytecount*8 + bitscount
} }
func (bs *BitStream) RemainBytes() int { func (bs *BitStream) RemainBytes() int {
if bs.bitsOffset > 0 { if bs.bitsOffset > 0 {
return len(bs.bits) - bs.bytesOffset - 1 return len(bs.bits) - bs.bytesOffset - 1
} else { } else {
return len(bs.bits) - bs.bytesOffset return len(bs.bits) - bs.bytesOffset
} }
} }
func (bs *BitStream) RemainBits() int { func (bs *BitStream) RemainBits() int {
if bs.bitsOffset > 0 { if bs.bitsOffset > 0 {
return bs.RemainBytes()*8 + 8 - bs.bitsOffset return bs.RemainBytes()*8 + 8 - bs.bitsOffset
} else { } else {
return bs.RemainBytes() * 8 return bs.RemainBytes() * 8
} }
} }
func (bs *BitStream) Bits() []byte { func (bs *BitStream) Bits() []byte {
return bs.bits return bs.bits
} }
func (bs *BitStream) RemainData() []byte { func (bs *BitStream) RemainData() []byte {
return bs.bits[bs.bytesOffset:] return bs.bits[bs.bytesOffset:]
} }
//无符号哥伦布熵编码 //无符号哥伦布熵编码
func (bs *BitStream) ReadUE() uint64 { func (bs *BitStream) ReadUE() uint64 {
leadingZeroBits := 0 leadingZeroBits := 0
for bs.GetBit() == 0 { for bs.GetBit() == 0 {
leadingZeroBits++ leadingZeroBits++
} }
if leadingZeroBits == 0 { if leadingZeroBits == 0 {
return 0 return 0
} }
info := bs.GetBits(leadingZeroBits) info := bs.GetBits(leadingZeroBits)
return uint64(1)<<leadingZeroBits - 1 + info return uint64(1)<<leadingZeroBits - 1 + info
} }
//有符号哥伦布熵编码 //有符号哥伦布熵编码
func (bs *BitStream) ReadSE() int64 { func (bs *BitStream) ReadSE() int64 {
v := bs.ReadUE() v := bs.ReadUE()
if v%2 == 0 { if v%2 == 0 {
return -1 * int64(v/2) return -1 * int64(v/2)
} else { } else {
return int64(v+1) / 2 return int64(v+1) / 2
} }
} }
func (bs *BitStream) ByteOffset() int { func (bs *BitStream) ByteOffset() int {
return bs.bytesOffset return bs.bytesOffset
} }
func (bs *BitStream) UnRead(n int) { func (bs *BitStream) UnRead(n int) {
if n-bs.bitsOffset <= 0 { if n-bs.bitsOffset <= 0 {
bs.bitsOffset -= n bs.bitsOffset -= n
} else { } else {
least := n - bs.bitsOffset least := n - bs.bitsOffset
for least >= 8 { for least >= 8 {
bs.bytesOffset-- bs.bytesOffset--
least -= 8 least -= 8
} }
if least > 0 { if least > 0 {
bs.bytesOffset-- bs.bytesOffset--
bs.bitsOffset = 8 - least bs.bitsOffset = 8 - least
} }
} }
} }
func (bs *BitStream) NextBits(n int) uint64 { func (bs *BitStream) NextBits(n int) uint64 {
r := bs.GetBits(n) r := bs.GetBits(n)
bs.UnRead(n) bs.UnRead(n)
return r return r
} }
func (bs *BitStream) EOS() bool { 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 { type BitStreamWriter struct {
bits []byte bits []byte
byteoffset int byteoffset int
bitsoffset int bitsoffset int
bitsmark int bitsmark int
bytemark int bytemark int
} }
func NewBitStreamWriter(n int) *BitStreamWriter { func NewBitStreamWriter(n int) *BitStreamWriter {
return &BitStreamWriter{ return &BitStreamWriter{
bits: make([]byte, n), bits: make([]byte, n),
byteoffset: 0, byteoffset: 0,
bitsoffset: 0, bitsoffset: 0,
bitsmark: 0, bitsmark: 0,
bytemark: 0, bytemark: 0,
} }
} }
func (bsw *BitStreamWriter) expandSpace(n int) { func (bsw *BitStreamWriter) expandSpace(n int) {
if (len(bsw.bits)-bsw.byteoffset-1)*8+8-bsw.bitsoffset < n { if (len(bsw.bits)-bsw.byteoffset-1)*8+8-bsw.bitsoffset < n {
newlen := 0 newlen := 0
if len(bsw.bits)*8 < n { if len(bsw.bits)*8 < n {
newlen = len(bsw.bits) + n/8 + 1 newlen = len(bsw.bits) + n/8 + 1
} else { } else {
newlen = len(bsw.bits) * 2 newlen = len(bsw.bits) * 2
} }
tmp := make([]byte, newlen) tmp := make([]byte, newlen)
copy(tmp, bsw.bits) copy(tmp, bsw.bits)
bsw.bits = tmp bsw.bits = tmp
} }
} }
func (bsw *BitStreamWriter) ByteOffset() int { func (bsw *BitStreamWriter) ByteOffset() int {
return bsw.byteoffset return bsw.byteoffset
} }
func (bsw *BitStreamWriter) BitOffset() int { func (bsw *BitStreamWriter) BitOffset() int {
return bsw.bitsoffset return bsw.bitsoffset
} }
func (bsw *BitStreamWriter) Markdot() { func (bsw *BitStreamWriter) Markdot() {
bsw.bitsmark = bsw.bitsoffset bsw.bitsmark = bsw.bitsoffset
bsw.bytemark = bsw.byteoffset bsw.bytemark = bsw.byteoffset
} }
func (bsw *BitStreamWriter) DistanceFromMarkDot() int { func (bsw *BitStreamWriter) DistanceFromMarkDot() int {
bytecount := bsw.byteoffset - bsw.bytemark - 1 bytecount := bsw.byteoffset - bsw.bytemark - 1
bitscount := bsw.bitsoffset + (8 - bsw.bitsmark) bitscount := bsw.bitsoffset + (8 - bsw.bitsmark)
return bytecount*8 + bitscount return bytecount*8 + bitscount
} }
func (bsw *BitStreamWriter) PutByte(v byte) { func (bsw *BitStreamWriter) PutByte(v byte) {
bsw.expandSpace(8) bsw.expandSpace(8)
if bsw.bitsoffset == 0 { if bsw.bitsoffset == 0 {
bsw.bits[bsw.byteoffset] = v bsw.bits[bsw.byteoffset] = v
bsw.byteoffset++ bsw.byteoffset++
} else { } else {
bsw.bits[bsw.byteoffset] |= v >> byte(bsw.bitsoffset) bsw.bits[bsw.byteoffset] |= v >> byte(bsw.bitsoffset)
bsw.byteoffset++ bsw.byteoffset++
bsw.bits[bsw.byteoffset] = v & BitMask[bsw.bitsoffset-1] bsw.bits[bsw.byteoffset] = v & BitMask[bsw.bitsoffset-1]
} }
} }
func (bsw *BitStreamWriter) PutBytes(v []byte) { func (bsw *BitStreamWriter) PutBytes(v []byte) {
if bsw.bitsoffset != 0 { if bsw.bitsoffset != 0 {
panic("bsw.bitsoffset > 0") panic("bsw.bitsoffset > 0")
} }
bsw.expandSpace(8 * len(v)) bsw.expandSpace(8 * len(v))
copy(bsw.bits[bsw.byteoffset:], v) copy(bsw.bits[bsw.byteoffset:], v)
bsw.byteoffset += len(v) bsw.byteoffset += len(v)
} }
func (bsw *BitStreamWriter) PutRepetValue(v byte, n int) { func (bsw *BitStreamWriter) PutRepetValue(v byte, n int) {
if bsw.bitsoffset != 0 { if bsw.bitsoffset != 0 {
panic("bsw.bitsoffset > 0") panic("bsw.bitsoffset > 0")
} }
bsw.expandSpace(8 * n) bsw.expandSpace(8 * n)
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
bsw.bits[bsw.byteoffset] = v bsw.bits[bsw.byteoffset] = v
bsw.byteoffset++ bsw.byteoffset++
} }
} }
func (bsw *BitStreamWriter) PutUint8(v uint8, n int) { 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) { 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) { 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) { func (bsw *BitStreamWriter) PutUint64(v uint64, n int) {
bsw.expandSpace(n) bsw.expandSpace(n)
if 8-bsw.bitsoffset >= n { if 8-bsw.bitsoffset >= n {
bsw.bits[bsw.byteoffset] |= uint8(v) & BitMask[n-1] << (8 - bsw.bitsoffset - n) bsw.bits[bsw.byteoffset] |= uint8(v) & BitMask[n-1] << (8 - bsw.bitsoffset - n)
bsw.bitsoffset += n bsw.bitsoffset += n
if bsw.bitsoffset == 8 { if bsw.bitsoffset == 8 {
bsw.bitsoffset = 0 bsw.bitsoffset = 0
bsw.byteoffset++ bsw.byteoffset++
} }
} else { } else {
bsw.bits[bsw.byteoffset] |= uint8(v>>(n-int(8-bsw.bitsoffset))) & BitMask[8-bsw.bitsoffset-1] bsw.bits[bsw.byteoffset] |= uint8(v>>(n-int(8-bsw.bitsoffset))) & BitMask[8-bsw.bitsoffset-1]
bsw.byteoffset++ bsw.byteoffset++
n -= 8 - bsw.bitsoffset n -= 8 - bsw.bitsoffset
for n-8 >= 0 { for n-8 >= 0 {
bsw.bits[bsw.byteoffset] = uint8(v>>(n-8)) & 0xFF bsw.bits[bsw.byteoffset] = uint8(v>>(n-8)) & 0xFF
bsw.byteoffset++ bsw.byteoffset++
n -= 8 n -= 8
} }
bsw.bitsoffset = n bsw.bitsoffset = n
if n > 0 { if n > 0 {
bsw.bits[bsw.byteoffset] |= (uint8(v) & BitMask[n-1]) << (8 - n) bsw.bits[bsw.byteoffset] |= (uint8(v) & BitMask[n-1]) << (8 - n)
} }
} }
} }
func (bsw *BitStreamWriter) SetByte(v byte, where int) { func (bsw *BitStreamWriter) SetByte(v byte, where int) {
bsw.bits[where] = v bsw.bits[where] = v
} }
func (bsw *BitStreamWriter) SetUint16(v uint16, where int) { 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 { func (bsw *BitStreamWriter) Bits() []byte {
if bsw.byteoffset == len(bsw.bits) { if bsw.byteoffset == len(bsw.bits) {
return bsw.bits return bsw.bits
} }
if bsw.bitsoffset > 0 { if bsw.bitsoffset > 0 {
return bsw.bits[0 : bsw.byteoffset+1] return bsw.bits[0 : bsw.byteoffset+1]
} else { } else {
return bsw.bits[0:bsw.byteoffset] return bsw.bits[0:bsw.byteoffset]
} }
} }
//用v 填充剩余字节 //用v 填充剩余字节
func (bsw *BitStreamWriter) FillRemainData(v byte) { func (bsw *BitStreamWriter) FillRemainData(v byte) {
for i := bsw.byteoffset; i < len(bsw.bits); i++ { for i := bsw.byteoffset; i < len(bsw.bits); i++ {
bsw.bits[i] = v bsw.bits[i] = v
} }
bsw.byteoffset = len(bsw.bits) bsw.byteoffset = len(bsw.bits)
bsw.bitsoffset = 0 bsw.bitsoffset = 0
} }
func (bsw *BitStreamWriter) Reset() { func (bsw *BitStreamWriter) Reset() {
for i := 0; i < len(bsw.bits); i++ { for i := 0; i < len(bsw.bits); i++ {
bsw.bits[i] = 0 bsw.bits[i] = 0
} }
bsw.bitsmark = 0 bsw.bitsmark = 0
bsw.bytemark = 0 bsw.bytemark = 0
bsw.bitsoffset = 0 bsw.bitsoffset = 0
bsw.byteoffset = 0 bsw.byteoffset = 0
} }

View file

@ -3,62 +3,62 @@ package codec
type CodecID int type CodecID int
const ( const (
CODECID_VIDEO_H264 CodecID = iota CODECID_VIDEO_H264 CodecID = iota
CODECID_VIDEO_H265 CODECID_VIDEO_H265
CODECID_VIDEO_VP8 CODECID_VIDEO_VP8
CODECID_AUDIO_AAC CodecID = iota + 98 CODECID_AUDIO_AAC CodecID = iota + 98
CODECID_AUDIO_G711A CODECID_AUDIO_G711A
CODECID_AUDIO_G711U CODECID_AUDIO_G711U
CODECID_AUDIO_OPUS CODECID_AUDIO_OPUS
CODECID_UNRECOGNIZED = 999 CODECID_UNRECOGNIZED = 999
) )
type H264_NAL_TYPE int type H264_NAL_TYPE int
const ( const (
H264_NAL_RESERVED H264_NAL_TYPE = iota H264_NAL_RESERVED H264_NAL_TYPE = iota
H264_NAL_P_SLICE H264_NAL_P_SLICE
H264_NAL_SLICE_A H264_NAL_SLICE_A
H264_NAL_SLICE_B H264_NAL_SLICE_B
H264_NAL_SLICE_C H264_NAL_SLICE_C
H264_NAL_I_SLICE H264_NAL_I_SLICE
H264_NAL_SEI H264_NAL_SEI
H264_NAL_SPS H264_NAL_SPS
H264_NAL_PPS H264_NAL_PPS
H264_NAL_AUD H264_NAL_AUD
) )
type H265_NAL_TYPE int type H265_NAL_TYPE int
const ( const (
H265_NAL_Slice_TRAIL_N H265_NAL_TYPE = iota H265_NAL_Slice_TRAIL_N H265_NAL_TYPE = iota
H265_NAL_LICE_TRAIL_R H265_NAL_LICE_TRAIL_R
H265_NAL_SLICE_TSA_N H265_NAL_SLICE_TSA_N
H265_NAL_SLICE_TSA_R H265_NAL_SLICE_TSA_R
H265_NAL_SLICE_STSA_N H265_NAL_SLICE_STSA_N
H265_NAL_SLICE_STSA_R H265_NAL_SLICE_STSA_R
H265_NAL_SLICE_RADL_N H265_NAL_SLICE_RADL_N
H265_NAL_SLICE_RADL_R H265_NAL_SLICE_RADL_R
H265_NAL_SLICE_RASL_N H265_NAL_SLICE_RASL_N
H265_NAL_SLICE_RASL_R H265_NAL_SLICE_RASL_R
//IDR //IDR
H265_NAL_SLICE_BLA_W_LP H265_NAL_TYPE = iota + 6 H265_NAL_SLICE_BLA_W_LP H265_NAL_TYPE = iota + 6
H265_NAL_SLICE_BLA_W_RADL H265_NAL_SLICE_BLA_W_RADL
H265_NAL_SLICE_BLA_N_LP H265_NAL_SLICE_BLA_N_LP
H265_NAL_SLICE_IDR_W_RADL H265_NAL_SLICE_IDR_W_RADL
H265_NAL_SLICE_IDR_N_LP H265_NAL_SLICE_IDR_N_LP
H265_NAL_SLICE_CRA H265_NAL_SLICE_CRA
//vps pps sps //vps pps sps
H265_NAL_VPS H265_NAL_TYPE = iota + 16 H265_NAL_VPS H265_NAL_TYPE = iota + 16
H265_NAL_SPS H265_NAL_SPS
H265_NAL_PPS H265_NAL_PPS
H265_NAL_AUD H265_NAL_AUD
//SEI //SEI
H265_NAL_SEI H265_NAL_TYPE = iota + 19 H265_NAL_SEI H265_NAL_TYPE = iota + 19
H265_NAL_SEI_SUFFIX H265_NAL_SEI_SUFFIX
) )

View file

@ -9,241 +9,241 @@ import "encoding/binary"
// } // }
type H264NaluHdr struct { type H264NaluHdr struct {
Forbidden_zero_bit uint8 Forbidden_zero_bit uint8
Nal_ref_idc uint8 Nal_ref_idc uint8
Nal_unit_type uint8 Nal_unit_type uint8
} }
func (hdr *H264NaluHdr) Decode(bs *BitStream) { func (hdr *H264NaluHdr) Decode(bs *BitStream) {
hdr.Forbidden_zero_bit = bs.GetBit() hdr.Forbidden_zero_bit = bs.GetBit()
hdr.Nal_ref_idc = bs.Uint8(2) hdr.Nal_ref_idc = bs.Uint8(2)
hdr.Nal_unit_type = bs.Uint8(5) hdr.Nal_unit_type = bs.Uint8(5)
} }
type SliceHeader struct { type SliceHeader struct {
First_mb_in_slice uint64 First_mb_in_slice uint64
Slice_type uint64 Slice_type uint64
Pic_parameter_set_id uint64 Pic_parameter_set_id uint64
Frame_num uint64 Frame_num uint64
} }
//调用方根据sps中的log2_max_frame_num_minus4的值来解析Frame_num //调用方根据sps中的log2_max_frame_num_minus4的值来解析Frame_num
func (sh *SliceHeader) Decode(bs *BitStream) { func (sh *SliceHeader) Decode(bs *BitStream) {
sh.First_mb_in_slice = bs.ReadUE() sh.First_mb_in_slice = bs.ReadUE()
sh.Slice_type = bs.ReadUE() sh.Slice_type = bs.ReadUE()
sh.Pic_parameter_set_id = bs.ReadUE() sh.Pic_parameter_set_id = bs.ReadUE()
} }
type SPS struct { type SPS struct {
Profile_idc uint8 Profile_idc uint8
Constraint_set0_flag uint8 Constraint_set0_flag uint8
Constraint_set1_flag uint8 Constraint_set1_flag uint8
Constraint_set2_flag uint8 Constraint_set2_flag uint8
Constraint_set3_flag uint8 Constraint_set3_flag uint8
Constraint_set4_flag uint8 Constraint_set4_flag uint8
Constraint_set5_flag uint8 Constraint_set5_flag uint8
Reserved_zero_2bits uint8 Reserved_zero_2bits uint8
Level_idc uint8 Level_idc uint8
Seq_parameter_set_id uint64 Seq_parameter_set_id uint64
Chroma_format_idc uint64 Chroma_format_idc uint64
Separate_colour_plane_flag uint8 Separate_colour_plane_flag uint8
Bit_depth_luma_minus8 uint64 Bit_depth_luma_minus8 uint64
Bit_depth_chroma_minus8 uint64 Bit_depth_chroma_minus8 uint64
Log2_max_frame_num_minus4 uint64 Log2_max_frame_num_minus4 uint64
Pic_order_cnt_type uint64 Pic_order_cnt_type uint64
Max_num_ref_frames uint64 Max_num_ref_frames uint64
Gaps_in_frame_num_value_allowed_flag uint8 Gaps_in_frame_num_value_allowed_flag uint8
Pic_width_in_mbs_minus1 uint64 Pic_width_in_mbs_minus1 uint64
Pic_height_in_map_units_minus1 uint64 Pic_height_in_map_units_minus1 uint64
Frame_mbs_only_flag uint8 Frame_mbs_only_flag uint8
Direct_8x8_inference_flag uint8 Direct_8x8_inference_flag uint8
Frame_cropping_flag uint8 Frame_cropping_flag uint8
Frame_crop_left_offset uint64 Frame_crop_left_offset uint64
Frame_crop_right_offset uint64 Frame_crop_right_offset uint64
Frame_crop_top_offset uint64 Frame_crop_top_offset uint64
Frame_crop_bottom_offset uint64 Frame_crop_bottom_offset uint64
Vui_parameters_present_flag uint8 Vui_parameters_present_flag uint8
} }
func (sps *SPS) Decode(bs *BitStream) { func (sps *SPS) Decode(bs *BitStream) {
sps.Profile_idc = bs.Uint8(8) sps.Profile_idc = bs.Uint8(8)
sps.Constraint_set0_flag = bs.GetBit() sps.Constraint_set0_flag = bs.GetBit()
sps.Constraint_set1_flag = bs.GetBit() sps.Constraint_set1_flag = bs.GetBit()
sps.Constraint_set2_flag = bs.GetBit() sps.Constraint_set2_flag = bs.GetBit()
sps.Constraint_set3_flag = bs.GetBit() sps.Constraint_set3_flag = bs.GetBit()
sps.Constraint_set4_flag = bs.GetBit() sps.Constraint_set4_flag = bs.GetBit()
sps.Constraint_set5_flag = bs.GetBit() sps.Constraint_set5_flag = bs.GetBit()
sps.Reserved_zero_2bits = bs.Uint8(2) sps.Reserved_zero_2bits = bs.Uint8(2)
sps.Level_idc = bs.Uint8(8) sps.Level_idc = bs.Uint8(8)
sps.Seq_parameter_set_id = bs.ReadUE() sps.Seq_parameter_set_id = bs.ReadUE()
if sps.Profile_idc == 100 || sps.Profile_idc == 110 || if sps.Profile_idc == 100 || sps.Profile_idc == 110 ||
sps.Profile_idc == 122 || sps.Profile_idc == 244 || sps.Profile_idc == 122 || sps.Profile_idc == 244 ||
sps.Profile_idc == 44 || sps.Profile_idc == 83 || sps.Profile_idc == 44 || sps.Profile_idc == 83 ||
sps.Profile_idc == 86 || sps.Profile_idc == 118 || sps.Profile_idc == 128 { sps.Profile_idc == 86 || sps.Profile_idc == 118 || sps.Profile_idc == 128 {
sps.Chroma_format_idc = bs.ReadUE() sps.Chroma_format_idc = bs.ReadUE()
if sps.Chroma_format_idc == 3 { if sps.Chroma_format_idc == 3 {
sps.Separate_colour_plane_flag = bs.Uint8(1) //separate_colour_plane_flag 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_luma_minus8 = bs.ReadUE() //bit_depth_luma_minus8
sps.Bit_depth_chroma_minus8 = bs.ReadUE() //bit_depth_chroma_minus8 sps.Bit_depth_chroma_minus8 = bs.ReadUE() //bit_depth_chroma_minus8
bs.SkipBits(1) //qpprime_y_zero_transform_bypass_flag bs.SkipBits(1) //qpprime_y_zero_transform_bypass_flag
seq_scaling_matrix_present_flag := bs.GetBit() seq_scaling_matrix_present_flag := bs.GetBit()
if seq_scaling_matrix_present_flag == 1 { if seq_scaling_matrix_present_flag == 1 {
//seq_scaling_list_present_flag[i] //seq_scaling_list_present_flag[i]
if sps.Chroma_format_idc == 3 { if sps.Chroma_format_idc == 3 {
bs.SkipBits(12) bs.SkipBits(12)
} else { } else {
bs.SkipBits(8) bs.SkipBits(8)
} }
} }
} }
sps.Log2_max_frame_num_minus4 = bs.ReadUE() sps.Log2_max_frame_num_minus4 = bs.ReadUE()
sps.Pic_order_cnt_type = bs.ReadUE() sps.Pic_order_cnt_type = bs.ReadUE()
if sps.Pic_order_cnt_type == 0 { if sps.Pic_order_cnt_type == 0 {
bs.ReadUE() // log2_max_pic_order_cnt_lsb_minus4 bs.ReadUE() // log2_max_pic_order_cnt_lsb_minus4
} else if sps.Pic_order_cnt_type == 1 { } else if sps.Pic_order_cnt_type == 1 {
bs.SkipBits(1) //delta_pic_order_always_zero_flag bs.SkipBits(1) //delta_pic_order_always_zero_flag
bs.ReadSE() //offset_for_non_ref_pic bs.ReadSE() //offset_for_non_ref_pic
bs.ReadSE() //offset_for_top_to_bottom_field bs.ReadSE() //offset_for_top_to_bottom_field
num_ref_frames_in_pic_order_cnt_cycle := bs.ReadUE() num_ref_frames_in_pic_order_cnt_cycle := bs.ReadUE()
for i := 0; i < int(num_ref_frames_in_pic_order_cnt_cycle); i++ { for i := 0; i < int(num_ref_frames_in_pic_order_cnt_cycle); i++ {
bs.ReadSE() //offset_for_ref_frame bs.ReadSE() //offset_for_ref_frame
} }
} }
sps.Max_num_ref_frames = bs.ReadUE() sps.Max_num_ref_frames = bs.ReadUE()
sps.Gaps_in_frame_num_value_allowed_flag = bs.GetBit() sps.Gaps_in_frame_num_value_allowed_flag = bs.GetBit()
sps.Pic_width_in_mbs_minus1 = bs.ReadUE() sps.Pic_width_in_mbs_minus1 = bs.ReadUE()
sps.Pic_height_in_map_units_minus1 = bs.ReadUE() sps.Pic_height_in_map_units_minus1 = bs.ReadUE()
sps.Frame_mbs_only_flag = bs.GetBit() sps.Frame_mbs_only_flag = bs.GetBit()
if sps.Frame_mbs_only_flag == 0 { if sps.Frame_mbs_only_flag == 0 {
bs.SkipBits(1) // mb_adaptive_frame_field_flag bs.SkipBits(1) // mb_adaptive_frame_field_flag
} }
sps.Direct_8x8_inference_flag = bs.GetBit() sps.Direct_8x8_inference_flag = bs.GetBit()
sps.Frame_cropping_flag = bs.GetBit() sps.Frame_cropping_flag = bs.GetBit()
if sps.Frame_cropping_flag == 1 { if sps.Frame_cropping_flag == 1 {
sps.Frame_crop_left_offset = bs.ReadUE() //frame_crop_left_offset 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_right_offset = bs.ReadUE() //frame_crop_right_offset
sps.Frame_crop_top_offset = bs.ReadUE() //frame_crop_top_offset sps.Frame_crop_top_offset = bs.ReadUE() //frame_crop_top_offset
sps.Frame_crop_bottom_offset = bs.ReadUE() //frame_crop_bottom_offset sps.Frame_crop_bottom_offset = bs.ReadUE() //frame_crop_bottom_offset
} }
sps.Vui_parameters_present_flag = bs.GetBit() sps.Vui_parameters_present_flag = bs.GetBit()
} }
type PPS struct { type PPS struct {
Pic_parameter_set_id uint64 Pic_parameter_set_id uint64
Seq_parameter_set_id uint64 Seq_parameter_set_id uint64
Entropy_coding_mode_flag uint8 Entropy_coding_mode_flag uint8
Bottom_field_pic_order_in_frame_present_flag uint8 Bottom_field_pic_order_in_frame_present_flag uint8
Num_slice_groups_minus1 uint64 Num_slice_groups_minus1 uint64
} }
func (pps *PPS) Decode(bs *BitStream) { func (pps *PPS) Decode(bs *BitStream) {
pps.Pic_parameter_set_id = bs.ReadUE() pps.Pic_parameter_set_id = bs.ReadUE()
pps.Seq_parameter_set_id = bs.ReadUE() pps.Seq_parameter_set_id = bs.ReadUE()
pps.Entropy_coding_mode_flag = bs.GetBit() pps.Entropy_coding_mode_flag = bs.GetBit()
pps.Bottom_field_pic_order_in_frame_present_flag = bs.GetBit() pps.Bottom_field_pic_order_in_frame_present_flag = bs.GetBit()
pps.Num_slice_groups_minus1 = bs.ReadUE() pps.Num_slice_groups_minus1 = bs.ReadUE()
} }
type SEIReaderWriter interface { type SEIReaderWriter interface {
Read(size uint16, bs *BitStream) Read(size uint16, bs *BitStream)
Write(bsw *BitStreamWriter) Write(bsw *BitStreamWriter)
} }
type UserDataUnregistered struct { type UserDataUnregistered struct {
UUID []byte UUID []byte
UserData []byte UserData []byte
} }
func (udu *UserDataUnregistered) Read(size uint16, bs *BitStream) { func (udu *UserDataUnregistered) Read(size uint16, bs *BitStream) {
udu.UUID = bs.GetBytes(16) udu.UUID = bs.GetBytes(16)
udu.UserData = bs.GetBytes(int(size - 16)) udu.UserData = bs.GetBytes(int(size - 16))
} }
func (udu *UserDataUnregistered) Write(bsw *BitStreamWriter) { func (udu *UserDataUnregistered) Write(bsw *BitStreamWriter) {
bsw.PutBytes(udu.UUID) bsw.PutBytes(udu.UUID)
bsw.PutBytes(udu.UserData) bsw.PutBytes(udu.UserData)
} }
type SEI struct { type SEI struct {
PayloadType uint16 PayloadType uint16
PayloadSize uint16 PayloadSize uint16
Sei_payload SEIReaderWriter Sei_payload SEIReaderWriter
} }
func (sei *SEI) Decode(bs *BitStream) { func (sei *SEI) Decode(bs *BitStream) {
for bs.NextBits(8) == 0xFF { for bs.NextBits(8) == 0xFF {
sei.PayloadType += 255 sei.PayloadType += 255
} }
sei.PayloadType += uint16(bs.Uint8(8)) sei.PayloadType += uint16(bs.Uint8(8))
for bs.NextBits(8) == 0xFF { for bs.NextBits(8) == 0xFF {
sei.PayloadSize += 255 sei.PayloadSize += 255
} }
sei.PayloadSize += uint16(bs.Uint8(8)) sei.PayloadSize += uint16(bs.Uint8(8))
if sei.PayloadType == 5 { if sei.PayloadType == 5 {
sei.Sei_payload = new(UserDataUnregistered) sei.Sei_payload = new(UserDataUnregistered)
sei.Sei_payload.Read(sei.PayloadSize, bs) sei.Sei_payload.Read(sei.PayloadSize, bs)
} }
} }
func (sei *SEI) Encode(bsw *BitStreamWriter) []byte { func (sei *SEI) Encode(bsw *BitStreamWriter) []byte {
payloadType := sei.PayloadType payloadType := sei.PayloadType
payloadSize := sei.PayloadSize payloadSize := sei.PayloadSize
for payloadType >= 0xFF { for payloadType >= 0xFF {
bsw.PutByte(0xFF) bsw.PutByte(0xFF)
payloadType -= 255 payloadType -= 255
} }
bsw.PutByte(uint8(payloadType)) bsw.PutByte(uint8(payloadType))
for payloadSize >= 0xFF { for payloadSize >= 0xFF {
bsw.PutByte(0xFF) bsw.PutByte(0xFF)
payloadSize -= 255 payloadSize -= 255
} }
bsw.PutByte(uint8(payloadSize)) bsw.PutByte(uint8(payloadSize))
sei.Sei_payload.Write(bsw) sei.Sei_payload.Write(bsw)
return bsw.Bits() return bsw.Bits()
} }
func GetSPSIdWithStartCode(sps []byte) uint64 { func GetSPSIdWithStartCode(sps []byte) uint64 {
start, sc := FindStartCode(sps, 0) start, sc := FindStartCode(sps, 0)
return GetSPSId(sps[start+int(sc):]) return GetSPSId(sps[start+int(sc):])
} }
func GetSPSId(sps []byte) uint64 { func GetSPSId(sps []byte) uint64 {
sps = sps[1:] sps = sps[1:]
bs := NewBitStream(sps) bs := NewBitStream(sps)
bs.SkipBits(24) bs.SkipBits(24)
return bs.ReadUE() return bs.ReadUE()
} }
func GetPPSIdWithStartCode(pps []byte) uint64 { func GetPPSIdWithStartCode(pps []byte) uint64 {
start, sc := FindStartCode(pps, 0) start, sc := FindStartCode(pps, 0)
return GetPPSId(pps[start+int(sc):]) return GetPPSId(pps[start+int(sc):])
} }
func GetPPSId(pps []byte) uint64 { func GetPPSId(pps []byte) uint64 {
pps = pps[1:] pps = pps[1:]
bs := NewBitStream(pps) bs := NewBitStream(pps)
return bs.ReadUE() return bs.ReadUE()
} }
//https://stackoverflow.com/questions/12018535/get-the-width-height-of-the-video-from-h-264-nalu //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 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); //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) { func GetH264Resolution(sps []byte) (width uint32, height uint32) {
start, sc := FindStartCode(sps, 0) start, sc := FindStartCode(sps, 0)
bs := NewBitStream(sps[start+int(sc)+1:]) bs := NewBitStream(sps[start+int(sc)+1:])
var s SPS var s SPS
s.Decode(bs) s.Decode(bs)
widthInSample := (uint32(s.Pic_width_in_mbs_minus1) + 1) * 16 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 widthCrop := uint32(s.Frame_crop_left_offset)*2 - uint32(s.Frame_crop_right_offset)*2
width = widthInSample - widthCrop width = widthInSample - widthCrop
heightInSample := ((2 - uint32(s.Frame_mbs_only_flag)) * (uint32(s.Pic_height_in_map_units_minus1) + 1) * 16) 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 heightCrop := uint32(s.Frame_crop_bottom_offset)*2 - uint32(s.Frame_crop_top_offset)*2
height = heightInSample - heightCrop height = heightInSample - heightCrop
return return
} }
// aligned(8) class AVCDecoderConfigurationRecord { // aligned(8) class AVCDecoderConfigurationRecord {
@ -302,95 +302,95 @@ func GetH264Resolution(sps []byte) (width uint32, height uint32) {
// variable PPS NALU data // variable PPS NALU data
func CreateH264AVCCExtradata(spss [][]byte, ppss [][]byte) []byte { func CreateH264AVCCExtradata(spss [][]byte, ppss [][]byte) []byte {
extradata := make([]byte, 6, 256) extradata := make([]byte, 6, 256)
for i, sps := range spss { for i, sps := range spss {
start, sc := FindStartCode(sps, 0) start, sc := FindStartCode(sps, 0)
spss[i] = sps[start+int(sc):] spss[i] = sps[start+int(sc):]
} }
for i, pps := range ppss { for i, pps := range ppss {
start, sc := FindStartCode(pps, 0) start, sc := FindStartCode(pps, 0)
ppss[i] = pps[start+int(sc):] ppss[i] = pps[start+int(sc):]
} }
extradata[0] = 0x01 extradata[0] = 0x01
extradata[1] = spss[0][1] extradata[1] = spss[0][1]
extradata[2] = spss[0][2] extradata[2] = spss[0][2]
extradata[3] = spss[0][3] extradata[3] = spss[0][3]
extradata[4] = 0xFF extradata[4] = 0xFF
extradata[5] = 0xE0 | uint8(len(spss)) extradata[5] = 0xE0 | uint8(len(spss))
for _, sps := range spss { for _, sps := range spss {
spssize := make([]byte, 2) spssize := make([]byte, 2)
binary.BigEndian.PutUint16(spssize, uint16(len(sps))) binary.BigEndian.PutUint16(spssize, uint16(len(sps)))
extradata = append(extradata, spssize...) extradata = append(extradata, spssize...)
extradata = append(extradata, sps...) extradata = append(extradata, sps...)
} }
extradata = append(extradata, uint8(len(ppss))) extradata = append(extradata, uint8(len(ppss)))
for _, pps := range ppss { for _, pps := range ppss {
ppssize := make([]byte, 2) ppssize := make([]byte, 2)
binary.BigEndian.PutUint16(ppssize, uint16(len(pps))) binary.BigEndian.PutUint16(ppssize, uint16(len(pps)))
extradata = append(extradata, ppssize...) extradata = append(extradata, ppssize...)
extradata = append(extradata, pps...) extradata = append(extradata, pps...)
} }
var h264sps SPS var h264sps SPS
h264sps.Decode(NewBitStream(spss[0][1:])) h264sps.Decode(NewBitStream(spss[0][1:]))
if h264sps.Profile_idc == 100 || if h264sps.Profile_idc == 100 ||
h264sps.Profile_idc == 110 || h264sps.Profile_idc == 110 ||
h264sps.Profile_idc == 122 || h264sps.Profile_idc == 122 ||
h264sps.Profile_idc == 144 { h264sps.Profile_idc == 144 {
tmp := make([]byte, 4) tmp := make([]byte, 4)
tmp[0] = 0xFC | uint8(h264sps.Chroma_format_idc&0x03) tmp[0] = 0xFC | uint8(h264sps.Chroma_format_idc&0x03)
tmp[1] = 0xF8 | uint8(h264sps.Bit_depth_luma_minus8&0x07) tmp[1] = 0xF8 | uint8(h264sps.Bit_depth_luma_minus8&0x07)
tmp[2] = 0xF8 | uint8(h264sps.Bit_depth_chroma_minus8&0x07) tmp[2] = 0xF8 | uint8(h264sps.Bit_depth_chroma_minus8&0x07)
tmp[3] = 0 tmp[3] = 0
extradata = append(extradata, tmp...) extradata = append(extradata, tmp...)
} }
return extradata return extradata
} }
func CovertExtradata(extraData []byte) ([][]byte, [][]byte) { func CovertExtradata(extraData []byte) ([][]byte, [][]byte) {
spsnum := extraData[5] & 0x1F spsnum := extraData[5] & 0x1F
spss := make([][]byte, spsnum) spss := make([][]byte, spsnum)
offset := 6 offset := 6
for i := 0; i < int(spsnum); i++ { for i := 0; i < int(spsnum); i++ {
spssize := binary.BigEndian.Uint16(extraData[offset:]) spssize := binary.BigEndian.Uint16(extraData[offset:])
sps := make([]byte, spssize+4) sps := make([]byte, spssize+4)
copy(sps, []byte{0x00, 0x00, 0x00, 0x01}) copy(sps, []byte{0x00, 0x00, 0x00, 0x01})
copy(sps[4:], extraData[offset+2:offset+2+int(spssize)]) copy(sps[4:], extraData[offset+2:offset+2+int(spssize)])
offset += 2 + int(spssize) offset += 2 + int(spssize)
spss[i] = sps spss[i] = sps
} }
ppsnum := extraData[offset] ppsnum := extraData[offset]
ppss := make([][]byte, ppsnum) ppss := make([][]byte, ppsnum)
offset++ offset++
for i := 0; i < int(ppsnum); i++ { for i := 0; i < int(ppsnum); i++ {
ppssize := binary.BigEndian.Uint16(extraData[offset:]) ppssize := binary.BigEndian.Uint16(extraData[offset:])
pps := make([]byte, ppssize+4) pps := make([]byte, ppssize+4)
copy(pps, []byte{0x00, 0x00, 0x00, 0x01}) copy(pps, []byte{0x00, 0x00, 0x00, 0x01})
copy(pps[4:], extraData[offset+2:offset+2+int(ppssize)]) copy(pps[4:], extraData[offset+2:offset+2+int(ppssize)])
offset += 2 + int(ppssize) offset += 2 + int(ppssize)
ppss[i] = pps ppss[i] = pps
} }
return spss, ppss return spss, ppss
} }
func ConvertAnnexBToAVCC(annexb []byte) []byte { func ConvertAnnexBToAVCC(annexb []byte) []byte {
start, sc := FindStartCode(annexb, 0) start, sc := FindStartCode(annexb, 0)
if sc == START_CODE_4 { if sc == START_CODE_4 {
binary.BigEndian.PutUint32(annexb[start:], uint32(len(annexb)-4)) binary.BigEndian.PutUint32(annexb[start:], uint32(len(annexb)-4))
return annexb return annexb
} else { } else {
avcc := make([]byte, 1+len(annexb)) avcc := make([]byte, 1+len(annexb))
binary.BigEndian.PutUint32(avcc, uint32(len(annexb)-3)) binary.BigEndian.PutUint32(avcc, uint32(len(annexb)-3))
copy(avcc[4:], annexb[start+3:]) copy(avcc[4:], annexb[start+3:])
return avcc return avcc
} }
} }
func CovertAVCCToAnnexB(avcc []byte) { func CovertAVCCToAnnexB(avcc []byte) {
avcc[0] = 0x00 avcc[0] = 0x00
avcc[1] = 0x00 avcc[1] = 0x00
avcc[2] = 0x00 avcc[2] = 0x00
avcc[3] = 0x01 avcc[3] = 0x01
} }

File diff suppressed because it is too large Load diff

View file

@ -1,8 +1,8 @@
package codec package codec
import ( import (
"encoding/binary" "encoding/binary"
"errors" "errors"
) )
// rfc6716 https://datatracker.ietf.org/doc/html/rfc6716 // rfc6716 https://datatracker.ietf.org/doc/html/rfc6716
@ -157,169 +157,169 @@ import (
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
var ( var (
/// 10ms,20ms,40ms,60ms, samplerate 48000 /// 10ms,20ms,40ms,60ms, samplerate 48000
// sample num per millisecond // sample num per millisecond
// 48000 / 1000ms * 10 = 480 ... // 48000 / 1000ms * 10 = 480 ...
SLKOpusSampleSize [4]int = [4]int{480, 960, 1920, 2880} SLKOpusSampleSize [4]int = [4]int{480, 960, 1920, 2880}
HybridOpusSampleSize [4]int = [4]int{480, 960} HybridOpusSampleSize [4]int = [4]int{480, 960}
CELTOpusSampleSize [4]int = [4]int{120, 210, 480, 960} CELTOpusSampleSize [4]int = [4]int{120, 210, 480, 960}
) )
func OpusPacketDuration(packet []byte) uint64 { func OpusPacketDuration(packet []byte) uint64 {
config := int(packet[0] >> 3) config := int(packet[0] >> 3)
code := packet[0] & 0x03 code := packet[0] & 0x03
frameCount := 0 frameCount := 0
var duration uint64 var duration uint64
if code == 0 { if code == 0 {
frameCount = 1 frameCount = 1
} else if code == 1 || code == 2 { } else if code == 1 || code == 2 {
frameCount = 2 frameCount = 2
} else if code == 3 { } else if code == 3 {
frameCount = int(packet[1] & 0x1F) frameCount = int(packet[1] & 0x1F)
} else { } else {
panic("code must <= 3") panic("code must <= 3")
} }
switch { switch {
case config >= 0 && config < 12: case config >= 0 && config < 12:
duration = uint64(frameCount * SLKOpusSampleSize[config%4]) duration = uint64(frameCount * SLKOpusSampleSize[config%4])
case config >= 12 && config < 16: case config >= 12 && config < 16:
duration = uint64(frameCount * HybridOpusSampleSize[config%2]) duration = uint64(frameCount * HybridOpusSampleSize[config%2])
case config >= 16 && config < 32: case config >= 16 && config < 32:
duration = uint64(frameCount * CELTOpusSampleSize[config%4]) duration = uint64(frameCount * CELTOpusSampleSize[config%4])
default: default:
panic("unkown opus config") panic("unkown opus config")
} }
return duration return duration
} }
//ffmpeg opus.h OpusPacket //ffmpeg opus.h OpusPacket
type OpusPacket struct { type OpusPacket struct {
Code int Code int
Config int Config int
Stereo int Stereo int
Vbr int Vbr int
FrameCount int FrameCount int
FrameLen []uint16 FrameLen []uint16
Frame []byte Frame []byte
Duration uint64 Duration uint64
} }
func DecodeOpusPacket(packet []byte) *OpusPacket { func DecodeOpusPacket(packet []byte) *OpusPacket {
pkt := &OpusPacket{} pkt := &OpusPacket{}
pkt.Code = int(packet[0] & 0x03) pkt.Code = int(packet[0] & 0x03)
pkt.Stereo = int((packet[0] >> 2) & 0x01) pkt.Stereo = int((packet[0] >> 2) & 0x01)
pkt.Config = int(packet[0] >> 3) pkt.Config = int(packet[0] >> 3)
switch pkt.Code { switch pkt.Code {
case 0: case 0:
pkt.FrameCount = 1 pkt.FrameCount = 1
pkt.FrameLen = make([]uint16, 1) pkt.FrameLen = make([]uint16, 1)
pkt.FrameLen[0] = uint16(len(packet) - 1) pkt.FrameLen[0] = uint16(len(packet) - 1)
pkt.Frame = packet[1:] pkt.Frame = packet[1:]
case 1: case 1:
pkt.FrameCount = 2 pkt.FrameCount = 2
pkt.FrameLen = make([]uint16, 1) pkt.FrameLen = make([]uint16, 1)
pkt.FrameLen[0] = uint16(len(packet)-1) / 2 pkt.FrameLen[0] = uint16(len(packet)-1) / 2
pkt.Frame = packet[1:] pkt.Frame = packet[1:]
case 2: case 2:
pkt.FrameCount = 2 pkt.FrameCount = 2
hdr := 1 hdr := 1
N1 := int(packet[1]) N1 := int(packet[1])
if N1 >= 252 { if N1 >= 252 {
N1 = N1 + int(packet[2]*4) N1 = N1 + int(packet[2]*4)
hdr = 2 hdr = 2
} }
pkt.FrameLen = make([]uint16, 2) pkt.FrameLen = make([]uint16, 2)
pkt.FrameLen[0] = uint16(N1) pkt.FrameLen[0] = uint16(N1)
pkt.FrameLen[1] = uint16(len(packet)-hdr) - uint16(N1) pkt.FrameLen[1] = uint16(len(packet)-hdr) - uint16(N1)
case 3: case 3:
hdr := 2 hdr := 2
pkt.Vbr = int(packet[1] >> 7) pkt.Vbr = int(packet[1] >> 7)
padding := packet[1] >> 6 padding := packet[1] >> 6
pkt.FrameCount = int(packet[1] & 0x1F) pkt.FrameCount = int(packet[1] & 0x1F)
paddingLen := 0 paddingLen := 0
if padding == 1 { if padding == 1 {
for packet[hdr] == 255 { for packet[hdr] == 255 {
paddingLen += 254 paddingLen += 254
hdr++ hdr++
} }
paddingLen += int(packet[hdr]) paddingLen += int(packet[hdr])
} }
if pkt.Vbr == 0 { if pkt.Vbr == 0 {
pkt.FrameLen = make([]uint16, 1) pkt.FrameLen = make([]uint16, 1)
pkt.FrameLen[0] = uint16(len(packet)-hdr-paddingLen) / uint16(pkt.FrameCount) pkt.FrameLen[0] = uint16(len(packet)-hdr-paddingLen) / uint16(pkt.FrameCount)
pkt.Frame = packet[hdr : hdr+int(pkt.FrameLen[0]*uint16(pkt.FrameCount))] pkt.Frame = packet[hdr : hdr+int(pkt.FrameLen[0]*uint16(pkt.FrameCount))]
} else { } else {
n := 0 n := 0
for i := 0; i < int(pkt.FrameCount)-1; i++ { for i := 0; i < int(pkt.FrameCount)-1; i++ {
N1 := int(packet[hdr]) N1 := int(packet[hdr])
hdr += 1 hdr += 1
if N1 >= 252 { if N1 >= 252 {
N1 = N1 + int(packet[hdr]*4) N1 = N1 + int(packet[hdr]*4)
hdr += 1 hdr += 1
} }
n += N1 n += N1
pkt.FrameLen = append(pkt.FrameLen, uint16(N1)) pkt.FrameLen = append(pkt.FrameLen, uint16(N1))
} }
lastFrameLen := len(packet) - hdr - paddingLen - n lastFrameLen := len(packet) - hdr - paddingLen - n
pkt.FrameLen = append(pkt.FrameLen, uint16(lastFrameLen)) pkt.FrameLen = append(pkt.FrameLen, uint16(lastFrameLen))
pkt.Frame = packet[hdr : hdr+n+lastFrameLen] pkt.Frame = packet[hdr : hdr+n+lastFrameLen]
} }
default: default:
panic("Error C must <= 3") panic("Error C must <= 3")
} }
OpusPacketDuration(packet) OpusPacketDuration(packet)
return pkt return pkt
} }
const ( const (
LEFT_CHANNEL = 0 LEFT_CHANNEL = 0
RIGHT_CHANNEL = 1 RIGHT_CHANNEL = 1
) )
var ( var (
vorbisChanLayoutOffset [8][8]byte = [8][8]byte{ vorbisChanLayoutOffset [8][8]byte = [8][8]byte{
{0}, {0},
{0, 1}, {0, 1},
{0, 2, 1}, {0, 2, 1},
{0, 1, 2, 3}, {0, 1, 2, 3},
{0, 2, 1, 3, 4}, {0, 2, 1, 3, 4},
{0, 2, 1, 5, 3, 4}, {0, 2, 1, 5, 3, 4},
{0, 2, 1, 6, 5, 3, 4}, {0, 2, 1, 6, 5, 3, 4},
{0, 2, 1, 7, 5, 6, 3, 4}, {0, 2, 1, 7, 5, 6, 3, 4},
} }
) )
type ChannelOrder func(channels int, idx int) int type ChannelOrder func(channels int, idx int) int
func defalutOrder(channels int, idx int) int { func defalutOrder(channels int, idx int) int {
return idx return idx
} }
func vorbisOrder(channels int, idx int) int { func vorbisOrder(channels int, idx int) int {
return int(vorbisChanLayoutOffset[channels-1][idx]) return int(vorbisChanLayoutOffset[channels-1][idx])
} }
type ChannelMap struct { type ChannelMap struct {
StreamIdx int StreamIdx int
ChannelIdx int ChannelIdx int
Silence bool Silence bool
Copy bool Copy bool
CopyFrom int CopyFrom int
} }
type OpusContext struct { type OpusContext struct {
Preskip int Preskip int
SampleRate int SampleRate int
ChannelCount int ChannelCount int
StreamCount int StreamCount int
StereoStreamCount int StereoStreamCount int
OutputGain uint16 OutputGain uint16
MapType uint8 MapType uint8
ChannelMaps []ChannelMap ChannelMaps []ChannelMap
} }
// opus ID Head // opus ID Head
@ -348,83 +348,83 @@ type OpusContext struct {
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// //
func (ctx *OpusContext) ParseExtranData(extraData []byte) error { func (ctx *OpusContext) ParseExtranData(extraData []byte) error {
if string(extraData[0:8]) != "OpusHead" { if string(extraData[0:8]) != "OpusHead" {
return errors.New("magic signature must equal OpusHead") return errors.New("magic signature must equal OpusHead")
} }
_ = extraData[8] // version _ = extraData[8] // version
ctx.ChannelCount = int(extraData[9]) ctx.ChannelCount = int(extraData[9])
ctx.Preskip = int(binary.LittleEndian.Uint16(extraData[10:])) ctx.Preskip = int(binary.LittleEndian.Uint16(extraData[10:]))
ctx.SampleRate = int(binary.LittleEndian.Uint32(extraData[12:])) ctx.SampleRate = int(binary.LittleEndian.Uint32(extraData[12:]))
ctx.OutputGain = binary.LittleEndian.Uint16(extraData[16:]) ctx.OutputGain = binary.LittleEndian.Uint16(extraData[16:])
ctx.MapType = extraData[18] ctx.MapType = extraData[18]
var channel []byte var channel []byte
var order ChannelOrder var order ChannelOrder
if ctx.MapType == 0 { if ctx.MapType == 0 {
ctx.StreamCount = 1 ctx.StreamCount = 1
ctx.StereoStreamCount = ctx.ChannelCount - 1 ctx.StereoStreamCount = ctx.ChannelCount - 1
channel = []byte{0, 1} channel = []byte{0, 1}
order = defalutOrder order = defalutOrder
} else if ctx.MapType == 1 || ctx.MapType == 2 || ctx.MapType == 255 { } else if ctx.MapType == 1 || ctx.MapType == 2 || ctx.MapType == 255 {
ctx.StreamCount = int(extraData[19]) ctx.StreamCount = int(extraData[19])
ctx.StereoStreamCount = int(extraData[20]) ctx.StereoStreamCount = int(extraData[20])
if ctx.MapType == 1 { if ctx.MapType == 1 {
channel = extraData[21 : 21+ctx.ChannelCount] channel = extraData[21 : 21+ctx.ChannelCount]
order = vorbisOrder order = vorbisOrder
} }
} else { } else {
return errors.New("unsupport map type 255") return errors.New("unsupport map type 255")
} }
for i := 0; i < ctx.ChannelCount; i++ { for i := 0; i < ctx.ChannelCount; i++ {
cm := ChannelMap{} cm := ChannelMap{}
index := channel[order(ctx.ChannelCount, i)] index := channel[order(ctx.ChannelCount, i)]
if index == 255 { if index == 255 {
cm.Silence = true cm.Silence = true
continue continue
} else if index > byte(ctx.StereoStreamCount)+byte(ctx.StreamCount) { } else if index > byte(ctx.StereoStreamCount)+byte(ctx.StreamCount) {
return errors.New("index must < (streamcount + stereo streamcount)") return errors.New("index must < (streamcount + stereo streamcount)")
} }
for j := 0; j < i; j++ { for j := 0; j < i; j++ {
if channel[order(ctx.ChannelCount, i)] == index { if channel[order(ctx.ChannelCount, i)] == index {
cm.Copy = true cm.Copy = true
cm.CopyFrom = j cm.CopyFrom = j
break break
} }
} }
if int(index) < 2*ctx.StereoStreamCount { if int(index) < 2*ctx.StereoStreamCount {
cm.StreamIdx = int(index) / 2 cm.StreamIdx = int(index) / 2
if index&1 == 0 { if index&1 == 0 {
cm.ChannelIdx = LEFT_CHANNEL cm.ChannelIdx = LEFT_CHANNEL
} else { } else {
cm.ChannelIdx = RIGHT_CHANNEL cm.ChannelIdx = RIGHT_CHANNEL
} }
} else { } else {
cm.StreamIdx = int(index) - ctx.StereoStreamCount cm.StreamIdx = int(index) - ctx.StereoStreamCount
cm.ChannelIdx = 0 cm.ChannelIdx = 0
} }
ctx.ChannelMaps = append(ctx.ChannelMaps, cm) ctx.ChannelMaps = append(ctx.ChannelMaps, cm)
} }
return nil return nil
} }
func (ctx *OpusContext) WriteOpusExtraData() []byte { func (ctx *OpusContext) WriteOpusExtraData() []byte {
extraData := make([]byte, 19) extraData := make([]byte, 19)
copy(extraData, string("OpusHead")) copy(extraData, string("OpusHead"))
extraData[8] = 0x01 extraData[8] = 0x01
extraData[9] = byte(ctx.ChannelCount) extraData[9] = byte(ctx.ChannelCount)
binary.LittleEndian.PutUint16(extraData[10:], uint16(ctx.Preskip)) binary.LittleEndian.PutUint16(extraData[10:], uint16(ctx.Preskip))
binary.LittleEndian.PutUint32(extraData[12:], uint32(ctx.SampleRate)) binary.LittleEndian.PutUint32(extraData[12:], uint32(ctx.SampleRate))
return extraData return extraData
} }
func WriteDefaultOpusExtraData() []byte { func WriteDefaultOpusExtraData() []byte {
return []byte{ return []byte{
'O', 'p', 'u', 's', 'H', 'e', 'a', 'd', 'O', 'p', 'u', 's', 'H', 'e', 'a', 'd',
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
} }
} }

View file

@ -5,253 +5,253 @@ import "fmt"
type START_CODE_TYPE int type START_CODE_TYPE int
const ( const (
START_CODE_3 START_CODE_TYPE = 3 START_CODE_3 START_CODE_TYPE = 3
START_CODE_4 = 4 START_CODE_4 = 4
) )
func FindStartCode(nalu []byte, offset int) (int, START_CODE_TYPE) { func FindStartCode(nalu []byte, offset int) (int, START_CODE_TYPE) {
for i := offset; i < len(nalu)-4; i++ { for i := offset; i < len(nalu)-4; i++ {
if nalu[i] == 0x00 && nalu[i+1] == 0x00 { if nalu[i] == 0x00 && nalu[i+1] == 0x00 {
if nalu[i+2] == 0x01 { if nalu[i+2] == 0x01 {
return i, START_CODE_3 return i, START_CODE_3
} else if nalu[i+2] == 0x00 && nalu[i+3] == 0x01 { } else if nalu[i+2] == 0x00 && nalu[i+3] == 0x01 {
return i, START_CODE_4 return i, START_CODE_4
} }
} }
} }
return -1, START_CODE_3 return -1, START_CODE_3
} }
func FindSyncword(aac []byte, offset int) int { func FindSyncword(aac []byte, offset int) int {
for i := offset; i < len(aac); i++ { for i := offset; i < len(aac); i++ {
if aac[i] == 0xFF && aac[i+1]&0xF0 == 0xF0 { if aac[i] == 0xFF && aac[i+1]&0xF0 == 0xF0 {
return i return i
} }
} }
return -1 return -1
} }
func SplitFrame(frames []byte, onFrame func(nalu []byte) bool) { func SplitFrame(frames []byte, onFrame func(nalu []byte) bool) {
beg, sc := FindStartCode(frames, 0) beg, sc := FindStartCode(frames, 0)
for beg >= 0 { for beg >= 0 {
end, sc2 := FindStartCode(frames, beg+int(sc)) end, sc2 := FindStartCode(frames, beg+int(sc))
if end == -1 { if end == -1 {
if onFrame != nil { if onFrame != nil {
onFrame(frames[beg+int(sc):]) onFrame(frames[beg+int(sc):])
} }
break break
} }
if onFrame != nil && onFrame(frames[beg+int(sc):end]) == false { if onFrame != nil && onFrame(frames[beg+int(sc):end]) == false {
break break
} }
beg = end beg = end
sc = sc2 sc = sc2
} }
} }
func SplitFrameWithStartCode(frames []byte, onFrame func(nalu []byte) bool) { func SplitFrameWithStartCode(frames []byte, onFrame func(nalu []byte) bool) {
beg, sc := FindStartCode(frames, 0) beg, sc := FindStartCode(frames, 0)
for beg >= 0 { for beg >= 0 {
end, sc2 := FindStartCode(frames, beg+int(sc)) end, sc2 := FindStartCode(frames, beg+int(sc))
if end == -1 { if end == -1 {
if onFrame != nil { if onFrame != nil {
onFrame(frames[beg:]) onFrame(frames[beg:])
} }
break break
} }
if onFrame != nil && onFrame(frames[beg:end]) == false { if onFrame != nil && onFrame(frames[beg:end]) == false {
break break
} }
beg = end beg = end
sc = sc2 sc = sc2
} }
} }
func SplitAACFrame(frames []byte, onFrame func(aac []byte)) { func SplitAACFrame(frames []byte, onFrame func(aac []byte)) {
var adts ADTS_Frame_Header var adts ADTS_Frame_Header
start := FindSyncword(frames, 0) start := FindSyncword(frames, 0)
for start >= 0 { for start >= 0 {
adts.Decode(frames[start:]) adts.Decode(frames[start:])
onFrame(frames[start : start+int(adts.Variable_Header.Frame_length)]) onFrame(frames[start : start+int(adts.Variable_Header.Frame_length)])
start = FindSyncword(frames, start+int(adts.Variable_Header.Frame_length)) start = FindSyncword(frames, start+int(adts.Variable_Header.Frame_length))
} }
} }
func H264NaluType(h264 []byte) H264_NAL_TYPE { func H264NaluType(h264 []byte) H264_NAL_TYPE {
loc, sc := FindStartCode(h264, 0) loc, sc := FindStartCode(h264, 0)
return H264_NAL_TYPE(h264[loc+int(sc)] & 0x1F) return H264_NAL_TYPE(h264[loc+int(sc)] & 0x1F)
} }
func H264NaluTypeWithoutStartCode(h264 []byte) H264_NAL_TYPE { 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 { func H265NaluType(h265 []byte) H265_NAL_TYPE {
loc, sc := FindStartCode(h265, 0) loc, sc := FindStartCode(h265, 0)
return H265_NAL_TYPE((h265[loc+int(sc)] >> 1) & 0x3F) return H265_NAL_TYPE((h265[loc+int(sc)] >> 1) & 0x3F)
} }
func H265NaluTypeWithoutStartCode(h265 []byte) H265_NAL_TYPE { 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 { func GetH264FirstMbInSlice(nalu []byte) uint64 {
start, sc := FindStartCode(nalu, 0) start, sc := FindStartCode(nalu, 0)
bs := NewBitStream(nalu[start+int(sc)+1:]) bs := NewBitStream(nalu[start+int(sc)+1:])
sliceHdr := &SliceHeader{} sliceHdr := &SliceHeader{}
sliceHdr.Decode(bs) sliceHdr.Decode(bs)
return sliceHdr.First_mb_in_slice return sliceHdr.First_mb_in_slice
} }
func GetH265FirstMbInSlice(nalu []byte) uint64 { func GetH265FirstMbInSlice(nalu []byte) uint64 {
start, sc := FindStartCode(nalu, 0) start, sc := FindStartCode(nalu, 0)
bs := NewBitStream(nalu[start+int(sc)+2:]) bs := NewBitStream(nalu[start+int(sc)+2:])
sliceHdr := &SliceHeader{} sliceHdr := &SliceHeader{}
sliceHdr.Decode(bs) sliceHdr.Decode(bs)
return sliceHdr.First_mb_in_slice return sliceHdr.First_mb_in_slice
} }
func IsH264IDRFrame(h264 []byte) bool { func IsH264IDRFrame(h264 []byte) bool {
ret := false ret := false
onnalu := func(nalu []byte) bool { onnalu := func(nalu []byte) bool {
nal_type := H264NaluTypeWithoutStartCode(nalu) nal_type := H264NaluTypeWithoutStartCode(nalu)
if nal_type < 5 { if nal_type < 5 {
return false return false
} else if nal_type == 5 { } else if nal_type == 5 {
ret = true ret = true
return false return false
} else { } else {
return true return true
} }
} }
SplitFrame(h264, onnalu) SplitFrame(h264, onnalu)
return ret return ret
} }
func IsH264VCLNaluType(nal_type H264_NAL_TYPE) bool { func IsH264VCLNaluType(nal_type H264_NAL_TYPE) bool {
if nal_type <= H264_NAL_I_SLICE && nal_type > H264_NAL_RESERVED { if nal_type <= H264_NAL_I_SLICE && nal_type > H264_NAL_RESERVED {
return true return true
} }
return false return false
} }
func IsH265VCLNaluType(nal_type H265_NAL_TYPE) bool { func IsH265VCLNaluType(nal_type H265_NAL_TYPE) bool {
if (nal_type <= H265_NAL_SLICE_CRA && nal_type >= H265_NAL_SLICE_BLA_W_LP) || 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) { (nal_type <= H265_NAL_SLICE_RASL_R && nal_type >= H265_NAL_Slice_TRAIL_N) {
return true return true
} }
return false return false
} }
func IsH265IDRFrame(h265 []byte) bool { func IsH265IDRFrame(h265 []byte) bool {
ret := false ret := false
onnalu := func(nalu []byte) bool { onnalu := func(nalu []byte) bool {
nal_type := H264NaluTypeWithoutStartCode(nalu) nal_type := H264NaluTypeWithoutStartCode(nalu)
if nal_type <= 9 && nal_type >= 0 { if nal_type <= 9 && nal_type >= 0 {
return false return false
} else if nal_type >= 16 && nal_type <= 21 { } else if nal_type >= 16 && nal_type <= 21 {
ret = true ret = true
return false return false
} else { } else {
return true return true
} }
} }
SplitFrame(h265, onnalu) SplitFrame(h265, onnalu)
return ret return ret
} }
func Max(x, y int) int { func Max(x, y int) int {
if x > y { if x > y {
return x return x
} else { } else {
return y return y
} }
} }
func Min(x, y int) int { func Min(x, y int) int {
if x > y { if x > y {
return y return y
} else { } else {
return x return x
} }
} }
func ShowPacketHexdump(data []byte) { func ShowPacketHexdump(data []byte) {
for k := 0; k < len(data); k++ { for k := 0; k < len(data); k++ {
if k%8 == 0 && k != 0 { if k%8 == 0 && k != 0 {
fmt.Printf("\n") fmt.Printf("\n")
} }
fmt.Printf("%02x ", data[k]) fmt.Printf("%02x ", data[k])
} }
fmt.Printf("\n") fmt.Printf("\n")
} }
var crc32table [256]uint32 = [256]uint32{ var crc32table [256]uint32 = [256]uint32{
0x00000000, 0xB71DC104, 0x6E3B8209, 0xD926430D, 0xDC760413, 0x6B6BC517, 0x00000000, 0xB71DC104, 0x6E3B8209, 0xD926430D, 0xDC760413, 0x6B6BC517,
0xB24D861A, 0x0550471E, 0xB8ED0826, 0x0FF0C922, 0xD6D68A2F, 0x61CB4B2B, 0xB24D861A, 0x0550471E, 0xB8ED0826, 0x0FF0C922, 0xD6D68A2F, 0x61CB4B2B,
0x649B0C35, 0xD386CD31, 0x0AA08E3C, 0xBDBD4F38, 0x70DB114C, 0xC7C6D048, 0x649B0C35, 0xD386CD31, 0x0AA08E3C, 0xBDBD4F38, 0x70DB114C, 0xC7C6D048,
0x1EE09345, 0xA9FD5241, 0xACAD155F, 0x1BB0D45B, 0xC2969756, 0x758B5652, 0x1EE09345, 0xA9FD5241, 0xACAD155F, 0x1BB0D45B, 0xC2969756, 0x758B5652,
0xC836196A, 0x7F2BD86E, 0xA60D9B63, 0x11105A67, 0x14401D79, 0xA35DDC7D, 0xC836196A, 0x7F2BD86E, 0xA60D9B63, 0x11105A67, 0x14401D79, 0xA35DDC7D,
0x7A7B9F70, 0xCD665E74, 0xE0B62398, 0x57ABE29C, 0x8E8DA191, 0x39906095, 0x7A7B9F70, 0xCD665E74, 0xE0B62398, 0x57ABE29C, 0x8E8DA191, 0x39906095,
0x3CC0278B, 0x8BDDE68F, 0x52FBA582, 0xE5E66486, 0x585B2BBE, 0xEF46EABA, 0x3CC0278B, 0x8BDDE68F, 0x52FBA582, 0xE5E66486, 0x585B2BBE, 0xEF46EABA,
0x3660A9B7, 0x817D68B3, 0x842D2FAD, 0x3330EEA9, 0xEA16ADA4, 0x5D0B6CA0, 0x3660A9B7, 0x817D68B3, 0x842D2FAD, 0x3330EEA9, 0xEA16ADA4, 0x5D0B6CA0,
0x906D32D4, 0x2770F3D0, 0xFE56B0DD, 0x494B71D9, 0x4C1B36C7, 0xFB06F7C3, 0x906D32D4, 0x2770F3D0, 0xFE56B0DD, 0x494B71D9, 0x4C1B36C7, 0xFB06F7C3,
0x2220B4CE, 0x953D75CA, 0x28803AF2, 0x9F9DFBF6, 0x46BBB8FB, 0xF1A679FF, 0x2220B4CE, 0x953D75CA, 0x28803AF2, 0x9F9DFBF6, 0x46BBB8FB, 0xF1A679FF,
0xF4F63EE1, 0x43EBFFE5, 0x9ACDBCE8, 0x2DD07DEC, 0x77708634, 0xC06D4730, 0xF4F63EE1, 0x43EBFFE5, 0x9ACDBCE8, 0x2DD07DEC, 0x77708634, 0xC06D4730,
0x194B043D, 0xAE56C539, 0xAB068227, 0x1C1B4323, 0xC53D002E, 0x7220C12A, 0x194B043D, 0xAE56C539, 0xAB068227, 0x1C1B4323, 0xC53D002E, 0x7220C12A,
0xCF9D8E12, 0x78804F16, 0xA1A60C1B, 0x16BBCD1F, 0x13EB8A01, 0xA4F64B05, 0xCF9D8E12, 0x78804F16, 0xA1A60C1B, 0x16BBCD1F, 0x13EB8A01, 0xA4F64B05,
0x7DD00808, 0xCACDC90C, 0x07AB9778, 0xB0B6567C, 0x69901571, 0xDE8DD475, 0x7DD00808, 0xCACDC90C, 0x07AB9778, 0xB0B6567C, 0x69901571, 0xDE8DD475,
0xDBDD936B, 0x6CC0526F, 0xB5E61162, 0x02FBD066, 0xBF469F5E, 0x085B5E5A, 0xDBDD936B, 0x6CC0526F, 0xB5E61162, 0x02FBD066, 0xBF469F5E, 0x085B5E5A,
0xD17D1D57, 0x6660DC53, 0x63309B4D, 0xD42D5A49, 0x0D0B1944, 0xBA16D840, 0xD17D1D57, 0x6660DC53, 0x63309B4D, 0xD42D5A49, 0x0D0B1944, 0xBA16D840,
0x97C6A5AC, 0x20DB64A8, 0xF9FD27A5, 0x4EE0E6A1, 0x4BB0A1BF, 0xFCAD60BB, 0x97C6A5AC, 0x20DB64A8, 0xF9FD27A5, 0x4EE0E6A1, 0x4BB0A1BF, 0xFCAD60BB,
0x258B23B6, 0x9296E2B2, 0x2F2BAD8A, 0x98366C8E, 0x41102F83, 0xF60DEE87, 0x258B23B6, 0x9296E2B2, 0x2F2BAD8A, 0x98366C8E, 0x41102F83, 0xF60DEE87,
0xF35DA999, 0x4440689D, 0x9D662B90, 0x2A7BEA94, 0xE71DB4E0, 0x500075E4, 0xF35DA999, 0x4440689D, 0x9D662B90, 0x2A7BEA94, 0xE71DB4E0, 0x500075E4,
0x892636E9, 0x3E3BF7ED, 0x3B6BB0F3, 0x8C7671F7, 0x555032FA, 0xE24DF3FE, 0x892636E9, 0x3E3BF7ED, 0x3B6BB0F3, 0x8C7671F7, 0x555032FA, 0xE24DF3FE,
0x5FF0BCC6, 0xE8ED7DC2, 0x31CB3ECF, 0x86D6FFCB, 0x8386B8D5, 0x349B79D1, 0x5FF0BCC6, 0xE8ED7DC2, 0x31CB3ECF, 0x86D6FFCB, 0x8386B8D5, 0x349B79D1,
0xEDBD3ADC, 0x5AA0FBD8, 0xEEE00C69, 0x59FDCD6D, 0x80DB8E60, 0x37C64F64, 0xEDBD3ADC, 0x5AA0FBD8, 0xEEE00C69, 0x59FDCD6D, 0x80DB8E60, 0x37C64F64,
0x3296087A, 0x858BC97E, 0x5CAD8A73, 0xEBB04B77, 0x560D044F, 0xE110C54B, 0x3296087A, 0x858BC97E, 0x5CAD8A73, 0xEBB04B77, 0x560D044F, 0xE110C54B,
0x38368646, 0x8F2B4742, 0x8A7B005C, 0x3D66C158, 0xE4408255, 0x535D4351, 0x38368646, 0x8F2B4742, 0x8A7B005C, 0x3D66C158, 0xE4408255, 0x535D4351,
0x9E3B1D25, 0x2926DC21, 0xF0009F2C, 0x471D5E28, 0x424D1936, 0xF550D832, 0x9E3B1D25, 0x2926DC21, 0xF0009F2C, 0x471D5E28, 0x424D1936, 0xF550D832,
0x2C769B3F, 0x9B6B5A3B, 0x26D61503, 0x91CBD407, 0x48ED970A, 0xFFF0560E, 0x2C769B3F, 0x9B6B5A3B, 0x26D61503, 0x91CBD407, 0x48ED970A, 0xFFF0560E,
0xFAA01110, 0x4DBDD014, 0x949B9319, 0x2386521D, 0x0E562FF1, 0xB94BEEF5, 0xFAA01110, 0x4DBDD014, 0x949B9319, 0x2386521D, 0x0E562FF1, 0xB94BEEF5,
0x606DADF8, 0xD7706CFC, 0xD2202BE2, 0x653DEAE6, 0xBC1BA9EB, 0x0B0668EF, 0x606DADF8, 0xD7706CFC, 0xD2202BE2, 0x653DEAE6, 0xBC1BA9EB, 0x0B0668EF,
0xB6BB27D7, 0x01A6E6D3, 0xD880A5DE, 0x6F9D64DA, 0x6ACD23C4, 0xDDD0E2C0, 0xB6BB27D7, 0x01A6E6D3, 0xD880A5DE, 0x6F9D64DA, 0x6ACD23C4, 0xDDD0E2C0,
0x04F6A1CD, 0xB3EB60C9, 0x7E8D3EBD, 0xC990FFB9, 0x10B6BCB4, 0xA7AB7DB0, 0x04F6A1CD, 0xB3EB60C9, 0x7E8D3EBD, 0xC990FFB9, 0x10B6BCB4, 0xA7AB7DB0,
0xA2FB3AAE, 0x15E6FBAA, 0xCCC0B8A7, 0x7BDD79A3, 0xC660369B, 0x717DF79F, 0xA2FB3AAE, 0x15E6FBAA, 0xCCC0B8A7, 0x7BDD79A3, 0xC660369B, 0x717DF79F,
0xA85BB492, 0x1F467596, 0x1A163288, 0xAD0BF38C, 0x742DB081, 0xC3307185, 0xA85BB492, 0x1F467596, 0x1A163288, 0xAD0BF38C, 0x742DB081, 0xC3307185,
0x99908A5D, 0x2E8D4B59, 0xF7AB0854, 0x40B6C950, 0x45E68E4E, 0xF2FB4F4A, 0x99908A5D, 0x2E8D4B59, 0xF7AB0854, 0x40B6C950, 0x45E68E4E, 0xF2FB4F4A,
0x2BDD0C47, 0x9CC0CD43, 0x217D827B, 0x9660437F, 0x4F460072, 0xF85BC176, 0x2BDD0C47, 0x9CC0CD43, 0x217D827B, 0x9660437F, 0x4F460072, 0xF85BC176,
0xFD0B8668, 0x4A16476C, 0x93300461, 0x242DC565, 0xE94B9B11, 0x5E565A15, 0xFD0B8668, 0x4A16476C, 0x93300461, 0x242DC565, 0xE94B9B11, 0x5E565A15,
0x87701918, 0x306DD81C, 0x353D9F02, 0x82205E06, 0x5B061D0B, 0xEC1BDC0F, 0x87701918, 0x306DD81C, 0x353D9F02, 0x82205E06, 0x5B061D0B, 0xEC1BDC0F,
0x51A69337, 0xE6BB5233, 0x3F9D113E, 0x8880D03A, 0x8DD09724, 0x3ACD5620, 0x51A69337, 0xE6BB5233, 0x3F9D113E, 0x8880D03A, 0x8DD09724, 0x3ACD5620,
0xE3EB152D, 0x54F6D429, 0x7926A9C5, 0xCE3B68C1, 0x171D2BCC, 0xA000EAC8, 0xE3EB152D, 0x54F6D429, 0x7926A9C5, 0xCE3B68C1, 0x171D2BCC, 0xA000EAC8,
0xA550ADD6, 0x124D6CD2, 0xCB6B2FDF, 0x7C76EEDB, 0xC1CBA1E3, 0x76D660E7, 0xA550ADD6, 0x124D6CD2, 0xCB6B2FDF, 0x7C76EEDB, 0xC1CBA1E3, 0x76D660E7,
0xAFF023EA, 0x18EDE2EE, 0x1DBDA5F0, 0xAAA064F4, 0x738627F9, 0xC49BE6FD, 0xAFF023EA, 0x18EDE2EE, 0x1DBDA5F0, 0xAAA064F4, 0x738627F9, 0xC49BE6FD,
0x09FDB889, 0xBEE0798D, 0x67C63A80, 0xD0DBFB84, 0xD58BBC9A, 0x62967D9E, 0x09FDB889, 0xBEE0798D, 0x67C63A80, 0xD0DBFB84, 0xD58BBC9A, 0x62967D9E,
0xBBB03E93, 0x0CADFF97, 0xB110B0AF, 0x060D71AB, 0xDF2B32A6, 0x6836F3A2, 0xBBB03E93, 0x0CADFF97, 0xB110B0AF, 0x060D71AB, 0xDF2B32A6, 0x6836F3A2,
0x6D66B4BC, 0xDA7B75B8, 0x035D36B5, 0xB440F7B1, 0x6D66B4BC, 0xDA7B75B8, 0x035D36B5, 0xB440F7B1,
} }
func CalcCrc32(crc uint32, buffer []byte) uint32 { func CalcCrc32(crc uint32, buffer []byte) uint32 {
var i int = 0 var i int = 0
for i = 0; i < len(buffer); i++ { for i = 0; i < len(buffer); i++ {
crc = crc32table[(crc^uint32(buffer[i]))&0xff] ^ (crc >> 8) crc = crc32table[(crc^uint32(buffer[i]))&0xff] ^ (crc >> 8)
} }
return crc return crc
} }
func CovertRbspToSodb(rbsp []byte) []byte { func CovertRbspToSodb(rbsp []byte) []byte {
bs := NewBitStream(rbsp) bs := NewBitStream(rbsp)
bsw := NewBitStreamWriter(len(rbsp)) bsw := NewBitStreamWriter(len(rbsp))
for !bs.EOS() { for !bs.EOS() {
if bs.RemainBytes() > 3 && bs.NextBits(24) == 0x000003 { if bs.RemainBytes() > 3 && bs.NextBits(24) == 0x000003 {
bsw.PutByte(bs.Uint8(8)) bsw.PutByte(bs.Uint8(8))
bsw.PutByte(bs.Uint8(8)) bsw.PutByte(bs.Uint8(8))
bs.SkipBits(8) bs.SkipBits(8)
} else { } else {
bsw.PutByte(bs.Uint8(8)) bsw.PutByte(bs.Uint8(8))
} }
} }
return bsw.Bits() return bsw.Bits()
} }

View file

@ -3,70 +3,70 @@ package codec
import "errors" import "errors"
type VP8FrameTag struct { type VP8FrameTag struct {
FrameType uint32 //0: I frame , 1: P frame FrameType uint32 //0: I frame , 1: P frame
Version uint32 Version uint32
Display uint32 Display uint32
FirstPartSize uint32 FirstPartSize uint32
} }
type VP8KeyFrameHead struct { type VP8KeyFrameHead struct {
Width int Width int
Height int Height int
HorizScale int HorizScale int
VertScale int VertScale int
} }
func DecodeFrameTag(frame []byte) (*VP8FrameTag, error) { func DecodeFrameTag(frame []byte) (*VP8FrameTag, error) {
if len(frame) < 3 { if len(frame) < 3 {
return nil, errors.New("frame bytes < 3") return nil, errors.New("frame bytes < 3")
} }
var tmp uint32 = (uint32(frame[2]) << 16) | (uint32(frame[1]) << 8) | uint32(frame[0]) var tmp uint32 = (uint32(frame[2]) << 16) | (uint32(frame[1]) << 8) | uint32(frame[0])
tag := &VP8FrameTag{} tag := &VP8FrameTag{}
tag.FrameType = tmp & 0x01 tag.FrameType = tmp & 0x01
tag.Version = (tmp >> 1) & 0x07 tag.Version = (tmp >> 1) & 0x07
tag.Display = (tmp >> 4) & 0x01 tag.Display = (tmp >> 4) & 0x01
tag.FirstPartSize = (tmp >> 5) & 0x7FFFF tag.FirstPartSize = (tmp >> 5) & 0x7FFFF
return tag, nil return tag, nil
} }
func DecodeKeyFrameHead(frame []byte) (*VP8KeyFrameHead, error) { func DecodeKeyFrameHead(frame []byte) (*VP8KeyFrameHead, error) {
if len(frame) < 7 { if len(frame) < 7 {
return nil, errors.New("frame bytes < 3") return nil, errors.New("frame bytes < 3")
} }
if frame[0] != 0x9d || frame[1] != 0x01 || frame[2] != 0x2a { if frame[0] != 0x9d || frame[1] != 0x01 || frame[2] != 0x2a {
return nil, errors.New("not find Start code") return nil, errors.New("not find Start code")
} }
head := &VP8KeyFrameHead{} head := &VP8KeyFrameHead{}
head.Width = int(uint16(frame[4]&0x3f)<<8 | uint16(frame[3])) head.Width = int(uint16(frame[4]&0x3f)<<8 | uint16(frame[3]))
head.HorizScale = int(frame[4] >> 6) head.HorizScale = int(frame[4] >> 6)
head.Height = int(uint16(frame[6]&0x3f)<<8 | uint16(frame[5])) head.Height = int(uint16(frame[6]&0x3f)<<8 | uint16(frame[5]))
head.VertScale = int(frame[6] >> 6) head.VertScale = int(frame[6] >> 6)
return head, nil return head, nil
} }
func IsKeyFrame(frame []byte) bool { func IsKeyFrame(frame []byte) bool {
tag, err := DecodeFrameTag(frame) tag, err := DecodeFrameTag(frame)
if err != nil { if err != nil {
return false return false
} }
if tag.FrameType == 0 { if tag.FrameType == 0 {
return true return true
} else { } else {
return false return false
} }
} }
func GetResloution(frame []byte) (width int, height int, err error) { func GetResloution(frame []byte) (width int, height int, err error) {
if !IsKeyFrame(frame) { if !IsKeyFrame(frame) {
return 0, 0, errors.New("the frame is not Key frame") return 0, 0, errors.New("the frame is not Key frame")
} }
head, err := DecodeKeyFrameHead(frame[3:]) head, err := DecodeKeyFrameHead(frame[3:])
if err != nil { if err != nil {
return 0, 0, err return 0, 0, err
} }
return head.Width, head.Height, nil return head.Width, head.Height, nil
} }

View file

@ -1,10 +1,10 @@
package mpeg2 package mpeg2
import ( import (
"fmt" "fmt"
"os" "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 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 type PES_STREMA_ID int
const ( const (
PES_STREAM_END PES_STREMA_ID = 0xB9 PES_STREAM_END PES_STREMA_ID = 0xB9
PES_STREAM_START PES_STREMA_ID = 0xBA PES_STREAM_START PES_STREMA_ID = 0xBA
PES_STREAM_SYSTEM_HEAD PES_STREMA_ID = 0xBB PES_STREAM_SYSTEM_HEAD PES_STREMA_ID = 0xBB
PES_STREAM_MAP PES_STREMA_ID = 0xBC PES_STREAM_MAP PES_STREMA_ID = 0xBC
PES_STREAM_PRIVATE PES_STREMA_ID = 0xBD PES_STREAM_PRIVATE PES_STREMA_ID = 0xBD
PES_STREAM_AUDIO PES_STREMA_ID = 0xC0 PES_STREAM_AUDIO PES_STREMA_ID = 0xC0
PES_STREAM_VIDEO PES_STREMA_ID = 0xE0 PES_STREAM_VIDEO PES_STREMA_ID = 0xE0
) )
func findPESIDByStreamType(cid TS_STREAM_TYPE) PES_STREMA_ID { func findPESIDByStreamType(cid TS_STREAM_TYPE) PES_STREMA_ID {
if cid == TS_STREAM_AAC { if cid == TS_STREAM_AAC {
return PES_STREAM_AUDIO return PES_STREAM_AUDIO
} else if cid == TS_STREAM_H264 || cid == TS_STREAM_H265 { } else if cid == TS_STREAM_H264 || cid == TS_STREAM_H265 {
return PES_STREAM_VIDEO return PES_STREAM_VIDEO
} else { } else {
return PES_STREAM_PRIVATE return PES_STREAM_PRIVATE
} }
} }
type PesPacket struct { type PesPacket struct {
Stream_id uint8 Stream_id uint8
PES_packet_length uint16 PES_packet_length uint16
PES_scrambling_control uint8 PES_scrambling_control uint8
PES_priority uint8 PES_priority uint8
Data_alignment_indicator uint8 Data_alignment_indicator uint8
Copyright uint8 Copyright uint8
Original_or_copy uint8 Original_or_copy uint8
PTS_DTS_flags uint8 PTS_DTS_flags uint8
ESCR_flag uint8 ESCR_flag uint8
ES_rate_flag uint8 ES_rate_flag uint8
DSM_trick_mode_flag uint8 DSM_trick_mode_flag uint8
Additional_copy_info_flag uint8 Additional_copy_info_flag uint8
PES_CRC_flag uint8 PES_CRC_flag uint8
PES_extension_flag uint8 PES_extension_flag uint8
PES_header_data_length uint8 PES_header_data_length uint8
Pts uint64 Pts uint64
Dts uint64 Dts uint64
ESCR_base uint64 ESCR_base uint64
ESCR_extension uint16 ESCR_extension uint16
ES_rate uint32 ES_rate uint32
Trick_mode_control uint8 Trick_mode_control uint8
Trick_value uint8 Trick_value uint8
Additional_copy_info uint8 Additional_copy_info uint8
Previous_PES_packet_CRC uint16 Previous_PES_packet_CRC uint16
Pes_payload []byte Pes_payload []byte
//TODO //TODO
//if ( PES_extension_flag == '1') //if ( PES_extension_flag == '1')
// PES_private_data_flag uint8 // PES_private_data_flag uint8
// pack_header_field_flag uint8 // pack_header_field_flag uint8
// program_packet_sequence_counter_flag uint8 // program_packet_sequence_counter_flag uint8
// P_STD_buffer_flag uint8 // P_STD_buffer_flag uint8
// PES_extension_flag_2 uint8 // PES_extension_flag_2 uint8
// PES_private_data [16]byte // PES_private_data [16]byte
} }
func NewPesPacket() *PesPacket { func NewPesPacket() *PesPacket {
return new(PesPacket) return new(PesPacket)
} }
func (pkg *PesPacket) PrettyPrint(file *os.File) { func (pkg *PesPacket) PrettyPrint(file *os.File) {
file.WriteString(fmt.Sprintf("stream_id:%d\n", pkg.Stream_id)) 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_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_scrambling_control:%d\n", pkg.PES_scrambling_control))
file.WriteString(fmt.Sprintf("PES_priority:%d\n", pkg.PES_priority)) 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("data_alignment_indicator:%d\n", pkg.Data_alignment_indicator))
file.WriteString(fmt.Sprintf("copyright:%d\n", pkg.Copyright)) 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("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("PTS_DTS_flags:%d\n", pkg.PTS_DTS_flags))
file.WriteString(fmt.Sprintf("ESCR_flag:%d\n", pkg.ESCR_flag)) 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("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("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("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_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_extension_flag:%d\n", pkg.PES_extension_flag))
file.WriteString(fmt.Sprintf("PES_header_data_length:%d\n", pkg.PES_header_data_length)) file.WriteString(fmt.Sprintf("PES_header_data_length:%d\n", pkg.PES_header_data_length))
if pkg.PTS_DTS_flags&0x02 == 0x02 { if pkg.PTS_DTS_flags&0x02 == 0x02 {
file.WriteString(fmt.Sprintf("PTS:%d\n", pkg.Pts)) file.WriteString(fmt.Sprintf("PTS:%d\n", pkg.Pts))
} }
if pkg.PTS_DTS_flags&0x03 == 0x03 { if pkg.PTS_DTS_flags&0x03 == 0x03 {
file.WriteString(fmt.Sprintf("DTS:%d\n", pkg.Dts)) file.WriteString(fmt.Sprintf("DTS:%d\n", pkg.Dts))
} }
if pkg.ESCR_flag == 1 { if pkg.ESCR_flag == 1 {
file.WriteString(fmt.Sprintf("ESCR_base:%d\n", pkg.ESCR_base)) file.WriteString(fmt.Sprintf("ESCR_base:%d\n", pkg.ESCR_base))
file.WriteString(fmt.Sprintf("ESCR_extension:%d\n", pkg.ESCR_extension)) file.WriteString(fmt.Sprintf("ESCR_extension:%d\n", pkg.ESCR_extension))
} }
if pkg.ES_rate_flag == 1 { if pkg.ES_rate_flag == 1 {
file.WriteString(fmt.Sprintf("ES_rate:%d\n", pkg.ES_rate)) file.WriteString(fmt.Sprintf("ES_rate:%d\n", pkg.ES_rate))
} }
if pkg.DSM_trick_mode_flag == 1 { if pkg.DSM_trick_mode_flag == 1 {
file.WriteString(fmt.Sprintf("trick_mode_control:%d\n", pkg.Trick_mode_control)) file.WriteString(fmt.Sprintf("trick_mode_control:%d\n", pkg.Trick_mode_control))
} }
if pkg.Additional_copy_info_flag == 1 { if pkg.Additional_copy_info_flag == 1 {
file.WriteString(fmt.Sprintf("additional_copy_info:%d\n", pkg.Additional_copy_info)) file.WriteString(fmt.Sprintf("additional_copy_info:%d\n", pkg.Additional_copy_info))
} }
if pkg.PES_CRC_flag == 1 { if pkg.PES_CRC_flag == 1 {
file.WriteString(fmt.Sprintf("previous_PES_packet_CRC:%d\n", pkg.Previous_PES_packet_CRC)) file.WriteString(fmt.Sprintf("previous_PES_packet_CRC:%d\n", pkg.Previous_PES_packet_CRC))
} }
file.WriteString("PES_packet_data_byte:\n") file.WriteString("PES_packet_data_byte:\n")
file.WriteString(fmt.Sprintf(" Size: %d\n", len(pkg.Pes_payload))) file.WriteString(fmt.Sprintf(" Size: %d\n", len(pkg.Pes_payload)))
file.WriteString(" data:") file.WriteString(" data:")
for i := 0; i < 12 && i < len(pkg.Pes_payload); i++ { for i := 0; i < 12 && i < len(pkg.Pes_payload); i++ {
if i%4 == 0 { if i%4 == 0 {
file.WriteString("\n") file.WriteString("\n")
file.WriteString(" ") file.WriteString(" ")
} }
file.WriteString(fmt.Sprintf("0x%02x ", pkg.Pes_payload[i])) file.WriteString(fmt.Sprintf("0x%02x ", pkg.Pes_payload[i]))
} }
file.WriteString("\n") file.WriteString("\n")
} }
func (pkg *PesPacket) Decode(bs *codec.BitStream) error { func (pkg *PesPacket) Decode(bs *codec.BitStream) error {
if bs.RemainBytes() < 9 { if bs.RemainBytes() < 9 {
return errNeedMore return errNeedMore
} }
bs.SkipBits(24) //packet_start_code_prefix bs.SkipBits(24) //packet_start_code_prefix
pkg.Stream_id = bs.Uint8(8) //stream_id pkg.Stream_id = bs.Uint8(8) //stream_id
pkg.PES_packet_length = bs.Uint16(16) pkg.PES_packet_length = bs.Uint16(16)
bs.SkipBits(2) //'10' bs.SkipBits(2) //'10'
pkg.PES_scrambling_control = bs.Uint8(2) pkg.PES_scrambling_control = bs.Uint8(2)
pkg.PES_priority = bs.Uint8(1) pkg.PES_priority = bs.Uint8(1)
pkg.Data_alignment_indicator = bs.Uint8(1) pkg.Data_alignment_indicator = bs.Uint8(1)
pkg.Copyright = bs.Uint8(1) pkg.Copyright = bs.Uint8(1)
pkg.Original_or_copy = bs.Uint8(1) pkg.Original_or_copy = bs.Uint8(1)
pkg.PTS_DTS_flags = bs.Uint8(2) pkg.PTS_DTS_flags = bs.Uint8(2)
pkg.ESCR_flag = bs.Uint8(1) pkg.ESCR_flag = bs.Uint8(1)
pkg.ES_rate_flag = bs.Uint8(1) pkg.ES_rate_flag = bs.Uint8(1)
pkg.DSM_trick_mode_flag = bs.Uint8(1) pkg.DSM_trick_mode_flag = bs.Uint8(1)
pkg.Additional_copy_info_flag = bs.Uint8(1) pkg.Additional_copy_info_flag = bs.Uint8(1)
pkg.PES_CRC_flag = bs.Uint8(1) pkg.PES_CRC_flag = bs.Uint8(1)
pkg.PES_extension_flag = bs.Uint8(1) pkg.PES_extension_flag = bs.Uint8(1)
pkg.PES_header_data_length = bs.Uint8(8) pkg.PES_header_data_length = bs.Uint8(8)
if bs.RemainBytes() < int(pkg.PES_header_data_length) { if bs.RemainBytes() < int(pkg.PES_header_data_length) {
bs.UnRead(9 * 8) bs.UnRead(9 * 8)
return errNeedMore return errNeedMore
} }
bs.Markdot() bs.Markdot()
if pkg.PTS_DTS_flags&0x02 == 0x02 { if pkg.PTS_DTS_flags&0x02 == 0x02 {
bs.SkipBits(4) bs.SkipBits(4)
pkg.Pts = bs.GetBits(3) pkg.Pts = bs.GetBits(3)
bs.SkipBits(1) bs.SkipBits(1)
pkg.Pts = (pkg.Pts << 15) | bs.GetBits(15) pkg.Pts = (pkg.Pts << 15) | bs.GetBits(15)
bs.SkipBits(1) bs.SkipBits(1)
pkg.Pts = (pkg.Pts << 15) | bs.GetBits(15) pkg.Pts = (pkg.Pts << 15) | bs.GetBits(15)
bs.SkipBits(1) bs.SkipBits(1)
} }
if pkg.PTS_DTS_flags&0x03 == 0x03 { if pkg.PTS_DTS_flags&0x03 == 0x03 {
bs.SkipBits(4) bs.SkipBits(4)
pkg.Dts = bs.GetBits(3) pkg.Dts = bs.GetBits(3)
bs.SkipBits(1) bs.SkipBits(1)
pkg.Dts = (pkg.Dts << 15) | bs.GetBits(15) pkg.Dts = (pkg.Dts << 15) | bs.GetBits(15)
bs.SkipBits(1) bs.SkipBits(1)
pkg.Dts = (pkg.Dts << 15) | bs.GetBits(15) pkg.Dts = (pkg.Dts << 15) | bs.GetBits(15)
bs.SkipBits(1) bs.SkipBits(1)
} else { } else {
pkg.Dts = pkg.Pts pkg.Dts = pkg.Pts
} }
if pkg.ESCR_flag == 1 { if pkg.ESCR_flag == 1 {
bs.SkipBits(2) bs.SkipBits(2)
pkg.ESCR_base = bs.GetBits(3) pkg.ESCR_base = bs.GetBits(3)
bs.SkipBits(1) bs.SkipBits(1)
pkg.ESCR_base = (pkg.Pts << 15) | bs.GetBits(15) pkg.ESCR_base = (pkg.Pts << 15) | bs.GetBits(15)
bs.SkipBits(1) bs.SkipBits(1)
pkg.ESCR_base = (pkg.Pts << 15) | bs.GetBits(15) pkg.ESCR_base = (pkg.Pts << 15) | bs.GetBits(15)
bs.SkipBits(1) bs.SkipBits(1)
pkg.ESCR_extension = bs.Uint16(9) pkg.ESCR_extension = bs.Uint16(9)
bs.SkipBits(1) bs.SkipBits(1)
} }
if pkg.ES_rate_flag == 1 { if pkg.ES_rate_flag == 1 {
bs.SkipBits(1) bs.SkipBits(1)
pkg.ES_rate = bs.Uint32(22) pkg.ES_rate = bs.Uint32(22)
bs.SkipBits(1) bs.SkipBits(1)
} }
if pkg.DSM_trick_mode_flag == 1 { if pkg.DSM_trick_mode_flag == 1 {
pkg.Trick_mode_control = bs.Uint8(3) pkg.Trick_mode_control = bs.Uint8(3)
pkg.Trick_value = bs.Uint8(5) pkg.Trick_value = bs.Uint8(5)
} }
if pkg.Additional_copy_info_flag == 1 { if pkg.Additional_copy_info_flag == 1 {
pkg.Additional_copy_info = bs.Uint8(7) pkg.Additional_copy_info = bs.Uint8(7)
} }
if pkg.PES_CRC_flag == 1 { if pkg.PES_CRC_flag == 1 {
pkg.Previous_PES_packet_CRC = bs.Uint16(16) pkg.Previous_PES_packet_CRC = bs.Uint16(16)
} }
loc := bs.DistanceFromMarkDot() loc := bs.DistanceFromMarkDot()
bs.SkipBits(int(pkg.PES_header_data_length)*8 - loc) // skip remaining header bs.SkipBits(int(pkg.PES_header_data_length)*8 - loc) // skip remaining header
// the -3 bytes are the combined lengths // the -3 bytes are the combined lengths
// of all fields between PES_packet_length and PES_header_data_length (2 bytes) // of all fields between PES_packet_length and PES_header_data_length (2 bytes)
// and the PES_header_data_length itself (1 byte) // and the PES_header_data_length itself (1 byte)
dataLen := int(pkg.PES_packet_length - 3 - uint16(pkg.PES_header_data_length)) dataLen := int(pkg.PES_packet_length - 3 - uint16(pkg.PES_header_data_length))
if bs.RemainBytes() < dataLen { if bs.RemainBytes() < dataLen {
pkg.Pes_payload = bs.RemainData() pkg.Pes_payload = bs.RemainData()
bs.UnRead((9 + int(pkg.PES_header_data_length)) * 8) bs.UnRead((9 + int(pkg.PES_header_data_length)) * 8)
return errNeedMore return errNeedMore
} }
if pkg.PES_packet_length == 0 || bs.RemainBytes() <= dataLen { if pkg.PES_packet_length == 0 || bs.RemainBytes() <= dataLen {
pkg.Pes_payload = bs.RemainData() pkg.Pes_payload = bs.RemainData()
bs.SkipBits(bs.RemainBits()) bs.SkipBits(bs.RemainBits())
} else { } else {
pkg.Pes_payload = bs.RemainData()[:dataLen] pkg.Pes_payload = bs.RemainData()[:dataLen]
bs.SkipBits(dataLen * 8) bs.SkipBits(dataLen * 8)
} }
return nil return nil
} }
func (pkg *PesPacket) DecodeMpeg1(bs *codec.BitStream) error { func (pkg *PesPacket) DecodeMpeg1(bs *codec.BitStream) error {
if bs.RemainBytes() < 6 { if bs.RemainBytes() < 6 {
return errNeedMore return errNeedMore
} }
bs.SkipBits(24) //packet_start_code_prefix bs.SkipBits(24) //packet_start_code_prefix
pkg.Stream_id = bs.Uint8(8) //stream_id pkg.Stream_id = bs.Uint8(8) //stream_id
pkg.PES_packet_length = bs.Uint16(16) pkg.PES_packet_length = bs.Uint16(16)
if pkg.PES_packet_length != 0 && bs.RemainBytes() < int(pkg.PES_packet_length) { if pkg.PES_packet_length != 0 && bs.RemainBytes() < int(pkg.PES_packet_length) {
bs.UnRead(6 * 8) bs.UnRead(6 * 8)
return errNeedMore return errNeedMore
} }
bs.Markdot() bs.Markdot()
for bs.NextBits(8) == 0xFF { for bs.NextBits(8) == 0xFF {
bs.SkipBits(8) bs.SkipBits(8)
} }
if bs.NextBits(2) == 0x01 { if bs.NextBits(2) == 0x01 {
bs.SkipBits(16) bs.SkipBits(16)
} }
if bs.NextBits(4) == 0x02 { if bs.NextBits(4) == 0x02 {
bs.SkipBits(4) bs.SkipBits(4)
pkg.Pts = bs.GetBits(3) pkg.Pts = bs.GetBits(3)
bs.SkipBits(1) bs.SkipBits(1)
pkg.Pts = pkg.Pts<<15 | bs.GetBits(15) pkg.Pts = pkg.Pts<<15 | bs.GetBits(15)
bs.SkipBits(1) bs.SkipBits(1)
pkg.Pts = pkg.Pts<<15 | bs.GetBits(15) pkg.Pts = pkg.Pts<<15 | bs.GetBits(15)
bs.SkipBits(1) bs.SkipBits(1)
} else if bs.NextBits(4) == 0x03 { } else if bs.NextBits(4) == 0x03 {
bs.SkipBits(4) bs.SkipBits(4)
pkg.Pts = bs.GetBits(3) pkg.Pts = bs.GetBits(3)
bs.SkipBits(1) bs.SkipBits(1)
pkg.Pts = pkg.Pts<<15 | bs.GetBits(15) pkg.Pts = pkg.Pts<<15 | bs.GetBits(15)
bs.SkipBits(1) bs.SkipBits(1)
pkg.Pts = pkg.Pts<<15 | bs.GetBits(15) pkg.Pts = pkg.Pts<<15 | bs.GetBits(15)
bs.SkipBits(1) bs.SkipBits(1)
pkg.Dts = bs.GetBits(3) pkg.Dts = bs.GetBits(3)
bs.SkipBits(1) bs.SkipBits(1)
pkg.Dts = pkg.Pts<<15 | bs.GetBits(15) pkg.Dts = pkg.Pts<<15 | bs.GetBits(15)
bs.SkipBits(1) bs.SkipBits(1)
pkg.Dts = pkg.Pts<<15 | bs.GetBits(15) pkg.Dts = pkg.Pts<<15 | bs.GetBits(15)
bs.SkipBits(1) bs.SkipBits(1)
} else if bs.NextBits(8) == 0x0F { } else if bs.NextBits(8) == 0x0F {
bs.SkipBits(8) bs.SkipBits(8)
} else { } else {
return errParser return errParser
} }
loc := bs.DistanceFromMarkDot() / 8 loc := bs.DistanceFromMarkDot() / 8
if pkg.PES_packet_length < uint16(loc) { if pkg.PES_packet_length < uint16(loc) {
return errParser return errParser
} }
if pkg.PES_packet_length == 0 || if pkg.PES_packet_length == 0 ||
bs.RemainBits() <= int(pkg.PES_packet_length-uint16(loc))*8 { bs.RemainBits() <= int(pkg.PES_packet_length-uint16(loc))*8 {
pkg.Pes_payload = bs.RemainData() pkg.Pes_payload = bs.RemainData()
bs.SkipBits(bs.RemainBits()) bs.SkipBits(bs.RemainBits())
} else { } else {
pkg.Pes_payload = bs.RemainData()[:pkg.PES_packet_length-uint16(loc)] pkg.Pes_payload = bs.RemainData()[:pkg.PES_packet_length-uint16(loc)]
bs.SkipBits(int(pkg.PES_packet_length-uint16(loc)) * 8) bs.SkipBits(int(pkg.PES_packet_length-uint16(loc)) * 8)
} }
return nil return nil
} }
func (pkg *PesPacket) Encode(bsw *codec.BitStreamWriter) { func (pkg *PesPacket) Encode(bsw *codec.BitStreamWriter) {
bsw.PutBytes([]byte{0x00, 0x00, 0x01}) bsw.PutBytes([]byte{0x00, 0x00, 0x01})
bsw.PutByte(pkg.Stream_id) bsw.PutByte(pkg.Stream_id)
bsw.PutUint16(pkg.PES_packet_length, 16) bsw.PutUint16(pkg.PES_packet_length, 16)
bsw.PutUint8(0x02, 2) bsw.PutUint8(0x02, 2)
bsw.PutUint8(pkg.PES_scrambling_control, 2) bsw.PutUint8(pkg.PES_scrambling_control, 2)
bsw.PutUint8(pkg.PES_priority, 1) bsw.PutUint8(pkg.PES_priority, 1)
bsw.PutUint8(pkg.Data_alignment_indicator, 1) bsw.PutUint8(pkg.Data_alignment_indicator, 1)
bsw.PutUint8(pkg.Copyright, 1) bsw.PutUint8(pkg.Copyright, 1)
bsw.PutUint8(pkg.Original_or_copy, 1) bsw.PutUint8(pkg.Original_or_copy, 1)
bsw.PutUint8(pkg.PTS_DTS_flags, 2) bsw.PutUint8(pkg.PTS_DTS_flags, 2)
bsw.PutUint8(pkg.ESCR_flag, 1) bsw.PutUint8(pkg.ESCR_flag, 1)
bsw.PutUint8(pkg.ES_rate_flag, 1) bsw.PutUint8(pkg.ES_rate_flag, 1)
bsw.PutUint8(pkg.DSM_trick_mode_flag, 1) bsw.PutUint8(pkg.DSM_trick_mode_flag, 1)
bsw.PutUint8(pkg.Additional_copy_info_flag, 1) bsw.PutUint8(pkg.Additional_copy_info_flag, 1)
bsw.PutUint8(pkg.PES_CRC_flag, 1) bsw.PutUint8(pkg.PES_CRC_flag, 1)
bsw.PutUint8(pkg.PES_extension_flag, 1) bsw.PutUint8(pkg.PES_extension_flag, 1)
bsw.PutByte(pkg.PES_header_data_length) bsw.PutByte(pkg.PES_header_data_length)
if pkg.PTS_DTS_flags == 0x02 { if pkg.PTS_DTS_flags == 0x02 {
bsw.PutUint8(0x02, 4) bsw.PutUint8(0x02, 4)
bsw.PutUint64(pkg.Pts>>30, 3) bsw.PutUint64(pkg.Pts>>30, 3)
bsw.PutUint8(0x01, 1) bsw.PutUint8(0x01, 1)
bsw.PutUint64(pkg.Pts>>15, 15) bsw.PutUint64(pkg.Pts>>15, 15)
bsw.PutUint8(0x01, 1) bsw.PutUint8(0x01, 1)
bsw.PutUint64(pkg.Pts, 15) bsw.PutUint64(pkg.Pts, 15)
bsw.PutUint8(0x01, 1) bsw.PutUint8(0x01, 1)
} }
if pkg.PTS_DTS_flags == 0x03 { if pkg.PTS_DTS_flags == 0x03 {
bsw.PutUint8(0x03, 4) bsw.PutUint8(0x03, 4)
bsw.PutUint64(pkg.Pts>>30, 3) bsw.PutUint64(pkg.Pts>>30, 3)
bsw.PutUint8(0x01, 1) bsw.PutUint8(0x01, 1)
bsw.PutUint64(pkg.Pts>>15, 15) bsw.PutUint64(pkg.Pts>>15, 15)
bsw.PutUint8(0x01, 1) bsw.PutUint8(0x01, 1)
bsw.PutUint64(pkg.Pts, 15) bsw.PutUint64(pkg.Pts, 15)
bsw.PutUint8(0x01, 1) bsw.PutUint8(0x01, 1)
bsw.PutUint8(0x01, 4) bsw.PutUint8(0x01, 4)
bsw.PutUint64(pkg.Dts>>30, 3) bsw.PutUint64(pkg.Dts>>30, 3)
bsw.PutUint8(0x01, 1) bsw.PutUint8(0x01, 1)
bsw.PutUint64(pkg.Dts>>15, 15) bsw.PutUint64(pkg.Dts>>15, 15)
bsw.PutUint8(0x01, 1) bsw.PutUint8(0x01, 1)
bsw.PutUint64(pkg.Dts, 15) bsw.PutUint64(pkg.Dts, 15)
bsw.PutUint8(0x01, 1) bsw.PutUint8(0x01, 1)
} }
if pkg.ESCR_flag == 1 { if pkg.ESCR_flag == 1 {
bsw.PutUint8(0x03, 2) bsw.PutUint8(0x03, 2)
bsw.PutUint64(pkg.ESCR_base>>30, 3) bsw.PutUint64(pkg.ESCR_base>>30, 3)
bsw.PutUint8(0x01, 1) bsw.PutUint8(0x01, 1)
bsw.PutUint64(pkg.ESCR_base>>15, 15) bsw.PutUint64(pkg.ESCR_base>>15, 15)
bsw.PutUint8(0x01, 1) bsw.PutUint8(0x01, 1)
bsw.PutUint64(pkg.ESCR_base, 15) bsw.PutUint64(pkg.ESCR_base, 15)
bsw.PutUint8(0x01, 1) bsw.PutUint8(0x01, 1)
} }
bsw.PutBytes(pkg.Pes_payload) bsw.PutBytes(pkg.Pes_payload)
} }

View file

@ -1,280 +1,280 @@
package mpeg2 package mpeg2
import ( import (
"github.com/yapingcat/gomedia/codec" "github.com/yapingcat/gomedia/codec"
) )
type psstream struct { type psstream struct {
sid uint8 sid uint8
cid PS_STREAM_TYPE cid PS_STREAM_TYPE
pts uint64 pts uint64
dts uint64 dts uint64
streamBuf []byte streamBuf []byte
} }
func newpsstream(sid uint8, cid PS_STREAM_TYPE) *psstream { func newpsstream(sid uint8, cid PS_STREAM_TYPE) *psstream {
return &psstream{ return &psstream{
sid: sid, sid: sid,
cid: cid, cid: cid,
streamBuf: make([]byte, 0, 4096), streamBuf: make([]byte, 0, 4096),
} }
} }
type PSDemuxer struct { type PSDemuxer struct {
streamMap map[uint8]*psstream streamMap map[uint8]*psstream
pkg *PSPacket pkg *PSPacket
mpeg1 bool mpeg1 bool
cache []byte cache []byte
OnFrame func(frame []byte, cid PS_STREAM_TYPE, pts uint64, dts uint64) OnFrame func(frame []byte, cid PS_STREAM_TYPE, pts uint64, dts uint64)
//解ps包过程中解码回调psmsystem headerpes包等 //解ps包过程中解码回调psmsystem headerpes包等
//decodeResult 解码ps包时的产生的错误 //decodeResult 解码ps包时的产生的错误
//这个回调主要用于debug查看是否ps包存在问题 //这个回调主要用于debug查看是否ps包存在问题
OnPacket func(pkg Display, decodeResult error) OnPacket func(pkg Display, decodeResult error)
} }
func NewPSDemuxer() *PSDemuxer { func NewPSDemuxer() *PSDemuxer {
return &PSDemuxer{ return &PSDemuxer{
streamMap: make(map[uint8]*psstream), streamMap: make(map[uint8]*psstream),
pkg: new(PSPacket), pkg: new(PSPacket),
cache: make([]byte, 0, 256), cache: make([]byte, 0, 256),
OnFrame: nil, OnFrame: nil,
OnPacket: nil, OnPacket: nil,
} }
} }
func (psdemuxer *PSDemuxer) Input(data []byte) error { func (psdemuxer *PSDemuxer) Input(data []byte) error {
var bs *codec.BitStream var bs *codec.BitStream
if len(psdemuxer.cache) > 0 { if len(psdemuxer.cache) > 0 {
psdemuxer.cache = append(psdemuxer.cache, data...) psdemuxer.cache = append(psdemuxer.cache, data...)
bs = codec.NewBitStream(psdemuxer.cache) bs = codec.NewBitStream(psdemuxer.cache)
} else { } else {
bs = codec.NewBitStream(data) bs = codec.NewBitStream(data)
} }
saveReseved := func() { saveReseved := func() {
tmpcache := make([]byte, bs.RemainBytes()) tmpcache := make([]byte, bs.RemainBytes())
copy(tmpcache, bs.RemainData()) copy(tmpcache, bs.RemainData())
psdemuxer.cache = tmpcache psdemuxer.cache = tmpcache
} }
var ret error = nil var ret error = nil
for !bs.EOS() { for !bs.EOS() {
if mpegerr, ok := ret.(Error); ok { if mpegerr, ok := ret.(Error); ok {
if mpegerr.NeedMore() { if mpegerr.NeedMore() {
saveReseved() saveReseved()
} }
break break
} }
if bs.RemainBits() < 32 { if bs.RemainBits() < 32 {
ret = errNeedMore ret = errNeedMore
saveReseved() saveReseved()
break break
} }
prefix_code := bs.NextBits(32) prefix_code := bs.NextBits(32)
switch prefix_code { switch prefix_code {
case 0x000001BA: //pack header case 0x000001BA: //pack header
if psdemuxer.pkg.Header == nil { if psdemuxer.pkg.Header == nil {
psdemuxer.pkg.Header = new(PSPackHeader) psdemuxer.pkg.Header = new(PSPackHeader)
} }
ret = psdemuxer.pkg.Header.Decode(bs) ret = psdemuxer.pkg.Header.Decode(bs)
psdemuxer.mpeg1 = psdemuxer.pkg.Header.IsMpeg1 psdemuxer.mpeg1 = psdemuxer.pkg.Header.IsMpeg1
if psdemuxer.OnPacket != nil { if psdemuxer.OnPacket != nil {
psdemuxer.OnPacket(psdemuxer.pkg.Header, ret) psdemuxer.OnPacket(psdemuxer.pkg.Header, ret)
} }
case 0x000001BB: //system header case 0x000001BB: //system header
if psdemuxer.pkg.Header == nil { if psdemuxer.pkg.Header == nil {
panic("psdemuxer.pkg.Header must not be nil") panic("psdemuxer.pkg.Header must not be nil")
} }
if psdemuxer.pkg.System == nil { if psdemuxer.pkg.System == nil {
psdemuxer.pkg.System = new(System_header) psdemuxer.pkg.System = new(System_header)
} }
ret = psdemuxer.pkg.System.Decode(bs) ret = psdemuxer.pkg.System.Decode(bs)
if psdemuxer.OnPacket != nil { if psdemuxer.OnPacket != nil {
psdemuxer.OnPacket(psdemuxer.pkg.System, ret) psdemuxer.OnPacket(psdemuxer.pkg.System, ret)
} }
case 0x000001BC: //program stream map case 0x000001BC: //program stream map
if psdemuxer.pkg.Psm == nil { if psdemuxer.pkg.Psm == nil {
psdemuxer.pkg.Psm = new(Program_stream_map) psdemuxer.pkg.Psm = new(Program_stream_map)
} }
if ret = psdemuxer.pkg.Psm.Decode(bs); ret == nil { if ret = psdemuxer.pkg.Psm.Decode(bs); ret == nil {
for _, streaminfo := range psdemuxer.pkg.Psm.Stream_map { for _, streaminfo := range psdemuxer.pkg.Psm.Stream_map {
if _, found := psdemuxer.streamMap[streaminfo.Elementary_stream_id]; !found { if _, found := psdemuxer.streamMap[streaminfo.Elementary_stream_id]; !found {
stream := newpsstream(streaminfo.Elementary_stream_id, PS_STREAM_TYPE(streaminfo.Stream_type)) stream := newpsstream(streaminfo.Elementary_stream_id, PS_STREAM_TYPE(streaminfo.Stream_type))
psdemuxer.streamMap[stream.sid] = stream psdemuxer.streamMap[stream.sid] = stream
} }
} }
} }
if psdemuxer.OnPacket != nil { if psdemuxer.OnPacket != nil {
psdemuxer.OnPacket(psdemuxer.pkg.Psm, ret) psdemuxer.OnPacket(psdemuxer.pkg.Psm, ret)
} }
case 0x000001BD, 0x000001BE, 0x000001BF, 0x000001F0, 0x000001F1, case 0x000001BD, 0x000001BE, 0x000001BF, 0x000001F0, 0x000001F1,
0x000001F2, 0x000001F3, 0x000001F4, 0x000001F5, 0x000001F6, 0x000001F2, 0x000001F3, 0x000001F4, 0x000001F5, 0x000001F6,
0x000001F7, 0x000001F8, 0x000001F9, 0x000001FA, 0x000001FB: 0x000001F7, 0x000001F8, 0x000001F9, 0x000001FA, 0x000001FB:
if psdemuxer.pkg.CommPes == nil { if psdemuxer.pkg.CommPes == nil {
psdemuxer.pkg.CommPes = new(CommonPesPacket) psdemuxer.pkg.CommPes = new(CommonPesPacket)
} }
ret = psdemuxer.pkg.CommPes.Decode(bs) ret = psdemuxer.pkg.CommPes.Decode(bs)
case 0x000001FF: //program stream directory case 0x000001FF: //program stream directory
if psdemuxer.pkg.Psd == nil { if psdemuxer.pkg.Psd == nil {
psdemuxer.pkg.Psd = new(Program_stream_directory) psdemuxer.pkg.Psd = new(Program_stream_directory)
} }
ret = psdemuxer.pkg.Psd.Decode(bs) ret = psdemuxer.pkg.Psd.Decode(bs)
case 0x000001B9: //MPEG_program_end_code case 0x000001B9: //MPEG_program_end_code
continue continue
default: default:
if prefix_code&0xFFFFFFE0 == 0x000001C0 || prefix_code&0xFFFFFFE0 == 0x000001E0 { if prefix_code&0xFFFFFFE0 == 0x000001C0 || prefix_code&0xFFFFFFE0 == 0x000001E0 {
if psdemuxer.pkg.Pes == nil { if psdemuxer.pkg.Pes == nil {
psdemuxer.pkg.Pes = NewPesPacket() psdemuxer.pkg.Pes = NewPesPacket()
} }
if psdemuxer.mpeg1 { if psdemuxer.mpeg1 {
ret = psdemuxer.pkg.Pes.DecodeMpeg1(bs) ret = psdemuxer.pkg.Pes.DecodeMpeg1(bs)
} else { } else {
ret = psdemuxer.pkg.Pes.Decode(bs) ret = psdemuxer.pkg.Pes.Decode(bs)
} }
if psdemuxer.OnPacket != nil { if psdemuxer.OnPacket != nil {
psdemuxer.OnPacket(psdemuxer.pkg.Pes, ret) psdemuxer.OnPacket(psdemuxer.pkg.Pes, ret)
} }
if ret == nil { if ret == nil {
if stream, found := psdemuxer.streamMap[psdemuxer.pkg.Pes.Stream_id]; found { if stream, found := psdemuxer.streamMap[psdemuxer.pkg.Pes.Stream_id]; found {
if psdemuxer.mpeg1 && stream.cid == PS_STREAM_UNKNOW { if psdemuxer.mpeg1 && stream.cid == PS_STREAM_UNKNOW {
psdemuxer.guessCodecid(stream) psdemuxer.guessCodecid(stream)
} }
psdemuxer.demuxPespacket(stream, psdemuxer.pkg.Pes) psdemuxer.demuxPespacket(stream, psdemuxer.pkg.Pes)
} else { } else {
if psdemuxer.mpeg1 { if psdemuxer.mpeg1 {
stream := newpsstream(psdemuxer.pkg.Pes.Stream_id, PS_STREAM_UNKNOW) stream := newpsstream(psdemuxer.pkg.Pes.Stream_id, PS_STREAM_UNKNOW)
psdemuxer.streamMap[stream.sid] = stream psdemuxer.streamMap[stream.sid] = stream
stream.streamBuf = append(stream.streamBuf, psdemuxer.pkg.Pes.Pes_payload...) stream.streamBuf = append(stream.streamBuf, psdemuxer.pkg.Pes.Pes_payload...)
stream.pts = psdemuxer.pkg.Pes.Pts stream.pts = psdemuxer.pkg.Pes.Pts
stream.dts = psdemuxer.pkg.Pes.Dts stream.dts = psdemuxer.pkg.Pes.Dts
} }
} }
} }
} else { } else {
bs.SkipBits(8) bs.SkipBits(8)
} }
} }
} }
if ret == nil && len(psdemuxer.cache) > 0 { if ret == nil && len(psdemuxer.cache) > 0 {
psdemuxer.cache = nil psdemuxer.cache = nil
} }
return ret return ret
} }
func (psdemuxer *PSDemuxer) Flush() { func (psdemuxer *PSDemuxer) Flush() {
for _, stream := range psdemuxer.streamMap { for _, stream := range psdemuxer.streamMap {
if len(stream.streamBuf) == 0 { if len(stream.streamBuf) == 0 {
continue continue
} }
if psdemuxer.OnFrame != nil { if psdemuxer.OnFrame != nil {
psdemuxer.OnFrame(stream.streamBuf, stream.cid, stream.pts/90, stream.dts/90) psdemuxer.OnFrame(stream.streamBuf, stream.cid, stream.pts/90, stream.dts/90)
} }
} }
} }
func (psdemuxer *PSDemuxer) guessCodecid(stream *psstream) { func (psdemuxer *PSDemuxer) guessCodecid(stream *psstream) {
if stream.sid&0xE0 == uint8(PES_STREAM_AUDIO) { if stream.sid&0xE0 == uint8(PES_STREAM_AUDIO) {
stream.cid = PS_STREAM_AAC stream.cid = PS_STREAM_AAC
} else if stream.sid&0xE0 == uint8(PES_STREAM_VIDEO) { } else if stream.sid&0xE0 == uint8(PES_STREAM_VIDEO) {
h264score := 0 h264score := 0
h265score := 0 h265score := 0
codec.SplitFrame(stream.streamBuf, func(nalu []byte) bool { codec.SplitFrame(stream.streamBuf, func(nalu []byte) bool {
h264nalutype := codec.H264NaluTypeWithoutStartCode(nalu) h264nalutype := codec.H264NaluTypeWithoutStartCode(nalu)
h265nalutype := codec.H265NaluTypeWithoutStartCode(nalu) h265nalutype := codec.H265NaluTypeWithoutStartCode(nalu)
if h264nalutype == codec.H264_NAL_PPS || if h264nalutype == codec.H264_NAL_PPS ||
h264nalutype == codec.H264_NAL_SPS || h264nalutype == codec.H264_NAL_SPS ||
h264nalutype == codec.H264_NAL_I_SLICE { h264nalutype == codec.H264_NAL_I_SLICE {
h264score += 2 h264score += 2
} else if h264nalutype < 5 { } else if h264nalutype < 5 {
h264score += 1 h264score += 1
} else if h264nalutype > 20 { } else if h264nalutype > 20 {
h264score -= 1 h264score -= 1
} }
if h265nalutype == codec.H265_NAL_PPS || if h265nalutype == codec.H265_NAL_PPS ||
h265nalutype == codec.H265_NAL_SPS || h265nalutype == codec.H265_NAL_SPS ||
h265nalutype == codec.H265_NAL_VPS || h265nalutype == codec.H265_NAL_VPS ||
(h265nalutype >= codec.H265_NAL_SLICE_BLA_W_LP && h265nalutype <= codec.H265_NAL_SLICE_CRA) { (h265nalutype >= codec.H265_NAL_SLICE_BLA_W_LP && h265nalutype <= codec.H265_NAL_SLICE_CRA) {
h265score += 2 h265score += 2
} else if h265nalutype >= codec.H265_NAL_Slice_TRAIL_N && h265nalutype <= codec.H265_NAL_SLICE_RASL_R { } else if h265nalutype >= codec.H265_NAL_Slice_TRAIL_N && h265nalutype <= codec.H265_NAL_SLICE_RASL_R {
h265score += 1 h265score += 1
} else if h265nalutype > 40 { } else if h265nalutype > 40 {
h265score -= 1 h265score -= 1
} }
if h264score > h265score && h264score >= 4 { if h264score > h265score && h264score >= 4 {
stream.cid = PS_STREAM_H264 stream.cid = PS_STREAM_H264
} else if h264score < h265score && h265score >= 4 { } else if h264score < h265score && h265score >= 4 {
stream.cid = PS_STREAM_H265 stream.cid = PS_STREAM_H265
} }
return true return true
}) })
} }
} }
func (psdemuxer *PSDemuxer) demuxPespacket(stream *psstream, pes *PesPacket) error { func (psdemuxer *PSDemuxer) demuxPespacket(stream *psstream, pes *PesPacket) error {
switch stream.cid { switch stream.cid {
case PS_STREAM_AAC, PS_STREAM_G711A, PS_STREAM_G711U: case PS_STREAM_AAC, PS_STREAM_G711A, PS_STREAM_G711U:
return psdemuxer.demuxAudio(stream, pes) return psdemuxer.demuxAudio(stream, pes)
case PS_STREAM_H264, PS_STREAM_H265: case PS_STREAM_H264, PS_STREAM_H265:
return psdemuxer.demuxH26x(stream, pes) return psdemuxer.demuxH26x(stream, pes)
case PS_STREAM_UNKNOW: case PS_STREAM_UNKNOW:
if stream.pts != pes.Pts { if stream.pts != pes.Pts {
stream.streamBuf = nil stream.streamBuf = nil
} }
stream.streamBuf = append(stream.streamBuf, pes.Pes_payload...) stream.streamBuf = append(stream.streamBuf, pes.Pes_payload...)
stream.pts = pes.Pts stream.pts = pes.Pts
stream.dts = pes.Dts stream.dts = pes.Dts
} }
return nil return nil
} }
func (psdemuxer *PSDemuxer) demuxAudio(stream *psstream, pes *PesPacket) error { func (psdemuxer *PSDemuxer) demuxAudio(stream *psstream, pes *PesPacket) error {
if stream.pts != pes.Pts && len(stream.streamBuf) > 0 { if stream.pts != pes.Pts && len(stream.streamBuf) > 0 {
if psdemuxer.OnFrame != nil { if psdemuxer.OnFrame != nil {
psdemuxer.OnFrame(stream.streamBuf, stream.cid, stream.pts/90, stream.dts/90) psdemuxer.OnFrame(stream.streamBuf, stream.cid, stream.pts/90, stream.dts/90)
} }
stream.streamBuf = stream.streamBuf[:0] stream.streamBuf = stream.streamBuf[:0]
} }
stream.streamBuf = append(stream.streamBuf, pes.Pes_payload...) stream.streamBuf = append(stream.streamBuf, pes.Pes_payload...)
stream.pts = pes.Pts stream.pts = pes.Pts
stream.dts = pes.Dts stream.dts = pes.Dts
return nil return nil
} }
func (psdemuxer *PSDemuxer) demuxH26x(stream *psstream, pes *PesPacket) error { func (psdemuxer *PSDemuxer) demuxH26x(stream *psstream, pes *PesPacket) error {
if len(stream.streamBuf) == 0 { if len(stream.streamBuf) == 0 {
stream.pts = pes.Pts stream.pts = pes.Pts
stream.dts = pes.Dts stream.dts = pes.Dts
} }
stream.streamBuf = append(stream.streamBuf, pes.Pes_payload...) stream.streamBuf = append(stream.streamBuf, pes.Pes_payload...)
start, sc := codec.FindStartCode(stream.streamBuf, 0) start, sc := codec.FindStartCode(stream.streamBuf, 0)
for start >= 0 { for start >= 0 {
end, sc2 := codec.FindStartCode(stream.streamBuf, start+int(sc)) end, sc2 := codec.FindStartCode(stream.streamBuf, start+int(sc))
if end < 0 { if end < 0 {
break break
} }
if stream.cid == PS_STREAM_H264 { if stream.cid == PS_STREAM_H264 {
naluType := codec.H264NaluType(stream.streamBuf[start:]) naluType := codec.H264NaluType(stream.streamBuf[start:])
if naluType != codec.H264_NAL_AUD { if naluType != codec.H264_NAL_AUD {
if psdemuxer.OnFrame != nil { if psdemuxer.OnFrame != nil {
psdemuxer.OnFrame(stream.streamBuf[start:end], stream.cid, stream.pts/90, stream.dts/90) psdemuxer.OnFrame(stream.streamBuf[start:end], stream.cid, stream.pts/90, stream.dts/90)
} }
} }
} else if stream.cid == PS_STREAM_H265 { } else if stream.cid == PS_STREAM_H265 {
naluType := codec.H265NaluType(stream.streamBuf[start:]) naluType := codec.H265NaluType(stream.streamBuf[start:])
if naluType != codec.H265_NAL_AUD { if naluType != codec.H265_NAL_AUD {
if psdemuxer.OnFrame != nil { if psdemuxer.OnFrame != nil {
psdemuxer.OnFrame(stream.streamBuf[start:end], stream.cid, stream.pts/90, stream.dts/90) psdemuxer.OnFrame(stream.streamBuf[start:end], stream.cid, stream.pts/90, stream.dts/90)
} }
} }
} }
start = end start = end
sc = sc2 sc = sc2
} }
stream.streamBuf = stream.streamBuf[start:] stream.streamBuf = stream.streamBuf[start:]
stream.pts = pes.Pts stream.pts = pes.Pts
stream.dts = pes.Dts stream.dts = pes.Dts
return nil return nil
} }

View file

@ -3,146 +3,146 @@ package mpeg2
import "github.com/yapingcat/gomedia/codec" import "github.com/yapingcat/gomedia/codec"
type PSMuxer struct { type PSMuxer struct {
system *System_header system *System_header
psm *Program_stream_map psm *Program_stream_map
OnPacket func(pkg []byte) OnPacket func(pkg []byte)
firstframe bool firstframe bool
} }
func NewPsMuxer() *PSMuxer { func NewPsMuxer() *PSMuxer {
muxer := new(PSMuxer) muxer := new(PSMuxer)
muxer.firstframe = true muxer.firstframe = true
muxer.system = new(System_header) muxer.system = new(System_header)
muxer.system.Rate_bound = 26234 muxer.system.Rate_bound = 26234
muxer.psm = new(Program_stream_map) muxer.psm = new(Program_stream_map)
muxer.psm.Current_next_indicator = 1 muxer.psm.Current_next_indicator = 1
muxer.psm.Program_stream_map_version = 1 muxer.psm.Program_stream_map_version = 1
muxer.OnPacket = nil muxer.OnPacket = nil
return muxer return muxer
} }
func (muxer *PSMuxer) AddStream(cid PS_STREAM_TYPE) uint8 { func (muxer *PSMuxer) AddStream(cid PS_STREAM_TYPE) uint8 {
if cid == PS_STREAM_H265 || cid == PS_STREAM_H264 { if cid == PS_STREAM_H265 || cid == PS_STREAM_H264 {
es := NewElementary_Stream(uint8(PES_STREAM_VIDEO) + muxer.system.Video_bound) es := NewElementary_Stream(uint8(PES_STREAM_VIDEO) + muxer.system.Video_bound)
es.P_STD_buffer_bound_scale = 1 es.P_STD_buffer_bound_scale = 1
es.P_STD_buffer_size_bound = 400 es.P_STD_buffer_size_bound = 400
muxer.system.Streams = append(muxer.system.Streams, es) muxer.system.Streams = append(muxer.system.Streams, es)
muxer.system.Video_bound++ muxer.system.Video_bound++
muxer.psm.Stream_map = append(muxer.psm.Stream_map, NewElementary_stream_elem(uint8(cid), es.Stream_id)) muxer.psm.Stream_map = append(muxer.psm.Stream_map, NewElementary_stream_elem(uint8(cid), es.Stream_id))
muxer.psm.Program_stream_map_version++ muxer.psm.Program_stream_map_version++
return es.Stream_id return es.Stream_id
} else { } else {
es := NewElementary_Stream(uint8(PES_STREAM_AUDIO) + muxer.system.Audio_bound) es := NewElementary_Stream(uint8(PES_STREAM_AUDIO) + muxer.system.Audio_bound)
es.P_STD_buffer_bound_scale = 0 es.P_STD_buffer_bound_scale = 0
es.P_STD_buffer_size_bound = 32 es.P_STD_buffer_size_bound = 32
muxer.system.Streams = append(muxer.system.Streams, es) muxer.system.Streams = append(muxer.system.Streams, es)
muxer.system.Audio_bound++ muxer.system.Audio_bound++
muxer.psm.Stream_map = append(muxer.psm.Stream_map, NewElementary_stream_elem(uint8(cid), es.Stream_id)) muxer.psm.Stream_map = append(muxer.psm.Stream_map, NewElementary_stream_elem(uint8(cid), es.Stream_id))
muxer.psm.Program_stream_map_version++ muxer.psm.Program_stream_map_version++
return es.Stream_id return es.Stream_id
} }
} }
func (muxer *PSMuxer) Write(sid uint8, frame []byte, pts uint64, dts uint64) error { func (muxer *PSMuxer) Write(sid uint8, frame []byte, pts uint64, dts uint64) error {
var stream *Elementary_stream_elem = nil var stream *Elementary_stream_elem = nil
for _, es := range muxer.psm.Stream_map { for _, es := range muxer.psm.Stream_map {
if es.Elementary_stream_id == sid { if es.Elementary_stream_id == sid {
stream = es stream = es
break break
} }
} }
if stream == nil { if stream == nil {
return errNotFound return errNotFound
} }
var withaud bool = false var withaud bool = false
var idr_flag bool = false var idr_flag bool = false
var first bool = true var first bool = true
var vcl bool = false var vcl bool = false
if stream.Stream_type == uint8(PS_STREAM_H264) || stream.Stream_type == uint8(PS_STREAM_H265) { if stream.Stream_type == uint8(PS_STREAM_H264) || stream.Stream_type == uint8(PS_STREAM_H265) {
codec.SplitFrame(frame, func(nalu []byte) bool { codec.SplitFrame(frame, func(nalu []byte) bool {
if stream.Stream_type == uint8(PS_STREAM_H264) { if stream.Stream_type == uint8(PS_STREAM_H264) {
nalu_type := codec.H264NaluTypeWithoutStartCode(nalu) nalu_type := codec.H264NaluTypeWithoutStartCode(nalu)
if nalu_type == codec.H264_NAL_AUD { if nalu_type == codec.H264_NAL_AUD {
withaud = true withaud = true
return false return false
} else if codec.IsH264VCLNaluType(nalu_type) { } else if codec.IsH264VCLNaluType(nalu_type) {
if nalu_type == codec.H264_NAL_I_SLICE { if nalu_type == codec.H264_NAL_I_SLICE {
idr_flag = true idr_flag = true
} }
vcl = true vcl = true
return false return false
} }
return true return true
} else { } else {
nalu_type := codec.H265NaluTypeWithoutStartCode(nalu) nalu_type := codec.H265NaluTypeWithoutStartCode(nalu)
if nalu_type == codec.H265_NAL_AUD { if nalu_type == codec.H265_NAL_AUD {
withaud = true withaud = true
return false return false
} else if codec.IsH265VCLNaluType(nalu_type) { } else if codec.IsH265VCLNaluType(nalu_type) {
if nalu_type >= codec.H265_NAL_SLICE_BLA_W_LP && nalu_type <= codec.H265_NAL_SLICE_CRA { if nalu_type >= codec.H265_NAL_SLICE_BLA_W_LP && nalu_type <= codec.H265_NAL_SLICE_CRA {
idr_flag = true idr_flag = true
} }
vcl = true vcl = true
return false return false
} }
return true return true
} }
}) })
} }
dts = dts * 90 dts = dts * 90
pts = pts * 90 pts = pts * 90
bsw := codec.NewBitStreamWriter(1024) bsw := codec.NewBitStreamWriter(1024)
var pack PSPackHeader var pack PSPackHeader
pack.System_clock_reference_base = dts - 3600 pack.System_clock_reference_base = dts - 3600
pack.System_clock_reference_extension = 0 pack.System_clock_reference_extension = 0
pack.Program_mux_rate = 6106 pack.Program_mux_rate = 6106
pack.Encode(bsw) pack.Encode(bsw)
if muxer.firstframe || idr_flag { if muxer.firstframe || idr_flag {
muxer.system.Encode(bsw) muxer.system.Encode(bsw)
muxer.psm.Encode(bsw) muxer.psm.Encode(bsw)
muxer.firstframe = false muxer.firstframe = false
} }
if muxer.OnPacket != nil { if muxer.OnPacket != nil {
muxer.OnPacket(bsw.Bits()) muxer.OnPacket(bsw.Bits())
} }
bsw.Reset() bsw.Reset()
pespkg := NewPesPacket() pespkg := NewPesPacket()
for len(frame) > 0 { for len(frame) > 0 {
peshdrlen := 13 peshdrlen := 13
pespkg.Stream_id = sid pespkg.Stream_id = sid
pespkg.PTS_DTS_flags = 0x03 pespkg.PTS_DTS_flags = 0x03
pespkg.PES_header_data_length = 10 pespkg.PES_header_data_length = 10
pespkg.Pts = pts pespkg.Pts = pts
pespkg.Dts = dts pespkg.Dts = dts
if idr_flag { if idr_flag {
pespkg.Data_alignment_indicator = 1 pespkg.Data_alignment_indicator = 1
} }
if first && !withaud && vcl { if first && !withaud && vcl {
if stream.Stream_type == uint8(PS_STREAM_H264) { if stream.Stream_type == uint8(PS_STREAM_H264) {
pespkg.Pes_payload = append(pespkg.Pes_payload, H264_AUD_NALU...) pespkg.Pes_payload = append(pespkg.Pes_payload, H264_AUD_NALU...)
peshdrlen += 6 peshdrlen += 6
} else if stream.Stream_type == uint8(PS_STREAM_H265) { } else if stream.Stream_type == uint8(PS_STREAM_H265) {
pespkg.Pes_payload = append(pespkg.Pes_payload, H265_AUD_NALU...) pespkg.Pes_payload = append(pespkg.Pes_payload, H265_AUD_NALU...)
peshdrlen += 7 peshdrlen += 7
} }
} }
if peshdrlen+len(frame) >= 0xFFFF { if peshdrlen+len(frame) >= 0xFFFF {
pespkg.PES_packet_length = 0xFFFF pespkg.PES_packet_length = 0xFFFF
pespkg.Pes_payload = append(pespkg.Pes_payload, frame[0:0xFFFF-peshdrlen]...) pespkg.Pes_payload = append(pespkg.Pes_payload, frame[0:0xFFFF-peshdrlen]...)
frame = frame[0xFFFF-peshdrlen:] frame = frame[0xFFFF-peshdrlen:]
} else { } else {
pespkg.PES_packet_length = uint16(peshdrlen + len(frame)) pespkg.PES_packet_length = uint16(peshdrlen + len(frame))
pespkg.Pes_payload = append(pespkg.Pes_payload, frame[0:]...) pespkg.Pes_payload = append(pespkg.Pes_payload, frame[0:]...)
frame = frame[:0] frame = frame[:0]
} }
pespkg.Encode(bsw) pespkg.Encode(bsw)
pespkg.Pes_payload = pespkg.Pes_payload[:0] pespkg.Pes_payload = pespkg.Pes_payload[:0]
if muxer.OnPacket != nil { if muxer.OnPacket != nil {
muxer.OnPacket(bsw.Bits()) muxer.OnPacket(bsw.Bits())
} }
bsw.Reset() bsw.Reset()
first = false first = false
} }
return nil return nil
} }

View file

@ -1,17 +1,17 @@
package mpeg2 package mpeg2
import ( import (
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"os" "os"
"github.com/yapingcat/gomedia/codec" "github.com/yapingcat/gomedia/codec"
) )
type Error interface { type Error interface {
NeedMore() bool NeedMore() bool
ParserError() bool ParserError() bool
StreamIdNotFound() bool StreamIdNotFound() bool
} }
var errNeedMore error = &needmoreError{} var errNeedMore error = &needmoreError{}
@ -44,12 +44,12 @@ func (e *sidNotFoundError) StreamIdNotFound() bool { return true }
type PS_STREAM_TYPE int type PS_STREAM_TYPE int
const ( const (
PS_STREAM_UNKNOW PS_STREAM_TYPE = 0xFF PS_STREAM_UNKNOW PS_STREAM_TYPE = 0xFF
PS_STREAM_AAC PS_STREAM_TYPE = 0x0F PS_STREAM_AAC PS_STREAM_TYPE = 0x0F
PS_STREAM_H264 PS_STREAM_TYPE = 0x1B PS_STREAM_H264 PS_STREAM_TYPE = 0x1B
PS_STREAM_H265 PS_STREAM_TYPE = 0x24 PS_STREAM_H265 PS_STREAM_TYPE = 0x24
PS_STREAM_G711A PS_STREAM_TYPE = 0x90 PS_STREAM_G711A PS_STREAM_TYPE = 0x90
PS_STREAM_G711U PS_STREAM_TYPE = 0x91 PS_STREAM_G711U PS_STREAM_TYPE = 0x91
) )
// Table 2-33 Program Stream pack header // Table 2-33 Program Stream pack header
@ -78,113 +78,113 @@ const (
// } // }
type PSPackHeader struct { type PSPackHeader struct {
IsMpeg1 bool IsMpeg1 bool
System_clock_reference_base uint64 //33 bits System_clock_reference_base uint64 //33 bits
System_clock_reference_extension uint16 //9 bits System_clock_reference_extension uint16 //9 bits
Program_mux_rate uint32 //22 bits Program_mux_rate uint32 //22 bits
Pack_stuffing_length uint8 //3 bitss Pack_stuffing_length uint8 //3 bitss
} }
func (ps_pkg_hdr *PSPackHeader) PrettyPrint(file *os.File) { func (ps_pkg_hdr *PSPackHeader) PrettyPrint(file *os.File) {
file.WriteString(fmt.Sprintf("IsMpeg1:%t\n", ps_pkg_hdr.IsMpeg1)) 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_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("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("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("Pack_stuffing_length:%d\n", ps_pkg_hdr.Pack_stuffing_length))
} }
func (ps_pkg_hdr *PSPackHeader) Decode(bs *codec.BitStream) error { func (ps_pkg_hdr *PSPackHeader) Decode(bs *codec.BitStream) error {
if bs.RemainBytes() < 5 { if bs.RemainBytes() < 5 {
return errNeedMore return errNeedMore
} }
if bs.Uint32(32) != 0x000001BA { if bs.Uint32(32) != 0x000001BA {
panic("ps header must start with 000001BA") panic("ps header must start with 000001BA")
} }
if bs.NextBits(2) == 0x01 { //mpeg2 if bs.NextBits(2) == 0x01 { //mpeg2
if bs.RemainBytes() < 10 { if bs.RemainBytes() < 10 {
return errNeedMore return errNeedMore
} }
return ps_pkg_hdr.decodeMpeg2(bs) return ps_pkg_hdr.decodeMpeg2(bs)
} else if bs.NextBits(4) == 0x02 { //mpeg1 } else if bs.NextBits(4) == 0x02 { //mpeg1
if bs.RemainBytes() < 8 { if bs.RemainBytes() < 8 {
return errNeedMore return errNeedMore
} }
ps_pkg_hdr.IsMpeg1 = true ps_pkg_hdr.IsMpeg1 = true
return ps_pkg_hdr.decodeMpeg1(bs) return ps_pkg_hdr.decodeMpeg1(bs)
} else { } else {
return errParser return errParser
} }
} }
func (ps_pkg_hdr *PSPackHeader) decodeMpeg2(bs *codec.BitStream) error { func (ps_pkg_hdr *PSPackHeader) decodeMpeg2(bs *codec.BitStream) error {
bs.SkipBits(2) bs.SkipBits(2)
ps_pkg_hdr.System_clock_reference_base = bs.GetBits(3) ps_pkg_hdr.System_clock_reference_base = bs.GetBits(3)
bs.SkipBits(1) bs.SkipBits(1)
ps_pkg_hdr.System_clock_reference_base = ps_pkg_hdr.System_clock_reference_base<<15 | bs.GetBits(15) ps_pkg_hdr.System_clock_reference_base = ps_pkg_hdr.System_clock_reference_base<<15 | bs.GetBits(15)
bs.SkipBits(1) bs.SkipBits(1)
ps_pkg_hdr.System_clock_reference_base = ps_pkg_hdr.System_clock_reference_base<<15 | bs.GetBits(15) ps_pkg_hdr.System_clock_reference_base = ps_pkg_hdr.System_clock_reference_base<<15 | bs.GetBits(15)
bs.SkipBits(1) bs.SkipBits(1)
ps_pkg_hdr.System_clock_reference_extension = bs.Uint16(9) ps_pkg_hdr.System_clock_reference_extension = bs.Uint16(9)
bs.SkipBits(1) bs.SkipBits(1)
ps_pkg_hdr.Program_mux_rate = bs.Uint32(22) ps_pkg_hdr.Program_mux_rate = bs.Uint32(22)
bs.SkipBits(1) bs.SkipBits(1)
bs.SkipBits(1) bs.SkipBits(1)
bs.SkipBits(5) bs.SkipBits(5)
ps_pkg_hdr.Pack_stuffing_length = bs.Uint8(3) ps_pkg_hdr.Pack_stuffing_length = bs.Uint8(3)
if bs.RemainBytes() < int(ps_pkg_hdr.Pack_stuffing_length) { if bs.RemainBytes() < int(ps_pkg_hdr.Pack_stuffing_length) {
bs.UnRead(10 * 8) bs.UnRead(10 * 8)
return errNeedMore return errNeedMore
} }
bs.SkipBits(int(ps_pkg_hdr.Pack_stuffing_length) * 8) bs.SkipBits(int(ps_pkg_hdr.Pack_stuffing_length) * 8)
return nil return nil
} }
func (ps_pkg_hdr *PSPackHeader) decodeMpeg1(bs *codec.BitStream) error { func (ps_pkg_hdr *PSPackHeader) decodeMpeg1(bs *codec.BitStream) error {
bs.SkipBits(4) bs.SkipBits(4)
ps_pkg_hdr.System_clock_reference_base = bs.GetBits(3) ps_pkg_hdr.System_clock_reference_base = bs.GetBits(3)
bs.SkipBits(1) bs.SkipBits(1)
ps_pkg_hdr.System_clock_reference_base = ps_pkg_hdr.System_clock_reference_base<<15 | bs.GetBits(15) ps_pkg_hdr.System_clock_reference_base = ps_pkg_hdr.System_clock_reference_base<<15 | bs.GetBits(15)
bs.SkipBits(1) bs.SkipBits(1)
ps_pkg_hdr.System_clock_reference_base = ps_pkg_hdr.System_clock_reference_base<<15 | bs.GetBits(15) ps_pkg_hdr.System_clock_reference_base = ps_pkg_hdr.System_clock_reference_base<<15 | bs.GetBits(15)
bs.SkipBits(1) bs.SkipBits(1)
ps_pkg_hdr.System_clock_reference_extension = 1 ps_pkg_hdr.System_clock_reference_extension = 1
ps_pkg_hdr.Program_mux_rate = bs.Uint32(7) ps_pkg_hdr.Program_mux_rate = bs.Uint32(7)
bs.SkipBits(1) bs.SkipBits(1)
ps_pkg_hdr.Program_mux_rate = ps_pkg_hdr.Program_mux_rate<<15 | bs.Uint32(15) ps_pkg_hdr.Program_mux_rate = ps_pkg_hdr.Program_mux_rate<<15 | bs.Uint32(15)
bs.SkipBits(1) bs.SkipBits(1)
return nil return nil
} }
func (ps_pkg_hdr *PSPackHeader) Encode(bsw *codec.BitStreamWriter) { func (ps_pkg_hdr *PSPackHeader) Encode(bsw *codec.BitStreamWriter) {
bsw.PutBytes([]byte{0x00, 0x00, 0x01, 0xBA}) bsw.PutBytes([]byte{0x00, 0x00, 0x01, 0xBA})
bsw.PutUint8(1, 2) bsw.PutUint8(1, 2)
bsw.PutUint64(ps_pkg_hdr.System_clock_reference_base>>30, 3) bsw.PutUint64(ps_pkg_hdr.System_clock_reference_base>>30, 3)
bsw.PutUint8(1, 1) bsw.PutUint8(1, 1)
bsw.PutUint64(ps_pkg_hdr.System_clock_reference_base>>15, 15) bsw.PutUint64(ps_pkg_hdr.System_clock_reference_base>>15, 15)
bsw.PutUint8(1, 1) bsw.PutUint8(1, 1)
bsw.PutUint64(ps_pkg_hdr.System_clock_reference_base, 15) bsw.PutUint64(ps_pkg_hdr.System_clock_reference_base, 15)
bsw.PutUint8(1, 1) bsw.PutUint8(1, 1)
bsw.PutUint16(ps_pkg_hdr.System_clock_reference_extension, 9) bsw.PutUint16(ps_pkg_hdr.System_clock_reference_extension, 9)
bsw.PutUint8(1, 1) bsw.PutUint8(1, 1)
bsw.PutUint32(ps_pkg_hdr.Program_mux_rate, 22) bsw.PutUint32(ps_pkg_hdr.Program_mux_rate, 22)
bsw.PutUint8(1, 1) bsw.PutUint8(1, 1)
bsw.PutUint8(1, 1) bsw.PutUint8(1, 1)
bsw.PutUint8(0x1F, 5) bsw.PutUint8(0x1F, 5)
bsw.PutUint8(ps_pkg_hdr.Pack_stuffing_length, 3) bsw.PutUint8(ps_pkg_hdr.Pack_stuffing_length, 3)
bsw.PutRepetValue(0xFF, int(ps_pkg_hdr.Pack_stuffing_length)) bsw.PutRepetValue(0xFF, int(ps_pkg_hdr.Pack_stuffing_length))
} }
type Elementary_Stream struct { type Elementary_Stream struct {
Stream_id uint8 Stream_id uint8
P_STD_buffer_bound_scale uint8 P_STD_buffer_bound_scale uint8
P_STD_buffer_size_bound uint16 P_STD_buffer_size_bound uint16
} }
func NewElementary_Stream(sid uint8) *Elementary_Stream { func NewElementary_Stream(sid uint8) *Elementary_Stream {
return &Elementary_Stream{ return &Elementary_Stream{
Stream_id: sid, Stream_id: sid,
} }
} }
// system_header () { // system_header () {
@ -211,118 +211,118 @@ func NewElementary_Stream(sid uint8) *Elementary_Stream {
// } // }
type System_header struct { type System_header struct {
Header_length uint16 Header_length uint16
Rate_bound uint32 Rate_bound uint32
Audio_bound uint8 Audio_bound uint8
Fixed_flag uint8 Fixed_flag uint8
CSPS_flag uint8 CSPS_flag uint8
System_audio_lock_flag uint8 System_audio_lock_flag uint8
System_video_lock_flag uint8 System_video_lock_flag uint8
Video_bound uint8 Video_bound uint8
Packet_rate_restriction_flag uint8 Packet_rate_restriction_flag uint8
Streams []*Elementary_Stream Streams []*Elementary_Stream
} }
func (sh *System_header) PrettyPrint(file *os.File) { func (sh *System_header) PrettyPrint(file *os.File) {
file.WriteString(fmt.Sprintf("Header_length:%d\n", sh.Header_length)) 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("Rate_bound:%d\n", sh.Rate_bound))
file.WriteString(fmt.Sprintf("Audio_bound:%d\n", sh.Audio_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("Fixed_flag:%d\n", sh.Fixed_flag))
file.WriteString(fmt.Sprintf("CSPS_flag:%d\n", sh.CSPS_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_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("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("Video_bound:%d\n", sh.Video_bound))
file.WriteString(fmt.Sprintf("Packet_rate_restriction_flag:%d\n", sh.Packet_rate_restriction_flag)) file.WriteString(fmt.Sprintf("Packet_rate_restriction_flag:%d\n", sh.Packet_rate_restriction_flag))
for i, es := range sh.Streams { for i, es := range sh.Streams {
file.WriteString(fmt.Sprintf("----streams %d\n", i)) file.WriteString(fmt.Sprintf("----streams %d\n", i))
file.WriteString(fmt.Sprintf(" Stream_id:%d\n", es.Stream_id)) 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_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(" P_STD_buffer_size_bound:%d\n", es.P_STD_buffer_size_bound))
} }
} }
func (sh *System_header) Encode(bsw *codec.BitStreamWriter) { func (sh *System_header) Encode(bsw *codec.BitStreamWriter) {
bsw.PutBytes([]byte{0x00, 0x00, 0x01, 0xBB}) bsw.PutBytes([]byte{0x00, 0x00, 0x01, 0xBB})
loc := bsw.ByteOffset() loc := bsw.ByteOffset()
bsw.PutUint16(0, 16) bsw.PutUint16(0, 16)
bsw.Markdot() bsw.Markdot()
bsw.PutUint8(1, 1) bsw.PutUint8(1, 1)
bsw.PutUint32(sh.Rate_bound, 22) bsw.PutUint32(sh.Rate_bound, 22)
bsw.PutUint8(1, 1) bsw.PutUint8(1, 1)
bsw.PutUint8(sh.Audio_bound, 6) bsw.PutUint8(sh.Audio_bound, 6)
bsw.PutUint8(sh.Fixed_flag, 1) bsw.PutUint8(sh.Fixed_flag, 1)
bsw.PutUint8(sh.CSPS_flag, 1) bsw.PutUint8(sh.CSPS_flag, 1)
bsw.PutUint8(sh.System_audio_lock_flag, 1) bsw.PutUint8(sh.System_audio_lock_flag, 1)
bsw.PutUint8(sh.System_video_lock_flag, 1) bsw.PutUint8(sh.System_video_lock_flag, 1)
bsw.PutUint8(1, 1) bsw.PutUint8(1, 1)
bsw.PutUint8(sh.Video_bound, 5) bsw.PutUint8(sh.Video_bound, 5)
bsw.PutUint8(sh.Packet_rate_restriction_flag, 1) bsw.PutUint8(sh.Packet_rate_restriction_flag, 1)
bsw.PutUint8(0x7F, 7) bsw.PutUint8(0x7F, 7)
for _, stream := range sh.Streams { for _, stream := range sh.Streams {
bsw.PutUint8(stream.Stream_id, 8) bsw.PutUint8(stream.Stream_id, 8)
bsw.PutUint8(3, 2) bsw.PutUint8(3, 2)
bsw.PutUint8(stream.P_STD_buffer_bound_scale, 1) bsw.PutUint8(stream.P_STD_buffer_bound_scale, 1)
bsw.PutUint16(stream.P_STD_buffer_size_bound, 13) bsw.PutUint16(stream.P_STD_buffer_size_bound, 13)
} }
length := bsw.DistanceFromMarkDot() / 8 length := bsw.DistanceFromMarkDot() / 8
bsw.SetUint16(uint16(length), loc) bsw.SetUint16(uint16(length), loc)
} }
func (sh *System_header) Decode(bs *codec.BitStream) error { func (sh *System_header) Decode(bs *codec.BitStream) error {
if bs.RemainBytes() < 12 { if bs.RemainBytes() < 12 {
return errNeedMore return errNeedMore
} }
if bs.Uint32(32) != 0x000001BB { if bs.Uint32(32) != 0x000001BB {
panic("system header must start with 000001BB") panic("system header must start with 000001BB")
} }
sh.Header_length = bs.Uint16(16) sh.Header_length = bs.Uint16(16)
if bs.RemainBytes() < int(sh.Header_length) { if bs.RemainBytes() < int(sh.Header_length) {
bs.UnRead(6 * 8) bs.UnRead(6 * 8)
return errNeedMore return errNeedMore
} }
if sh.Header_length < 6 || (sh.Header_length-6)%3 != 0 { if sh.Header_length < 6 || (sh.Header_length-6)%3 != 0 {
return errParser return errParser
} }
bs.SkipBits(1) bs.SkipBits(1)
sh.Rate_bound = bs.Uint32(22) sh.Rate_bound = bs.Uint32(22)
bs.SkipBits(1) bs.SkipBits(1)
sh.Audio_bound = bs.Uint8(6) sh.Audio_bound = bs.Uint8(6)
sh.Fixed_flag = bs.Uint8(1) sh.Fixed_flag = bs.Uint8(1)
sh.CSPS_flag = bs.Uint8(1) sh.CSPS_flag = bs.Uint8(1)
sh.System_audio_lock_flag = bs.Uint8(1) sh.System_audio_lock_flag = bs.Uint8(1)
sh.System_video_lock_flag = bs.Uint8(1) sh.System_video_lock_flag = bs.Uint8(1)
bs.SkipBits(1) bs.SkipBits(1)
sh.Video_bound = bs.Uint8(5) sh.Video_bound = bs.Uint8(5)
sh.Packet_rate_restriction_flag = bs.Uint8(1) sh.Packet_rate_restriction_flag = bs.Uint8(1)
bs.SkipBits(7) bs.SkipBits(7)
sh.Streams = sh.Streams[:0] sh.Streams = sh.Streams[:0]
least := sh.Header_length - 6 least := sh.Header_length - 6
for least > 0 && bs.NextBits(1) == 0x01 { for least > 0 && bs.NextBits(1) == 0x01 {
es := new(Elementary_Stream) es := new(Elementary_Stream)
es.Stream_id = bs.Uint8(8) es.Stream_id = bs.Uint8(8)
bs.SkipBits(2) bs.SkipBits(2)
es.P_STD_buffer_bound_scale = bs.GetBit() es.P_STD_buffer_bound_scale = bs.GetBit()
es.P_STD_buffer_size_bound = bs.Uint16(13) es.P_STD_buffer_size_bound = bs.Uint16(13)
sh.Streams = append(sh.Streams, es) sh.Streams = append(sh.Streams, es)
least -= 3 least -= 3
} }
if least > 0 { if least > 0 {
return errParser return errParser
} }
return nil return nil
} }
type Elementary_stream_elem struct { type Elementary_stream_elem struct {
Stream_type uint8 Stream_type uint8
Elementary_stream_id uint8 Elementary_stream_id uint8
Elementary_stream_info_length uint16 Elementary_stream_info_length uint16
} }
func NewElementary_stream_elem(stype uint8, esid uint8) *Elementary_stream_elem { func NewElementary_stream_elem(stype uint8, esid uint8) *Elementary_stream_elem {
return &Elementary_stream_elem{ return &Elementary_stream_elem{
Stream_type: stype, Stream_type: stype,
Elementary_stream_id: esid, Elementary_stream_id: esid,
} }
} }
// program_stream_map() { // program_stream_map() {
@ -351,171 +351,171 @@ func NewElementary_stream_elem(stype uint8, esid uint8) *Elementary_stream_elem
// } // }
type Program_stream_map struct { type Program_stream_map struct {
Map_stream_id uint8 Map_stream_id uint8
Program_stream_map_length uint16 Program_stream_map_length uint16
Current_next_indicator uint8 Current_next_indicator uint8
Program_stream_map_version uint8 Program_stream_map_version uint8
Program_stream_info_length uint16 Program_stream_info_length uint16
Elementary_stream_map_length uint16 Elementary_stream_map_length uint16
Stream_map []*Elementary_stream_elem Stream_map []*Elementary_stream_elem
} }
func (psm *Program_stream_map) PrettyPrint(file *os.File) { 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("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("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("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_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("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)) file.WriteString(fmt.Sprintf("elementary_stream_map_length:%d\n", psm.Elementary_stream_map_length))
for i, es := range psm.Stream_map { for i, es := range psm.Stream_map {
file.WriteString(fmt.Sprintf("----ES stream %d\n", i)) file.WriteString(fmt.Sprintf("----ES stream %d\n", i))
if es.Stream_type == uint8(PS_STREAM_AAC) { if es.Stream_type == uint8(PS_STREAM_AAC) {
file.WriteString(" stream_type:AAC\n") file.WriteString(" stream_type:AAC\n")
} else if es.Stream_type == uint8(PS_STREAM_G711A) { } else if es.Stream_type == uint8(PS_STREAM_G711A) {
file.WriteString(" stream_type:G711A\n") file.WriteString(" stream_type:G711A\n")
} else if es.Stream_type == uint8(PS_STREAM_G711U) { } else if es.Stream_type == uint8(PS_STREAM_G711U) {
file.WriteString(" stream_type:G711U\n") file.WriteString(" stream_type:G711U\n")
} else if es.Stream_type == uint8(PS_STREAM_H264) { } else if es.Stream_type == uint8(PS_STREAM_H264) {
file.WriteString(" stream_type:H264\n") file.WriteString(" stream_type:H264\n")
} else if es.Stream_type == uint8(PS_STREAM_H265) { } else if es.Stream_type == uint8(PS_STREAM_H265) {
file.WriteString(" stream_type:H265\n") 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_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(" elementary_stream_info_length:%d\n", es.Elementary_stream_info_length))
} }
} }
func (psm *Program_stream_map) Encode(bsw *codec.BitStreamWriter) { func (psm *Program_stream_map) Encode(bsw *codec.BitStreamWriter) {
bsw.PutBytes([]byte{0x00, 0x00, 0x01, 0xBC}) bsw.PutBytes([]byte{0x00, 0x00, 0x01, 0xBC})
loc := bsw.ByteOffset() loc := bsw.ByteOffset()
bsw.PutUint16(psm.Program_stream_map_length, 16) bsw.PutUint16(psm.Program_stream_map_length, 16)
bsw.Markdot() bsw.Markdot()
bsw.PutUint8(psm.Current_next_indicator, 1) bsw.PutUint8(psm.Current_next_indicator, 1)
bsw.PutUint8(3, 2) bsw.PutUint8(3, 2)
bsw.PutUint8(psm.Program_stream_map_version, 5) bsw.PutUint8(psm.Program_stream_map_version, 5)
bsw.PutUint8(0x7F, 7) bsw.PutUint8(0x7F, 7)
bsw.PutUint8(1, 1) bsw.PutUint8(1, 1)
bsw.PutUint16(0, 16) bsw.PutUint16(0, 16)
psm.Elementary_stream_map_length = uint16(len(psm.Stream_map) * 4) psm.Elementary_stream_map_length = uint16(len(psm.Stream_map) * 4)
bsw.PutUint16(psm.Elementary_stream_map_length, 16) bsw.PutUint16(psm.Elementary_stream_map_length, 16)
for _, streaminfo := range psm.Stream_map { for _, streaminfo := range psm.Stream_map {
bsw.PutUint8(streaminfo.Stream_type, 8) bsw.PutUint8(streaminfo.Stream_type, 8)
bsw.PutUint8(streaminfo.Elementary_stream_id, 8) bsw.PutUint8(streaminfo.Elementary_stream_id, 8)
bsw.PutUint16(0, 16) bsw.PutUint16(0, 16)
} }
length := bsw.DistanceFromMarkDot()/8 + 4 length := bsw.DistanceFromMarkDot()/8 + 4
bsw.SetUint16(uint16(length), loc) bsw.SetUint16(uint16(length), loc)
crc := codec.CalcCrc32(0xffffffff, bsw.Bits()[bsw.ByteOffset()-int(length-4)-4:bsw.ByteOffset()]) crc := codec.CalcCrc32(0xffffffff, bsw.Bits()[bsw.ByteOffset()-int(length-4)-4:bsw.ByteOffset()])
tmpcrc := make([]byte, 4) tmpcrc := make([]byte, 4)
binary.LittleEndian.PutUint32(tmpcrc, crc) binary.LittleEndian.PutUint32(tmpcrc, crc)
bsw.PutBytes(tmpcrc) bsw.PutBytes(tmpcrc)
} }
func (psm *Program_stream_map) Decode(bs *codec.BitStream) error { func (psm *Program_stream_map) Decode(bs *codec.BitStream) error {
if bs.RemainBytes() < 16 { if bs.RemainBytes() < 16 {
return errNeedMore return errNeedMore
} }
if bs.Uint32(24) != 0x000001 { if bs.Uint32(24) != 0x000001 {
panic("program stream map must startwith 0x000001") panic("program stream map must startwith 0x000001")
} }
psm.Map_stream_id = bs.Uint8(8) psm.Map_stream_id = bs.Uint8(8)
if psm.Map_stream_id != 0xBC { if psm.Map_stream_id != 0xBC {
panic("map stream id must be 0xBC") panic("map stream id must be 0xBC")
} }
psm.Program_stream_map_length = bs.Uint16(16) psm.Program_stream_map_length = bs.Uint16(16)
if bs.RemainBytes() < int(psm.Program_stream_map_length) { if bs.RemainBytes() < int(psm.Program_stream_map_length) {
bs.UnRead(6 * 8) bs.UnRead(6 * 8)
return errNeedMore return errNeedMore
} }
psm.Current_next_indicator = bs.Uint8(1) psm.Current_next_indicator = bs.Uint8(1)
bs.SkipBits(2) bs.SkipBits(2)
psm.Program_stream_map_version = bs.Uint8(5) psm.Program_stream_map_version = bs.Uint8(5)
bs.SkipBits(8) bs.SkipBits(8)
psm.Program_stream_info_length = bs.Uint16(16) psm.Program_stream_info_length = bs.Uint16(16)
if bs.RemainBytes() < int(psm.Program_stream_info_length)+2 { if bs.RemainBytes() < int(psm.Program_stream_info_length)+2 {
bs.UnRead(10 * 8) bs.UnRead(10 * 8)
return errNeedMore return errNeedMore
} }
bs.SkipBits(int(psm.Program_stream_info_length) * 8) bs.SkipBits(int(psm.Program_stream_info_length) * 8)
psm.Elementary_stream_map_length = bs.Uint16(16) 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 { if psm.Program_stream_map_length != 6+psm.Program_stream_info_length+psm.Elementary_stream_map_length+4 {
return errParser return errParser
} }
if bs.RemainBytes() < int(psm.Elementary_stream_map_length)+4 { if bs.RemainBytes() < int(psm.Elementary_stream_map_length)+4 {
bs.UnRead(12*8 + int(psm.Program_stream_info_length)*8) bs.UnRead(12*8 + int(psm.Program_stream_info_length)*8)
return errNeedMore return errNeedMore
} }
i := 0 i := 0
psm.Stream_map = psm.Stream_map[:0] psm.Stream_map = psm.Stream_map[:0]
for i < int(psm.Elementary_stream_map_length) { for i < int(psm.Elementary_stream_map_length) {
elem := new(Elementary_stream_elem) elem := new(Elementary_stream_elem)
elem.Stream_type = bs.Uint8(8) elem.Stream_type = bs.Uint8(8)
elem.Elementary_stream_id = bs.Uint8(8) elem.Elementary_stream_id = bs.Uint8(8)
elem.Elementary_stream_info_length = bs.Uint16(16) elem.Elementary_stream_info_length = bs.Uint16(16)
//TODO Parser descriptor //TODO Parser descriptor
if bs.RemainBytes() < int(elem.Elementary_stream_info_length) { if bs.RemainBytes() < int(elem.Elementary_stream_info_length) {
return errParser return errParser
} }
bs.SkipBits(int(elem.Elementary_stream_info_length) * 8) bs.SkipBits(int(elem.Elementary_stream_info_length) * 8)
i += int(4 + elem.Elementary_stream_info_length) i += int(4 + elem.Elementary_stream_info_length)
psm.Stream_map = append(psm.Stream_map, elem) psm.Stream_map = append(psm.Stream_map, elem)
} }
if i != int(psm.Elementary_stream_map_length) { if i != int(psm.Elementary_stream_map_length) {
return errParser return errParser
} }
bs.SkipBits(32) bs.SkipBits(32)
return nil return nil
} }
type Program_stream_directory struct { type Program_stream_directory struct {
PES_packet_length uint16 PES_packet_length uint16
} }
func (psd *Program_stream_directory) Decode(bs *codec.BitStream) error { func (psd *Program_stream_directory) Decode(bs *codec.BitStream) error {
if bs.RemainBytes() < 6 { if bs.RemainBytes() < 6 {
return errNeedMore return errNeedMore
} }
if bs.Uint32(32) != 0x000001FF { if bs.Uint32(32) != 0x000001FF {
panic("program stream directory 000001FF") panic("program stream directory 000001FF")
} }
psd.PES_packet_length = bs.Uint16(16) psd.PES_packet_length = bs.Uint16(16)
if bs.RemainBytes() < int(psd.PES_packet_length) { if bs.RemainBytes() < int(psd.PES_packet_length) {
bs.UnRead(6 * 8) bs.UnRead(6 * 8)
return errNeedMore return errNeedMore
} }
//TODO Program Stream directory //TODO Program Stream directory
bs.SkipBits(int(psd.PES_packet_length) * 8) bs.SkipBits(int(psd.PES_packet_length) * 8)
return nil return nil
} }
type CommonPesPacket struct { type CommonPesPacket struct {
Stream_id uint8 Stream_id uint8
PES_packet_length uint16 PES_packet_length uint16
} }
func (compes *CommonPesPacket) Decode(bs *codec.BitStream) error { func (compes *CommonPesPacket) Decode(bs *codec.BitStream) error {
if bs.RemainBytes() < 6 { if bs.RemainBytes() < 6 {
return errNeedMore return errNeedMore
} }
bs.SkipBits(24) bs.SkipBits(24)
compes.Stream_id = bs.Uint8(8) compes.Stream_id = bs.Uint8(8)
compes.PES_packet_length = bs.Uint16(16) compes.PES_packet_length = bs.Uint16(16)
if bs.RemainBytes() < int(compes.PES_packet_length) { if bs.RemainBytes() < int(compes.PES_packet_length) {
bs.UnRead(6 * 8) bs.UnRead(6 * 8)
return errNeedMore return errNeedMore
} }
bs.SkipBits(int(compes.PES_packet_length) * 8) bs.SkipBits(int(compes.PES_packet_length) * 8)
return nil return nil
} }
type PSPacket struct { type PSPacket struct {
Header *PSPackHeader Header *PSPackHeader
System *System_header System *System_header
Psm *Program_stream_map Psm *Program_stream_map
Psd *Program_stream_directory Psd *Program_stream_directory
CommPes *CommonPesPacket CommPes *CommonPesPacket
Pes *PesPacket Pes *PesPacket
} }

View file

@ -1,218 +1,218 @@
package mpeg2 package mpeg2
import ( import (
"errors" "errors"
"io" "io"
"github.com/yapingcat/gomedia/codec" "github.com/yapingcat/gomedia/codec"
) )
type pakcet_t struct { type pakcet_t struct {
payload []byte payload []byte
pts uint64 pts uint64
dts uint64 dts uint64
} }
func newPacket_t(size uint32) *pakcet_t { func newPacket_t(size uint32) *pakcet_t {
return &pakcet_t{ return &pakcet_t{
payload: make([]byte, 0, size), payload: make([]byte, 0, size),
pts: 0, pts: 0,
dts: 0, dts: 0,
} }
} }
type tsstream struct { type tsstream struct {
cid TS_STREAM_TYPE cid TS_STREAM_TYPE
pes_sid PES_STREMA_ID pes_sid PES_STREMA_ID
pes_pkg *PesPacket pes_pkg *PesPacket
pkg *pakcet_t pkg *pakcet_t
} }
type tsprogram struct { type tsprogram struct {
pn uint16 pn uint16
streams map[uint16]*tsstream streams map[uint16]*tsstream
} }
type TSDemuxer struct { type TSDemuxer struct {
programs map[uint16]*tsprogram programs map[uint16]*tsprogram
OnFrame func(cid TS_STREAM_TYPE, frame []byte, pts uint64, dts uint64) OnFrame func(cid TS_STREAM_TYPE, frame []byte, pts uint64, dts uint64)
OnTSPacket func(pkg *TSPacket) OnTSPacket func(pkg *TSPacket)
} }
func NewTSDemuxer() *TSDemuxer { func NewTSDemuxer() *TSDemuxer {
return &TSDemuxer{ return &TSDemuxer{
programs: make(map[uint16]*tsprogram), programs: make(map[uint16]*tsprogram),
OnFrame: nil, OnFrame: nil,
OnTSPacket: nil, OnTSPacket: nil,
} }
} }
func (demuxer *TSDemuxer) Input(r io.Reader) error { func (demuxer *TSDemuxer) Input(r io.Reader) error {
buf := make([]byte, TS_PAKCET_SIZE) buf := make([]byte, TS_PAKCET_SIZE)
_, err := io.ReadFull(r, buf) _, err := io.ReadFull(r, buf)
if err != nil { if err != nil {
return errNeedMore return errNeedMore
} }
for { for {
bs := codec.NewBitStream(buf) bs := codec.NewBitStream(buf)
var pkg TSPacket var pkg TSPacket
if err := pkg.DecodeHeader(bs); err != nil { if err := pkg.DecodeHeader(bs); err != nil {
return err return err
} }
if pkg.PID == uint16(TS_PID_PAT) { if pkg.PID == uint16(TS_PID_PAT) {
if pkg.Payload_unit_start_indicator == 1 { if pkg.Payload_unit_start_indicator == 1 {
bs.SkipBits(8) bs.SkipBits(8)
} }
pat := NewPat() pat := NewPat()
if err := pat.Decode(bs); err != nil { if err := pat.Decode(bs); err != nil {
return err return err
} }
pkg.Payload = pat pkg.Payload = pat
if pat.Table_id != uint8(TS_TID_PAS) { if pat.Table_id != uint8(TS_TID_PAS) {
return errors.New("pat table id is wrong") return errors.New("pat table id is wrong")
} }
for _, pmt := range pat.Pmts { for _, pmt := range pat.Pmts {
if pmt.Program_number != 0x0000 { if pmt.Program_number != 0x0000 {
if _, found := demuxer.programs[pmt.PID]; !found { if _, found := demuxer.programs[pmt.PID]; !found {
demuxer.programs[pmt.PID] = &tsprogram{pn: 0, streams: make(map[uint16]*tsstream)} demuxer.programs[pmt.PID] = &tsprogram{pn: 0, streams: make(map[uint16]*tsstream)}
} }
} }
} }
} else { } else {
for p, s := range demuxer.programs { for p, s := range demuxer.programs {
if p == pkg.PID { // pmt table if p == pkg.PID { // pmt table
if pkg.Payload_unit_start_indicator == 1 { if pkg.Payload_unit_start_indicator == 1 {
bs.SkipBits(8) //pointer filed bs.SkipBits(8) //pointer filed
} }
pmt := NewPmt() pmt := NewPmt()
if err := pmt.Decode(bs); err != nil { if err := pmt.Decode(bs); err != nil {
return err return err
} }
pkg.Payload = pmt pkg.Payload = pmt
s.pn = pmt.Program_number s.pn = pmt.Program_number
for _, ps := range pmt.Streams { for _, ps := range pmt.Streams {
if _, found := s.streams[ps.Elementary_PID]; !found { if _, found := s.streams[ps.Elementary_PID]; !found {
s.streams[ps.Elementary_PID] = &tsstream{ s.streams[ps.Elementary_PID] = &tsstream{
cid: TS_STREAM_TYPE(ps.StreamType), cid: TS_STREAM_TYPE(ps.StreamType),
pes_sid: findPESIDByStreamType(TS_STREAM_TYPE(ps.StreamType)), pes_sid: findPESIDByStreamType(TS_STREAM_TYPE(ps.StreamType)),
pes_pkg: NewPesPacket(), pes_pkg: NewPesPacket(),
} }
} }
} }
} else { } else {
for sid, stream := range s.streams { for sid, stream := range s.streams {
if sid != pkg.PID { if sid != pkg.PID {
continue continue
} }
if pkg.Payload_unit_start_indicator == 1 { if pkg.Payload_unit_start_indicator == 1 {
err := stream.pes_pkg.Decode(bs) err := stream.pes_pkg.Decode(bs)
// ignore error if it was a short payload read, next ts packet should append missing data // 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) { if err != nil && !(errors.Is(err, errNeedMore) && stream.pes_pkg.Pes_payload != nil) {
return err return err
} }
pkg.Payload = stream.pes_pkg pkg.Payload = stream.pes_pkg
} else { } else {
stream.pes_pkg.Pes_payload = bs.RemainData() stream.pes_pkg.Pes_payload = bs.RemainData()
pkg.Payload = bs.RemainData() pkg.Payload = bs.RemainData()
} }
stype := findPESIDByStreamType(stream.cid) stype := findPESIDByStreamType(stream.cid)
if stype == PES_STREAM_AUDIO { if stype == PES_STREAM_AUDIO {
demuxer.doAudioPesPacket(stream, pkg.Payload_unit_start_indicator) demuxer.doAudioPesPacket(stream, pkg.Payload_unit_start_indicator)
} else if stype == PES_STREAM_VIDEO { } else if stype == PES_STREAM_VIDEO {
demuxer.doVideoPesPacket(stream, pkg.Payload_unit_start_indicator) demuxer.doVideoPesPacket(stream, pkg.Payload_unit_start_indicator)
} }
} }
} }
} }
} }
if demuxer.OnTSPacket != nil { if demuxer.OnTSPacket != nil {
demuxer.OnTSPacket(&pkg) demuxer.OnTSPacket(&pkg)
} }
_, err := io.ReadFull(r, buf) _, err := io.ReadFull(r, buf)
if err != nil { if err != nil {
if errors.Is(err, io.EOF) { if errors.Is(err, io.EOF) {
break break
} else { } else {
return errNeedMore return errNeedMore
} }
} }
} }
demuxer.flush() demuxer.flush()
return nil return nil
} }
func (demuxer *TSDemuxer) flush() { func (demuxer *TSDemuxer) flush() {
for _, pm := range demuxer.programs { for _, pm := range demuxer.programs {
for _, stream := range pm.streams { for _, stream := range pm.streams {
if stream.pkg == nil || len(stream.pkg.payload) == 0 { if stream.pkg == nil || len(stream.pkg.payload) == 0 {
continue continue
} }
if demuxer.OnFrame != nil { if demuxer.OnFrame != nil {
demuxer.OnFrame(stream.cid, stream.pkg.payload, stream.pkg.pts/90, stream.pkg.dts/90) demuxer.OnFrame(stream.cid, stream.pkg.payload, stream.pkg.pts/90, stream.pkg.dts/90)
} }
} }
} }
} }
func (demuxer *TSDemuxer) doVideoPesPacket(stream *tsstream, start uint8) { func (demuxer *TSDemuxer) doVideoPesPacket(stream *tsstream, start uint8) {
if stream.cid != TS_STREAM_H264 && stream.cid != TS_STREAM_H265 { if stream.cid != TS_STREAM_H264 && stream.cid != TS_STREAM_H265 {
return return
} }
if stream.pkg == nil { if stream.pkg == nil {
stream.pkg = newPacket_t(1024) stream.pkg = newPacket_t(1024)
stream.pkg.pts = stream.pes_pkg.Pts stream.pkg.pts = stream.pes_pkg.Pts
stream.pkg.dts = stream.pes_pkg.Dts stream.pkg.dts = stream.pes_pkg.Dts
} }
stream.pkg.payload = append(stream.pkg.payload, stream.pes_pkg.Pes_payload...) stream.pkg.payload = append(stream.pkg.payload, stream.pes_pkg.Pes_payload...)
demuxer.splitH26XFrame(stream) demuxer.splitH26XFrame(stream)
stream.pkg.pts = stream.pes_pkg.Pts stream.pkg.pts = stream.pes_pkg.Pts
stream.pkg.dts = stream.pes_pkg.Dts stream.pkg.dts = stream.pes_pkg.Dts
} }
func (demuxer *TSDemuxer) doAudioPesPacket(stream *tsstream, start uint8) { func (demuxer *TSDemuxer) doAudioPesPacket(stream *tsstream, start uint8) {
if stream.cid != TS_STREAM_AAC { if stream.cid != TS_STREAM_AAC {
return return
} }
if stream.pkg == nil { if stream.pkg == nil {
stream.pkg = newPacket_t(1024) stream.pkg = newPacket_t(1024)
stream.pkg.pts = stream.pes_pkg.Pts stream.pkg.pts = stream.pes_pkg.Pts
stream.pkg.dts = stream.pes_pkg.Dts stream.pkg.dts = stream.pes_pkg.Dts
} }
if len(stream.pkg.payload) > 0 && (start == 1 || stream.pes_pkg.Pts != stream.pkg.pts) { if len(stream.pkg.payload) > 0 && (start == 1 || stream.pes_pkg.Pts != stream.pkg.pts) {
if demuxer.OnFrame != nil { if demuxer.OnFrame != nil {
demuxer.OnFrame(stream.cid, stream.pkg.payload, stream.pkg.pts/90, stream.pkg.dts/90) 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 = stream.pkg.payload[:0]
} }
stream.pkg.payload = append(stream.pkg.payload, stream.pes_pkg.Pes_payload...) stream.pkg.payload = append(stream.pkg.payload, stream.pes_pkg.Pes_payload...)
stream.pkg.pts = stream.pes_pkg.Pts stream.pkg.pts = stream.pes_pkg.Pts
stream.pkg.dts = stream.pes_pkg.Dts stream.pkg.dts = stream.pes_pkg.Dts
} }
func (demuxer *TSDemuxer) splitH26XFrame(stream *tsstream) { func (demuxer *TSDemuxer) splitH26XFrame(stream *tsstream) {
data := stream.pkg.payload data := stream.pkg.payload
start, _ := codec.FindStartCode(data, 0) start, _ := codec.FindStartCode(data, 0)
datalen := len(data) datalen := len(data)
for start < datalen { for start < datalen {
end, _ := codec.FindStartCode(data, start+3) end, _ := codec.FindStartCode(data, start+3)
if end < 0 { if end < 0 {
break break
} }
if (stream.cid == TS_STREAM_H264 && codec.H264NaluTypeWithoutStartCode(data[start:end]) == codec.H264_NAL_AUD) || 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) { (stream.cid == TS_STREAM_H265 && codec.H265NaluTypeWithoutStartCode(data[start:end]) == codec.H265_NAL_AUD) {
start = end start = end
continue continue
} }
if demuxer.OnFrame != nil { if demuxer.OnFrame != nil {
demuxer.OnFrame(stream.cid, data[start:end], stream.pkg.pts/90, stream.pkg.dts/90) demuxer.OnFrame(stream.cid, data[start:end], stream.pkg.pts/90, stream.pkg.dts/90)
} }
start = end start = end
} }
if start == 0 { if start == 0 {
return return
} }
copy(stream.pkg.payload, data[start:datalen]) copy(stream.pkg.payload, data[start:datalen])
stream.pkg.payload = stream.pkg.payload[0 : datalen-start] stream.pkg.payload = stream.pkg.payload[0 : datalen-start]
} }

View file

@ -1,93 +1,93 @@
package mpeg2 package mpeg2
import ( import (
"errors" "errors"
"github.com/yapingcat/gomedia/codec" "github.com/yapingcat/gomedia/codec"
) )
type pes_stream struct { type pes_stream struct {
pid uint16 pid uint16
cc uint8 cc uint8
streamtype TS_STREAM_TYPE streamtype TS_STREAM_TYPE
} }
func NewPESStream(pid uint16, cid TS_STREAM_TYPE) *pes_stream { func NewPESStream(pid uint16, cid TS_STREAM_TYPE) *pes_stream {
return &pes_stream{ return &pes_stream{
pid: pid, pid: pid,
cc: 0, cc: 0,
streamtype: cid, streamtype: cid,
} }
} }
type table_pmt struct { type table_pmt struct {
pid uint16 pid uint16
cc uint8 cc uint8
pcr_pid uint16 pcr_pid uint16
version_number uint8 version_number uint8
pm uint16 pm uint16
streams []*pes_stream streams []*pes_stream
} }
func NewTablePmt() *table_pmt { func NewTablePmt() *table_pmt {
return &table_pmt{ return &table_pmt{
pid: 0, pid: 0,
cc: 0, cc: 0,
pcr_pid: 0, pcr_pid: 0,
version_number: 0, version_number: 0,
pm: 0, pm: 0,
streams: make([]*pes_stream, 0, 2), streams: make([]*pes_stream, 0, 2),
} }
} }
type table_pat struct { type table_pat struct {
cc uint8 cc uint8
version_number uint8 version_number uint8
pmts []*table_pmt pmts []*table_pmt
} }
func NewTablePat() *table_pat { func NewTablePat() *table_pat {
return &table_pat{ return &table_pat{
cc: 0, cc: 0,
version_number: 0, version_number: 0,
pmts: make([]*table_pmt, 0, 8), pmts: make([]*table_pmt, 0, 8),
} }
} }
type TSMuxer struct { type TSMuxer struct {
pat *table_pat pat *table_pat
stream_pid uint16 stream_pid uint16
pmt_pid uint16 pmt_pid uint16
pat_period uint64 pat_period uint64
OnPacket func(pkg []byte) OnPacket func(pkg []byte)
} }
func NewTSMuxer() *TSMuxer { func NewTSMuxer() *TSMuxer {
return &TSMuxer{ return &TSMuxer{
pat: NewTablePat(), pat: NewTablePat(),
stream_pid: 0x100, stream_pid: 0x100,
pmt_pid: 0x200, pmt_pid: 0x200,
pat_period: 0, pat_period: 0,
OnPacket: nil, OnPacket: nil,
} }
} }
func (mux *TSMuxer) AddStream(cid TS_STREAM_TYPE) uint16 { func (mux *TSMuxer) AddStream(cid TS_STREAM_TYPE) uint16 {
if mux.pat == nil { if mux.pat == nil {
mux.pat = NewTablePat() mux.pat = NewTablePat()
} }
if len(mux.pat.pmts) == 0 { if len(mux.pat.pmts) == 0 {
tmppmt := NewTablePmt() tmppmt := NewTablePmt()
tmppmt.pid = mux.pmt_pid tmppmt.pid = mux.pmt_pid
tmppmt.pm = 1 tmppmt.pm = 1
mux.pmt_pid++ mux.pmt_pid++
mux.pat.pmts = append(mux.pat.pmts, tmppmt) mux.pat.pmts = append(mux.pat.pmts, tmppmt)
} }
sid := mux.stream_pid sid := mux.stream_pid
tmpstream := NewPESStream(sid, cid) tmpstream := NewPESStream(sid, cid)
mux.stream_pid++ mux.stream_pid++
mux.pat.pmts[0].streams = append(mux.pat.pmts[0].streams, tmpstream) mux.pat.pmts[0].streams = append(mux.pat.pmts[0].streams, tmpstream)
return sid return sid
} }
/// Muxer audio/video stream data /// 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 /// pts: audio/video stream timestamp in ms
/// dts: 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 { func (mux *TSMuxer) Write(pid uint16, data []byte, pts uint64, dts uint64) error {
var whichpmt *table_pmt = nil var whichpmt *table_pmt = nil
var whichstream *pes_stream = nil var whichstream *pes_stream = nil
for _, pmt := range mux.pat.pmts { for _, pmt := range mux.pat.pmts {
for _, stream := range pmt.streams { for _, stream := range pmt.streams {
if stream.pid == pid { if stream.pid == pid {
whichpmt = pmt whichpmt = pmt
whichstream = stream whichstream = stream
break break
} }
} }
} }
if whichpmt == nil || whichstream == nil { if whichpmt == nil || whichstream == nil {
return errors.New("not Found pid stream") return errors.New("not Found pid stream")
} }
if whichpmt.pcr_pid == 0 || (findPESIDByStreamType(whichstream.streamtype) == PES_STREAM_VIDEO && whichpmt.pcr_pid != pid) { if whichpmt.pcr_pid == 0 || (findPESIDByStreamType(whichstream.streamtype) == PES_STREAM_VIDEO && whichpmt.pcr_pid != pid) {
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 { if whichstream.streamtype == TS_STREAM_H264 || whichstream.streamtype == TS_STREAM_H265 {
codec.SplitFrame(data, func(nalu []byte) bool { codec.SplitFrame(data, func(nalu []byte) bool {
if whichstream.streamtype == TS_STREAM_H264 { if whichstream.streamtype == TS_STREAM_H264 {
nalu_type := codec.H264NaluTypeWithoutStartCode(nalu) nalu_type := codec.H264NaluTypeWithoutStartCode(nalu)
if nalu_type == codec.H264_NAL_AUD { if nalu_type == codec.H264_NAL_AUD {
withaud = true withaud = true
return false return false
} else if codec.IsH264VCLNaluType(nalu_type) { } else if codec.IsH264VCLNaluType(nalu_type) {
return false return false
} }
return true return true
} else { } else {
nalu_type := codec.H265NaluTypeWithoutStartCode(nalu) nalu_type := codec.H265NaluTypeWithoutStartCode(nalu)
if nalu_type == codec.H265_NAL_AUD { if nalu_type == codec.H265_NAL_AUD {
withaud = true withaud = true
return false return false
} else if codec.IsH265VCLNaluType(nalu_type) { } else if codec.IsH265VCLNaluType(nalu_type) {
return false return false
} }
return true return true
} }
}) })
} }
if mux.pat_period == 0 || mux.pat_period+400 < dts { if mux.pat_period == 0 || mux.pat_period+400 < dts {
mux.pat_period = dts mux.pat_period = dts
if mux.pat_period == 0 { if mux.pat_period == 0 {
mux.pat_period = 1 //avoid write pat twice mux.pat_period = 1 //avoid write pat twice
} }
tmppat := NewPat() tmppat := NewPat()
tmppat.Version_number = mux.pat.version_number tmppat.Version_number = mux.pat.version_number
for _, pmt := range mux.pat.pmts { for _, pmt := range mux.pat.pmts {
tmppm := PmtPair{ tmppm := PmtPair{
Program_number: pmt.pm, Program_number: pmt.pm,
PID: pmt.pid, PID: pmt.pid,
} }
tmppat.Pmts = append(tmppat.Pmts, tmppm) tmppat.Pmts = append(tmppat.Pmts, tmppm)
} }
mux.writePat(tmppat) mux.writePat(tmppat)
for _, pmt := range mux.pat.pmts { for _, pmt := range mux.pat.pmts {
tmppmt := NewPmt() tmppmt := NewPmt()
tmppmt.Program_number = pmt.pm tmppmt.Program_number = pmt.pm
tmppmt.Version_number = pmt.version_number tmppmt.Version_number = pmt.version_number
tmppmt.PCR_PID = pmt.pcr_pid tmppmt.PCR_PID = pmt.pcr_pid
for _, stream := range pmt.streams { for _, stream := range pmt.streams {
var sp StreamPair var sp StreamPair
sp.StreamType = uint8(stream.streamtype) sp.StreamType = uint8(stream.streamtype)
sp.Elementary_PID = stream.pid sp.Elementary_PID = stream.pid
sp.ES_Info_Length = 0 sp.ES_Info_Length = 0
tmppmt.Streams = append(tmppmt.Streams, sp) tmppmt.Streams = append(tmppmt.Streams, sp)
} }
mux.writePmt(tmppmt, pmt) mux.writePmt(tmppmt, pmt)
} }
} }
flag := false flag := false
switch whichstream.streamtype { switch whichstream.streamtype {
case TS_STREAM_H264: case TS_STREAM_H264:
flag = codec.IsH264IDRFrame(data) flag = codec.IsH264IDRFrame(data)
case TS_STREAM_H265: case TS_STREAM_H265:
flag = codec.IsH265IDRFrame(data) flag = codec.IsH265IDRFrame(data)
} }
mux.writePES(whichstream, whichpmt, data, pts*90, dts*90, flag, withaud) mux.writePES(whichstream, whichpmt, data, pts*90, dts*90, flag, withaud)
return nil return nil
} }
func (mux *TSMuxer) writePat(pat *Pat) { func (mux *TSMuxer) writePat(pat *Pat) {
var tshdr TSPacket var tshdr TSPacket
tshdr.Payload_unit_start_indicator = 1 tshdr.Payload_unit_start_indicator = 1
tshdr.PID = 0 tshdr.PID = 0
tshdr.Adaptation_field_control = 0x01 tshdr.Adaptation_field_control = 0x01
tshdr.Continuity_counter = mux.pat.cc tshdr.Continuity_counter = mux.pat.cc
mux.pat.cc++ mux.pat.cc++
mux.pat.cc = (mux.pat.cc + 1) % 16 mux.pat.cc = (mux.pat.cc + 1) % 16
bsw := codec.NewBitStreamWriter(TS_PAKCET_SIZE) bsw := codec.NewBitStreamWriter(TS_PAKCET_SIZE)
tshdr.EncodeHeader(bsw) tshdr.EncodeHeader(bsw)
bsw.PutByte(0x00) //pointer bsw.PutByte(0x00) //pointer
pat.Encode(bsw) pat.Encode(bsw)
bsw.FillRemainData(0xff) bsw.FillRemainData(0xff)
if mux.OnPacket != nil { if mux.OnPacket != nil {
mux.OnPacket(bsw.Bits()) mux.OnPacket(bsw.Bits())
} }
} }
func (mux *TSMuxer) writePmt(pmt *Pmt, t_pmt *table_pmt) { func (mux *TSMuxer) writePmt(pmt *Pmt, t_pmt *table_pmt) {
var tshdr TSPacket var tshdr TSPacket
tshdr.Payload_unit_start_indicator = 1 tshdr.Payload_unit_start_indicator = 1
tshdr.PID = t_pmt.pid tshdr.PID = t_pmt.pid
tshdr.Adaptation_field_control = 0x01 tshdr.Adaptation_field_control = 0x01
tshdr.Continuity_counter = t_pmt.cc tshdr.Continuity_counter = t_pmt.cc
t_pmt.cc = (t_pmt.cc + 1) % 16 t_pmt.cc = (t_pmt.cc + 1) % 16
bsw := codec.NewBitStreamWriter(TS_PAKCET_SIZE) bsw := codec.NewBitStreamWriter(TS_PAKCET_SIZE)
tshdr.EncodeHeader(bsw) tshdr.EncodeHeader(bsw)
bsw.PutByte(0x00) //pointer bsw.PutByte(0x00) //pointer
pmt.Encode(bsw) pmt.Encode(bsw)
bsw.FillRemainData(0xff) bsw.FillRemainData(0xff)
if mux.OnPacket != nil { if mux.OnPacket != nil {
mux.OnPacket(bsw.Bits()) 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) { 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 var firstPesPacket bool = true
bsw := codec.NewBitStreamWriter(TS_PAKCET_SIZE) bsw := codec.NewBitStreamWriter(TS_PAKCET_SIZE)
for { for {
bsw.Reset() bsw.Reset()
var tshdr TSPacket var tshdr TSPacket
if firstPesPacket { if firstPesPacket {
tshdr.Payload_unit_start_indicator = 1 tshdr.Payload_unit_start_indicator = 1
} }
tshdr.PID = pes.pid tshdr.PID = pes.pid
tshdr.Adaptation_field_control = 0x01 tshdr.Adaptation_field_control = 0x01
tshdr.Continuity_counter = pes.cc tshdr.Continuity_counter = pes.cc
headlen := 4 headlen := 4
pes.cc = (pes.cc + 1) % 16 pes.cc = (pes.cc + 1) % 16
var adaptation *Adaptation_field = nil var adaptation *Adaptation_field = nil
if firstPesPacket && idr_flag { if firstPesPacket && idr_flag {
adaptation = new(Adaptation_field) adaptation = new(Adaptation_field)
tshdr.Adaptation_field_control = tshdr.Adaptation_field_control | 0x20 tshdr.Adaptation_field_control = tshdr.Adaptation_field_control | 0x20
adaptation.Random_access_indicator = 1 adaptation.Random_access_indicator = 1
headlen += 2 headlen += 2
} }
if firstPesPacket && pes.pid == pmt.pcr_pid { if firstPesPacket && pes.pid == pmt.pcr_pid {
if adaptation == nil { if adaptation == nil {
adaptation = new(Adaptation_field) adaptation = new(Adaptation_field)
headlen += 2 headlen += 2
} }
tshdr.Adaptation_field_control = tshdr.Adaptation_field_control | 0x20 tshdr.Adaptation_field_control = tshdr.Adaptation_field_control | 0x20
adaptation.PCR_flag = 1 adaptation.PCR_flag = 1
var pcr_base uint64 = 0 var pcr_base uint64 = 0
var pcr_ext uint16 = 0 var pcr_ext uint16 = 0
if dts == 0 { if dts == 0 {
pcr_base = pts * 300 / 300 pcr_base = pts * 300 / 300
pcr_ext = uint16(pts * 300 % 300) pcr_ext = uint16(pts * 300 % 300)
} else { } else {
pcr_base = dts * 300 / 300 pcr_base = dts * 300 / 300
pcr_ext = uint16(dts * 300 % 300) pcr_ext = uint16(dts * 300 % 300)
} }
adaptation.Program_clock_reference_base = pcr_base adaptation.Program_clock_reference_base = pcr_base
adaptation.Program_clock_reference_extension = pcr_ext adaptation.Program_clock_reference_extension = pcr_ext
headlen += 6 headlen += 6
} }
var payload []byte var payload []byte
var pespkg *PesPacket = nil var pespkg *PesPacket = nil
if firstPesPacket { if firstPesPacket {
oldheadlen := headlen oldheadlen := headlen
headlen += 19 headlen += 19
if !withaud && pes.streamtype == TS_STREAM_H264 { if !withaud && pes.streamtype == TS_STREAM_H264 {
headlen += 6 headlen += 6
payload = append(payload, H264_AUD_NALU...) payload = append(payload, H264_AUD_NALU...)
} else if !withaud && pes.streamtype == TS_STREAM_H265 { } else if !withaud && pes.streamtype == TS_STREAM_H265 {
payload = append(payload, H265_AUD_NALU...) payload = append(payload, H265_AUD_NALU...)
headlen += 7 headlen += 7
} }
pespkg = NewPesPacket() pespkg = NewPesPacket()
pespkg.PTS_DTS_flags = 0x03 pespkg.PTS_DTS_flags = 0x03
pespkg.PES_header_data_length = 10 pespkg.PES_header_data_length = 10
pespkg.Pts = pts pespkg.Pts = pts
pespkg.Dts = dts pespkg.Dts = dts
pespkg.Stream_id = uint8(findPESIDByStreamType(pes.streamtype)) pespkg.Stream_id = uint8(findPESIDByStreamType(pes.streamtype))
if idr_flag { if idr_flag {
pespkg.Data_alignment_indicator = 1 pespkg.Data_alignment_indicator = 1
} }
if headlen-oldheadlen-6+len(data) > 0xFFFF { if headlen-oldheadlen-6+len(data) > 0xFFFF {
pespkg.PES_packet_length = 0 pespkg.PES_packet_length = 0
} else { } else {
pespkg.PES_packet_length = uint16(len(data) + headlen - oldheadlen - 6) pespkg.PES_packet_length = uint16(len(data) + headlen - oldheadlen - 6)
} }
} }
if len(data)+headlen < TS_PAKCET_SIZE { if len(data)+headlen < TS_PAKCET_SIZE {
if adaptation == nil { if adaptation == nil {
adaptation = new(Adaptation_field) adaptation = new(Adaptation_field)
headlen += 1 headlen += 1
if TS_PAKCET_SIZE-len(data)-headlen >= 1 { if TS_PAKCET_SIZE-len(data)-headlen >= 1 {
headlen += 1 headlen += 1
} else { } else {
adaptation.SingleStuffingByte = true adaptation.SingleStuffingByte = true
} }
} }
adaptation.Stuffing_byte = uint8(TS_PAKCET_SIZE - len(data) - headlen) adaptation.Stuffing_byte = uint8(TS_PAKCET_SIZE - len(data) - headlen)
payload = append(payload, data...) payload = append(payload, data...)
data = data[:0] data = data[:0]
} else { } else {
payload = append(payload, data[0:TS_PAKCET_SIZE-headlen]...) payload = append(payload, data[0:TS_PAKCET_SIZE-headlen]...)
data = data[TS_PAKCET_SIZE-headlen:] data = data[TS_PAKCET_SIZE-headlen:]
} }
if adaptation != nil { if adaptation != nil {
tshdr.Field = adaptation tshdr.Field = adaptation
tshdr.Adaptation_field_control |= 0x02 tshdr.Adaptation_field_control |= 0x02
} }
tshdr.EncodeHeader(bsw) tshdr.EncodeHeader(bsw)
if pespkg != nil { if pespkg != nil {
pespkg.Pes_payload = payload pespkg.Pes_payload = payload
pespkg.Encode(bsw) pespkg.Encode(bsw)
} else { } else {
bsw.PutBytes(payload) bsw.PutBytes(payload)
} }
firstPesPacket = false firstPesPacket = false
if mux.OnPacket != nil { if mux.OnPacket != nil {
if len(bsw.Bits()) != TS_PAKCET_SIZE { if len(bsw.Bits()) != TS_PAKCET_SIZE {
panic("packet ts packet failed") panic("packet ts packet failed")
} }
mux.OnPacket(bsw.Bits()) mux.OnPacket(bsw.Bits())
} }
if len(data) == 0 { if len(data) == 0 {
break break
} }
} }
} }

View file

@ -1,50 +1,50 @@
package mpeg2 package mpeg2
import ( import (
"encoding/binary" "encoding/binary"
"errors" "errors"
"fmt" "fmt"
"os" "os"
"github.com/yapingcat/gomedia/codec" "github.com/yapingcat/gomedia/codec"
) )
//PID //PID
type TS_PID int type TS_PID int
const ( const (
TS_PID_PAT TS_PID = 0x0000 TS_PID_PAT TS_PID = 0x0000
TS_PID_CAT TS_PID_CAT
TS_PID_TSDT TS_PID_TSDT
TS_PID_IPMP TS_PID_IPMP
TS_PID_Nil = 0x1FFFF TS_PID_Nil = 0x1FFFF
) )
//Table id //Table id
type PAT_TID int type PAT_TID int
const ( const (
TS_TID_PAS PAT_TID = 0x00 // program_association_section TS_TID_PAS PAT_TID = 0x00 // program_association_section
TS_TID_CAS = 0x01 // conditional_access_section(CA_section) TS_TID_CAS = 0x01 // conditional_access_section(CA_section)
TS_TID_PMS = 0x02 // TS_program_map_section TS_TID_PMS = 0x02 // TS_program_map_section
TS_TID_SDS = 0x03 //TS_description_section TS_TID_SDS = 0x03 //TS_description_section
TS_TID_FORBIDDEN PAT_TID = 0xFF TS_TID_FORBIDDEN PAT_TID = 0xFF
) )
type TS_STREAM_TYPE int type TS_STREAM_TYPE int
const ( const (
TS_STREAM_AAC TS_STREAM_TYPE = 0x0F TS_STREAM_AAC TS_STREAM_TYPE = 0x0F
TS_STREAM_H264 TS_STREAM_TYPE = 0x1B TS_STREAM_H264 TS_STREAM_TYPE = 0x1B
TS_STREAM_H265 TS_STREAM_TYPE = 0x24 TS_STREAM_H265 TS_STREAM_TYPE = 0x24
) )
const ( const (
TS_PAKCET_SIZE = 188 TS_PAKCET_SIZE = 188
) )
type Display interface { type Display interface {
PrettyPrint(file *os.File) PrettyPrint(file *os.File)
} }
// transport_packet(){ // transport_packet(){
@ -67,63 +67,63 @@ type Display interface {
// } // }
type TSPacket struct { type TSPacket struct {
Transport_error_indicator uint8 Transport_error_indicator uint8
Payload_unit_start_indicator uint8 Payload_unit_start_indicator uint8
Transport_priority uint8 Transport_priority uint8
PID uint16 PID uint16
Transport_scrambling_control uint8 Transport_scrambling_control uint8
Adaptation_field_control uint8 Adaptation_field_control uint8
Continuity_counter uint8 Continuity_counter uint8
Field *Adaptation_field Field *Adaptation_field
Payload interface{} Payload interface{}
} }
func (pkg *TSPacket) PrettyPrint(file *os.File) { func (pkg *TSPacket) PrettyPrint(file *os.File) {
file.WriteString(fmt.Sprintf("Transport_error_indicator:%d\n", pkg.Transport_error_indicator)) 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("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("Transport_priority:%d\n", pkg.Transport_priority))
file.WriteString(fmt.Sprintf("PID:%d\n", pkg.PID)) 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("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("Adaptation_field_control:%d\n", pkg.Adaptation_field_control))
file.WriteString(fmt.Sprintf("Continuity_counter:%d\n", pkg.Continuity_counter)) file.WriteString(fmt.Sprintf("Continuity_counter:%d\n", pkg.Continuity_counter))
} }
func (pkg *TSPacket) EncodeHeader(bsw *codec.BitStreamWriter) { func (pkg *TSPacket) EncodeHeader(bsw *codec.BitStreamWriter) {
bsw.PutByte(0x47) bsw.PutByte(0x47)
bsw.PutUint8(pkg.Transport_error_indicator, 1) bsw.PutUint8(pkg.Transport_error_indicator, 1)
bsw.PutUint8(pkg.Payload_unit_start_indicator, 1) bsw.PutUint8(pkg.Payload_unit_start_indicator, 1)
bsw.PutUint8(pkg.Transport_priority, 1) bsw.PutUint8(pkg.Transport_priority, 1)
bsw.PutUint16(pkg.PID, 13) bsw.PutUint16(pkg.PID, 13)
bsw.PutUint8(pkg.Transport_scrambling_control, 2) bsw.PutUint8(pkg.Transport_scrambling_control, 2)
bsw.PutUint8(pkg.Adaptation_field_control, 2) bsw.PutUint8(pkg.Adaptation_field_control, 2)
bsw.PutUint8(pkg.Continuity_counter, 4) bsw.PutUint8(pkg.Continuity_counter, 4)
if pkg.Field != nil && (pkg.Adaptation_field_control&0x02) != 0 { if pkg.Field != nil && (pkg.Adaptation_field_control&0x02) != 0 {
pkg.Field.Encode(bsw) pkg.Field.Encode(bsw)
} }
} }
func (pkg *TSPacket) DecodeHeader(bs *codec.BitStream) error { func (pkg *TSPacket) DecodeHeader(bs *codec.BitStream) error {
sync_byte := bs.Uint8(8) sync_byte := bs.Uint8(8)
if sync_byte != 0x47 { if sync_byte != 0x47 {
return errors.New("ts packet must start with 0x47") return errors.New("ts packet must start with 0x47")
} }
pkg.Transport_error_indicator = bs.GetBit() pkg.Transport_error_indicator = bs.GetBit()
pkg.Payload_unit_start_indicator = bs.GetBit() pkg.Payload_unit_start_indicator = bs.GetBit()
pkg.Transport_priority = bs.GetBit() pkg.Transport_priority = bs.GetBit()
pkg.PID = bs.Uint16(13) pkg.PID = bs.Uint16(13)
pkg.Transport_scrambling_control = bs.Uint8(2) pkg.Transport_scrambling_control = bs.Uint8(2)
pkg.Adaptation_field_control = bs.Uint8(2) pkg.Adaptation_field_control = bs.Uint8(2)
pkg.Continuity_counter = bs.Uint8(4) pkg.Continuity_counter = bs.Uint8(4)
if pkg.Adaptation_field_control == 0x02 || pkg.Adaptation_field_control == 0x03 { if pkg.Adaptation_field_control == 0x02 || pkg.Adaptation_field_control == 0x03 {
if pkg.Field == nil { if pkg.Field == nil {
pkg.Field = new(Adaptation_field) pkg.Field = new(Adaptation_field)
} }
err := pkg.Field.Decode(bs) err := pkg.Field.Decode(bs)
if err != nil { if err != nil {
return err return err
} }
} }
return nil return nil
} }
// //
@ -189,414 +189,414 @@ func (pkg *TSPacket) DecodeHeader(bs *codec.BitStream) error {
// } // }
type Adaptation_field struct { type Adaptation_field struct {
SingleStuffingByte bool // The value 0 is for inserting a single stuffing byte in a Transport Stream packet SingleStuffingByte bool // The value 0 is for inserting a single stuffing byte in a Transport Stream packet
Adaptation_field_length uint8 //8 uimsbf Adaptation_field_length uint8 //8 uimsbf
Discontinuity_indicator uint8 //1 bslbf Discontinuity_indicator uint8 //1 bslbf
Random_access_indicator uint8 //1 bslbf Random_access_indicator uint8 //1 bslbf
Elementary_stream_priority_indicator uint8 //1 bslbf Elementary_stream_priority_indicator uint8 //1 bslbf
PCR_flag uint8 //1 bslbf PCR_flag uint8 //1 bslbf
OPCR_flag uint8 //1 bslbf OPCR_flag uint8 //1 bslbf
Splicing_point_flag uint8 //1 bslbf Splicing_point_flag uint8 //1 bslbf
Transport_private_data_flag uint8 //1 bslbf Transport_private_data_flag uint8 //1 bslbf
Adaptation_field_extension_flag uint8 //1 bslbf Adaptation_field_extension_flag uint8 //1 bslbf
Program_clock_reference_base uint64 //33 uimsbf Program_clock_reference_base uint64 //33 uimsbf
Program_clock_reference_extension uint16 //9 uimsbf Program_clock_reference_extension uint16 //9 uimsbf
Original_program_clock_reference_base uint64 //33 uimsbf Original_program_clock_reference_base uint64 //33 uimsbf
Original_program_clock_reference_extension uint16 //9 uimsbf Original_program_clock_reference_extension uint16 //9 uimsbf
Splice_countdown uint8 //8 uimsbf Splice_countdown uint8 //8 uimsbf
Transport_private_data_length uint8 //8 uimsbf Transport_private_data_length uint8 //8 uimsbf
Adaptation_field_extension_length uint8 //8 uimsbf Adaptation_field_extension_length uint8 //8 uimsbf
Ltw_flag uint8 //1 bslbf Ltw_flag uint8 //1 bslbf
Piecewise_rate_flag uint8 //1 bslbf Piecewise_rate_flag uint8 //1 bslbf
Seamless_splice_flag uint8 //1 bslbf Seamless_splice_flag uint8 //1 bslbf
Ltw_valid_flag uint8 //1 bslbf Ltw_valid_flag uint8 //1 bslbf
Ltw_offset uint16 //15 uimsbf Ltw_offset uint16 //15 uimsbf
Piecewise_rate uint32 //22 uimsbf Piecewise_rate uint32 //22 uimsbf
Splice_type uint8 //4 uimsbf Splice_type uint8 //4 uimsbf
DTS_next_AU uint64 DTS_next_AU uint64
Stuffing_byte uint8 Stuffing_byte uint8
} }
func (adaptation *Adaptation_field) PrettyPrint(file *os.File) { 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("Adaptation_field_length:%d\n", adaptation.Adaptation_field_length))
file.WriteString(fmt.Sprintf("Discontinuity_indicator:%d\n", adaptation.Discontinuity_indicator)) 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("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("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("PCR_flag:%d\n", adaptation.PCR_flag))
file.WriteString(fmt.Sprintf("OPCR_flag:%d\n", adaptation.OPCR_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("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("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)) file.WriteString(fmt.Sprintf("Adaptation_field_extension_flag:%d\n", adaptation.Adaptation_field_extension_flag))
if adaptation.PCR_flag == 1 { 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_base:%d\n", adaptation.Program_clock_reference_base))
file.WriteString(fmt.Sprintf("Program_clock_reference_extension:%d\n", adaptation.Program_clock_reference_extension)) file.WriteString(fmt.Sprintf("Program_clock_reference_extension:%d\n", adaptation.Program_clock_reference_extension))
} }
if adaptation.OPCR_flag == 1 { 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_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)) file.WriteString(fmt.Sprintf("Original_program_clock_reference_extension:%d\n", adaptation.Original_program_clock_reference_extension))
} }
if adaptation.Splicing_point_flag == 1 { if adaptation.Splicing_point_flag == 1 {
file.WriteString(fmt.Sprintf("Splice_countdown:%d\n", adaptation.Splice_countdown)) file.WriteString(fmt.Sprintf("Splice_countdown:%d\n", adaptation.Splice_countdown))
} }
if adaptation.Transport_private_data_flag == 1 { if adaptation.Transport_private_data_flag == 1 {
file.WriteString(fmt.Sprintf("Transport_private_data_length:%d\n", adaptation.Transport_private_data_length)) file.WriteString(fmt.Sprintf("Transport_private_data_length:%d\n", adaptation.Transport_private_data_length))
} }
if adaptation.Adaptation_field_extension_flag == 1 { 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("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("Ltw_flag:%d\n", adaptation.Ltw_flag))
file.WriteString(fmt.Sprintf("Piecewise_rate_flag:%d\n", adaptation.Piecewise_rate_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)) file.WriteString(fmt.Sprintf("Seamless_splice_flag:%d\n", adaptation.Seamless_splice_flag))
if adaptation.Ltw_flag == 1 { if adaptation.Ltw_flag == 1 {
file.WriteString(fmt.Sprintf("Ltw_valid_flag:%d\n", adaptation.Ltw_valid_flag)) file.WriteString(fmt.Sprintf("Ltw_valid_flag:%d\n", adaptation.Ltw_valid_flag))
file.WriteString(fmt.Sprintf("Ltw_offset:%d\n", adaptation.Ltw_offset)) file.WriteString(fmt.Sprintf("Ltw_offset:%d\n", adaptation.Ltw_offset))
} }
if adaptation.Piecewise_rate_flag == 1 { if adaptation.Piecewise_rate_flag == 1 {
file.WriteString(fmt.Sprintf("Piecewise_rate:%d\n", adaptation.Piecewise_rate)) file.WriteString(fmt.Sprintf("Piecewise_rate:%d\n", adaptation.Piecewise_rate))
} }
if adaptation.Seamless_splice_flag == 1 { if adaptation.Seamless_splice_flag == 1 {
file.WriteString(fmt.Sprintf("Splice_type:%d\n", adaptation.Splice_type)) 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("DTS_next_AU:%d\n", adaptation.DTS_next_AU))
} }
} }
} }
func (adaptation *Adaptation_field) Encode(bsw *codec.BitStreamWriter) { func (adaptation *Adaptation_field) Encode(bsw *codec.BitStreamWriter) {
loc := bsw.ByteOffset() loc := bsw.ByteOffset()
bsw.PutUint8(adaptation.Adaptation_field_length, 8) bsw.PutUint8(adaptation.Adaptation_field_length, 8)
if adaptation.SingleStuffingByte { if adaptation.SingleStuffingByte {
return return
} }
bsw.Markdot() bsw.Markdot()
bsw.PutUint8(adaptation.Discontinuity_indicator, 1) bsw.PutUint8(adaptation.Discontinuity_indicator, 1)
bsw.PutUint8(adaptation.Random_access_indicator, 1) bsw.PutUint8(adaptation.Random_access_indicator, 1)
bsw.PutUint8(adaptation.Elementary_stream_priority_indicator, 1) bsw.PutUint8(adaptation.Elementary_stream_priority_indicator, 1)
bsw.PutUint8(adaptation.PCR_flag, 1) bsw.PutUint8(adaptation.PCR_flag, 1)
bsw.PutUint8(adaptation.OPCR_flag, 1) bsw.PutUint8(adaptation.OPCR_flag, 1)
bsw.PutUint8(adaptation.Splicing_point_flag, 1) bsw.PutUint8(adaptation.Splicing_point_flag, 1)
bsw.PutUint8(0 /*adaptation.Transport_private_data_flag*/, 1) bsw.PutUint8(0 /*adaptation.Transport_private_data_flag*/, 1)
bsw.PutUint8(0 /*adaptation.Adaptation_field_extension_flag*/, 1) bsw.PutUint8(0 /*adaptation.Adaptation_field_extension_flag*/, 1)
if adaptation.PCR_flag == 1 { if adaptation.PCR_flag == 1 {
bsw.PutUint64(adaptation.Program_clock_reference_base, 33) bsw.PutUint64(adaptation.Program_clock_reference_base, 33)
bsw.PutUint8(0, 6) bsw.PutUint8(0, 6)
bsw.PutUint16(adaptation.Program_clock_reference_extension, 9) bsw.PutUint16(adaptation.Program_clock_reference_extension, 9)
} }
if adaptation.OPCR_flag == 1 { if adaptation.OPCR_flag == 1 {
bsw.PutUint64(adaptation.Original_program_clock_reference_base, 33) bsw.PutUint64(adaptation.Original_program_clock_reference_base, 33)
bsw.PutUint8(0, 6) bsw.PutUint8(0, 6)
bsw.PutUint16(adaptation.Original_program_clock_reference_extension, 9) bsw.PutUint16(adaptation.Original_program_clock_reference_extension, 9)
} }
if adaptation.Splicing_point_flag == 1 { if adaptation.Splicing_point_flag == 1 {
bsw.PutUint8(adaptation.Splice_countdown, 8) bsw.PutUint8(adaptation.Splice_countdown, 8)
} }
//TODO //TODO
// if adaptation.Transport_private_data_flag == 0 { // if adaptation.Transport_private_data_flag == 0 {
// } // }
// if adaptation.Adaptation_field_extension_flag == 0 { // if adaptation.Adaptation_field_extension_flag == 0 {
// } // }
adaptation.Adaptation_field_length = uint8(bsw.DistanceFromMarkDot() / 8) adaptation.Adaptation_field_length = uint8(bsw.DistanceFromMarkDot() / 8)
bsw.PutRepetValue(0xff, int(adaptation.Stuffing_byte)) bsw.PutRepetValue(0xff, int(adaptation.Stuffing_byte))
adaptation.Adaptation_field_length += adaptation.Stuffing_byte adaptation.Adaptation_field_length += adaptation.Stuffing_byte
bsw.SetByte(adaptation.Adaptation_field_length, loc) bsw.SetByte(adaptation.Adaptation_field_length, loc)
} }
func (adaptation *Adaptation_field) Decode(bs *codec.BitStream) error { func (adaptation *Adaptation_field) Decode(bs *codec.BitStream) error {
if bs.RemainBytes() < 1 { if bs.RemainBytes() < 1 {
return errors.New("len of data < 1 byte") return errors.New("len of data < 1 byte")
} }
adaptation.Adaptation_field_length = bs.Uint8(8) adaptation.Adaptation_field_length = bs.Uint8(8)
startoffset := bs.ByteOffset() startoffset := bs.ByteOffset()
//fmt.Printf("Adaptation_field_length=%d\n", adaptation.Adaptation_field_length) //fmt.Printf("Adaptation_field_length=%d\n", adaptation.Adaptation_field_length)
if bs.RemainBytes() < int(adaptation.Adaptation_field_length) { if bs.RemainBytes() < int(adaptation.Adaptation_field_length) {
return errors.New("len of data < Adaptation_field_length") return errors.New("len of data < Adaptation_field_length")
} }
if adaptation.Adaptation_field_length == 0 { if adaptation.Adaptation_field_length == 0 {
return nil return nil
} }
adaptation.Discontinuity_indicator = bs.GetBit() adaptation.Discontinuity_indicator = bs.GetBit()
adaptation.Random_access_indicator = bs.GetBit() adaptation.Random_access_indicator = bs.GetBit()
adaptation.Elementary_stream_priority_indicator = bs.GetBit() adaptation.Elementary_stream_priority_indicator = bs.GetBit()
adaptation.PCR_flag = bs.GetBit() adaptation.PCR_flag = bs.GetBit()
adaptation.OPCR_flag = bs.GetBit() adaptation.OPCR_flag = bs.GetBit()
adaptation.Splicing_point_flag = bs.GetBit() adaptation.Splicing_point_flag = bs.GetBit()
adaptation.Transport_private_data_flag = bs.GetBit() adaptation.Transport_private_data_flag = bs.GetBit()
adaptation.Adaptation_field_extension_flag = bs.GetBit() adaptation.Adaptation_field_extension_flag = bs.GetBit()
if adaptation.PCR_flag == 1 { if adaptation.PCR_flag == 1 {
adaptation.Program_clock_reference_base = bs.GetBits(33) adaptation.Program_clock_reference_base = bs.GetBits(33)
bs.SkipBits(6) bs.SkipBits(6)
adaptation.Program_clock_reference_extension = uint16(bs.GetBits(9)) adaptation.Program_clock_reference_extension = uint16(bs.GetBits(9))
} }
if adaptation.OPCR_flag == 1 { if adaptation.OPCR_flag == 1 {
adaptation.Original_program_clock_reference_base = bs.GetBits(33) adaptation.Original_program_clock_reference_base = bs.GetBits(33)
bs.SkipBits(6) bs.SkipBits(6)
adaptation.Original_program_clock_reference_extension = uint16(bs.GetBits(9)) adaptation.Original_program_clock_reference_extension = uint16(bs.GetBits(9))
} }
if adaptation.Splicing_point_flag == 1 { if adaptation.Splicing_point_flag == 1 {
adaptation.Splice_countdown = bs.Uint8(8) adaptation.Splice_countdown = bs.Uint8(8)
} }
if adaptation.Transport_private_data_flag == 1 { if adaptation.Transport_private_data_flag == 1 {
adaptation.Transport_private_data_length = bs.Uint8(8) adaptation.Transport_private_data_length = bs.Uint8(8)
bs.SkipBits(8 * int(adaptation.Transport_private_data_length)) bs.SkipBits(8 * int(adaptation.Transport_private_data_length))
} }
if adaptation.Adaptation_field_extension_flag == 1 { if adaptation.Adaptation_field_extension_flag == 1 {
adaptation.Adaptation_field_extension_length = bs.Uint8(8) adaptation.Adaptation_field_extension_length = bs.Uint8(8)
bs.Markdot() bs.Markdot()
adaptation.Ltw_flag = bs.GetBit() adaptation.Ltw_flag = bs.GetBit()
adaptation.Piecewise_rate_flag = bs.GetBit() adaptation.Piecewise_rate_flag = bs.GetBit()
adaptation.Seamless_splice_flag = bs.GetBit() adaptation.Seamless_splice_flag = bs.GetBit()
bs.SkipBits(5) bs.SkipBits(5)
if adaptation.Ltw_flag == 1 { if adaptation.Ltw_flag == 1 {
adaptation.Ltw_valid_flag = bs.GetBit() adaptation.Ltw_valid_flag = bs.GetBit()
adaptation.Ltw_offset = uint16(bs.GetBits(15)) adaptation.Ltw_offset = uint16(bs.GetBits(15))
} }
if adaptation.Piecewise_rate_flag == 1 { if adaptation.Piecewise_rate_flag == 1 {
bs.SkipBits(2) bs.SkipBits(2)
adaptation.Piecewise_rate = uint32(bs.GetBits(22)) adaptation.Piecewise_rate = uint32(bs.GetBits(22))
} }
if adaptation.Seamless_splice_flag == 1 { if adaptation.Seamless_splice_flag == 1 {
adaptation.Splice_type = uint8(bs.GetBits(4)) adaptation.Splice_type = uint8(bs.GetBits(4))
adaptation.DTS_next_AU = bs.GetBits(3) adaptation.DTS_next_AU = bs.GetBits(3)
bs.SkipBits(1) bs.SkipBits(1)
adaptation.DTS_next_AU = adaptation.DTS_next_AU<<15 | bs.GetBits(15) adaptation.DTS_next_AU = adaptation.DTS_next_AU<<15 | bs.GetBits(15)
bs.SkipBits(1) bs.SkipBits(1)
adaptation.DTS_next_AU = adaptation.DTS_next_AU<<15 | bs.GetBits(15) adaptation.DTS_next_AU = adaptation.DTS_next_AU<<15 | bs.GetBits(15)
bs.SkipBits(1) bs.SkipBits(1)
} }
bitscount := bs.DistanceFromMarkDot() bitscount := bs.DistanceFromMarkDot()
if bitscount%8 > 0 { if bitscount%8 > 0 {
panic("maybe parser ts file failed") panic("maybe parser ts file failed")
} }
bs.SkipBits(int(adaptation.Adaptation_field_extension_length*8 - uint8(bitscount))) bs.SkipBits(int(adaptation.Adaptation_field_extension_length*8 - uint8(bitscount)))
} }
endoffset := bs.ByteOffset() endoffset := bs.ByteOffset()
bs.SkipBits((int(adaptation.Adaptation_field_length) - (endoffset - startoffset)) * 8) bs.SkipBits((int(adaptation.Adaptation_field_length) - (endoffset - startoffset)) * 8)
return nil return nil
} }
type PmtPair struct { type PmtPair struct {
Program_number uint16 Program_number uint16
PID uint16 PID uint16
} }
type Pat struct { type Pat struct {
Table_id uint8 //8 uimsbf Table_id uint8 //8 uimsbf
Section_syntax_indicator uint8 //1 bslbf Section_syntax_indicator uint8 //1 bslbf
Section_length uint16 //12 uimsbf Section_length uint16 //12 uimsbf
Transport_stream_id uint16 //16 uimsbf Transport_stream_id uint16 //16 uimsbf
Version_number uint8 //5 uimsbf Version_number uint8 //5 uimsbf
Current_next_indicator uint8 //1 bslbf Current_next_indicator uint8 //1 bslbf
Section_number uint8 //8 uimsbf Section_number uint8 //8 uimsbf
Last_section_number uint8 //8 uimsbf Last_section_number uint8 //8 uimsbf
Pmts []PmtPair Pmts []PmtPair
} }
func NewPat() *Pat { func NewPat() *Pat {
return &Pat{ return &Pat{
Table_id: uint8(TS_TID_PAS), Table_id: uint8(TS_TID_PAS),
Pmts: make([]PmtPair, 0, 8), Pmts: make([]PmtPair, 0, 8),
} }
} }
func (pat *Pat) PrettyPrint(file *os.File) { func (pat *Pat) PrettyPrint(file *os.File) {
file.WriteString(fmt.Sprintf("Table id:%d\n", pat.Table_id)) 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_syntax_indicator:%d\n", pat.Section_syntax_indicator))
file.WriteString(fmt.Sprintf("Section_length:%d\n", pat.Section_length)) 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("Transport_stream_id:%d\n", pat.Transport_stream_id))
file.WriteString(fmt.Sprintf("Version_number:%d\n", pat.Version_number)) 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("Current_next_indicator:%d\n", pat.Current_next_indicator))
file.WriteString(fmt.Sprintf("Section_number:%d\n", pat.Section_number)) file.WriteString(fmt.Sprintf("Section_number:%d\n", pat.Section_number))
file.WriteString(fmt.Sprintf("Last_section_number:%d\n", pat.Last_section_number)) file.WriteString(fmt.Sprintf("Last_section_number:%d\n", pat.Last_section_number))
for i, pmt := range pat.Pmts { for i, pmt := range pat.Pmts {
file.WriteString(fmt.Sprintf("----pmt %d\n", i)) file.WriteString(fmt.Sprintf("----pmt %d\n", i))
file.WriteString(fmt.Sprintf(" program_number:%d\n", pmt.Program_number)) file.WriteString(fmt.Sprintf(" program_number:%d\n", pmt.Program_number))
if pmt.Program_number == 0x0000 { if pmt.Program_number == 0x0000 {
file.WriteString(fmt.Sprintf(" network_PID:%d\n", pmt.PID)) file.WriteString(fmt.Sprintf(" network_PID:%d\n", pmt.PID))
} else { } else {
file.WriteString(fmt.Sprintf(" program_map_PID:%d\n", pmt.PID)) file.WriteString(fmt.Sprintf(" program_map_PID:%d\n", pmt.PID))
} }
} }
} }
func (pat *Pat) Encode(bsw *codec.BitStreamWriter) { func (pat *Pat) Encode(bsw *codec.BitStreamWriter) {
bsw.PutUint8(0x00, 8) bsw.PutUint8(0x00, 8)
loc := bsw.ByteOffset() loc := bsw.ByteOffset()
bsw.PutUint8(pat.Section_syntax_indicator, 1) bsw.PutUint8(pat.Section_syntax_indicator, 1)
bsw.PutUint8(0x00, 1) bsw.PutUint8(0x00, 1)
bsw.PutUint8(0x03, 2) bsw.PutUint8(0x03, 2)
bsw.PutUint16(0, 12) bsw.PutUint16(0, 12)
bsw.Markdot() bsw.Markdot()
bsw.PutUint16(pat.Transport_stream_id, 16) bsw.PutUint16(pat.Transport_stream_id, 16)
bsw.PutUint8(0x03, 2) bsw.PutUint8(0x03, 2)
bsw.PutUint8(pat.Version_number, 5) bsw.PutUint8(pat.Version_number, 5)
bsw.PutUint8(pat.Current_next_indicator, 1) bsw.PutUint8(pat.Current_next_indicator, 1)
bsw.PutUint8(pat.Section_number, 8) bsw.PutUint8(pat.Section_number, 8)
bsw.PutUint8(pat.Last_section_number, 8) bsw.PutUint8(pat.Last_section_number, 8)
for _, pms := range pat.Pmts { for _, pms := range pat.Pmts {
bsw.PutUint16(pms.Program_number, 16) bsw.PutUint16(pms.Program_number, 16)
bsw.PutUint8(0x07, 3) bsw.PutUint8(0x07, 3)
bsw.PutUint16(pms.PID, 13) bsw.PutUint16(pms.PID, 13)
} }
length := bsw.DistanceFromMarkDot() length := bsw.DistanceFromMarkDot()
//|Section_syntax_indicator|'0'|reserved|Section_length| //|Section_syntax_indicator|'0'|reserved|Section_length|
pat.Section_length = uint16(length)/8 + 4 pat.Section_length = uint16(length)/8 + 4
bsw.SetUint16(pat.Section_length&0x0FFF|(uint16(pat.Section_syntax_indicator)<<15)|0x3000, loc) 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()]) crc := codec.CalcCrc32(0xffffffff, bsw.Bits()[bsw.ByteOffset()-int(pat.Section_length-4)-3:bsw.ByteOffset()])
tmpcrc := make([]byte, 4) tmpcrc := make([]byte, 4)
binary.LittleEndian.PutUint32(tmpcrc, crc) binary.LittleEndian.PutUint32(tmpcrc, crc)
bsw.PutBytes(tmpcrc) bsw.PutBytes(tmpcrc)
} }
func (pat *Pat) Decode(bs *codec.BitStream) error { 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) { if pat.Table_id != uint8(TS_TID_PAS) {
return errors.New("table id is Not TS_TID_PAS") return errors.New("table id is Not TS_TID_PAS")
} }
pat.Section_syntax_indicator = bs.Uint8(1) pat.Section_syntax_indicator = bs.Uint8(1)
bs.SkipBits(3) bs.SkipBits(3)
pat.Section_length = bs.Uint16(12) pat.Section_length = bs.Uint16(12)
pat.Transport_stream_id = bs.Uint16(16) pat.Transport_stream_id = bs.Uint16(16)
bs.SkipBits(2) bs.SkipBits(2)
pat.Version_number = bs.Uint8(5) pat.Version_number = bs.Uint8(5)
pat.Current_next_indicator = bs.Uint8(1) pat.Current_next_indicator = bs.Uint8(1)
pat.Section_number = bs.Uint8(8) pat.Section_number = bs.Uint8(8)
pat.Last_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 { for i := 0; i+4 <= int(pat.Section_length)-5-4; i = i + 4 {
tmp := PmtPair{ tmp := PmtPair{
Program_number: 0, Program_number: 0,
PID: 0, PID: 0,
} }
tmp.Program_number = bs.Uint16(16) tmp.Program_number = bs.Uint16(16)
bs.SkipBits(3) bs.SkipBits(3)
tmp.PID = bs.Uint16(13) tmp.PID = bs.Uint16(13)
pat.Pmts = append(pat.Pmts, tmp) pat.Pmts = append(pat.Pmts, tmp)
} }
return nil return nil
} }
type StreamPair struct { type StreamPair struct {
StreamType uint8 //8 uimsbf StreamType uint8 //8 uimsbf
Elementary_PID uint16 //13 uimsbf Elementary_PID uint16 //13 uimsbf
ES_Info_Length uint16 //12 uimsbf ES_Info_Length uint16 //12 uimsbf
} }
type Pmt struct { type Pmt struct {
Table_id uint8 //8 uimsbf Table_id uint8 //8 uimsbf
Section_syntax_indicator uint8 //1 bslbf Section_syntax_indicator uint8 //1 bslbf
Section_length uint16 //12 uimsbf Section_length uint16 //12 uimsbf
Program_number uint16 //16 uimsbf Program_number uint16 //16 uimsbf
Version_number uint8 //5 uimsbf Version_number uint8 //5 uimsbf
Current_next_indicator uint8 //1 bslbf Current_next_indicator uint8 //1 bslbf
Section_number uint8 //8 uimsbf Section_number uint8 //8 uimsbf
Last_section_number uint8 //8 uimsbf Last_section_number uint8 //8 uimsbf
PCR_PID uint16 //13 uimsbf PCR_PID uint16 //13 uimsbf
Program_info_length uint16 //12 uimsbf Program_info_length uint16 //12 uimsbf
Streams []StreamPair Streams []StreamPair
} }
func NewPmt() *Pmt { func NewPmt() *Pmt {
return &Pmt{ return &Pmt{
Table_id: uint8(TS_TID_PMS), Table_id: uint8(TS_TID_PMS),
Streams: make([]StreamPair, 0, 8), Streams: make([]StreamPair, 0, 8),
} }
} }
func (pmt *Pmt) PrettyPrint(file *os.File) { func (pmt *Pmt) PrettyPrint(file *os.File) {
file.WriteString(fmt.Sprintf("Table id:%d\n", pmt.Table_id)) 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_syntax_indicator:%d\n", pmt.Section_syntax_indicator))
file.WriteString(fmt.Sprintf("Section_length:%d\n", pmt.Section_length)) 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("Program_number:%d\n", pmt.Program_number))
file.WriteString(fmt.Sprintf("Version_number:%d\n", pmt.Version_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("Current_next_indicator:%d\n", pmt.Current_next_indicator))
file.WriteString(fmt.Sprintf("Section_number:%d\n", pmt.Section_number)) 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("Last_section_number:%d\n", pmt.Last_section_number))
file.WriteString(fmt.Sprintf("PCR_PID:%d\n", pmt.PCR_PID)) file.WriteString(fmt.Sprintf("PCR_PID:%d\n", pmt.PCR_PID))
file.WriteString(fmt.Sprintf("program_info_length:%d\n", pmt.Program_info_length)) file.WriteString(fmt.Sprintf("program_info_length:%d\n", pmt.Program_info_length))
for i, stream := range pmt.Streams { for i, stream := range pmt.Streams {
file.WriteString(fmt.Sprintf("----stream %d\n", i)) file.WriteString(fmt.Sprintf("----stream %d\n", i))
if stream.StreamType == uint8(TS_STREAM_AAC) { if stream.StreamType == uint8(TS_STREAM_AAC) {
file.WriteString(" stream_type:AAC\n") file.WriteString(" stream_type:AAC\n")
} else if stream.StreamType == uint8(TS_STREAM_H264) { } else if stream.StreamType == uint8(TS_STREAM_H264) {
file.WriteString(" stream_type:H264\n") file.WriteString(" stream_type:H264\n")
} else if stream.StreamType == uint8(TS_STREAM_H265) { } else if stream.StreamType == uint8(TS_STREAM_H265) {
file.WriteString(" stream_type:H265\n") file.WriteString(" stream_type:H265\n")
} }
file.WriteString(fmt.Sprintf(" elementary_PID:%d\n", stream.Elementary_PID)) 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(" ES_info_length:%d\n", stream.ES_Info_Length))
} }
} }
func (pmt *Pmt) Encode(bsw *codec.BitStreamWriter) { func (pmt *Pmt) Encode(bsw *codec.BitStreamWriter) {
bsw.PutUint8(pmt.Table_id, 8) bsw.PutUint8(pmt.Table_id, 8)
loc := bsw.ByteOffset() loc := bsw.ByteOffset()
bsw.PutUint8(pmt.Section_syntax_indicator, 1) bsw.PutUint8(pmt.Section_syntax_indicator, 1)
bsw.PutUint8(0x00, 1) bsw.PutUint8(0x00, 1)
bsw.PutUint8(0x03, 2) bsw.PutUint8(0x03, 2)
bsw.PutUint16(pmt.Section_length, 12) bsw.PutUint16(pmt.Section_length, 12)
bsw.Markdot() bsw.Markdot()
bsw.PutUint16(pmt.Program_number, 16) bsw.PutUint16(pmt.Program_number, 16)
bsw.PutUint8(0x03, 2) bsw.PutUint8(0x03, 2)
bsw.PutUint8(pmt.Version_number, 5) bsw.PutUint8(pmt.Version_number, 5)
bsw.PutUint8(pmt.Current_next_indicator, 1) bsw.PutUint8(pmt.Current_next_indicator, 1)
bsw.PutUint8(pmt.Section_number, 8) bsw.PutUint8(pmt.Section_number, 8)
bsw.PutUint8(pmt.Last_section_number, 8) bsw.PutUint8(pmt.Last_section_number, 8)
bsw.PutUint8(0x07, 3) bsw.PutUint8(0x07, 3)
bsw.PutUint16(pmt.PCR_PID, 13) bsw.PutUint16(pmt.PCR_PID, 13)
bsw.PutUint8(0x0f, 4) bsw.PutUint8(0x0f, 4)
//TODO Program info length //TODO Program info length
bsw.PutUint16(0x0000 /*pmt.Program_info_length*/, 12) bsw.PutUint16(0x0000 /*pmt.Program_info_length*/, 12)
for _, stream := range pmt.Streams { for _, stream := range pmt.Streams {
bsw.PutUint8(stream.StreamType, 8) bsw.PutUint8(stream.StreamType, 8)
bsw.PutUint8(0x00, 3) bsw.PutUint8(0x00, 3)
bsw.PutUint16(stream.Elementary_PID, 13) bsw.PutUint16(stream.Elementary_PID, 13)
bsw.PutUint8(0x00, 4) bsw.PutUint8(0x00, 4)
//TODO ES_info //TODO ES_info
bsw.PutUint8(0 /*ES_info_length*/, 12) bsw.PutUint8(0 /*ES_info_length*/, 12)
} }
length := bsw.DistanceFromMarkDot() length := bsw.DistanceFromMarkDot()
pmt.Section_length = uint16(length)/8 + 4 pmt.Section_length = uint16(length)/8 + 4
bsw.SetUint16(pmt.Section_length&0x0FFF|(uint16(pmt.Section_syntax_indicator)<<15)|0x3000, loc) 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()]) crc := codec.CalcCrc32(0xffffffff, bsw.Bits()[bsw.ByteOffset()-int(pmt.Section_length-4)-3:bsw.ByteOffset()])
tmpcrc := make([]byte, 4) tmpcrc := make([]byte, 4)
binary.LittleEndian.PutUint32(tmpcrc, crc) binary.LittleEndian.PutUint32(tmpcrc, crc)
bsw.PutBytes(tmpcrc) bsw.PutBytes(tmpcrc)
} }
func (pmt *Pmt) Decode(bs *codec.BitStream) error { func (pmt *Pmt) Decode(bs *codec.BitStream) error {
pmt.Table_id = bs.Uint8(8) pmt.Table_id = bs.Uint8(8)
if pmt.Table_id != uint8(TS_TID_PMS) { if pmt.Table_id != uint8(TS_TID_PMS) {
return errors.New("table id is Not TS_TID_PAS") return errors.New("table id is Not TS_TID_PAS")
} }
pmt.Section_syntax_indicator = bs.Uint8(1) pmt.Section_syntax_indicator = bs.Uint8(1)
bs.SkipBits(3) bs.SkipBits(3)
pmt.Section_length = bs.Uint16(12) pmt.Section_length = bs.Uint16(12)
pmt.Program_number = bs.Uint16(16) pmt.Program_number = bs.Uint16(16)
bs.SkipBits(2) bs.SkipBits(2)
pmt.Version_number = bs.Uint8(5) pmt.Version_number = bs.Uint8(5)
pmt.Current_next_indicator = bs.Uint8(1) pmt.Current_next_indicator = bs.Uint8(1)
pmt.Section_number = bs.Uint8(8) pmt.Section_number = bs.Uint8(8)
pmt.Last_section_number = bs.Uint8(8) pmt.Last_section_number = bs.Uint8(8)
bs.SkipBits(3) bs.SkipBits(3)
pmt.PCR_PID = bs.Uint16(13) pmt.PCR_PID = bs.Uint16(13)
bs.SkipBits(4) bs.SkipBits(4)
pmt.Program_info_length = bs.Uint16(12) pmt.Program_info_length = bs.Uint16(12)
//TODO N loop descriptors //TODO N loop descriptors
bs.SkipBits(int(pmt.Program_info_length) * 8) 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) //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; { for i := 0; i < int(pmt.Section_length)-9-int(pmt.Program_info_length)-4; {
tmp := StreamPair{ tmp := StreamPair{
StreamType: 0, StreamType: 0,
Elementary_PID: 0, Elementary_PID: 0,
ES_Info_Length: 0, ES_Info_Length: 0,
} }
tmp.StreamType = bs.Uint8(8) tmp.StreamType = bs.Uint8(8)
bs.SkipBits(3) bs.SkipBits(3)
tmp.Elementary_PID = bs.Uint16(13) tmp.Elementary_PID = bs.Uint16(13)
bs.SkipBits(4) bs.SkipBits(4)
tmp.ES_Info_Length = bs.Uint16(12) tmp.ES_Info_Length = bs.Uint16(12)
//TODO N loop descriptors //TODO N loop descriptors
bs.SkipBits(int(tmp.ES_Info_Length) * 8) bs.SkipBits(int(tmp.ES_Info_Length) * 8)
pmt.Streams = append(pmt.Streams, tmp) pmt.Streams = append(pmt.Streams, tmp)
i += 5 + int(tmp.ES_Info_Length) i += 5 + int(tmp.ES_Info_Length)
} }
return nil return nil
} }

View file

@ -1,12 +1,21 @@
FROM ossrs/srs:dev-gcc7-cache FROM ossrs/srs:ubuntu20-cache
# Install depends tools. ARG MAKEARGS
RUN yum install -y gcc make gcc-c++ patch unzip perl git 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. # Build and install SRS.
COPY . /srs COPY . /srs
WORKDIR /srs/trunk WORKDIR /srs/trunk
# Note that we must enable the gcc7 or link failed. # 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 ./configure --srt=on --gb28181=on --apm=on --h265=on --utest=on --gcov=on --sanitizer=off
RUN scl enable devtoolset-7 -- make utest RUN make utest ${MAKEARGS}

View file

@ -1,16 +1,24 @@
FROM ossrs/srs:dev-gcc7-cache FROM ossrs/srs:ubuntu20-cache
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. # Build and install SRS.
COPY . /srs COPY . /srs
WORKDIR /srs/trunk WORKDIR /srs/trunk
# Note that we must enable the gcc7 or link failed. # 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 ./configure --srt=on --gb28181=on --srt=on --gb28181=on --apm=on --h265=on --utest=on
RUN scl enable devtoolset-7 -- make utest RUN make utest ${MAKEARGS}
# Build benchmark tool. # Build benchmark tool.
RUN cd 3rdparty/srs-bench && make RUN cd 3rdparty/srs-bench && make ${MAKEARGS}
# Run utest
RUN ./objs/srs_utest

View file

@ -1,6 +1,8 @@
listen 1935; listen 1935;
max_connections 1000; max_connections 1000;
# For clion, use console as output.
daemon off; daemon off;
srs_log_tank console; srs_log_tank console;

View file

@ -1,7 +1,11 @@
listen 1935; listen 1935;
max_connections 1000; 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 { stream_caster {
enabled on; enabled on;

View file

@ -24,6 +24,7 @@ The changelog for SRS.
## SRS 5.0 Changelog ## 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 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-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 * v5.0, 2022-12-26, For [#939](https://github.com/ossrs/srs/issues/939): FLV: Fix bug for header flag gussing. v5.0.119

View file

@ -9,6 +9,6 @@
#define VERSION_MAJOR 5 #define VERSION_MAJOR 5
#define VERSION_MINOR 0 #define VERSION_MINOR 0
#define VERSION_REVISION 121 #define VERSION_REVISION 122
#endif #endif