mirror of
https://github.com/Danile71/go-rtsp.git
synced 2025-09-26 20:21:15 +08:00
Merge branch 'dev'
This commit is contained in:
11
CHANGELOG.md
11
CHANGELOG.md
@@ -5,7 +5,15 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [Unreleased]
|
||||
### Added
|
||||
- [x] Add avformat_close_input
|
||||
- [x] Remove avresample
|
||||
|
||||
## [0.1.0] - 2021-07-23
|
||||
### Added
|
||||
- [x] Doc
|
||||
|
||||
>>>>>>> dev
|
||||
## [0.0.3] - 2021-07-22
|
||||
### Added
|
||||
- [x] New examples
|
||||
@@ -24,7 +32,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
### Added
|
||||
- [x] Init repo
|
||||
|
||||
[Unreleased]: https://github.com/Danile71/go-rtsp/compare/v0.0.3...master
|
||||
[Unreleased]: https://github.com/Danile71/go-rtsp/compare/v0.1.0...master
|
||||
[0.1.0]: https://github.com/Danile71/go-rtsp/compare/v0.0.3...v0.1.0
|
||||
[0.0.3]: https://github.com/Danile71/go-rtsp/compare/v0.0.2...v0.0.3
|
||||
[0.0.2]: https://github.com/Danile71/go-rtsp/compare/v0.0.1...v0.0.2
|
||||
[0.0.1]: https://github.com/Danile71/go-rtsp/tree/v0.0.1
|
||||
|
35
decoder.go
35
decoder.go
@@ -7,6 +7,7 @@ package rtsp
|
||||
import "C"
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
@@ -24,6 +25,40 @@ func decodeAVPacket(packet *C.AVPacket) (data []byte) {
|
||||
return
|
||||
}
|
||||
|
||||
func newDecoder(cstream *C.AVStream) (*decoder, error) {
|
||||
decoder := &decoder{index: int(cstream.index)}
|
||||
runtime.SetFinalizer(decoder, freeDecoder)
|
||||
|
||||
decoder.swrContext = nil
|
||||
decoder.codecCtx = C.avcodec_alloc_context3(nil)
|
||||
C.avcodec_parameters_to_context(decoder.codecCtx, cstream.codecpar)
|
||||
decoder.codec = C.avcodec_find_decoder(decoder.codecCtx.codec_id)
|
||||
decoder.codecType = int(cstream.codecpar.codec_type)
|
||||
if decoder.codec == nil {
|
||||
return nil, fmt.Errorf("ffmpeg: avcodec_find_decoder failed: codec %d not found", decoder.codecCtx.codec_id)
|
||||
}
|
||||
|
||||
if cerr := C.avcodec_open2(decoder.codecCtx, decoder.codec, nil); int(cerr) != 0 {
|
||||
return nil, fmt.Errorf("ffmpeg: avcodec_open2 failed: %d", cerr)
|
||||
}
|
||||
return decoder, nil
|
||||
}
|
||||
|
||||
func freeDecoder(decoder *decoder) {
|
||||
if decoder.codecCtx != nil {
|
||||
C.avcodec_close(decoder.codecCtx)
|
||||
C.av_free(unsafe.Pointer(decoder.codecCtx))
|
||||
decoder.codecCtx = nil
|
||||
}
|
||||
if decoder.codec != nil {
|
||||
decoder.codec = nil
|
||||
}
|
||||
if decoder.swrContext != nil {
|
||||
C.swr_close(decoder.swrContext)
|
||||
C.swr_free(&decoder.swrContext)
|
||||
}
|
||||
}
|
||||
|
||||
func (decoder *decoder) Decode(packet *C.AVPacket) (pkt *Packet, err error) {
|
||||
pkt = &Packet{}
|
||||
|
||||
|
1
ffmpeg.h
1
ffmpeg.h
@@ -3,7 +3,6 @@
|
||||
#include <libavutil/avutil.h>
|
||||
#include <libavutil/imgutils.h>
|
||||
#include <libswresample/swresample.h>
|
||||
#include <libavresample/avresample.h>
|
||||
#include <libswscale/swscale.h>
|
||||
#include <libavutil/opt.h>
|
||||
#include <string.h>
|
||||
|
6
rtsp.go
6
rtsp.go
@@ -1,7 +1,7 @@
|
||||
package rtsp
|
||||
|
||||
// Open rtsp stream of file
|
||||
func Open(url string) (*Stream, error) {
|
||||
stream := New(url)
|
||||
// Open rtsp stream or file
|
||||
func Open(uri string) (*Stream, error) {
|
||||
stream := New(uri)
|
||||
return stream, stream.Setup(Auto)
|
||||
}
|
||||
|
56
stream.go
56
stream.go
@@ -23,13 +23,15 @@ const (
|
||||
type Stream struct {
|
||||
formatCtx *C.AVFormatContext
|
||||
dictionary *C.AVDictionary
|
||||
decoders map[int]*decoder
|
||||
mu sync.RWMutex
|
||||
url string
|
||||
|
||||
decoders map[int]*decoder
|
||||
mu sync.RWMutex
|
||||
uri string
|
||||
}
|
||||
|
||||
func New(url string) (stream *Stream) {
|
||||
stream = &Stream{url: url}
|
||||
// New stream
|
||||
func New(uri string) (stream *Stream) {
|
||||
stream = &Stream{uri: uri}
|
||||
stream.decoders = make(map[int]*decoder)
|
||||
stream.formatCtx = C.avformat_alloc_context()
|
||||
|
||||
@@ -39,38 +41,18 @@ func New(url string) (stream *Stream) {
|
||||
|
||||
func free(stream *Stream) {
|
||||
if stream.formatCtx != nil {
|
||||
C.avformat_close_input(&stream.formatCtx)
|
||||
C.avformat_free_context(stream.formatCtx)
|
||||
stream.formatCtx = nil
|
||||
|
||||
}
|
||||
|
||||
if stream.dictionary != nil {
|
||||
C.av_dict_free(&stream.dictionary)
|
||||
stream.dictionary = nil
|
||||
}
|
||||
|
||||
for _, decoder := range stream.decoders {
|
||||
if decoder != nil {
|
||||
if decoder.codecCtx != nil {
|
||||
C.avcodec_close(decoder.codecCtx)
|
||||
C.av_free(unsafe.Pointer(decoder.codecCtx))
|
||||
decoder.codecCtx = nil
|
||||
}
|
||||
if decoder.codec != nil {
|
||||
decoder.codec = nil
|
||||
}
|
||||
|
||||
if decoder.swrContext != nil {
|
||||
C.swr_close(decoder.swrContext)
|
||||
C.swr_free(&decoder.swrContext)
|
||||
}
|
||||
|
||||
decoder = nil
|
||||
}
|
||||
}
|
||||
stream.decoders = nil
|
||||
}
|
||||
|
||||
// Setup transport (tcp or udp)
|
||||
func (stream *Stream) Setup(t Type) (err error) {
|
||||
transport := C.CString("rtsp_transport")
|
||||
defer C.free(unsafe.Pointer(transport))
|
||||
@@ -89,7 +71,7 @@ func (stream *Stream) Setup(t Type) (err error) {
|
||||
default:
|
||||
}
|
||||
|
||||
uri := C.CString(stream.url)
|
||||
uri := C.CString(stream.uri)
|
||||
defer C.free(unsafe.Pointer(uri))
|
||||
|
||||
cerr := C.avformat_open_input(&stream.formatCtx, uri, nil, &stream.dictionary)
|
||||
@@ -112,22 +94,12 @@ func (stream *Stream) Setup(t Type) (err error) {
|
||||
|
||||
switch cstream.codecpar.codec_type {
|
||||
case C.AVMEDIA_TYPE_VIDEO, C.AVMEDIA_TYPE_AUDIO:
|
||||
decoder := &decoder{index: int(cstream.index)}
|
||||
decoder.swrContext = nil
|
||||
stream.decoders[decoder.index] = decoder
|
||||
decoder.codecCtx = C.avcodec_alloc_context3(nil)
|
||||
C.avcodec_parameters_to_context(decoder.codecCtx, cstream.codecpar)
|
||||
decoder.codec = C.avcodec_find_decoder(decoder.codecCtx.codec_id)
|
||||
decoder.codecType = int(cstream.codecpar.codec_type)
|
||||
if decoder.codec == nil {
|
||||
err = fmt.Errorf("ffmpeg: avcodec_find_decoder failed: codec %d not found", decoder.codecCtx.codec_id)
|
||||
return
|
||||
decoder, err := newDecoder(cstream)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if cerr = C.avcodec_open2(decoder.codecCtx, decoder.codec, nil); int(cerr) != 0 {
|
||||
err = fmt.Errorf("ffmpeg: avcodec_open2 failed: %d", cerr)
|
||||
return
|
||||
}
|
||||
stream.decoders[decoder.index] = decoder
|
||||
case C.AVMEDIA_TYPE_DATA, C.AVMEDIA_TYPE_SUBTITLE, C.AVMEDIA_TYPE_NB, C.AVMEDIA_TYPE_ATTACHMENT:
|
||||
// do nothing
|
||||
default:
|
||||
|
Reference in New Issue
Block a user