diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d8cff8e87..5ca048ece 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -4,6 +4,7 @@ name: "Test" on: [push, pull_request] # The dependency graph: +# test(6m) # multiple-arch-armv7(13m) # multiple-arch-aarch64(7m) # cygwin64-cache(1m) @@ -16,9 +17,7 @@ on: [push, pull_request] # build-cross-arm(3m) # build-cross-aarch64(3m) # multiple-arch-amd64(2m) -# utest(3m) # coverage(3m) -# blackbox(3m) jobs: cygwin64-cache: @@ -163,30 +162,8 @@ jobs: run: DOCKER_BUILDKIT=1 docker build -f trunk/Dockerfile.builds --target ubuntu20-cross-aarch64 . runs-on: ubuntu-20.04 - utest: - name: utest - needs: - - fast - steps: - - name: Checkout repository - uses: actions/checkout@v3 - # Tests - - name: Build test image - run: docker build --tag srs:test --build-arg MAKEARGS='-j2' -f trunk/Dockerfile.test . - # For utest - - name: Run SRS utest - run: docker run --rm srs:test ./objs/srs_utest - # For regression-test - - name: Run SRS regression-test - run: | - docker run --rm srs:test bash -c './objs/srs -c conf/regression-test.conf && \ - cd 3rdparty/srs-bench && ./objs/srs_test -test.v && ./objs/srs_gb28181_test -test.v' - runs-on: ubuntu-20.04 - - blackbox: - name: blackbox - needs: - - fast + test: + name: utest-regression-blackbox-test steps: - name: Checkout repository uses: actions/checkout@v3 @@ -196,10 +173,21 @@ jobs: # For blackbox-test - name: Run SRS blackbox-test run: | + #docker run --rm -w /srs/trunk/3rdparty/srs-bench srs:test ./objs/srs_blackbox_test -test.v \ + # -test.run 'TestFast_RtmpPublish_DvrFlv_Basic' -srs-log -srs-stdout srs-ffmpeg-stderr -srs-dvr-stderr \ + # -srs-ffprobe-stdout docker run --rm -w /srs/trunk/3rdparty/srs-bench srs:test \ ./objs/srs_blackbox_test -test.v -test.run '^TestFast' -test.parallel 64 docker run --rm -w /srs/trunk/3rdparty/srs-bench srs:test \ ./objs/srs_blackbox_test -test.v -test.run '^TestSlow' -test.parallel 4 + # For utest + - name: Run SRS utest + run: docker run --rm srs:test ./objs/srs_utest + # For regression-test + - name: Run SRS regression-test + run: | + docker run --rm srs:test bash -c './objs/srs -c conf/regression-test.conf && \ + cd 3rdparty/srs-bench && ./objs/srs_test -test.v && ./objs/srs_gb28181_test -test.v' runs-on: ubuntu-20.04 coverage: @@ -312,8 +300,7 @@ jobs: needs: - cygwin64 - coverage - - blackbox - - utest + - test - build-centos7 - build-ubuntu16 - build-ubuntu18 diff --git a/trunk/3rdparty/srs-bench/blackbox/dvr_test.go b/trunk/3rdparty/srs-bench/blackbox/dvr_test.go new file mode 100644 index 000000000..48214ceda --- /dev/null +++ b/trunk/3rdparty/srs-bench/blackbox/dvr_test.go @@ -0,0 +1,143 @@ +// The MIT License (MIT) +// +// # Copyright (c) 2023 Winlin +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +package blackbox + +import ( + "context" + "fmt" + "github.com/ossrs/go-oryx-lib/errors" + "github.com/ossrs/go-oryx-lib/logger" + "math/rand" + "os" + "path" + "sync" + "testing" + "time" +) + +func TestFast_RtmpPublish_DvrFlv_Basic(t *testing.T) { + // This case is run in parallel. + t.Parallel() + + // Setup the max timeout for this case. + ctx, cancel := context.WithTimeout(logger.WithContext(context.Background()), time.Duration(*srsTimeout)*time.Millisecond) + defer cancel() + + // Check a set of errors. + var r0, r1, r2, r3, r4, r5, r6 error + defer func(ctx context.Context) { + if err := filterTestError(ctx.Err(), r0, r1, r2, r3, r4, r5, r6); err != nil { + t.Errorf("Fail for err %+v", err) + } else { + logger.Tf(ctx, "test done with err %+v", err) + } + }(ctx) + + var wg sync.WaitGroup + defer wg.Wait() + + // Start hooks service. + hooks := NewHooksService() + wg.Add(1) + go func() { + defer wg.Done() + r6 = hooks.Run(ctx, cancel) + }() + + // Start SRS server and wait for it to be ready. + svr := NewSRSServer(func(v *srsServer) { + v.envs = []string{ + "SRS_VHOST_DVR_ENABLED=on", + "SRS_VHOST_DVR_DVR_PLAN=session", + "SRS_VHOST_DVR_DVR_PATH=./objs/nginx/html/[app]/[stream].[timestamp].flv", + fmt.Sprintf("SRS_VHOST_DVR_DVR_DURATION=%v", *srsFFprobeDuration), + "SRS_VHOST_HTTP_HOOKS_ENABLED=on", + fmt.Sprintf("SRS_VHOST_HTTP_HOOKS_ON_DVR=http://localhost:%v/api/v1/dvrs", hooks.HooksAPI()), + } + }) + wg.Add(1) + go func() { + defer wg.Done() + <-hooks.ReadyCtx().Done() + r0 = svr.Run(ctx, cancel) + }() + + // Start FFmpeg to publish stream. + duration := time.Duration(*srsFFprobeDuration) * time.Millisecond + streamID := fmt.Sprintf("stream-%v-%v", os.Getpid(), rand.Int()) + streamURL := fmt.Sprintf("rtmp://localhost:%v/live/%v", svr.RTMPPort(), streamID) + ffmpeg := NewFFmpeg(func(v *ffmpegClient) { + // When process quit, still keep case to run. + v.cancelCaseWhenQuit, v.ffmpegDuration = false, duration + v.args = []string{ + "-stream_loop", "-1", "-re", "-i", *srsPublishAvatar, "-c", "copy", "-f", "flv", streamURL, + } + }) + wg.Add(1) + go func() { + defer wg.Done() + <-svr.ReadyCtx().Done() + r1 = ffmpeg.Run(ctx, cancel) + }() + + // Start FFprobe to detect and verify stream. + ffprobe := NewFFprobe(func(v *ffprobeClient) { + v.dvrByFFmpeg, v.streamURL = false, streamURL + v.duration, v.timeout = duration, time.Duration(*srsFFprobeTimeout)*time.Millisecond + + wg.Add(1) + go func() { + defer wg.Done() + for evt := range hooks.HooksEvents() { + if onDvrEvt, ok := evt.(*HooksEventOnDvr); ok { + fp := path.Join(svr.WorkDir(), onDvrEvt.File) + logger.Tf(ctx, "FFprobe: Set the dvrFile=%v from callback", fp) + v.dvrFile = fp + } + } + }() + }) + wg.Add(1) + go func() { + defer wg.Done() + <-svr.ReadyCtx().Done() + r2 = ffprobe.Run(ctx, cancel) + }() + + // Fast quit for probe done. + select { + case <-ctx.Done(): + case <-ffprobe.ProbeDoneCtx().Done(): + defer cancel() + + str, m := ffprobe.Result() + if len(m.Streams) != 2 { + r3 = errors.Errorf("invalid streams=%v, %v, %v", len(m.Streams), m.String(), str) + } + + if ts := 90; m.Format.ProbeScore < ts { + r4 = errors.Errorf("low score=%v < %v, %v, %v", m.Format.ProbeScore, ts, m.String(), str) + } + if dv := m.Duration(); dv < duration/2 { + r5 = errors.Errorf("short duration=%v < %v, %v, %v", dv, duration/2, m.String(), str) + } + } +} diff --git a/trunk/3rdparty/srs-bench/blackbox/util.go b/trunk/3rdparty/srs-bench/blackbox/util.go index c85508bf2..829da568f 100644 --- a/trunk/3rdparty/srs-bench/blackbox/util.go +++ b/trunk/3rdparty/srs-bench/blackbox/util.go @@ -27,6 +27,7 @@ import ( "flag" "fmt" "github.com/ossrs/go-oryx-lib/errors" + ohttp "github.com/ossrs/go-oryx-lib/http" "github.com/ossrs/go-oryx-lib/logger" "io/ioutil" "math/rand" @@ -200,6 +201,8 @@ type backendService struct { name string args []string env []string + // If timeout, kill the process. + duration time.Duration // The process stdout and stderr. stdout bytes.Buffer @@ -315,6 +318,22 @@ func (v *backendService) Run(ctx context.Context, cancel context.CancelFunc) err // The context for SRS process. processDone, processDoneCancel := context.WithCancel(context.Background()) + // If exceed timeout, kill the process. + v.wg.Add(1) + go func() { + defer v.wg.Done() + if v.duration <= 0 { + return + } + + select { + case <- ctx.Done(): + case <-time.After(v.duration): + logger.Tf(ctx, "Process killed duration=%v, pid=%v, name=%v, args=%v", v.duration, v.pid, v.name, v.args) + cmd.Process.Kill() + } + }() + // If SRS process terminated, notify case to stop. v.wg.Add(1) go func() { @@ -327,12 +346,12 @@ func (v *backendService) Run(ctx context.Context, cancel context.CancelFunc) err defer processDoneCancel() if err := cmd.Wait(); err != nil && !v.ignoreExitStatusError { - v.r0 = errors.Wrapf(err, "Process wait err, name=%v, args=%v", v.name, v.args) + v.r0 = errors.Wrapf(err, "Process wait err, pid=%v, name=%v, args=%v", v.pid, v.name, v.args) } if v.onStop != nil { if err := v.onStop(ctx, v, cmd, v.r0, &v.stdout, &v.stderr); err != nil { if v.r0 == nil { - v.r0 = errors.Wrapf(err, "Process onStop err, name=%v, args=%v", v.name, v.args) + v.r0 = errors.Wrapf(err, "Process onStop err, pid=%v, name=%v, args=%v", v.pid, v.name, v.args) } else { logger.Ef(ctx, "Process onStop err %v", err) } @@ -435,7 +454,7 @@ type srsServer struct { func NewSRSServer(opts ...func(v *srsServer)) SRSServer { rid := fmt.Sprintf("%v-%v", os.Getpid(), rand.Int()) v := &srsServer{ - workDir: "./", + workDir: path.Join("objs", fmt.Sprintf("%v", rand.Int())), srsID: fmt.Sprintf("srs-id-%v", rid), process: newBackendService(), } @@ -443,7 +462,7 @@ func NewSRSServer(opts ...func(v *srsServer)) SRSServer { // If we run in GoLand, the current directory is in blackbox, so we use parent directory. if _, err := os.Stat("objs"); err != nil { - v.workDir = "../" + v.workDir = path.Join("..", "objs", fmt.Sprintf("%v", rand.Int())) } // Do allocate resource. @@ -461,22 +480,12 @@ func NewSRSServer(opts ...func(v *srsServer)) SRSServer { allocator.Free(v.httpListen) allocator.Free(v.srtListen) - pidFile := path.Join(v.workDir, v.srsRelativePidFile) - if _, err := os.Stat(pidFile); err == nil { - os.Remove(pidFile) + if _, err := os.Stat(v.workDir); err == nil { + os.RemoveAll(v.workDir) } - idFile := path.Join(v.workDir, v.srsRelativeIDFile) - if _, err := os.Stat(idFile); err == nil { - os.Remove(idFile) - } - - hlsFiles := path.Join(v.workDir, "objs", "live") - if _, err := os.Stat(hlsFiles); err == nil { - os.RemoveAll(hlsFiles) - } - - logger.Tf(ctx, "SRS server is closed, id=%v, pid=%v, r0=%v", v.srsID, bs.pid, bs.r0) + logger.Tf(ctx, "SRS server is closed, id=%v, pid=%v, cleanup=%v r0=%v", + v.srsID, bs.pid, v.workDir, bs.r0) return nil } @@ -512,20 +521,39 @@ func (v *srsServer) Run(ctx context.Context, cancel context.CancelFunc) error { v.workDir, *srsBinary, v.srsID, v.srsRelativePidFile, v.rtmpListen, ) + // Create directories. + if err := os.MkdirAll(path.Join(v.workDir, "./objs/nginx/html"), os.FileMode(0755) | os.ModeDir); err != nil { + return errors.Wrapf(err, "SRS create directory %v", path.Join(v.workDir, "./objs/nginx/html")) + } + // Setup the name and args of process. v.process.name = *srsBinary v.process.args = []string{"-e"} - // Setup the envrionment variables. + // Setup the constant values. v.process.env = []string{ - // SRS working directory. - fmt.Sprintf("SRS_WORK_DIR=%v", v.workDir), // Run in frontend. "SRS_DAEMON=off", // Write logs to stdout and stderr. "SRS_SRS_LOG_FILE=console", // Disable warning for asan. "MallocNanoZone=0", + // Avoid error for macOS, which ulimit to 256. + "SRS_MAX_CONNECTIONS=100", + } + // For directories. + v.process.env = append(v.process.env, []string{ + // SRS working directory. + fmt.Sprintf("SRS_WORK_DIR=%v", v.workDir), + // Setup the default directory for HTTP server. + "SRS_HTTP_SERVER_DIR=./objs/nginx/html", + // Setup the default directory for HLS stream. + "SRS_VHOST_HLS_HLS_PATH=./objs/nginx/html", + "SRS_VHOST_HLS_HLS_M3U8_FILE=[app]/[stream].m3u8", + "SRS_VHOST_HLS_HLS_TS_FILE=[app]/[stream]-[seq].ts", + }...) + // For variables. + v.process.env = append(v.process.env, []string{ // SRS PID file. fmt.Sprintf("SRS_PID=%v", v.srsRelativePidFile), // SRS ID file. @@ -533,19 +561,13 @@ func (v *srsServer) Run(ctx context.Context, cancel context.CancelFunc) error { // HTTP API to detect the service. fmt.Sprintf("SRS_HTTP_API_ENABLED=on"), fmt.Sprintf("SRS_HTTP_API_LISTEN=%v", v.apiListen), - // Avoid error for macOS, which ulimit to 256. - "SRS_MAX_CONNECTIONS=100", - // Setup the default directory for HTTP server. - "SRS_HTTP_SERVER_DIR=objs", - // Setup the default directory for HLS stream. - "SRS_VHOST_HLS_HLS_PATH=objs", // Setup the RTMP listen port. fmt.Sprintf("SRS_LISTEN=%v", v.rtmpListen), // Setup the HTTP sever listen port. fmt.Sprintf("SRS_HTTP_SERVER_LISTEN=%v", v.httpListen), // Setup the SRT server listen port. fmt.Sprintf("SRS_SRT_SERVER_LISTEN=%v", v.srtListen), - } + }...) // Rewrite envs by case. if v.envs != nil { v.process.env = append(v.process.env, v.envs...) @@ -588,8 +610,8 @@ func (v *srsServer) Run(ctx context.Context, cancel context.CancelFunc) error { // Hooks for process. v.process.onBeforeStart = func(ctx context.Context, bs *backendService, cmd *exec.Cmd) error { - logger.Tf(ctx, "SRS id=%v, env=%v, cmd is %v %v", - v.srsID, cmd.Env, bs.name, strings.Join(bs.args, " ")) + logger.Tf(ctx, "SRS id=%v, env %v %v %v", + v.srsID, strings.Join(cmd.Env, " "), bs.name, strings.Join(bs.args, " ")) return nil } v.process.onAfterStart = func(ctx context.Context, bs *backendService, cmd *exec.Cmd) error { @@ -625,11 +647,16 @@ type ffmpegClient struct { // FFmpeg cli args, without ffmpeg binary. args []string + // Let the process quit, do not cancel the case. + cancelCaseWhenQuit bool + // When timeout, stop FFmpeg, sometimes the '-t' does not work. + ffmpegDuration time.Duration } func NewFFmpeg(opts ...func(v *ffmpegClient)) FFmpegClient { v := &ffmpegClient{ process: newBackendService(), + cancelCaseWhenQuit: true, } // Do cleanup. @@ -657,6 +684,7 @@ func (v *ffmpegClient) Run(ctx context.Context, cancel context.CancelFunc) error v.process.name = *srsFFmpeg v.process.args = v.args v.process.env = os.Environ() + v.process.duration = v.ffmpegDuration v.process.onStop = func(ctx context.Context, bs *backendService, cmd *exec.Cmd, r0 error, stdout, stderr *bytes.Buffer) error { logger.Tf(ctx, "FFmpeg process pid=%v exit, r0=%v, stdout=%v", bs.pid, r0, stdout.String()) @@ -666,7 +694,20 @@ func (v *ffmpegClient) Run(ctx context.Context, cancel context.CancelFunc) error return nil } - return v.process.Run(ctx, cancel) + // We might not want to cancel the case, for example, when check DVR by session, we just let the FFmpeg process to + // quit and we should check the callback and DVR file. + ffCtx, ffCancel := context.WithCancel(ctx) + go func() { + select { + case <- ctx.Done(): + case <-ffCtx.Done(): + if v.cancelCaseWhenQuit { + cancel() + } + } + }() + + return v.process.Run(ffCtx, ffCancel) } type FFprobeClient interface { @@ -678,16 +719,19 @@ type FFprobeClient interface { } type ffprobeClient struct { - // The stream to probe. - streamURL string - - // The DVR file for ffprobe. We DVR stream to file, then use ffprobe to detect it. + // The DVR file for ffprobe. Stream should be DVR to file, then use ffprobe to detect it. If DVR by FFmpeg, we will + // start a FFmpeg process to do the DVR, or the DVR should be done by other tools. dvrFile string - // The duration of video file for DVR. - duration time.Duration // The timeout to wait for task to done. timeout time.Duration + // Whether do DVR by FFmpeg, if using SRS DVR, please set to false. + dvrByFFmpeg bool + // The stream to DVR for probing. Ignore if not DVR by ffmpeg + streamURL string + // The duration of video file for DVR and probing. + duration time.Duration + // When probe stream metadata object. doneCtx context.Context doneCancel context.CancelFunc @@ -699,7 +743,8 @@ type ffprobeClient struct { func NewFFprobe(opts ...func(v *ffprobeClient)) FFprobeClient { v := &ffprobeClient{ - metadata: &ffprobeObject{}, + metadata: &ffprobeObject{}, + dvrByFFmpeg: true, } v.doneCtx, v.doneCancel = context.WithCancel(context.Background()) @@ -728,9 +773,12 @@ func (v *ffprobeClient) Run(ctxCase context.Context, cancelCase context.CancelFu // Try to start a DVR process. for ctx.Err() == nil { - // If error, just ignore and retry, because the stream might not be ready. For example, for HLS, the DVR process - // might need to wait for a duration of segment, 10s as such. - _ = v.doDVR(ctx) + // If not DVR by FFmpeg, we just wait the DVR file to be ready, and it should be done by SRS or other tools. + if v.dvrByFFmpeg { + // If error, just ignore and retry, because the stream might not be ready. For example, for HLS, the DVR process + // might need to wait for a duration of segment, 10s as such. + _ = v.doDVR(ctx) + } // Check whether DVR file is ok. if fs, err := os.Stat(v.dvrFile); err == nil && fs.Size() > 1024 { @@ -738,9 +786,14 @@ func (v *ffprobeClient) Run(ctxCase context.Context, cancelCase context.CancelFu break } + // If not DVR by FFmpeg, must be by other tools, only need to wait. + if !v.dvrByFFmpeg { + logger.Tf(ctx, "Waiting stream=%v to be DVR", v.streamURL) + } + // Wait for a while and retry. Use larger timeout for HLS. retryTimeout := 1 * time.Second - if strings.Contains(v.streamURL, ".m3u8") { + if strings.Contains(v.streamURL, ".m3u8") || v.dvrFile == "" { retryTimeout = 3 * time.Second } @@ -763,6 +816,10 @@ func (v *ffprobeClient) Run(ctxCase context.Context, cancelCase context.CancelFu func (v *ffprobeClient) doDVR(ctx context.Context) error { ctx, cancel := context.WithCancel(ctx) + if !v.dvrByFFmpeg { + return nil + } + process := newBackendService() process.name = *srsFFmpeg process.args = []string{ @@ -1070,3 +1127,167 @@ func (v *ffprobeObject) Audio() *ffprobeObjectMedia { } return nil } + +type HooksEvent interface { + HookAction() string +} + +type HooksEventBase struct { + Action string `json:"action"` +} + +func (v *HooksEventBase) HookAction() string { + return v.Action +} + +type HooksEventOnDvr struct { + HooksEventBase + Stream string `json:"stream"` + StreamUrl string `json:"stream_url"` + StreamID string `json:"stream_id"` + CWD string `json:"cwd"` + File string `json:"file"` + TcUrl string `json:"tcUrl"` + App string `json:"app"` + Vhost string `json:"vhost"` + IP string `json:"ip"` + ClientIP string `json:"client_id"` + ServerID string `json:"server_id"` +} + +type HooksService interface { + ServiceRunner + ServiceReadyQuerier + HooksAPI() int + HooksEvents() <-chan HooksEvent +} + +type hooksService struct { + readyCtx context.Context + readyCancel context.CancelFunc + + httpPort int + dispose func() + + r0 error + hooksOnDvr chan HooksEvent +} + +func NewHooksService(opts ...func(v *hooksService)) HooksService { + v := &hooksService{} + + v.httpPort = allocator.Allocate() + v.dispose = func() { + allocator.Free(v.httpPort) + close(v.hooksOnDvr) + } + v.hooksOnDvr = make(chan HooksEvent, 64) + v.readyCtx, v.readyCancel = context.WithCancel(context.Background()) + + for _, opt := range opts { + opt(v) + } + + return v +} + +func (v *hooksService) ReadyCtx() context.Context { + return v.readyCtx +} + +func (v *hooksService) HooksAPI() int { + return v.httpPort +} + +func (v *hooksService) HooksEvents() <-chan HooksEvent { + return v.hooksOnDvr +} + +func (v *hooksService) Run(ctx context.Context, cancel context.CancelFunc) error { + defer func() { + v.readyCancel() + v.dispose() + }() + + handler := http.ServeMux{} + handler.HandleFunc("/api/v1/ping", func(w http.ResponseWriter, r *http.Request) { + ohttp.WriteData(ctx, w, r, "pong") + }) + + handler.HandleFunc("/api/v1/dvrs", func(w http.ResponseWriter, r *http.Request) { + b, err := ioutil.ReadAll(r.Body) + if err != nil { + ohttp.WriteError(ctx, w, r, err) + return + } + + evt := HooksEventOnDvr{} + if err := json.Unmarshal(b, &evt); err != nil { + ohttp.WriteError(ctx, w, r, err) + return + } + + select { + case <-ctx.Done(): + case v.hooksOnDvr <- &evt: + } + + logger.Tf(ctx, "Callback: Got on_dvr request %v", string(b)) + ohttp.WriteData(ctx, w, r, nil) + }) + + server := &http.Server{Addr: fmt.Sprintf(":%v", v.httpPort), Handler: &handler} + + var wg sync.WaitGroup + defer wg.Wait() + + wg.Add(1) + go func() { + defer wg.Done() + logger.Tf(ctx, "Callback: Start hooks server, listen=%v", v.httpPort) + + if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed { + logger.Wf(ctx, "Callback: Service listen=%v, err %v", v.httpPort, err) + v.r0 = errors.Wrapf(err, "server listen=%v", v.httpPort) + cancel() + return + } + logger.Tf(ctx, "Callback: Hooks done, listen=%v", v.httpPort) + }() + + wg.Add(1) + go func() { + defer wg.Done() + <-ctx.Done() + + go server.Shutdown(context.Background()) + }() + + wg.Add(1) + go func() { + defer wg.Done() + + for ctx.Err() == nil { + time.Sleep(100 * time.Millisecond) + + r := fmt.Sprintf("http://localhost:%v/api/v1/ping", v.httpPort) + res, err := http.Get(r) + if err != nil { + continue + } + defer res.Body.Close() + + b, err := ioutil.ReadAll(res.Body) + if err != nil { + continue + } + + logger.Tf(ctx, "Callback: API is ready, %v %v", r, string(b)) + v.readyCancel() + return + } + }() + + wg.Wait() + return v.r0 +} diff --git a/trunk/3rdparty/srs-bench/go.mod b/trunk/3rdparty/srs-bench/go.mod index cf79ee8c5..294179920 100644 --- a/trunk/3rdparty/srs-bench/go.mod +++ b/trunk/3rdparty/srs-bench/go.mod @@ -12,6 +12,7 @@ require ( github.com/pion/sdp/v3 v3.0.4 github.com/pion/transport v0.12.2 github.com/pion/webrtc/v3 v3.0.13 + github.com/pkg/errors v0.9.1 github.com/yapingcat/gomedia/codec v0.0.0-20220617074658-94762898dc25 github.com/yapingcat/gomedia/mpeg2 v0.0.0-20220617074658-94762898dc25 ) diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/ghettovoice/gosip/sip/parser/error.go b/trunk/3rdparty/srs-bench/vendor/github.com/ghettovoice/gosip/sip/parser/error.go index b5979ca8e..caea6ef3c 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/ghettovoice/gosip/sip/parser/error.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/ghettovoice/gosip/sip/parser/error.go @@ -11,9 +11,7 @@ type InvalidStartLineError string func (err InvalidStartLineError) Syntax() bool { return true } func (err InvalidStartLineError) Malformed() bool { return false } func (err InvalidStartLineError) Broken() bool { return true } -func (err InvalidStartLineError) Error() string { - return "parser.InvalidStartLineError: " + string(err) -} +func (err InvalidStartLineError) Error() string { return "parser.InvalidStartLineError: " + string(err) } type InvalidMessageFormat string diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/ossrs/go-oryx-lib/http/api.go b/trunk/3rdparty/srs-bench/vendor/github.com/ossrs/go-oryx-lib/http/api.go new file mode 100644 index 000000000..09273c8c1 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/ossrs/go-oryx-lib/http/api.go @@ -0,0 +1,87 @@ +// The MIT License (MIT) +// +// Copyright (c) 2013-2017 Oryx(ossrs) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +// The oryx http package, the response parse service. +package http + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "net/http" +) + +// Read http api by HTTP GET and parse the code/data. +func ApiRequest(url string) (code int, body []byte, err error) { + if body, err = apiGet(url); err != nil { + return + } + + if code, _, err = apiParse(url, body); err != nil { + return + } + + return +} + +// Read http api by HTTP GET. +func apiGet(url string) (body []byte, err error) { + var resp *http.Response + if resp, err = http.Get(url); err != nil { + err = fmt.Errorf("api get failed, url=%v, err is %v", url, err) + return + } + defer resp.Body.Close() + + if body, err = ioutil.ReadAll(resp.Body); err != nil { + err = fmt.Errorf("api read failed, url=%v, err is %v", url, err) + return + } + + return +} + +// Parse the standard response {code:int,data:object}. +func apiParse(url string, body []byte) (code int, data interface{}, err error) { + obj := make(map[string]interface{}) + if err = json.Unmarshal(body, &obj); err != nil { + err = fmt.Errorf("api parse failed, url=%v, body=%v, err is %v", url, string(body), err) + return + } + + if value, ok := obj["code"]; !ok { + err = fmt.Errorf("api no code, url=%v, body=%v", url, string(body)) + return + } else if value, ok := value.(float64); !ok { + err = fmt.Errorf("api code not number, code=%v, url=%v, body=%v", value, url, string(body)) + return + } else { + code = int(value) + } + + data, _ = obj["data"] + if code != 0 { + err = fmt.Errorf("api error, code=%v, url=%v, body=%v, data=%v", code, url, string(body), data) + return + } + + return +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/ossrs/go-oryx-lib/http/http.go b/trunk/3rdparty/srs-bench/vendor/github.com/ossrs/go-oryx-lib/http/http.go new file mode 100644 index 000000000..489fa7f70 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/ossrs/go-oryx-lib/http/http.go @@ -0,0 +1,274 @@ +// The MIT License (MIT) +// +// Copyright (c) 2013-2017 Oryx(ossrs) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +// The oryx http package provides standard request and response in json. +// Error, when error, use this handler. +// CplxError, for complex error, use this handler. +// Data, when no error, use this handler. +// SystemError, application level error code. +// SetHeader, for direclty response the raw stream. +// The standard server response: +// code, an int error code. +// data, specifies the data. +// The api for simple api: +// WriteVersion, to directly response the version. +// WriteData, to directly write the data in json. +// WriteError, to directly write the error. +// WriteCplxError, to directly write the complex error. +// The global variables: +// oh.Server, to set the response header["Server"]. +package http + +import ( + "encoding/json" + "fmt" + ol "github.com/ossrs/go-oryx-lib/logger" + "net/http" + "os" + "strconv" + "strings" +) + +// header["Content-Type"] in response. +const ( + HttpJson = "application/json" + HttpJavaScript = "application/javascript" +) + +// header["Server"] in response. +var Server = "Oryx" + +// system int error. +type SystemError int + +func (v SystemError) Error() string { + return fmt.Sprintf("System error=%d", int(v)) +} + +// system conplex error. +type SystemComplexError struct { + // the system error code. + Code SystemError `json:"code"` + // the description for this error. + Message string `json:"data"` +} + +func (v SystemComplexError) Error() string { + return fmt.Sprintf("%v, %v", v.Code.Error(), v.Message) +} + +// application level, with code. +type AppError interface { + Code() int + error +} + +// HTTP Status Code +type HTTPStatus interface { + Status() int +} + +// http standard error response. +// @remark for not SystemError, we will use logger.E to print it. +// @remark user can use WriteError() for simple api. +func Error(ctx ol.Context, err error) http.Handler { + // for complex error, use code instead. + if v, ok := err.(SystemComplexError); ok { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + jsonHandler(ctx, FilterCplxSystemError(ctx, w, r, v)).ServeHTTP(w, r) + }) + } + + // for int error, use code instead. + if v, ok := err.(SystemError); ok { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + jsonHandler(ctx, FilterSystemError(ctx, w, r, v)).ServeHTTP(w, r) + }) + } + + // for application error, use code instead. + if v, ok := err.(AppError); ok { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + jsonHandler(ctx, FilterAppError(ctx, w, r, v)).ServeHTTP(w, r) + }) + } + + // unknown error, log and response detail + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + SetHeader(w) + w.Header().Set("Content-Type", HttpJson) + + status := http.StatusInternalServerError + if v, ok := err.(HTTPStatus); ok { + status = v.Status() + } + + http.Error(w, FilterError(ctx, w, r, err), status) + }) +} + +// Wrapper for complex error use Error(ctx, SystemComplexError{}) +// @remark user can use WriteCplxError() for simple api. +func CplxError(ctx ol.Context, code SystemError, message string) http.Handler { + return Error(ctx, SystemComplexError{code, message}) +} + +// http normal response. +// @remark user can use nil v to response success, which data is null. +// @remark user can use WriteData() for simple api. +func Data(ctx ol.Context, v interface{}) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + jsonHandler(ctx, FilterData(ctx, w, r, v)).ServeHTTP(w, r) + }) +} + +// set http header, for directly use the w, +// for example, user want to directly write raw text. +func SetHeader(w http.ResponseWriter) { + w.Header().Set("Server", Server) +} + +// response json directly. +func jsonHandler(ctx ol.Context, rv interface{}) http.Handler { + var err error + var b []byte + if b, err = json.Marshal(rv); err != nil { + return Error(ctx, err) + } + + status := http.StatusOK + if v, ok := rv.(HTTPStatus); ok { + status = v.Status() + } + + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + SetHeader(w) + + q := r.URL.Query() + if cb := q.Get("callback"); cb != "" { + w.Header().Set("Content-Type", HttpJavaScript) + if status != http.StatusOK { + w.WriteHeader(status) + } + + // TODO: Handle error. + fmt.Fprintf(w, "%s(%s)", cb, string(b)) + } else { + w.Header().Set("Content-Type", HttpJson) + if status != http.StatusOK { + w.WriteHeader(status) + } + // TODO: Handle error. + w.Write(b) + } + }) +} + +// response the standard version info: +// {code, server, data} where server is the server pid, and data is below object: +// {major, minor, revision, extra, version, signature} +// @param version in {major.minor.revision-extra}, where -extra is optional, +// for example: 1.0.0 or 1.0.0-0 or 1.0.0-1 +func WriteVersion(w http.ResponseWriter, r *http.Request, version string) { + var major, minor, revision, extra int + + versions := strings.Split(version, "-") + if len(versions) > 1 { + extra, _ = strconv.Atoi(versions[1]) + } + + versions = strings.Split(versions[0], ".") + if len(versions) > 0 { + major, _ = strconv.Atoi(versions[0]) + } + if len(versions) > 1 { + minor, _ = strconv.Atoi(versions[1]) + } + if len(versions) > 2 { + revision, _ = strconv.Atoi(versions[2]) + } + + Data(nil, map[string]interface{}{ + "major": major, + "minor": minor, + "revision": revision, + "extra": extra, + "version": version, + "signature": Server, + }).ServeHTTP(w, r) +} + +// Directly write json data, a wrapper for Data(). +// @remark user can use Data() for group of complex apis. +func WriteData(ctx ol.Context, w http.ResponseWriter, r *http.Request, v interface{}) { + Data(ctx, v).ServeHTTP(w, r) +} + +// Directly write success json response, same to WriteData(ctx, w, r, nil). +func Success(ctx ol.Context, w http.ResponseWriter, r *http.Request) { + WriteData(ctx, w, r, nil) +} + +// Directly write error, a wrapper for Error(). +// @remark user can use Error() for group of complex apis. +func WriteError(ctx ol.Context, w http.ResponseWriter, r *http.Request, err error) { + Error(ctx, err).ServeHTTP(w, r) +} + +// Directly write complex error, a wrappter for CplxError(). +// @remark user can use CplxError() for group of complex apis. +func WriteCplxError(ctx ol.Context, w http.ResponseWriter, r *http.Request, code SystemError, message string) { + CplxError(ctx, code, message).ServeHTTP(w, r) +} + +// for hijack to define the response structure. +// user can redefine these functions for special response. +var FilterCplxSystemError = func(ctx ol.Context, w http.ResponseWriter, r *http.Request, o SystemComplexError) interface{} { + ol.Ef(ctx, "Serve %v failed, err is %+v", r.URL, o) + return o +} +var FilterSystemError = func(ctx ol.Context, w http.ResponseWriter, r *http.Request, o SystemError) interface{} { + ol.Ef(ctx, "Serve %v failed, err is %+v", r.URL, o) + return map[string]int{"code": int(o)} +} +var FilterAppError = func(ctx ol.Context, w http.ResponseWriter, r *http.Request, err AppError) interface{} { + ol.Ef(ctx, "Serve %v failed, err is %+v", r.URL, err) + return map[string]interface{}{"code": err.Code(), "data": err.Error()} +} +var FilterError = func(ctx ol.Context, w http.ResponseWriter, r *http.Request, err error) string { + ol.Ef(ctx, "Serve %v failed, err is %+v", r.URL, err) + return err.Error() +} +var FilterData = func(ctx ol.Context, w http.ResponseWriter, r *http.Request, o interface{}) interface{} { + rv := map[string]interface{}{ + "code": 0, + "server": os.Getpid(), + "data": o, + } + + // for string, directly use it without convert, + // for the type covert by golang maybe modify the content. + if v, ok := o.(string); ok { + rv["data"] = v + } + + return rv +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/sirupsen/logrus/terminal_check_bsd.go b/trunk/3rdparty/srs-bench/vendor/github.com/sirupsen/logrus/terminal_check_bsd.go index ff6ff7b99..3c4f43f91 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/sirupsen/logrus/terminal_check_bsd.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/sirupsen/logrus/terminal_check_bsd.go @@ -10,3 +10,4 @@ func isTerminal(fd int) bool { _, err := unix.IoctlGetTermios(fd, ioctlReadTermios) return err == nil } + diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/sirupsen/logrus/terminal_check_unix.go b/trunk/3rdparty/srs-bench/vendor/github.com/sirupsen/logrus/terminal_check_unix.go index 163c468d5..355dc966f 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/sirupsen/logrus/terminal_check_unix.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/sirupsen/logrus/terminal_check_unix.go @@ -10,3 +10,4 @@ func isTerminal(fd int) bool { _, err := unix.IoctlGetTermios(fd, ioctlReadTermios) return err == nil } + diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/x-cray/logrus-prefixed-formatter/formatter.go b/trunk/3rdparty/srs-bench/vendor/github.com/x-cray/logrus-prefixed-formatter/formatter.go index 1a5194f68..1235bcc39 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/x-cray/logrus-prefixed-formatter/formatter.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/x-cray/logrus-prefixed-formatter/formatter.go @@ -11,8 +11,8 @@ import ( "sync" "time" - "github.com/mgutz/ansi" "github.com/sirupsen/logrus" + "github.com/mgutz/ansi" "golang.org/x/crypto/ssh/terminal" ) diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/codec/aac.go b/trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/codec/aac.go index 1f96013c3..c9383a1d4 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/codec/aac.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/codec/aac.go @@ -12,25 +12,25 @@ import "errors" type AAC_PROFILE int const ( - MAIN AAC_PROFILE = iota - LC - SSR + MAIN AAC_PROFILE = iota + LC + SSR ) type AAC_SAMPLING_FREQUENCY int const ( - AAC_SAMPLE_96000 AAC_SAMPLING_FREQUENCY = iota - AAC_SAMPLE_88200 - AAC_SAMPLE_64000 - AAC_SAMPLE_48000 - AAC_SAMPLE_44100 - AAC_SAMPLE_32000 - AAC_SAMPLE_24000 - AAC_SAMPLE_22050 - AAC_SAMPLE_16000 - AAC_SAMPLE_11025 - AAC_SAMPLE_8000 + AAC_SAMPLE_96000 AAC_SAMPLING_FREQUENCY = iota + AAC_SAMPLE_88200 + AAC_SAMPLE_64000 + AAC_SAMPLE_48000 + AAC_SAMPLE_44100 + AAC_SAMPLE_32000 + AAC_SAMPLE_24000 + AAC_SAMPLE_22050 + AAC_SAMPLE_16000 + AAC_SAMPLE_11025 + AAC_SAMPLE_8000 ) var AAC_Sampling_Idx [11]int = [11]int{96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 11025, 8000} @@ -73,15 +73,15 @@ var AAC_Sampling_Idx [11]int = [11]int{96000, 88200, 64000, 48000, 44100, 32000, // } type ADTS_Fix_Header struct { - ID uint8 - Layer uint8 - Protection_absent uint8 - Profile uint8 - Sampling_frequency_index uint8 - Private_bit uint8 - Channel_configuration uint8 - Originalorcopy uint8 - Home uint8 + ID uint8 + Layer uint8 + Protection_absent uint8 + Profile uint8 + Sampling_frequency_index uint8 + Private_bit uint8 + Channel_configuration uint8 + Originalorcopy uint8 + Home uint8 } // adts_variable_header() { @@ -93,91 +93,91 @@ type ADTS_Fix_Header struct { // } type ADTS_Variable_Header struct { - Copyright_identification_bit uint8 - copyright_identification_start uint8 - Frame_length uint16 - Adts_buffer_fullness uint16 - Number_of_raw_data_blocks_in_frame uint8 + Copyright_identification_bit uint8 + copyright_identification_start uint8 + Frame_length uint16 + Adts_buffer_fullness uint16 + Number_of_raw_data_blocks_in_frame uint8 } type ADTS_Frame_Header struct { - Fix_Header ADTS_Fix_Header - Variable_Header ADTS_Variable_Header + Fix_Header ADTS_Fix_Header + Variable_Header ADTS_Variable_Header } func NewAdtsFrameHeader() *ADTS_Frame_Header { - return &ADTS_Frame_Header{ - Fix_Header: ADTS_Fix_Header{ - ID: 0, - Layer: 0, - Protection_absent: 1, - Profile: uint8(MAIN), - Sampling_frequency_index: uint8(AAC_SAMPLE_44100), - Private_bit: 0, - Channel_configuration: 0, - Originalorcopy: 0, - Home: 0, - }, + return &ADTS_Frame_Header{ + Fix_Header: ADTS_Fix_Header{ + ID: 0, + Layer: 0, + Protection_absent: 1, + Profile: uint8(MAIN), + Sampling_frequency_index: uint8(AAC_SAMPLE_44100), + Private_bit: 0, + Channel_configuration: 0, + Originalorcopy: 0, + Home: 0, + }, - Variable_Header: ADTS_Variable_Header{ - copyright_identification_start: 0, - Copyright_identification_bit: 0, - Frame_length: 0, - Adts_buffer_fullness: 0, - Number_of_raw_data_blocks_in_frame: 0, - }, - } + Variable_Header: ADTS_Variable_Header{ + copyright_identification_start: 0, + Copyright_identification_bit: 0, + Frame_length: 0, + Adts_buffer_fullness: 0, + Number_of_raw_data_blocks_in_frame: 0, + }, + } } func (frame *ADTS_Frame_Header) Decode(aac []byte) error { - _ = aac[6] - frame.Fix_Header.ID = aac[1] >> 3 - frame.Fix_Header.Layer = aac[1] >> 1 & 0x03 - frame.Fix_Header.Protection_absent = aac[1] & 0x01 - frame.Fix_Header.Profile = aac[2] >> 6 & 0x03 - frame.Fix_Header.Sampling_frequency_index = aac[2] >> 2 & 0x0F - frame.Fix_Header.Private_bit = aac[2] >> 1 & 0x01 - frame.Fix_Header.Channel_configuration = (aac[2] & 0x01 << 2) | (aac[3] >> 6) - frame.Fix_Header.Originalorcopy = aac[3] >> 5 & 0x01 - frame.Fix_Header.Home = aac[3] >> 4 & 0x01 - frame.Variable_Header.Copyright_identification_bit = aac[3] >> 3 & 0x01 - frame.Variable_Header.copyright_identification_start = aac[3] >> 2 & 0x01 - frame.Variable_Header.Frame_length = (uint16(aac[3]&0x03) << 11) | (uint16(aac[4]) << 3) | (uint16(aac[5]>>5) & 0x07) - frame.Variable_Header.Adts_buffer_fullness = (uint16(aac[5]&0x1F) << 6) | uint16(aac[6]>>2) - frame.Variable_Header.Number_of_raw_data_blocks_in_frame = aac[6] & 0x03 - return nil + _ = aac[6] + frame.Fix_Header.ID = aac[1] >> 3 + frame.Fix_Header.Layer = aac[1] >> 1 & 0x03 + frame.Fix_Header.Protection_absent = aac[1] & 0x01 + frame.Fix_Header.Profile = aac[2] >> 6 & 0x03 + frame.Fix_Header.Sampling_frequency_index = aac[2] >> 2 & 0x0F + frame.Fix_Header.Private_bit = aac[2] >> 1 & 0x01 + frame.Fix_Header.Channel_configuration = (aac[2] & 0x01 << 2) | (aac[3] >> 6) + frame.Fix_Header.Originalorcopy = aac[3] >> 5 & 0x01 + frame.Fix_Header.Home = aac[3] >> 4 & 0x01 + frame.Variable_Header.Copyright_identification_bit = aac[3] >> 3 & 0x01 + frame.Variable_Header.copyright_identification_start = aac[3] >> 2 & 0x01 + frame.Variable_Header.Frame_length = (uint16(aac[3]&0x03) << 11) | (uint16(aac[4]) << 3) | (uint16(aac[5]>>5) & 0x07) + frame.Variable_Header.Adts_buffer_fullness = (uint16(aac[5]&0x1F) << 6) | uint16(aac[6]>>2) + frame.Variable_Header.Number_of_raw_data_blocks_in_frame = aac[6] & 0x03 + return nil } func (frame *ADTS_Frame_Header) Encode() []byte { - var hdr []byte - if frame.Fix_Header.Protection_absent == 1 { - hdr = make([]byte, 7) - } else { - hdr = make([]byte, 9) - } - hdr[0] = 0xFF - hdr[1] = 0xF0 - hdr[1] = hdr[1] | (frame.Fix_Header.ID << 3) | (frame.Fix_Header.Layer << 1) | frame.Fix_Header.Protection_absent - hdr[2] = frame.Fix_Header.Profile<<6 | frame.Fix_Header.Sampling_frequency_index<<2 | frame.Fix_Header.Private_bit<<1 | frame.Fix_Header.Channel_configuration>>2 - hdr[3] = frame.Fix_Header.Channel_configuration<<6 | frame.Fix_Header.Originalorcopy<<5 | frame.Fix_Header.Home<<4 - hdr[3] = hdr[3] | frame.Variable_Header.copyright_identification_start<<3 | frame.Variable_Header.Copyright_identification_bit<<2 | byte(frame.Variable_Header.Frame_length<<11) - hdr[4] = byte(frame.Variable_Header.Frame_length >> 3) - hdr[5] = byte((frame.Variable_Header.Frame_length&0x07)<<5) | byte(frame.Variable_Header.Adts_buffer_fullness>>3) - hdr[6] = byte(frame.Variable_Header.Adts_buffer_fullness&0x3F<<2) | frame.Variable_Header.Number_of_raw_data_blocks_in_frame - return hdr + var hdr []byte + if frame.Fix_Header.Protection_absent == 1 { + hdr = make([]byte, 7) + } else { + hdr = make([]byte, 9) + } + hdr[0] = 0xFF + hdr[1] = 0xF0 + hdr[1] = hdr[1] | (frame.Fix_Header.ID << 3) | (frame.Fix_Header.Layer << 1) | frame.Fix_Header.Protection_absent + hdr[2] = frame.Fix_Header.Profile<<6 | frame.Fix_Header.Sampling_frequency_index<<2 | frame.Fix_Header.Private_bit<<1 | frame.Fix_Header.Channel_configuration>>2 + hdr[3] = frame.Fix_Header.Channel_configuration<<6 | frame.Fix_Header.Originalorcopy<<5 | frame.Fix_Header.Home<<4 + hdr[3] = hdr[3] | frame.Variable_Header.copyright_identification_start<<3 | frame.Variable_Header.Copyright_identification_bit<<2 | byte(frame.Variable_Header.Frame_length<<11) + hdr[4] = byte(frame.Variable_Header.Frame_length >> 3) + hdr[5] = byte((frame.Variable_Header.Frame_length&0x07)<<5) | byte(frame.Variable_Header.Adts_buffer_fullness>>3) + hdr[6] = byte(frame.Variable_Header.Adts_buffer_fullness&0x3F<<2) | frame.Variable_Header.Number_of_raw_data_blocks_in_frame + return hdr } func SampleToAACSampleIndex(sampling int) int { - for i, v := range AAC_Sampling_Idx { - if v == sampling { - return i - } - } - panic("not Found AAC Sample Index") + for i, v := range AAC_Sampling_Idx { + if v == sampling { + return i + } + } + panic("not Found AAC Sample Index") } func AACSampleIdxToSample(idx int) int { - return AAC_Sampling_Idx[idx] + return AAC_Sampling_Idx[idx] } // +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ @@ -185,71 +185,71 @@ func AACSampleIdxToSample(idx int) int { // +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ type AudioSpecificConfiguration struct { - Audio_object_type uint8 - Sample_freq_index uint8 - Channel_configuration uint8 - GA_framelength_flag uint8 - GA_depends_on_core_coder uint8 - GA_extension_flag uint8 + Audio_object_type uint8 + Sample_freq_index uint8 + Channel_configuration uint8 + GA_framelength_flag uint8 + GA_depends_on_core_coder uint8 + GA_extension_flag uint8 } func NewAudioSpecificConfiguration() *AudioSpecificConfiguration { - return &AudioSpecificConfiguration{ - Audio_object_type: 0, - Sample_freq_index: 0, - Channel_configuration: 0, - GA_framelength_flag: 0, - GA_depends_on_core_coder: 0, - GA_extension_flag: 0, - } + return &AudioSpecificConfiguration{ + Audio_object_type: 0, + Sample_freq_index: 0, + Channel_configuration: 0, + GA_framelength_flag: 0, + GA_depends_on_core_coder: 0, + GA_extension_flag: 0, + } } func (asc *AudioSpecificConfiguration) Encode() []byte { - buf := make([]byte, 2) - buf[0] = (asc.Audio_object_type & 0x1f << 3) | (asc.Sample_freq_index & 0x0F >> 1) - buf[1] = (asc.Sample_freq_index & 0x0F << 7) | (asc.Channel_configuration & 0x0F << 3) | (asc.GA_framelength_flag & 0x01 << 2) | (asc.GA_depends_on_core_coder & 0x01 << 1) | (asc.GA_extension_flag & 0x01) - return buf + buf := make([]byte, 2) + buf[0] = (asc.Audio_object_type & 0x1f << 3) | (asc.Sample_freq_index & 0x0F >> 1) + buf[1] = (asc.Sample_freq_index & 0x0F << 7) | (asc.Channel_configuration & 0x0F << 3) | (asc.GA_framelength_flag & 0x01 << 2) | (asc.GA_depends_on_core_coder & 0x01 << 1) | (asc.GA_extension_flag & 0x01) + return buf } func (asc *AudioSpecificConfiguration) Decode(buf []byte) error { - if len(buf) < 2 { - return errors.New("len of buf < 2 ") - } + if len(buf) < 2 { + return errors.New("len of buf < 2 ") + } - asc.Audio_object_type = buf[0] >> 3 - asc.Sample_freq_index = (buf[0] & 0x07 << 1) | (buf[1] >> 7) - asc.Channel_configuration = buf[1] >> 3 & 0x0F - asc.GA_framelength_flag = buf[1] >> 2 & 0x01 - asc.GA_depends_on_core_coder = buf[1] >> 1 & 0x01 - asc.GA_extension_flag = buf[1] & 0x01 - return nil + asc.Audio_object_type = buf[0] >> 3 + asc.Sample_freq_index = (buf[0] & 0x07 << 1) | (buf[1] >> 7) + asc.Channel_configuration = buf[1] >> 3 & 0x0F + asc.GA_framelength_flag = buf[1] >> 2 & 0x01 + asc.GA_depends_on_core_coder = buf[1] >> 1 & 0x01 + asc.GA_extension_flag = buf[1] & 0x01 + return nil } func ConvertADTSToASC(frame []byte) ([]byte, error) { - if len(frame) < 7 { - return nil, errors.New("len of frame < 7") - } + if len(frame) < 7 { + return nil, errors.New("len of frame < 7") + } - adts := NewAdtsFrameHeader() - adts.Decode(frame) - asc := NewAudioSpecificConfiguration() - asc.Audio_object_type = adts.Fix_Header.Profile + 1 - asc.Channel_configuration = adts.Fix_Header.Channel_configuration - asc.Sample_freq_index = adts.Fix_Header.Sampling_frequency_index - return asc.Encode(), nil + adts := NewAdtsFrameHeader() + adts.Decode(frame) + asc := NewAudioSpecificConfiguration() + asc.Audio_object_type = adts.Fix_Header.Profile + 1 + asc.Channel_configuration = adts.Fix_Header.Channel_configuration + asc.Sample_freq_index = adts.Fix_Header.Sampling_frequency_index + return asc.Encode(), nil } func ConvertASCToADTS(asc []byte, aacbytes int) []byte { - aac_asc := NewAudioSpecificConfiguration() - aac_asc.Decode(asc) - aac_adts := NewAdtsFrameHeader() - aac_adts.Fix_Header.Profile = aac_asc.Audio_object_type - 1 - aac_adts.Fix_Header.Channel_configuration = aac_asc.Channel_configuration - aac_adts.Fix_Header.Sampling_frequency_index = aac_asc.Sample_freq_index - aac_adts.Fix_Header.Protection_absent = 1 - aac_adts.Variable_Header.Adts_buffer_fullness = 0x3F - aac_adts.Variable_Header.Frame_length = uint16(aacbytes) - return aac_adts.Encode() + aac_asc := NewAudioSpecificConfiguration() + aac_asc.Decode(asc) + aac_adts := NewAdtsFrameHeader() + aac_adts.Fix_Header.Profile = aac_asc.Audio_object_type - 1 + aac_adts.Fix_Header.Channel_configuration = aac_asc.Channel_configuration + aac_adts.Fix_Header.Sampling_frequency_index = aac_asc.Sample_freq_index + aac_adts.Fix_Header.Protection_absent = 1 + aac_adts.Variable_Header.Adts_buffer_fullness = 0x3F + aac_adts.Variable_Header.Frame_length = uint16(aacbytes) + return aac_adts.Encode() } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/codec/bitstream.go b/trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/codec/bitstream.go index 2c2654bd9..6d719b01a 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/codec/bitstream.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/codec/bitstream.go @@ -1,358 +1,358 @@ package codec import ( - "encoding/binary" + "encoding/binary" ) var BitMask [8]byte = [8]byte{0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF} type BitStream struct { - bits []byte - bytesOffset int - bitsOffset int - bitsmark int - bytemark int + bits []byte + bytesOffset int + bitsOffset int + bitsmark int + bytemark int } func NewBitStream(buf []byte) *BitStream { - return &BitStream{ - bits: buf, - bytesOffset: 0, - bitsOffset: 0, - bitsmark: 0, - bytemark: 0, - } + return &BitStream{ + bits: buf, + bytesOffset: 0, + bitsOffset: 0, + bitsmark: 0, + bytemark: 0, + } } func (bs *BitStream) Uint8(n int) uint8 { - return uint8(bs.GetBits(n)) + return uint8(bs.GetBits(n)) } func (bs *BitStream) Uint16(n int) uint16 { - return uint16(bs.GetBits(n)) + return uint16(bs.GetBits(n)) } func (bs *BitStream) Uint32(n int) uint32 { - return uint32(bs.GetBits(n)) + return uint32(bs.GetBits(n)) } func (bs *BitStream) GetBytes(n int) []byte { - if bs.bytesOffset+n > len(bs.bits) { - panic("OUT OF RANGE") - } - if bs.bitsOffset != 0 { - panic("invaild operation") - } - data := make([]byte, n) - copy(data, bs.bits[bs.bytesOffset:bs.bytesOffset+n]) - bs.bytesOffset += n - return data + if bs.bytesOffset+n > len(bs.bits) { + panic("OUT OF RANGE") + } + if bs.bitsOffset != 0 { + panic("invaild operation") + } + data := make([]byte, n) + copy(data, bs.bits[bs.bytesOffset:bs.bytesOffset+n]) + bs.bytesOffset += n + return data } //n <= 64 func (bs *BitStream) GetBits(n int) uint64 { - if bs.bytesOffset >= len(bs.bits) { - panic("OUT OF RANGE") - } - var ret uint64 = 0 - if 8-bs.bitsOffset >= n { - ret = uint64((bs.bits[bs.bytesOffset] >> (8 - bs.bitsOffset - n)) & BitMask[n-1]) - bs.bitsOffset += n - if bs.bitsOffset == 8 { - bs.bytesOffset++ - bs.bitsOffset = 0 - } - } else { - ret = uint64(bs.bits[bs.bytesOffset] & BitMask[8-bs.bitsOffset-1]) - bs.bytesOffset++ - n -= 8 - bs.bitsOffset - bs.bitsOffset = 0 - for n > 0 { - if bs.bytesOffset >= len(bs.bits) { - panic("OUT OF RANGE") - } - if n >= 8 { - ret = ret<<8 | uint64(bs.bits[bs.bytesOffset]) - bs.bytesOffset++ - n -= 8 - } else { - ret = (ret << n) | uint64((bs.bits[bs.bytesOffset]>>(8-n))&BitMask[n-1]) - bs.bitsOffset = n - break - } - } - } - return ret + if bs.bytesOffset >= len(bs.bits) { + panic("OUT OF RANGE") + } + var ret uint64 = 0 + if 8-bs.bitsOffset >= n { + ret = uint64((bs.bits[bs.bytesOffset] >> (8 - bs.bitsOffset - n)) & BitMask[n-1]) + bs.bitsOffset += n + if bs.bitsOffset == 8 { + bs.bytesOffset++ + bs.bitsOffset = 0 + } + } else { + ret = uint64(bs.bits[bs.bytesOffset] & BitMask[8-bs.bitsOffset-1]) + bs.bytesOffset++ + n -= 8 - bs.bitsOffset + bs.bitsOffset = 0 + for n > 0 { + if bs.bytesOffset >= len(bs.bits) { + panic("OUT OF RANGE") + } + if n >= 8 { + ret = ret<<8 | uint64(bs.bits[bs.bytesOffset]) + bs.bytesOffset++ + n -= 8 + } else { + ret = (ret << n) | uint64((bs.bits[bs.bytesOffset]>>(8-n))&BitMask[n-1]) + bs.bitsOffset = n + break + } + } + } + return ret } func (bs *BitStream) GetBit() uint8 { - if bs.bytesOffset >= len(bs.bits) { - panic("OUT OF RANGE") - } - ret := bs.bits[bs.bytesOffset] >> (7 - bs.bitsOffset) & 0x01 - bs.bitsOffset++ - if bs.bitsOffset >= 8 { - bs.bytesOffset++ - bs.bitsOffset = 0 - } - return ret + if bs.bytesOffset >= len(bs.bits) { + panic("OUT OF RANGE") + } + ret := bs.bits[bs.bytesOffset] >> (7 - bs.bitsOffset) & 0x01 + bs.bitsOffset++ + if bs.bitsOffset >= 8 { + bs.bytesOffset++ + bs.bitsOffset = 0 + } + return ret } func (bs *BitStream) SkipBits(n int) { - bytecount := n / 8 - bitscount := n % 8 - bs.bytesOffset += bytecount - if bs.bitsOffset+bitscount < 8 { - bs.bitsOffset += bitscount - } else { - bs.bytesOffset += 1 - bs.bitsOffset += bitscount - 8 - } + bytecount := n / 8 + bitscount := n % 8 + bs.bytesOffset += bytecount + if bs.bitsOffset+bitscount < 8 { + bs.bitsOffset += bitscount + } else { + bs.bytesOffset += 1 + bs.bitsOffset += bitscount - 8 + } } func (bs *BitStream) Markdot() { - bs.bitsmark = bs.bitsOffset - bs.bytemark = bs.bytesOffset + bs.bitsmark = bs.bitsOffset + bs.bytemark = bs.bytesOffset } func (bs *BitStream) DistanceFromMarkDot() int { - bytecount := bs.bytesOffset - bs.bytemark - 1 - bitscount := bs.bitsOffset + (8 - bs.bitsmark) - return bytecount*8 + bitscount + bytecount := bs.bytesOffset - bs.bytemark - 1 + bitscount := bs.bitsOffset + (8 - bs.bitsmark) + return bytecount*8 + bitscount } func (bs *BitStream) RemainBytes() int { - if bs.bitsOffset > 0 { - return len(bs.bits) - bs.bytesOffset - 1 - } else { - return len(bs.bits) - bs.bytesOffset - } + if bs.bitsOffset > 0 { + return len(bs.bits) - bs.bytesOffset - 1 + } else { + return len(bs.bits) - bs.bytesOffset + } } func (bs *BitStream) RemainBits() int { - if bs.bitsOffset > 0 { - return bs.RemainBytes()*8 + 8 - bs.bitsOffset - } else { - return bs.RemainBytes() * 8 - } + if bs.bitsOffset > 0 { + return bs.RemainBytes()*8 + 8 - bs.bitsOffset + } else { + return bs.RemainBytes() * 8 + } } func (bs *BitStream) Bits() []byte { - return bs.bits + return bs.bits } func (bs *BitStream) RemainData() []byte { - return bs.bits[bs.bytesOffset:] + return bs.bits[bs.bytesOffset:] } //无符号哥伦布熵编码 func (bs *BitStream) ReadUE() uint64 { - leadingZeroBits := 0 - for bs.GetBit() == 0 { - leadingZeroBits++ - } - if leadingZeroBits == 0 { - return 0 - } - info := bs.GetBits(leadingZeroBits) - return uint64(1)<= 8 { - bs.bytesOffset-- - least -= 8 - } - if least > 0 { - bs.bytesOffset-- - bs.bitsOffset = 8 - least - } - } + if n-bs.bitsOffset <= 0 { + bs.bitsOffset -= n + } else { + least := n - bs.bitsOffset + for least >= 8 { + bs.bytesOffset-- + least -= 8 + } + if least > 0 { + bs.bytesOffset-- + bs.bitsOffset = 8 - least + } + } } func (bs *BitStream) NextBits(n int) uint64 { - r := bs.GetBits(n) - bs.UnRead(n) - return r + r := bs.GetBits(n) + bs.UnRead(n) + return r } func (bs *BitStream) EOS() bool { - return bs.bytesOffset == len(bs.bits) && bs.bitsOffset == 0 + return bs.bytesOffset == len(bs.bits) && bs.bitsOffset == 0 } type BitStreamWriter struct { - bits []byte - byteoffset int - bitsoffset int - bitsmark int - bytemark int + bits []byte + byteoffset int + bitsoffset int + bitsmark int + bytemark int } func NewBitStreamWriter(n int) *BitStreamWriter { - return &BitStreamWriter{ - bits: make([]byte, n), - byteoffset: 0, - bitsoffset: 0, - bitsmark: 0, - bytemark: 0, - } + return &BitStreamWriter{ + bits: make([]byte, n), + byteoffset: 0, + bitsoffset: 0, + bitsmark: 0, + bytemark: 0, + } } func (bsw *BitStreamWriter) expandSpace(n int) { - if (len(bsw.bits)-bsw.byteoffset-1)*8+8-bsw.bitsoffset < n { - newlen := 0 - if len(bsw.bits)*8 < n { - newlen = len(bsw.bits) + n/8 + 1 - } else { - newlen = len(bsw.bits) * 2 - } - tmp := make([]byte, newlen) - copy(tmp, bsw.bits) - bsw.bits = tmp - } + if (len(bsw.bits)-bsw.byteoffset-1)*8+8-bsw.bitsoffset < n { + newlen := 0 + if len(bsw.bits)*8 < n { + newlen = len(bsw.bits) + n/8 + 1 + } else { + newlen = len(bsw.bits) * 2 + } + tmp := make([]byte, newlen) + copy(tmp, bsw.bits) + bsw.bits = tmp + } } func (bsw *BitStreamWriter) ByteOffset() int { - return bsw.byteoffset + return bsw.byteoffset } func (bsw *BitStreamWriter) BitOffset() int { - return bsw.bitsoffset + return bsw.bitsoffset } func (bsw *BitStreamWriter) Markdot() { - bsw.bitsmark = bsw.bitsoffset - bsw.bytemark = bsw.byteoffset + bsw.bitsmark = bsw.bitsoffset + bsw.bytemark = bsw.byteoffset } func (bsw *BitStreamWriter) DistanceFromMarkDot() int { - bytecount := bsw.byteoffset - bsw.bytemark - 1 - bitscount := bsw.bitsoffset + (8 - bsw.bitsmark) - return bytecount*8 + bitscount + bytecount := bsw.byteoffset - bsw.bytemark - 1 + bitscount := bsw.bitsoffset + (8 - bsw.bitsmark) + return bytecount*8 + bitscount } func (bsw *BitStreamWriter) PutByte(v byte) { - bsw.expandSpace(8) - if bsw.bitsoffset == 0 { - bsw.bits[bsw.byteoffset] = v - bsw.byteoffset++ - } else { - bsw.bits[bsw.byteoffset] |= v >> byte(bsw.bitsoffset) - bsw.byteoffset++ - bsw.bits[bsw.byteoffset] = v & BitMask[bsw.bitsoffset-1] - } + bsw.expandSpace(8) + if bsw.bitsoffset == 0 { + bsw.bits[bsw.byteoffset] = v + bsw.byteoffset++ + } else { + bsw.bits[bsw.byteoffset] |= v >> byte(bsw.bitsoffset) + bsw.byteoffset++ + bsw.bits[bsw.byteoffset] = v & BitMask[bsw.bitsoffset-1] + } } func (bsw *BitStreamWriter) PutBytes(v []byte) { - if bsw.bitsoffset != 0 { - panic("bsw.bitsoffset > 0") - } - bsw.expandSpace(8 * len(v)) - copy(bsw.bits[bsw.byteoffset:], v) - bsw.byteoffset += len(v) + if bsw.bitsoffset != 0 { + panic("bsw.bitsoffset > 0") + } + bsw.expandSpace(8 * len(v)) + copy(bsw.bits[bsw.byteoffset:], v) + bsw.byteoffset += len(v) } func (bsw *BitStreamWriter) PutRepetValue(v byte, n int) { - if bsw.bitsoffset != 0 { - panic("bsw.bitsoffset > 0") - } - bsw.expandSpace(8 * n) - for i := 0; i < n; i++ { - bsw.bits[bsw.byteoffset] = v - bsw.byteoffset++ - } + if bsw.bitsoffset != 0 { + panic("bsw.bitsoffset > 0") + } + bsw.expandSpace(8 * n) + for i := 0; i < n; i++ { + bsw.bits[bsw.byteoffset] = v + bsw.byteoffset++ + } } func (bsw *BitStreamWriter) PutUint8(v uint8, n int) { - bsw.PutUint64(uint64(v), n) + bsw.PutUint64(uint64(v), n) } func (bsw *BitStreamWriter) PutUint16(v uint16, n int) { - bsw.PutUint64(uint64(v), n) + bsw.PutUint64(uint64(v), n) } func (bsw *BitStreamWriter) PutUint32(v uint32, n int) { - bsw.PutUint64(uint64(v), n) + bsw.PutUint64(uint64(v), n) } func (bsw *BitStreamWriter) PutUint64(v uint64, n int) { - bsw.expandSpace(n) - if 8-bsw.bitsoffset >= n { - bsw.bits[bsw.byteoffset] |= uint8(v) & BitMask[n-1] << (8 - bsw.bitsoffset - n) - bsw.bitsoffset += n - if bsw.bitsoffset == 8 { - bsw.bitsoffset = 0 - bsw.byteoffset++ - } - } else { - bsw.bits[bsw.byteoffset] |= uint8(v>>(n-int(8-bsw.bitsoffset))) & BitMask[8-bsw.bitsoffset-1] - bsw.byteoffset++ - n -= 8 - bsw.bitsoffset - for n-8 >= 0 { - bsw.bits[bsw.byteoffset] = uint8(v>>(n-8)) & 0xFF - bsw.byteoffset++ - n -= 8 - } - bsw.bitsoffset = n - if n > 0 { - bsw.bits[bsw.byteoffset] |= (uint8(v) & BitMask[n-1]) << (8 - n) - } - } + bsw.expandSpace(n) + if 8-bsw.bitsoffset >= n { + bsw.bits[bsw.byteoffset] |= uint8(v) & BitMask[n-1] << (8 - bsw.bitsoffset - n) + bsw.bitsoffset += n + if bsw.bitsoffset == 8 { + bsw.bitsoffset = 0 + bsw.byteoffset++ + } + } else { + bsw.bits[bsw.byteoffset] |= uint8(v>>(n-int(8-bsw.bitsoffset))) & BitMask[8-bsw.bitsoffset-1] + bsw.byteoffset++ + n -= 8 - bsw.bitsoffset + for n-8 >= 0 { + bsw.bits[bsw.byteoffset] = uint8(v>>(n-8)) & 0xFF + bsw.byteoffset++ + n -= 8 + } + bsw.bitsoffset = n + if n > 0 { + bsw.bits[bsw.byteoffset] |= (uint8(v) & BitMask[n-1]) << (8 - n) + } + } } func (bsw *BitStreamWriter) SetByte(v byte, where int) { - bsw.bits[where] = v + bsw.bits[where] = v } func (bsw *BitStreamWriter) SetUint16(v uint16, where int) { - binary.BigEndian.PutUint16(bsw.bits[where:where+2], v) + binary.BigEndian.PutUint16(bsw.bits[where:where+2], v) } func (bsw *BitStreamWriter) Bits() []byte { - if bsw.byteoffset == len(bsw.bits) { - return bsw.bits - } - if bsw.bitsoffset > 0 { - return bsw.bits[0 : bsw.byteoffset+1] - } else { - return bsw.bits[0:bsw.byteoffset] - } + if bsw.byteoffset == len(bsw.bits) { + return bsw.bits + } + if bsw.bitsoffset > 0 { + return bsw.bits[0 : bsw.byteoffset+1] + } else { + return bsw.bits[0:bsw.byteoffset] + } } //用v 填充剩余字节 func (bsw *BitStreamWriter) FillRemainData(v byte) { - for i := bsw.byteoffset; i < len(bsw.bits); i++ { - bsw.bits[i] = v - } - bsw.byteoffset = len(bsw.bits) - bsw.bitsoffset = 0 + for i := bsw.byteoffset; i < len(bsw.bits); i++ { + bsw.bits[i] = v + } + bsw.byteoffset = len(bsw.bits) + bsw.bitsoffset = 0 } func (bsw *BitStreamWriter) Reset() { - for i := 0; i < len(bsw.bits); i++ { - bsw.bits[i] = 0 - } - bsw.bitsmark = 0 - bsw.bytemark = 0 - bsw.bitsoffset = 0 - bsw.byteoffset = 0 + for i := 0; i < len(bsw.bits); i++ { + bsw.bits[i] = 0 + } + bsw.bitsmark = 0 + bsw.bytemark = 0 + bsw.bitsoffset = 0 + bsw.byteoffset = 0 } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/codec/codec.go b/trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/codec/codec.go index 5dc7507f5..8f577c886 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/codec/codec.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/codec/codec.go @@ -3,62 +3,62 @@ package codec type CodecID int const ( - CODECID_VIDEO_H264 CodecID = iota - CODECID_VIDEO_H265 - CODECID_VIDEO_VP8 + CODECID_VIDEO_H264 CodecID = iota + CODECID_VIDEO_H265 + CODECID_VIDEO_VP8 - CODECID_AUDIO_AAC CodecID = iota + 98 - CODECID_AUDIO_G711A - CODECID_AUDIO_G711U - CODECID_AUDIO_OPUS + CODECID_AUDIO_AAC CodecID = iota + 98 + CODECID_AUDIO_G711A + CODECID_AUDIO_G711U + CODECID_AUDIO_OPUS - CODECID_UNRECOGNIZED = 999 + CODECID_UNRECOGNIZED = 999 ) type H264_NAL_TYPE int const ( - H264_NAL_RESERVED H264_NAL_TYPE = iota - H264_NAL_P_SLICE - H264_NAL_SLICE_A - H264_NAL_SLICE_B - H264_NAL_SLICE_C - H264_NAL_I_SLICE - H264_NAL_SEI - H264_NAL_SPS - H264_NAL_PPS - H264_NAL_AUD + H264_NAL_RESERVED H264_NAL_TYPE = iota + H264_NAL_P_SLICE + H264_NAL_SLICE_A + H264_NAL_SLICE_B + H264_NAL_SLICE_C + H264_NAL_I_SLICE + H264_NAL_SEI + H264_NAL_SPS + H264_NAL_PPS + H264_NAL_AUD ) type H265_NAL_TYPE int const ( - H265_NAL_Slice_TRAIL_N H265_NAL_TYPE = iota - H265_NAL_LICE_TRAIL_R - H265_NAL_SLICE_TSA_N - H265_NAL_SLICE_TSA_R - H265_NAL_SLICE_STSA_N - H265_NAL_SLICE_STSA_R - H265_NAL_SLICE_RADL_N - H265_NAL_SLICE_RADL_R - H265_NAL_SLICE_RASL_N - H265_NAL_SLICE_RASL_R + H265_NAL_Slice_TRAIL_N H265_NAL_TYPE = iota + H265_NAL_LICE_TRAIL_R + H265_NAL_SLICE_TSA_N + H265_NAL_SLICE_TSA_R + H265_NAL_SLICE_STSA_N + H265_NAL_SLICE_STSA_R + H265_NAL_SLICE_RADL_N + H265_NAL_SLICE_RADL_R + H265_NAL_SLICE_RASL_N + H265_NAL_SLICE_RASL_R - //IDR - H265_NAL_SLICE_BLA_W_LP H265_NAL_TYPE = iota + 6 - H265_NAL_SLICE_BLA_W_RADL - H265_NAL_SLICE_BLA_N_LP - H265_NAL_SLICE_IDR_W_RADL - H265_NAL_SLICE_IDR_N_LP - H265_NAL_SLICE_CRA + //IDR + H265_NAL_SLICE_BLA_W_LP H265_NAL_TYPE = iota + 6 + H265_NAL_SLICE_BLA_W_RADL + H265_NAL_SLICE_BLA_N_LP + H265_NAL_SLICE_IDR_W_RADL + H265_NAL_SLICE_IDR_N_LP + H265_NAL_SLICE_CRA - //vps pps sps - H265_NAL_VPS H265_NAL_TYPE = iota + 16 - H265_NAL_SPS - H265_NAL_PPS - H265_NAL_AUD + //vps pps sps + H265_NAL_VPS H265_NAL_TYPE = iota + 16 + H265_NAL_SPS + H265_NAL_PPS + H265_NAL_AUD - //SEI - H265_NAL_SEI H265_NAL_TYPE = iota + 19 - H265_NAL_SEI_SUFFIX + //SEI + H265_NAL_SEI H265_NAL_TYPE = iota + 19 + H265_NAL_SEI_SUFFIX ) diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/codec/h264.go b/trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/codec/h264.go index 941cf74b6..36fd31a0b 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/codec/h264.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/codec/h264.go @@ -9,241 +9,241 @@ import "encoding/binary" // } type H264NaluHdr struct { - Forbidden_zero_bit uint8 - Nal_ref_idc uint8 - Nal_unit_type uint8 + Forbidden_zero_bit uint8 + Nal_ref_idc uint8 + Nal_unit_type uint8 } func (hdr *H264NaluHdr) Decode(bs *BitStream) { - hdr.Forbidden_zero_bit = bs.GetBit() - hdr.Nal_ref_idc = bs.Uint8(2) - hdr.Nal_unit_type = bs.Uint8(5) + hdr.Forbidden_zero_bit = bs.GetBit() + hdr.Nal_ref_idc = bs.Uint8(2) + hdr.Nal_unit_type = bs.Uint8(5) } type SliceHeader struct { - First_mb_in_slice uint64 - Slice_type uint64 - Pic_parameter_set_id uint64 - Frame_num uint64 + First_mb_in_slice uint64 + Slice_type uint64 + Pic_parameter_set_id uint64 + Frame_num uint64 } //调用方根据sps中的log2_max_frame_num_minus4的值来解析Frame_num func (sh *SliceHeader) Decode(bs *BitStream) { - sh.First_mb_in_slice = bs.ReadUE() - sh.Slice_type = bs.ReadUE() - sh.Pic_parameter_set_id = bs.ReadUE() + sh.First_mb_in_slice = bs.ReadUE() + sh.Slice_type = bs.ReadUE() + sh.Pic_parameter_set_id = bs.ReadUE() } type SPS struct { - Profile_idc uint8 - Constraint_set0_flag uint8 - Constraint_set1_flag uint8 - Constraint_set2_flag uint8 - Constraint_set3_flag uint8 - Constraint_set4_flag uint8 - Constraint_set5_flag uint8 - Reserved_zero_2bits uint8 - Level_idc uint8 - Seq_parameter_set_id uint64 - Chroma_format_idc uint64 - Separate_colour_plane_flag uint8 - Bit_depth_luma_minus8 uint64 - Bit_depth_chroma_minus8 uint64 - Log2_max_frame_num_minus4 uint64 - Pic_order_cnt_type uint64 - Max_num_ref_frames uint64 - Gaps_in_frame_num_value_allowed_flag uint8 - Pic_width_in_mbs_minus1 uint64 - Pic_height_in_map_units_minus1 uint64 - Frame_mbs_only_flag uint8 - Direct_8x8_inference_flag uint8 - Frame_cropping_flag uint8 - Frame_crop_left_offset uint64 - Frame_crop_right_offset uint64 - Frame_crop_top_offset uint64 - Frame_crop_bottom_offset uint64 - Vui_parameters_present_flag uint8 + Profile_idc uint8 + Constraint_set0_flag uint8 + Constraint_set1_flag uint8 + Constraint_set2_flag uint8 + Constraint_set3_flag uint8 + Constraint_set4_flag uint8 + Constraint_set5_flag uint8 + Reserved_zero_2bits uint8 + Level_idc uint8 + Seq_parameter_set_id uint64 + Chroma_format_idc uint64 + Separate_colour_plane_flag uint8 + Bit_depth_luma_minus8 uint64 + Bit_depth_chroma_minus8 uint64 + Log2_max_frame_num_minus4 uint64 + Pic_order_cnt_type uint64 + Max_num_ref_frames uint64 + Gaps_in_frame_num_value_allowed_flag uint8 + Pic_width_in_mbs_minus1 uint64 + Pic_height_in_map_units_minus1 uint64 + Frame_mbs_only_flag uint8 + Direct_8x8_inference_flag uint8 + Frame_cropping_flag uint8 + Frame_crop_left_offset uint64 + Frame_crop_right_offset uint64 + Frame_crop_top_offset uint64 + Frame_crop_bottom_offset uint64 + Vui_parameters_present_flag uint8 } func (sps *SPS) Decode(bs *BitStream) { - sps.Profile_idc = bs.Uint8(8) - sps.Constraint_set0_flag = bs.GetBit() - sps.Constraint_set1_flag = bs.GetBit() - sps.Constraint_set2_flag = bs.GetBit() - sps.Constraint_set3_flag = bs.GetBit() - sps.Constraint_set4_flag = bs.GetBit() - sps.Constraint_set5_flag = bs.GetBit() - sps.Reserved_zero_2bits = bs.Uint8(2) - sps.Level_idc = bs.Uint8(8) - sps.Seq_parameter_set_id = bs.ReadUE() - if sps.Profile_idc == 100 || sps.Profile_idc == 110 || - sps.Profile_idc == 122 || sps.Profile_idc == 244 || - sps.Profile_idc == 44 || sps.Profile_idc == 83 || - sps.Profile_idc == 86 || sps.Profile_idc == 118 || sps.Profile_idc == 128 { - sps.Chroma_format_idc = bs.ReadUE() - if sps.Chroma_format_idc == 3 { - sps.Separate_colour_plane_flag = bs.Uint8(1) //separate_colour_plane_flag - } - sps.Bit_depth_luma_minus8 = bs.ReadUE() //bit_depth_luma_minus8 - sps.Bit_depth_chroma_minus8 = bs.ReadUE() //bit_depth_chroma_minus8 - bs.SkipBits(1) //qpprime_y_zero_transform_bypass_flag - seq_scaling_matrix_present_flag := bs.GetBit() - if seq_scaling_matrix_present_flag == 1 { - //seq_scaling_list_present_flag[i] - if sps.Chroma_format_idc == 3 { - bs.SkipBits(12) - } else { - bs.SkipBits(8) - } - } - } - sps.Log2_max_frame_num_minus4 = bs.ReadUE() - sps.Pic_order_cnt_type = bs.ReadUE() - if sps.Pic_order_cnt_type == 0 { - bs.ReadUE() // log2_max_pic_order_cnt_lsb_minus4 - } else if sps.Pic_order_cnt_type == 1 { - bs.SkipBits(1) //delta_pic_order_always_zero_flag - bs.ReadSE() //offset_for_non_ref_pic - bs.ReadSE() //offset_for_top_to_bottom_field - num_ref_frames_in_pic_order_cnt_cycle := bs.ReadUE() - for i := 0; i < int(num_ref_frames_in_pic_order_cnt_cycle); i++ { - bs.ReadSE() //offset_for_ref_frame - } - } - sps.Max_num_ref_frames = bs.ReadUE() - sps.Gaps_in_frame_num_value_allowed_flag = bs.GetBit() - sps.Pic_width_in_mbs_minus1 = bs.ReadUE() - sps.Pic_height_in_map_units_minus1 = bs.ReadUE() - sps.Frame_mbs_only_flag = bs.GetBit() - if sps.Frame_mbs_only_flag == 0 { - bs.SkipBits(1) // mb_adaptive_frame_field_flag - } - sps.Direct_8x8_inference_flag = bs.GetBit() - sps.Frame_cropping_flag = bs.GetBit() - if sps.Frame_cropping_flag == 1 { - sps.Frame_crop_left_offset = bs.ReadUE() //frame_crop_left_offset - sps.Frame_crop_right_offset = bs.ReadUE() //frame_crop_right_offset - sps.Frame_crop_top_offset = bs.ReadUE() //frame_crop_top_offset - sps.Frame_crop_bottom_offset = bs.ReadUE() //frame_crop_bottom_offset - } - sps.Vui_parameters_present_flag = bs.GetBit() + sps.Profile_idc = bs.Uint8(8) + sps.Constraint_set0_flag = bs.GetBit() + sps.Constraint_set1_flag = bs.GetBit() + sps.Constraint_set2_flag = bs.GetBit() + sps.Constraint_set3_flag = bs.GetBit() + sps.Constraint_set4_flag = bs.GetBit() + sps.Constraint_set5_flag = bs.GetBit() + sps.Reserved_zero_2bits = bs.Uint8(2) + sps.Level_idc = bs.Uint8(8) + sps.Seq_parameter_set_id = bs.ReadUE() + if sps.Profile_idc == 100 || sps.Profile_idc == 110 || + sps.Profile_idc == 122 || sps.Profile_idc == 244 || + sps.Profile_idc == 44 || sps.Profile_idc == 83 || + sps.Profile_idc == 86 || sps.Profile_idc == 118 || sps.Profile_idc == 128 { + sps.Chroma_format_idc = bs.ReadUE() + if sps.Chroma_format_idc == 3 { + sps.Separate_colour_plane_flag = bs.Uint8(1) //separate_colour_plane_flag + } + sps.Bit_depth_luma_minus8 = bs.ReadUE() //bit_depth_luma_minus8 + sps.Bit_depth_chroma_minus8 = bs.ReadUE() //bit_depth_chroma_minus8 + bs.SkipBits(1) //qpprime_y_zero_transform_bypass_flag + seq_scaling_matrix_present_flag := bs.GetBit() + if seq_scaling_matrix_present_flag == 1 { + //seq_scaling_list_present_flag[i] + if sps.Chroma_format_idc == 3 { + bs.SkipBits(12) + } else { + bs.SkipBits(8) + } + } + } + sps.Log2_max_frame_num_minus4 = bs.ReadUE() + sps.Pic_order_cnt_type = bs.ReadUE() + if sps.Pic_order_cnt_type == 0 { + bs.ReadUE() // log2_max_pic_order_cnt_lsb_minus4 + } else if sps.Pic_order_cnt_type == 1 { + bs.SkipBits(1) //delta_pic_order_always_zero_flag + bs.ReadSE() //offset_for_non_ref_pic + bs.ReadSE() //offset_for_top_to_bottom_field + num_ref_frames_in_pic_order_cnt_cycle := bs.ReadUE() + for i := 0; i < int(num_ref_frames_in_pic_order_cnt_cycle); i++ { + bs.ReadSE() //offset_for_ref_frame + } + } + sps.Max_num_ref_frames = bs.ReadUE() + sps.Gaps_in_frame_num_value_allowed_flag = bs.GetBit() + sps.Pic_width_in_mbs_minus1 = bs.ReadUE() + sps.Pic_height_in_map_units_minus1 = bs.ReadUE() + sps.Frame_mbs_only_flag = bs.GetBit() + if sps.Frame_mbs_only_flag == 0 { + bs.SkipBits(1) // mb_adaptive_frame_field_flag + } + sps.Direct_8x8_inference_flag = bs.GetBit() + sps.Frame_cropping_flag = bs.GetBit() + if sps.Frame_cropping_flag == 1 { + sps.Frame_crop_left_offset = bs.ReadUE() //frame_crop_left_offset + sps.Frame_crop_right_offset = bs.ReadUE() //frame_crop_right_offset + sps.Frame_crop_top_offset = bs.ReadUE() //frame_crop_top_offset + sps.Frame_crop_bottom_offset = bs.ReadUE() //frame_crop_bottom_offset + } + sps.Vui_parameters_present_flag = bs.GetBit() } type PPS struct { - Pic_parameter_set_id uint64 - Seq_parameter_set_id uint64 - Entropy_coding_mode_flag uint8 - Bottom_field_pic_order_in_frame_present_flag uint8 - Num_slice_groups_minus1 uint64 + Pic_parameter_set_id uint64 + Seq_parameter_set_id uint64 + Entropy_coding_mode_flag uint8 + Bottom_field_pic_order_in_frame_present_flag uint8 + Num_slice_groups_minus1 uint64 } func (pps *PPS) Decode(bs *BitStream) { - pps.Pic_parameter_set_id = bs.ReadUE() - pps.Seq_parameter_set_id = bs.ReadUE() - pps.Entropy_coding_mode_flag = bs.GetBit() - pps.Bottom_field_pic_order_in_frame_present_flag = bs.GetBit() - pps.Num_slice_groups_minus1 = bs.ReadUE() + pps.Pic_parameter_set_id = bs.ReadUE() + pps.Seq_parameter_set_id = bs.ReadUE() + pps.Entropy_coding_mode_flag = bs.GetBit() + pps.Bottom_field_pic_order_in_frame_present_flag = bs.GetBit() + pps.Num_slice_groups_minus1 = bs.ReadUE() } type SEIReaderWriter interface { - Read(size uint16, bs *BitStream) - Write(bsw *BitStreamWriter) + Read(size uint16, bs *BitStream) + Write(bsw *BitStreamWriter) } type UserDataUnregistered struct { - UUID []byte - UserData []byte + UUID []byte + UserData []byte } func (udu *UserDataUnregistered) Read(size uint16, bs *BitStream) { - udu.UUID = bs.GetBytes(16) - udu.UserData = bs.GetBytes(int(size - 16)) + udu.UUID = bs.GetBytes(16) + udu.UserData = bs.GetBytes(int(size - 16)) } func (udu *UserDataUnregistered) Write(bsw *BitStreamWriter) { - bsw.PutBytes(udu.UUID) - bsw.PutBytes(udu.UserData) + bsw.PutBytes(udu.UUID) + bsw.PutBytes(udu.UserData) } type SEI struct { - PayloadType uint16 - PayloadSize uint16 - Sei_payload SEIReaderWriter + PayloadType uint16 + PayloadSize uint16 + Sei_payload SEIReaderWriter } func (sei *SEI) Decode(bs *BitStream) { - for bs.NextBits(8) == 0xFF { - sei.PayloadType += 255 - } - sei.PayloadType += uint16(bs.Uint8(8)) - for bs.NextBits(8) == 0xFF { - sei.PayloadSize += 255 - } - sei.PayloadSize += uint16(bs.Uint8(8)) - if sei.PayloadType == 5 { - sei.Sei_payload = new(UserDataUnregistered) - sei.Sei_payload.Read(sei.PayloadSize, bs) - } + for bs.NextBits(8) == 0xFF { + sei.PayloadType += 255 + } + sei.PayloadType += uint16(bs.Uint8(8)) + for bs.NextBits(8) == 0xFF { + sei.PayloadSize += 255 + } + sei.PayloadSize += uint16(bs.Uint8(8)) + if sei.PayloadType == 5 { + sei.Sei_payload = new(UserDataUnregistered) + sei.Sei_payload.Read(sei.PayloadSize, bs) + } } func (sei *SEI) Encode(bsw *BitStreamWriter) []byte { - payloadType := sei.PayloadType - payloadSize := sei.PayloadSize - for payloadType >= 0xFF { - bsw.PutByte(0xFF) - payloadType -= 255 - } - bsw.PutByte(uint8(payloadType)) - for payloadSize >= 0xFF { - bsw.PutByte(0xFF) - payloadSize -= 255 - } - bsw.PutByte(uint8(payloadSize)) - sei.Sei_payload.Write(bsw) - return bsw.Bits() + payloadType := sei.PayloadType + payloadSize := sei.PayloadSize + for payloadType >= 0xFF { + bsw.PutByte(0xFF) + payloadType -= 255 + } + bsw.PutByte(uint8(payloadType)) + for payloadSize >= 0xFF { + bsw.PutByte(0xFF) + payloadSize -= 255 + } + bsw.PutByte(uint8(payloadSize)) + sei.Sei_payload.Write(bsw) + return bsw.Bits() } func GetSPSIdWithStartCode(sps []byte) uint64 { - start, sc := FindStartCode(sps, 0) - return GetSPSId(sps[start+int(sc):]) + start, sc := FindStartCode(sps, 0) + return GetSPSId(sps[start+int(sc):]) } func GetSPSId(sps []byte) uint64 { - sps = sps[1:] - bs := NewBitStream(sps) - bs.SkipBits(24) - return bs.ReadUE() + sps = sps[1:] + bs := NewBitStream(sps) + bs.SkipBits(24) + return bs.ReadUE() } func GetPPSIdWithStartCode(pps []byte) uint64 { - start, sc := FindStartCode(pps, 0) - return GetPPSId(pps[start+int(sc):]) + start, sc := FindStartCode(pps, 0) + return GetPPSId(pps[start+int(sc):]) } func GetPPSId(pps []byte) uint64 { - pps = pps[1:] - bs := NewBitStream(pps) - return bs.ReadUE() + pps = pps[1:] + bs := NewBitStream(pps) + return bs.ReadUE() } //https://stackoverflow.com/questions/12018535/get-the-width-height-of-the-video-from-h-264-nalu //int Width = ((pic_width_in_mbs_minus1 +1)*16) - frame_crop_right_offset *2 - frame_crop_left_offset *2; //int Height = ((2 - frame_mbs_only_flag)* (pic_height_in_map_units_minus1 +1) * 16) - (frame_crop_bottom_offset* 2) - (frame_crop_top_offset* 2); func GetH264Resolution(sps []byte) (width uint32, height uint32) { - start, sc := FindStartCode(sps, 0) - bs := NewBitStream(sps[start+int(sc)+1:]) - var s SPS - s.Decode(bs) + start, sc := FindStartCode(sps, 0) + bs := NewBitStream(sps[start+int(sc)+1:]) + var s SPS + s.Decode(bs) - widthInSample := (uint32(s.Pic_width_in_mbs_minus1) + 1) * 16 - widthCrop := uint32(s.Frame_crop_left_offset)*2 - uint32(s.Frame_crop_right_offset)*2 - width = widthInSample - widthCrop + widthInSample := (uint32(s.Pic_width_in_mbs_minus1) + 1) * 16 + widthCrop := uint32(s.Frame_crop_left_offset)*2 - uint32(s.Frame_crop_right_offset)*2 + width = widthInSample - widthCrop - heightInSample := ((2 - uint32(s.Frame_mbs_only_flag)) * (uint32(s.Pic_height_in_map_units_minus1) + 1) * 16) - heightCrop := uint32(s.Frame_crop_bottom_offset)*2 - uint32(s.Frame_crop_top_offset)*2 - height = heightInSample - heightCrop + heightInSample := ((2 - uint32(s.Frame_mbs_only_flag)) * (uint32(s.Pic_height_in_map_units_minus1) + 1) * 16) + heightCrop := uint32(s.Frame_crop_bottom_offset)*2 - uint32(s.Frame_crop_top_offset)*2 + height = heightInSample - heightCrop - return + return } // aligned(8) class AVCDecoderConfigurationRecord { @@ -302,95 +302,95 @@ func GetH264Resolution(sps []byte) (width uint32, height uint32) { // variable PPS NALU data func CreateH264AVCCExtradata(spss [][]byte, ppss [][]byte) []byte { - extradata := make([]byte, 6, 256) - for i, sps := range spss { - start, sc := FindStartCode(sps, 0) - spss[i] = sps[start+int(sc):] - } + extradata := make([]byte, 6, 256) + for i, sps := range spss { + start, sc := FindStartCode(sps, 0) + spss[i] = sps[start+int(sc):] + } - for i, pps := range ppss { - start, sc := FindStartCode(pps, 0) - ppss[i] = pps[start+int(sc):] - } + for i, pps := range ppss { + start, sc := FindStartCode(pps, 0) + ppss[i] = pps[start+int(sc):] + } - extradata[0] = 0x01 - extradata[1] = spss[0][1] - extradata[2] = spss[0][2] - extradata[3] = spss[0][3] - extradata[4] = 0xFF - extradata[5] = 0xE0 | uint8(len(spss)) - for _, sps := range spss { - spssize := make([]byte, 2) - binary.BigEndian.PutUint16(spssize, uint16(len(sps))) - extradata = append(extradata, spssize...) - extradata = append(extradata, sps...) - } - extradata = append(extradata, uint8(len(ppss))) - for _, pps := range ppss { - ppssize := make([]byte, 2) - binary.BigEndian.PutUint16(ppssize, uint16(len(pps))) - extradata = append(extradata, ppssize...) - extradata = append(extradata, pps...) - } - var h264sps SPS - h264sps.Decode(NewBitStream(spss[0][1:])) - if h264sps.Profile_idc == 100 || - h264sps.Profile_idc == 110 || - h264sps.Profile_idc == 122 || - h264sps.Profile_idc == 144 { - tmp := make([]byte, 4) - tmp[0] = 0xFC | uint8(h264sps.Chroma_format_idc&0x03) - tmp[1] = 0xF8 | uint8(h264sps.Bit_depth_luma_minus8&0x07) - tmp[2] = 0xF8 | uint8(h264sps.Bit_depth_chroma_minus8&0x07) - tmp[3] = 0 - extradata = append(extradata, tmp...) - } + extradata[0] = 0x01 + extradata[1] = spss[0][1] + extradata[2] = spss[0][2] + extradata[3] = spss[0][3] + extradata[4] = 0xFF + extradata[5] = 0xE0 | uint8(len(spss)) + for _, sps := range spss { + spssize := make([]byte, 2) + binary.BigEndian.PutUint16(spssize, uint16(len(sps))) + extradata = append(extradata, spssize...) + extradata = append(extradata, sps...) + } + extradata = append(extradata, uint8(len(ppss))) + for _, pps := range ppss { + ppssize := make([]byte, 2) + binary.BigEndian.PutUint16(ppssize, uint16(len(pps))) + extradata = append(extradata, ppssize...) + extradata = append(extradata, pps...) + } + var h264sps SPS + h264sps.Decode(NewBitStream(spss[0][1:])) + if h264sps.Profile_idc == 100 || + h264sps.Profile_idc == 110 || + h264sps.Profile_idc == 122 || + h264sps.Profile_idc == 144 { + tmp := make([]byte, 4) + tmp[0] = 0xFC | uint8(h264sps.Chroma_format_idc&0x03) + tmp[1] = 0xF8 | uint8(h264sps.Bit_depth_luma_minus8&0x07) + tmp[2] = 0xF8 | uint8(h264sps.Bit_depth_chroma_minus8&0x07) + tmp[3] = 0 + extradata = append(extradata, tmp...) + } - return extradata + return extradata } func CovertExtradata(extraData []byte) ([][]byte, [][]byte) { - spsnum := extraData[5] & 0x1F - spss := make([][]byte, spsnum) - offset := 6 - for i := 0; i < int(spsnum); i++ { - spssize := binary.BigEndian.Uint16(extraData[offset:]) - sps := make([]byte, spssize+4) - copy(sps, []byte{0x00, 0x00, 0x00, 0x01}) - copy(sps[4:], extraData[offset+2:offset+2+int(spssize)]) - offset += 2 + int(spssize) - spss[i] = sps - } - ppsnum := extraData[offset] - ppss := make([][]byte, ppsnum) - offset++ - for i := 0; i < int(ppsnum); i++ { - ppssize := binary.BigEndian.Uint16(extraData[offset:]) - pps := make([]byte, ppssize+4) - copy(pps, []byte{0x00, 0x00, 0x00, 0x01}) - copy(pps[4:], extraData[offset+2:offset+2+int(ppssize)]) - offset += 2 + int(ppssize) - ppss[i] = pps - } - return spss, ppss + spsnum := extraData[5] & 0x1F + spss := make([][]byte, spsnum) + offset := 6 + for i := 0; i < int(spsnum); i++ { + spssize := binary.BigEndian.Uint16(extraData[offset:]) + sps := make([]byte, spssize+4) + copy(sps, []byte{0x00, 0x00, 0x00, 0x01}) + copy(sps[4:], extraData[offset+2:offset+2+int(spssize)]) + offset += 2 + int(spssize) + spss[i] = sps + } + ppsnum := extraData[offset] + ppss := make([][]byte, ppsnum) + offset++ + for i := 0; i < int(ppsnum); i++ { + ppssize := binary.BigEndian.Uint16(extraData[offset:]) + pps := make([]byte, ppssize+4) + copy(pps, []byte{0x00, 0x00, 0x00, 0x01}) + copy(pps[4:], extraData[offset+2:offset+2+int(ppssize)]) + offset += 2 + int(ppssize) + ppss[i] = pps + } + return spss, ppss } func ConvertAnnexBToAVCC(annexb []byte) []byte { - start, sc := FindStartCode(annexb, 0) - if sc == START_CODE_4 { - binary.BigEndian.PutUint32(annexb[start:], uint32(len(annexb)-4)) - return annexb - } else { - avcc := make([]byte, 1+len(annexb)) - binary.BigEndian.PutUint32(avcc, uint32(len(annexb)-3)) - copy(avcc[4:], annexb[start+3:]) - return avcc - } + start, sc := FindStartCode(annexb, 0) + if sc == START_CODE_4 { + binary.BigEndian.PutUint32(annexb[start:], uint32(len(annexb)-4)) + return annexb + } else { + avcc := make([]byte, 1+len(annexb)) + binary.BigEndian.PutUint32(avcc, uint32(len(annexb)-3)) + copy(avcc[4:], annexb[start+3:]) + return avcc + } } func CovertAVCCToAnnexB(avcc []byte) { - avcc[0] = 0x00 - avcc[1] = 0x00 - avcc[2] = 0x00 - avcc[3] = 0x01 + avcc[0] = 0x00 + avcc[1] = 0x00 + avcc[2] = 0x00 + avcc[3] = 0x01 } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/codec/h265.go b/trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/codec/h265.go index eb2569c40..1277be6c1 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/codec/h265.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/codec/h265.go @@ -1,7 +1,7 @@ package codec import ( - "bytes" + "bytes" ) // nal_unit_header() { @@ -12,581 +12,581 @@ import ( // } type H265NaluHdr struct { - Forbidden_zero_bit uint8 - Nal_unit_type uint8 - Nuh_layer_id uint8 - Nuh_temporal_id_plus1 uint8 + Forbidden_zero_bit uint8 + Nal_unit_type uint8 + Nuh_layer_id uint8 + Nuh_temporal_id_plus1 uint8 } func (hdr *H265NaluHdr) Decode(bs *BitStream) { - hdr.Forbidden_zero_bit = bs.GetBit() - hdr.Nal_unit_type = bs.Uint8(6) - hdr.Nuh_layer_id = bs.Uint8(6) - hdr.Nuh_temporal_id_plus1 = bs.Uint8(3) + hdr.Forbidden_zero_bit = bs.GetBit() + hdr.Nal_unit_type = bs.Uint8(6) + hdr.Nuh_layer_id = bs.Uint8(6) + hdr.Nuh_temporal_id_plus1 = bs.Uint8(3) } type VPS struct { - Vps_video_parameter_set_id uint8 - Vps_base_layer_internal_flag uint8 - Vps_base_layer_available_flag uint8 - Vps_max_layers_minus1 uint8 - Vps_max_sub_layers_minus1 uint8 - Vps_temporal_id_nesting_flag uint8 - Vps_reserved_0xffff_16bits uint16 - Ptl ProfileTierLevel - Vps_sub_layer_ordering_info_present_flag uint8 - Vps_max_dec_pic_buffering_minus1 [8]uint64 - Vps_max_num_reorder_pics [8]uint64 - Vps_max_latency_increase_plus1 [8]uint64 - Vps_max_layer_id uint8 - Vps_num_layer_sets_minus1 uint64 - Layer_id_included_flag [][]uint8 - Vps_timing_info_present_flag uint8 - TimeInfo VPSTimeInfo - // Vps_extension_flag uint8 + Vps_video_parameter_set_id uint8 + Vps_base_layer_internal_flag uint8 + Vps_base_layer_available_flag uint8 + Vps_max_layers_minus1 uint8 + Vps_max_sub_layers_minus1 uint8 + Vps_temporal_id_nesting_flag uint8 + Vps_reserved_0xffff_16bits uint16 + Ptl ProfileTierLevel + Vps_sub_layer_ordering_info_present_flag uint8 + Vps_max_dec_pic_buffering_minus1 [8]uint64 + Vps_max_num_reorder_pics [8]uint64 + Vps_max_latency_increase_plus1 [8]uint64 + Vps_max_layer_id uint8 + Vps_num_layer_sets_minus1 uint64 + Layer_id_included_flag [][]uint8 + Vps_timing_info_present_flag uint8 + TimeInfo VPSTimeInfo + // Vps_extension_flag uint8 } type VPSTimeInfo struct { - Vps_num_units_in_tick uint32 - Vps_time_scale uint32 - Vps_poc_proportional_to_timing_flag uint8 - Vps_num_ticks_poc_diff_one_minus1 uint64 - Vps_num_hrd_parameters uint64 - Hrd_layer_set_idx []uint64 - Cprms_present_flag []uint8 + Vps_num_units_in_tick uint32 + Vps_time_scale uint32 + Vps_poc_proportional_to_timing_flag uint8 + Vps_num_ticks_poc_diff_one_minus1 uint64 + Vps_num_hrd_parameters uint64 + Hrd_layer_set_idx []uint64 + Cprms_present_flag []uint8 } type ProfileTierLevel struct { - General_profile_space uint8 - General_tier_flag uint8 - General_profile_idc uint8 - General_profile_compatibility_flag uint32 - General_constraint_indicator_flag uint64 - General_level_idc uint8 - Sub_layer_profile_present_flag [8]uint8 - Sub_layer_level_present_flag [8]uint8 + General_profile_space uint8 + General_tier_flag uint8 + General_profile_idc uint8 + General_profile_compatibility_flag uint32 + General_constraint_indicator_flag uint64 + General_level_idc uint8 + Sub_layer_profile_present_flag [8]uint8 + Sub_layer_level_present_flag [8]uint8 } //nalu without startcode func (vps *VPS) Decode(nalu []byte) { - sodb := CovertRbspToSodb(nalu) - bs := NewBitStream(sodb) - hdr := H265NaluHdr{} - hdr.Decode(bs) - vps.Vps_video_parameter_set_id = bs.Uint8(4) - vps.Vps_base_layer_internal_flag = bs.Uint8(1) - vps.Vps_base_layer_available_flag = bs.Uint8(1) - vps.Vps_max_layers_minus1 = bs.Uint8(6) - vps.Vps_max_sub_layers_minus1 = bs.Uint8(3) - vps.Vps_temporal_id_nesting_flag = bs.Uint8(1) - vps.Vps_reserved_0xffff_16bits = bs.Uint16(16) - vps.Ptl = Profile_tier_level(1, vps.Vps_max_sub_layers_minus1, bs) - vps.Vps_sub_layer_ordering_info_present_flag = bs.Uint8(1) - var i int - if vps.Vps_sub_layer_ordering_info_present_flag > 0 { - i = 0 - } else { - i = int(vps.Vps_max_sub_layers_minus1) - } - for ; i <= int(vps.Vps_max_sub_layers_minus1); i++ { - vps.Vps_max_dec_pic_buffering_minus1[i] = bs.ReadUE() - vps.Vps_max_num_reorder_pics[i] = bs.ReadUE() - vps.Vps_max_latency_increase_plus1[i] = bs.ReadUE() - } - vps.Vps_max_layer_id = bs.Uint8(6) - vps.Vps_num_layer_sets_minus1 = bs.ReadUE() - vps.Layer_id_included_flag = make([][]uint8, vps.Vps_num_layer_sets_minus1) - for i := 1; i <= int(vps.Vps_num_layer_sets_minus1); i++ { - vps.Layer_id_included_flag[i] = make([]uint8, vps.Vps_max_layer_id) - for j := 0; j <= int(vps.Vps_max_layer_id); j++ { - vps.Layer_id_included_flag[i][j] = bs.Uint8(1) - } - } - vps.Vps_timing_info_present_flag = bs.Uint8(1) - if vps.Vps_timing_info_present_flag == 1 { - vps.TimeInfo = ParserVPSTimeinfo(bs) - } + sodb := CovertRbspToSodb(nalu) + bs := NewBitStream(sodb) + hdr := H265NaluHdr{} + hdr.Decode(bs) + vps.Vps_video_parameter_set_id = bs.Uint8(4) + vps.Vps_base_layer_internal_flag = bs.Uint8(1) + vps.Vps_base_layer_available_flag = bs.Uint8(1) + vps.Vps_max_layers_minus1 = bs.Uint8(6) + vps.Vps_max_sub_layers_minus1 = bs.Uint8(3) + vps.Vps_temporal_id_nesting_flag = bs.Uint8(1) + vps.Vps_reserved_0xffff_16bits = bs.Uint16(16) + vps.Ptl = Profile_tier_level(1, vps.Vps_max_sub_layers_minus1, bs) + vps.Vps_sub_layer_ordering_info_present_flag = bs.Uint8(1) + var i int + if vps.Vps_sub_layer_ordering_info_present_flag > 0 { + i = 0 + } else { + i = int(vps.Vps_max_sub_layers_minus1) + } + for ; i <= int(vps.Vps_max_sub_layers_minus1); i++ { + vps.Vps_max_dec_pic_buffering_minus1[i] = bs.ReadUE() + vps.Vps_max_num_reorder_pics[i] = bs.ReadUE() + vps.Vps_max_latency_increase_plus1[i] = bs.ReadUE() + } + vps.Vps_max_layer_id = bs.Uint8(6) + vps.Vps_num_layer_sets_minus1 = bs.ReadUE() + vps.Layer_id_included_flag = make([][]uint8, vps.Vps_num_layer_sets_minus1) + for i := 1; i <= int(vps.Vps_num_layer_sets_minus1); i++ { + vps.Layer_id_included_flag[i] = make([]uint8, vps.Vps_max_layer_id) + for j := 0; j <= int(vps.Vps_max_layer_id); j++ { + vps.Layer_id_included_flag[i][j] = bs.Uint8(1) + } + } + vps.Vps_timing_info_present_flag = bs.Uint8(1) + if vps.Vps_timing_info_present_flag == 1 { + vps.TimeInfo = ParserVPSTimeinfo(bs) + } } //ffmpeg hevc.c //static void hvcc_parse_ptl(GetBitContext *gb,HEVCDecoderConfigurationRecord *hvcc,unsigned int max_sub_layers_minus1) func Profile_tier_level(profilePresentFlag uint8, maxNumSubLayersMinus1 uint8, bs *BitStream) ProfileTierLevel { - var ptl ProfileTierLevel - ptl.General_profile_space = bs.Uint8(2) - ptl.General_tier_flag = bs.Uint8(1) - ptl.General_profile_idc = bs.Uint8(5) - ptl.General_profile_compatibility_flag = bs.Uint32(32) - ptl.General_constraint_indicator_flag = bs.GetBits(48) - ptl.General_level_idc = bs.Uint8(8) - for i := 0; i < int(maxNumSubLayersMinus1); i++ { - ptl.Sub_layer_profile_present_flag[i] = bs.GetBit() - ptl.Sub_layer_level_present_flag[i] = bs.GetBit() - } - if maxNumSubLayersMinus1 > 0 { - for i := maxNumSubLayersMinus1; i < 8; i++ { - bs.SkipBits(2) - } - } + var ptl ProfileTierLevel + ptl.General_profile_space = bs.Uint8(2) + ptl.General_tier_flag = bs.Uint8(1) + ptl.General_profile_idc = bs.Uint8(5) + ptl.General_profile_compatibility_flag = bs.Uint32(32) + ptl.General_constraint_indicator_flag = bs.GetBits(48) + ptl.General_level_idc = bs.Uint8(8) + for i := 0; i < int(maxNumSubLayersMinus1); i++ { + ptl.Sub_layer_profile_present_flag[i] = bs.GetBit() + ptl.Sub_layer_level_present_flag[i] = bs.GetBit() + } + if maxNumSubLayersMinus1 > 0 { + for i := maxNumSubLayersMinus1; i < 8; i++ { + bs.SkipBits(2) + } + } - for i := 0; i < int(maxNumSubLayersMinus1); i++ { - if ptl.Sub_layer_profile_present_flag[i] == 1 { - /* - * sub_layer_profile_space[i] u(2) - * sub_layer_tier_flag[i] u(1) - * sub_layer_profile_idc[i] u(5) - * sub_layer_profile_compatibility_flag[i][0..31] u(32) - * sub_layer_progressive_source_flag[i] u(1) - * sub_layer_interlaced_source_flag[i] u(1) - * sub_layer_non_packed_constraint_flag[i] u(1) - * sub_layer_frame_only_constraint_flag[i] u(1) - * sub_layer_reserved_zero_44bits[i] u(44) - */ - bs.SkipBits(88) - } - if ptl.Sub_layer_level_present_flag[i] == 1 { - bs.SkipBits(8) - } - } - return ptl + for i := 0; i < int(maxNumSubLayersMinus1); i++ { + if ptl.Sub_layer_profile_present_flag[i] == 1 { + /* + * sub_layer_profile_space[i] u(2) + * sub_layer_tier_flag[i] u(1) + * sub_layer_profile_idc[i] u(5) + * sub_layer_profile_compatibility_flag[i][0..31] u(32) + * sub_layer_progressive_source_flag[i] u(1) + * sub_layer_interlaced_source_flag[i] u(1) + * sub_layer_non_packed_constraint_flag[i] u(1) + * sub_layer_frame_only_constraint_flag[i] u(1) + * sub_layer_reserved_zero_44bits[i] u(44) + */ + bs.SkipBits(88) + } + if ptl.Sub_layer_level_present_flag[i] == 1 { + bs.SkipBits(8) + } + } + return ptl } func ParserVPSTimeinfo(bs *BitStream) VPSTimeInfo { - var ti VPSTimeInfo - ti.Vps_num_units_in_tick = bs.Uint32(32) - ti.Vps_time_scale = bs.Uint32(32) - ti.Vps_poc_proportional_to_timing_flag = bs.Uint8(1) - if ti.Vps_poc_proportional_to_timing_flag == 1 { - ti.Vps_num_ticks_poc_diff_one_minus1 = bs.ReadUE() - } - ti.Vps_num_hrd_parameters = bs.ReadUE() - // for i := 0; i < int(ti.Vps_num_hrd_parameters); i++ { - // ti.Hrd_layer_set_idx[i] = bs.ReadUE() - // if i > 0 { - // ti.Cprms_present_flag[i] = bs.Uint8(1) - // } - // //Hrd_parameters(ti.Cprms_present_flag[i]) - // } - return ti + var ti VPSTimeInfo + ti.Vps_num_units_in_tick = bs.Uint32(32) + ti.Vps_time_scale = bs.Uint32(32) + ti.Vps_poc_proportional_to_timing_flag = bs.Uint8(1) + if ti.Vps_poc_proportional_to_timing_flag == 1 { + ti.Vps_num_ticks_poc_diff_one_minus1 = bs.ReadUE() + } + ti.Vps_num_hrd_parameters = bs.ReadUE() + // for i := 0; i < int(ti.Vps_num_hrd_parameters); i++ { + // ti.Hrd_layer_set_idx[i] = bs.ReadUE() + // if i > 0 { + // ti.Cprms_present_flag[i] = bs.Uint8(1) + // } + // //Hrd_parameters(ti.Cprms_present_flag[i]) + // } + return ti } type H265RawSPS struct { - Sps_video_parameter_set_id uint8 - Sps_max_sub_layers_minus1 uint8 - Sps_temporal_id_nesting_flag uint8 - Ptl ProfileTierLevel - Sps_seq_parameter_set_id uint64 - Chroma_format_idc uint64 - Pic_width_in_luma_samples uint64 - Pic_height_in_luma_samples uint64 - Conformance_window_flag uint8 - Conf_win_left_offset uint64 - Conf_win_right_offset uint64 - Conf_win_top_offset uint64 - Conf_win_bottom_offset uint64 - Bit_depth_luma_minus8 uint64 - Bit_depth_chroma_minus8 uint64 - Log2_max_pic_order_cnt_lsb_minus4 uint64 - Sps_sub_layer_ordering_info_present_flag uint8 - Vui_parameters_present_flag uint8 - Vui VUI_Parameters + Sps_video_parameter_set_id uint8 + Sps_max_sub_layers_minus1 uint8 + Sps_temporal_id_nesting_flag uint8 + Ptl ProfileTierLevel + Sps_seq_parameter_set_id uint64 + Chroma_format_idc uint64 + Pic_width_in_luma_samples uint64 + Pic_height_in_luma_samples uint64 + Conformance_window_flag uint8 + Conf_win_left_offset uint64 + Conf_win_right_offset uint64 + Conf_win_top_offset uint64 + Conf_win_bottom_offset uint64 + Bit_depth_luma_minus8 uint64 + Bit_depth_chroma_minus8 uint64 + Log2_max_pic_order_cnt_lsb_minus4 uint64 + Sps_sub_layer_ordering_info_present_flag uint8 + Vui_parameters_present_flag uint8 + Vui VUI_Parameters } //nalu without startcode func (sps *H265RawSPS) Decode(nalu []byte) { - sodb := CovertRbspToSodb(nalu) - bs := NewBitStream(sodb) - hdr := H265NaluHdr{} - hdr.Decode(bs) - sps.Sps_video_parameter_set_id = bs.Uint8(4) - sps.Sps_max_sub_layers_minus1 = bs.Uint8(3) - sps.Sps_temporal_id_nesting_flag = bs.Uint8(1) - sps.Ptl = Profile_tier_level(1, sps.Sps_max_sub_layers_minus1, bs) - sps.Sps_seq_parameter_set_id = bs.ReadUE() - sps.Chroma_format_idc = bs.ReadUE() - if sps.Chroma_format_idc == 3 { - bs.SkipBits(1) - } - sps.Pic_width_in_luma_samples = bs.ReadUE() - sps.Pic_height_in_luma_samples = bs.ReadUE() - sps.Conformance_window_flag = bs.Uint8(1) - if sps.Conformance_window_flag == 1 { - sps.Conf_win_left_offset = bs.ReadUE() - sps.Conf_win_right_offset = bs.ReadUE() - sps.Conf_win_top_offset = bs.ReadUE() - sps.Conf_win_bottom_offset = bs.ReadUE() - } - sps.Bit_depth_luma_minus8 = bs.ReadUE() - sps.Bit_depth_chroma_minus8 = bs.ReadUE() - sps.Log2_max_pic_order_cnt_lsb_minus4 = bs.ReadUE() - sps.Sps_sub_layer_ordering_info_present_flag = bs.Uint8(1) - i := 0 - if sps.Sps_sub_layer_ordering_info_present_flag == 0 { - i = int(sps.Sps_max_sub_layers_minus1) - } - for ; i <= int(sps.Sps_max_sub_layers_minus1); i++ { - bs.ReadUE() - bs.ReadUE() - bs.ReadUE() - } + sodb := CovertRbspToSodb(nalu) + bs := NewBitStream(sodb) + hdr := H265NaluHdr{} + hdr.Decode(bs) + sps.Sps_video_parameter_set_id = bs.Uint8(4) + sps.Sps_max_sub_layers_minus1 = bs.Uint8(3) + sps.Sps_temporal_id_nesting_flag = bs.Uint8(1) + sps.Ptl = Profile_tier_level(1, sps.Sps_max_sub_layers_minus1, bs) + sps.Sps_seq_parameter_set_id = bs.ReadUE() + sps.Chroma_format_idc = bs.ReadUE() + if sps.Chroma_format_idc == 3 { + bs.SkipBits(1) + } + sps.Pic_width_in_luma_samples = bs.ReadUE() + sps.Pic_height_in_luma_samples = bs.ReadUE() + sps.Conformance_window_flag = bs.Uint8(1) + if sps.Conformance_window_flag == 1 { + sps.Conf_win_left_offset = bs.ReadUE() + sps.Conf_win_right_offset = bs.ReadUE() + sps.Conf_win_top_offset = bs.ReadUE() + sps.Conf_win_bottom_offset = bs.ReadUE() + } + sps.Bit_depth_luma_minus8 = bs.ReadUE() + sps.Bit_depth_chroma_minus8 = bs.ReadUE() + sps.Log2_max_pic_order_cnt_lsb_minus4 = bs.ReadUE() + sps.Sps_sub_layer_ordering_info_present_flag = bs.Uint8(1) + i := 0 + if sps.Sps_sub_layer_ordering_info_present_flag == 0 { + i = int(sps.Sps_max_sub_layers_minus1) + } + for ; i <= int(sps.Sps_max_sub_layers_minus1); i++ { + bs.ReadUE() + bs.ReadUE() + bs.ReadUE() + } - bs.ReadUE() // log2_min_luma_coding_block_size_minus3 - bs.ReadUE() // log2_diff_max_min_luma_coding_block_size - bs.ReadUE() // log2_min_transform_block_size_minus2 - bs.ReadUE() // log2_diff_max_min_transform_block_size - bs.ReadUE() // max_transform_hierarchy_depth_inter - bs.ReadUE() // max_transform_hierarchy_depth_intra - scaling_list_enabled_flag := bs.GetBit() - if scaling_list_enabled_flag > 0 { - sps_scaling_list_data_present_flag := bs.GetBit() - if sps_scaling_list_data_present_flag > 0 { - scaling_list_data(bs) - } - } + bs.ReadUE() // log2_min_luma_coding_block_size_minus3 + bs.ReadUE() // log2_diff_max_min_luma_coding_block_size + bs.ReadUE() // log2_min_transform_block_size_minus2 + bs.ReadUE() // log2_diff_max_min_transform_block_size + bs.ReadUE() // max_transform_hierarchy_depth_inter + bs.ReadUE() // max_transform_hierarchy_depth_intra + scaling_list_enabled_flag := bs.GetBit() + if scaling_list_enabled_flag > 0 { + sps_scaling_list_data_present_flag := bs.GetBit() + if sps_scaling_list_data_present_flag > 0 { + scaling_list_data(bs) + } + } - bs.SkipBits(1) - bs.SkipBits(1) - if bs.GetBit() == 1 { - bs.GetBits(4) - bs.GetBits(4) - bs.ReadUE() - bs.ReadUE() - bs.GetBit() - } - num_short_term_ref_pic_sets := bs.ReadUE() - if num_short_term_ref_pic_sets > 64 { - panic("beyond HEVC_MAX_SHORT_TERM_REF_PIC_SETS") - } - var num_delta_pocs [64]uint32 - for i := 0; i < int(num_short_term_ref_pic_sets); i++ { - parse_rps(i, num_short_term_ref_pic_sets, num_delta_pocs, bs) - } - if bs.GetBit() == 1 { - num_long_term_ref_pics_sps := bs.ReadUE() - for i := 0; i < int(num_long_term_ref_pics_sps); i++ { - length := Min(int(sps.Log2_max_pic_order_cnt_lsb_minus4+4), 16) - bs.SkipBits(length) - bs.SkipBits(1) - } - } - bs.SkipBits(1) - bs.SkipBits(1) - sps.Vui_parameters_present_flag = bs.GetBit() - if sps.Vui_parameters_present_flag == 1 { - sps.Vui.Decode(bs, sps.Sps_max_sub_layers_minus1) - } + bs.SkipBits(1) + bs.SkipBits(1) + if bs.GetBit() == 1 { + bs.GetBits(4) + bs.GetBits(4) + bs.ReadUE() + bs.ReadUE() + bs.GetBit() + } + num_short_term_ref_pic_sets := bs.ReadUE() + if num_short_term_ref_pic_sets > 64 { + panic("beyond HEVC_MAX_SHORT_TERM_REF_PIC_SETS") + } + var num_delta_pocs [64]uint32 + for i := 0; i < int(num_short_term_ref_pic_sets); i++ { + parse_rps(i, num_short_term_ref_pic_sets, num_delta_pocs, bs) + } + if bs.GetBit() == 1 { + num_long_term_ref_pics_sps := bs.ReadUE() + for i := 0; i < int(num_long_term_ref_pics_sps); i++ { + length := Min(int(sps.Log2_max_pic_order_cnt_lsb_minus4+4), 16) + bs.SkipBits(length) + bs.SkipBits(1) + } + } + bs.SkipBits(1) + bs.SkipBits(1) + sps.Vui_parameters_present_flag = bs.GetBit() + if sps.Vui_parameters_present_flag == 1 { + sps.Vui.Decode(bs, sps.Sps_max_sub_layers_minus1) + } } type VUI_Parameters struct { - Aspect_ratio_info_present_flag uint8 - Overscan_info_present_flag uint8 - Chroma_loc_info_present_flag uint8 - Neutral_chroma_indication_flag uint8 - Field_seq_flag uint8 - Frame_field_info_present_flag uint8 - Default_display_window_flag uint8 - Vui_timing_info_present_flag uint8 - Vui_num_units_in_tick uint32 - Vui_time_scale uint32 - Vui_poc_proportional_to_timing_flag uint8 - Vui_hrd_parameters_present_flag uint8 - Bitstream_restriction_flag uint8 - Tiles_fixed_structure_flag uint8 - Motion_vectors_over_pic_boundaries_flag uint8 - Restricted_ref_pic_lists_flag uint8 - Min_spatial_segmentation_idc uint64 - Max_bytes_per_pic_denom uint64 - Max_bits_per_min_cu_denom uint64 - Log2_max_mv_length_horizontal uint64 - Log2_max_mv_length_vertical uint64 + Aspect_ratio_info_present_flag uint8 + Overscan_info_present_flag uint8 + Chroma_loc_info_present_flag uint8 + Neutral_chroma_indication_flag uint8 + Field_seq_flag uint8 + Frame_field_info_present_flag uint8 + Default_display_window_flag uint8 + Vui_timing_info_present_flag uint8 + Vui_num_units_in_tick uint32 + Vui_time_scale uint32 + Vui_poc_proportional_to_timing_flag uint8 + Vui_hrd_parameters_present_flag uint8 + Bitstream_restriction_flag uint8 + Tiles_fixed_structure_flag uint8 + Motion_vectors_over_pic_boundaries_flag uint8 + Restricted_ref_pic_lists_flag uint8 + Min_spatial_segmentation_idc uint64 + Max_bytes_per_pic_denom uint64 + Max_bits_per_min_cu_denom uint64 + Log2_max_mv_length_horizontal uint64 + Log2_max_mv_length_vertical uint64 } func (vui *VUI_Parameters) Decode(bs *BitStream, max_sub_layers_minus1 uint8) { - vui.Aspect_ratio_info_present_flag = bs.Uint8(1) - if vui.Aspect_ratio_info_present_flag == 1 { - if bs.Uint8(8) == 255 { - bs.SkipBits(32) - } - } - vui.Overscan_info_present_flag = bs.Uint8(1) - if vui.Overscan_info_present_flag == 1 { - bs.SkipBits(1) - } - if bs.GetBit() == 1 { - bs.SkipBits(4) - if bs.GetBit() == 1 { - bs.SkipBits(24) - } - } - vui.Chroma_loc_info_present_flag = bs.GetBit() - if vui.Chroma_loc_info_present_flag == 1 { - bs.ReadUE() - bs.ReadUE() - } - vui.Neutral_chroma_indication_flag = bs.GetBit() - vui.Field_seq_flag = bs.GetBit() - vui.Frame_field_info_present_flag = bs.GetBit() - vui.Default_display_window_flag = bs.GetBit() - if vui.Default_display_window_flag == 1 { - bs.ReadUE() - bs.ReadUE() - bs.ReadUE() - bs.ReadUE() - } - vui.Vui_timing_info_present_flag = bs.GetBit() - if vui.Vui_timing_info_present_flag == 1 { - vui.Vui_num_units_in_tick = bs.Uint32(32) - vui.Vui_time_scale = bs.Uint32(32) - vui.Vui_poc_proportional_to_timing_flag = bs.GetBit() - if vui.Vui_poc_proportional_to_timing_flag == 1 { - bs.ReadUE() - } - vui.Vui_hrd_parameters_present_flag = bs.GetBit() - if vui.Vui_hrd_parameters_present_flag == 1 { - skip_hrd_parameters(1, uint32(max_sub_layers_minus1), bs) - } - } - vui.Bitstream_restriction_flag = bs.GetBit() - if vui.Bitstream_restriction_flag == 1 { - vui.Tiles_fixed_structure_flag = bs.GetBit() - vui.Motion_vectors_over_pic_boundaries_flag = bs.GetBit() - vui.Restricted_ref_pic_lists_flag = bs.GetBit() - vui.Min_spatial_segmentation_idc = bs.ReadUE() - vui.Max_bytes_per_pic_denom = bs.ReadUE() - vui.Max_bits_per_min_cu_denom = bs.ReadUE() - vui.Log2_max_mv_length_horizontal = bs.ReadUE() - vui.Log2_max_mv_length_vertical = bs.ReadUE() - } + vui.Aspect_ratio_info_present_flag = bs.Uint8(1) + if vui.Aspect_ratio_info_present_flag == 1 { + if bs.Uint8(8) == 255 { + bs.SkipBits(32) + } + } + vui.Overscan_info_present_flag = bs.Uint8(1) + if vui.Overscan_info_present_flag == 1 { + bs.SkipBits(1) + } + if bs.GetBit() == 1 { + bs.SkipBits(4) + if bs.GetBit() == 1 { + bs.SkipBits(24) + } + } + vui.Chroma_loc_info_present_flag = bs.GetBit() + if vui.Chroma_loc_info_present_flag == 1 { + bs.ReadUE() + bs.ReadUE() + } + vui.Neutral_chroma_indication_flag = bs.GetBit() + vui.Field_seq_flag = bs.GetBit() + vui.Frame_field_info_present_flag = bs.GetBit() + vui.Default_display_window_flag = bs.GetBit() + if vui.Default_display_window_flag == 1 { + bs.ReadUE() + bs.ReadUE() + bs.ReadUE() + bs.ReadUE() + } + vui.Vui_timing_info_present_flag = bs.GetBit() + if vui.Vui_timing_info_present_flag == 1 { + vui.Vui_num_units_in_tick = bs.Uint32(32) + vui.Vui_time_scale = bs.Uint32(32) + vui.Vui_poc_proportional_to_timing_flag = bs.GetBit() + if vui.Vui_poc_proportional_to_timing_flag == 1 { + bs.ReadUE() + } + vui.Vui_hrd_parameters_present_flag = bs.GetBit() + if vui.Vui_hrd_parameters_present_flag == 1 { + skip_hrd_parameters(1, uint32(max_sub_layers_minus1), bs) + } + } + vui.Bitstream_restriction_flag = bs.GetBit() + if vui.Bitstream_restriction_flag == 1 { + vui.Tiles_fixed_structure_flag = bs.GetBit() + vui.Motion_vectors_over_pic_boundaries_flag = bs.GetBit() + vui.Restricted_ref_pic_lists_flag = bs.GetBit() + vui.Min_spatial_segmentation_idc = bs.ReadUE() + vui.Max_bytes_per_pic_denom = bs.ReadUE() + vui.Max_bits_per_min_cu_denom = bs.ReadUE() + vui.Log2_max_mv_length_horizontal = bs.ReadUE() + vui.Log2_max_mv_length_vertical = bs.ReadUE() + } } func skip_hrd_parameters(cprms_present_flag uint8, max_sub_layers_minus1 uint32, bs *BitStream) { - nal_hrd_parameters_present_flag := uint8(0) - vcl_hrd_parameters_present_flag := uint8(0) - sub_pic_hrd_params_present_flag := uint8(0) - if cprms_present_flag == 1 { - nal_hrd_parameters_present_flag = bs.GetBit() - vcl_hrd_parameters_present_flag = bs.GetBit() + nal_hrd_parameters_present_flag := uint8(0) + vcl_hrd_parameters_present_flag := uint8(0) + sub_pic_hrd_params_present_flag := uint8(0) + if cprms_present_flag == 1 { + nal_hrd_parameters_present_flag = bs.GetBit() + vcl_hrd_parameters_present_flag = bs.GetBit() - if nal_hrd_parameters_present_flag == 1 || vcl_hrd_parameters_present_flag == 1 { - sub_pic_hrd_params_present_flag = bs.GetBit() + if nal_hrd_parameters_present_flag == 1 || vcl_hrd_parameters_present_flag == 1 { + sub_pic_hrd_params_present_flag = bs.GetBit() - if sub_pic_hrd_params_present_flag == 1 { - /* - * tick_divisor_minus2 u(8) - * du_cpb_removal_delay_increment_length_minus1 u(5) - * sub_pic_cpb_params_in_pic_timing_sei_flag u(1) - * dpb_output_delay_du_length_minus1 u(5) - */ - bs.SkipBits(19) - } + if sub_pic_hrd_params_present_flag == 1 { + /* + * tick_divisor_minus2 u(8) + * du_cpb_removal_delay_increment_length_minus1 u(5) + * sub_pic_cpb_params_in_pic_timing_sei_flag u(1) + * dpb_output_delay_du_length_minus1 u(5) + */ + bs.SkipBits(19) + } - bs.SkipBits(8) + bs.SkipBits(8) - if sub_pic_hrd_params_present_flag == 1 { - // cpb_size_du_scale - bs.SkipBits(4) - } + if sub_pic_hrd_params_present_flag == 1 { + // cpb_size_du_scale + bs.SkipBits(4) + } - /* - * initial_cpb_removal_delay_length_minus1 u(5) - * au_cpb_removal_delay_length_minus1 u(5) - * dpb_output_delay_length_minus1 u(5) - */ - bs.SkipBits(15) - } - } - for i := 0; i <= int(max_sub_layers_minus1); i++ { - fixed_pic_rate_general_flag := bs.GetBit() - fixed_pic_rate_within_cvs_flag := uint8(0) - low_delay_hrd_flag := uint8(0) - cpb_cnt_minus1 := uint32(0) - if fixed_pic_rate_general_flag == 0 { - fixed_pic_rate_within_cvs_flag = bs.GetBit() - } - if fixed_pic_rate_within_cvs_flag == 1 { - bs.ReadUE() - } else { - low_delay_hrd_flag = bs.GetBit() - } - if low_delay_hrd_flag == 0 { - cpb_cnt_minus1 = uint32(bs.ReadUE()) - if cpb_cnt_minus1 > 31 { - panic("cpb_cnt_minus1 > 31") - } - } - skip_sub_layer_hrd_parameters := func() { - for i := 0; i < int(cpb_cnt_minus1); i++ { - bs.ReadUE() - bs.ReadUE() - if sub_pic_hrd_params_present_flag == 1 { - bs.ReadUE() - bs.ReadUE() - } - bs.SkipBits(1) - } - } - if nal_hrd_parameters_present_flag == 1 { - skip_sub_layer_hrd_parameters() - } - if vcl_hrd_parameters_present_flag == 1 { - skip_sub_layer_hrd_parameters() - } - } + /* + * initial_cpb_removal_delay_length_minus1 u(5) + * au_cpb_removal_delay_length_minus1 u(5) + * dpb_output_delay_length_minus1 u(5) + */ + bs.SkipBits(15) + } + } + for i := 0; i <= int(max_sub_layers_minus1); i++ { + fixed_pic_rate_general_flag := bs.GetBit() + fixed_pic_rate_within_cvs_flag := uint8(0) + low_delay_hrd_flag := uint8(0) + cpb_cnt_minus1 := uint32(0) + if fixed_pic_rate_general_flag == 0 { + fixed_pic_rate_within_cvs_flag = bs.GetBit() + } + if fixed_pic_rate_within_cvs_flag == 1 { + bs.ReadUE() + } else { + low_delay_hrd_flag = bs.GetBit() + } + if low_delay_hrd_flag == 0 { + cpb_cnt_minus1 = uint32(bs.ReadUE()) + if cpb_cnt_minus1 > 31 { + panic("cpb_cnt_minus1 > 31") + } + } + skip_sub_layer_hrd_parameters := func() { + for i := 0; i < int(cpb_cnt_minus1); i++ { + bs.ReadUE() + bs.ReadUE() + if sub_pic_hrd_params_present_flag == 1 { + bs.ReadUE() + bs.ReadUE() + } + bs.SkipBits(1) + } + } + if nal_hrd_parameters_present_flag == 1 { + skip_sub_layer_hrd_parameters() + } + if vcl_hrd_parameters_present_flag == 1 { + skip_sub_layer_hrd_parameters() + } + } } func scaling_list_data(bs *BitStream) { - for i := 0; i < 4; i++ { - maxj := 6 - if i == 3 { - maxj = 2 - } - for j := 0; j < maxj; j++ { - if bs.GetBit() == 0 { - bs.ReadUE() - } else { - num_coeffs := Min(64, 1<<(4+(i<<1))) - if i > 1 { - bs.ReadSE() - } - for k := 0; k < num_coeffs; k++ { - bs.ReadSE() - } - } - } - } + for i := 0; i < 4; i++ { + maxj := 6 + if i == 3 { + maxj = 2 + } + for j := 0; j < maxj; j++ { + if bs.GetBit() == 0 { + bs.ReadUE() + } else { + num_coeffs := Min(64, 1<<(4+(i<<1))) + if i > 1 { + bs.ReadSE() + } + for k := 0; k < num_coeffs; k++ { + bs.ReadSE() + } + } + } + } } func parse_rps(rps_idx int, nums_rps uint64, num_delta_pocs [64]uint32, bs *BitStream) { - if rps_idx > 0 && bs.GetBit() > 0 { - if rps_idx > int(nums_rps) { - panic("rps_idx > int(nums_rps)") - } - bs.SkipBits(1) - bs.ReadUE() - num_delta_pocs[rps_idx] = 0 - for i := uint32(0); i <= num_delta_pocs[rps_idx-1]; i++ { - var use_delta_flag uint8 - var used_by_curr_pic_flag uint8 = bs.GetBit() - if used_by_curr_pic_flag == 0 { - use_delta_flag = bs.GetBit() - } - if use_delta_flag > 0 || used_by_curr_pic_flag > 0 { - num_delta_pocs[rps_idx]++ - } - } - } else { - num_negative_pics := bs.ReadUE() - num_positive_pics := bs.ReadUE() - if (num_negative_pics+num_positive_pics)*2 > uint64(bs.RemainBits()) { - panic("(num_negative_pics + num_positive_pics) * 2> uint64(bs.RemainBits())") - } - for i := 0; i < int(num_negative_pics); i++ { - bs.ReadUE() - bs.SkipBits(1) - } - for i := 0; i < int(num_positive_pics); i++ { - bs.ReadUE() - bs.SkipBits(1) - } - } + if rps_idx > 0 && bs.GetBit() > 0 { + if rps_idx > int(nums_rps) { + panic("rps_idx > int(nums_rps)") + } + bs.SkipBits(1) + bs.ReadUE() + num_delta_pocs[rps_idx] = 0 + for i := uint32(0); i <= num_delta_pocs[rps_idx-1]; i++ { + var use_delta_flag uint8 + var used_by_curr_pic_flag uint8 = bs.GetBit() + if used_by_curr_pic_flag == 0 { + use_delta_flag = bs.GetBit() + } + if use_delta_flag > 0 || used_by_curr_pic_flag > 0 { + num_delta_pocs[rps_idx]++ + } + } + } else { + num_negative_pics := bs.ReadUE() + num_positive_pics := bs.ReadUE() + if (num_negative_pics+num_positive_pics)*2 > uint64(bs.RemainBits()) { + panic("(num_negative_pics + num_positive_pics) * 2> uint64(bs.RemainBits())") + } + for i := 0; i < int(num_negative_pics); i++ { + bs.ReadUE() + bs.SkipBits(1) + } + for i := 0; i < int(num_positive_pics); i++ { + bs.ReadUE() + bs.SkipBits(1) + } + } } type H265RawPPS struct { - Pps_pic_parameter_set_id uint64 - Pps_seq_parameter_set_id uint64 - Dependent_slice_segments_enabled_flag uint8 - Output_flag_present_flag uint8 - Num_extra_slice_header_bits uint8 - Sign_data_hiding_enabled_flag uint8 - Cabac_init_present_flag uint8 - Num_ref_idx_l0_default_active_minus1 uint64 - Num_ref_idx_l1_default_active_minus1 uint64 - Init_qp_minus26 int64 - Constrained_intra_pred_flag uint8 - Transform_skip_enabled_flag uint8 - Cu_qp_delta_enabled_flag uint8 - Diff_cu_qp_delta_depth uint64 - Pps_cb_qp_offset int64 - Pps_cr_qp_offset int64 - Pps_slice_chroma_qp_offsets_present_flag uint8 - Weighted_pred_flag uint8 - Weighted_bipred_flag uint8 - Transquant_bypass_enabled_flag uint8 - Tiles_enabled_flag uint8 - Entropy_coding_sync_enabled_flag uint8 + Pps_pic_parameter_set_id uint64 + Pps_seq_parameter_set_id uint64 + Dependent_slice_segments_enabled_flag uint8 + Output_flag_present_flag uint8 + Num_extra_slice_header_bits uint8 + Sign_data_hiding_enabled_flag uint8 + Cabac_init_present_flag uint8 + Num_ref_idx_l0_default_active_minus1 uint64 + Num_ref_idx_l1_default_active_minus1 uint64 + Init_qp_minus26 int64 + Constrained_intra_pred_flag uint8 + Transform_skip_enabled_flag uint8 + Cu_qp_delta_enabled_flag uint8 + Diff_cu_qp_delta_depth uint64 + Pps_cb_qp_offset int64 + Pps_cr_qp_offset int64 + Pps_slice_chroma_qp_offsets_present_flag uint8 + Weighted_pred_flag uint8 + Weighted_bipred_flag uint8 + Transquant_bypass_enabled_flag uint8 + Tiles_enabled_flag uint8 + Entropy_coding_sync_enabled_flag uint8 } //nalu without startcode func (pps *H265RawPPS) Decode(nalu []byte) { - sodb := CovertRbspToSodb(nalu) - bs := NewBitStream(sodb) - hdr := H265NaluHdr{} - hdr.Decode(bs) - pps.Pps_pic_parameter_set_id = bs.ReadUE() - pps.Pps_seq_parameter_set_id = bs.ReadUE() - pps.Dependent_slice_segments_enabled_flag = bs.GetBit() - pps.Output_flag_present_flag = bs.GetBit() - pps.Num_extra_slice_header_bits = bs.Uint8(3) - pps.Sign_data_hiding_enabled_flag = bs.GetBit() - pps.Cabac_init_present_flag = bs.GetBit() - pps.Num_ref_idx_l0_default_active_minus1 = bs.ReadUE() - pps.Num_ref_idx_l1_default_active_minus1 = bs.ReadUE() - pps.Init_qp_minus26 = bs.ReadSE() - pps.Constrained_intra_pred_flag = bs.GetBit() - pps.Transform_skip_enabled_flag = bs.GetBit() - pps.Cu_qp_delta_enabled_flag = bs.GetBit() - if pps.Cu_qp_delta_enabled_flag == 1 { - pps.Diff_cu_qp_delta_depth = bs.ReadUE() - } - pps.Pps_cb_qp_offset = bs.ReadSE() - pps.Pps_cr_qp_offset = bs.ReadSE() - pps.Pps_slice_chroma_qp_offsets_present_flag = bs.GetBit() - pps.Weighted_pred_flag = bs.GetBit() - pps.Weighted_bipred_flag = bs.GetBit() - pps.Transquant_bypass_enabled_flag = bs.GetBit() - pps.Tiles_enabled_flag = bs.GetBit() - pps.Entropy_coding_sync_enabled_flag = bs.GetBit() + sodb := CovertRbspToSodb(nalu) + bs := NewBitStream(sodb) + hdr := H265NaluHdr{} + hdr.Decode(bs) + pps.Pps_pic_parameter_set_id = bs.ReadUE() + pps.Pps_seq_parameter_set_id = bs.ReadUE() + pps.Dependent_slice_segments_enabled_flag = bs.GetBit() + pps.Output_flag_present_flag = bs.GetBit() + pps.Num_extra_slice_header_bits = bs.Uint8(3) + pps.Sign_data_hiding_enabled_flag = bs.GetBit() + pps.Cabac_init_present_flag = bs.GetBit() + pps.Num_ref_idx_l0_default_active_minus1 = bs.ReadUE() + pps.Num_ref_idx_l1_default_active_minus1 = bs.ReadUE() + pps.Init_qp_minus26 = bs.ReadSE() + pps.Constrained_intra_pred_flag = bs.GetBit() + pps.Transform_skip_enabled_flag = bs.GetBit() + pps.Cu_qp_delta_enabled_flag = bs.GetBit() + if pps.Cu_qp_delta_enabled_flag == 1 { + pps.Diff_cu_qp_delta_depth = bs.ReadUE() + } + pps.Pps_cb_qp_offset = bs.ReadSE() + pps.Pps_cr_qp_offset = bs.ReadSE() + pps.Pps_slice_chroma_qp_offsets_present_flag = bs.GetBit() + pps.Weighted_pred_flag = bs.GetBit() + pps.Weighted_bipred_flag = bs.GetBit() + pps.Transquant_bypass_enabled_flag = bs.GetBit() + pps.Tiles_enabled_flag = bs.GetBit() + pps.Entropy_coding_sync_enabled_flag = bs.GetBit() } func GetH265Resolution(sps []byte) (width uint32, height uint32) { - start, sc := FindStartCode(sps, 0) - h265sps := H265RawSPS{} - h265sps.Decode(sps[start+int(sc):]) - width = uint32(h265sps.Pic_width_in_luma_samples) - height = uint32(h265sps.Pic_height_in_luma_samples) - return + start, sc := FindStartCode(sps, 0) + h265sps := H265RawSPS{} + h265sps.Decode(sps[start+int(sc):]) + width = uint32(h265sps.Pic_width_in_luma_samples) + height = uint32(h265sps.Pic_height_in_luma_samples) + return } func GetVPSIdWithStartCode(vps []byte) uint8 { - start, sc := FindStartCode(vps, 0) - return GetVPSId(vps[start+int(sc):]) + start, sc := FindStartCode(vps, 0) + return GetVPSId(vps[start+int(sc):]) } func GetVPSId(vps []byte) uint8 { - var rawvps VPS - rawvps.Decode(vps) - return rawvps.Vps_video_parameter_set_id + var rawvps VPS + rawvps.Decode(vps) + return rawvps.Vps_video_parameter_set_id } func GetH265SPSIdWithStartCode(sps []byte) uint64 { - start, sc := FindStartCode(sps, 0) - return GetH265SPSId(sps[start+int(sc):]) + start, sc := FindStartCode(sps, 0) + return GetH265SPSId(sps[start+int(sc):]) } func GetH265SPSId(sps []byte) uint64 { - var rawsps H265RawSPS - rawsps.Decode(sps) - return rawsps.Sps_seq_parameter_set_id + var rawsps H265RawSPS + rawsps.Decode(sps) + return rawsps.Sps_seq_parameter_set_id } func GetH65PPSIdWithStartCode(pps []byte) uint64 { - start, sc := FindStartCode(pps, 0) - return GetH265SPSId(pps[start+int(sc):]) + start, sc := FindStartCode(pps, 0) + return GetH265SPSId(pps[start+int(sc):]) } func GetH265PPSId(pps []byte) uint64 { - var rawpps H265RawPPS - rawpps.Decode(pps) - return rawpps.Pps_pic_parameter_set_id + var rawpps H265RawPPS + rawpps.Decode(pps) + return rawpps.Pps_pic_parameter_set_id } /* @@ -630,369 +630,369 @@ aligned(8) class HEVCDecoderConfigurationRecord { */ type NalUnit struct { - NalUnitLength uint16 - Nalu []byte + NalUnitLength uint16 + Nalu []byte } type HVCCNALUnitArray struct { - Array_completeness uint8 - NAL_unit_type uint8 - NumNalus uint16 - NalUnits []*NalUnit + Array_completeness uint8 + NAL_unit_type uint8 + NumNalus uint16 + NalUnits []*NalUnit } type HEVCRecordConfiguration struct { - ConfigurationVersion uint8 - General_profile_space uint8 - General_tier_flag uint8 - General_profile_idc uint8 - General_profile_compatibility_flags uint32 - General_constraint_indicator_flags uint64 - General_level_idc uint8 - Min_spatial_segmentation_idc uint16 - ParallelismType uint8 - ChromaFormat uint8 - BitDepthLumaMinus8 uint8 - BitDepthChromaMinus8 uint8 - AvgFrameRate uint16 - ConstantFrameRate uint8 - NumTemporalLayers uint8 - TemporalIdNested uint8 - LengthSizeMinusOne uint8 - NumOfArrays uint8 - Arrays []*HVCCNALUnitArray + ConfigurationVersion uint8 + General_profile_space uint8 + General_tier_flag uint8 + General_profile_idc uint8 + General_profile_compatibility_flags uint32 + General_constraint_indicator_flags uint64 + General_level_idc uint8 + Min_spatial_segmentation_idc uint16 + ParallelismType uint8 + ChromaFormat uint8 + BitDepthLumaMinus8 uint8 + BitDepthChromaMinus8 uint8 + AvgFrameRate uint16 + ConstantFrameRate uint8 + NumTemporalLayers uint8 + TemporalIdNested uint8 + LengthSizeMinusOne uint8 + NumOfArrays uint8 + Arrays []*HVCCNALUnitArray } func NewHEVCRecordConfiguration() *HEVCRecordConfiguration { - return &HEVCRecordConfiguration{ - ConfigurationVersion: 1, - General_profile_compatibility_flags: 0xffffffff, - General_constraint_indicator_flags: 0xffffffffffffffff, - Min_spatial_segmentation_idc: 4097, - LengthSizeMinusOne: 3, - } + return &HEVCRecordConfiguration{ + ConfigurationVersion: 1, + General_profile_compatibility_flags: 0xffffffff, + General_constraint_indicator_flags: 0xffffffffffffffff, + Min_spatial_segmentation_idc: 4097, + LengthSizeMinusOne: 3, + } } func (hvcc *HEVCRecordConfiguration) Encode() []byte { - bsw := NewBitStreamWriter(512) - bsw.PutByte(hvcc.ConfigurationVersion) - bsw.PutUint8(hvcc.General_profile_space, 2) - bsw.PutUint8(hvcc.General_tier_flag, 1) - bsw.PutUint8(hvcc.General_profile_idc, 5) - bsw.PutUint32(hvcc.General_profile_compatibility_flags, 32) - bsw.PutUint64(hvcc.General_constraint_indicator_flags, 48) - bsw.PutByte(hvcc.General_level_idc) - bsw.PutUint8(0x0F, 4) - bsw.PutUint16(hvcc.Min_spatial_segmentation_idc, 12) - bsw.PutUint8(0x3F, 6) - //ffmpeg hvcc_write(AVIOContext *pb, HEVCDecoderConfigurationRecord *hvcc) - /* - * parallelismType indicates the type of parallelism that is used to meet - * the restrictions imposed by min_spatial_segmentation_idc when the value - * of min_spatial_segmentation_idc is greater than 0. - */ - if hvcc.Min_spatial_segmentation_idc == 0 { - hvcc.ParallelismType = 0 - } - bsw.PutUint8(hvcc.ParallelismType, 2) - bsw.PutUint8(0x3F, 6) - bsw.PutUint8(hvcc.ChromaFormat, 2) - bsw.PutUint8(0x1F, 5) - bsw.PutUint8(hvcc.BitDepthLumaMinus8, 3) - bsw.PutUint8(0x1F, 5) - bsw.PutUint8(hvcc.BitDepthChromaMinus8, 3) - bsw.PutUint16(hvcc.AvgFrameRate, 16) - bsw.PutUint8(hvcc.ConstantFrameRate, 2) - bsw.PutUint8(hvcc.NumTemporalLayers, 3) - bsw.PutUint8(hvcc.TemporalIdNested, 1) - bsw.PutUint8(hvcc.LengthSizeMinusOne, 2) - bsw.PutByte(uint8(len(hvcc.Arrays))) - for _, arrays := range hvcc.Arrays { - bsw.PutUint8(arrays.Array_completeness, 1) - bsw.PutUint8(0, 1) - bsw.PutUint8(arrays.NAL_unit_type, 6) - bsw.PutUint16(arrays.NumNalus, 16) - for _, nalu := range arrays.NalUnits { - bsw.PutUint16(nalu.NalUnitLength, 16) - bsw.PutBytes(nalu.Nalu) - } - } - return bsw.Bits() + bsw := NewBitStreamWriter(512) + bsw.PutByte(hvcc.ConfigurationVersion) + bsw.PutUint8(hvcc.General_profile_space, 2) + bsw.PutUint8(hvcc.General_tier_flag, 1) + bsw.PutUint8(hvcc.General_profile_idc, 5) + bsw.PutUint32(hvcc.General_profile_compatibility_flags, 32) + bsw.PutUint64(hvcc.General_constraint_indicator_flags, 48) + bsw.PutByte(hvcc.General_level_idc) + bsw.PutUint8(0x0F, 4) + bsw.PutUint16(hvcc.Min_spatial_segmentation_idc, 12) + bsw.PutUint8(0x3F, 6) + //ffmpeg hvcc_write(AVIOContext *pb, HEVCDecoderConfigurationRecord *hvcc) + /* + * parallelismType indicates the type of parallelism that is used to meet + * the restrictions imposed by min_spatial_segmentation_idc when the value + * of min_spatial_segmentation_idc is greater than 0. + */ + if hvcc.Min_spatial_segmentation_idc == 0 { + hvcc.ParallelismType = 0 + } + bsw.PutUint8(hvcc.ParallelismType, 2) + bsw.PutUint8(0x3F, 6) + bsw.PutUint8(hvcc.ChromaFormat, 2) + bsw.PutUint8(0x1F, 5) + bsw.PutUint8(hvcc.BitDepthLumaMinus8, 3) + bsw.PutUint8(0x1F, 5) + bsw.PutUint8(hvcc.BitDepthChromaMinus8, 3) + bsw.PutUint16(hvcc.AvgFrameRate, 16) + bsw.PutUint8(hvcc.ConstantFrameRate, 2) + bsw.PutUint8(hvcc.NumTemporalLayers, 3) + bsw.PutUint8(hvcc.TemporalIdNested, 1) + bsw.PutUint8(hvcc.LengthSizeMinusOne, 2) + bsw.PutByte(uint8(len(hvcc.Arrays))) + for _, arrays := range hvcc.Arrays { + bsw.PutUint8(arrays.Array_completeness, 1) + bsw.PutUint8(0, 1) + bsw.PutUint8(arrays.NAL_unit_type, 6) + bsw.PutUint16(arrays.NumNalus, 16) + for _, nalu := range arrays.NalUnits { + bsw.PutUint16(nalu.NalUnitLength, 16) + bsw.PutBytes(nalu.Nalu) + } + } + return bsw.Bits() } func (hvcc *HEVCRecordConfiguration) Decode(hevc []byte) { - bs := NewBitStream(hevc) - hvcc.ConfigurationVersion = bs.Uint8(8) - hvcc.General_profile_space = bs.Uint8(2) - hvcc.General_tier_flag = bs.Uint8(1) - hvcc.General_profile_idc = bs.Uint8(5) - hvcc.General_profile_compatibility_flags = bs.Uint32(32) - hvcc.General_constraint_indicator_flags = bs.GetBits(48) - hvcc.General_level_idc = bs.Uint8(8) - bs.SkipBits(4) - hvcc.Min_spatial_segmentation_idc = bs.Uint16(12) - bs.SkipBits(6) - hvcc.ParallelismType = bs.Uint8(2) - bs.SkipBits(6) - hvcc.ChromaFormat = bs.Uint8(2) - bs.SkipBits(5) - hvcc.BitDepthLumaMinus8 = bs.Uint8(3) - bs.SkipBits(5) - hvcc.BitDepthChromaMinus8 = bs.Uint8(3) - hvcc.AvgFrameRate = bs.Uint16(16) - hvcc.ConstantFrameRate = bs.Uint8(2) - hvcc.NumTemporalLayers = bs.Uint8(3) - hvcc.TemporalIdNested = bs.Uint8(1) - hvcc.LengthSizeMinusOne = bs.Uint8(2) - hvcc.NumOfArrays = bs.Uint8(8) - hvcc.Arrays = make([]*HVCCNALUnitArray, hvcc.NumOfArrays) - for i := 0; i < int(hvcc.NumOfArrays); i++ { - hvcc.Arrays[i] = new(HVCCNALUnitArray) - hvcc.Arrays[i].Array_completeness = bs.GetBit() - bs.SkipBits(1) - hvcc.Arrays[i].NAL_unit_type = bs.Uint8(6) - hvcc.Arrays[i].NumNalus = bs.Uint16(16) - hvcc.Arrays[i].NalUnits = make([]*NalUnit, hvcc.Arrays[i].NumNalus) - for j := 0; j < int(hvcc.Arrays[i].NumNalus); j++ { - hvcc.Arrays[i].NalUnits[j] = new(NalUnit) - hvcc.Arrays[i].NalUnits[j].NalUnitLength = bs.Uint16(16) - hvcc.Arrays[i].NalUnits[j].Nalu = bs.GetBytes(int(hvcc.Arrays[i].NalUnits[j].NalUnitLength)) - } - } + bs := NewBitStream(hevc) + hvcc.ConfigurationVersion = bs.Uint8(8) + hvcc.General_profile_space = bs.Uint8(2) + hvcc.General_tier_flag = bs.Uint8(1) + hvcc.General_profile_idc = bs.Uint8(5) + hvcc.General_profile_compatibility_flags = bs.Uint32(32) + hvcc.General_constraint_indicator_flags = bs.GetBits(48) + hvcc.General_level_idc = bs.Uint8(8) + bs.SkipBits(4) + hvcc.Min_spatial_segmentation_idc = bs.Uint16(12) + bs.SkipBits(6) + hvcc.ParallelismType = bs.Uint8(2) + bs.SkipBits(6) + hvcc.ChromaFormat = bs.Uint8(2) + bs.SkipBits(5) + hvcc.BitDepthLumaMinus8 = bs.Uint8(3) + bs.SkipBits(5) + hvcc.BitDepthChromaMinus8 = bs.Uint8(3) + hvcc.AvgFrameRate = bs.Uint16(16) + hvcc.ConstantFrameRate = bs.Uint8(2) + hvcc.NumTemporalLayers = bs.Uint8(3) + hvcc.TemporalIdNested = bs.Uint8(1) + hvcc.LengthSizeMinusOne = bs.Uint8(2) + hvcc.NumOfArrays = bs.Uint8(8) + hvcc.Arrays = make([]*HVCCNALUnitArray, hvcc.NumOfArrays) + for i := 0; i < int(hvcc.NumOfArrays); i++ { + hvcc.Arrays[i] = new(HVCCNALUnitArray) + hvcc.Arrays[i].Array_completeness = bs.GetBit() + bs.SkipBits(1) + hvcc.Arrays[i].NAL_unit_type = bs.Uint8(6) + hvcc.Arrays[i].NumNalus = bs.Uint16(16) + hvcc.Arrays[i].NalUnits = make([]*NalUnit, hvcc.Arrays[i].NumNalus) + for j := 0; j < int(hvcc.Arrays[i].NumNalus); j++ { + hvcc.Arrays[i].NalUnits[j] = new(NalUnit) + hvcc.Arrays[i].NalUnits[j].NalUnitLength = bs.Uint16(16) + hvcc.Arrays[i].NalUnits[j].Nalu = bs.GetBytes(int(hvcc.Arrays[i].NalUnits[j].NalUnitLength)) + } + } } func (hvcc *HEVCRecordConfiguration) UpdateSPS(sps []byte) { - start, sc := FindStartCode(sps, 0) - sps = sps[start+int(sc):] - var rawsps H265RawSPS - rawsps.Decode(sps) - spsid := rawsps.Sps_seq_parameter_set_id - var needUpdate bool = false - i := 0 - for ; i < len(hvcc.Arrays); i++ { - arrays := hvcc.Arrays[i] - found := false - if arrays.NAL_unit_type == uint8(H265_NAL_SPS) { - j := 0 - for ; j < len(arrays.NalUnits); j++ { - if spsid != GetH265SPSId(arrays.NalUnits[j].Nalu) { - found = true - continue - } - //find the same sps nalu - if arrays.NalUnits[j].NalUnitLength == uint16(len(sps)) && bytes.Equal(arrays.NalUnits[j].Nalu, sps) { - return - } - tmpsps := make([]byte, len(sps)) - copy(tmpsps, sps) - arrays.NalUnits[j].Nalu = tmpsps - arrays.NalUnits[j].NalUnitLength = uint16(len(tmpsps)) - needUpdate = true - break - } - if j == len(arrays.NalUnits) { - nalu := &NalUnit{ - Nalu: make([]byte, len(sps)), - NalUnitLength: uint16(len(sps)), - } - copy(nalu.Nalu, sps) - arrays.NalUnits = append(arrays.NalUnits, nalu) - needUpdate = true - } - } - if found { - break - } - } - if i == len(hvcc.Arrays) { - nua := &HVCCNALUnitArray{ - Array_completeness: 1, - NAL_unit_type: 33, - NumNalus: 1, - NalUnits: make([]*NalUnit, 1), - } - nu := &NalUnit{ - NalUnitLength: uint16(len(sps)), - Nalu: make([]byte, len(sps)), - } - copy(nu.Nalu, sps) - nua.NalUnits[0] = nu - hvcc.Arrays = append(hvcc.Arrays, nua) - needUpdate = true - } - if needUpdate { - hvcc.NumTemporalLayers = uint8(Max(int(hvcc.NumTemporalLayers), int(rawsps.Sps_max_sub_layers_minus1+1))) - hvcc.TemporalIdNested = rawsps.Sps_temporal_id_nesting_flag - hvcc.ChromaFormat = uint8(rawsps.Chroma_format_idc) - hvcc.BitDepthChromaMinus8 = uint8(rawsps.Bit_depth_chroma_minus8) - hvcc.BitDepthLumaMinus8 = uint8(rawsps.Bit_depth_luma_minus8) - hvcc.updatePtl(rawsps.Ptl) - hvcc.updateVui(rawsps.Vui) - } + start, sc := FindStartCode(sps, 0) + sps = sps[start+int(sc):] + var rawsps H265RawSPS + rawsps.Decode(sps) + spsid := rawsps.Sps_seq_parameter_set_id + var needUpdate bool = false + i := 0 + for ; i < len(hvcc.Arrays); i++ { + arrays := hvcc.Arrays[i] + found := false + if arrays.NAL_unit_type == uint8(H265_NAL_SPS) { + j := 0 + for ; j < len(arrays.NalUnits); j++ { + if spsid != GetH265SPSId(arrays.NalUnits[j].Nalu) { + found = true + continue + } + //find the same sps nalu + if arrays.NalUnits[j].NalUnitLength == uint16(len(sps)) && bytes.Equal(arrays.NalUnits[j].Nalu, sps) { + return + } + tmpsps := make([]byte, len(sps)) + copy(tmpsps, sps) + arrays.NalUnits[j].Nalu = tmpsps + arrays.NalUnits[j].NalUnitLength = uint16(len(tmpsps)) + needUpdate = true + break + } + if j == len(arrays.NalUnits) { + nalu := &NalUnit{ + Nalu: make([]byte, len(sps)), + NalUnitLength: uint16(len(sps)), + } + copy(nalu.Nalu, sps) + arrays.NalUnits = append(arrays.NalUnits, nalu) + needUpdate = true + } + } + if found { + break + } + } + if i == len(hvcc.Arrays) { + nua := &HVCCNALUnitArray{ + Array_completeness: 1, + NAL_unit_type: 33, + NumNalus: 1, + NalUnits: make([]*NalUnit, 1), + } + nu := &NalUnit{ + NalUnitLength: uint16(len(sps)), + Nalu: make([]byte, len(sps)), + } + copy(nu.Nalu, sps) + nua.NalUnits[0] = nu + hvcc.Arrays = append(hvcc.Arrays, nua) + needUpdate = true + } + if needUpdate { + hvcc.NumTemporalLayers = uint8(Max(int(hvcc.NumTemporalLayers), int(rawsps.Sps_max_sub_layers_minus1+1))) + hvcc.TemporalIdNested = rawsps.Sps_temporal_id_nesting_flag + hvcc.ChromaFormat = uint8(rawsps.Chroma_format_idc) + hvcc.BitDepthChromaMinus8 = uint8(rawsps.Bit_depth_chroma_minus8) + hvcc.BitDepthLumaMinus8 = uint8(rawsps.Bit_depth_luma_minus8) + hvcc.updatePtl(rawsps.Ptl) + hvcc.updateVui(rawsps.Vui) + } } func (hvcc *HEVCRecordConfiguration) UpdatePPS(pps []byte) { - start, sc := FindStartCode(pps, 0) - pps = pps[start+int(sc):] - var rawpps H265RawPPS - rawpps.Decode(pps) - ppsid := rawpps.Pps_pic_parameter_set_id - var needUpdate bool = false - i := 0 - for ; i < len(hvcc.Arrays); i++ { - arrays := hvcc.Arrays[i] - found := false - if arrays.NAL_unit_type == uint8(H265_NAL_PPS) { - j := 0 - for ; j < len(arrays.NalUnits); j++ { - if ppsid != GetH265PPSId(arrays.NalUnits[j].Nalu) { - found = true - continue - } - //find the same sps nalu - if arrays.NalUnits[j].NalUnitLength == uint16(len(pps)) && bytes.Equal(arrays.NalUnits[j].Nalu, pps) { - return - } - tmppps := make([]byte, len(pps)) - copy(tmppps, pps) - arrays.NalUnits[j].Nalu = tmppps - arrays.NalUnits[j].NalUnitLength = uint16(len(tmppps)) - needUpdate = true - break - } - if j == len(arrays.NalUnits) { - nalu := &NalUnit{ - Nalu: make([]byte, len(pps)), - NalUnitLength: uint16(len(pps)), - } - copy(nalu.Nalu, pps) - arrays.NalUnits = append(arrays.NalUnits, nalu) - needUpdate = true - } - } - if found { - break - } - } - if i == len(hvcc.Arrays) { - nua := &HVCCNALUnitArray{ - Array_completeness: 1, - NAL_unit_type: 34, - NumNalus: 1, - NalUnits: make([]*NalUnit, 1), - } - nu := &NalUnit{ - NalUnitLength: uint16(len(pps)), - Nalu: make([]byte, len(pps)), - } - copy(nu.Nalu, pps) - nua.NalUnits[0] = nu - hvcc.Arrays = append(hvcc.Arrays, nua) - needUpdate = true - } - if needUpdate { - if rawpps.Entropy_coding_sync_enabled_flag == 1 && rawpps.Tiles_enabled_flag == 1 { - hvcc.ParallelismType = 0 - } else if rawpps.Entropy_coding_sync_enabled_flag == 1 { - hvcc.ParallelismType = 3 - } else if rawpps.Tiles_enabled_flag == 1 { - hvcc.ParallelismType = 2 - } else { - hvcc.ParallelismType = 1 - } - } + start, sc := FindStartCode(pps, 0) + pps = pps[start+int(sc):] + var rawpps H265RawPPS + rawpps.Decode(pps) + ppsid := rawpps.Pps_pic_parameter_set_id + var needUpdate bool = false + i := 0 + for ; i < len(hvcc.Arrays); i++ { + arrays := hvcc.Arrays[i] + found := false + if arrays.NAL_unit_type == uint8(H265_NAL_PPS) { + j := 0 + for ; j < len(arrays.NalUnits); j++ { + if ppsid != GetH265PPSId(arrays.NalUnits[j].Nalu) { + found = true + continue + } + //find the same sps nalu + if arrays.NalUnits[j].NalUnitLength == uint16(len(pps)) && bytes.Equal(arrays.NalUnits[j].Nalu, pps) { + return + } + tmppps := make([]byte, len(pps)) + copy(tmppps, pps) + arrays.NalUnits[j].Nalu = tmppps + arrays.NalUnits[j].NalUnitLength = uint16(len(tmppps)) + needUpdate = true + break + } + if j == len(arrays.NalUnits) { + nalu := &NalUnit{ + Nalu: make([]byte, len(pps)), + NalUnitLength: uint16(len(pps)), + } + copy(nalu.Nalu, pps) + arrays.NalUnits = append(arrays.NalUnits, nalu) + needUpdate = true + } + } + if found { + break + } + } + if i == len(hvcc.Arrays) { + nua := &HVCCNALUnitArray{ + Array_completeness: 1, + NAL_unit_type: 34, + NumNalus: 1, + NalUnits: make([]*NalUnit, 1), + } + nu := &NalUnit{ + NalUnitLength: uint16(len(pps)), + Nalu: make([]byte, len(pps)), + } + copy(nu.Nalu, pps) + nua.NalUnits[0] = nu + hvcc.Arrays = append(hvcc.Arrays, nua) + needUpdate = true + } + if needUpdate { + if rawpps.Entropy_coding_sync_enabled_flag == 1 && rawpps.Tiles_enabled_flag == 1 { + hvcc.ParallelismType = 0 + } else if rawpps.Entropy_coding_sync_enabled_flag == 1 { + hvcc.ParallelismType = 3 + } else if rawpps.Tiles_enabled_flag == 1 { + hvcc.ParallelismType = 2 + } else { + hvcc.ParallelismType = 1 + } + } } func (hvcc *HEVCRecordConfiguration) UpdateVPS(vps []byte) { - start, sc := FindStartCode(vps, 0) - vps = vps[start+int(sc):] - var rawvps VPS - rawvps.Decode(vps) - vpsid := rawvps.Vps_video_parameter_set_id - var needUpdate bool = false - i := 0 - for ; i < len(hvcc.Arrays); i++ { - arrays := hvcc.Arrays[i] - found := false - if arrays.NAL_unit_type == uint8(H265_NAL_VPS) { - found = true - j := 0 - for ; j < len(arrays.NalUnits); j++ { - if vpsid != GetVPSId(arrays.NalUnits[j].Nalu) { - found = true - continue - } - //find the same sps nalu - if arrays.NalUnits[j].NalUnitLength == uint16(len(vps)) && bytes.Equal(arrays.NalUnits[j].Nalu, vps) { - return - } - tmpvps := make([]byte, len(vps)) - copy(tmpvps, vps) - arrays.NalUnits[j].Nalu = tmpvps - arrays.NalUnits[j].NalUnitLength = uint16(len(tmpvps)) - needUpdate = true - break - } - if j == len(arrays.NalUnits) { - nalu := &NalUnit{ - Nalu: make([]byte, len(vps)), - NalUnitLength: uint16(len(vps)), - } - copy(nalu.Nalu, vps) - arrays.NalUnits = append(arrays.NalUnits, nalu) - needUpdate = true - } - } - if found { - break - } - } - if i == len(hvcc.Arrays) { - nua := &HVCCNALUnitArray{ - Array_completeness: 1, - NAL_unit_type: 32, - NumNalus: 1, - NalUnits: make([]*NalUnit, 1), - } - nu := &NalUnit{ - NalUnitLength: uint16(len(vps)), - Nalu: make([]byte, len(vps)), - } - copy(nu.Nalu, vps) - nua.NalUnits[0] = nu - hvcc.Arrays = append(hvcc.Arrays, nua) - needUpdate = true - } - if needUpdate { - hvcc.NumTemporalLayers = uint8(Max(int(hvcc.NumTemporalLayers), int(rawvps.Vps_max_layers_minus1+1))) - hvcc.updatePtl(rawvps.Ptl) - } + start, sc := FindStartCode(vps, 0) + vps = vps[start+int(sc):] + var rawvps VPS + rawvps.Decode(vps) + vpsid := rawvps.Vps_video_parameter_set_id + var needUpdate bool = false + i := 0 + for ; i < len(hvcc.Arrays); i++ { + arrays := hvcc.Arrays[i] + found := false + if arrays.NAL_unit_type == uint8(H265_NAL_VPS) { + found = true + j := 0 + for ; j < len(arrays.NalUnits); j++ { + if vpsid != GetVPSId(arrays.NalUnits[j].Nalu) { + found = true + continue + } + //find the same sps nalu + if arrays.NalUnits[j].NalUnitLength == uint16(len(vps)) && bytes.Equal(arrays.NalUnits[j].Nalu, vps) { + return + } + tmpvps := make([]byte, len(vps)) + copy(tmpvps, vps) + arrays.NalUnits[j].Nalu = tmpvps + arrays.NalUnits[j].NalUnitLength = uint16(len(tmpvps)) + needUpdate = true + break + } + if j == len(arrays.NalUnits) { + nalu := &NalUnit{ + Nalu: make([]byte, len(vps)), + NalUnitLength: uint16(len(vps)), + } + copy(nalu.Nalu, vps) + arrays.NalUnits = append(arrays.NalUnits, nalu) + needUpdate = true + } + } + if found { + break + } + } + if i == len(hvcc.Arrays) { + nua := &HVCCNALUnitArray{ + Array_completeness: 1, + NAL_unit_type: 32, + NumNalus: 1, + NalUnits: make([]*NalUnit, 1), + } + nu := &NalUnit{ + NalUnitLength: uint16(len(vps)), + Nalu: make([]byte, len(vps)), + } + copy(nu.Nalu, vps) + nua.NalUnits[0] = nu + hvcc.Arrays = append(hvcc.Arrays, nua) + needUpdate = true + } + if needUpdate { + hvcc.NumTemporalLayers = uint8(Max(int(hvcc.NumTemporalLayers), int(rawvps.Vps_max_layers_minus1+1))) + hvcc.updatePtl(rawvps.Ptl) + } } func (hvcc *HEVCRecordConfiguration) ToNalus() (nalus []byte) { - startcode := []byte{0x00, 0x00, 0x00, 0x01} - for _, arrays := range hvcc.Arrays { - for _, unit := range arrays.NalUnits { - nalus = append(nalus, startcode...) - nalus = append(nalus, unit.Nalu[:unit.NalUnitLength]...) - } - } - return + startcode := []byte{0x00, 0x00, 0x00, 0x01} + for _, arrays := range hvcc.Arrays { + for _, unit := range arrays.NalUnits { + nalus = append(nalus, startcode...) + nalus = append(nalus, unit.Nalu[:unit.NalUnitLength]...) + } + } + return } func (hvcc *HEVCRecordConfiguration) updatePtl(ptl ProfileTierLevel) { - hvcc.General_profile_space = ptl.General_profile_space - if hvcc.General_tier_flag < ptl.General_tier_flag { - hvcc.General_level_idc = ptl.General_level_idc - } else { - hvcc.General_level_idc = uint8(Max(int(hvcc.General_level_idc), int(ptl.General_level_idc))) - } - hvcc.General_tier_flag = uint8(Max(int(hvcc.General_tier_flag), int(ptl.General_tier_flag))) - hvcc.General_profile_idc = uint8(Max(int(hvcc.General_profile_idc), int(ptl.General_profile_idc))) - hvcc.General_profile_compatibility_flags &= ptl.General_profile_compatibility_flag - hvcc.General_constraint_indicator_flags &= ptl.General_constraint_indicator_flag + hvcc.General_profile_space = ptl.General_profile_space + if hvcc.General_tier_flag < ptl.General_tier_flag { + hvcc.General_level_idc = ptl.General_level_idc + } else { + hvcc.General_level_idc = uint8(Max(int(hvcc.General_level_idc), int(ptl.General_level_idc))) + } + hvcc.General_tier_flag = uint8(Max(int(hvcc.General_tier_flag), int(ptl.General_tier_flag))) + hvcc.General_profile_idc = uint8(Max(int(hvcc.General_profile_idc), int(ptl.General_profile_idc))) + hvcc.General_profile_compatibility_flags &= ptl.General_profile_compatibility_flag + hvcc.General_constraint_indicator_flags &= ptl.General_constraint_indicator_flag } func (hvcc *HEVCRecordConfiguration) updateVui(vui VUI_Parameters) { - hvcc.Min_spatial_segmentation_idc = uint16(Min(int(hvcc.Min_spatial_segmentation_idc), int(vui.Min_spatial_segmentation_idc))) + hvcc.Min_spatial_segmentation_idc = uint16(Min(int(hvcc.Min_spatial_segmentation_idc), int(vui.Min_spatial_segmentation_idc))) } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/codec/opus.go b/trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/codec/opus.go index f07b360cb..170bc52ab 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/codec/opus.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/codec/opus.go @@ -1,8 +1,8 @@ package codec import ( - "encoding/binary" - "errors" + "encoding/binary" + "errors" ) // rfc6716 https://datatracker.ietf.org/doc/html/rfc6716 @@ -157,169 +157,169 @@ import ( // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ var ( - /// 10ms,20ms,40ms,60ms, samplerate 48000 - // sample num per millisecond - // 48000 / 1000ms * 10 = 480 ... - SLKOpusSampleSize [4]int = [4]int{480, 960, 1920, 2880} - HybridOpusSampleSize [4]int = [4]int{480, 960} - CELTOpusSampleSize [4]int = [4]int{120, 210, 480, 960} + /// 10ms,20ms,40ms,60ms, samplerate 48000 + // sample num per millisecond + // 48000 / 1000ms * 10 = 480 ... + SLKOpusSampleSize [4]int = [4]int{480, 960, 1920, 2880} + HybridOpusSampleSize [4]int = [4]int{480, 960} + CELTOpusSampleSize [4]int = [4]int{120, 210, 480, 960} ) func OpusPacketDuration(packet []byte) uint64 { - config := int(packet[0] >> 3) - code := packet[0] & 0x03 - frameCount := 0 - var duration uint64 - if code == 0 { - frameCount = 1 - } else if code == 1 || code == 2 { - frameCount = 2 - } else if code == 3 { - frameCount = int(packet[1] & 0x1F) - } else { - panic("code must <= 3") - } + config := int(packet[0] >> 3) + code := packet[0] & 0x03 + frameCount := 0 + var duration uint64 + if code == 0 { + frameCount = 1 + } else if code == 1 || code == 2 { + frameCount = 2 + } else if code == 3 { + frameCount = int(packet[1] & 0x1F) + } else { + panic("code must <= 3") + } - switch { - case config >= 0 && config < 12: - duration = uint64(frameCount * SLKOpusSampleSize[config%4]) - case config >= 12 && config < 16: - duration = uint64(frameCount * HybridOpusSampleSize[config%2]) - case config >= 16 && config < 32: - duration = uint64(frameCount * CELTOpusSampleSize[config%4]) - default: - panic("unkown opus config") - } + switch { + case config >= 0 && config < 12: + duration = uint64(frameCount * SLKOpusSampleSize[config%4]) + case config >= 12 && config < 16: + duration = uint64(frameCount * HybridOpusSampleSize[config%2]) + case config >= 16 && config < 32: + duration = uint64(frameCount * CELTOpusSampleSize[config%4]) + default: + panic("unkown opus config") + } - return duration + return duration } //ffmpeg opus.h OpusPacket type OpusPacket struct { - Code int - Config int - Stereo int - Vbr int - FrameCount int - FrameLen []uint16 - Frame []byte - Duration uint64 + Code int + Config int + Stereo int + Vbr int + FrameCount int + FrameLen []uint16 + Frame []byte + Duration uint64 } func DecodeOpusPacket(packet []byte) *OpusPacket { - pkt := &OpusPacket{} - pkt.Code = int(packet[0] & 0x03) - pkt.Stereo = int((packet[0] >> 2) & 0x01) - pkt.Config = int(packet[0] >> 3) + pkt := &OpusPacket{} + pkt.Code = int(packet[0] & 0x03) + pkt.Stereo = int((packet[0] >> 2) & 0x01) + pkt.Config = int(packet[0] >> 3) - switch pkt.Code { - case 0: - pkt.FrameCount = 1 - pkt.FrameLen = make([]uint16, 1) - pkt.FrameLen[0] = uint16(len(packet) - 1) - pkt.Frame = packet[1:] - case 1: - pkt.FrameCount = 2 - pkt.FrameLen = make([]uint16, 1) - pkt.FrameLen[0] = uint16(len(packet)-1) / 2 - pkt.Frame = packet[1:] - case 2: - pkt.FrameCount = 2 - hdr := 1 - N1 := int(packet[1]) - if N1 >= 252 { - N1 = N1 + int(packet[2]*4) - hdr = 2 - } - pkt.FrameLen = make([]uint16, 2) - pkt.FrameLen[0] = uint16(N1) - pkt.FrameLen[1] = uint16(len(packet)-hdr) - uint16(N1) - case 3: - hdr := 2 - pkt.Vbr = int(packet[1] >> 7) - padding := packet[1] >> 6 - pkt.FrameCount = int(packet[1] & 0x1F) - paddingLen := 0 - if padding == 1 { - for packet[hdr] == 255 { - paddingLen += 254 - hdr++ - } - paddingLen += int(packet[hdr]) - } + switch pkt.Code { + case 0: + pkt.FrameCount = 1 + pkt.FrameLen = make([]uint16, 1) + pkt.FrameLen[0] = uint16(len(packet) - 1) + pkt.Frame = packet[1:] + case 1: + pkt.FrameCount = 2 + pkt.FrameLen = make([]uint16, 1) + pkt.FrameLen[0] = uint16(len(packet)-1) / 2 + pkt.Frame = packet[1:] + case 2: + pkt.FrameCount = 2 + hdr := 1 + N1 := int(packet[1]) + if N1 >= 252 { + N1 = N1 + int(packet[2]*4) + hdr = 2 + } + pkt.FrameLen = make([]uint16, 2) + pkt.FrameLen[0] = uint16(N1) + pkt.FrameLen[1] = uint16(len(packet)-hdr) - uint16(N1) + case 3: + hdr := 2 + pkt.Vbr = int(packet[1] >> 7) + padding := packet[1] >> 6 + pkt.FrameCount = int(packet[1] & 0x1F) + paddingLen := 0 + if padding == 1 { + for packet[hdr] == 255 { + paddingLen += 254 + hdr++ + } + paddingLen += int(packet[hdr]) + } - if pkt.Vbr == 0 { - pkt.FrameLen = make([]uint16, 1) - pkt.FrameLen[0] = uint16(len(packet)-hdr-paddingLen) / uint16(pkt.FrameCount) - pkt.Frame = packet[hdr : hdr+int(pkt.FrameLen[0]*uint16(pkt.FrameCount))] - } else { - n := 0 - for i := 0; i < int(pkt.FrameCount)-1; i++ { - N1 := int(packet[hdr]) - hdr += 1 - if N1 >= 252 { - N1 = N1 + int(packet[hdr]*4) - hdr += 1 - } - n += N1 - pkt.FrameLen = append(pkt.FrameLen, uint16(N1)) - } - lastFrameLen := len(packet) - hdr - paddingLen - n - pkt.FrameLen = append(pkt.FrameLen, uint16(lastFrameLen)) - pkt.Frame = packet[hdr : hdr+n+lastFrameLen] - } - default: - panic("Error C must <= 3") - } - OpusPacketDuration(packet) - return pkt + if pkt.Vbr == 0 { + pkt.FrameLen = make([]uint16, 1) + pkt.FrameLen[0] = uint16(len(packet)-hdr-paddingLen) / uint16(pkt.FrameCount) + pkt.Frame = packet[hdr : hdr+int(pkt.FrameLen[0]*uint16(pkt.FrameCount))] + } else { + n := 0 + for i := 0; i < int(pkt.FrameCount)-1; i++ { + N1 := int(packet[hdr]) + hdr += 1 + if N1 >= 252 { + N1 = N1 + int(packet[hdr]*4) + hdr += 1 + } + n += N1 + pkt.FrameLen = append(pkt.FrameLen, uint16(N1)) + } + lastFrameLen := len(packet) - hdr - paddingLen - n + pkt.FrameLen = append(pkt.FrameLen, uint16(lastFrameLen)) + pkt.Frame = packet[hdr : hdr+n+lastFrameLen] + } + default: + panic("Error C must <= 3") + } + OpusPacketDuration(packet) + return pkt } const ( - LEFT_CHANNEL = 0 - RIGHT_CHANNEL = 1 + LEFT_CHANNEL = 0 + RIGHT_CHANNEL = 1 ) var ( - vorbisChanLayoutOffset [8][8]byte = [8][8]byte{ - {0}, - {0, 1}, - {0, 2, 1}, - {0, 1, 2, 3}, - {0, 2, 1, 3, 4}, - {0, 2, 1, 5, 3, 4}, - {0, 2, 1, 6, 5, 3, 4}, - {0, 2, 1, 7, 5, 6, 3, 4}, - } + vorbisChanLayoutOffset [8][8]byte = [8][8]byte{ + {0}, + {0, 1}, + {0, 2, 1}, + {0, 1, 2, 3}, + {0, 2, 1, 3, 4}, + {0, 2, 1, 5, 3, 4}, + {0, 2, 1, 6, 5, 3, 4}, + {0, 2, 1, 7, 5, 6, 3, 4}, + } ) type ChannelOrder func(channels int, idx int) int func defalutOrder(channels int, idx int) int { - return idx + return idx } func vorbisOrder(channels int, idx int) int { - return int(vorbisChanLayoutOffset[channels-1][idx]) + return int(vorbisChanLayoutOffset[channels-1][idx]) } type ChannelMap struct { - StreamIdx int - ChannelIdx int - Silence bool - Copy bool - CopyFrom int + StreamIdx int + ChannelIdx int + Silence bool + Copy bool + CopyFrom int } type OpusContext struct { - Preskip int - SampleRate int - ChannelCount int - StreamCount int - StereoStreamCount int - OutputGain uint16 - MapType uint8 - ChannelMaps []ChannelMap + Preskip int + SampleRate int + ChannelCount int + StreamCount int + StereoStreamCount int + OutputGain uint16 + MapType uint8 + ChannelMaps []ChannelMap } // opus ID Head @@ -348,83 +348,83 @@ type OpusContext struct { // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // func (ctx *OpusContext) ParseExtranData(extraData []byte) error { - if string(extraData[0:8]) != "OpusHead" { - return errors.New("magic signature must equal OpusHead") - } + if string(extraData[0:8]) != "OpusHead" { + return errors.New("magic signature must equal OpusHead") + } - _ = extraData[8] // version - ctx.ChannelCount = int(extraData[9]) - ctx.Preskip = int(binary.LittleEndian.Uint16(extraData[10:])) - ctx.SampleRate = int(binary.LittleEndian.Uint32(extraData[12:])) - ctx.OutputGain = binary.LittleEndian.Uint16(extraData[16:]) - ctx.MapType = extraData[18] - var channel []byte - var order ChannelOrder - if ctx.MapType == 0 { - ctx.StreamCount = 1 - ctx.StereoStreamCount = ctx.ChannelCount - 1 - channel = []byte{0, 1} - order = defalutOrder - } else if ctx.MapType == 1 || ctx.MapType == 2 || ctx.MapType == 255 { - ctx.StreamCount = int(extraData[19]) - ctx.StereoStreamCount = int(extraData[20]) - if ctx.MapType == 1 { - channel = extraData[21 : 21+ctx.ChannelCount] - order = vorbisOrder - } - } else { - return errors.New("unsupport map type 255") - } + _ = extraData[8] // version + ctx.ChannelCount = int(extraData[9]) + ctx.Preskip = int(binary.LittleEndian.Uint16(extraData[10:])) + ctx.SampleRate = int(binary.LittleEndian.Uint32(extraData[12:])) + ctx.OutputGain = binary.LittleEndian.Uint16(extraData[16:]) + ctx.MapType = extraData[18] + var channel []byte + var order ChannelOrder + if ctx.MapType == 0 { + ctx.StreamCount = 1 + ctx.StereoStreamCount = ctx.ChannelCount - 1 + channel = []byte{0, 1} + order = defalutOrder + } else if ctx.MapType == 1 || ctx.MapType == 2 || ctx.MapType == 255 { + ctx.StreamCount = int(extraData[19]) + ctx.StereoStreamCount = int(extraData[20]) + if ctx.MapType == 1 { + channel = extraData[21 : 21+ctx.ChannelCount] + order = vorbisOrder + } + } else { + return errors.New("unsupport map type 255") + } - for i := 0; i < ctx.ChannelCount; i++ { - cm := ChannelMap{} - index := channel[order(ctx.ChannelCount, i)] - if index == 255 { - cm.Silence = true - continue - } else if index > byte(ctx.StereoStreamCount)+byte(ctx.StreamCount) { - return errors.New("index must < (streamcount + stereo streamcount)") - } + for i := 0; i < ctx.ChannelCount; i++ { + cm := ChannelMap{} + index := channel[order(ctx.ChannelCount, i)] + if index == 255 { + cm.Silence = true + continue + } else if index > byte(ctx.StereoStreamCount)+byte(ctx.StreamCount) { + return errors.New("index must < (streamcount + stereo streamcount)") + } - for j := 0; j < i; j++ { - if channel[order(ctx.ChannelCount, i)] == index { - cm.Copy = true - cm.CopyFrom = j - break - } - } + for j := 0; j < i; j++ { + if channel[order(ctx.ChannelCount, i)] == index { + cm.Copy = true + cm.CopyFrom = j + break + } + } - if int(index) < 2*ctx.StereoStreamCount { - cm.StreamIdx = int(index) / 2 - if index&1 == 0 { - cm.ChannelIdx = LEFT_CHANNEL - } else { - cm.ChannelIdx = RIGHT_CHANNEL - } - } else { - cm.StreamIdx = int(index) - ctx.StereoStreamCount - cm.ChannelIdx = 0 - } - ctx.ChannelMaps = append(ctx.ChannelMaps, cm) - } + if int(index) < 2*ctx.StereoStreamCount { + cm.StreamIdx = int(index) / 2 + if index&1 == 0 { + cm.ChannelIdx = LEFT_CHANNEL + } else { + cm.ChannelIdx = RIGHT_CHANNEL + } + } else { + cm.StreamIdx = int(index) - ctx.StereoStreamCount + cm.ChannelIdx = 0 + } + ctx.ChannelMaps = append(ctx.ChannelMaps, cm) + } - return nil + return nil } func (ctx *OpusContext) WriteOpusExtraData() []byte { - extraData := make([]byte, 19) - copy(extraData, string("OpusHead")) - extraData[8] = 0x01 - extraData[9] = byte(ctx.ChannelCount) - binary.LittleEndian.PutUint16(extraData[10:], uint16(ctx.Preskip)) - binary.LittleEndian.PutUint32(extraData[12:], uint32(ctx.SampleRate)) - return extraData + extraData := make([]byte, 19) + copy(extraData, string("OpusHead")) + extraData[8] = 0x01 + extraData[9] = byte(ctx.ChannelCount) + binary.LittleEndian.PutUint16(extraData[10:], uint16(ctx.Preskip)) + binary.LittleEndian.PutUint32(extraData[12:], uint32(ctx.SampleRate)) + return extraData } func WriteDefaultOpusExtraData() []byte { - return []byte{ - 'O', 'p', 'u', 's', 'H', 'e', 'a', 'd', - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - } + return []byte{ + 'O', 'p', 'u', 's', 'H', 'e', 'a', 'd', + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + } } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/codec/util.go b/trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/codec/util.go index 5eec7e3eb..3d6b69a1c 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/codec/util.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/codec/util.go @@ -5,253 +5,253 @@ import "fmt" type START_CODE_TYPE int const ( - START_CODE_3 START_CODE_TYPE = 3 - START_CODE_4 = 4 + START_CODE_3 START_CODE_TYPE = 3 + START_CODE_4 = 4 ) func FindStartCode(nalu []byte, offset int) (int, START_CODE_TYPE) { - for i := offset; i < len(nalu)-4; i++ { - if nalu[i] == 0x00 && nalu[i+1] == 0x00 { - if nalu[i+2] == 0x01 { - return i, START_CODE_3 - } else if nalu[i+2] == 0x00 && nalu[i+3] == 0x01 { - return i, START_CODE_4 - } - } - } - return -1, START_CODE_3 + for i := offset; i < len(nalu)-4; i++ { + if nalu[i] == 0x00 && nalu[i+1] == 0x00 { + if nalu[i+2] == 0x01 { + return i, START_CODE_3 + } else if nalu[i+2] == 0x00 && nalu[i+3] == 0x01 { + return i, START_CODE_4 + } + } + } + return -1, START_CODE_3 } func FindSyncword(aac []byte, offset int) int { - for i := offset; i < len(aac); i++ { - if aac[i] == 0xFF && aac[i+1]&0xF0 == 0xF0 { - return i - } - } - return -1 + for i := offset; i < len(aac); i++ { + if aac[i] == 0xFF && aac[i+1]&0xF0 == 0xF0 { + return i + } + } + return -1 } func SplitFrame(frames []byte, onFrame func(nalu []byte) bool) { - beg, sc := FindStartCode(frames, 0) - for beg >= 0 { - end, sc2 := FindStartCode(frames, beg+int(sc)) - if end == -1 { - if onFrame != nil { - onFrame(frames[beg+int(sc):]) - } - break - } - if onFrame != nil && onFrame(frames[beg+int(sc):end]) == false { - break - } - beg = end - sc = sc2 - } + beg, sc := FindStartCode(frames, 0) + for beg >= 0 { + end, sc2 := FindStartCode(frames, beg+int(sc)) + if end == -1 { + if onFrame != nil { + onFrame(frames[beg+int(sc):]) + } + break + } + if onFrame != nil && onFrame(frames[beg+int(sc):end]) == false { + break + } + beg = end + sc = sc2 + } } func SplitFrameWithStartCode(frames []byte, onFrame func(nalu []byte) bool) { - beg, sc := FindStartCode(frames, 0) - for beg >= 0 { - end, sc2 := FindStartCode(frames, beg+int(sc)) - if end == -1 { - if onFrame != nil { - onFrame(frames[beg:]) - } - break - } - if onFrame != nil && onFrame(frames[beg:end]) == false { - break - } - beg = end - sc = sc2 - } + beg, sc := FindStartCode(frames, 0) + for beg >= 0 { + end, sc2 := FindStartCode(frames, beg+int(sc)) + if end == -1 { + if onFrame != nil { + onFrame(frames[beg:]) + } + break + } + if onFrame != nil && onFrame(frames[beg:end]) == false { + break + } + beg = end + sc = sc2 + } } func SplitAACFrame(frames []byte, onFrame func(aac []byte)) { - var adts ADTS_Frame_Header - start := FindSyncword(frames, 0) - for start >= 0 { - adts.Decode(frames[start:]) - onFrame(frames[start : start+int(adts.Variable_Header.Frame_length)]) - start = FindSyncword(frames, start+int(adts.Variable_Header.Frame_length)) - } + var adts ADTS_Frame_Header + start := FindSyncword(frames, 0) + for start >= 0 { + adts.Decode(frames[start:]) + onFrame(frames[start : start+int(adts.Variable_Header.Frame_length)]) + start = FindSyncword(frames, start+int(adts.Variable_Header.Frame_length)) + } } func H264NaluType(h264 []byte) H264_NAL_TYPE { - loc, sc := FindStartCode(h264, 0) - return H264_NAL_TYPE(h264[loc+int(sc)] & 0x1F) + loc, sc := FindStartCode(h264, 0) + return H264_NAL_TYPE(h264[loc+int(sc)] & 0x1F) } func H264NaluTypeWithoutStartCode(h264 []byte) H264_NAL_TYPE { - return H264_NAL_TYPE(h264[0] & 0x1F) + return H264_NAL_TYPE(h264[0] & 0x1F) } func H265NaluType(h265 []byte) H265_NAL_TYPE { - loc, sc := FindStartCode(h265, 0) - return H265_NAL_TYPE((h265[loc+int(sc)] >> 1) & 0x3F) + loc, sc := FindStartCode(h265, 0) + return H265_NAL_TYPE((h265[loc+int(sc)] >> 1) & 0x3F) } func H265NaluTypeWithoutStartCode(h265 []byte) H265_NAL_TYPE { - return H265_NAL_TYPE((h265[0] >> 1) & 0x3F) + return H265_NAL_TYPE((h265[0] >> 1) & 0x3F) } func GetH264FirstMbInSlice(nalu []byte) uint64 { - start, sc := FindStartCode(nalu, 0) - bs := NewBitStream(nalu[start+int(sc)+1:]) - sliceHdr := &SliceHeader{} - sliceHdr.Decode(bs) - return sliceHdr.First_mb_in_slice + start, sc := FindStartCode(nalu, 0) + bs := NewBitStream(nalu[start+int(sc)+1:]) + sliceHdr := &SliceHeader{} + sliceHdr.Decode(bs) + return sliceHdr.First_mb_in_slice } func GetH265FirstMbInSlice(nalu []byte) uint64 { - start, sc := FindStartCode(nalu, 0) - bs := NewBitStream(nalu[start+int(sc)+2:]) - sliceHdr := &SliceHeader{} - sliceHdr.Decode(bs) - return sliceHdr.First_mb_in_slice + start, sc := FindStartCode(nalu, 0) + bs := NewBitStream(nalu[start+int(sc)+2:]) + sliceHdr := &SliceHeader{} + sliceHdr.Decode(bs) + return sliceHdr.First_mb_in_slice } func IsH264IDRFrame(h264 []byte) bool { - ret := false - onnalu := func(nalu []byte) bool { - nal_type := H264NaluTypeWithoutStartCode(nalu) - if nal_type < 5 { - return false - } else if nal_type == 5 { - ret = true - return false - } else { - return true - } - } - SplitFrame(h264, onnalu) - return ret + ret := false + onnalu := func(nalu []byte) bool { + nal_type := H264NaluTypeWithoutStartCode(nalu) + if nal_type < 5 { + return false + } else if nal_type == 5 { + ret = true + return false + } else { + return true + } + } + SplitFrame(h264, onnalu) + return ret } func IsH264VCLNaluType(nal_type H264_NAL_TYPE) bool { - if nal_type <= H264_NAL_I_SLICE && nal_type > H264_NAL_RESERVED { - return true - } - return false + if nal_type <= H264_NAL_I_SLICE && nal_type > H264_NAL_RESERVED { + return true + } + return false } func IsH265VCLNaluType(nal_type H265_NAL_TYPE) bool { - if (nal_type <= H265_NAL_SLICE_CRA && nal_type >= H265_NAL_SLICE_BLA_W_LP) || - (nal_type <= H265_NAL_SLICE_RASL_R && nal_type >= H265_NAL_Slice_TRAIL_N) { - return true - } - return false + if (nal_type <= H265_NAL_SLICE_CRA && nal_type >= H265_NAL_SLICE_BLA_W_LP) || + (nal_type <= H265_NAL_SLICE_RASL_R && nal_type >= H265_NAL_Slice_TRAIL_N) { + return true + } + return false } func IsH265IDRFrame(h265 []byte) bool { - ret := false - onnalu := func(nalu []byte) bool { - nal_type := H264NaluTypeWithoutStartCode(nalu) - if nal_type <= 9 && nal_type >= 0 { - return false - } else if nal_type >= 16 && nal_type <= 21 { - ret = true - return false - } else { - return true - } - } - SplitFrame(h265, onnalu) - return ret + ret := false + onnalu := func(nalu []byte) bool { + nal_type := H264NaluTypeWithoutStartCode(nalu) + if nal_type <= 9 && nal_type >= 0 { + return false + } else if nal_type >= 16 && nal_type <= 21 { + ret = true + return false + } else { + return true + } + } + SplitFrame(h265, onnalu) + return ret } func Max(x, y int) int { - if x > y { - return x - } else { - return y - } + if x > y { + return x + } else { + return y + } } func Min(x, y int) int { - if x > y { - return y - } else { - return x - } + if x > y { + return y + } else { + return x + } } func ShowPacketHexdump(data []byte) { - for k := 0; k < len(data); k++ { - if k%8 == 0 && k != 0 { - fmt.Printf("\n") - } - fmt.Printf("%02x ", data[k]) - } - fmt.Printf("\n") + for k := 0; k < len(data); k++ { + if k%8 == 0 && k != 0 { + fmt.Printf("\n") + } + fmt.Printf("%02x ", data[k]) + } + fmt.Printf("\n") } var crc32table [256]uint32 = [256]uint32{ - 0x00000000, 0xB71DC104, 0x6E3B8209, 0xD926430D, 0xDC760413, 0x6B6BC517, - 0xB24D861A, 0x0550471E, 0xB8ED0826, 0x0FF0C922, 0xD6D68A2F, 0x61CB4B2B, - 0x649B0C35, 0xD386CD31, 0x0AA08E3C, 0xBDBD4F38, 0x70DB114C, 0xC7C6D048, - 0x1EE09345, 0xA9FD5241, 0xACAD155F, 0x1BB0D45B, 0xC2969756, 0x758B5652, - 0xC836196A, 0x7F2BD86E, 0xA60D9B63, 0x11105A67, 0x14401D79, 0xA35DDC7D, - 0x7A7B9F70, 0xCD665E74, 0xE0B62398, 0x57ABE29C, 0x8E8DA191, 0x39906095, - 0x3CC0278B, 0x8BDDE68F, 0x52FBA582, 0xE5E66486, 0x585B2BBE, 0xEF46EABA, - 0x3660A9B7, 0x817D68B3, 0x842D2FAD, 0x3330EEA9, 0xEA16ADA4, 0x5D0B6CA0, - 0x906D32D4, 0x2770F3D0, 0xFE56B0DD, 0x494B71D9, 0x4C1B36C7, 0xFB06F7C3, - 0x2220B4CE, 0x953D75CA, 0x28803AF2, 0x9F9DFBF6, 0x46BBB8FB, 0xF1A679FF, - 0xF4F63EE1, 0x43EBFFE5, 0x9ACDBCE8, 0x2DD07DEC, 0x77708634, 0xC06D4730, - 0x194B043D, 0xAE56C539, 0xAB068227, 0x1C1B4323, 0xC53D002E, 0x7220C12A, - 0xCF9D8E12, 0x78804F16, 0xA1A60C1B, 0x16BBCD1F, 0x13EB8A01, 0xA4F64B05, - 0x7DD00808, 0xCACDC90C, 0x07AB9778, 0xB0B6567C, 0x69901571, 0xDE8DD475, - 0xDBDD936B, 0x6CC0526F, 0xB5E61162, 0x02FBD066, 0xBF469F5E, 0x085B5E5A, - 0xD17D1D57, 0x6660DC53, 0x63309B4D, 0xD42D5A49, 0x0D0B1944, 0xBA16D840, - 0x97C6A5AC, 0x20DB64A8, 0xF9FD27A5, 0x4EE0E6A1, 0x4BB0A1BF, 0xFCAD60BB, - 0x258B23B6, 0x9296E2B2, 0x2F2BAD8A, 0x98366C8E, 0x41102F83, 0xF60DEE87, - 0xF35DA999, 0x4440689D, 0x9D662B90, 0x2A7BEA94, 0xE71DB4E0, 0x500075E4, - 0x892636E9, 0x3E3BF7ED, 0x3B6BB0F3, 0x8C7671F7, 0x555032FA, 0xE24DF3FE, - 0x5FF0BCC6, 0xE8ED7DC2, 0x31CB3ECF, 0x86D6FFCB, 0x8386B8D5, 0x349B79D1, - 0xEDBD3ADC, 0x5AA0FBD8, 0xEEE00C69, 0x59FDCD6D, 0x80DB8E60, 0x37C64F64, - 0x3296087A, 0x858BC97E, 0x5CAD8A73, 0xEBB04B77, 0x560D044F, 0xE110C54B, - 0x38368646, 0x8F2B4742, 0x8A7B005C, 0x3D66C158, 0xE4408255, 0x535D4351, - 0x9E3B1D25, 0x2926DC21, 0xF0009F2C, 0x471D5E28, 0x424D1936, 0xF550D832, - 0x2C769B3F, 0x9B6B5A3B, 0x26D61503, 0x91CBD407, 0x48ED970A, 0xFFF0560E, - 0xFAA01110, 0x4DBDD014, 0x949B9319, 0x2386521D, 0x0E562FF1, 0xB94BEEF5, - 0x606DADF8, 0xD7706CFC, 0xD2202BE2, 0x653DEAE6, 0xBC1BA9EB, 0x0B0668EF, - 0xB6BB27D7, 0x01A6E6D3, 0xD880A5DE, 0x6F9D64DA, 0x6ACD23C4, 0xDDD0E2C0, - 0x04F6A1CD, 0xB3EB60C9, 0x7E8D3EBD, 0xC990FFB9, 0x10B6BCB4, 0xA7AB7DB0, - 0xA2FB3AAE, 0x15E6FBAA, 0xCCC0B8A7, 0x7BDD79A3, 0xC660369B, 0x717DF79F, - 0xA85BB492, 0x1F467596, 0x1A163288, 0xAD0BF38C, 0x742DB081, 0xC3307185, - 0x99908A5D, 0x2E8D4B59, 0xF7AB0854, 0x40B6C950, 0x45E68E4E, 0xF2FB4F4A, - 0x2BDD0C47, 0x9CC0CD43, 0x217D827B, 0x9660437F, 0x4F460072, 0xF85BC176, - 0xFD0B8668, 0x4A16476C, 0x93300461, 0x242DC565, 0xE94B9B11, 0x5E565A15, - 0x87701918, 0x306DD81C, 0x353D9F02, 0x82205E06, 0x5B061D0B, 0xEC1BDC0F, - 0x51A69337, 0xE6BB5233, 0x3F9D113E, 0x8880D03A, 0x8DD09724, 0x3ACD5620, - 0xE3EB152D, 0x54F6D429, 0x7926A9C5, 0xCE3B68C1, 0x171D2BCC, 0xA000EAC8, - 0xA550ADD6, 0x124D6CD2, 0xCB6B2FDF, 0x7C76EEDB, 0xC1CBA1E3, 0x76D660E7, - 0xAFF023EA, 0x18EDE2EE, 0x1DBDA5F0, 0xAAA064F4, 0x738627F9, 0xC49BE6FD, - 0x09FDB889, 0xBEE0798D, 0x67C63A80, 0xD0DBFB84, 0xD58BBC9A, 0x62967D9E, - 0xBBB03E93, 0x0CADFF97, 0xB110B0AF, 0x060D71AB, 0xDF2B32A6, 0x6836F3A2, - 0x6D66B4BC, 0xDA7B75B8, 0x035D36B5, 0xB440F7B1, + 0x00000000, 0xB71DC104, 0x6E3B8209, 0xD926430D, 0xDC760413, 0x6B6BC517, + 0xB24D861A, 0x0550471E, 0xB8ED0826, 0x0FF0C922, 0xD6D68A2F, 0x61CB4B2B, + 0x649B0C35, 0xD386CD31, 0x0AA08E3C, 0xBDBD4F38, 0x70DB114C, 0xC7C6D048, + 0x1EE09345, 0xA9FD5241, 0xACAD155F, 0x1BB0D45B, 0xC2969756, 0x758B5652, + 0xC836196A, 0x7F2BD86E, 0xA60D9B63, 0x11105A67, 0x14401D79, 0xA35DDC7D, + 0x7A7B9F70, 0xCD665E74, 0xE0B62398, 0x57ABE29C, 0x8E8DA191, 0x39906095, + 0x3CC0278B, 0x8BDDE68F, 0x52FBA582, 0xE5E66486, 0x585B2BBE, 0xEF46EABA, + 0x3660A9B7, 0x817D68B3, 0x842D2FAD, 0x3330EEA9, 0xEA16ADA4, 0x5D0B6CA0, + 0x906D32D4, 0x2770F3D0, 0xFE56B0DD, 0x494B71D9, 0x4C1B36C7, 0xFB06F7C3, + 0x2220B4CE, 0x953D75CA, 0x28803AF2, 0x9F9DFBF6, 0x46BBB8FB, 0xF1A679FF, + 0xF4F63EE1, 0x43EBFFE5, 0x9ACDBCE8, 0x2DD07DEC, 0x77708634, 0xC06D4730, + 0x194B043D, 0xAE56C539, 0xAB068227, 0x1C1B4323, 0xC53D002E, 0x7220C12A, + 0xCF9D8E12, 0x78804F16, 0xA1A60C1B, 0x16BBCD1F, 0x13EB8A01, 0xA4F64B05, + 0x7DD00808, 0xCACDC90C, 0x07AB9778, 0xB0B6567C, 0x69901571, 0xDE8DD475, + 0xDBDD936B, 0x6CC0526F, 0xB5E61162, 0x02FBD066, 0xBF469F5E, 0x085B5E5A, + 0xD17D1D57, 0x6660DC53, 0x63309B4D, 0xD42D5A49, 0x0D0B1944, 0xBA16D840, + 0x97C6A5AC, 0x20DB64A8, 0xF9FD27A5, 0x4EE0E6A1, 0x4BB0A1BF, 0xFCAD60BB, + 0x258B23B6, 0x9296E2B2, 0x2F2BAD8A, 0x98366C8E, 0x41102F83, 0xF60DEE87, + 0xF35DA999, 0x4440689D, 0x9D662B90, 0x2A7BEA94, 0xE71DB4E0, 0x500075E4, + 0x892636E9, 0x3E3BF7ED, 0x3B6BB0F3, 0x8C7671F7, 0x555032FA, 0xE24DF3FE, + 0x5FF0BCC6, 0xE8ED7DC2, 0x31CB3ECF, 0x86D6FFCB, 0x8386B8D5, 0x349B79D1, + 0xEDBD3ADC, 0x5AA0FBD8, 0xEEE00C69, 0x59FDCD6D, 0x80DB8E60, 0x37C64F64, + 0x3296087A, 0x858BC97E, 0x5CAD8A73, 0xEBB04B77, 0x560D044F, 0xE110C54B, + 0x38368646, 0x8F2B4742, 0x8A7B005C, 0x3D66C158, 0xE4408255, 0x535D4351, + 0x9E3B1D25, 0x2926DC21, 0xF0009F2C, 0x471D5E28, 0x424D1936, 0xF550D832, + 0x2C769B3F, 0x9B6B5A3B, 0x26D61503, 0x91CBD407, 0x48ED970A, 0xFFF0560E, + 0xFAA01110, 0x4DBDD014, 0x949B9319, 0x2386521D, 0x0E562FF1, 0xB94BEEF5, + 0x606DADF8, 0xD7706CFC, 0xD2202BE2, 0x653DEAE6, 0xBC1BA9EB, 0x0B0668EF, + 0xB6BB27D7, 0x01A6E6D3, 0xD880A5DE, 0x6F9D64DA, 0x6ACD23C4, 0xDDD0E2C0, + 0x04F6A1CD, 0xB3EB60C9, 0x7E8D3EBD, 0xC990FFB9, 0x10B6BCB4, 0xA7AB7DB0, + 0xA2FB3AAE, 0x15E6FBAA, 0xCCC0B8A7, 0x7BDD79A3, 0xC660369B, 0x717DF79F, + 0xA85BB492, 0x1F467596, 0x1A163288, 0xAD0BF38C, 0x742DB081, 0xC3307185, + 0x99908A5D, 0x2E8D4B59, 0xF7AB0854, 0x40B6C950, 0x45E68E4E, 0xF2FB4F4A, + 0x2BDD0C47, 0x9CC0CD43, 0x217D827B, 0x9660437F, 0x4F460072, 0xF85BC176, + 0xFD0B8668, 0x4A16476C, 0x93300461, 0x242DC565, 0xE94B9B11, 0x5E565A15, + 0x87701918, 0x306DD81C, 0x353D9F02, 0x82205E06, 0x5B061D0B, 0xEC1BDC0F, + 0x51A69337, 0xE6BB5233, 0x3F9D113E, 0x8880D03A, 0x8DD09724, 0x3ACD5620, + 0xE3EB152D, 0x54F6D429, 0x7926A9C5, 0xCE3B68C1, 0x171D2BCC, 0xA000EAC8, + 0xA550ADD6, 0x124D6CD2, 0xCB6B2FDF, 0x7C76EEDB, 0xC1CBA1E3, 0x76D660E7, + 0xAFF023EA, 0x18EDE2EE, 0x1DBDA5F0, 0xAAA064F4, 0x738627F9, 0xC49BE6FD, + 0x09FDB889, 0xBEE0798D, 0x67C63A80, 0xD0DBFB84, 0xD58BBC9A, 0x62967D9E, + 0xBBB03E93, 0x0CADFF97, 0xB110B0AF, 0x060D71AB, 0xDF2B32A6, 0x6836F3A2, + 0x6D66B4BC, 0xDA7B75B8, 0x035D36B5, 0xB440F7B1, } func CalcCrc32(crc uint32, buffer []byte) uint32 { - var i int = 0 - for i = 0; i < len(buffer); i++ { - crc = crc32table[(crc^uint32(buffer[i]))&0xff] ^ (crc >> 8) - } - return crc + var i int = 0 + for i = 0; i < len(buffer); i++ { + crc = crc32table[(crc^uint32(buffer[i]))&0xff] ^ (crc >> 8) + } + return crc } func CovertRbspToSodb(rbsp []byte) []byte { - bs := NewBitStream(rbsp) - bsw := NewBitStreamWriter(len(rbsp)) - for !bs.EOS() { - if bs.RemainBytes() > 3 && bs.NextBits(24) == 0x000003 { - bsw.PutByte(bs.Uint8(8)) - bsw.PutByte(bs.Uint8(8)) - bs.SkipBits(8) - } else { - bsw.PutByte(bs.Uint8(8)) - } - } - return bsw.Bits() + bs := NewBitStream(rbsp) + bsw := NewBitStreamWriter(len(rbsp)) + for !bs.EOS() { + if bs.RemainBytes() > 3 && bs.NextBits(24) == 0x000003 { + bsw.PutByte(bs.Uint8(8)) + bsw.PutByte(bs.Uint8(8)) + bs.SkipBits(8) + } else { + bsw.PutByte(bs.Uint8(8)) + } + } + return bsw.Bits() } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/codec/vp8.go b/trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/codec/vp8.go index 267f5521e..211e0765f 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/codec/vp8.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/codec/vp8.go @@ -3,70 +3,70 @@ package codec import "errors" type VP8FrameTag struct { - FrameType uint32 //0: I frame , 1: P frame - Version uint32 - Display uint32 - FirstPartSize uint32 + FrameType uint32 //0: I frame , 1: P frame + Version uint32 + Display uint32 + FirstPartSize uint32 } type VP8KeyFrameHead struct { - Width int - Height int - HorizScale int - VertScale int + Width int + Height int + HorizScale int + VertScale int } func DecodeFrameTag(frame []byte) (*VP8FrameTag, error) { - if len(frame) < 3 { - return nil, errors.New("frame bytes < 3") - } - var tmp uint32 = (uint32(frame[2]) << 16) | (uint32(frame[1]) << 8) | uint32(frame[0]) - tag := &VP8FrameTag{} - tag.FrameType = tmp & 0x01 - tag.Version = (tmp >> 1) & 0x07 - tag.Display = (tmp >> 4) & 0x01 - tag.FirstPartSize = (tmp >> 5) & 0x7FFFF - return tag, nil + if len(frame) < 3 { + return nil, errors.New("frame bytes < 3") + } + var tmp uint32 = (uint32(frame[2]) << 16) | (uint32(frame[1]) << 8) | uint32(frame[0]) + tag := &VP8FrameTag{} + tag.FrameType = tmp & 0x01 + tag.Version = (tmp >> 1) & 0x07 + tag.Display = (tmp >> 4) & 0x01 + tag.FirstPartSize = (tmp >> 5) & 0x7FFFF + return tag, nil } func DecodeKeyFrameHead(frame []byte) (*VP8KeyFrameHead, error) { - if len(frame) < 7 { - return nil, errors.New("frame bytes < 3") - } + if len(frame) < 7 { + return nil, errors.New("frame bytes < 3") + } - if frame[0] != 0x9d || frame[1] != 0x01 || frame[2] != 0x2a { - return nil, errors.New("not find Start code") - } + if frame[0] != 0x9d || frame[1] != 0x01 || frame[2] != 0x2a { + return nil, errors.New("not find Start code") + } - head := &VP8KeyFrameHead{} - head.Width = int(uint16(frame[4]&0x3f)<<8 | uint16(frame[3])) - head.HorizScale = int(frame[4] >> 6) - head.Height = int(uint16(frame[6]&0x3f)<<8 | uint16(frame[5])) - head.VertScale = int(frame[6] >> 6) - return head, nil + head := &VP8KeyFrameHead{} + head.Width = int(uint16(frame[4]&0x3f)<<8 | uint16(frame[3])) + head.HorizScale = int(frame[4] >> 6) + head.Height = int(uint16(frame[6]&0x3f)<<8 | uint16(frame[5])) + head.VertScale = int(frame[6] >> 6) + return head, nil } func IsKeyFrame(frame []byte) bool { - tag, err := DecodeFrameTag(frame) - if err != nil { - return false - } + tag, err := DecodeFrameTag(frame) + if err != nil { + return false + } - if tag.FrameType == 0 { - return true - } else { - return false - } + if tag.FrameType == 0 { + return true + } else { + return false + } } func GetResloution(frame []byte) (width int, height int, err error) { - if !IsKeyFrame(frame) { - return 0, 0, errors.New("the frame is not Key frame") - } + if !IsKeyFrame(frame) { + return 0, 0, errors.New("the frame is not Key frame") + } - head, err := DecodeKeyFrameHead(frame[3:]) - if err != nil { - return 0, 0, err - } - return head.Width, head.Height, nil + head, err := DecodeKeyFrameHead(frame[3:]) + if err != nil { + return 0, 0, err + } + return head.Width, head.Height, nil } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/mpeg2/pes-proto.go b/trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/mpeg2/pes-proto.go index 59c61cce6..ac8bc5037 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/mpeg2/pes-proto.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/mpeg2/pes-proto.go @@ -1,10 +1,10 @@ package mpeg2 import ( - "fmt" - "os" + "fmt" + "os" - "github.com/yapingcat/gomedia/codec" + "github.com/yapingcat/gomedia/codec" ) var H264_AUD_NALU []byte = []byte{0x00, 0x00, 0x00, 0x01, 0x09, 0xF0} //ffmpeg mpegtsenc.c mpegts_write_packet_internal @@ -13,337 +13,337 @@ var H265_AUD_NALU []byte = []byte{0x00, 0x00, 0x00, 0x01, 0x46, 0x01, 0x50} type PES_STREMA_ID int const ( - PES_STREAM_END PES_STREMA_ID = 0xB9 - PES_STREAM_START PES_STREMA_ID = 0xBA - PES_STREAM_SYSTEM_HEAD PES_STREMA_ID = 0xBB - PES_STREAM_MAP PES_STREMA_ID = 0xBC - PES_STREAM_PRIVATE PES_STREMA_ID = 0xBD - PES_STREAM_AUDIO PES_STREMA_ID = 0xC0 - PES_STREAM_VIDEO PES_STREMA_ID = 0xE0 + PES_STREAM_END PES_STREMA_ID = 0xB9 + PES_STREAM_START PES_STREMA_ID = 0xBA + PES_STREAM_SYSTEM_HEAD PES_STREMA_ID = 0xBB + PES_STREAM_MAP PES_STREMA_ID = 0xBC + PES_STREAM_PRIVATE PES_STREMA_ID = 0xBD + PES_STREAM_AUDIO PES_STREMA_ID = 0xC0 + PES_STREAM_VIDEO PES_STREMA_ID = 0xE0 ) func findPESIDByStreamType(cid TS_STREAM_TYPE) PES_STREMA_ID { - if cid == TS_STREAM_AAC { - return PES_STREAM_AUDIO - } else if cid == TS_STREAM_H264 || cid == TS_STREAM_H265 { - return PES_STREAM_VIDEO - } else { - return PES_STREAM_PRIVATE - } + if cid == TS_STREAM_AAC { + return PES_STREAM_AUDIO + } else if cid == TS_STREAM_H264 || cid == TS_STREAM_H265 { + return PES_STREAM_VIDEO + } else { + return PES_STREAM_PRIVATE + } } type PesPacket struct { - Stream_id uint8 - PES_packet_length uint16 - PES_scrambling_control uint8 - PES_priority uint8 - Data_alignment_indicator uint8 - Copyright uint8 - Original_or_copy uint8 - PTS_DTS_flags uint8 - ESCR_flag uint8 - ES_rate_flag uint8 - DSM_trick_mode_flag uint8 - Additional_copy_info_flag uint8 - PES_CRC_flag uint8 - PES_extension_flag uint8 - PES_header_data_length uint8 - Pts uint64 - Dts uint64 - ESCR_base uint64 - ESCR_extension uint16 - ES_rate uint32 - Trick_mode_control uint8 - Trick_value uint8 - Additional_copy_info uint8 - Previous_PES_packet_CRC uint16 - Pes_payload []byte - //TODO - //if ( PES_extension_flag == '1') - // PES_private_data_flag uint8 - // pack_header_field_flag uint8 - // program_packet_sequence_counter_flag uint8 - // P_STD_buffer_flag uint8 - // PES_extension_flag_2 uint8 - // PES_private_data [16]byte + Stream_id uint8 + PES_packet_length uint16 + PES_scrambling_control uint8 + PES_priority uint8 + Data_alignment_indicator uint8 + Copyright uint8 + Original_or_copy uint8 + PTS_DTS_flags uint8 + ESCR_flag uint8 + ES_rate_flag uint8 + DSM_trick_mode_flag uint8 + Additional_copy_info_flag uint8 + PES_CRC_flag uint8 + PES_extension_flag uint8 + PES_header_data_length uint8 + Pts uint64 + Dts uint64 + ESCR_base uint64 + ESCR_extension uint16 + ES_rate uint32 + Trick_mode_control uint8 + Trick_value uint8 + Additional_copy_info uint8 + Previous_PES_packet_CRC uint16 + Pes_payload []byte + //TODO + //if ( PES_extension_flag == '1') + // PES_private_data_flag uint8 + // pack_header_field_flag uint8 + // program_packet_sequence_counter_flag uint8 + // P_STD_buffer_flag uint8 + // PES_extension_flag_2 uint8 + // PES_private_data [16]byte } func NewPesPacket() *PesPacket { - return new(PesPacket) + return new(PesPacket) } func (pkg *PesPacket) PrettyPrint(file *os.File) { - file.WriteString(fmt.Sprintf("stream_id:%d\n", pkg.Stream_id)) - file.WriteString(fmt.Sprintf("PES_packet_length:%d\n", pkg.PES_packet_length)) - file.WriteString(fmt.Sprintf("PES_scrambling_control:%d\n", pkg.PES_scrambling_control)) - file.WriteString(fmt.Sprintf("PES_priority:%d\n", pkg.PES_priority)) - file.WriteString(fmt.Sprintf("data_alignment_indicator:%d\n", pkg.Data_alignment_indicator)) - file.WriteString(fmt.Sprintf("copyright:%d\n", pkg.Copyright)) - file.WriteString(fmt.Sprintf("original_or_copy:%d\n", pkg.Original_or_copy)) - file.WriteString(fmt.Sprintf("PTS_DTS_flags:%d\n", pkg.PTS_DTS_flags)) - file.WriteString(fmt.Sprintf("ESCR_flag:%d\n", pkg.ESCR_flag)) - file.WriteString(fmt.Sprintf("ES_rate_flag:%d\n", pkg.ES_rate_flag)) - file.WriteString(fmt.Sprintf("DSM_trick_mode_flag:%d\n", pkg.DSM_trick_mode_flag)) - file.WriteString(fmt.Sprintf("additional_copy_info_flag:%d\n", pkg.Additional_copy_info_flag)) - file.WriteString(fmt.Sprintf("PES_CRC_flag:%d\n", pkg.PES_CRC_flag)) - file.WriteString(fmt.Sprintf("PES_extension_flag:%d\n", pkg.PES_extension_flag)) - file.WriteString(fmt.Sprintf("PES_header_data_length:%d\n", pkg.PES_header_data_length)) - if pkg.PTS_DTS_flags&0x02 == 0x02 { - file.WriteString(fmt.Sprintf("PTS:%d\n", pkg.Pts)) - } - if pkg.PTS_DTS_flags&0x03 == 0x03 { - file.WriteString(fmt.Sprintf("DTS:%d\n", pkg.Dts)) - } + file.WriteString(fmt.Sprintf("stream_id:%d\n", pkg.Stream_id)) + file.WriteString(fmt.Sprintf("PES_packet_length:%d\n", pkg.PES_packet_length)) + file.WriteString(fmt.Sprintf("PES_scrambling_control:%d\n", pkg.PES_scrambling_control)) + file.WriteString(fmt.Sprintf("PES_priority:%d\n", pkg.PES_priority)) + file.WriteString(fmt.Sprintf("data_alignment_indicator:%d\n", pkg.Data_alignment_indicator)) + file.WriteString(fmt.Sprintf("copyright:%d\n", pkg.Copyright)) + file.WriteString(fmt.Sprintf("original_or_copy:%d\n", pkg.Original_or_copy)) + file.WriteString(fmt.Sprintf("PTS_DTS_flags:%d\n", pkg.PTS_DTS_flags)) + file.WriteString(fmt.Sprintf("ESCR_flag:%d\n", pkg.ESCR_flag)) + file.WriteString(fmt.Sprintf("ES_rate_flag:%d\n", pkg.ES_rate_flag)) + file.WriteString(fmt.Sprintf("DSM_trick_mode_flag:%d\n", pkg.DSM_trick_mode_flag)) + file.WriteString(fmt.Sprintf("additional_copy_info_flag:%d\n", pkg.Additional_copy_info_flag)) + file.WriteString(fmt.Sprintf("PES_CRC_flag:%d\n", pkg.PES_CRC_flag)) + file.WriteString(fmt.Sprintf("PES_extension_flag:%d\n", pkg.PES_extension_flag)) + file.WriteString(fmt.Sprintf("PES_header_data_length:%d\n", pkg.PES_header_data_length)) + if pkg.PTS_DTS_flags&0x02 == 0x02 { + file.WriteString(fmt.Sprintf("PTS:%d\n", pkg.Pts)) + } + if pkg.PTS_DTS_flags&0x03 == 0x03 { + file.WriteString(fmt.Sprintf("DTS:%d\n", pkg.Dts)) + } - if pkg.ESCR_flag == 1 { - file.WriteString(fmt.Sprintf("ESCR_base:%d\n", pkg.ESCR_base)) - file.WriteString(fmt.Sprintf("ESCR_extension:%d\n", pkg.ESCR_extension)) - } + if pkg.ESCR_flag == 1 { + file.WriteString(fmt.Sprintf("ESCR_base:%d\n", pkg.ESCR_base)) + file.WriteString(fmt.Sprintf("ESCR_extension:%d\n", pkg.ESCR_extension)) + } - if pkg.ES_rate_flag == 1 { - file.WriteString(fmt.Sprintf("ES_rate:%d\n", pkg.ES_rate)) - } + if pkg.ES_rate_flag == 1 { + file.WriteString(fmt.Sprintf("ES_rate:%d\n", pkg.ES_rate)) + } - if pkg.DSM_trick_mode_flag == 1 { - file.WriteString(fmt.Sprintf("trick_mode_control:%d\n", pkg.Trick_mode_control)) - } + if pkg.DSM_trick_mode_flag == 1 { + file.WriteString(fmt.Sprintf("trick_mode_control:%d\n", pkg.Trick_mode_control)) + } - if pkg.Additional_copy_info_flag == 1 { - file.WriteString(fmt.Sprintf("additional_copy_info:%d\n", pkg.Additional_copy_info)) - } + if pkg.Additional_copy_info_flag == 1 { + file.WriteString(fmt.Sprintf("additional_copy_info:%d\n", pkg.Additional_copy_info)) + } - if pkg.PES_CRC_flag == 1 { - file.WriteString(fmt.Sprintf("previous_PES_packet_CRC:%d\n", pkg.Previous_PES_packet_CRC)) - } - file.WriteString("PES_packet_data_byte:\n") - file.WriteString(fmt.Sprintf(" Size: %d\n", len(pkg.Pes_payload))) - file.WriteString(" data:") - for i := 0; i < 12 && i < len(pkg.Pes_payload); i++ { - if i%4 == 0 { - file.WriteString("\n") - file.WriteString(" ") - } - file.WriteString(fmt.Sprintf("0x%02x ", pkg.Pes_payload[i])) - } - file.WriteString("\n") + if pkg.PES_CRC_flag == 1 { + file.WriteString(fmt.Sprintf("previous_PES_packet_CRC:%d\n", pkg.Previous_PES_packet_CRC)) + } + file.WriteString("PES_packet_data_byte:\n") + file.WriteString(fmt.Sprintf(" Size: %d\n", len(pkg.Pes_payload))) + file.WriteString(" data:") + for i := 0; i < 12 && i < len(pkg.Pes_payload); i++ { + if i%4 == 0 { + file.WriteString("\n") + file.WriteString(" ") + } + file.WriteString(fmt.Sprintf("0x%02x ", pkg.Pes_payload[i])) + } + file.WriteString("\n") } func (pkg *PesPacket) Decode(bs *codec.BitStream) error { - if bs.RemainBytes() < 9 { - return errNeedMore - } - bs.SkipBits(24) //packet_start_code_prefix - pkg.Stream_id = bs.Uint8(8) //stream_id - pkg.PES_packet_length = bs.Uint16(16) - bs.SkipBits(2) //'10' - pkg.PES_scrambling_control = bs.Uint8(2) - pkg.PES_priority = bs.Uint8(1) - pkg.Data_alignment_indicator = bs.Uint8(1) - pkg.Copyright = bs.Uint8(1) - pkg.Original_or_copy = bs.Uint8(1) - pkg.PTS_DTS_flags = bs.Uint8(2) - pkg.ESCR_flag = bs.Uint8(1) - pkg.ES_rate_flag = bs.Uint8(1) - pkg.DSM_trick_mode_flag = bs.Uint8(1) - pkg.Additional_copy_info_flag = bs.Uint8(1) - pkg.PES_CRC_flag = bs.Uint8(1) - pkg.PES_extension_flag = bs.Uint8(1) - pkg.PES_header_data_length = bs.Uint8(8) - if bs.RemainBytes() < int(pkg.PES_header_data_length) { - bs.UnRead(9 * 8) - return errNeedMore - } - bs.Markdot() - if pkg.PTS_DTS_flags&0x02 == 0x02 { - bs.SkipBits(4) - pkg.Pts = bs.GetBits(3) - bs.SkipBits(1) - pkg.Pts = (pkg.Pts << 15) | bs.GetBits(15) - bs.SkipBits(1) - pkg.Pts = (pkg.Pts << 15) | bs.GetBits(15) - bs.SkipBits(1) - } - if pkg.PTS_DTS_flags&0x03 == 0x03 { - bs.SkipBits(4) - pkg.Dts = bs.GetBits(3) - bs.SkipBits(1) - pkg.Dts = (pkg.Dts << 15) | bs.GetBits(15) - bs.SkipBits(1) - pkg.Dts = (pkg.Dts << 15) | bs.GetBits(15) - bs.SkipBits(1) - } else { - pkg.Dts = pkg.Pts - } + if bs.RemainBytes() < 9 { + return errNeedMore + } + bs.SkipBits(24) //packet_start_code_prefix + pkg.Stream_id = bs.Uint8(8) //stream_id + pkg.PES_packet_length = bs.Uint16(16) + bs.SkipBits(2) //'10' + pkg.PES_scrambling_control = bs.Uint8(2) + pkg.PES_priority = bs.Uint8(1) + pkg.Data_alignment_indicator = bs.Uint8(1) + pkg.Copyright = bs.Uint8(1) + pkg.Original_or_copy = bs.Uint8(1) + pkg.PTS_DTS_flags = bs.Uint8(2) + pkg.ESCR_flag = bs.Uint8(1) + pkg.ES_rate_flag = bs.Uint8(1) + pkg.DSM_trick_mode_flag = bs.Uint8(1) + pkg.Additional_copy_info_flag = bs.Uint8(1) + pkg.PES_CRC_flag = bs.Uint8(1) + pkg.PES_extension_flag = bs.Uint8(1) + pkg.PES_header_data_length = bs.Uint8(8) + if bs.RemainBytes() < int(pkg.PES_header_data_length) { + bs.UnRead(9 * 8) + return errNeedMore + } + bs.Markdot() + if pkg.PTS_DTS_flags&0x02 == 0x02 { + bs.SkipBits(4) + pkg.Pts = bs.GetBits(3) + bs.SkipBits(1) + pkg.Pts = (pkg.Pts << 15) | bs.GetBits(15) + bs.SkipBits(1) + pkg.Pts = (pkg.Pts << 15) | bs.GetBits(15) + bs.SkipBits(1) + } + if pkg.PTS_DTS_flags&0x03 == 0x03 { + bs.SkipBits(4) + pkg.Dts = bs.GetBits(3) + bs.SkipBits(1) + pkg.Dts = (pkg.Dts << 15) | bs.GetBits(15) + bs.SkipBits(1) + pkg.Dts = (pkg.Dts << 15) | bs.GetBits(15) + bs.SkipBits(1) + } else { + pkg.Dts = pkg.Pts + } - if pkg.ESCR_flag == 1 { - bs.SkipBits(2) - pkg.ESCR_base = bs.GetBits(3) - bs.SkipBits(1) - pkg.ESCR_base = (pkg.Pts << 15) | bs.GetBits(15) - bs.SkipBits(1) - pkg.ESCR_base = (pkg.Pts << 15) | bs.GetBits(15) - bs.SkipBits(1) - pkg.ESCR_extension = bs.Uint16(9) - bs.SkipBits(1) - } + if pkg.ESCR_flag == 1 { + bs.SkipBits(2) + pkg.ESCR_base = bs.GetBits(3) + bs.SkipBits(1) + pkg.ESCR_base = (pkg.Pts << 15) | bs.GetBits(15) + bs.SkipBits(1) + pkg.ESCR_base = (pkg.Pts << 15) | bs.GetBits(15) + bs.SkipBits(1) + pkg.ESCR_extension = bs.Uint16(9) + bs.SkipBits(1) + } - if pkg.ES_rate_flag == 1 { - bs.SkipBits(1) - pkg.ES_rate = bs.Uint32(22) - bs.SkipBits(1) - } + if pkg.ES_rate_flag == 1 { + bs.SkipBits(1) + pkg.ES_rate = bs.Uint32(22) + bs.SkipBits(1) + } - if pkg.DSM_trick_mode_flag == 1 { - pkg.Trick_mode_control = bs.Uint8(3) - pkg.Trick_value = bs.Uint8(5) - } + if pkg.DSM_trick_mode_flag == 1 { + pkg.Trick_mode_control = bs.Uint8(3) + pkg.Trick_value = bs.Uint8(5) + } - if pkg.Additional_copy_info_flag == 1 { - pkg.Additional_copy_info = bs.Uint8(7) - } + if pkg.Additional_copy_info_flag == 1 { + pkg.Additional_copy_info = bs.Uint8(7) + } - if pkg.PES_CRC_flag == 1 { - pkg.Previous_PES_packet_CRC = bs.Uint16(16) - } + if pkg.PES_CRC_flag == 1 { + pkg.Previous_PES_packet_CRC = bs.Uint16(16) + } - loc := bs.DistanceFromMarkDot() - bs.SkipBits(int(pkg.PES_header_data_length)*8 - loc) // skip remaining header + loc := bs.DistanceFromMarkDot() + bs.SkipBits(int(pkg.PES_header_data_length)*8 - loc) // skip remaining header - // the -3 bytes are the combined lengths - // of all fields between PES_packet_length and PES_header_data_length (2 bytes) - // and the PES_header_data_length itself (1 byte) - dataLen := int(pkg.PES_packet_length - 3 - uint16(pkg.PES_header_data_length)) + // the -3 bytes are the combined lengths + // of all fields between PES_packet_length and PES_header_data_length (2 bytes) + // and the PES_header_data_length itself (1 byte) + dataLen := int(pkg.PES_packet_length - 3 - uint16(pkg.PES_header_data_length)) - if bs.RemainBytes() < dataLen { - pkg.Pes_payload = bs.RemainData() - bs.UnRead((9 + int(pkg.PES_header_data_length)) * 8) - return errNeedMore - } + if bs.RemainBytes() < dataLen { + pkg.Pes_payload = bs.RemainData() + bs.UnRead((9 + int(pkg.PES_header_data_length)) * 8) + return errNeedMore + } - if pkg.PES_packet_length == 0 || bs.RemainBytes() <= dataLen { - pkg.Pes_payload = bs.RemainData() - bs.SkipBits(bs.RemainBits()) - } else { - pkg.Pes_payload = bs.RemainData()[:dataLen] - bs.SkipBits(dataLen * 8) - } + if pkg.PES_packet_length == 0 || bs.RemainBytes() <= dataLen { + pkg.Pes_payload = bs.RemainData() + bs.SkipBits(bs.RemainBits()) + } else { + pkg.Pes_payload = bs.RemainData()[:dataLen] + bs.SkipBits(dataLen * 8) + } - return nil + return nil } func (pkg *PesPacket) DecodeMpeg1(bs *codec.BitStream) error { - if bs.RemainBytes() < 6 { - return errNeedMore - } - bs.SkipBits(24) //packet_start_code_prefix - pkg.Stream_id = bs.Uint8(8) //stream_id - pkg.PES_packet_length = bs.Uint16(16) - if pkg.PES_packet_length != 0 && bs.RemainBytes() < int(pkg.PES_packet_length) { - bs.UnRead(6 * 8) - return errNeedMore - } - bs.Markdot() - for bs.NextBits(8) == 0xFF { - bs.SkipBits(8) - } - if bs.NextBits(2) == 0x01 { - bs.SkipBits(16) - } - if bs.NextBits(4) == 0x02 { - bs.SkipBits(4) - pkg.Pts = bs.GetBits(3) - bs.SkipBits(1) - pkg.Pts = pkg.Pts<<15 | bs.GetBits(15) - bs.SkipBits(1) - pkg.Pts = pkg.Pts<<15 | bs.GetBits(15) - bs.SkipBits(1) - } else if bs.NextBits(4) == 0x03 { - bs.SkipBits(4) - pkg.Pts = bs.GetBits(3) - bs.SkipBits(1) - pkg.Pts = pkg.Pts<<15 | bs.GetBits(15) - bs.SkipBits(1) - pkg.Pts = pkg.Pts<<15 | bs.GetBits(15) - bs.SkipBits(1) - pkg.Dts = bs.GetBits(3) - bs.SkipBits(1) - pkg.Dts = pkg.Pts<<15 | bs.GetBits(15) - bs.SkipBits(1) - pkg.Dts = pkg.Pts<<15 | bs.GetBits(15) - bs.SkipBits(1) - } else if bs.NextBits(8) == 0x0F { - bs.SkipBits(8) - } else { - return errParser - } - loc := bs.DistanceFromMarkDot() / 8 - if pkg.PES_packet_length < uint16(loc) { - return errParser - } - if pkg.PES_packet_length == 0 || - bs.RemainBits() <= int(pkg.PES_packet_length-uint16(loc))*8 { - pkg.Pes_payload = bs.RemainData() - bs.SkipBits(bs.RemainBits()) - } else { - pkg.Pes_payload = bs.RemainData()[:pkg.PES_packet_length-uint16(loc)] - bs.SkipBits(int(pkg.PES_packet_length-uint16(loc)) * 8) - } - return nil + if bs.RemainBytes() < 6 { + return errNeedMore + } + bs.SkipBits(24) //packet_start_code_prefix + pkg.Stream_id = bs.Uint8(8) //stream_id + pkg.PES_packet_length = bs.Uint16(16) + if pkg.PES_packet_length != 0 && bs.RemainBytes() < int(pkg.PES_packet_length) { + bs.UnRead(6 * 8) + return errNeedMore + } + bs.Markdot() + for bs.NextBits(8) == 0xFF { + bs.SkipBits(8) + } + if bs.NextBits(2) == 0x01 { + bs.SkipBits(16) + } + if bs.NextBits(4) == 0x02 { + bs.SkipBits(4) + pkg.Pts = bs.GetBits(3) + bs.SkipBits(1) + pkg.Pts = pkg.Pts<<15 | bs.GetBits(15) + bs.SkipBits(1) + pkg.Pts = pkg.Pts<<15 | bs.GetBits(15) + bs.SkipBits(1) + } else if bs.NextBits(4) == 0x03 { + bs.SkipBits(4) + pkg.Pts = bs.GetBits(3) + bs.SkipBits(1) + pkg.Pts = pkg.Pts<<15 | bs.GetBits(15) + bs.SkipBits(1) + pkg.Pts = pkg.Pts<<15 | bs.GetBits(15) + bs.SkipBits(1) + pkg.Dts = bs.GetBits(3) + bs.SkipBits(1) + pkg.Dts = pkg.Pts<<15 | bs.GetBits(15) + bs.SkipBits(1) + pkg.Dts = pkg.Pts<<15 | bs.GetBits(15) + bs.SkipBits(1) + } else if bs.NextBits(8) == 0x0F { + bs.SkipBits(8) + } else { + return errParser + } + loc := bs.DistanceFromMarkDot() / 8 + if pkg.PES_packet_length < uint16(loc) { + return errParser + } + if pkg.PES_packet_length == 0 || + bs.RemainBits() <= int(pkg.PES_packet_length-uint16(loc))*8 { + pkg.Pes_payload = bs.RemainData() + bs.SkipBits(bs.RemainBits()) + } else { + pkg.Pes_payload = bs.RemainData()[:pkg.PES_packet_length-uint16(loc)] + bs.SkipBits(int(pkg.PES_packet_length-uint16(loc)) * 8) + } + return nil } func (pkg *PesPacket) Encode(bsw *codec.BitStreamWriter) { - bsw.PutBytes([]byte{0x00, 0x00, 0x01}) - bsw.PutByte(pkg.Stream_id) - bsw.PutUint16(pkg.PES_packet_length, 16) - bsw.PutUint8(0x02, 2) - bsw.PutUint8(pkg.PES_scrambling_control, 2) - bsw.PutUint8(pkg.PES_priority, 1) - bsw.PutUint8(pkg.Data_alignment_indicator, 1) - bsw.PutUint8(pkg.Copyright, 1) - bsw.PutUint8(pkg.Original_or_copy, 1) - bsw.PutUint8(pkg.PTS_DTS_flags, 2) - bsw.PutUint8(pkg.ESCR_flag, 1) - bsw.PutUint8(pkg.ES_rate_flag, 1) - bsw.PutUint8(pkg.DSM_trick_mode_flag, 1) - bsw.PutUint8(pkg.Additional_copy_info_flag, 1) - bsw.PutUint8(pkg.PES_CRC_flag, 1) - bsw.PutUint8(pkg.PES_extension_flag, 1) - bsw.PutByte(pkg.PES_header_data_length) - if pkg.PTS_DTS_flags == 0x02 { - bsw.PutUint8(0x02, 4) - bsw.PutUint64(pkg.Pts>>30, 3) - bsw.PutUint8(0x01, 1) - bsw.PutUint64(pkg.Pts>>15, 15) - bsw.PutUint8(0x01, 1) - bsw.PutUint64(pkg.Pts, 15) - bsw.PutUint8(0x01, 1) - } + bsw.PutBytes([]byte{0x00, 0x00, 0x01}) + bsw.PutByte(pkg.Stream_id) + bsw.PutUint16(pkg.PES_packet_length, 16) + bsw.PutUint8(0x02, 2) + bsw.PutUint8(pkg.PES_scrambling_control, 2) + bsw.PutUint8(pkg.PES_priority, 1) + bsw.PutUint8(pkg.Data_alignment_indicator, 1) + bsw.PutUint8(pkg.Copyright, 1) + bsw.PutUint8(pkg.Original_or_copy, 1) + bsw.PutUint8(pkg.PTS_DTS_flags, 2) + bsw.PutUint8(pkg.ESCR_flag, 1) + bsw.PutUint8(pkg.ES_rate_flag, 1) + bsw.PutUint8(pkg.DSM_trick_mode_flag, 1) + bsw.PutUint8(pkg.Additional_copy_info_flag, 1) + bsw.PutUint8(pkg.PES_CRC_flag, 1) + bsw.PutUint8(pkg.PES_extension_flag, 1) + bsw.PutByte(pkg.PES_header_data_length) + if pkg.PTS_DTS_flags == 0x02 { + bsw.PutUint8(0x02, 4) + bsw.PutUint64(pkg.Pts>>30, 3) + bsw.PutUint8(0x01, 1) + bsw.PutUint64(pkg.Pts>>15, 15) + bsw.PutUint8(0x01, 1) + bsw.PutUint64(pkg.Pts, 15) + bsw.PutUint8(0x01, 1) + } - if pkg.PTS_DTS_flags == 0x03 { - bsw.PutUint8(0x03, 4) - bsw.PutUint64(pkg.Pts>>30, 3) - bsw.PutUint8(0x01, 1) - bsw.PutUint64(pkg.Pts>>15, 15) - bsw.PutUint8(0x01, 1) - bsw.PutUint64(pkg.Pts, 15) - bsw.PutUint8(0x01, 1) - bsw.PutUint8(0x01, 4) - bsw.PutUint64(pkg.Dts>>30, 3) - bsw.PutUint8(0x01, 1) - bsw.PutUint64(pkg.Dts>>15, 15) - bsw.PutUint8(0x01, 1) - bsw.PutUint64(pkg.Dts, 15) - bsw.PutUint8(0x01, 1) - } + if pkg.PTS_DTS_flags == 0x03 { + bsw.PutUint8(0x03, 4) + bsw.PutUint64(pkg.Pts>>30, 3) + bsw.PutUint8(0x01, 1) + bsw.PutUint64(pkg.Pts>>15, 15) + bsw.PutUint8(0x01, 1) + bsw.PutUint64(pkg.Pts, 15) + bsw.PutUint8(0x01, 1) + bsw.PutUint8(0x01, 4) + bsw.PutUint64(pkg.Dts>>30, 3) + bsw.PutUint8(0x01, 1) + bsw.PutUint64(pkg.Dts>>15, 15) + bsw.PutUint8(0x01, 1) + bsw.PutUint64(pkg.Dts, 15) + bsw.PutUint8(0x01, 1) + } - if pkg.ESCR_flag == 1 { - bsw.PutUint8(0x03, 2) - bsw.PutUint64(pkg.ESCR_base>>30, 3) - bsw.PutUint8(0x01, 1) - bsw.PutUint64(pkg.ESCR_base>>15, 15) - bsw.PutUint8(0x01, 1) - bsw.PutUint64(pkg.ESCR_base, 15) - bsw.PutUint8(0x01, 1) - } - bsw.PutBytes(pkg.Pes_payload) + if pkg.ESCR_flag == 1 { + bsw.PutUint8(0x03, 2) + bsw.PutUint64(pkg.ESCR_base>>30, 3) + bsw.PutUint8(0x01, 1) + bsw.PutUint64(pkg.ESCR_base>>15, 15) + bsw.PutUint8(0x01, 1) + bsw.PutUint64(pkg.ESCR_base, 15) + bsw.PutUint8(0x01, 1) + } + bsw.PutBytes(pkg.Pes_payload) } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/mpeg2/ps-demuxer.go b/trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/mpeg2/ps-demuxer.go index 0a4687e04..460fda8a6 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/mpeg2/ps-demuxer.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/mpeg2/ps-demuxer.go @@ -1,280 +1,280 @@ package mpeg2 import ( - "github.com/yapingcat/gomedia/codec" + "github.com/yapingcat/gomedia/codec" ) type psstream struct { - sid uint8 - cid PS_STREAM_TYPE - pts uint64 - dts uint64 - streamBuf []byte + sid uint8 + cid PS_STREAM_TYPE + pts uint64 + dts uint64 + streamBuf []byte } func newpsstream(sid uint8, cid PS_STREAM_TYPE) *psstream { - return &psstream{ - sid: sid, - cid: cid, - streamBuf: make([]byte, 0, 4096), - } + return &psstream{ + sid: sid, + cid: cid, + streamBuf: make([]byte, 0, 4096), + } } type PSDemuxer struct { - streamMap map[uint8]*psstream - pkg *PSPacket - mpeg1 bool - cache []byte - OnFrame func(frame []byte, cid PS_STREAM_TYPE, pts uint64, dts uint64) - //解ps包过程中,解码回调psm,system header,pes包等 - //decodeResult 解码ps包时的产生的错误 - //这个回调主要用于debug,查看是否ps包存在问题 - OnPacket func(pkg Display, decodeResult error) + streamMap map[uint8]*psstream + pkg *PSPacket + mpeg1 bool + cache []byte + OnFrame func(frame []byte, cid PS_STREAM_TYPE, pts uint64, dts uint64) + //解ps包过程中,解码回调psm,system header,pes包等 + //decodeResult 解码ps包时的产生的错误 + //这个回调主要用于debug,查看是否ps包存在问题 + OnPacket func(pkg Display, decodeResult error) } func NewPSDemuxer() *PSDemuxer { - return &PSDemuxer{ - streamMap: make(map[uint8]*psstream), - pkg: new(PSPacket), - cache: make([]byte, 0, 256), - OnFrame: nil, - OnPacket: nil, - } + return &PSDemuxer{ + streamMap: make(map[uint8]*psstream), + pkg: new(PSPacket), + cache: make([]byte, 0, 256), + OnFrame: nil, + OnPacket: nil, + } } func (psdemuxer *PSDemuxer) Input(data []byte) error { - var bs *codec.BitStream - if len(psdemuxer.cache) > 0 { - psdemuxer.cache = append(psdemuxer.cache, data...) - bs = codec.NewBitStream(psdemuxer.cache) - } else { - bs = codec.NewBitStream(data) - } + var bs *codec.BitStream + if len(psdemuxer.cache) > 0 { + psdemuxer.cache = append(psdemuxer.cache, data...) + bs = codec.NewBitStream(psdemuxer.cache) + } else { + bs = codec.NewBitStream(data) + } - saveReseved := func() { - tmpcache := make([]byte, bs.RemainBytes()) - copy(tmpcache, bs.RemainData()) - psdemuxer.cache = tmpcache - } + saveReseved := func() { + tmpcache := make([]byte, bs.RemainBytes()) + copy(tmpcache, bs.RemainData()) + psdemuxer.cache = tmpcache + } - var ret error = nil - for !bs.EOS() { - if mpegerr, ok := ret.(Error); ok { - if mpegerr.NeedMore() { - saveReseved() - } - break - } - if bs.RemainBits() < 32 { - ret = errNeedMore - saveReseved() - break - } - prefix_code := bs.NextBits(32) - switch prefix_code { - case 0x000001BA: //pack header - if psdemuxer.pkg.Header == nil { - psdemuxer.pkg.Header = new(PSPackHeader) - } - ret = psdemuxer.pkg.Header.Decode(bs) - psdemuxer.mpeg1 = psdemuxer.pkg.Header.IsMpeg1 - if psdemuxer.OnPacket != nil { - psdemuxer.OnPacket(psdemuxer.pkg.Header, ret) - } - case 0x000001BB: //system header - if psdemuxer.pkg.Header == nil { - panic("psdemuxer.pkg.Header must not be nil") - } - if psdemuxer.pkg.System == nil { - psdemuxer.pkg.System = new(System_header) - } - ret = psdemuxer.pkg.System.Decode(bs) - if psdemuxer.OnPacket != nil { - psdemuxer.OnPacket(psdemuxer.pkg.System, ret) - } - case 0x000001BC: //program stream map - if psdemuxer.pkg.Psm == nil { - psdemuxer.pkg.Psm = new(Program_stream_map) - } - if ret = psdemuxer.pkg.Psm.Decode(bs); ret == nil { - for _, streaminfo := range psdemuxer.pkg.Psm.Stream_map { - if _, found := psdemuxer.streamMap[streaminfo.Elementary_stream_id]; !found { - stream := newpsstream(streaminfo.Elementary_stream_id, PS_STREAM_TYPE(streaminfo.Stream_type)) - psdemuxer.streamMap[stream.sid] = stream - } - } - } - if psdemuxer.OnPacket != nil { - psdemuxer.OnPacket(psdemuxer.pkg.Psm, ret) - } - case 0x000001BD, 0x000001BE, 0x000001BF, 0x000001F0, 0x000001F1, - 0x000001F2, 0x000001F3, 0x000001F4, 0x000001F5, 0x000001F6, - 0x000001F7, 0x000001F8, 0x000001F9, 0x000001FA, 0x000001FB: - if psdemuxer.pkg.CommPes == nil { - psdemuxer.pkg.CommPes = new(CommonPesPacket) - } - ret = psdemuxer.pkg.CommPes.Decode(bs) - case 0x000001FF: //program stream directory - if psdemuxer.pkg.Psd == nil { - psdemuxer.pkg.Psd = new(Program_stream_directory) - } - ret = psdemuxer.pkg.Psd.Decode(bs) - case 0x000001B9: //MPEG_program_end_code - continue - default: - if prefix_code&0xFFFFFFE0 == 0x000001C0 || prefix_code&0xFFFFFFE0 == 0x000001E0 { - if psdemuxer.pkg.Pes == nil { - psdemuxer.pkg.Pes = NewPesPacket() - } - if psdemuxer.mpeg1 { - ret = psdemuxer.pkg.Pes.DecodeMpeg1(bs) - } else { - ret = psdemuxer.pkg.Pes.Decode(bs) - } - if psdemuxer.OnPacket != nil { - psdemuxer.OnPacket(psdemuxer.pkg.Pes, ret) - } - if ret == nil { - if stream, found := psdemuxer.streamMap[psdemuxer.pkg.Pes.Stream_id]; found { - if psdemuxer.mpeg1 && stream.cid == PS_STREAM_UNKNOW { - psdemuxer.guessCodecid(stream) - } - psdemuxer.demuxPespacket(stream, psdemuxer.pkg.Pes) - } else { - if psdemuxer.mpeg1 { - stream := newpsstream(psdemuxer.pkg.Pes.Stream_id, PS_STREAM_UNKNOW) - psdemuxer.streamMap[stream.sid] = stream - stream.streamBuf = append(stream.streamBuf, psdemuxer.pkg.Pes.Pes_payload...) - stream.pts = psdemuxer.pkg.Pes.Pts - stream.dts = psdemuxer.pkg.Pes.Dts - } - } - } - } else { - bs.SkipBits(8) - } - } - } + var ret error = nil + for !bs.EOS() { + if mpegerr, ok := ret.(Error); ok { + if mpegerr.NeedMore() { + saveReseved() + } + break + } + if bs.RemainBits() < 32 { + ret = errNeedMore + saveReseved() + break + } + prefix_code := bs.NextBits(32) + switch prefix_code { + case 0x000001BA: //pack header + if psdemuxer.pkg.Header == nil { + psdemuxer.pkg.Header = new(PSPackHeader) + } + ret = psdemuxer.pkg.Header.Decode(bs) + psdemuxer.mpeg1 = psdemuxer.pkg.Header.IsMpeg1 + if psdemuxer.OnPacket != nil { + psdemuxer.OnPacket(psdemuxer.pkg.Header, ret) + } + case 0x000001BB: //system header + if psdemuxer.pkg.Header == nil { + panic("psdemuxer.pkg.Header must not be nil") + } + if psdemuxer.pkg.System == nil { + psdemuxer.pkg.System = new(System_header) + } + ret = psdemuxer.pkg.System.Decode(bs) + if psdemuxer.OnPacket != nil { + psdemuxer.OnPacket(psdemuxer.pkg.System, ret) + } + case 0x000001BC: //program stream map + if psdemuxer.pkg.Psm == nil { + psdemuxer.pkg.Psm = new(Program_stream_map) + } + if ret = psdemuxer.pkg.Psm.Decode(bs); ret == nil { + for _, streaminfo := range psdemuxer.pkg.Psm.Stream_map { + if _, found := psdemuxer.streamMap[streaminfo.Elementary_stream_id]; !found { + stream := newpsstream(streaminfo.Elementary_stream_id, PS_STREAM_TYPE(streaminfo.Stream_type)) + psdemuxer.streamMap[stream.sid] = stream + } + } + } + if psdemuxer.OnPacket != nil { + psdemuxer.OnPacket(psdemuxer.pkg.Psm, ret) + } + case 0x000001BD, 0x000001BE, 0x000001BF, 0x000001F0, 0x000001F1, + 0x000001F2, 0x000001F3, 0x000001F4, 0x000001F5, 0x000001F6, + 0x000001F7, 0x000001F8, 0x000001F9, 0x000001FA, 0x000001FB: + if psdemuxer.pkg.CommPes == nil { + psdemuxer.pkg.CommPes = new(CommonPesPacket) + } + ret = psdemuxer.pkg.CommPes.Decode(bs) + case 0x000001FF: //program stream directory + if psdemuxer.pkg.Psd == nil { + psdemuxer.pkg.Psd = new(Program_stream_directory) + } + ret = psdemuxer.pkg.Psd.Decode(bs) + case 0x000001B9: //MPEG_program_end_code + continue + default: + if prefix_code&0xFFFFFFE0 == 0x000001C0 || prefix_code&0xFFFFFFE0 == 0x000001E0 { + if psdemuxer.pkg.Pes == nil { + psdemuxer.pkg.Pes = NewPesPacket() + } + if psdemuxer.mpeg1 { + ret = psdemuxer.pkg.Pes.DecodeMpeg1(bs) + } else { + ret = psdemuxer.pkg.Pes.Decode(bs) + } + if psdemuxer.OnPacket != nil { + psdemuxer.OnPacket(psdemuxer.pkg.Pes, ret) + } + if ret == nil { + if stream, found := psdemuxer.streamMap[psdemuxer.pkg.Pes.Stream_id]; found { + if psdemuxer.mpeg1 && stream.cid == PS_STREAM_UNKNOW { + psdemuxer.guessCodecid(stream) + } + psdemuxer.demuxPespacket(stream, psdemuxer.pkg.Pes) + } else { + if psdemuxer.mpeg1 { + stream := newpsstream(psdemuxer.pkg.Pes.Stream_id, PS_STREAM_UNKNOW) + psdemuxer.streamMap[stream.sid] = stream + stream.streamBuf = append(stream.streamBuf, psdemuxer.pkg.Pes.Pes_payload...) + stream.pts = psdemuxer.pkg.Pes.Pts + stream.dts = psdemuxer.pkg.Pes.Dts + } + } + } + } else { + bs.SkipBits(8) + } + } + } - if ret == nil && len(psdemuxer.cache) > 0 { - psdemuxer.cache = nil - } + if ret == nil && len(psdemuxer.cache) > 0 { + psdemuxer.cache = nil + } - return ret + return ret } func (psdemuxer *PSDemuxer) Flush() { - for _, stream := range psdemuxer.streamMap { - if len(stream.streamBuf) == 0 { - continue - } - if psdemuxer.OnFrame != nil { - psdemuxer.OnFrame(stream.streamBuf, stream.cid, stream.pts/90, stream.dts/90) - } - } + for _, stream := range psdemuxer.streamMap { + if len(stream.streamBuf) == 0 { + continue + } + if psdemuxer.OnFrame != nil { + psdemuxer.OnFrame(stream.streamBuf, stream.cid, stream.pts/90, stream.dts/90) + } + } } func (psdemuxer *PSDemuxer) guessCodecid(stream *psstream) { - if stream.sid&0xE0 == uint8(PES_STREAM_AUDIO) { - stream.cid = PS_STREAM_AAC - } else if stream.sid&0xE0 == uint8(PES_STREAM_VIDEO) { - h264score := 0 - h265score := 0 - codec.SplitFrame(stream.streamBuf, func(nalu []byte) bool { - h264nalutype := codec.H264NaluTypeWithoutStartCode(nalu) - h265nalutype := codec.H265NaluTypeWithoutStartCode(nalu) - if h264nalutype == codec.H264_NAL_PPS || - h264nalutype == codec.H264_NAL_SPS || - h264nalutype == codec.H264_NAL_I_SLICE { - h264score += 2 - } else if h264nalutype < 5 { - h264score += 1 - } else if h264nalutype > 20 { - h264score -= 1 - } + if stream.sid&0xE0 == uint8(PES_STREAM_AUDIO) { + stream.cid = PS_STREAM_AAC + } else if stream.sid&0xE0 == uint8(PES_STREAM_VIDEO) { + h264score := 0 + h265score := 0 + codec.SplitFrame(stream.streamBuf, func(nalu []byte) bool { + h264nalutype := codec.H264NaluTypeWithoutStartCode(nalu) + h265nalutype := codec.H265NaluTypeWithoutStartCode(nalu) + if h264nalutype == codec.H264_NAL_PPS || + h264nalutype == codec.H264_NAL_SPS || + h264nalutype == codec.H264_NAL_I_SLICE { + h264score += 2 + } else if h264nalutype < 5 { + h264score += 1 + } else if h264nalutype > 20 { + h264score -= 1 + } - if h265nalutype == codec.H265_NAL_PPS || - h265nalutype == codec.H265_NAL_SPS || - h265nalutype == codec.H265_NAL_VPS || - (h265nalutype >= codec.H265_NAL_SLICE_BLA_W_LP && h265nalutype <= codec.H265_NAL_SLICE_CRA) { - h265score += 2 - } else if h265nalutype >= codec.H265_NAL_Slice_TRAIL_N && h265nalutype <= codec.H265_NAL_SLICE_RASL_R { - h265score += 1 - } else if h265nalutype > 40 { - h265score -= 1 - } - if h264score > h265score && h264score >= 4 { - stream.cid = PS_STREAM_H264 - } else if h264score < h265score && h265score >= 4 { - stream.cid = PS_STREAM_H265 - } - return true - }) - } + if h265nalutype == codec.H265_NAL_PPS || + h265nalutype == codec.H265_NAL_SPS || + h265nalutype == codec.H265_NAL_VPS || + (h265nalutype >= codec.H265_NAL_SLICE_BLA_W_LP && h265nalutype <= codec.H265_NAL_SLICE_CRA) { + h265score += 2 + } else if h265nalutype >= codec.H265_NAL_Slice_TRAIL_N && h265nalutype <= codec.H265_NAL_SLICE_RASL_R { + h265score += 1 + } else if h265nalutype > 40 { + h265score -= 1 + } + if h264score > h265score && h264score >= 4 { + stream.cid = PS_STREAM_H264 + } else if h264score < h265score && h265score >= 4 { + stream.cid = PS_STREAM_H265 + } + return true + }) + } } func (psdemuxer *PSDemuxer) demuxPespacket(stream *psstream, pes *PesPacket) error { - switch stream.cid { - case PS_STREAM_AAC, PS_STREAM_G711A, PS_STREAM_G711U: - return psdemuxer.demuxAudio(stream, pes) - case PS_STREAM_H264, PS_STREAM_H265: - return psdemuxer.demuxH26x(stream, pes) - case PS_STREAM_UNKNOW: - if stream.pts != pes.Pts { - stream.streamBuf = nil - } - stream.streamBuf = append(stream.streamBuf, pes.Pes_payload...) - stream.pts = pes.Pts - stream.dts = pes.Dts - } - return nil + switch stream.cid { + case PS_STREAM_AAC, PS_STREAM_G711A, PS_STREAM_G711U: + return psdemuxer.demuxAudio(stream, pes) + case PS_STREAM_H264, PS_STREAM_H265: + return psdemuxer.demuxH26x(stream, pes) + case PS_STREAM_UNKNOW: + if stream.pts != pes.Pts { + stream.streamBuf = nil + } + stream.streamBuf = append(stream.streamBuf, pes.Pes_payload...) + stream.pts = pes.Pts + stream.dts = pes.Dts + } + return nil } func (psdemuxer *PSDemuxer) demuxAudio(stream *psstream, pes *PesPacket) error { - if stream.pts != pes.Pts && len(stream.streamBuf) > 0 { - if psdemuxer.OnFrame != nil { - psdemuxer.OnFrame(stream.streamBuf, stream.cid, stream.pts/90, stream.dts/90) - } - stream.streamBuf = stream.streamBuf[:0] - } - stream.streamBuf = append(stream.streamBuf, pes.Pes_payload...) - stream.pts = pes.Pts - stream.dts = pes.Dts - return nil + if stream.pts != pes.Pts && len(stream.streamBuf) > 0 { + if psdemuxer.OnFrame != nil { + psdemuxer.OnFrame(stream.streamBuf, stream.cid, stream.pts/90, stream.dts/90) + } + stream.streamBuf = stream.streamBuf[:0] + } + stream.streamBuf = append(stream.streamBuf, pes.Pes_payload...) + stream.pts = pes.Pts + stream.dts = pes.Dts + return nil } func (psdemuxer *PSDemuxer) demuxH26x(stream *psstream, pes *PesPacket) error { - if len(stream.streamBuf) == 0 { - stream.pts = pes.Pts - stream.dts = pes.Dts - } - stream.streamBuf = append(stream.streamBuf, pes.Pes_payload...) - start, sc := codec.FindStartCode(stream.streamBuf, 0) - for start >= 0 { - end, sc2 := codec.FindStartCode(stream.streamBuf, start+int(sc)) - if end < 0 { - break - } - if stream.cid == PS_STREAM_H264 { - naluType := codec.H264NaluType(stream.streamBuf[start:]) - if naluType != codec.H264_NAL_AUD { - if psdemuxer.OnFrame != nil { - psdemuxer.OnFrame(stream.streamBuf[start:end], stream.cid, stream.pts/90, stream.dts/90) - } - } - } else if stream.cid == PS_STREAM_H265 { - naluType := codec.H265NaluType(stream.streamBuf[start:]) - if naluType != codec.H265_NAL_AUD { - if psdemuxer.OnFrame != nil { - psdemuxer.OnFrame(stream.streamBuf[start:end], stream.cid, stream.pts/90, stream.dts/90) - } - } - } - start = end - sc = sc2 - } - stream.streamBuf = stream.streamBuf[start:] - stream.pts = pes.Pts - stream.dts = pes.Dts - return nil + if len(stream.streamBuf) == 0 { + stream.pts = pes.Pts + stream.dts = pes.Dts + } + stream.streamBuf = append(stream.streamBuf, pes.Pes_payload...) + start, sc := codec.FindStartCode(stream.streamBuf, 0) + for start >= 0 { + end, sc2 := codec.FindStartCode(stream.streamBuf, start+int(sc)) + if end < 0 { + break + } + if stream.cid == PS_STREAM_H264 { + naluType := codec.H264NaluType(stream.streamBuf[start:]) + if naluType != codec.H264_NAL_AUD { + if psdemuxer.OnFrame != nil { + psdemuxer.OnFrame(stream.streamBuf[start:end], stream.cid, stream.pts/90, stream.dts/90) + } + } + } else if stream.cid == PS_STREAM_H265 { + naluType := codec.H265NaluType(stream.streamBuf[start:]) + if naluType != codec.H265_NAL_AUD { + if psdemuxer.OnFrame != nil { + psdemuxer.OnFrame(stream.streamBuf[start:end], stream.cid, stream.pts/90, stream.dts/90) + } + } + } + start = end + sc = sc2 + } + stream.streamBuf = stream.streamBuf[start:] + stream.pts = pes.Pts + stream.dts = pes.Dts + return nil } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/mpeg2/ps-muxer.go b/trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/mpeg2/ps-muxer.go index 425107bf3..a8834e0dc 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/mpeg2/ps-muxer.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/mpeg2/ps-muxer.go @@ -3,146 +3,146 @@ package mpeg2 import "github.com/yapingcat/gomedia/codec" type PSMuxer struct { - system *System_header - psm *Program_stream_map - OnPacket func(pkg []byte) - firstframe bool + system *System_header + psm *Program_stream_map + OnPacket func(pkg []byte) + firstframe bool } func NewPsMuxer() *PSMuxer { - muxer := new(PSMuxer) - muxer.firstframe = true - muxer.system = new(System_header) - muxer.system.Rate_bound = 26234 - muxer.psm = new(Program_stream_map) - muxer.psm.Current_next_indicator = 1 - muxer.psm.Program_stream_map_version = 1 - muxer.OnPacket = nil - return muxer + muxer := new(PSMuxer) + muxer.firstframe = true + muxer.system = new(System_header) + muxer.system.Rate_bound = 26234 + muxer.psm = new(Program_stream_map) + muxer.psm.Current_next_indicator = 1 + muxer.psm.Program_stream_map_version = 1 + muxer.OnPacket = nil + return muxer } func (muxer *PSMuxer) AddStream(cid PS_STREAM_TYPE) uint8 { - if cid == PS_STREAM_H265 || cid == PS_STREAM_H264 { - es := NewElementary_Stream(uint8(PES_STREAM_VIDEO) + muxer.system.Video_bound) - es.P_STD_buffer_bound_scale = 1 - es.P_STD_buffer_size_bound = 400 - muxer.system.Streams = append(muxer.system.Streams, es) - muxer.system.Video_bound++ - muxer.psm.Stream_map = append(muxer.psm.Stream_map, NewElementary_stream_elem(uint8(cid), es.Stream_id)) - muxer.psm.Program_stream_map_version++ - return es.Stream_id - } else { - es := NewElementary_Stream(uint8(PES_STREAM_AUDIO) + muxer.system.Audio_bound) - es.P_STD_buffer_bound_scale = 0 - es.P_STD_buffer_size_bound = 32 - muxer.system.Streams = append(muxer.system.Streams, es) - muxer.system.Audio_bound++ - muxer.psm.Stream_map = append(muxer.psm.Stream_map, NewElementary_stream_elem(uint8(cid), es.Stream_id)) - muxer.psm.Program_stream_map_version++ - return es.Stream_id - } + if cid == PS_STREAM_H265 || cid == PS_STREAM_H264 { + es := NewElementary_Stream(uint8(PES_STREAM_VIDEO) + muxer.system.Video_bound) + es.P_STD_buffer_bound_scale = 1 + es.P_STD_buffer_size_bound = 400 + muxer.system.Streams = append(muxer.system.Streams, es) + muxer.system.Video_bound++ + muxer.psm.Stream_map = append(muxer.psm.Stream_map, NewElementary_stream_elem(uint8(cid), es.Stream_id)) + muxer.psm.Program_stream_map_version++ + return es.Stream_id + } else { + es := NewElementary_Stream(uint8(PES_STREAM_AUDIO) + muxer.system.Audio_bound) + es.P_STD_buffer_bound_scale = 0 + es.P_STD_buffer_size_bound = 32 + muxer.system.Streams = append(muxer.system.Streams, es) + muxer.system.Audio_bound++ + muxer.psm.Stream_map = append(muxer.psm.Stream_map, NewElementary_stream_elem(uint8(cid), es.Stream_id)) + muxer.psm.Program_stream_map_version++ + return es.Stream_id + } } func (muxer *PSMuxer) Write(sid uint8, frame []byte, pts uint64, dts uint64) error { - var stream *Elementary_stream_elem = nil - for _, es := range muxer.psm.Stream_map { - if es.Elementary_stream_id == sid { - stream = es - break - } - } - if stream == nil { - return errNotFound - } - var withaud bool = false - var idr_flag bool = false - var first bool = true - var vcl bool = false - if stream.Stream_type == uint8(PS_STREAM_H264) || stream.Stream_type == uint8(PS_STREAM_H265) { - codec.SplitFrame(frame, func(nalu []byte) bool { - if stream.Stream_type == uint8(PS_STREAM_H264) { - nalu_type := codec.H264NaluTypeWithoutStartCode(nalu) - if nalu_type == codec.H264_NAL_AUD { - withaud = true - return false - } else if codec.IsH264VCLNaluType(nalu_type) { - if nalu_type == codec.H264_NAL_I_SLICE { - idr_flag = true - } - vcl = true - return false - } - return true - } else { - nalu_type := codec.H265NaluTypeWithoutStartCode(nalu) - if nalu_type == codec.H265_NAL_AUD { - withaud = true - return false - } else if codec.IsH265VCLNaluType(nalu_type) { - if nalu_type >= codec.H265_NAL_SLICE_BLA_W_LP && nalu_type <= codec.H265_NAL_SLICE_CRA { - idr_flag = true - } - vcl = true - return false - } - return true - } - }) - } + var stream *Elementary_stream_elem = nil + for _, es := range muxer.psm.Stream_map { + if es.Elementary_stream_id == sid { + stream = es + break + } + } + if stream == nil { + return errNotFound + } + var withaud bool = false + var idr_flag bool = false + var first bool = true + var vcl bool = false + if stream.Stream_type == uint8(PS_STREAM_H264) || stream.Stream_type == uint8(PS_STREAM_H265) { + codec.SplitFrame(frame, func(nalu []byte) bool { + if stream.Stream_type == uint8(PS_STREAM_H264) { + nalu_type := codec.H264NaluTypeWithoutStartCode(nalu) + if nalu_type == codec.H264_NAL_AUD { + withaud = true + return false + } else if codec.IsH264VCLNaluType(nalu_type) { + if nalu_type == codec.H264_NAL_I_SLICE { + idr_flag = true + } + vcl = true + return false + } + return true + } else { + nalu_type := codec.H265NaluTypeWithoutStartCode(nalu) + if nalu_type == codec.H265_NAL_AUD { + withaud = true + return false + } else if codec.IsH265VCLNaluType(nalu_type) { + if nalu_type >= codec.H265_NAL_SLICE_BLA_W_LP && nalu_type <= codec.H265_NAL_SLICE_CRA { + idr_flag = true + } + vcl = true + return false + } + return true + } + }) + } - dts = dts * 90 - pts = pts * 90 - bsw := codec.NewBitStreamWriter(1024) - var pack PSPackHeader - pack.System_clock_reference_base = dts - 3600 - pack.System_clock_reference_extension = 0 - pack.Program_mux_rate = 6106 - pack.Encode(bsw) - if muxer.firstframe || idr_flag { - muxer.system.Encode(bsw) - muxer.psm.Encode(bsw) - muxer.firstframe = false - } - if muxer.OnPacket != nil { - muxer.OnPacket(bsw.Bits()) - } - bsw.Reset() - pespkg := NewPesPacket() - for len(frame) > 0 { - peshdrlen := 13 - pespkg.Stream_id = sid - pespkg.PTS_DTS_flags = 0x03 - pespkg.PES_header_data_length = 10 - pespkg.Pts = pts - pespkg.Dts = dts - if idr_flag { - pespkg.Data_alignment_indicator = 1 - } - if first && !withaud && vcl { - if stream.Stream_type == uint8(PS_STREAM_H264) { - pespkg.Pes_payload = append(pespkg.Pes_payload, H264_AUD_NALU...) - peshdrlen += 6 - } else if stream.Stream_type == uint8(PS_STREAM_H265) { - pespkg.Pes_payload = append(pespkg.Pes_payload, H265_AUD_NALU...) - peshdrlen += 7 - } - } - if peshdrlen+len(frame) >= 0xFFFF { - pespkg.PES_packet_length = 0xFFFF - pespkg.Pes_payload = append(pespkg.Pes_payload, frame[0:0xFFFF-peshdrlen]...) - frame = frame[0xFFFF-peshdrlen:] - } else { - pespkg.PES_packet_length = uint16(peshdrlen + len(frame)) - pespkg.Pes_payload = append(pespkg.Pes_payload, frame[0:]...) - frame = frame[:0] - } - pespkg.Encode(bsw) - pespkg.Pes_payload = pespkg.Pes_payload[:0] - if muxer.OnPacket != nil { - muxer.OnPacket(bsw.Bits()) - } - bsw.Reset() - first = false - } - return nil + dts = dts * 90 + pts = pts * 90 + bsw := codec.NewBitStreamWriter(1024) + var pack PSPackHeader + pack.System_clock_reference_base = dts - 3600 + pack.System_clock_reference_extension = 0 + pack.Program_mux_rate = 6106 + pack.Encode(bsw) + if muxer.firstframe || idr_flag { + muxer.system.Encode(bsw) + muxer.psm.Encode(bsw) + muxer.firstframe = false + } + if muxer.OnPacket != nil { + muxer.OnPacket(bsw.Bits()) + } + bsw.Reset() + pespkg := NewPesPacket() + for len(frame) > 0 { + peshdrlen := 13 + pespkg.Stream_id = sid + pespkg.PTS_DTS_flags = 0x03 + pespkg.PES_header_data_length = 10 + pespkg.Pts = pts + pespkg.Dts = dts + if idr_flag { + pespkg.Data_alignment_indicator = 1 + } + if first && !withaud && vcl { + if stream.Stream_type == uint8(PS_STREAM_H264) { + pespkg.Pes_payload = append(pespkg.Pes_payload, H264_AUD_NALU...) + peshdrlen += 6 + } else if stream.Stream_type == uint8(PS_STREAM_H265) { + pespkg.Pes_payload = append(pespkg.Pes_payload, H265_AUD_NALU...) + peshdrlen += 7 + } + } + if peshdrlen+len(frame) >= 0xFFFF { + pespkg.PES_packet_length = 0xFFFF + pespkg.Pes_payload = append(pespkg.Pes_payload, frame[0:0xFFFF-peshdrlen]...) + frame = frame[0xFFFF-peshdrlen:] + } else { + pespkg.PES_packet_length = uint16(peshdrlen + len(frame)) + pespkg.Pes_payload = append(pespkg.Pes_payload, frame[0:]...) + frame = frame[:0] + } + pespkg.Encode(bsw) + pespkg.Pes_payload = pespkg.Pes_payload[:0] + if muxer.OnPacket != nil { + muxer.OnPacket(bsw.Bits()) + } + bsw.Reset() + first = false + } + return nil } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/mpeg2/ps-proto.go b/trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/mpeg2/ps-proto.go index d2282b276..baf52a395 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/mpeg2/ps-proto.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/mpeg2/ps-proto.go @@ -1,17 +1,17 @@ package mpeg2 import ( - "encoding/binary" - "fmt" - "os" + "encoding/binary" + "fmt" + "os" - "github.com/yapingcat/gomedia/codec" + "github.com/yapingcat/gomedia/codec" ) type Error interface { - NeedMore() bool - ParserError() bool - StreamIdNotFound() bool + NeedMore() bool + ParserError() bool + StreamIdNotFound() bool } var errNeedMore error = &needmoreError{} @@ -44,12 +44,12 @@ func (e *sidNotFoundError) StreamIdNotFound() bool { return true } type PS_STREAM_TYPE int const ( - PS_STREAM_UNKNOW PS_STREAM_TYPE = 0xFF - PS_STREAM_AAC PS_STREAM_TYPE = 0x0F - PS_STREAM_H264 PS_STREAM_TYPE = 0x1B - PS_STREAM_H265 PS_STREAM_TYPE = 0x24 - PS_STREAM_G711A PS_STREAM_TYPE = 0x90 - PS_STREAM_G711U PS_STREAM_TYPE = 0x91 + PS_STREAM_UNKNOW PS_STREAM_TYPE = 0xFF + PS_STREAM_AAC PS_STREAM_TYPE = 0x0F + PS_STREAM_H264 PS_STREAM_TYPE = 0x1B + PS_STREAM_H265 PS_STREAM_TYPE = 0x24 + PS_STREAM_G711A PS_STREAM_TYPE = 0x90 + PS_STREAM_G711U PS_STREAM_TYPE = 0x91 ) // Table 2-33 – Program Stream pack header @@ -78,113 +78,113 @@ const ( // } type PSPackHeader struct { - IsMpeg1 bool - System_clock_reference_base uint64 //33 bits - System_clock_reference_extension uint16 //9 bits - Program_mux_rate uint32 //22 bits - Pack_stuffing_length uint8 //3 bitss + IsMpeg1 bool + System_clock_reference_base uint64 //33 bits + System_clock_reference_extension uint16 //9 bits + Program_mux_rate uint32 //22 bits + Pack_stuffing_length uint8 //3 bitss } func (ps_pkg_hdr *PSPackHeader) PrettyPrint(file *os.File) { - file.WriteString(fmt.Sprintf("IsMpeg1:%t\n", ps_pkg_hdr.IsMpeg1)) - file.WriteString(fmt.Sprintf("System_clock_reference_base:%d\n", ps_pkg_hdr.System_clock_reference_base)) - file.WriteString(fmt.Sprintf("System_clock_reference_extension:%d\n", ps_pkg_hdr.System_clock_reference_extension)) - file.WriteString(fmt.Sprintf("Program_mux_rate:%d\n", ps_pkg_hdr.Program_mux_rate)) - file.WriteString(fmt.Sprintf("Pack_stuffing_length:%d\n", ps_pkg_hdr.Pack_stuffing_length)) + file.WriteString(fmt.Sprintf("IsMpeg1:%t\n", ps_pkg_hdr.IsMpeg1)) + file.WriteString(fmt.Sprintf("System_clock_reference_base:%d\n", ps_pkg_hdr.System_clock_reference_base)) + file.WriteString(fmt.Sprintf("System_clock_reference_extension:%d\n", ps_pkg_hdr.System_clock_reference_extension)) + file.WriteString(fmt.Sprintf("Program_mux_rate:%d\n", ps_pkg_hdr.Program_mux_rate)) + file.WriteString(fmt.Sprintf("Pack_stuffing_length:%d\n", ps_pkg_hdr.Pack_stuffing_length)) } func (ps_pkg_hdr *PSPackHeader) Decode(bs *codec.BitStream) error { - if bs.RemainBytes() < 5 { - return errNeedMore - } - if bs.Uint32(32) != 0x000001BA { - panic("ps header must start with 000001BA") - } + if bs.RemainBytes() < 5 { + return errNeedMore + } + if bs.Uint32(32) != 0x000001BA { + panic("ps header must start with 000001BA") + } - if bs.NextBits(2) == 0x01 { //mpeg2 - if bs.RemainBytes() < 10 { - return errNeedMore - } - return ps_pkg_hdr.decodeMpeg2(bs) - } else if bs.NextBits(4) == 0x02 { //mpeg1 - if bs.RemainBytes() < 8 { - return errNeedMore - } - ps_pkg_hdr.IsMpeg1 = true - return ps_pkg_hdr.decodeMpeg1(bs) - } else { - return errParser - } + if bs.NextBits(2) == 0x01 { //mpeg2 + if bs.RemainBytes() < 10 { + return errNeedMore + } + return ps_pkg_hdr.decodeMpeg2(bs) + } else if bs.NextBits(4) == 0x02 { //mpeg1 + if bs.RemainBytes() < 8 { + return errNeedMore + } + ps_pkg_hdr.IsMpeg1 = true + return ps_pkg_hdr.decodeMpeg1(bs) + } else { + return errParser + } } func (ps_pkg_hdr *PSPackHeader) decodeMpeg2(bs *codec.BitStream) error { - bs.SkipBits(2) - ps_pkg_hdr.System_clock_reference_base = bs.GetBits(3) - bs.SkipBits(1) - ps_pkg_hdr.System_clock_reference_base = ps_pkg_hdr.System_clock_reference_base<<15 | bs.GetBits(15) - bs.SkipBits(1) - ps_pkg_hdr.System_clock_reference_base = ps_pkg_hdr.System_clock_reference_base<<15 | bs.GetBits(15) - bs.SkipBits(1) - ps_pkg_hdr.System_clock_reference_extension = bs.Uint16(9) - bs.SkipBits(1) - ps_pkg_hdr.Program_mux_rate = bs.Uint32(22) - bs.SkipBits(1) - bs.SkipBits(1) - bs.SkipBits(5) - ps_pkg_hdr.Pack_stuffing_length = bs.Uint8(3) - if bs.RemainBytes() < int(ps_pkg_hdr.Pack_stuffing_length) { - bs.UnRead(10 * 8) - return errNeedMore - } - bs.SkipBits(int(ps_pkg_hdr.Pack_stuffing_length) * 8) - return nil + bs.SkipBits(2) + ps_pkg_hdr.System_clock_reference_base = bs.GetBits(3) + bs.SkipBits(1) + ps_pkg_hdr.System_clock_reference_base = ps_pkg_hdr.System_clock_reference_base<<15 | bs.GetBits(15) + bs.SkipBits(1) + ps_pkg_hdr.System_clock_reference_base = ps_pkg_hdr.System_clock_reference_base<<15 | bs.GetBits(15) + bs.SkipBits(1) + ps_pkg_hdr.System_clock_reference_extension = bs.Uint16(9) + bs.SkipBits(1) + ps_pkg_hdr.Program_mux_rate = bs.Uint32(22) + bs.SkipBits(1) + bs.SkipBits(1) + bs.SkipBits(5) + ps_pkg_hdr.Pack_stuffing_length = bs.Uint8(3) + if bs.RemainBytes() < int(ps_pkg_hdr.Pack_stuffing_length) { + bs.UnRead(10 * 8) + return errNeedMore + } + bs.SkipBits(int(ps_pkg_hdr.Pack_stuffing_length) * 8) + return nil } func (ps_pkg_hdr *PSPackHeader) decodeMpeg1(bs *codec.BitStream) error { - bs.SkipBits(4) - ps_pkg_hdr.System_clock_reference_base = bs.GetBits(3) - bs.SkipBits(1) - ps_pkg_hdr.System_clock_reference_base = ps_pkg_hdr.System_clock_reference_base<<15 | bs.GetBits(15) - bs.SkipBits(1) - ps_pkg_hdr.System_clock_reference_base = ps_pkg_hdr.System_clock_reference_base<<15 | bs.GetBits(15) - bs.SkipBits(1) - ps_pkg_hdr.System_clock_reference_extension = 1 - ps_pkg_hdr.Program_mux_rate = bs.Uint32(7) - bs.SkipBits(1) - ps_pkg_hdr.Program_mux_rate = ps_pkg_hdr.Program_mux_rate<<15 | bs.Uint32(15) - bs.SkipBits(1) - return nil + bs.SkipBits(4) + ps_pkg_hdr.System_clock_reference_base = bs.GetBits(3) + bs.SkipBits(1) + ps_pkg_hdr.System_clock_reference_base = ps_pkg_hdr.System_clock_reference_base<<15 | bs.GetBits(15) + bs.SkipBits(1) + ps_pkg_hdr.System_clock_reference_base = ps_pkg_hdr.System_clock_reference_base<<15 | bs.GetBits(15) + bs.SkipBits(1) + ps_pkg_hdr.System_clock_reference_extension = 1 + ps_pkg_hdr.Program_mux_rate = bs.Uint32(7) + bs.SkipBits(1) + ps_pkg_hdr.Program_mux_rate = ps_pkg_hdr.Program_mux_rate<<15 | bs.Uint32(15) + bs.SkipBits(1) + return nil } func (ps_pkg_hdr *PSPackHeader) Encode(bsw *codec.BitStreamWriter) { - bsw.PutBytes([]byte{0x00, 0x00, 0x01, 0xBA}) - bsw.PutUint8(1, 2) - bsw.PutUint64(ps_pkg_hdr.System_clock_reference_base>>30, 3) - bsw.PutUint8(1, 1) - bsw.PutUint64(ps_pkg_hdr.System_clock_reference_base>>15, 15) - bsw.PutUint8(1, 1) - bsw.PutUint64(ps_pkg_hdr.System_clock_reference_base, 15) - bsw.PutUint8(1, 1) - bsw.PutUint16(ps_pkg_hdr.System_clock_reference_extension, 9) - bsw.PutUint8(1, 1) - bsw.PutUint32(ps_pkg_hdr.Program_mux_rate, 22) - bsw.PutUint8(1, 1) - bsw.PutUint8(1, 1) - bsw.PutUint8(0x1F, 5) - bsw.PutUint8(ps_pkg_hdr.Pack_stuffing_length, 3) - bsw.PutRepetValue(0xFF, int(ps_pkg_hdr.Pack_stuffing_length)) + bsw.PutBytes([]byte{0x00, 0x00, 0x01, 0xBA}) + bsw.PutUint8(1, 2) + bsw.PutUint64(ps_pkg_hdr.System_clock_reference_base>>30, 3) + bsw.PutUint8(1, 1) + bsw.PutUint64(ps_pkg_hdr.System_clock_reference_base>>15, 15) + bsw.PutUint8(1, 1) + bsw.PutUint64(ps_pkg_hdr.System_clock_reference_base, 15) + bsw.PutUint8(1, 1) + bsw.PutUint16(ps_pkg_hdr.System_clock_reference_extension, 9) + bsw.PutUint8(1, 1) + bsw.PutUint32(ps_pkg_hdr.Program_mux_rate, 22) + bsw.PutUint8(1, 1) + bsw.PutUint8(1, 1) + bsw.PutUint8(0x1F, 5) + bsw.PutUint8(ps_pkg_hdr.Pack_stuffing_length, 3) + bsw.PutRepetValue(0xFF, int(ps_pkg_hdr.Pack_stuffing_length)) } type Elementary_Stream struct { - Stream_id uint8 - P_STD_buffer_bound_scale uint8 - P_STD_buffer_size_bound uint16 + Stream_id uint8 + P_STD_buffer_bound_scale uint8 + P_STD_buffer_size_bound uint16 } func NewElementary_Stream(sid uint8) *Elementary_Stream { - return &Elementary_Stream{ - Stream_id: sid, - } + return &Elementary_Stream{ + Stream_id: sid, + } } // system_header () { @@ -211,118 +211,118 @@ func NewElementary_Stream(sid uint8) *Elementary_Stream { // } type System_header struct { - Header_length uint16 - Rate_bound uint32 - Audio_bound uint8 - Fixed_flag uint8 - CSPS_flag uint8 - System_audio_lock_flag uint8 - System_video_lock_flag uint8 - Video_bound uint8 - Packet_rate_restriction_flag uint8 - Streams []*Elementary_Stream + Header_length uint16 + Rate_bound uint32 + Audio_bound uint8 + Fixed_flag uint8 + CSPS_flag uint8 + System_audio_lock_flag uint8 + System_video_lock_flag uint8 + Video_bound uint8 + Packet_rate_restriction_flag uint8 + Streams []*Elementary_Stream } func (sh *System_header) PrettyPrint(file *os.File) { - file.WriteString(fmt.Sprintf("Header_length:%d\n", sh.Header_length)) - file.WriteString(fmt.Sprintf("Rate_bound:%d\n", sh.Rate_bound)) - file.WriteString(fmt.Sprintf("Audio_bound:%d\n", sh.Audio_bound)) - file.WriteString(fmt.Sprintf("Fixed_flag:%d\n", sh.Fixed_flag)) - file.WriteString(fmt.Sprintf("CSPS_flag:%d\n", sh.CSPS_flag)) - file.WriteString(fmt.Sprintf("System_audio_lock_flag:%d\n", sh.System_audio_lock_flag)) - file.WriteString(fmt.Sprintf("System_video_lock_flag:%d\n", sh.System_video_lock_flag)) - file.WriteString(fmt.Sprintf("Video_bound:%d\n", sh.Video_bound)) - file.WriteString(fmt.Sprintf("Packet_rate_restriction_flag:%d\n", sh.Packet_rate_restriction_flag)) - for i, es := range sh.Streams { - file.WriteString(fmt.Sprintf("----streams %d\n", i)) - file.WriteString(fmt.Sprintf(" Stream_id:%d\n", es.Stream_id)) - file.WriteString(fmt.Sprintf(" P_STD_buffer_bound_scale:%d\n", es.P_STD_buffer_bound_scale)) - file.WriteString(fmt.Sprintf(" P_STD_buffer_size_bound:%d\n", es.P_STD_buffer_size_bound)) - } + file.WriteString(fmt.Sprintf("Header_length:%d\n", sh.Header_length)) + file.WriteString(fmt.Sprintf("Rate_bound:%d\n", sh.Rate_bound)) + file.WriteString(fmt.Sprintf("Audio_bound:%d\n", sh.Audio_bound)) + file.WriteString(fmt.Sprintf("Fixed_flag:%d\n", sh.Fixed_flag)) + file.WriteString(fmt.Sprintf("CSPS_flag:%d\n", sh.CSPS_flag)) + file.WriteString(fmt.Sprintf("System_audio_lock_flag:%d\n", sh.System_audio_lock_flag)) + file.WriteString(fmt.Sprintf("System_video_lock_flag:%d\n", sh.System_video_lock_flag)) + file.WriteString(fmt.Sprintf("Video_bound:%d\n", sh.Video_bound)) + file.WriteString(fmt.Sprintf("Packet_rate_restriction_flag:%d\n", sh.Packet_rate_restriction_flag)) + for i, es := range sh.Streams { + file.WriteString(fmt.Sprintf("----streams %d\n", i)) + file.WriteString(fmt.Sprintf(" Stream_id:%d\n", es.Stream_id)) + file.WriteString(fmt.Sprintf(" P_STD_buffer_bound_scale:%d\n", es.P_STD_buffer_bound_scale)) + file.WriteString(fmt.Sprintf(" P_STD_buffer_size_bound:%d\n", es.P_STD_buffer_size_bound)) + } } func (sh *System_header) Encode(bsw *codec.BitStreamWriter) { - bsw.PutBytes([]byte{0x00, 0x00, 0x01, 0xBB}) - loc := bsw.ByteOffset() - bsw.PutUint16(0, 16) - bsw.Markdot() - bsw.PutUint8(1, 1) - bsw.PutUint32(sh.Rate_bound, 22) - bsw.PutUint8(1, 1) - bsw.PutUint8(sh.Audio_bound, 6) - bsw.PutUint8(sh.Fixed_flag, 1) - bsw.PutUint8(sh.CSPS_flag, 1) - bsw.PutUint8(sh.System_audio_lock_flag, 1) - bsw.PutUint8(sh.System_video_lock_flag, 1) - bsw.PutUint8(1, 1) - bsw.PutUint8(sh.Video_bound, 5) - bsw.PutUint8(sh.Packet_rate_restriction_flag, 1) - bsw.PutUint8(0x7F, 7) - for _, stream := range sh.Streams { - bsw.PutUint8(stream.Stream_id, 8) - bsw.PutUint8(3, 2) - bsw.PutUint8(stream.P_STD_buffer_bound_scale, 1) - bsw.PutUint16(stream.P_STD_buffer_size_bound, 13) - } - length := bsw.DistanceFromMarkDot() / 8 - bsw.SetUint16(uint16(length), loc) + bsw.PutBytes([]byte{0x00, 0x00, 0x01, 0xBB}) + loc := bsw.ByteOffset() + bsw.PutUint16(0, 16) + bsw.Markdot() + bsw.PutUint8(1, 1) + bsw.PutUint32(sh.Rate_bound, 22) + bsw.PutUint8(1, 1) + bsw.PutUint8(sh.Audio_bound, 6) + bsw.PutUint8(sh.Fixed_flag, 1) + bsw.PutUint8(sh.CSPS_flag, 1) + bsw.PutUint8(sh.System_audio_lock_flag, 1) + bsw.PutUint8(sh.System_video_lock_flag, 1) + bsw.PutUint8(1, 1) + bsw.PutUint8(sh.Video_bound, 5) + bsw.PutUint8(sh.Packet_rate_restriction_flag, 1) + bsw.PutUint8(0x7F, 7) + for _, stream := range sh.Streams { + bsw.PutUint8(stream.Stream_id, 8) + bsw.PutUint8(3, 2) + bsw.PutUint8(stream.P_STD_buffer_bound_scale, 1) + bsw.PutUint16(stream.P_STD_buffer_size_bound, 13) + } + length := bsw.DistanceFromMarkDot() / 8 + bsw.SetUint16(uint16(length), loc) } func (sh *System_header) Decode(bs *codec.BitStream) error { - if bs.RemainBytes() < 12 { - return errNeedMore - } - if bs.Uint32(32) != 0x000001BB { - panic("system header must start with 000001BB") - } - sh.Header_length = bs.Uint16(16) - if bs.RemainBytes() < int(sh.Header_length) { - bs.UnRead(6 * 8) - return errNeedMore - } - if sh.Header_length < 6 || (sh.Header_length-6)%3 != 0 { - return errParser - } - bs.SkipBits(1) - sh.Rate_bound = bs.Uint32(22) - bs.SkipBits(1) - sh.Audio_bound = bs.Uint8(6) - sh.Fixed_flag = bs.Uint8(1) - sh.CSPS_flag = bs.Uint8(1) - sh.System_audio_lock_flag = bs.Uint8(1) - sh.System_video_lock_flag = bs.Uint8(1) - bs.SkipBits(1) - sh.Video_bound = bs.Uint8(5) - sh.Packet_rate_restriction_flag = bs.Uint8(1) - bs.SkipBits(7) - sh.Streams = sh.Streams[:0] - least := sh.Header_length - 6 - for least > 0 && bs.NextBits(1) == 0x01 { - es := new(Elementary_Stream) - es.Stream_id = bs.Uint8(8) - bs.SkipBits(2) - es.P_STD_buffer_bound_scale = bs.GetBit() - es.P_STD_buffer_size_bound = bs.Uint16(13) - sh.Streams = append(sh.Streams, es) - least -= 3 - } - if least > 0 { - return errParser - } - return nil + if bs.RemainBytes() < 12 { + return errNeedMore + } + if bs.Uint32(32) != 0x000001BB { + panic("system header must start with 000001BB") + } + sh.Header_length = bs.Uint16(16) + if bs.RemainBytes() < int(sh.Header_length) { + bs.UnRead(6 * 8) + return errNeedMore + } + if sh.Header_length < 6 || (sh.Header_length-6)%3 != 0 { + return errParser + } + bs.SkipBits(1) + sh.Rate_bound = bs.Uint32(22) + bs.SkipBits(1) + sh.Audio_bound = bs.Uint8(6) + sh.Fixed_flag = bs.Uint8(1) + sh.CSPS_flag = bs.Uint8(1) + sh.System_audio_lock_flag = bs.Uint8(1) + sh.System_video_lock_flag = bs.Uint8(1) + bs.SkipBits(1) + sh.Video_bound = bs.Uint8(5) + sh.Packet_rate_restriction_flag = bs.Uint8(1) + bs.SkipBits(7) + sh.Streams = sh.Streams[:0] + least := sh.Header_length - 6 + for least > 0 && bs.NextBits(1) == 0x01 { + es := new(Elementary_Stream) + es.Stream_id = bs.Uint8(8) + bs.SkipBits(2) + es.P_STD_buffer_bound_scale = bs.GetBit() + es.P_STD_buffer_size_bound = bs.Uint16(13) + sh.Streams = append(sh.Streams, es) + least -= 3 + } + if least > 0 { + return errParser + } + return nil } type Elementary_stream_elem struct { - Stream_type uint8 - Elementary_stream_id uint8 - Elementary_stream_info_length uint16 + Stream_type uint8 + Elementary_stream_id uint8 + Elementary_stream_info_length uint16 } func NewElementary_stream_elem(stype uint8, esid uint8) *Elementary_stream_elem { - return &Elementary_stream_elem{ - Stream_type: stype, - Elementary_stream_id: esid, - } + return &Elementary_stream_elem{ + Stream_type: stype, + Elementary_stream_id: esid, + } } // program_stream_map() { @@ -351,171 +351,171 @@ func NewElementary_stream_elem(stype uint8, esid uint8) *Elementary_stream_elem // } type Program_stream_map struct { - Map_stream_id uint8 - Program_stream_map_length uint16 - Current_next_indicator uint8 - Program_stream_map_version uint8 - Program_stream_info_length uint16 - Elementary_stream_map_length uint16 - Stream_map []*Elementary_stream_elem + Map_stream_id uint8 + Program_stream_map_length uint16 + Current_next_indicator uint8 + Program_stream_map_version uint8 + Program_stream_info_length uint16 + Elementary_stream_map_length uint16 + Stream_map []*Elementary_stream_elem } func (psm *Program_stream_map) PrettyPrint(file *os.File) { - file.WriteString(fmt.Sprintf("map_stream_id:%d\n", psm.Map_stream_id)) - file.WriteString(fmt.Sprintf("program_stream_map_length:%d\n", psm.Program_stream_map_length)) - file.WriteString(fmt.Sprintf("current_next_indicator:%d\n", psm.Current_next_indicator)) - file.WriteString(fmt.Sprintf("program_stream_map_version:%d\n", psm.Program_stream_map_version)) - file.WriteString(fmt.Sprintf("program_stream_info_length:%d\n", psm.Program_stream_info_length)) - file.WriteString(fmt.Sprintf("elementary_stream_map_length:%d\n", psm.Elementary_stream_map_length)) - for i, es := range psm.Stream_map { - file.WriteString(fmt.Sprintf("----ES stream %d\n", i)) - if es.Stream_type == uint8(PS_STREAM_AAC) { - file.WriteString(" stream_type:AAC\n") - } else if es.Stream_type == uint8(PS_STREAM_G711A) { - file.WriteString(" stream_type:G711A\n") - } else if es.Stream_type == uint8(PS_STREAM_G711U) { - file.WriteString(" stream_type:G711U\n") - } else if es.Stream_type == uint8(PS_STREAM_H264) { - file.WriteString(" stream_type:H264\n") - } else if es.Stream_type == uint8(PS_STREAM_H265) { - file.WriteString(" stream_type:H265\n") - } - file.WriteString(fmt.Sprintf(" elementary_stream_id:%d\n", es.Elementary_stream_id)) - file.WriteString(fmt.Sprintf(" elementary_stream_info_length:%d\n", es.Elementary_stream_info_length)) - } + file.WriteString(fmt.Sprintf("map_stream_id:%d\n", psm.Map_stream_id)) + file.WriteString(fmt.Sprintf("program_stream_map_length:%d\n", psm.Program_stream_map_length)) + file.WriteString(fmt.Sprintf("current_next_indicator:%d\n", psm.Current_next_indicator)) + file.WriteString(fmt.Sprintf("program_stream_map_version:%d\n", psm.Program_stream_map_version)) + file.WriteString(fmt.Sprintf("program_stream_info_length:%d\n", psm.Program_stream_info_length)) + file.WriteString(fmt.Sprintf("elementary_stream_map_length:%d\n", psm.Elementary_stream_map_length)) + for i, es := range psm.Stream_map { + file.WriteString(fmt.Sprintf("----ES stream %d\n", i)) + if es.Stream_type == uint8(PS_STREAM_AAC) { + file.WriteString(" stream_type:AAC\n") + } else if es.Stream_type == uint8(PS_STREAM_G711A) { + file.WriteString(" stream_type:G711A\n") + } else if es.Stream_type == uint8(PS_STREAM_G711U) { + file.WriteString(" stream_type:G711U\n") + } else if es.Stream_type == uint8(PS_STREAM_H264) { + file.WriteString(" stream_type:H264\n") + } else if es.Stream_type == uint8(PS_STREAM_H265) { + file.WriteString(" stream_type:H265\n") + } + file.WriteString(fmt.Sprintf(" elementary_stream_id:%d\n", es.Elementary_stream_id)) + file.WriteString(fmt.Sprintf(" elementary_stream_info_length:%d\n", es.Elementary_stream_info_length)) + } } func (psm *Program_stream_map) Encode(bsw *codec.BitStreamWriter) { - bsw.PutBytes([]byte{0x00, 0x00, 0x01, 0xBC}) - loc := bsw.ByteOffset() - bsw.PutUint16(psm.Program_stream_map_length, 16) - bsw.Markdot() - bsw.PutUint8(psm.Current_next_indicator, 1) - bsw.PutUint8(3, 2) - bsw.PutUint8(psm.Program_stream_map_version, 5) - bsw.PutUint8(0x7F, 7) - bsw.PutUint8(1, 1) - bsw.PutUint16(0, 16) - psm.Elementary_stream_map_length = uint16(len(psm.Stream_map) * 4) - bsw.PutUint16(psm.Elementary_stream_map_length, 16) - for _, streaminfo := range psm.Stream_map { - bsw.PutUint8(streaminfo.Stream_type, 8) - bsw.PutUint8(streaminfo.Elementary_stream_id, 8) - bsw.PutUint16(0, 16) - } - length := bsw.DistanceFromMarkDot()/8 + 4 - bsw.SetUint16(uint16(length), loc) - crc := codec.CalcCrc32(0xffffffff, bsw.Bits()[bsw.ByteOffset()-int(length-4)-4:bsw.ByteOffset()]) - tmpcrc := make([]byte, 4) - binary.LittleEndian.PutUint32(tmpcrc, crc) - bsw.PutBytes(tmpcrc) + bsw.PutBytes([]byte{0x00, 0x00, 0x01, 0xBC}) + loc := bsw.ByteOffset() + bsw.PutUint16(psm.Program_stream_map_length, 16) + bsw.Markdot() + bsw.PutUint8(psm.Current_next_indicator, 1) + bsw.PutUint8(3, 2) + bsw.PutUint8(psm.Program_stream_map_version, 5) + bsw.PutUint8(0x7F, 7) + bsw.PutUint8(1, 1) + bsw.PutUint16(0, 16) + psm.Elementary_stream_map_length = uint16(len(psm.Stream_map) * 4) + bsw.PutUint16(psm.Elementary_stream_map_length, 16) + for _, streaminfo := range psm.Stream_map { + bsw.PutUint8(streaminfo.Stream_type, 8) + bsw.PutUint8(streaminfo.Elementary_stream_id, 8) + bsw.PutUint16(0, 16) + } + length := bsw.DistanceFromMarkDot()/8 + 4 + bsw.SetUint16(uint16(length), loc) + crc := codec.CalcCrc32(0xffffffff, bsw.Bits()[bsw.ByteOffset()-int(length-4)-4:bsw.ByteOffset()]) + tmpcrc := make([]byte, 4) + binary.LittleEndian.PutUint32(tmpcrc, crc) + bsw.PutBytes(tmpcrc) } func (psm *Program_stream_map) Decode(bs *codec.BitStream) error { - if bs.RemainBytes() < 16 { - return errNeedMore - } - if bs.Uint32(24) != 0x000001 { - panic("program stream map must startwith 0x000001") - } - psm.Map_stream_id = bs.Uint8(8) - if psm.Map_stream_id != 0xBC { - panic("map stream id must be 0xBC") - } - psm.Program_stream_map_length = bs.Uint16(16) - if bs.RemainBytes() < int(psm.Program_stream_map_length) { - bs.UnRead(6 * 8) - return errNeedMore - } - psm.Current_next_indicator = bs.Uint8(1) - bs.SkipBits(2) - psm.Program_stream_map_version = bs.Uint8(5) - bs.SkipBits(8) - psm.Program_stream_info_length = bs.Uint16(16) - if bs.RemainBytes() < int(psm.Program_stream_info_length)+2 { - bs.UnRead(10 * 8) - return errNeedMore - } - bs.SkipBits(int(psm.Program_stream_info_length) * 8) - psm.Elementary_stream_map_length = bs.Uint16(16) - if psm.Program_stream_map_length != 6+psm.Program_stream_info_length+psm.Elementary_stream_map_length+4 { - return errParser - } - if bs.RemainBytes() < int(psm.Elementary_stream_map_length)+4 { - bs.UnRead(12*8 + int(psm.Program_stream_info_length)*8) - return errNeedMore - } + if bs.RemainBytes() < 16 { + return errNeedMore + } + if bs.Uint32(24) != 0x000001 { + panic("program stream map must startwith 0x000001") + } + psm.Map_stream_id = bs.Uint8(8) + if psm.Map_stream_id != 0xBC { + panic("map stream id must be 0xBC") + } + psm.Program_stream_map_length = bs.Uint16(16) + if bs.RemainBytes() < int(psm.Program_stream_map_length) { + bs.UnRead(6 * 8) + return errNeedMore + } + psm.Current_next_indicator = bs.Uint8(1) + bs.SkipBits(2) + psm.Program_stream_map_version = bs.Uint8(5) + bs.SkipBits(8) + psm.Program_stream_info_length = bs.Uint16(16) + if bs.RemainBytes() < int(psm.Program_stream_info_length)+2 { + bs.UnRead(10 * 8) + return errNeedMore + } + bs.SkipBits(int(psm.Program_stream_info_length) * 8) + psm.Elementary_stream_map_length = bs.Uint16(16) + if psm.Program_stream_map_length != 6+psm.Program_stream_info_length+psm.Elementary_stream_map_length+4 { + return errParser + } + if bs.RemainBytes() < int(psm.Elementary_stream_map_length)+4 { + bs.UnRead(12*8 + int(psm.Program_stream_info_length)*8) + return errNeedMore + } - i := 0 - psm.Stream_map = psm.Stream_map[:0] - for i < int(psm.Elementary_stream_map_length) { - elem := new(Elementary_stream_elem) - elem.Stream_type = bs.Uint8(8) - elem.Elementary_stream_id = bs.Uint8(8) - elem.Elementary_stream_info_length = bs.Uint16(16) - //TODO Parser descriptor - if bs.RemainBytes() < int(elem.Elementary_stream_info_length) { - return errParser - } - bs.SkipBits(int(elem.Elementary_stream_info_length) * 8) - i += int(4 + elem.Elementary_stream_info_length) - psm.Stream_map = append(psm.Stream_map, elem) - } + i := 0 + psm.Stream_map = psm.Stream_map[:0] + for i < int(psm.Elementary_stream_map_length) { + elem := new(Elementary_stream_elem) + elem.Stream_type = bs.Uint8(8) + elem.Elementary_stream_id = bs.Uint8(8) + elem.Elementary_stream_info_length = bs.Uint16(16) + //TODO Parser descriptor + if bs.RemainBytes() < int(elem.Elementary_stream_info_length) { + return errParser + } + bs.SkipBits(int(elem.Elementary_stream_info_length) * 8) + i += int(4 + elem.Elementary_stream_info_length) + psm.Stream_map = append(psm.Stream_map, elem) + } - if i != int(psm.Elementary_stream_map_length) { - return errParser - } + if i != int(psm.Elementary_stream_map_length) { + return errParser + } - bs.SkipBits(32) - return nil + bs.SkipBits(32) + return nil } type Program_stream_directory struct { - PES_packet_length uint16 + PES_packet_length uint16 } func (psd *Program_stream_directory) Decode(bs *codec.BitStream) error { - if bs.RemainBytes() < 6 { - return errNeedMore - } - if bs.Uint32(32) != 0x000001FF { - panic("program stream directory 000001FF") - } - psd.PES_packet_length = bs.Uint16(16) - if bs.RemainBytes() < int(psd.PES_packet_length) { - bs.UnRead(6 * 8) - return errNeedMore - } - //TODO Program Stream directory - bs.SkipBits(int(psd.PES_packet_length) * 8) - return nil + if bs.RemainBytes() < 6 { + return errNeedMore + } + if bs.Uint32(32) != 0x000001FF { + panic("program stream directory 000001FF") + } + psd.PES_packet_length = bs.Uint16(16) + if bs.RemainBytes() < int(psd.PES_packet_length) { + bs.UnRead(6 * 8) + return errNeedMore + } + //TODO Program Stream directory + bs.SkipBits(int(psd.PES_packet_length) * 8) + return nil } type CommonPesPacket struct { - Stream_id uint8 - PES_packet_length uint16 + Stream_id uint8 + PES_packet_length uint16 } func (compes *CommonPesPacket) Decode(bs *codec.BitStream) error { - if bs.RemainBytes() < 6 { - return errNeedMore - } - bs.SkipBits(24) - compes.Stream_id = bs.Uint8(8) - compes.PES_packet_length = bs.Uint16(16) - if bs.RemainBytes() < int(compes.PES_packet_length) { - bs.UnRead(6 * 8) - return errNeedMore - } - bs.SkipBits(int(compes.PES_packet_length) * 8) - return nil + if bs.RemainBytes() < 6 { + return errNeedMore + } + bs.SkipBits(24) + compes.Stream_id = bs.Uint8(8) + compes.PES_packet_length = bs.Uint16(16) + if bs.RemainBytes() < int(compes.PES_packet_length) { + bs.UnRead(6 * 8) + return errNeedMore + } + bs.SkipBits(int(compes.PES_packet_length) * 8) + return nil } type PSPacket struct { - Header *PSPackHeader - System *System_header - Psm *Program_stream_map - Psd *Program_stream_directory - CommPes *CommonPesPacket - Pes *PesPacket + Header *PSPackHeader + System *System_header + Psm *Program_stream_map + Psd *Program_stream_directory + CommPes *CommonPesPacket + Pes *PesPacket } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/mpeg2/ts-demuxer.go b/trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/mpeg2/ts-demuxer.go index 988b7375b..4bfb4244a 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/mpeg2/ts-demuxer.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/mpeg2/ts-demuxer.go @@ -1,218 +1,218 @@ package mpeg2 import ( - "errors" - "io" + "errors" + "io" - "github.com/yapingcat/gomedia/codec" + "github.com/yapingcat/gomedia/codec" ) type pakcet_t struct { - payload []byte - pts uint64 - dts uint64 + payload []byte + pts uint64 + dts uint64 } func newPacket_t(size uint32) *pakcet_t { - return &pakcet_t{ - payload: make([]byte, 0, size), - pts: 0, - dts: 0, - } + return &pakcet_t{ + payload: make([]byte, 0, size), + pts: 0, + dts: 0, + } } type tsstream struct { - cid TS_STREAM_TYPE - pes_sid PES_STREMA_ID - pes_pkg *PesPacket - pkg *pakcet_t + cid TS_STREAM_TYPE + pes_sid PES_STREMA_ID + pes_pkg *PesPacket + pkg *pakcet_t } type tsprogram struct { - pn uint16 - streams map[uint16]*tsstream + pn uint16 + streams map[uint16]*tsstream } type TSDemuxer struct { - programs map[uint16]*tsprogram - OnFrame func(cid TS_STREAM_TYPE, frame []byte, pts uint64, dts uint64) - OnTSPacket func(pkg *TSPacket) + programs map[uint16]*tsprogram + OnFrame func(cid TS_STREAM_TYPE, frame []byte, pts uint64, dts uint64) + OnTSPacket func(pkg *TSPacket) } func NewTSDemuxer() *TSDemuxer { - return &TSDemuxer{ - programs: make(map[uint16]*tsprogram), - OnFrame: nil, - OnTSPacket: nil, - } + return &TSDemuxer{ + programs: make(map[uint16]*tsprogram), + OnFrame: nil, + OnTSPacket: nil, + } } func (demuxer *TSDemuxer) Input(r io.Reader) error { - buf := make([]byte, TS_PAKCET_SIZE) - _, err := io.ReadFull(r, buf) - if err != nil { - return errNeedMore - } - for { - bs := codec.NewBitStream(buf) - var pkg TSPacket - if err := pkg.DecodeHeader(bs); err != nil { - return err - } - if pkg.PID == uint16(TS_PID_PAT) { - if pkg.Payload_unit_start_indicator == 1 { - bs.SkipBits(8) - } - pat := NewPat() - if err := pat.Decode(bs); err != nil { - return err - } - pkg.Payload = pat - if pat.Table_id != uint8(TS_TID_PAS) { - return errors.New("pat table id is wrong") - } - for _, pmt := range pat.Pmts { - if pmt.Program_number != 0x0000 { - if _, found := demuxer.programs[pmt.PID]; !found { - demuxer.programs[pmt.PID] = &tsprogram{pn: 0, streams: make(map[uint16]*tsstream)} - } - } - } - } else { - for p, s := range demuxer.programs { - if p == pkg.PID { // pmt table - if pkg.Payload_unit_start_indicator == 1 { - bs.SkipBits(8) //pointer filed - } - pmt := NewPmt() - if err := pmt.Decode(bs); err != nil { - return err - } - pkg.Payload = pmt - s.pn = pmt.Program_number - for _, ps := range pmt.Streams { - if _, found := s.streams[ps.Elementary_PID]; !found { - s.streams[ps.Elementary_PID] = &tsstream{ - cid: TS_STREAM_TYPE(ps.StreamType), - pes_sid: findPESIDByStreamType(TS_STREAM_TYPE(ps.StreamType)), - pes_pkg: NewPesPacket(), - } - } - } - } else { - for sid, stream := range s.streams { - if sid != pkg.PID { - continue - } - if pkg.Payload_unit_start_indicator == 1 { - err := stream.pes_pkg.Decode(bs) - // ignore error if it was a short payload read, next ts packet should append missing data - if err != nil && !(errors.Is(err, errNeedMore) && stream.pes_pkg.Pes_payload != nil) { - return err - } - pkg.Payload = stream.pes_pkg - } else { - stream.pes_pkg.Pes_payload = bs.RemainData() - pkg.Payload = bs.RemainData() - } - stype := findPESIDByStreamType(stream.cid) - if stype == PES_STREAM_AUDIO { - demuxer.doAudioPesPacket(stream, pkg.Payload_unit_start_indicator) - } else if stype == PES_STREAM_VIDEO { - demuxer.doVideoPesPacket(stream, pkg.Payload_unit_start_indicator) - } - } - } - } - } - if demuxer.OnTSPacket != nil { - demuxer.OnTSPacket(&pkg) - } - _, err := io.ReadFull(r, buf) - if err != nil { - if errors.Is(err, io.EOF) { - break - } else { - return errNeedMore - } - } - } - demuxer.flush() - return nil + buf := make([]byte, TS_PAKCET_SIZE) + _, err := io.ReadFull(r, buf) + if err != nil { + return errNeedMore + } + for { + bs := codec.NewBitStream(buf) + var pkg TSPacket + if err := pkg.DecodeHeader(bs); err != nil { + return err + } + if pkg.PID == uint16(TS_PID_PAT) { + if pkg.Payload_unit_start_indicator == 1 { + bs.SkipBits(8) + } + pat := NewPat() + if err := pat.Decode(bs); err != nil { + return err + } + pkg.Payload = pat + if pat.Table_id != uint8(TS_TID_PAS) { + return errors.New("pat table id is wrong") + } + for _, pmt := range pat.Pmts { + if pmt.Program_number != 0x0000 { + if _, found := demuxer.programs[pmt.PID]; !found { + demuxer.programs[pmt.PID] = &tsprogram{pn: 0, streams: make(map[uint16]*tsstream)} + } + } + } + } else { + for p, s := range demuxer.programs { + if p == pkg.PID { // pmt table + if pkg.Payload_unit_start_indicator == 1 { + bs.SkipBits(8) //pointer filed + } + pmt := NewPmt() + if err := pmt.Decode(bs); err != nil { + return err + } + pkg.Payload = pmt + s.pn = pmt.Program_number + for _, ps := range pmt.Streams { + if _, found := s.streams[ps.Elementary_PID]; !found { + s.streams[ps.Elementary_PID] = &tsstream{ + cid: TS_STREAM_TYPE(ps.StreamType), + pes_sid: findPESIDByStreamType(TS_STREAM_TYPE(ps.StreamType)), + pes_pkg: NewPesPacket(), + } + } + } + } else { + for sid, stream := range s.streams { + if sid != pkg.PID { + continue + } + if pkg.Payload_unit_start_indicator == 1 { + err := stream.pes_pkg.Decode(bs) + // ignore error if it was a short payload read, next ts packet should append missing data + if err != nil && !(errors.Is(err, errNeedMore) && stream.pes_pkg.Pes_payload != nil) { + return err + } + pkg.Payload = stream.pes_pkg + } else { + stream.pes_pkg.Pes_payload = bs.RemainData() + pkg.Payload = bs.RemainData() + } + stype := findPESIDByStreamType(stream.cid) + if stype == PES_STREAM_AUDIO { + demuxer.doAudioPesPacket(stream, pkg.Payload_unit_start_indicator) + } else if stype == PES_STREAM_VIDEO { + demuxer.doVideoPesPacket(stream, pkg.Payload_unit_start_indicator) + } + } + } + } + } + if demuxer.OnTSPacket != nil { + demuxer.OnTSPacket(&pkg) + } + _, err := io.ReadFull(r, buf) + if err != nil { + if errors.Is(err, io.EOF) { + break + } else { + return errNeedMore + } + } + } + demuxer.flush() + return nil } func (demuxer *TSDemuxer) flush() { - for _, pm := range demuxer.programs { - for _, stream := range pm.streams { - if stream.pkg == nil || len(stream.pkg.payload) == 0 { - continue - } - if demuxer.OnFrame != nil { - demuxer.OnFrame(stream.cid, stream.pkg.payload, stream.pkg.pts/90, stream.pkg.dts/90) - } - } - } + for _, pm := range demuxer.programs { + for _, stream := range pm.streams { + if stream.pkg == nil || len(stream.pkg.payload) == 0 { + continue + } + if demuxer.OnFrame != nil { + demuxer.OnFrame(stream.cid, stream.pkg.payload, stream.pkg.pts/90, stream.pkg.dts/90) + } + } + } } func (demuxer *TSDemuxer) doVideoPesPacket(stream *tsstream, start uint8) { - if stream.cid != TS_STREAM_H264 && stream.cid != TS_STREAM_H265 { - return - } - if stream.pkg == nil { - stream.pkg = newPacket_t(1024) - stream.pkg.pts = stream.pes_pkg.Pts - stream.pkg.dts = stream.pes_pkg.Dts - } - stream.pkg.payload = append(stream.pkg.payload, stream.pes_pkg.Pes_payload...) - demuxer.splitH26XFrame(stream) - stream.pkg.pts = stream.pes_pkg.Pts - stream.pkg.dts = stream.pes_pkg.Dts + if stream.cid != TS_STREAM_H264 && stream.cid != TS_STREAM_H265 { + return + } + if stream.pkg == nil { + stream.pkg = newPacket_t(1024) + stream.pkg.pts = stream.pes_pkg.Pts + stream.pkg.dts = stream.pes_pkg.Dts + } + stream.pkg.payload = append(stream.pkg.payload, stream.pes_pkg.Pes_payload...) + demuxer.splitH26XFrame(stream) + stream.pkg.pts = stream.pes_pkg.Pts + stream.pkg.dts = stream.pes_pkg.Dts } func (demuxer *TSDemuxer) doAudioPesPacket(stream *tsstream, start uint8) { - if stream.cid != TS_STREAM_AAC { - return - } + if stream.cid != TS_STREAM_AAC { + return + } - if stream.pkg == nil { - stream.pkg = newPacket_t(1024) - stream.pkg.pts = stream.pes_pkg.Pts - stream.pkg.dts = stream.pes_pkg.Dts - } + if stream.pkg == nil { + stream.pkg = newPacket_t(1024) + stream.pkg.pts = stream.pes_pkg.Pts + stream.pkg.dts = stream.pes_pkg.Dts + } - if len(stream.pkg.payload) > 0 && (start == 1 || stream.pes_pkg.Pts != stream.pkg.pts) { - if demuxer.OnFrame != nil { - demuxer.OnFrame(stream.cid, stream.pkg.payload, stream.pkg.pts/90, stream.pkg.dts/90) - } - stream.pkg.payload = stream.pkg.payload[:0] - } - stream.pkg.payload = append(stream.pkg.payload, stream.pes_pkg.Pes_payload...) - stream.pkg.pts = stream.pes_pkg.Pts - stream.pkg.dts = stream.pes_pkg.Dts + if len(stream.pkg.payload) > 0 && (start == 1 || stream.pes_pkg.Pts != stream.pkg.pts) { + if demuxer.OnFrame != nil { + demuxer.OnFrame(stream.cid, stream.pkg.payload, stream.pkg.pts/90, stream.pkg.dts/90) + } + stream.pkg.payload = stream.pkg.payload[:0] + } + stream.pkg.payload = append(stream.pkg.payload, stream.pes_pkg.Pes_payload...) + stream.pkg.pts = stream.pes_pkg.Pts + stream.pkg.dts = stream.pes_pkg.Dts } func (demuxer *TSDemuxer) splitH26XFrame(stream *tsstream) { - data := stream.pkg.payload - start, _ := codec.FindStartCode(data, 0) - datalen := len(data) - for start < datalen { - end, _ := codec.FindStartCode(data, start+3) - if end < 0 { - break - } - if (stream.cid == TS_STREAM_H264 && codec.H264NaluTypeWithoutStartCode(data[start:end]) == codec.H264_NAL_AUD) || - (stream.cid == TS_STREAM_H265 && codec.H265NaluTypeWithoutStartCode(data[start:end]) == codec.H265_NAL_AUD) { - start = end - continue - } - if demuxer.OnFrame != nil { - demuxer.OnFrame(stream.cid, data[start:end], stream.pkg.pts/90, stream.pkg.dts/90) - } - start = end - } - if start == 0 { - return - } - copy(stream.pkg.payload, data[start:datalen]) - stream.pkg.payload = stream.pkg.payload[0 : datalen-start] + data := stream.pkg.payload + start, _ := codec.FindStartCode(data, 0) + datalen := len(data) + for start < datalen { + end, _ := codec.FindStartCode(data, start+3) + if end < 0 { + break + } + if (stream.cid == TS_STREAM_H264 && codec.H264NaluTypeWithoutStartCode(data[start:end]) == codec.H264_NAL_AUD) || + (stream.cid == TS_STREAM_H265 && codec.H265NaluTypeWithoutStartCode(data[start:end]) == codec.H265_NAL_AUD) { + start = end + continue + } + if demuxer.OnFrame != nil { + demuxer.OnFrame(stream.cid, data[start:end], stream.pkg.pts/90, stream.pkg.dts/90) + } + start = end + } + if start == 0 { + return + } + copy(stream.pkg.payload, data[start:datalen]) + stream.pkg.payload = stream.pkg.payload[0 : datalen-start] } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/mpeg2/ts-muxer.go b/trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/mpeg2/ts-muxer.go index 0308577ef..804b85309 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/mpeg2/ts-muxer.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/mpeg2/ts-muxer.go @@ -1,93 +1,93 @@ package mpeg2 import ( - "errors" + "errors" - "github.com/yapingcat/gomedia/codec" + "github.com/yapingcat/gomedia/codec" ) type pes_stream struct { - pid uint16 - cc uint8 - streamtype TS_STREAM_TYPE + pid uint16 + cc uint8 + streamtype TS_STREAM_TYPE } func NewPESStream(pid uint16, cid TS_STREAM_TYPE) *pes_stream { - return &pes_stream{ - pid: pid, - cc: 0, - streamtype: cid, - } + return &pes_stream{ + pid: pid, + cc: 0, + streamtype: cid, + } } type table_pmt struct { - pid uint16 - cc uint8 - pcr_pid uint16 - version_number uint8 - pm uint16 - streams []*pes_stream + pid uint16 + cc uint8 + pcr_pid uint16 + version_number uint8 + pm uint16 + streams []*pes_stream } func NewTablePmt() *table_pmt { - return &table_pmt{ - pid: 0, - cc: 0, - pcr_pid: 0, - version_number: 0, - pm: 0, - streams: make([]*pes_stream, 0, 2), - } + return &table_pmt{ + pid: 0, + cc: 0, + pcr_pid: 0, + version_number: 0, + pm: 0, + streams: make([]*pes_stream, 0, 2), + } } type table_pat struct { - cc uint8 - version_number uint8 - pmts []*table_pmt + cc uint8 + version_number uint8 + pmts []*table_pmt } func NewTablePat() *table_pat { - return &table_pat{ - cc: 0, - version_number: 0, - pmts: make([]*table_pmt, 0, 8), - } + return &table_pat{ + cc: 0, + version_number: 0, + pmts: make([]*table_pmt, 0, 8), + } } type TSMuxer struct { - pat *table_pat - stream_pid uint16 - pmt_pid uint16 - pat_period uint64 - OnPacket func(pkg []byte) + pat *table_pat + stream_pid uint16 + pmt_pid uint16 + pat_period uint64 + OnPacket func(pkg []byte) } func NewTSMuxer() *TSMuxer { - return &TSMuxer{ - pat: NewTablePat(), - stream_pid: 0x100, - pmt_pid: 0x200, - pat_period: 0, - OnPacket: nil, - } + return &TSMuxer{ + pat: NewTablePat(), + stream_pid: 0x100, + pmt_pid: 0x200, + pat_period: 0, + OnPacket: nil, + } } func (mux *TSMuxer) AddStream(cid TS_STREAM_TYPE) uint16 { - if mux.pat == nil { - mux.pat = NewTablePat() - } - if len(mux.pat.pmts) == 0 { - tmppmt := NewTablePmt() - tmppmt.pid = mux.pmt_pid - tmppmt.pm = 1 - mux.pmt_pid++ - mux.pat.pmts = append(mux.pat.pmts, tmppmt) - } - sid := mux.stream_pid - tmpstream := NewPESStream(sid, cid) - mux.stream_pid++ - mux.pat.pmts[0].streams = append(mux.pat.pmts[0].streams, tmpstream) - return sid + if mux.pat == nil { + mux.pat = NewTablePat() + } + if len(mux.pat.pmts) == 0 { + tmppmt := NewTablePmt() + tmppmt.pid = mux.pmt_pid + tmppmt.pm = 1 + mux.pmt_pid++ + mux.pat.pmts = append(mux.pat.pmts, tmppmt) + } + sid := mux.stream_pid + tmpstream := NewPESStream(sid, cid) + mux.stream_pid++ + mux.pat.pmts[0].streams = append(mux.pat.pmts[0].streams, tmpstream) + return sid } /// Muxer audio/video stream data @@ -95,239 +95,239 @@ func (mux *TSMuxer) AddStream(cid TS_STREAM_TYPE) uint16 { /// pts: audio/video stream timestamp in ms /// dts: audio/video stream timestamp in ms func (mux *TSMuxer) Write(pid uint16, data []byte, pts uint64, dts uint64) error { - var whichpmt *table_pmt = nil - var whichstream *pes_stream = nil - for _, pmt := range mux.pat.pmts { - for _, stream := range pmt.streams { - if stream.pid == pid { - whichpmt = pmt - whichstream = stream - break - } - } - } - if whichpmt == nil || whichstream == nil { - return errors.New("not Found pid stream") - } - if whichpmt.pcr_pid == 0 || (findPESIDByStreamType(whichstream.streamtype) == PES_STREAM_VIDEO && whichpmt.pcr_pid != pid) { - whichpmt.pcr_pid = pid - } + var whichpmt *table_pmt = nil + var whichstream *pes_stream = nil + for _, pmt := range mux.pat.pmts { + for _, stream := range pmt.streams { + if stream.pid == pid { + whichpmt = pmt + whichstream = stream + break + } + } + } + if whichpmt == nil || whichstream == nil { + return errors.New("not Found pid stream") + } + if whichpmt.pcr_pid == 0 || (findPESIDByStreamType(whichstream.streamtype) == PES_STREAM_VIDEO && whichpmt.pcr_pid != pid) { + whichpmt.pcr_pid = pid + } - var withaud bool = false + var withaud bool = false - if whichstream.streamtype == TS_STREAM_H264 || whichstream.streamtype == TS_STREAM_H265 { - codec.SplitFrame(data, func(nalu []byte) bool { - if whichstream.streamtype == TS_STREAM_H264 { - nalu_type := codec.H264NaluTypeWithoutStartCode(nalu) - if nalu_type == codec.H264_NAL_AUD { - withaud = true - return false - } else if codec.IsH264VCLNaluType(nalu_type) { - return false - } - return true - } else { - nalu_type := codec.H265NaluTypeWithoutStartCode(nalu) - if nalu_type == codec.H265_NAL_AUD { - withaud = true - return false - } else if codec.IsH265VCLNaluType(nalu_type) { - return false - } - return true - } - }) - } + if whichstream.streamtype == TS_STREAM_H264 || whichstream.streamtype == TS_STREAM_H265 { + codec.SplitFrame(data, func(nalu []byte) bool { + if whichstream.streamtype == TS_STREAM_H264 { + nalu_type := codec.H264NaluTypeWithoutStartCode(nalu) + if nalu_type == codec.H264_NAL_AUD { + withaud = true + return false + } else if codec.IsH264VCLNaluType(nalu_type) { + return false + } + return true + } else { + nalu_type := codec.H265NaluTypeWithoutStartCode(nalu) + if nalu_type == codec.H265_NAL_AUD { + withaud = true + return false + } else if codec.IsH265VCLNaluType(nalu_type) { + return false + } + return true + } + }) + } - if mux.pat_period == 0 || mux.pat_period+400 < dts { - mux.pat_period = dts - if mux.pat_period == 0 { - mux.pat_period = 1 //avoid write pat twice - } - tmppat := NewPat() - tmppat.Version_number = mux.pat.version_number - for _, pmt := range mux.pat.pmts { - tmppm := PmtPair{ - Program_number: pmt.pm, - PID: pmt.pid, - } - tmppat.Pmts = append(tmppat.Pmts, tmppm) - } - mux.writePat(tmppat) + if mux.pat_period == 0 || mux.pat_period+400 < dts { + mux.pat_period = dts + if mux.pat_period == 0 { + mux.pat_period = 1 //avoid write pat twice + } + tmppat := NewPat() + tmppat.Version_number = mux.pat.version_number + for _, pmt := range mux.pat.pmts { + tmppm := PmtPair{ + Program_number: pmt.pm, + PID: pmt.pid, + } + tmppat.Pmts = append(tmppat.Pmts, tmppm) + } + mux.writePat(tmppat) - for _, pmt := range mux.pat.pmts { - tmppmt := NewPmt() - tmppmt.Program_number = pmt.pm - tmppmt.Version_number = pmt.version_number - tmppmt.PCR_PID = pmt.pcr_pid - for _, stream := range pmt.streams { - var sp StreamPair - sp.StreamType = uint8(stream.streamtype) - sp.Elementary_PID = stream.pid - sp.ES_Info_Length = 0 - tmppmt.Streams = append(tmppmt.Streams, sp) - } - mux.writePmt(tmppmt, pmt) - } - } + for _, pmt := range mux.pat.pmts { + tmppmt := NewPmt() + tmppmt.Program_number = pmt.pm + tmppmt.Version_number = pmt.version_number + tmppmt.PCR_PID = pmt.pcr_pid + for _, stream := range pmt.streams { + var sp StreamPair + sp.StreamType = uint8(stream.streamtype) + sp.Elementary_PID = stream.pid + sp.ES_Info_Length = 0 + tmppmt.Streams = append(tmppmt.Streams, sp) + } + mux.writePmt(tmppmt, pmt) + } + } - flag := false - switch whichstream.streamtype { - case TS_STREAM_H264: - flag = codec.IsH264IDRFrame(data) - case TS_STREAM_H265: - flag = codec.IsH265IDRFrame(data) - } + flag := false + switch whichstream.streamtype { + case TS_STREAM_H264: + flag = codec.IsH264IDRFrame(data) + case TS_STREAM_H265: + flag = codec.IsH265IDRFrame(data) + } - mux.writePES(whichstream, whichpmt, data, pts*90, dts*90, flag, withaud) - return nil + mux.writePES(whichstream, whichpmt, data, pts*90, dts*90, flag, withaud) + return nil } func (mux *TSMuxer) writePat(pat *Pat) { - var tshdr TSPacket - tshdr.Payload_unit_start_indicator = 1 - tshdr.PID = 0 - tshdr.Adaptation_field_control = 0x01 - tshdr.Continuity_counter = mux.pat.cc - mux.pat.cc++ - mux.pat.cc = (mux.pat.cc + 1) % 16 - bsw := codec.NewBitStreamWriter(TS_PAKCET_SIZE) - tshdr.EncodeHeader(bsw) - bsw.PutByte(0x00) //pointer - pat.Encode(bsw) - bsw.FillRemainData(0xff) - if mux.OnPacket != nil { - mux.OnPacket(bsw.Bits()) - } + var tshdr TSPacket + tshdr.Payload_unit_start_indicator = 1 + tshdr.PID = 0 + tshdr.Adaptation_field_control = 0x01 + tshdr.Continuity_counter = mux.pat.cc + mux.pat.cc++ + mux.pat.cc = (mux.pat.cc + 1) % 16 + bsw := codec.NewBitStreamWriter(TS_PAKCET_SIZE) + tshdr.EncodeHeader(bsw) + bsw.PutByte(0x00) //pointer + pat.Encode(bsw) + bsw.FillRemainData(0xff) + if mux.OnPacket != nil { + mux.OnPacket(bsw.Bits()) + } } func (mux *TSMuxer) writePmt(pmt *Pmt, t_pmt *table_pmt) { - var tshdr TSPacket - tshdr.Payload_unit_start_indicator = 1 - tshdr.PID = t_pmt.pid - tshdr.Adaptation_field_control = 0x01 - tshdr.Continuity_counter = t_pmt.cc - t_pmt.cc = (t_pmt.cc + 1) % 16 - bsw := codec.NewBitStreamWriter(TS_PAKCET_SIZE) - tshdr.EncodeHeader(bsw) - bsw.PutByte(0x00) //pointer - pmt.Encode(bsw) - bsw.FillRemainData(0xff) - if mux.OnPacket != nil { - mux.OnPacket(bsw.Bits()) - } + var tshdr TSPacket + tshdr.Payload_unit_start_indicator = 1 + tshdr.PID = t_pmt.pid + tshdr.Adaptation_field_control = 0x01 + tshdr.Continuity_counter = t_pmt.cc + t_pmt.cc = (t_pmt.cc + 1) % 16 + bsw := codec.NewBitStreamWriter(TS_PAKCET_SIZE) + tshdr.EncodeHeader(bsw) + bsw.PutByte(0x00) //pointer + pmt.Encode(bsw) + bsw.FillRemainData(0xff) + if mux.OnPacket != nil { + mux.OnPacket(bsw.Bits()) + } } func (mux *TSMuxer) writePES(pes *pes_stream, pmt *table_pmt, data []byte, pts uint64, dts uint64, idr_flag bool, withaud bool) { - var firstPesPacket bool = true - bsw := codec.NewBitStreamWriter(TS_PAKCET_SIZE) - for { - bsw.Reset() - var tshdr TSPacket - if firstPesPacket { - tshdr.Payload_unit_start_indicator = 1 - } - tshdr.PID = pes.pid - tshdr.Adaptation_field_control = 0x01 - tshdr.Continuity_counter = pes.cc - headlen := 4 - pes.cc = (pes.cc + 1) % 16 - var adaptation *Adaptation_field = nil - if firstPesPacket && idr_flag { - adaptation = new(Adaptation_field) - tshdr.Adaptation_field_control = tshdr.Adaptation_field_control | 0x20 - adaptation.Random_access_indicator = 1 - headlen += 2 - } + var firstPesPacket bool = true + bsw := codec.NewBitStreamWriter(TS_PAKCET_SIZE) + for { + bsw.Reset() + var tshdr TSPacket + if firstPesPacket { + tshdr.Payload_unit_start_indicator = 1 + } + tshdr.PID = pes.pid + tshdr.Adaptation_field_control = 0x01 + tshdr.Continuity_counter = pes.cc + headlen := 4 + pes.cc = (pes.cc + 1) % 16 + var adaptation *Adaptation_field = nil + if firstPesPacket && idr_flag { + adaptation = new(Adaptation_field) + tshdr.Adaptation_field_control = tshdr.Adaptation_field_control | 0x20 + adaptation.Random_access_indicator = 1 + headlen += 2 + } - if firstPesPacket && pes.pid == pmt.pcr_pid { - if adaptation == nil { - adaptation = new(Adaptation_field) - headlen += 2 - } - tshdr.Adaptation_field_control = tshdr.Adaptation_field_control | 0x20 - adaptation.PCR_flag = 1 - var pcr_base uint64 = 0 - var pcr_ext uint16 = 0 - if dts == 0 { - pcr_base = pts * 300 / 300 - pcr_ext = uint16(pts * 300 % 300) - } else { - pcr_base = dts * 300 / 300 - pcr_ext = uint16(dts * 300 % 300) - } - adaptation.Program_clock_reference_base = pcr_base - adaptation.Program_clock_reference_extension = pcr_ext - headlen += 6 - } + if firstPesPacket && pes.pid == pmt.pcr_pid { + if adaptation == nil { + adaptation = new(Adaptation_field) + headlen += 2 + } + tshdr.Adaptation_field_control = tshdr.Adaptation_field_control | 0x20 + adaptation.PCR_flag = 1 + var pcr_base uint64 = 0 + var pcr_ext uint16 = 0 + if dts == 0 { + pcr_base = pts * 300 / 300 + pcr_ext = uint16(pts * 300 % 300) + } else { + pcr_base = dts * 300 / 300 + pcr_ext = uint16(dts * 300 % 300) + } + adaptation.Program_clock_reference_base = pcr_base + adaptation.Program_clock_reference_extension = pcr_ext + headlen += 6 + } - var payload []byte - var pespkg *PesPacket = nil - if firstPesPacket { - oldheadlen := headlen - headlen += 19 - if !withaud && pes.streamtype == TS_STREAM_H264 { - headlen += 6 - payload = append(payload, H264_AUD_NALU...) - } else if !withaud && pes.streamtype == TS_STREAM_H265 { - payload = append(payload, H265_AUD_NALU...) - headlen += 7 - } - pespkg = NewPesPacket() - pespkg.PTS_DTS_flags = 0x03 - pespkg.PES_header_data_length = 10 - pespkg.Pts = pts - pespkg.Dts = dts - pespkg.Stream_id = uint8(findPESIDByStreamType(pes.streamtype)) - if idr_flag { - pespkg.Data_alignment_indicator = 1 - } - if headlen-oldheadlen-6+len(data) > 0xFFFF { - pespkg.PES_packet_length = 0 - } else { - pespkg.PES_packet_length = uint16(len(data) + headlen - oldheadlen - 6) - } + var payload []byte + var pespkg *PesPacket = nil + if firstPesPacket { + oldheadlen := headlen + headlen += 19 + if !withaud && pes.streamtype == TS_STREAM_H264 { + headlen += 6 + payload = append(payload, H264_AUD_NALU...) + } else if !withaud && pes.streamtype == TS_STREAM_H265 { + payload = append(payload, H265_AUD_NALU...) + headlen += 7 + } + pespkg = NewPesPacket() + pespkg.PTS_DTS_flags = 0x03 + pespkg.PES_header_data_length = 10 + pespkg.Pts = pts + pespkg.Dts = dts + pespkg.Stream_id = uint8(findPESIDByStreamType(pes.streamtype)) + if idr_flag { + pespkg.Data_alignment_indicator = 1 + } + if headlen-oldheadlen-6+len(data) > 0xFFFF { + pespkg.PES_packet_length = 0 + } else { + pespkg.PES_packet_length = uint16(len(data) + headlen - oldheadlen - 6) + } - } + } - if len(data)+headlen < TS_PAKCET_SIZE { - if adaptation == nil { - adaptation = new(Adaptation_field) - headlen += 1 - if TS_PAKCET_SIZE-len(data)-headlen >= 1 { - headlen += 1 - } else { - adaptation.SingleStuffingByte = true - } - } - adaptation.Stuffing_byte = uint8(TS_PAKCET_SIZE - len(data) - headlen) - payload = append(payload, data...) - data = data[:0] - } else { - payload = append(payload, data[0:TS_PAKCET_SIZE-headlen]...) - data = data[TS_PAKCET_SIZE-headlen:] - } + if len(data)+headlen < TS_PAKCET_SIZE { + if adaptation == nil { + adaptation = new(Adaptation_field) + headlen += 1 + if TS_PAKCET_SIZE-len(data)-headlen >= 1 { + headlen += 1 + } else { + adaptation.SingleStuffingByte = true + } + } + adaptation.Stuffing_byte = uint8(TS_PAKCET_SIZE - len(data) - headlen) + payload = append(payload, data...) + data = data[:0] + } else { + payload = append(payload, data[0:TS_PAKCET_SIZE-headlen]...) + data = data[TS_PAKCET_SIZE-headlen:] + } - if adaptation != nil { - tshdr.Field = adaptation - tshdr.Adaptation_field_control |= 0x02 - } - tshdr.EncodeHeader(bsw) - if pespkg != nil { - pespkg.Pes_payload = payload - pespkg.Encode(bsw) - } else { - bsw.PutBytes(payload) - } - firstPesPacket = false - if mux.OnPacket != nil { - if len(bsw.Bits()) != TS_PAKCET_SIZE { - panic("packet ts packet failed") - } - mux.OnPacket(bsw.Bits()) - } - if len(data) == 0 { - break - } - } + if adaptation != nil { + tshdr.Field = adaptation + tshdr.Adaptation_field_control |= 0x02 + } + tshdr.EncodeHeader(bsw) + if pespkg != nil { + pespkg.Pes_payload = payload + pespkg.Encode(bsw) + } else { + bsw.PutBytes(payload) + } + firstPesPacket = false + if mux.OnPacket != nil { + if len(bsw.Bits()) != TS_PAKCET_SIZE { + panic("packet ts packet failed") + } + mux.OnPacket(bsw.Bits()) + } + if len(data) == 0 { + break + } + } } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/mpeg2/ts-proto.go b/trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/mpeg2/ts-proto.go index da437828c..d0dc3d1eb 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/mpeg2/ts-proto.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/mpeg2/ts-proto.go @@ -1,50 +1,50 @@ package mpeg2 import ( - "encoding/binary" - "errors" - "fmt" - "os" + "encoding/binary" + "errors" + "fmt" + "os" - "github.com/yapingcat/gomedia/codec" + "github.com/yapingcat/gomedia/codec" ) //PID type TS_PID int const ( - TS_PID_PAT TS_PID = 0x0000 - TS_PID_CAT - TS_PID_TSDT - TS_PID_IPMP - TS_PID_Nil = 0x1FFFF + TS_PID_PAT TS_PID = 0x0000 + TS_PID_CAT + TS_PID_TSDT + TS_PID_IPMP + TS_PID_Nil = 0x1FFFF ) //Table id type PAT_TID int const ( - TS_TID_PAS PAT_TID = 0x00 // program_association_section - TS_TID_CAS = 0x01 // conditional_access_section(CA_section) - TS_TID_PMS = 0x02 // TS_program_map_section - TS_TID_SDS = 0x03 //TS_description_section - TS_TID_FORBIDDEN PAT_TID = 0xFF + TS_TID_PAS PAT_TID = 0x00 // program_association_section + TS_TID_CAS = 0x01 // conditional_access_section(CA_section) + TS_TID_PMS = 0x02 // TS_program_map_section + TS_TID_SDS = 0x03 //TS_description_section + TS_TID_FORBIDDEN PAT_TID = 0xFF ) type TS_STREAM_TYPE int const ( - TS_STREAM_AAC TS_STREAM_TYPE = 0x0F - TS_STREAM_H264 TS_STREAM_TYPE = 0x1B - TS_STREAM_H265 TS_STREAM_TYPE = 0x24 + TS_STREAM_AAC TS_STREAM_TYPE = 0x0F + TS_STREAM_H264 TS_STREAM_TYPE = 0x1B + TS_STREAM_H265 TS_STREAM_TYPE = 0x24 ) const ( - TS_PAKCET_SIZE = 188 + TS_PAKCET_SIZE = 188 ) type Display interface { - PrettyPrint(file *os.File) + PrettyPrint(file *os.File) } // transport_packet(){ @@ -67,63 +67,63 @@ type Display interface { // } type TSPacket struct { - Transport_error_indicator uint8 - Payload_unit_start_indicator uint8 - Transport_priority uint8 - PID uint16 - Transport_scrambling_control uint8 - Adaptation_field_control uint8 - Continuity_counter uint8 - Field *Adaptation_field - Payload interface{} + Transport_error_indicator uint8 + Payload_unit_start_indicator uint8 + Transport_priority uint8 + PID uint16 + Transport_scrambling_control uint8 + Adaptation_field_control uint8 + Continuity_counter uint8 + Field *Adaptation_field + Payload interface{} } func (pkg *TSPacket) PrettyPrint(file *os.File) { - file.WriteString(fmt.Sprintf("Transport_error_indicator:%d\n", pkg.Transport_error_indicator)) - file.WriteString(fmt.Sprintf("Payload_unit_start_indicator:%d\n", pkg.Payload_unit_start_indicator)) - file.WriteString(fmt.Sprintf("Transport_priority:%d\n", pkg.Transport_priority)) - file.WriteString(fmt.Sprintf("PID:%d\n", pkg.PID)) - file.WriteString(fmt.Sprintf("Transport_scrambling_control:%d\n", pkg.Transport_scrambling_control)) - file.WriteString(fmt.Sprintf("Adaptation_field_control:%d\n", pkg.Adaptation_field_control)) - file.WriteString(fmt.Sprintf("Continuity_counter:%d\n", pkg.Continuity_counter)) + file.WriteString(fmt.Sprintf("Transport_error_indicator:%d\n", pkg.Transport_error_indicator)) + file.WriteString(fmt.Sprintf("Payload_unit_start_indicator:%d\n", pkg.Payload_unit_start_indicator)) + file.WriteString(fmt.Sprintf("Transport_priority:%d\n", pkg.Transport_priority)) + file.WriteString(fmt.Sprintf("PID:%d\n", pkg.PID)) + file.WriteString(fmt.Sprintf("Transport_scrambling_control:%d\n", pkg.Transport_scrambling_control)) + file.WriteString(fmt.Sprintf("Adaptation_field_control:%d\n", pkg.Adaptation_field_control)) + file.WriteString(fmt.Sprintf("Continuity_counter:%d\n", pkg.Continuity_counter)) } func (pkg *TSPacket) EncodeHeader(bsw *codec.BitStreamWriter) { - bsw.PutByte(0x47) - bsw.PutUint8(pkg.Transport_error_indicator, 1) - bsw.PutUint8(pkg.Payload_unit_start_indicator, 1) - bsw.PutUint8(pkg.Transport_priority, 1) - bsw.PutUint16(pkg.PID, 13) - bsw.PutUint8(pkg.Transport_scrambling_control, 2) - bsw.PutUint8(pkg.Adaptation_field_control, 2) - bsw.PutUint8(pkg.Continuity_counter, 4) - if pkg.Field != nil && (pkg.Adaptation_field_control&0x02) != 0 { - pkg.Field.Encode(bsw) - } + bsw.PutByte(0x47) + bsw.PutUint8(pkg.Transport_error_indicator, 1) + bsw.PutUint8(pkg.Payload_unit_start_indicator, 1) + bsw.PutUint8(pkg.Transport_priority, 1) + bsw.PutUint16(pkg.PID, 13) + bsw.PutUint8(pkg.Transport_scrambling_control, 2) + bsw.PutUint8(pkg.Adaptation_field_control, 2) + bsw.PutUint8(pkg.Continuity_counter, 4) + if pkg.Field != nil && (pkg.Adaptation_field_control&0x02) != 0 { + pkg.Field.Encode(bsw) + } } func (pkg *TSPacket) DecodeHeader(bs *codec.BitStream) error { - sync_byte := bs.Uint8(8) - if sync_byte != 0x47 { - return errors.New("ts packet must start with 0x47") - } - pkg.Transport_error_indicator = bs.GetBit() - pkg.Payload_unit_start_indicator = bs.GetBit() - pkg.Transport_priority = bs.GetBit() - pkg.PID = bs.Uint16(13) - pkg.Transport_scrambling_control = bs.Uint8(2) - pkg.Adaptation_field_control = bs.Uint8(2) - pkg.Continuity_counter = bs.Uint8(4) - if pkg.Adaptation_field_control == 0x02 || pkg.Adaptation_field_control == 0x03 { - if pkg.Field == nil { - pkg.Field = new(Adaptation_field) - } - err := pkg.Field.Decode(bs) - if err != nil { - return err - } - } - return nil + sync_byte := bs.Uint8(8) + if sync_byte != 0x47 { + return errors.New("ts packet must start with 0x47") + } + pkg.Transport_error_indicator = bs.GetBit() + pkg.Payload_unit_start_indicator = bs.GetBit() + pkg.Transport_priority = bs.GetBit() + pkg.PID = bs.Uint16(13) + pkg.Transport_scrambling_control = bs.Uint8(2) + pkg.Adaptation_field_control = bs.Uint8(2) + pkg.Continuity_counter = bs.Uint8(4) + if pkg.Adaptation_field_control == 0x02 || pkg.Adaptation_field_control == 0x03 { + if pkg.Field == nil { + pkg.Field = new(Adaptation_field) + } + err := pkg.Field.Decode(bs) + if err != nil { + return err + } + } + return nil } // @@ -189,414 +189,414 @@ func (pkg *TSPacket) DecodeHeader(bs *codec.BitStream) error { // } type Adaptation_field struct { - SingleStuffingByte bool // The value 0 is for inserting a single stuffing byte in a Transport Stream packet - Adaptation_field_length uint8 //8 uimsbf - Discontinuity_indicator uint8 //1 bslbf - Random_access_indicator uint8 //1 bslbf - Elementary_stream_priority_indicator uint8 //1 bslbf - PCR_flag uint8 //1 bslbf - OPCR_flag uint8 //1 bslbf - Splicing_point_flag uint8 //1 bslbf - Transport_private_data_flag uint8 //1 bslbf - Adaptation_field_extension_flag uint8 //1 bslbf - Program_clock_reference_base uint64 //33 uimsbf - Program_clock_reference_extension uint16 //9 uimsbf - Original_program_clock_reference_base uint64 //33 uimsbf - Original_program_clock_reference_extension uint16 //9 uimsbf - Splice_countdown uint8 //8 uimsbf - Transport_private_data_length uint8 //8 uimsbf - Adaptation_field_extension_length uint8 //8 uimsbf - Ltw_flag uint8 //1 bslbf - Piecewise_rate_flag uint8 //1 bslbf - Seamless_splice_flag uint8 //1 bslbf - Ltw_valid_flag uint8 //1 bslbf - Ltw_offset uint16 //15 uimsbf - Piecewise_rate uint32 //22 uimsbf - Splice_type uint8 //4 uimsbf - DTS_next_AU uint64 - Stuffing_byte uint8 + SingleStuffingByte bool // The value 0 is for inserting a single stuffing byte in a Transport Stream packet + Adaptation_field_length uint8 //8 uimsbf + Discontinuity_indicator uint8 //1 bslbf + Random_access_indicator uint8 //1 bslbf + Elementary_stream_priority_indicator uint8 //1 bslbf + PCR_flag uint8 //1 bslbf + OPCR_flag uint8 //1 bslbf + Splicing_point_flag uint8 //1 bslbf + Transport_private_data_flag uint8 //1 bslbf + Adaptation_field_extension_flag uint8 //1 bslbf + Program_clock_reference_base uint64 //33 uimsbf + Program_clock_reference_extension uint16 //9 uimsbf + Original_program_clock_reference_base uint64 //33 uimsbf + Original_program_clock_reference_extension uint16 //9 uimsbf + Splice_countdown uint8 //8 uimsbf + Transport_private_data_length uint8 //8 uimsbf + Adaptation_field_extension_length uint8 //8 uimsbf + Ltw_flag uint8 //1 bslbf + Piecewise_rate_flag uint8 //1 bslbf + Seamless_splice_flag uint8 //1 bslbf + Ltw_valid_flag uint8 //1 bslbf + Ltw_offset uint16 //15 uimsbf + Piecewise_rate uint32 //22 uimsbf + Splice_type uint8 //4 uimsbf + DTS_next_AU uint64 + Stuffing_byte uint8 } func (adaptation *Adaptation_field) PrettyPrint(file *os.File) { - file.WriteString(fmt.Sprintf("Adaptation_field_length:%d\n", adaptation.Adaptation_field_length)) - file.WriteString(fmt.Sprintf("Discontinuity_indicator:%d\n", adaptation.Discontinuity_indicator)) - file.WriteString(fmt.Sprintf("Random_access_indicator:%d\n", adaptation.Random_access_indicator)) - file.WriteString(fmt.Sprintf("Elementary_stream_priority_indicator:%d\n", adaptation.Elementary_stream_priority_indicator)) - file.WriteString(fmt.Sprintf("PCR_flag:%d\n", adaptation.PCR_flag)) - file.WriteString(fmt.Sprintf("OPCR_flag:%d\n", adaptation.OPCR_flag)) - file.WriteString(fmt.Sprintf("Splicing_point_flag:%d\n", adaptation.Splicing_point_flag)) - file.WriteString(fmt.Sprintf("Transport_private_data_flag:%d\n", adaptation.Transport_private_data_flag)) - file.WriteString(fmt.Sprintf("Adaptation_field_extension_flag:%d\n", adaptation.Adaptation_field_extension_flag)) - if adaptation.PCR_flag == 1 { - file.WriteString(fmt.Sprintf("Program_clock_reference_base:%d\n", adaptation.Program_clock_reference_base)) - file.WriteString(fmt.Sprintf("Program_clock_reference_extension:%d\n", adaptation.Program_clock_reference_extension)) - } - if adaptation.OPCR_flag == 1 { - file.WriteString(fmt.Sprintf("Original_program_clock_reference_base:%d\n", adaptation.Original_program_clock_reference_base)) - file.WriteString(fmt.Sprintf("Original_program_clock_reference_extension:%d\n", adaptation.Original_program_clock_reference_extension)) - } - if adaptation.Splicing_point_flag == 1 { - file.WriteString(fmt.Sprintf("Splice_countdown:%d\n", adaptation.Splice_countdown)) - } - if adaptation.Transport_private_data_flag == 1 { - file.WriteString(fmt.Sprintf("Transport_private_data_length:%d\n", adaptation.Transport_private_data_length)) - } - if adaptation.Adaptation_field_extension_flag == 1 { - file.WriteString(fmt.Sprintf("Adaptation_field_extension_length:%d\n", adaptation.Adaptation_field_extension_length)) - file.WriteString(fmt.Sprintf("Ltw_flag:%d\n", adaptation.Ltw_flag)) - file.WriteString(fmt.Sprintf("Piecewise_rate_flag:%d\n", adaptation.Piecewise_rate_flag)) - file.WriteString(fmt.Sprintf("Seamless_splice_flag:%d\n", adaptation.Seamless_splice_flag)) - if adaptation.Ltw_flag == 1 { - file.WriteString(fmt.Sprintf("Ltw_valid_flag:%d\n", adaptation.Ltw_valid_flag)) - file.WriteString(fmt.Sprintf("Ltw_offset:%d\n", adaptation.Ltw_offset)) - } - if adaptation.Piecewise_rate_flag == 1 { - file.WriteString(fmt.Sprintf("Piecewise_rate:%d\n", adaptation.Piecewise_rate)) - } - if adaptation.Seamless_splice_flag == 1 { - file.WriteString(fmt.Sprintf("Splice_type:%d\n", adaptation.Splice_type)) - file.WriteString(fmt.Sprintf("DTS_next_AU:%d\n", adaptation.DTS_next_AU)) - } - } + file.WriteString(fmt.Sprintf("Adaptation_field_length:%d\n", adaptation.Adaptation_field_length)) + file.WriteString(fmt.Sprintf("Discontinuity_indicator:%d\n", adaptation.Discontinuity_indicator)) + file.WriteString(fmt.Sprintf("Random_access_indicator:%d\n", adaptation.Random_access_indicator)) + file.WriteString(fmt.Sprintf("Elementary_stream_priority_indicator:%d\n", adaptation.Elementary_stream_priority_indicator)) + file.WriteString(fmt.Sprintf("PCR_flag:%d\n", adaptation.PCR_flag)) + file.WriteString(fmt.Sprintf("OPCR_flag:%d\n", adaptation.OPCR_flag)) + file.WriteString(fmt.Sprintf("Splicing_point_flag:%d\n", adaptation.Splicing_point_flag)) + file.WriteString(fmt.Sprintf("Transport_private_data_flag:%d\n", adaptation.Transport_private_data_flag)) + file.WriteString(fmt.Sprintf("Adaptation_field_extension_flag:%d\n", adaptation.Adaptation_field_extension_flag)) + if adaptation.PCR_flag == 1 { + file.WriteString(fmt.Sprintf("Program_clock_reference_base:%d\n", adaptation.Program_clock_reference_base)) + file.WriteString(fmt.Sprintf("Program_clock_reference_extension:%d\n", adaptation.Program_clock_reference_extension)) + } + if adaptation.OPCR_flag == 1 { + file.WriteString(fmt.Sprintf("Original_program_clock_reference_base:%d\n", adaptation.Original_program_clock_reference_base)) + file.WriteString(fmt.Sprintf("Original_program_clock_reference_extension:%d\n", adaptation.Original_program_clock_reference_extension)) + } + if adaptation.Splicing_point_flag == 1 { + file.WriteString(fmt.Sprintf("Splice_countdown:%d\n", adaptation.Splice_countdown)) + } + if adaptation.Transport_private_data_flag == 1 { + file.WriteString(fmt.Sprintf("Transport_private_data_length:%d\n", adaptation.Transport_private_data_length)) + } + if adaptation.Adaptation_field_extension_flag == 1 { + file.WriteString(fmt.Sprintf("Adaptation_field_extension_length:%d\n", adaptation.Adaptation_field_extension_length)) + file.WriteString(fmt.Sprintf("Ltw_flag:%d\n", adaptation.Ltw_flag)) + file.WriteString(fmt.Sprintf("Piecewise_rate_flag:%d\n", adaptation.Piecewise_rate_flag)) + file.WriteString(fmt.Sprintf("Seamless_splice_flag:%d\n", adaptation.Seamless_splice_flag)) + if adaptation.Ltw_flag == 1 { + file.WriteString(fmt.Sprintf("Ltw_valid_flag:%d\n", adaptation.Ltw_valid_flag)) + file.WriteString(fmt.Sprintf("Ltw_offset:%d\n", adaptation.Ltw_offset)) + } + if adaptation.Piecewise_rate_flag == 1 { + file.WriteString(fmt.Sprintf("Piecewise_rate:%d\n", adaptation.Piecewise_rate)) + } + if adaptation.Seamless_splice_flag == 1 { + file.WriteString(fmt.Sprintf("Splice_type:%d\n", adaptation.Splice_type)) + file.WriteString(fmt.Sprintf("DTS_next_AU:%d\n", adaptation.DTS_next_AU)) + } + } } func (adaptation *Adaptation_field) Encode(bsw *codec.BitStreamWriter) { - loc := bsw.ByteOffset() - bsw.PutUint8(adaptation.Adaptation_field_length, 8) - if adaptation.SingleStuffingByte { - return - } - bsw.Markdot() - bsw.PutUint8(adaptation.Discontinuity_indicator, 1) - bsw.PutUint8(adaptation.Random_access_indicator, 1) - bsw.PutUint8(adaptation.Elementary_stream_priority_indicator, 1) - bsw.PutUint8(adaptation.PCR_flag, 1) - bsw.PutUint8(adaptation.OPCR_flag, 1) - bsw.PutUint8(adaptation.Splicing_point_flag, 1) - bsw.PutUint8(0 /*adaptation.Transport_private_data_flag*/, 1) - bsw.PutUint8(0 /*adaptation.Adaptation_field_extension_flag*/, 1) - if adaptation.PCR_flag == 1 { - bsw.PutUint64(adaptation.Program_clock_reference_base, 33) - bsw.PutUint8(0, 6) - bsw.PutUint16(adaptation.Program_clock_reference_extension, 9) - } - if adaptation.OPCR_flag == 1 { - bsw.PutUint64(adaptation.Original_program_clock_reference_base, 33) - bsw.PutUint8(0, 6) - bsw.PutUint16(adaptation.Original_program_clock_reference_extension, 9) - } - if adaptation.Splicing_point_flag == 1 { - bsw.PutUint8(adaptation.Splice_countdown, 8) - } - //TODO - // if adaptation.Transport_private_data_flag == 0 { - // } - // if adaptation.Adaptation_field_extension_flag == 0 { - // } - adaptation.Adaptation_field_length = uint8(bsw.DistanceFromMarkDot() / 8) - bsw.PutRepetValue(0xff, int(adaptation.Stuffing_byte)) - adaptation.Adaptation_field_length += adaptation.Stuffing_byte - bsw.SetByte(adaptation.Adaptation_field_length, loc) + loc := bsw.ByteOffset() + bsw.PutUint8(adaptation.Adaptation_field_length, 8) + if adaptation.SingleStuffingByte { + return + } + bsw.Markdot() + bsw.PutUint8(adaptation.Discontinuity_indicator, 1) + bsw.PutUint8(adaptation.Random_access_indicator, 1) + bsw.PutUint8(adaptation.Elementary_stream_priority_indicator, 1) + bsw.PutUint8(adaptation.PCR_flag, 1) + bsw.PutUint8(adaptation.OPCR_flag, 1) + bsw.PutUint8(adaptation.Splicing_point_flag, 1) + bsw.PutUint8(0 /*adaptation.Transport_private_data_flag*/, 1) + bsw.PutUint8(0 /*adaptation.Adaptation_field_extension_flag*/, 1) + if adaptation.PCR_flag == 1 { + bsw.PutUint64(adaptation.Program_clock_reference_base, 33) + bsw.PutUint8(0, 6) + bsw.PutUint16(adaptation.Program_clock_reference_extension, 9) + } + if adaptation.OPCR_flag == 1 { + bsw.PutUint64(adaptation.Original_program_clock_reference_base, 33) + bsw.PutUint8(0, 6) + bsw.PutUint16(adaptation.Original_program_clock_reference_extension, 9) + } + if adaptation.Splicing_point_flag == 1 { + bsw.PutUint8(adaptation.Splice_countdown, 8) + } + //TODO + // if adaptation.Transport_private_data_flag == 0 { + // } + // if adaptation.Adaptation_field_extension_flag == 0 { + // } + adaptation.Adaptation_field_length = uint8(bsw.DistanceFromMarkDot() / 8) + bsw.PutRepetValue(0xff, int(adaptation.Stuffing_byte)) + adaptation.Adaptation_field_length += adaptation.Stuffing_byte + bsw.SetByte(adaptation.Adaptation_field_length, loc) } func (adaptation *Adaptation_field) Decode(bs *codec.BitStream) error { - if bs.RemainBytes() < 1 { - return errors.New("len of data < 1 byte") - } - adaptation.Adaptation_field_length = bs.Uint8(8) - startoffset := bs.ByteOffset() - //fmt.Printf("Adaptation_field_length=%d\n", adaptation.Adaptation_field_length) - if bs.RemainBytes() < int(adaptation.Adaptation_field_length) { - return errors.New("len of data < Adaptation_field_length") - } - if adaptation.Adaptation_field_length == 0 { - return nil - } - adaptation.Discontinuity_indicator = bs.GetBit() - adaptation.Random_access_indicator = bs.GetBit() - adaptation.Elementary_stream_priority_indicator = bs.GetBit() - adaptation.PCR_flag = bs.GetBit() - adaptation.OPCR_flag = bs.GetBit() - adaptation.Splicing_point_flag = bs.GetBit() - adaptation.Transport_private_data_flag = bs.GetBit() - adaptation.Adaptation_field_extension_flag = bs.GetBit() - if adaptation.PCR_flag == 1 { - adaptation.Program_clock_reference_base = bs.GetBits(33) - bs.SkipBits(6) - adaptation.Program_clock_reference_extension = uint16(bs.GetBits(9)) - } - if adaptation.OPCR_flag == 1 { - adaptation.Original_program_clock_reference_base = bs.GetBits(33) - bs.SkipBits(6) - adaptation.Original_program_clock_reference_extension = uint16(bs.GetBits(9)) - } - if adaptation.Splicing_point_flag == 1 { - adaptation.Splice_countdown = bs.Uint8(8) - } - if adaptation.Transport_private_data_flag == 1 { - adaptation.Transport_private_data_length = bs.Uint8(8) - bs.SkipBits(8 * int(adaptation.Transport_private_data_length)) - } - if adaptation.Adaptation_field_extension_flag == 1 { - adaptation.Adaptation_field_extension_length = bs.Uint8(8) - bs.Markdot() - adaptation.Ltw_flag = bs.GetBit() - adaptation.Piecewise_rate_flag = bs.GetBit() - adaptation.Seamless_splice_flag = bs.GetBit() - bs.SkipBits(5) - if adaptation.Ltw_flag == 1 { - adaptation.Ltw_valid_flag = bs.GetBit() - adaptation.Ltw_offset = uint16(bs.GetBits(15)) - } - if adaptation.Piecewise_rate_flag == 1 { - bs.SkipBits(2) - adaptation.Piecewise_rate = uint32(bs.GetBits(22)) - } - if adaptation.Seamless_splice_flag == 1 { - adaptation.Splice_type = uint8(bs.GetBits(4)) - adaptation.DTS_next_AU = bs.GetBits(3) - bs.SkipBits(1) - adaptation.DTS_next_AU = adaptation.DTS_next_AU<<15 | bs.GetBits(15) - bs.SkipBits(1) - adaptation.DTS_next_AU = adaptation.DTS_next_AU<<15 | bs.GetBits(15) - bs.SkipBits(1) - } - bitscount := bs.DistanceFromMarkDot() - if bitscount%8 > 0 { - panic("maybe parser ts file failed") - } - bs.SkipBits(int(adaptation.Adaptation_field_extension_length*8 - uint8(bitscount))) - } - endoffset := bs.ByteOffset() - bs.SkipBits((int(adaptation.Adaptation_field_length) - (endoffset - startoffset)) * 8) - return nil + if bs.RemainBytes() < 1 { + return errors.New("len of data < 1 byte") + } + adaptation.Adaptation_field_length = bs.Uint8(8) + startoffset := bs.ByteOffset() + //fmt.Printf("Adaptation_field_length=%d\n", adaptation.Adaptation_field_length) + if bs.RemainBytes() < int(adaptation.Adaptation_field_length) { + return errors.New("len of data < Adaptation_field_length") + } + if adaptation.Adaptation_field_length == 0 { + return nil + } + adaptation.Discontinuity_indicator = bs.GetBit() + adaptation.Random_access_indicator = bs.GetBit() + adaptation.Elementary_stream_priority_indicator = bs.GetBit() + adaptation.PCR_flag = bs.GetBit() + adaptation.OPCR_flag = bs.GetBit() + adaptation.Splicing_point_flag = bs.GetBit() + adaptation.Transport_private_data_flag = bs.GetBit() + adaptation.Adaptation_field_extension_flag = bs.GetBit() + if adaptation.PCR_flag == 1 { + adaptation.Program_clock_reference_base = bs.GetBits(33) + bs.SkipBits(6) + adaptation.Program_clock_reference_extension = uint16(bs.GetBits(9)) + } + if adaptation.OPCR_flag == 1 { + adaptation.Original_program_clock_reference_base = bs.GetBits(33) + bs.SkipBits(6) + adaptation.Original_program_clock_reference_extension = uint16(bs.GetBits(9)) + } + if adaptation.Splicing_point_flag == 1 { + adaptation.Splice_countdown = bs.Uint8(8) + } + if adaptation.Transport_private_data_flag == 1 { + adaptation.Transport_private_data_length = bs.Uint8(8) + bs.SkipBits(8 * int(adaptation.Transport_private_data_length)) + } + if adaptation.Adaptation_field_extension_flag == 1 { + adaptation.Adaptation_field_extension_length = bs.Uint8(8) + bs.Markdot() + adaptation.Ltw_flag = bs.GetBit() + adaptation.Piecewise_rate_flag = bs.GetBit() + adaptation.Seamless_splice_flag = bs.GetBit() + bs.SkipBits(5) + if adaptation.Ltw_flag == 1 { + adaptation.Ltw_valid_flag = bs.GetBit() + adaptation.Ltw_offset = uint16(bs.GetBits(15)) + } + if adaptation.Piecewise_rate_flag == 1 { + bs.SkipBits(2) + adaptation.Piecewise_rate = uint32(bs.GetBits(22)) + } + if adaptation.Seamless_splice_flag == 1 { + adaptation.Splice_type = uint8(bs.GetBits(4)) + adaptation.DTS_next_AU = bs.GetBits(3) + bs.SkipBits(1) + adaptation.DTS_next_AU = adaptation.DTS_next_AU<<15 | bs.GetBits(15) + bs.SkipBits(1) + adaptation.DTS_next_AU = adaptation.DTS_next_AU<<15 | bs.GetBits(15) + bs.SkipBits(1) + } + bitscount := bs.DistanceFromMarkDot() + if bitscount%8 > 0 { + panic("maybe parser ts file failed") + } + bs.SkipBits(int(adaptation.Adaptation_field_extension_length*8 - uint8(bitscount))) + } + endoffset := bs.ByteOffset() + bs.SkipBits((int(adaptation.Adaptation_field_length) - (endoffset - startoffset)) * 8) + return nil } type PmtPair struct { - Program_number uint16 - PID uint16 + Program_number uint16 + PID uint16 } type Pat struct { - Table_id uint8 //8 uimsbf - Section_syntax_indicator uint8 //1 bslbf - Section_length uint16 //12 uimsbf - Transport_stream_id uint16 //16 uimsbf - Version_number uint8 //5 uimsbf - Current_next_indicator uint8 //1 bslbf - Section_number uint8 //8 uimsbf - Last_section_number uint8 //8 uimsbf - Pmts []PmtPair + Table_id uint8 //8 uimsbf + Section_syntax_indicator uint8 //1 bslbf + Section_length uint16 //12 uimsbf + Transport_stream_id uint16 //16 uimsbf + Version_number uint8 //5 uimsbf + Current_next_indicator uint8 //1 bslbf + Section_number uint8 //8 uimsbf + Last_section_number uint8 //8 uimsbf + Pmts []PmtPair } func NewPat() *Pat { - return &Pat{ - Table_id: uint8(TS_TID_PAS), - Pmts: make([]PmtPair, 0, 8), - } + return &Pat{ + Table_id: uint8(TS_TID_PAS), + Pmts: make([]PmtPair, 0, 8), + } } func (pat *Pat) PrettyPrint(file *os.File) { - file.WriteString(fmt.Sprintf("Table id:%d\n", pat.Table_id)) - file.WriteString(fmt.Sprintf("Section_syntax_indicator:%d\n", pat.Section_syntax_indicator)) - file.WriteString(fmt.Sprintf("Section_length:%d\n", pat.Section_length)) - file.WriteString(fmt.Sprintf("Transport_stream_id:%d\n", pat.Transport_stream_id)) - file.WriteString(fmt.Sprintf("Version_number:%d\n", pat.Version_number)) - file.WriteString(fmt.Sprintf("Current_next_indicator:%d\n", pat.Current_next_indicator)) - file.WriteString(fmt.Sprintf("Section_number:%d\n", pat.Section_number)) - file.WriteString(fmt.Sprintf("Last_section_number:%d\n", pat.Last_section_number)) - for i, pmt := range pat.Pmts { - file.WriteString(fmt.Sprintf("----pmt %d\n", i)) - file.WriteString(fmt.Sprintf(" program_number:%d\n", pmt.Program_number)) - if pmt.Program_number == 0x0000 { - file.WriteString(fmt.Sprintf(" network_PID:%d\n", pmt.PID)) - } else { - file.WriteString(fmt.Sprintf(" program_map_PID:%d\n", pmt.PID)) - } - } + file.WriteString(fmt.Sprintf("Table id:%d\n", pat.Table_id)) + file.WriteString(fmt.Sprintf("Section_syntax_indicator:%d\n", pat.Section_syntax_indicator)) + file.WriteString(fmt.Sprintf("Section_length:%d\n", pat.Section_length)) + file.WriteString(fmt.Sprintf("Transport_stream_id:%d\n", pat.Transport_stream_id)) + file.WriteString(fmt.Sprintf("Version_number:%d\n", pat.Version_number)) + file.WriteString(fmt.Sprintf("Current_next_indicator:%d\n", pat.Current_next_indicator)) + file.WriteString(fmt.Sprintf("Section_number:%d\n", pat.Section_number)) + file.WriteString(fmt.Sprintf("Last_section_number:%d\n", pat.Last_section_number)) + for i, pmt := range pat.Pmts { + file.WriteString(fmt.Sprintf("----pmt %d\n", i)) + file.WriteString(fmt.Sprintf(" program_number:%d\n", pmt.Program_number)) + if pmt.Program_number == 0x0000 { + file.WriteString(fmt.Sprintf(" network_PID:%d\n", pmt.PID)) + } else { + file.WriteString(fmt.Sprintf(" program_map_PID:%d\n", pmt.PID)) + } + } } func (pat *Pat) Encode(bsw *codec.BitStreamWriter) { - bsw.PutUint8(0x00, 8) - loc := bsw.ByteOffset() - bsw.PutUint8(pat.Section_syntax_indicator, 1) - bsw.PutUint8(0x00, 1) - bsw.PutUint8(0x03, 2) - bsw.PutUint16(0, 12) - bsw.Markdot() - bsw.PutUint16(pat.Transport_stream_id, 16) - bsw.PutUint8(0x03, 2) - bsw.PutUint8(pat.Version_number, 5) - bsw.PutUint8(pat.Current_next_indicator, 1) - bsw.PutUint8(pat.Section_number, 8) - bsw.PutUint8(pat.Last_section_number, 8) - for _, pms := range pat.Pmts { - bsw.PutUint16(pms.Program_number, 16) - bsw.PutUint8(0x07, 3) - bsw.PutUint16(pms.PID, 13) - } - length := bsw.DistanceFromMarkDot() - //|Section_syntax_indicator|'0'|reserved|Section_length| - pat.Section_length = uint16(length)/8 + 4 - bsw.SetUint16(pat.Section_length&0x0FFF|(uint16(pat.Section_syntax_indicator)<<15)|0x3000, loc) - crc := codec.CalcCrc32(0xffffffff, bsw.Bits()[bsw.ByteOffset()-int(pat.Section_length-4)-3:bsw.ByteOffset()]) - tmpcrc := make([]byte, 4) - binary.LittleEndian.PutUint32(tmpcrc, crc) - bsw.PutBytes(tmpcrc) + bsw.PutUint8(0x00, 8) + loc := bsw.ByteOffset() + bsw.PutUint8(pat.Section_syntax_indicator, 1) + bsw.PutUint8(0x00, 1) + bsw.PutUint8(0x03, 2) + bsw.PutUint16(0, 12) + bsw.Markdot() + bsw.PutUint16(pat.Transport_stream_id, 16) + bsw.PutUint8(0x03, 2) + bsw.PutUint8(pat.Version_number, 5) + bsw.PutUint8(pat.Current_next_indicator, 1) + bsw.PutUint8(pat.Section_number, 8) + bsw.PutUint8(pat.Last_section_number, 8) + for _, pms := range pat.Pmts { + bsw.PutUint16(pms.Program_number, 16) + bsw.PutUint8(0x07, 3) + bsw.PutUint16(pms.PID, 13) + } + length := bsw.DistanceFromMarkDot() + //|Section_syntax_indicator|'0'|reserved|Section_length| + pat.Section_length = uint16(length)/8 + 4 + bsw.SetUint16(pat.Section_length&0x0FFF|(uint16(pat.Section_syntax_indicator)<<15)|0x3000, loc) + crc := codec.CalcCrc32(0xffffffff, bsw.Bits()[bsw.ByteOffset()-int(pat.Section_length-4)-3:bsw.ByteOffset()]) + tmpcrc := make([]byte, 4) + binary.LittleEndian.PutUint32(tmpcrc, crc) + bsw.PutBytes(tmpcrc) } func (pat *Pat) Decode(bs *codec.BitStream) error { - pat.Table_id = bs.Uint8(8) + pat.Table_id = bs.Uint8(8) - if pat.Table_id != uint8(TS_TID_PAS) { - return errors.New("table id is Not TS_TID_PAS") - } - pat.Section_syntax_indicator = bs.Uint8(1) - bs.SkipBits(3) - pat.Section_length = bs.Uint16(12) - pat.Transport_stream_id = bs.Uint16(16) - bs.SkipBits(2) - pat.Version_number = bs.Uint8(5) - pat.Current_next_indicator = bs.Uint8(1) - pat.Section_number = bs.Uint8(8) - pat.Last_section_number = bs.Uint8(8) - for i := 0; i+4 <= int(pat.Section_length)-5-4; i = i + 4 { - tmp := PmtPair{ - Program_number: 0, - PID: 0, - } - tmp.Program_number = bs.Uint16(16) - bs.SkipBits(3) - tmp.PID = bs.Uint16(13) - pat.Pmts = append(pat.Pmts, tmp) - } - return nil + if pat.Table_id != uint8(TS_TID_PAS) { + return errors.New("table id is Not TS_TID_PAS") + } + pat.Section_syntax_indicator = bs.Uint8(1) + bs.SkipBits(3) + pat.Section_length = bs.Uint16(12) + pat.Transport_stream_id = bs.Uint16(16) + bs.SkipBits(2) + pat.Version_number = bs.Uint8(5) + pat.Current_next_indicator = bs.Uint8(1) + pat.Section_number = bs.Uint8(8) + pat.Last_section_number = bs.Uint8(8) + for i := 0; i+4 <= int(pat.Section_length)-5-4; i = i + 4 { + tmp := PmtPair{ + Program_number: 0, + PID: 0, + } + tmp.Program_number = bs.Uint16(16) + bs.SkipBits(3) + tmp.PID = bs.Uint16(13) + pat.Pmts = append(pat.Pmts, tmp) + } + return nil } type StreamPair struct { - StreamType uint8 //8 uimsbf - Elementary_PID uint16 //13 uimsbf - ES_Info_Length uint16 //12 uimsbf + StreamType uint8 //8 uimsbf + Elementary_PID uint16 //13 uimsbf + ES_Info_Length uint16 //12 uimsbf } type Pmt struct { - Table_id uint8 //8 uimsbf - Section_syntax_indicator uint8 //1 bslbf - Section_length uint16 //12 uimsbf - Program_number uint16 //16 uimsbf - Version_number uint8 //5 uimsbf - Current_next_indicator uint8 //1 bslbf - Section_number uint8 //8 uimsbf - Last_section_number uint8 //8 uimsbf - PCR_PID uint16 //13 uimsbf - Program_info_length uint16 //12 uimsbf - Streams []StreamPair + Table_id uint8 //8 uimsbf + Section_syntax_indicator uint8 //1 bslbf + Section_length uint16 //12 uimsbf + Program_number uint16 //16 uimsbf + Version_number uint8 //5 uimsbf + Current_next_indicator uint8 //1 bslbf + Section_number uint8 //8 uimsbf + Last_section_number uint8 //8 uimsbf + PCR_PID uint16 //13 uimsbf + Program_info_length uint16 //12 uimsbf + Streams []StreamPair } func NewPmt() *Pmt { - return &Pmt{ - Table_id: uint8(TS_TID_PMS), - Streams: make([]StreamPair, 0, 8), - } + return &Pmt{ + Table_id: uint8(TS_TID_PMS), + Streams: make([]StreamPair, 0, 8), + } } func (pmt *Pmt) PrettyPrint(file *os.File) { - file.WriteString(fmt.Sprintf("Table id:%d\n", pmt.Table_id)) - file.WriteString(fmt.Sprintf("Section_syntax_indicator:%d\n", pmt.Section_syntax_indicator)) - file.WriteString(fmt.Sprintf("Section_length:%d\n", pmt.Section_length)) - file.WriteString(fmt.Sprintf("Program_number:%d\n", pmt.Program_number)) - file.WriteString(fmt.Sprintf("Version_number:%d\n", pmt.Version_number)) - file.WriteString(fmt.Sprintf("Current_next_indicator:%d\n", pmt.Current_next_indicator)) - file.WriteString(fmt.Sprintf("Section_number:%d\n", pmt.Section_number)) - file.WriteString(fmt.Sprintf("Last_section_number:%d\n", pmt.Last_section_number)) - file.WriteString(fmt.Sprintf("PCR_PID:%d\n", pmt.PCR_PID)) - file.WriteString(fmt.Sprintf("program_info_length:%d\n", pmt.Program_info_length)) - for i, stream := range pmt.Streams { - file.WriteString(fmt.Sprintf("----stream %d\n", i)) - if stream.StreamType == uint8(TS_STREAM_AAC) { - file.WriteString(" stream_type:AAC\n") - } else if stream.StreamType == uint8(TS_STREAM_H264) { - file.WriteString(" stream_type:H264\n") - } else if stream.StreamType == uint8(TS_STREAM_H265) { - file.WriteString(" stream_type:H265\n") - } - file.WriteString(fmt.Sprintf(" elementary_PID:%d\n", stream.Elementary_PID)) - file.WriteString(fmt.Sprintf(" ES_info_length:%d\n", stream.ES_Info_Length)) - } + file.WriteString(fmt.Sprintf("Table id:%d\n", pmt.Table_id)) + file.WriteString(fmt.Sprintf("Section_syntax_indicator:%d\n", pmt.Section_syntax_indicator)) + file.WriteString(fmt.Sprintf("Section_length:%d\n", pmt.Section_length)) + file.WriteString(fmt.Sprintf("Program_number:%d\n", pmt.Program_number)) + file.WriteString(fmt.Sprintf("Version_number:%d\n", pmt.Version_number)) + file.WriteString(fmt.Sprintf("Current_next_indicator:%d\n", pmt.Current_next_indicator)) + file.WriteString(fmt.Sprintf("Section_number:%d\n", pmt.Section_number)) + file.WriteString(fmt.Sprintf("Last_section_number:%d\n", pmt.Last_section_number)) + file.WriteString(fmt.Sprintf("PCR_PID:%d\n", pmt.PCR_PID)) + file.WriteString(fmt.Sprintf("program_info_length:%d\n", pmt.Program_info_length)) + for i, stream := range pmt.Streams { + file.WriteString(fmt.Sprintf("----stream %d\n", i)) + if stream.StreamType == uint8(TS_STREAM_AAC) { + file.WriteString(" stream_type:AAC\n") + } else if stream.StreamType == uint8(TS_STREAM_H264) { + file.WriteString(" stream_type:H264\n") + } else if stream.StreamType == uint8(TS_STREAM_H265) { + file.WriteString(" stream_type:H265\n") + } + file.WriteString(fmt.Sprintf(" elementary_PID:%d\n", stream.Elementary_PID)) + file.WriteString(fmt.Sprintf(" ES_info_length:%d\n", stream.ES_Info_Length)) + } } func (pmt *Pmt) Encode(bsw *codec.BitStreamWriter) { - bsw.PutUint8(pmt.Table_id, 8) - loc := bsw.ByteOffset() - bsw.PutUint8(pmt.Section_syntax_indicator, 1) - bsw.PutUint8(0x00, 1) - bsw.PutUint8(0x03, 2) - bsw.PutUint16(pmt.Section_length, 12) - bsw.Markdot() - bsw.PutUint16(pmt.Program_number, 16) - bsw.PutUint8(0x03, 2) - bsw.PutUint8(pmt.Version_number, 5) - bsw.PutUint8(pmt.Current_next_indicator, 1) - bsw.PutUint8(pmt.Section_number, 8) - bsw.PutUint8(pmt.Last_section_number, 8) - bsw.PutUint8(0x07, 3) - bsw.PutUint16(pmt.PCR_PID, 13) - bsw.PutUint8(0x0f, 4) - //TODO Program info length - bsw.PutUint16(0x0000 /*pmt.Program_info_length*/, 12) - for _, stream := range pmt.Streams { - bsw.PutUint8(stream.StreamType, 8) - bsw.PutUint8(0x00, 3) - bsw.PutUint16(stream.Elementary_PID, 13) - bsw.PutUint8(0x00, 4) - //TODO ES_info - bsw.PutUint8(0 /*ES_info_length*/, 12) - } - length := bsw.DistanceFromMarkDot() - pmt.Section_length = uint16(length)/8 + 4 - bsw.SetUint16(pmt.Section_length&0x0FFF|(uint16(pmt.Section_syntax_indicator)<<15)|0x3000, loc) - crc := codec.CalcCrc32(0xffffffff, bsw.Bits()[bsw.ByteOffset()-int(pmt.Section_length-4)-3:bsw.ByteOffset()]) - tmpcrc := make([]byte, 4) - binary.LittleEndian.PutUint32(tmpcrc, crc) - bsw.PutBytes(tmpcrc) + bsw.PutUint8(pmt.Table_id, 8) + loc := bsw.ByteOffset() + bsw.PutUint8(pmt.Section_syntax_indicator, 1) + bsw.PutUint8(0x00, 1) + bsw.PutUint8(0x03, 2) + bsw.PutUint16(pmt.Section_length, 12) + bsw.Markdot() + bsw.PutUint16(pmt.Program_number, 16) + bsw.PutUint8(0x03, 2) + bsw.PutUint8(pmt.Version_number, 5) + bsw.PutUint8(pmt.Current_next_indicator, 1) + bsw.PutUint8(pmt.Section_number, 8) + bsw.PutUint8(pmt.Last_section_number, 8) + bsw.PutUint8(0x07, 3) + bsw.PutUint16(pmt.PCR_PID, 13) + bsw.PutUint8(0x0f, 4) + //TODO Program info length + bsw.PutUint16(0x0000 /*pmt.Program_info_length*/, 12) + for _, stream := range pmt.Streams { + bsw.PutUint8(stream.StreamType, 8) + bsw.PutUint8(0x00, 3) + bsw.PutUint16(stream.Elementary_PID, 13) + bsw.PutUint8(0x00, 4) + //TODO ES_info + bsw.PutUint8(0 /*ES_info_length*/, 12) + } + length := bsw.DistanceFromMarkDot() + pmt.Section_length = uint16(length)/8 + 4 + bsw.SetUint16(pmt.Section_length&0x0FFF|(uint16(pmt.Section_syntax_indicator)<<15)|0x3000, loc) + crc := codec.CalcCrc32(0xffffffff, bsw.Bits()[bsw.ByteOffset()-int(pmt.Section_length-4)-3:bsw.ByteOffset()]) + tmpcrc := make([]byte, 4) + binary.LittleEndian.PutUint32(tmpcrc, crc) + bsw.PutBytes(tmpcrc) } func (pmt *Pmt) Decode(bs *codec.BitStream) error { - pmt.Table_id = bs.Uint8(8) - if pmt.Table_id != uint8(TS_TID_PMS) { - return errors.New("table id is Not TS_TID_PAS") - } - pmt.Section_syntax_indicator = bs.Uint8(1) - bs.SkipBits(3) - pmt.Section_length = bs.Uint16(12) - pmt.Program_number = bs.Uint16(16) - bs.SkipBits(2) - pmt.Version_number = bs.Uint8(5) - pmt.Current_next_indicator = bs.Uint8(1) - pmt.Section_number = bs.Uint8(8) - pmt.Last_section_number = bs.Uint8(8) - bs.SkipBits(3) - pmt.PCR_PID = bs.Uint16(13) - bs.SkipBits(4) - pmt.Program_info_length = bs.Uint16(12) - //TODO N loop descriptors - bs.SkipBits(int(pmt.Program_info_length) * 8) - //fmt.Printf("section length %d pmt.Pogram_info_length=%d\n", pmt.Section_length, pmt.Pogram_info_length) - for i := 0; i < int(pmt.Section_length)-9-int(pmt.Program_info_length)-4; { - tmp := StreamPair{ - StreamType: 0, - Elementary_PID: 0, - ES_Info_Length: 0, - } - tmp.StreamType = bs.Uint8(8) - bs.SkipBits(3) - tmp.Elementary_PID = bs.Uint16(13) - bs.SkipBits(4) - tmp.ES_Info_Length = bs.Uint16(12) - //TODO N loop descriptors - bs.SkipBits(int(tmp.ES_Info_Length) * 8) - pmt.Streams = append(pmt.Streams, tmp) - i += 5 + int(tmp.ES_Info_Length) - } - return nil + pmt.Table_id = bs.Uint8(8) + if pmt.Table_id != uint8(TS_TID_PMS) { + return errors.New("table id is Not TS_TID_PAS") + } + pmt.Section_syntax_indicator = bs.Uint8(1) + bs.SkipBits(3) + pmt.Section_length = bs.Uint16(12) + pmt.Program_number = bs.Uint16(16) + bs.SkipBits(2) + pmt.Version_number = bs.Uint8(5) + pmt.Current_next_indicator = bs.Uint8(1) + pmt.Section_number = bs.Uint8(8) + pmt.Last_section_number = bs.Uint8(8) + bs.SkipBits(3) + pmt.PCR_PID = bs.Uint16(13) + bs.SkipBits(4) + pmt.Program_info_length = bs.Uint16(12) + //TODO N loop descriptors + bs.SkipBits(int(pmt.Program_info_length) * 8) + //fmt.Printf("section length %d pmt.Pogram_info_length=%d\n", pmt.Section_length, pmt.Pogram_info_length) + for i := 0; i < int(pmt.Section_length)-9-int(pmt.Program_info_length)-4; { + tmp := StreamPair{ + StreamType: 0, + Elementary_PID: 0, + ES_Info_Length: 0, + } + tmp.StreamType = bs.Uint8(8) + bs.SkipBits(3) + tmp.Elementary_PID = bs.Uint16(13) + bs.SkipBits(4) + tmp.ES_Info_Length = bs.Uint16(12) + //TODO N loop descriptors + bs.SkipBits(int(tmp.ES_Info_Length) * 8) + pmt.Streams = append(pmt.Streams, tmp) + i += 5 + int(tmp.ES_Info_Length) + } + return nil } diff --git a/trunk/3rdparty/srs-bench/vendor/modules.txt b/trunk/3rdparty/srs-bench/vendor/modules.txt index d99520a76..54943dbfb 100644 --- a/trunk/3rdparty/srs-bench/vendor/modules.txt +++ b/trunk/3rdparty/srs-bench/vendor/modules.txt @@ -33,6 +33,7 @@ github.com/ossrs/go-oryx-lib/amf0 github.com/ossrs/go-oryx-lib/avc github.com/ossrs/go-oryx-lib/errors github.com/ossrs/go-oryx-lib/flv +github.com/ossrs/go-oryx-lib/http github.com/ossrs/go-oryx-lib/logger github.com/ossrs/go-oryx-lib/rtmp # github.com/pion/datachannel v1.4.21 @@ -116,6 +117,7 @@ github.com/pion/webrtc/v3/pkg/media/oggreader github.com/pion/webrtc/v3/pkg/media/oggwriter github.com/pion/webrtc/v3/pkg/rtcerr # github.com/pkg/errors v0.9.1 +## explicit github.com/pkg/errors # github.com/satori/go.uuid v1.2.1-0.20181028125025-b2ce2384e17b github.com/satori/go.uuid diff --git a/trunk/conf/full.conf b/trunk/conf/full.conf index e01556c61..f16b799af 100644 --- a/trunk/conf/full.conf +++ b/trunk/conf/full.conf @@ -1515,6 +1515,7 @@ vhost http.remux.srs.com { vhost hooks.callback.srs.com { http_hooks { # whether the http hooks enable. + # Overwrite by env SRS_VHOST_HTTP_HOOKS_ENABLED for all vhosts. # default off. enabled on; # when client(encoder) publish to vhost/app/stream, call the hook, @@ -1533,6 +1534,7 @@ vhost hooks.callback.srs.com { # on_publish http://xxx/api0 http://xxx/api1 http://xxx/apiN # @remark For SRS4, the HTTPS url is supported, for example: # on_publish https://xxx/api0 https://xxx/api1 https://xxx/apiN + # Overwrite by env SRS_VHOST_HTTP_HOOKS_ON_PUBLISH for all vhosts. on_publish http://127.0.0.1:8085/api/v1/streams http://localhost:8085/api/v1/streams; # when client(encoder) stop publish to vhost/app/stream, call the hook, # the request in the POST data string is a object encode by json: @@ -1550,6 +1552,7 @@ vhost hooks.callback.srs.com { # on_unpublish http://xxx/api0 http://xxx/api1 http://xxx/apiN # @remark For SRS4, the HTTPS url is supported, for example: # on_unpublish https://xxx/api0 https://xxx/api1 https://xxx/apiN + # Overwrite by env SRS_VHOST_HTTP_HOOKS_ON_UNPUBLISH for all vhosts. on_unpublish http://127.0.0.1:8085/api/v1/streams http://localhost:8085/api/v1/streams; # when client start to play vhost/app/stream, call the hook, # the request in the POST data string is a object encode by json: @@ -1568,6 +1571,7 @@ vhost hooks.callback.srs.com { # on_play http://xxx/api0 http://xxx/api1 http://xxx/apiN # @remark For SRS4, the HTTPS url is supported, for example: # on_play https://xxx/api0 https://xxx/api1 https://xxx/apiN + # Overwrite by env SRS_VHOST_HTTP_HOOKS_ON_PLAY for all vhosts. on_play http://127.0.0.1:8085/api/v1/sessions http://localhost:8085/api/v1/sessions; # when client stop to play vhost/app/stream, call the hook, # the request in the POST data string is a object encode by json: @@ -1585,6 +1589,7 @@ vhost hooks.callback.srs.com { # on_stop http://xxx/api0 http://xxx/api1 http://xxx/apiN # @remark For SRS4, the HTTPS url is supported, for example: # on_stop https://xxx/api0 https://xxx/api1 https://xxx/apiN + # Overwrite by env SRS_VHOST_HTTP_HOOKS_ON_STOP for all vhosts. on_stop http://127.0.0.1:8085/api/v1/sessions http://localhost:8085/api/v1/sessions; # when srs reap a dvr file, call the hook, # the request in the POST data string is a object encode by json: @@ -1600,6 +1605,7 @@ vhost hooks.callback.srs.com { # if valid, the hook must return HTTP code 200(Status OK) and response # an int value specifies the error code(0 corresponding to success): # 0 + # Overwrite by env SRS_VHOST_HTTP_HOOKS_ON_DVR for all vhosts. on_dvr http://127.0.0.1:8085/api/v1/dvrs http://localhost:8085/api/v1/dvrs; # when srs reap a ts file of hls, call the hook, # the request in the POST data string is a object encode by json: @@ -1620,6 +1626,7 @@ vhost hooks.callback.srs.com { # if valid, the hook must return HTTP code 200(Status OK) and response # an int value specifies the error code(0 corresponding to success): # 0 + # Overwrite by env SRS_VHOST_HTTP_HOOKS_ON_HLS for all vhosts. on_hls http://127.0.0.1:8085/api/v1/hls http://localhost:8085/api/v1/hls; # when srs reap a ts file of hls, call this hook, # used to push file to cdn network, by get the ts file from cdn network. @@ -1631,6 +1638,7 @@ vhost hooks.callback.srs.com { # [ts_url], replace with the ts url. # ignore any return data of server. # @remark random select a url to report, not report all. + # Overwrite by env SRS_VHOST_HTTP_HOOKS_ON_HLS_NOTIFY for all vhosts. on_hls_notify http://127.0.0.1:8085/api/v1/hls/[server_id]/[app]/[stream]/[ts_url][param]; } } diff --git a/trunk/doc/CHANGELOG.md b/trunk/doc/CHANGELOG.md index 2b1e6aa74..10ab034c0 100644 --- a/trunk/doc/CHANGELOG.md +++ b/trunk/doc/CHANGELOG.md @@ -27,7 +27,8 @@ The changelog for SRS. ## SRS 5.0 Changelog -* v5.0, 2023-01-05, FFmpeg: Support build with FFmpeg native opus. v5.0.131 (#3140) +* v5.0, 2023-01-06, DVR: Support blackbox test based on hooks. v5.0.132 +* v5.0, 2023-01-06, FFmpeg: Support build with FFmpeg native opus. v5.0.131 (#3140) * v5.0, 2023-01-05, CORS: Refine HTTP CORS headers. v5.0.130 * v5.0, 2023-01-03, Add blackbox test for HLS and MP3 codec. v5.0.129 * v5.0, 2023-01-02, Merge [#3355](https://github.com/ossrs/srs/pull/3355): Test: Support blackbox test by FFmpeg. v5.0.128 diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index effecfc88..c4c7b5a91 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -68,6 +68,16 @@ const char* _srs_version = "XCORE-" RTMP_SIG_SRS_SERVER; #define SRS_OVERWRITE_BY_ENV_MILLISECONDS(key) if (!srs_getenv(key).empty()) return (srs_utime_t)(::atoi(srs_getenv(key).c_str()) * SRS_UTIME_MILLISECONDS) #define SRS_OVERWRITE_BY_ENV_FLOAT_SECONDS(key) if (!srs_getenv(key).empty()) return srs_utime_t(::atof(srs_getenv(key).c_str()) * SRS_UTIME_SECONDS) #define SRS_OVERWRITE_BY_ENV_FLOAT_MILLISECONDS(key) if (!srs_getenv(key).empty()) return srs_utime_t(::atof(srs_getenv(key).c_str()) * SRS_UTIME_MILLISECONDS) +#define SRS_OVERWRITE_BY_ENV_DIRECTIVE(key) { \ + static SrsConfDirective* dir = NULL; \ + if (!dir && !srs_getenv(key).empty()) { \ + string v = srs_getenv(key); \ + dir = new SrsConfDirective(); \ + dir->name = key; \ + dir->args.push_back(v); \ + } \ + if (dir) return dir; \ + } /** * dumps the ingest/transcode-engine in @param dir to amf0 object @param engine. @@ -5359,6 +5369,8 @@ SrsConfDirective* SrsConfig::get_vhost_http_hooks(string vhost) bool SrsConfig::get_vhost_http_hooks_enabled(string vhost) { + SRS_OVERWRITE_BY_ENV_BOOL("srs.vhost.http_hooks.enabled"); // SRS_VHOST_HTTP_HOOKS_ENABLED + static bool DEFAULT = false; SrsConfDirective* conf = get_vhost(vhost); @@ -5371,6 +5383,8 @@ bool SrsConfig::get_vhost_http_hooks_enabled(string vhost) bool SrsConfig::get_vhost_http_hooks_enabled(SrsConfDirective* vhost) { + SRS_OVERWRITE_BY_ENV_BOOL("srs.vhost.http_hooks.enabled"); // SRS_VHOST_HTTP_HOOKS_ENABLED + static bool DEFAULT = false; SrsConfDirective* conf = vhost->get("http_hooks"); @@ -5388,6 +5402,8 @@ bool SrsConfig::get_vhost_http_hooks_enabled(SrsConfDirective* vhost) SrsConfDirective* SrsConfig::get_vhost_on_connect(string vhost) { + SRS_OVERWRITE_BY_ENV_DIRECTIVE("srs.vhost.http_hooks.on_connect"); // SRS_VHOST_HTTP_HOOKS_ON_CONNECT + SrsConfDirective* conf = get_vhost_http_hooks(vhost); if (!conf) { return NULL; @@ -5398,6 +5414,8 @@ SrsConfDirective* SrsConfig::get_vhost_on_connect(string vhost) SrsConfDirective* SrsConfig::get_vhost_on_close(string vhost) { + SRS_OVERWRITE_BY_ENV_DIRECTIVE("srs.vhost.http_hooks.on_close"); // SRS_VHOST_HTTP_HOOKS_ON_CLOSE + SrsConfDirective* conf = get_vhost_http_hooks(vhost); if (!conf) { return NULL; @@ -5408,6 +5426,8 @@ SrsConfDirective* SrsConfig::get_vhost_on_close(string vhost) SrsConfDirective* SrsConfig::get_vhost_on_publish(string vhost) { + SRS_OVERWRITE_BY_ENV_DIRECTIVE("srs.vhost.http_hooks.on_publish"); // SRS_VHOST_HTTP_HOOKS_ON_PUBLISH + SrsConfDirective* conf = get_vhost_http_hooks(vhost); if (!conf) { return NULL; @@ -5418,6 +5438,8 @@ SrsConfDirective* SrsConfig::get_vhost_on_publish(string vhost) SrsConfDirective* SrsConfig::get_vhost_on_unpublish(string vhost) { + SRS_OVERWRITE_BY_ENV_DIRECTIVE("srs.vhost.http_hooks.on_unpublish"); // SRS_VHOST_HTTP_HOOKS_ON_UNPUBLISH + SrsConfDirective* conf = get_vhost_http_hooks(vhost); if (!conf) { return NULL; @@ -5428,6 +5450,8 @@ SrsConfDirective* SrsConfig::get_vhost_on_unpublish(string vhost) SrsConfDirective* SrsConfig::get_vhost_on_play(string vhost) { + SRS_OVERWRITE_BY_ENV_DIRECTIVE("srs.vhost.http_hooks.on_play"); // SRS_VHOST_HTTP_HOOKS_ON_PLAY + SrsConfDirective* conf = get_vhost_http_hooks(vhost); if (!conf) { return NULL; @@ -5438,6 +5462,8 @@ SrsConfDirective* SrsConfig::get_vhost_on_play(string vhost) SrsConfDirective* SrsConfig::get_vhost_on_stop(string vhost) { + SRS_OVERWRITE_BY_ENV_DIRECTIVE("srs.vhost.http_hooks.on_stop"); // SRS_VHOST_HTTP_HOOKS_ON_STOP + SrsConfDirective* conf = get_vhost_http_hooks(vhost); if (!conf) { return NULL; @@ -5448,6 +5474,8 @@ SrsConfDirective* SrsConfig::get_vhost_on_stop(string vhost) SrsConfDirective* SrsConfig::get_vhost_on_dvr(string vhost) { + SRS_OVERWRITE_BY_ENV_DIRECTIVE("srs.vhost.http_hooks.on_dvr"); // SRS_VHOST_HTTP_HOOKS_ON_DVR + SrsConfDirective* conf = get_vhost_http_hooks(vhost); if (!conf) { return NULL; @@ -5458,6 +5486,8 @@ SrsConfDirective* SrsConfig::get_vhost_on_dvr(string vhost) SrsConfDirective* SrsConfig::get_vhost_on_hls(string vhost) { + SRS_OVERWRITE_BY_ENV_DIRECTIVE("srs.vhost.http_hooks.on_hls"); // SRS_VHOST_HTTP_HOOKS_ON_HLS + SrsConfDirective* conf = get_vhost_http_hooks(vhost); if (!conf) { return NULL; @@ -5468,6 +5498,8 @@ SrsConfDirective* SrsConfig::get_vhost_on_hls(string vhost) SrsConfDirective* SrsConfig::get_vhost_on_hls_notify(string vhost) { + SRS_OVERWRITE_BY_ENV_DIRECTIVE("srs.vhost.http_hooks.on_hls_notify"); // SRS_VHOST_HTTP_HOOKS_ON_HLS_NOTIFY + SrsConfDirective* conf = get_vhost_http_hooks(vhost); if (!conf) { return NULL; diff --git a/trunk/src/core/srs_core_version5.hpp b/trunk/src/core/srs_core_version5.hpp index 021b485e2..bb69daa81 100644 --- a/trunk/src/core/srs_core_version5.hpp +++ b/trunk/src/core/srs_core_version5.hpp @@ -9,6 +9,6 @@ #define VERSION_MAJOR 5 #define VERSION_MINOR 0 -#define VERSION_REVISION 131 +#define VERSION_REVISION 132 #endif diff --git a/trunk/src/utest/srs_utest_config.cpp b/trunk/src/utest/srs_utest_config.cpp index ff00f0858..ddaf71ff9 100644 --- a/trunk/src/utest/srs_utest_config.cpp +++ b/trunk/src/utest/srs_utest_config.cpp @@ -3937,8 +3937,6 @@ VOID TEST(ConfigMainTest, SrtServerTlpktDrop) VOID TEST(ConfigEnvTest, CheckEnvValuesGlobal) { - srs_error_t err; - if (true) { MockSrsConfig conf; @@ -4035,8 +4033,6 @@ VOID TEST(ConfigEnvTest, CheckEnvValuesGlobal) VOID TEST(ConfigEnvTest, CheckEnvValuesthreads) { - srs_error_t err; - if (true) { MockSrsConfig conf; @@ -4047,8 +4043,6 @@ VOID TEST(ConfigEnvTest, CheckEnvValuesthreads) VOID TEST(ConfigEnvTest, CheckEnvValuesRtmp) { - srs_error_t err; - if (true) { MockSrsConfig conf; @@ -4082,8 +4076,6 @@ VOID TEST(ConfigEnvTest, CheckEnvValuesRtmp) VOID TEST(ConfigEnvTest, CheckEnvValuesHttpApi) { - srs_error_t err; - if (true) { MockSrsConfig conf; @@ -4126,8 +4118,6 @@ VOID TEST(ConfigEnvTest, CheckEnvValuesHttpApi) VOID TEST(ConfigEnvTest, CheckEnvValuesHttpServer) { - srs_error_t err; - if (true) { MockSrsConfig conf; @@ -4163,8 +4153,6 @@ VOID TEST(ConfigEnvTest, CheckEnvValuesHttpServer) VOID TEST(ConfigEnvTest, CheckEnvValuesSrtServer) { - srs_error_t err; - if (true) { MockSrsConfig conf; @@ -4220,8 +4208,6 @@ VOID TEST(ConfigEnvTest, CheckEnvValuesSrtServer) VOID TEST(ConfigEnvTest, CheckEnvValuesVhostSrt) { - srs_error_t err; - if (true) { MockSrsConfig conf; @@ -4235,8 +4221,6 @@ VOID TEST(ConfigEnvTest, CheckEnvValuesVhostSrt) VOID TEST(ConfigEnvTest, CheckEnvValuesRtcServer) { - srs_error_t err; - if (true) { MockSrsConfig conf; @@ -4303,8 +4287,6 @@ VOID TEST(ConfigEnvTest, CheckEnvValuesRtcServer) VOID TEST(ConfigEnvTest, CheckEnvValuesVhostRtc) { - srs_error_t err; - if (true) { MockSrsConfig conf; @@ -4362,8 +4344,6 @@ VOID TEST(ConfigEnvTest, CheckEnvValuesVhostRtc) VOID TEST(ConfigEnvTest, CheckEnvValuesVhostPlay) { - srs_error_t err; - if (true) { MockSrsConfig conf; @@ -4433,8 +4413,6 @@ VOID TEST(ConfigEnvTest, CheckEnvValuesVhostPlay) VOID TEST(ConfigEnvTest, CheckEnvValuesVhostPublish) { - srs_error_t err; - if (true) { MockSrsConfig conf; @@ -4460,8 +4438,6 @@ VOID TEST(ConfigEnvTest, CheckEnvValuesVhostPublish) VOID TEST(ConfigEnvTest, CheckEnvValuesCircuitBreaker) { - srs_error_t err; - if (true) { MockSrsConfig conf; @@ -4490,8 +4466,6 @@ VOID TEST(ConfigEnvTest, CheckEnvValuesCircuitBreaker) VOID TEST(ConfigEnvTest, CheckEnvValuesTencentcloudCls) { - srs_error_t err; - if (true) { MockSrsConfig conf; @@ -4539,8 +4513,6 @@ VOID TEST(ConfigEnvTest, CheckEnvValuesTencentcloudCls) VOID TEST(ConfigEnvTest, CheckEnvValuesTencentcloudApm) { - srs_error_t err; - if (true) { MockSrsConfig conf; @@ -4566,8 +4538,6 @@ VOID TEST(ConfigEnvTest, CheckEnvValuesTencentcloudApm) VOID TEST(ConfigEnvTest, CheckEnvValuesExporter) { - srs_error_t err; - if (true) { MockSrsConfig conf; @@ -4587,8 +4557,6 @@ VOID TEST(ConfigEnvTest, CheckEnvValuesExporter) VOID TEST(ConfigEnvTest, CheckEnvValuesHeartbeat) { - srs_error_t err; - if (true) { MockSrsConfig conf; @@ -4611,8 +4579,6 @@ VOID TEST(ConfigEnvTest, CheckEnvValuesHeartbeat) VOID TEST(ConfigEnvTest, CheckEnvValuesScope) { - srs_error_t err; - if (true) { MockSrsConfig conf; @@ -4646,8 +4612,6 @@ VOID TEST(ConfigEnvTest, CheckEnvValuesScope) VOID TEST(ConfigEnvTest, CheckEnvValuesHttpStatic) { - srs_error_t err; - if (true) { MockSrsConfig conf; @@ -4664,8 +4628,6 @@ VOID TEST(ConfigEnvTest, CheckEnvValuesHttpStatic) VOID TEST(ConfigEnvTest, CheckEnvValuesHttpRemux) { - srs_error_t err; - MockSrsConfig conf; if (true) { @@ -4722,8 +4684,6 @@ VOID TEST(ConfigEnvTest, CheckEnvValuesHttpRemux) VOID TEST(ConfigEnvTest, CheckEnvValuesDash) { - srs_error_t err; - if (true) { MockSrsConfig conf; @@ -4776,8 +4736,6 @@ VOID TEST(ConfigEnvTest, CheckEnvValuesHds) VOID TEST(ConfigEnvTest, CheckEnvValuesDvr) { - srs_error_t err; - if (true) { MockSrsConfig conf; @@ -4806,8 +4764,6 @@ VOID TEST(ConfigEnvTest, CheckEnvValuesDvr) VOID TEST(ConfigEnvTest, CheckEnvValuesHls) { - srs_error_t err; - if (true) { MockSrsConfig conf; @@ -4886,4 +4842,71 @@ VOID TEST(ConfigEnvTest, CheckEnvValuesHls) SrsSetEnvConfig(hls_dts_directly, "SRS_VHOST_HLS_HLS_DTS_DIRECTLY", "off"); EXPECT_FALSE(conf.get_vhost_hls_dts_directly("__defaultVhost__")); } -} \ No newline at end of file +} + +VOID TEST(ConfigEnvTest, CheckEnvValuesHooks) +{ + MockSrsConfig conf; + + if (true) { + SrsSetEnvConfig(hooks, "SRS_VHOST_HTTP_HOOKS_ENABLED", "on"); + EXPECT_TRUE(conf.get_vhost_http_hooks_enabled("__defaultVhost__")); + } + + if (true) { + SrsSetEnvConfig(hooks, "SRS_VHOST_HTTP_HOOKS_ON_PUBLISH", "http://server/api/publish"); + SrsConfDirective* dir = conf.get_vhost_on_publish("__defaultVhost__"); + ASSERT_TRUE(dir != NULL); + ASSERT_TRUE((int)dir->args.size() == 1); + ASSERT_STREQ("http://server/api/publish", dir->arg0().c_str()); + } + + if (true) { + SrsSetEnvConfig(hooks, "SRS_VHOST_HTTP_HOOKS_ON_UNPUBLISH", "http://server/api/unpublish"); + SrsConfDirective* dir = conf.get_vhost_on_unpublish("__defaultVhost__"); + ASSERT_TRUE(dir != NULL); + ASSERT_TRUE((int)dir->args.size() == 1); + ASSERT_STREQ("http://server/api/unpublish", dir->arg0().c_str()); + } + + if (true) { + SrsSetEnvConfig(hooks, "SRS_VHOST_HTTP_HOOKS_ON_PLAY", "http://server/api/play"); + SrsConfDirective* dir = conf.get_vhost_on_play("__defaultVhost__"); + ASSERT_TRUE(dir != NULL); + ASSERT_TRUE((int)dir->args.size() == 1); + ASSERT_STREQ("http://server/api/play", dir->arg0().c_str()); + } + + if (true) { + SrsSetEnvConfig(hooks, "SRS_VHOST_HTTP_HOOKS_ON_STOP", "http://server/api/stop"); + SrsConfDirective* dir = conf.get_vhost_on_stop("__defaultVhost__"); + ASSERT_TRUE(dir != NULL); + ASSERT_TRUE((int)dir->args.size() == 1); + ASSERT_STREQ("http://server/api/stop", dir->arg0().c_str()); + } + + if (true) { + SrsSetEnvConfig(hooks, "SRS_VHOST_HTTP_HOOKS_ON_DVR", "http://server/api/dvr"); + SrsConfDirective* dir = conf.get_vhost_on_dvr("__defaultVhost__"); + ASSERT_TRUE(dir != NULL); + ASSERT_TRUE((int)dir->args.size() == 1); + ASSERT_STREQ("http://server/api/dvr", dir->arg0().c_str()); + } + + if (true) { + SrsSetEnvConfig(hooks, "SRS_VHOST_HTTP_HOOKS_ON_HLS", "http://server/api/hls"); + SrsConfDirective* dir = conf.get_vhost_on_hls("__defaultVhost__"); + ASSERT_TRUE(dir != NULL); + ASSERT_TRUE((int)dir->args.size() == 1); + ASSERT_STREQ("http://server/api/hls", dir->arg0().c_str()); + } + + if (true) { + SrsSetEnvConfig(hooks, "SRS_VHOST_HTTP_HOOKS_ON_HLS_NOTIFY", "http://server/api/hls_notify"); + SrsConfDirective* dir = conf.get_vhost_on_hls_notify("__defaultVhost__"); + ASSERT_TRUE(dir != NULL); + ASSERT_TRUE((int)dir->args.size() == 1); + ASSERT_STREQ("http://server/api/hls_notify", dir->arg0().c_str()); + } +} +