mirror of
https://github.com/pion/mediadevices.git
synced 2025-09-27 21:02:17 +08:00
Compare commits
14 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
ad37c826b9 | ||
![]() |
d84d0a3b0c | ||
![]() |
c068f1176d | ||
![]() |
76908aca89 | ||
![]() |
f3ac1f5480 | ||
![]() |
6280b450ba | ||
![]() |
db0884a77c | ||
![]() |
1b5203d3a0 | ||
![]() |
f472618b71 | ||
![]() |
7f4d1bc5ad | ||
![]() |
97046bc6ec | ||
![]() |
7bcc9111f4 | ||
![]() |
044b5566d1 | ||
![]() |
7f41f9b8df |
16
.github/workflows/ci.yaml
vendored
16
.github/workflows/ci.yaml
vendored
@@ -11,6 +11,7 @@ jobs:
|
||||
build-linux:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
go: [ '1.15', '1.14' ]
|
||||
name: Linux Go ${{ matrix.go }}
|
||||
@@ -48,6 +49,7 @@ jobs:
|
||||
build-darwin:
|
||||
runs-on: macos-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
go: [ '1.15', '1.14' ]
|
||||
name: Darwin Go ${{ matrix.go }}
|
||||
@@ -79,3 +81,17 @@ jobs:
|
||||
run: go test . pkg/... -v
|
||||
env:
|
||||
CGO_ENABLED: 0
|
||||
check-licenses:
|
||||
runs-on: ubuntu-latest
|
||||
name: Check Licenses
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: '1.15'
|
||||
- name: Installing go-licenses
|
||||
run: go get github.com/google/go-licenses
|
||||
- name: Checking licenses
|
||||
run: go-licenses check ./...
|
||||
|
2
.gitignore
vendored
2
.gitignore
vendored
@@ -10,3 +10,5 @@
|
||||
|
||||
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||
*.out
|
||||
|
||||
scripts/cross
|
||||
|
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -1,3 +0,0 @@
|
||||
[submodule "cvendor/src/openh264"]
|
||||
path = cvendor/src/openh264
|
||||
url = https://github.com/cisco/openh264.git
|
||||
|
56
Makefile
56
Makefile
@@ -1,56 +0,0 @@
|
||||
vendor_dir = cvendor
|
||||
src_dir = $(vendor_dir)/src
|
||||
lib_dir = $(vendor_dir)/lib
|
||||
include_dir = $(vendor_dir)/include
|
||||
|
||||
make_args.x86_64-windows = \
|
||||
CC=x86_64-w64-mingw32-gcc \
|
||||
CXX=x86_64-w64-mingw32-g++ \
|
||||
ARCH=x86_64 \
|
||||
OS=mingw_nt
|
||||
make_args.x86_64-darwin = \
|
||||
CC=o64-clang \
|
||||
CXX=o64-clang++ \
|
||||
AR=llvm-ar \
|
||||
ARCH=x86_64 \
|
||||
OS=darwin
|
||||
|
||||
.PHONY: vendor
|
||||
vendor: \
|
||||
$(include_dir)/openh264 \
|
||||
cross-libraries
|
||||
|
||||
$(include_dir)/openh264: $(src_dir)/openh264
|
||||
mkdir -p $@
|
||||
cp $^/codec/api/svc/*.h $@
|
||||
|
||||
$(lib_dir)/openh264/libopenh264.x86_64-linux.a: $(src_dir)/openh264
|
||||
$(MAKE) -C $^ clean \
|
||||
&& $(MAKE) -C $^ libraries
|
||||
mkdir -p $(dir $@)
|
||||
cp $^/libopenh264.a $@
|
||||
|
||||
$(lib_dir)/openh264/libopenh264.x86_64-windows.a: $(src_dir)/openh264
|
||||
$(MAKE) -C $^ clean \
|
||||
&& $(MAKE) -C $^ $(make_args.x86_64-windows) libraries
|
||||
mkdir -p $(dir $@)
|
||||
cp $^/libopenh264.a $@
|
||||
|
||||
$(lib_dir)/openh264/libopenh264.x86_64-darwin.a: $(src_dir)/openh264
|
||||
$(MAKE) -C $^ clean \
|
||||
&& $(MAKE) -C $^ $(make_args.x86_64-darwin) libraries
|
||||
mkdir -p $(dir $@)
|
||||
cp $^/libopenh264.a $@
|
||||
|
||||
.PHONY: cross-libraries
|
||||
cross-libraries:
|
||||
docker build -t mediadevices-libs-builder -f libs-builder.Dockerfile .
|
||||
docker run --rm \
|
||||
-v $(CURDIR):/go/src/github.com/pion/mediadevices \
|
||||
mediadevices-libs-builder make $(lib_dir)/openh264/libopenh264.x86_64-linux.a
|
||||
docker run --rm \
|
||||
-v $(CURDIR):/go/src/github.com/pion/mediadevices \
|
||||
mediadevices-libs-builder make $(lib_dir)/openh264/libopenh264.x86_64-windows.a
|
||||
docker run --rm \
|
||||
-v $(CURDIR):/go/src/github.com/pion/mediadevices \
|
||||
mediadevices-libs-builder make $(lib_dir)/openh264/libopenh264.x86_64-darwin.a
|
70
build.sh
Executable file
70
build.sh
Executable file
@@ -0,0 +1,70 @@
|
||||
#!/bin/bash
|
||||
|
||||
MEDIADEVICES_TOOLCHAIN_OWNER=lherman
|
||||
MEDIADEVICES_TOOLCHAIN_PREFIX=cross
|
||||
MEDIADEVICES_SCRIPT_PATH=$(realpath ./scripts)
|
||||
MEDIADEVICES_TOOLCHAIN_PATH=${MEDIADEVICES_SCRIPT_PATH}/${MEDIADEVICES_TOOLCHAIN_PREFIX}
|
||||
MEDIADEVICES_DOCKERFILES_PATH=dockerfiles
|
||||
|
||||
# Reference: https://github.com/dockcross/dockcross#cross-compilers
|
||||
MEDIADEVICES_TARGET_PLATFORMS=(
|
||||
linux-armv7
|
||||
linux-arm64
|
||||
linux-x64
|
||||
windows-x64
|
||||
darwin-x64
|
||||
)
|
||||
|
||||
if [[ -z ${VERBOSE} ]]; then
|
||||
MEDIADEVICES_OUTPUT=/dev/null
|
||||
else
|
||||
MEDIADEVICES_OUTPUT=/dev/stdout
|
||||
fi
|
||||
|
||||
install_toolchains() {
|
||||
bash ${MEDIADEVICES_DOCKERFILES_PATH}/build.sh &> ${MEDIADEVICES_OUTPUT}
|
||||
for platform in ${MEDIADEVICES_TARGET_PLATFORMS[@]}
|
||||
do
|
||||
mkdir -p ${MEDIADEVICES_TOOLCHAIN_PATH}
|
||||
image=${MEDIADEVICES_TOOLCHAIN_OWNER}/${MEDIADEVICES_TOOLCHAIN_PREFIX}-${platform}
|
||||
bin_path=${MEDIADEVICES_TOOLCHAIN_PATH}/${MEDIADEVICES_TOOLCHAIN_PREFIX}-${platform}
|
||||
docker run ${image} > ${bin_path}
|
||||
chmod +x ${bin_path}
|
||||
done
|
||||
}
|
||||
|
||||
build() {
|
||||
sub_builds=$(find pkg -type f -name "build.sh")
|
||||
for sub_build in ${sub_builds[@]}
|
||||
do
|
||||
sub_build=$(realpath ${sub_build})
|
||||
sub_build_dir=$(dirname ${sub_build})
|
||||
current_dir=${PWD}
|
||||
cd $sub_build_dir
|
||||
for platform in ${MEDIADEVICES_TARGET_PLATFORMS[@]}
|
||||
do
|
||||
export MEDIADEVICES_TOOLCHAIN_BIN=${MEDIADEVICES_TOOLCHAIN_PATH}/${MEDIADEVICES_TOOLCHAIN_PREFIX}-${platform}
|
||||
# convert '-' to '_' since '_' is more common in library names
|
||||
export MEDIADEVICES_TARGET_PLATFORM=${platform//-/_}
|
||||
export MEDIADEVICES_TARGET_OS=$(echo $MEDIADEVICES_TARGET_PLATFORM | cut -d'_' -f1)
|
||||
export MEDIADEVICES_TARGET_ARCH=${platform//${MEDIADEVICES_TARGET_OS}-/}
|
||||
|
||||
echo "Building ${sub_build_dir}:"
|
||||
echo " PLATFORM : ${MEDIADEVICES_TARGET_PLATFORM}"
|
||||
echo " OS : ${MEDIADEVICES_TARGET_OS}"
|
||||
echo " ARCH : ${MEDIADEVICES_TARGET_ARCH}"
|
||||
echo " TOOLCHAIN_BIN : ${MEDIADEVICES_TOOLCHAIN_BIN}"
|
||||
echo ""
|
||||
|
||||
${sub_build} &> ${MEDIADEVICES_OUTPUT}
|
||||
done
|
||||
cd ${current_dir}
|
||||
done
|
||||
}
|
||||
|
||||
if [[ $# > 0 && $1 != "all" ]]; then
|
||||
MEDIADEVICES_TARGET_PLATFORMS=($1)
|
||||
fi
|
||||
|
||||
install_toolchains
|
||||
build
|
28
codec.go
28
codec.go
@@ -9,7 +9,7 @@ import (
|
||||
"github.com/pion/mediadevices/pkg/io/audio"
|
||||
"github.com/pion/mediadevices/pkg/io/video"
|
||||
"github.com/pion/mediadevices/pkg/prop"
|
||||
"github.com/pion/webrtc/v2"
|
||||
"github.com/pion/webrtc/v3"
|
||||
)
|
||||
|
||||
// CodecSelector is a container of video and audio encoder builders, which later will be used
|
||||
@@ -50,14 +50,15 @@ func NewCodecSelector(opts ...CodecSelectorOption) *CodecSelector {
|
||||
// Populate lets the webrtc engine be aware of supported codecs that are contained in CodecSelector
|
||||
func (selector *CodecSelector) Populate(setting *webrtc.MediaEngine) {
|
||||
for _, encoder := range selector.videoEncoders {
|
||||
setting.RegisterCodec(encoder.RTPCodec().RTPCodec)
|
||||
setting.RegisterCodec(encoder.RTPCodec().RTPCodecParameters, webrtc.RTPCodecTypeVideo)
|
||||
}
|
||||
|
||||
for _, encoder := range selector.audioEncoders {
|
||||
setting.RegisterCodec(encoder.RTPCodec().RTPCodec)
|
||||
setting.RegisterCodec(encoder.RTPCodec().RTPCodecParameters, webrtc.RTPCodecTypeAudio)
|
||||
}
|
||||
}
|
||||
|
||||
// selectVideoCodecByNames selects a single codec that can be built and matched. codecNames can be formatted as "video/<codecName>" or "<codecName>"
|
||||
func (selector *CodecSelector) selectVideoCodecByNames(reader video.Reader, inputProp prop.Media, codecNames ...string) (codec.ReadCloser, *codec.RTPCodec, error) {
|
||||
var selectedEncoder codec.VideoEncoderBuilder
|
||||
var encodedReader codec.ReadCloser
|
||||
@@ -66,8 +67,10 @@ func (selector *CodecSelector) selectVideoCodecByNames(reader video.Reader, inpu
|
||||
|
||||
outer:
|
||||
for _, wantCodec := range codecNames {
|
||||
wantCodecLower := strings.ToLower(wantCodec)
|
||||
for _, encoder := range selector.videoEncoders {
|
||||
if encoder.RTPCodec().Name == wantCodec {
|
||||
// MimeType is formated as "video/<codecName>"
|
||||
if strings.HasSuffix(strings.ToLower(encoder.RTPCodec().MimeType), wantCodecLower) {
|
||||
encodedReader, err = encoder.BuildVideoEncoder(reader, inputProp)
|
||||
if err == nil {
|
||||
selectedEncoder = encoder
|
||||
@@ -75,7 +78,7 @@ outer:
|
||||
}
|
||||
}
|
||||
|
||||
errReasons = append(errReasons, fmt.Sprintf("%s: %s", encoder.RTPCodec().Name, err))
|
||||
errReasons = append(errReasons, fmt.Sprintf("%s: %s", encoder.RTPCodec().MimeType, err))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,16 +89,17 @@ outer:
|
||||
return encodedReader, selectedEncoder.RTPCodec(), nil
|
||||
}
|
||||
|
||||
func (selector *CodecSelector) selectVideoCodec(reader video.Reader, inputProp prop.Media, codecs ...*webrtc.RTPCodec) (codec.ReadCloser, *codec.RTPCodec, error) {
|
||||
func (selector *CodecSelector) selectVideoCodec(reader video.Reader, inputProp prop.Media, codecs ...webrtc.RTPCodecParameters) (codec.ReadCloser, *codec.RTPCodec, error) {
|
||||
var codecNames []string
|
||||
|
||||
for _, codec := range codecs {
|
||||
codecNames = append(codecNames, codec.Name)
|
||||
codecNames = append(codecNames, codec.MimeType)
|
||||
}
|
||||
|
||||
return selector.selectVideoCodecByNames(reader, inputProp, codecNames...)
|
||||
}
|
||||
|
||||
// selectAudioCodecByNames selects a single codec that can be built and matched. codecNames can be formatted as "audio/<codecName>" or "<codecName>"
|
||||
func (selector *CodecSelector) selectAudioCodecByNames(reader audio.Reader, inputProp prop.Media, codecNames ...string) (codec.ReadCloser, *codec.RTPCodec, error) {
|
||||
var selectedEncoder codec.AudioEncoderBuilder
|
||||
var encodedReader codec.ReadCloser
|
||||
@@ -104,8 +108,10 @@ func (selector *CodecSelector) selectAudioCodecByNames(reader audio.Reader, inpu
|
||||
|
||||
outer:
|
||||
for _, wantCodec := range codecNames {
|
||||
wantCodecLower := strings.ToLower(wantCodec)
|
||||
for _, encoder := range selector.audioEncoders {
|
||||
if encoder.RTPCodec().Name == wantCodec {
|
||||
// MimeType is formated as "audio/<codecName>"
|
||||
if strings.HasSuffix(strings.ToLower(encoder.RTPCodec().MimeType), wantCodecLower) {
|
||||
encodedReader, err = encoder.BuildAudioEncoder(reader, inputProp)
|
||||
if err == nil {
|
||||
selectedEncoder = encoder
|
||||
@@ -113,7 +119,7 @@ outer:
|
||||
}
|
||||
}
|
||||
|
||||
errReasons = append(errReasons, fmt.Sprintf("%s: %s", encoder.RTPCodec().Name, err))
|
||||
errReasons = append(errReasons, fmt.Sprintf("%s: %s", encoder.RTPCodec().MimeType, err))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,11 +130,11 @@ outer:
|
||||
return encodedReader, selectedEncoder.RTPCodec(), nil
|
||||
}
|
||||
|
||||
func (selector *CodecSelector) selectAudioCodec(reader audio.Reader, inputProp prop.Media, codecs ...*webrtc.RTPCodec) (codec.ReadCloser, *codec.RTPCodec, error) {
|
||||
func (selector *CodecSelector) selectAudioCodec(reader audio.Reader, inputProp prop.Media, codecs ...webrtc.RTPCodecParameters) (codec.ReadCloser, *codec.RTPCodec, error) {
|
||||
var codecNames []string
|
||||
|
||||
for _, codec := range codecs {
|
||||
codecNames = append(codecNames, codec.Name)
|
||||
codecNames = append(codecNames, codec.MimeType)
|
||||
}
|
||||
|
||||
return selector.selectAudioCodecByNames(reader, inputProp, codecNames...)
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Submodule cvendor/src/openh264 deleted from 71374015cd
13
dockerfiles/build.sh
Executable file
13
dockerfiles/build.sh
Executable file
@@ -0,0 +1,13 @@
|
||||
#!/bin/bash
|
||||
|
||||
cd $(dirname $0)
|
||||
|
||||
OWNER=lherman
|
||||
PREFIX=cross
|
||||
IMAGES=$(ls *.Dockerfile)
|
||||
|
||||
for image in ${IMAGES[@]}
|
||||
do
|
||||
tag=${OWNER}/cross-${image//.Dockerfile/}
|
||||
docker build -t "${tag}" -f "$image" .
|
||||
done
|
23
dockerfiles/darwin-x64.Dockerfile
Normal file
23
dockerfiles/darwin-x64.Dockerfile
Normal file
@@ -0,0 +1,23 @@
|
||||
FROM dockcross/base
|
||||
|
||||
ENV OSX_CROSS_PATH=/osxcross
|
||||
|
||||
COPY --from=dockercore/golang-cross "${OSX_CROSS_PATH}/." "${OSX_CROSS_PATH}/"
|
||||
ENV PATH=${OSX_CROSS_PATH}/target/bin:$PATH
|
||||
|
||||
COPY init.sh /tmp/init.sh
|
||||
RUN bash /tmp/init.sh
|
||||
|
||||
ENV CC=x86_64-apple-darwin14-clang \
|
||||
CXX=x86_64-apple-darwin14-clang++ \
|
||||
CPP=x86_64-apple-darwin14-clang++ \
|
||||
AR=x86_64-apple-darwin14-ar \
|
||||
AS=x86_64-apple-darwin14-as \
|
||||
LD=x86_64-apple-darwin14-ld
|
||||
|
||||
COPY darwin-x64.cmake ${OSX_CROSS_PATH}/
|
||||
ENV CMAKE_TOOLCHAIN_FILE ${OSX_CROSS_PATH}/darwin-x64.cmake
|
||||
|
||||
ARG IMAGE=lherman/cross-darwin-x64
|
||||
ARG VERSION=latest
|
||||
ENV DEFAULT_DOCKCROSS_IMAGE ${IMAGE}:${VERSION}
|
8
dockerfiles/darwin-x64.cmake
Normal file
8
dockerfiles/darwin-x64.cmake
Normal file
@@ -0,0 +1,8 @@
|
||||
set(CMAKE_SYSTEM_NAME Darwin)
|
||||
set(CMAKE_SYSTEM_VERSION 1)
|
||||
set(CMAKE_SYSTEM_PROCESSOR x86_64)
|
||||
|
||||
set(CMAKE_C_COMPILER $ENV{CC})
|
||||
set(CMAKE_CXX_COMPILER $ENV{CXX})
|
||||
set(CMAKE_AR $ENV{AR})
|
||||
set(CMAKE_ASM_COMPILER ${CMAKE_C_COMPILER})
|
7
dockerfiles/init.sh
Executable file
7
dockerfiles/init.sh
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
apt-get update
|
||||
apt-get install -y nasm clang llvm
|
||||
|
||||
curl -L https://golang.org/dl/go1.15.6.linux-amd64.tar.gz | tar -C /usr/local -xzf -
|
||||
ln -s /usr/local/go/bin/go /usr/local/bin/go
|
8
dockerfiles/linux-arm64.Dockerfile
Normal file
8
dockerfiles/linux-arm64.Dockerfile
Normal file
@@ -0,0 +1,8 @@
|
||||
FROM dockcross/linux-arm64
|
||||
|
||||
ARG IMAGE=lherman/cross-linux-arm64
|
||||
ARG VERSION=latest
|
||||
ENV DEFAULT_DOCKCROSS_IMAGE ${IMAGE}:${VERSION}
|
||||
|
||||
COPY init.sh /tmp/init.sh
|
||||
RUN bash /tmp/init.sh
|
8
dockerfiles/linux-armv7.Dockerfile
Normal file
8
dockerfiles/linux-armv7.Dockerfile
Normal file
@@ -0,0 +1,8 @@
|
||||
FROM dockcross/linux-armv7
|
||||
|
||||
ARG IMAGE=lherman/cross-linux-armv7
|
||||
ARG VERSION=latest
|
||||
ENV DEFAULT_DOCKCROSS_IMAGE ${IMAGE}:${VERSION}
|
||||
|
||||
COPY init.sh /tmp/init.sh
|
||||
RUN bash /tmp/init.sh
|
8
dockerfiles/linux-x64.Dockerfile
Normal file
8
dockerfiles/linux-x64.Dockerfile
Normal file
@@ -0,0 +1,8 @@
|
||||
FROM dockcross/linux-x64
|
||||
|
||||
ARG IMAGE=lherman/cross-linux-x64
|
||||
ARG VERSION=latest
|
||||
ENV DEFAULT_DOCKCROSS_IMAGE ${IMAGE}:${VERSION}
|
||||
|
||||
COPY init.sh /tmp/init.sh
|
||||
RUN bash /tmp/init.sh
|
11
dockerfiles/windows-x64.Dockerfile
Normal file
11
dockerfiles/windows-x64.Dockerfile
Normal file
@@ -0,0 +1,11 @@
|
||||
FROM dockcross/windows-static-x64-posix
|
||||
|
||||
ARG IMAGE=lherman/cross-windows-x64
|
||||
ARG VERSION=latest
|
||||
ENV DEFAULT_DOCKCROSS_IMAGE ${IMAGE}:${VERSION}
|
||||
|
||||
COPY init.sh /tmp/init.sh
|
||||
RUN bash /tmp/init.sh
|
||||
RUN ln -s /usr/src/mxe/usr/bin/x86_64-w64-mingw32.static.posix-gcc /usr/bin/x86_64-w64-mingw32-gcc && \
|
||||
ln -s /usr/src/mxe/usr/bin/x86_64-w64-mingw32.static.posix-g++ /usr/bin/x86_64-w64-mingw32-g++ && \
|
||||
ln -s /usr/src/mxe/usr/bin/x86_64-w64-mingw32.static.posix-ar /usr/bin/x86_64-w64-mingw32-ar
|
1
examples/archive/.gitignore
vendored
Normal file
1
examples/archive/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
archive
|
Binary file not shown.
@@ -68,7 +68,7 @@ func main() {
|
||||
})
|
||||
}))
|
||||
|
||||
reader, err := videoTrack.NewEncodedReader(x264Params.RTPCodec().Name)
|
||||
reader, err := videoTrack.NewEncodedIOReader(x264Params.RTPCodec().MimeType)
|
||||
must(err)
|
||||
defer reader.Close()
|
||||
|
||||
|
1
examples/facedetection/.gitignore
vendored
Normal file
1
examples/facedetection/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
facedetection
|
1
examples/http/.gitignore
vendored
Normal file
1
examples/http/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
http
|
1
examples/rtp/.gitignore
vendored
Normal file
1
examples/rtp/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
rtp
|
@@ -2,6 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"net"
|
||||
"os"
|
||||
|
||||
@@ -51,7 +52,7 @@ func main() {
|
||||
videoTrack := mediaStream.GetVideoTracks()[0]
|
||||
defer videoTrack.Close()
|
||||
|
||||
rtpReader, err := videoTrack.NewRTPReader(x264Params.RTPCodec().Name, mtu)
|
||||
rtpReader, err := videoTrack.NewRTPReader(x264Params.RTPCodec().MimeType, rand.Uint32(), mtu)
|
||||
must(err)
|
||||
|
||||
addr, err := net.ResolveUDPAddr("udp", dest)
|
||||
|
1
examples/webrtc/.gitignore
vendored
Normal file
1
examples/webrtc/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
webrtc
|
@@ -7,7 +7,7 @@ import (
|
||||
"github.com/pion/mediadevices/examples/internal/signal"
|
||||
"github.com/pion/mediadevices/pkg/frame"
|
||||
"github.com/pion/mediadevices/pkg/prop"
|
||||
"github.com/pion/webrtc/v2"
|
||||
"github.com/pion/webrtc/v3"
|
||||
|
||||
// If you don't like x264, you can also use vpx by importing as below
|
||||
// "github.com/pion/mediadevices/pkg/codec/vpx" // This is required to use VP8/VP9 video encoder
|
||||
@@ -57,10 +57,7 @@ func main() {
|
||||
|
||||
mediaEngine := webrtc.MediaEngine{}
|
||||
codecSelector.Populate(&mediaEngine)
|
||||
if err := mediaEngine.PopulateFromSDP(offer); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
api := webrtc.NewAPI(webrtc.WithMediaEngine(mediaEngine))
|
||||
api := webrtc.NewAPI(webrtc.WithMediaEngine(&mediaEngine))
|
||||
peerConnection, err := api.NewPeerConnection(config)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
@@ -86,19 +83,13 @@ func main() {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
for _, tracker := range s.GetTracks() {
|
||||
tracker.OnEnded(func(err error) {
|
||||
for _, track := range s.GetTracks() {
|
||||
track.OnEnded(func(err error) {
|
||||
fmt.Printf("Track (ID: %s) ended with error: %v\n",
|
||||
tracker.ID(), err)
|
||||
track.ID(), err)
|
||||
})
|
||||
|
||||
// In Pion/webrtc v3, bind will be called automatically after SDP negotiation
|
||||
webrtcTrack, err := tracker.Bind(peerConnection)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
_, err = peerConnection.AddTransceiverFromTrack(webrtcTrack,
|
||||
_, err = peerConnection.AddTransceiverFromTrack(track,
|
||||
webrtc.RtpTransceiverInit{
|
||||
Direction: webrtc.RTPTransceiverDirectionSendonly,
|
||||
},
|
||||
|
9
go.mod
9
go.mod
@@ -5,15 +5,16 @@ go 1.13
|
||||
require (
|
||||
github.com/BurntSushi/xgb v0.0.0-20201008132610-5f9e7b3c49cd // indirect
|
||||
github.com/blackjack/webcam v0.0.0-20200313125108-10ed912a8539
|
||||
github.com/gen2brain/malgo v0.10.25
|
||||
github.com/gen2brain/malgo v0.10.27
|
||||
github.com/gen2brain/shm v0.0.0-20200228170931-49f9650110c5 // indirect
|
||||
github.com/google/uuid v1.1.2
|
||||
github.com/kbinani/screenshot v0.0.0-20191211154542-3a185f1ce18f
|
||||
github.com/lherman-cs/opus v0.0.2
|
||||
github.com/lxn/win v0.0.0-20201111105847-2a20daff6a55 // indirect
|
||||
github.com/pion/logging v0.2.2
|
||||
github.com/pion/rtp v1.6.1
|
||||
github.com/pion/webrtc/v2 v2.2.26
|
||||
github.com/pion/rtp v1.6.2
|
||||
github.com/pion/webrtc/v3 v3.0.0
|
||||
github.com/satori/go.uuid v1.2.0
|
||||
golang.org/x/image v0.0.0-20200927104501-e162460cd6b5
|
||||
golang.org/x/sys v0.0.0-20201029080932-201ba4db2418 // indirect
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
||||
)
|
||||
|
136
go.sum
136
go.sum
@@ -2,86 +2,85 @@ github.com/BurntSushi/xgb v0.0.0-20201008132610-5f9e7b3c49cd h1:u7K2oMFMd8APDV3f
|
||||
github.com/BurntSushi/xgb v0.0.0-20201008132610-5f9e7b3c49cd/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/blackjack/webcam v0.0.0-20200313125108-10ed912a8539 h1:1aIqYfg9s9RETAJHGfVKZW4ok0b22p4QTwk8MsdRtPs=
|
||||
github.com/blackjack/webcam v0.0.0-20200313125108-10ed912a8539/go.mod h1:G0X+rEqYPWSq0dG8OMf8M446MtKytzpPjgS3HbdOJZ4=
|
||||
github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE=
|
||||
github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/gen2brain/malgo v0.10.25 h1:VRiYTBmBeHTCXD0wCg7XyLi6lJJBqND/XVmSEyrGkGc=
|
||||
github.com/gen2brain/malgo v0.10.25/go.mod h1:zHSUNZAXfCeNsZou0RtQ6Zk7gDYLIcKOrUWtAdksnEs=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/gen2brain/malgo v0.10.27 h1:KlNitZIO8V4W2VnjtTM8AGMy/XBb2pN+fnIB5bEps8E=
|
||||
github.com/gen2brain/malgo v0.10.27/go.mod h1:zHSUNZAXfCeNsZou0RtQ6Zk7gDYLIcKOrUWtAdksnEs=
|
||||
github.com/gen2brain/shm v0.0.0-20200228170931-49f9650110c5 h1:Y5Q2mEwfzjMt5+3u70Gtw93ZOu2UuPeeeTBDntF7FoY=
|
||||
github.com/gen2brain/shm v0.0.0-20200228170931-49f9650110c5/go.mod h1:uF6rMu/1nvu+5DpiRLwusA6xB8zlkNoGzKn8lmYONUo=
|
||||
github.com/golang/mock v1.2.0 h1:28o5sBqPkBsMGnC6b4MvE2TzSr5/AT4c/1fLqVGIwlk=
|
||||
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
|
||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
|
||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/kbinani/screenshot v0.0.0-20191211154542-3a185f1ce18f h1:5hWo+DzJQSOBl6X+TDac0SPWffRonuRJ2///OYtYRT8=
|
||||
github.com/kbinani/screenshot v0.0.0-20191211154542-3a185f1ce18f/go.mod h1:f8GY5V3lRzakvEyr49P7hHRYoHtPr8zvj/7JodCoRzw=
|
||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/lherman-cs/opus v0.0.2 h1:fE9Du3NKXDBztqvoTd6P2y9eJ9vgIHahGK8yQostnhA=
|
||||
github.com/lherman-cs/opus v0.0.2/go.mod h1:v9KQvlDYMuvlwniumBVMlrB0VHQvyTgxNvaXjPmTmps=
|
||||
github.com/lucas-clemente/quic-go v0.7.1-0.20190401152353-907071221cf9 h1:tbuodUh2vuhOVZAdW3NEUvosFHUMJwUNl7jk/VSEiwc=
|
||||
github.com/lucas-clemente/quic-go v0.7.1-0.20190401152353-907071221cf9/go.mod h1:PpMmPfPKO9nKJ/psF49ESTAGQSdfXxlg1otPbEB2nOw=
|
||||
github.com/lxn/win v0.0.0-20201111105847-2a20daff6a55 h1:4BxFx5XCtXc+nFtXDGDW+Uu5sPtsAbvPh6RObj3fG9o=
|
||||
github.com/lxn/win v0.0.0-20201111105847-2a20daff6a55/go.mod h1:KxxjdtRkfNoYDCUP5ryK7XJJNTnpC8atvtmTheChOtk=
|
||||
github.com/marten-seemann/qtls v0.2.3 h1:0yWJ43C62LsZt08vuQJDK1uC1czUc3FJeCLPoNAI4vA=
|
||||
github.com/marten-seemann/qtls v0.2.3/go.mod h1:xzjG7avBwGGbdZ8dTGxlBnLArsVKLvwmjgmPuiQEcYk=
|
||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs=
|
||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU=
|
||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||
github.com/onsi/ginkgo v1.14.2/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
|
||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||
github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc=
|
||||
github.com/pion/datachannel v1.4.21 h1:3ZvhNyfmxsAqltQrApLPQMhSFNA+aT87RqyCq4OXmf0=
|
||||
github.com/pion/datachannel v1.4.21/go.mod h1:oiNyP4gHx2DIwRzX/MFyH0Rz/Gz05OgBlayAI2hAWjg=
|
||||
github.com/pion/dtls/v2 v2.0.1/go.mod h1:uMQkz2W0cSqY00xav7WByQ4Hb+18xeQh2oH2fRezr5U=
|
||||
github.com/pion/dtls/v2 v2.0.2 h1:FHCHTiM182Y8e15aFTiORroiATUI16ryHiQh8AIOJ1E=
|
||||
github.com/pion/dtls/v2 v2.0.2/go.mod h1:27PEO3MDdaCfo21heT59/vsdmZc0zMt9wQPcSlLu/1I=
|
||||
github.com/pion/ice v0.7.18 h1:KbAWlzWRUdX9SmehBh3gYpIFsirjhSQsCw6K2MjYMK0=
|
||||
github.com/pion/ice v0.7.18/go.mod h1:+Bvnm3nYC6Nnp7VV6glUkuOfToB/AtMRZpOU8ihuf4c=
|
||||
github.com/pion/dtls/v2 v2.0.4 h1:WuUcqi6oYMu/noNTz92QrF1DaFj4eXbhQ6dzaaAwOiI=
|
||||
github.com/pion/dtls/v2 v2.0.4/go.mod h1:qAkFscX0ZHoI1E07RfYPoRw3manThveu+mlTDdOxoGI=
|
||||
github.com/pion/ice/v2 v2.0.14 h1:FxXxauyykf89SWAtkQCfnHkno6G8+bhRkNguSh9zU+4=
|
||||
github.com/pion/ice/v2 v2.0.14/go.mod h1:wqaUbOq5ObDNU5ox1hRsEst0rWfsKuH1zXjQFEWiZwM=
|
||||
github.com/pion/interceptor v0.0.8 h1:qsVJv9RF7mPq/RUnUV5iZCzxwGizO880FuiFKkEGQaE=
|
||||
github.com/pion/interceptor v0.0.8/go.mod h1:dHgEP5dtxOTf21MObuBAjJeAayPxLUAZjerGH8Xr07c=
|
||||
github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY=
|
||||
github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms=
|
||||
github.com/pion/mdns v0.0.4 h1:O4vvVqr4DGX63vzmO6Fw9vpy3lfztVWHGCQfyw0ZLSY=
|
||||
github.com/pion/mdns v0.0.4/go.mod h1:R1sL0p50l42S5lJs91oNdUL58nm0QHrhxnSegr++qC0=
|
||||
github.com/pion/quic v0.1.1 h1:D951FV+TOqI9A0rTF7tHx0Loooqz+nyzjEyj8o3PuMA=
|
||||
github.com/pion/quic v0.1.1/go.mod h1:zEU51v7ru8Mp4AUBJvj6psrSth5eEFNnVQK5K48oV3k=
|
||||
github.com/pion/randutil v0.0.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8=
|
||||
github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA=
|
||||
github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8=
|
||||
github.com/pion/rtcp v1.2.3 h1:2wrhKnqgSz91Q5nzYTO07mQXztYPtxL8a0XOss4rJqA=
|
||||
github.com/pion/rtcp v1.2.3/go.mod h1:zGhIv0RPRF0Z1Wiij22pUt5W/c9fevqSzT4jje/oK7I=
|
||||
github.com/pion/rtp v1.6.0 h1:4Ssnl/T5W2LzxHj9ssYpGVEQh3YYhQFNVmSWO88MMwk=
|
||||
github.com/pion/rtp v1.6.0/go.mod h1:QgfogHsMBVE/RFNno467U/KBqfUywEH+HK+0rtnwsdI=
|
||||
github.com/pion/rtp v1.6.1 h1:2Y2elcVBrahYnHKN2X7rMHX/r1R4TEBMP1LaVu/wNhk=
|
||||
github.com/pion/rtcp v1.2.4/go.mod h1:52rMNPWFsjr39z9B9MhnkqhPLoeHTv1aN63o/42bWE0=
|
||||
github.com/pion/rtcp v1.2.6 h1:1zvwBbyd0TeEuuWftrd/4d++m+/kZSeiguxU61LFWpo=
|
||||
github.com/pion/rtcp v1.2.6/go.mod h1:52rMNPWFsjr39z9B9MhnkqhPLoeHTv1aN63o/42bWE0=
|
||||
github.com/pion/rtp v1.6.1/go.mod h1:bDb5n+BFZxXx0Ea7E5qe+klMuqiBrP+w8XSjiWtCUko=
|
||||
github.com/pion/sctp v1.7.10 h1:o3p3/hZB5Cx12RMGyWmItevJtZ6o2cpuxaw6GOS4x+8=
|
||||
github.com/pion/rtp v1.6.2 h1:iGBerLX6JiDjB9NXuaPzHyxHFG9JsIEdgwTC0lp5n/U=
|
||||
github.com/pion/rtp v1.6.2/go.mod h1:bDb5n+BFZxXx0Ea7E5qe+klMuqiBrP+w8XSjiWtCUko=
|
||||
github.com/pion/sctp v1.7.10/go.mod h1:EhpTUQu1/lcK3xI+eriS6/96fWetHGCvBi9MSsnaBN0=
|
||||
github.com/pion/sdp/v2 v2.4.0 h1:luUtaETR5x2KNNpvEMv/r4Y+/kzImzbz4Lm1z8eQNQI=
|
||||
github.com/pion/sdp/v2 v2.4.0/go.mod h1:L2LxrOpSTJbAns244vfPChbciR/ReU1KWfG04OpkR7E=
|
||||
github.com/pion/srtp v1.5.1 h1:9Q3jAfslYZBt+C69SI/ZcONJh9049JUHZWYRRf5KEKw=
|
||||
github.com/pion/srtp v1.5.1/go.mod h1:B+QgX5xPeQTNc1CJStJPHzOlHK66ViMDWTT0HZTCkcA=
|
||||
github.com/pion/sctp v1.7.11 h1:UCnj7MsobLKLuP/Hh+JMiI/6W5Bs/VF45lWKgHFjSIE=
|
||||
github.com/pion/sctp v1.7.11/go.mod h1:EhpTUQu1/lcK3xI+eriS6/96fWetHGCvBi9MSsnaBN0=
|
||||
github.com/pion/sdp/v3 v3.0.3 h1:gJK9hk+JFD2NGIM1nXmqNCq1DkVaIZ9dlA3u3otnkaw=
|
||||
github.com/pion/sdp/v3 v3.0.3/go.mod h1:bNiSknmJE0HYBprTHXKPQ3+JjacTv5uap92ueJZKsRk=
|
||||
github.com/pion/srtp/v2 v2.0.0-rc.3 h1:1fPiK1nJlNyh235tSGgBnXrPc99wK1/D707f6ntb3qY=
|
||||
github.com/pion/srtp/v2 v2.0.0-rc.3/go.mod h1:S6J9oY6ahAXdU3ni4nUwhWTJuBfssFjPxoB0u41TBpY=
|
||||
github.com/pion/stun v0.3.5 h1:uLUCBCkQby4S1cf6CGuR9QrVOKcvUwFeemaC865QHDg=
|
||||
github.com/pion/stun v0.3.5/go.mod h1:gDMim+47EeEtfWogA37n6qXZS88L5V6LqFcf+DZA2UA=
|
||||
github.com/pion/transport v0.6.0/go.mod h1:iWZ07doqOosSLMhZ+FXUTq+TamDoXSllxpbGcfkCmbE=
|
||||
github.com/pion/transport v0.8.10/go.mod h1:tBmha/UCjpum5hqTWhfAEs3CO4/tHSg0MYRhSzR+CZ8=
|
||||
github.com/pion/transport v0.10.0/go.mod h1:BnHnUipd0rZQyTVB2SBGojFHT9CBt5C5TcsJSQGkvSE=
|
||||
github.com/pion/transport v0.10.1 h1:2W+yJT+0mOQ160ThZYUx5Zp2skzshiNgxrNE9GUfhJM=
|
||||
github.com/pion/transport v0.10.1/go.mod h1:PBis1stIILMiis0PewDw91WJeLJkyIMcEk+DwKOzf4A=
|
||||
github.com/pion/turn/v2 v2.0.4 h1:oDguhEv2L/4rxwbL9clGLgtzQPjtuZwCdoM7Te8vQVk=
|
||||
github.com/pion/turn/v2 v2.0.4/go.mod h1:1812p4DcGVbYVBTiraUmP50XoKye++AMkbfp+N27mog=
|
||||
github.com/pion/transport v0.12.0 h1:UFmOBBZkTZ3LgvLRf/NGrfWdZEubcU6zkLU3PsA9YvU=
|
||||
github.com/pion/transport v0.12.0/go.mod h1:N3+vZQD9HlDP5GWkZ85LohxNsDcNgofQmyL6ojX5d8Q=
|
||||
github.com/pion/turn/v2 v2.0.5 h1:iwMHqDfPEDEOFzwWKT56eFmh6DYC6o/+xnLAEzgISbA=
|
||||
github.com/pion/turn/v2 v2.0.5/go.mod h1:APg43CFyt/14Uy7heYUOGWdkem/Wu4PhCO/bjyrTqMw=
|
||||
github.com/pion/udp v0.1.0 h1:uGxQsNyrqG3GLINv36Ff60covYmfrLoxzwnCsIYspXI=
|
||||
github.com/pion/udp v0.1.0/go.mod h1:BPELIjbwE9PRbd/zxI/KYBnbo7B6+oA6YuEaNE8lths=
|
||||
github.com/pion/webrtc/v2 v2.2.26 h1:01hWE26pL3LgqfxvQ1fr6O4ZtyRFFJmQEZK39pHWfFc=
|
||||
github.com/pion/webrtc/v2 v2.2.26/go.mod h1:XMZbZRNHyPDe1gzTIHFcQu02283YO45CbiwFgKvXnmc=
|
||||
github.com/pion/webrtc/v3 v3.0.0 h1:/eTiY3NbfpKj5op8cqtCZlpTv9/yumd17YRinDNOUX0=
|
||||
github.com/pion/webrtc/v3 v3.0.0/go.mod h1:/xwKHOAk1Y8dspJcxMwuTtxpi8t/Gzks37iB3W6hNuM=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
@@ -90,51 +89,60 @@ github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
|
||||
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
||||
github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
golang.org/x/crypto v0.0.0-20190228161510-8dd112bcdc25/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20200602180216-279210d13fed/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899 h1:DZhuSZLsGlFL4CmhA8BcRA0mnthyA/nZ00AqCUo7vHg=
|
||||
golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 h1:pLI5jrR7OSLijeIDcmRxNmw2api+jEfxLoykJVice/E=
|
||||
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/image v0.0.0-20200927104501-e162460cd6b5 h1:QelT11PB4FXiDEXucrfNckHoFxwt8USGY1ajP1ZF5lM=
|
||||
golang.org/x/image v0.0.0-20200927104501-e162460cd6b5/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20191126235420-ef20fe5d7933/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381 h1:VXak5I6aEWmAXeQjA+QSZzlgNrpq9mjcfDemuexIKsU=
|
||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA=
|
||||
golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201201195509-5d6afe98e0b7 h1:3uJsdck53FDIpWwLeAXlia9p4C8j0BO2xZrqzKpL0D8=
|
||||
golang.org/x/net v0.0.0-20201201195509-5d6afe98e0b7/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200724161237-0e2f3a69832c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201018230417-eeed37f84f13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201029080932-201ba4db2418 h1:HlFl4V6pEMziuLXyRkm5BIYq1y1GAbb02pRlWvI54OM=
|
||||
golang.org/x/sys v0.0.0-20201029080932-201ba4db2418/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
@@ -2,12 +2,18 @@ package codec
|
||||
|
||||
import (
|
||||
"io"
|
||||
"runtime"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestMeasureBitRateStatic(t *testing.T) {
|
||||
// https://github.com/pion/mediadevices/issues/198
|
||||
if runtime.GOOS == "darwin" {
|
||||
t.Skip("Skipping because Darwin CI is not reliable for timing related tests.")
|
||||
}
|
||||
|
||||
r, w := io.Pipe()
|
||||
const (
|
||||
dataSize = 1000
|
||||
@@ -54,6 +60,11 @@ func TestMeasureBitRateStatic(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestMeasureBitRateDynamic(t *testing.T) {
|
||||
// https://github.com/pion/mediadevices/issues/198
|
||||
if runtime.GOOS == "darwin" {
|
||||
t.Skip("Skipping because Darwin CI is not reliable for timing related tests.")
|
||||
}
|
||||
|
||||
r, w := io.Pipe()
|
||||
const (
|
||||
dataSize = 1000
|
||||
|
53
ioreader.go
53
ioreader.go
@@ -1,14 +1,61 @@
|
||||
package mediadevices
|
||||
|
||||
type EncodedBuffer struct {
|
||||
Data []byte
|
||||
Samples uint32
|
||||
}
|
||||
|
||||
type EncodedReadCloser interface {
|
||||
Read() (EncodedBuffer, func(), error)
|
||||
Close() error
|
||||
}
|
||||
|
||||
type encodedReadCloserImpl struct {
|
||||
readFn func([]byte) (int, error)
|
||||
readFn func() (EncodedBuffer, func(), error)
|
||||
closeFn func() error
|
||||
}
|
||||
|
||||
func (r *encodedReadCloserImpl) Read(b []byte) (int, error) {
|
||||
return r.readFn(b)
|
||||
func (r *encodedReadCloserImpl) Read() (EncodedBuffer, func(), error) {
|
||||
return r.readFn()
|
||||
}
|
||||
|
||||
func (r *encodedReadCloserImpl) Close() error {
|
||||
return r.closeFn()
|
||||
}
|
||||
|
||||
type encodedIOReadCloserImpl struct {
|
||||
readFn func([]byte) (int, error)
|
||||
closeFn func() error
|
||||
}
|
||||
|
||||
func newEncodedIOReadCloserImpl(reader EncodedReadCloser) *encodedIOReadCloserImpl {
|
||||
var encoded EncodedBuffer
|
||||
release := func() {}
|
||||
return &encodedIOReadCloserImpl{
|
||||
readFn: func(b []byte) (int, error) {
|
||||
var err error
|
||||
|
||||
if len(encoded.Data) == 0 {
|
||||
release()
|
||||
encoded, release, err = reader.Read()
|
||||
if err != nil {
|
||||
reader.Close()
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
|
||||
n := copy(b, encoded.Data)
|
||||
encoded.Data = encoded.Data[n:]
|
||||
return n, nil
|
||||
},
|
||||
closeFn: reader.Close,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *encodedIOReadCloserImpl) Read(b []byte) (int, error) {
|
||||
return r.readFn(b)
|
||||
}
|
||||
|
||||
func (r *encodedIOReadCloserImpl) Close() error {
|
||||
return r.closeFn()
|
||||
}
|
||||
|
@@ -1,10 +0,0 @@
|
||||
FROM dockercore/golang-cross
|
||||
|
||||
RUN apt-get update -qq \
|
||||
&& apt-get install -y \
|
||||
g++-mingw-w64 \
|
||||
nasm \
|
||||
&& apt-get clean && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
VOLUME /go/src/github.com/pion/mediadevices
|
||||
WORKDIR /go/src/github.com/pion/mediadevices
|
@@ -2,6 +2,8 @@ package mediadevices
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/pion/webrtc/v3"
|
||||
)
|
||||
|
||||
// MediaStream is an interface that represents a collection of existing tracks.
|
||||
@@ -23,7 +25,7 @@ type mediaStream struct {
|
||||
l sync.RWMutex
|
||||
}
|
||||
|
||||
const trackTypeDefault MediaDeviceType = 0
|
||||
const trackTypeDefault webrtc.RTPCodecType = 0
|
||||
|
||||
// NewMediaStream creates a MediaStream interface that's defined in
|
||||
// https://w3c.github.io/mediacapture-main/#dom-mediastream
|
||||
@@ -40,11 +42,11 @@ func NewMediaStream(tracks ...Track) (MediaStream, error) {
|
||||
}
|
||||
|
||||
func (m *mediaStream) GetAudioTracks() []Track {
|
||||
return m.queryTracks(AudioInput)
|
||||
return m.queryTracks(webrtc.RTPCodecTypeAudio)
|
||||
}
|
||||
|
||||
func (m *mediaStream) GetVideoTracks() []Track {
|
||||
return m.queryTracks(VideoInput)
|
||||
return m.queryTracks(webrtc.RTPCodecTypeVideo)
|
||||
}
|
||||
|
||||
func (m *mediaStream) GetTracks() []Track {
|
||||
@@ -53,7 +55,7 @@ func (m *mediaStream) GetTracks() []Track {
|
||||
|
||||
// queryTracks returns all tracks that are the same kind as t.
|
||||
// If t is 0, which is the default, queryTracks will return all the tracks.
|
||||
func (m *mediaStream) queryTracks(t MediaDeviceType) []Track {
|
||||
func (m *mediaStream) queryTracks(t webrtc.RTPCodecType) []Track {
|
||||
m.l.RLock()
|
||||
defer m.l.RUnlock()
|
||||
|
||||
|
@@ -4,7 +4,7 @@ import (
|
||||
"io"
|
||||
"testing"
|
||||
|
||||
"github.com/pion/webrtc/v2"
|
||||
"github.com/pion/webrtc/v3"
|
||||
)
|
||||
|
||||
type mockMediaStreamTrack struct {
|
||||
@@ -15,30 +15,45 @@ func (track *mockMediaStreamTrack) ID() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (track *mockMediaStreamTrack) StreamID() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (track *mockMediaStreamTrack) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (track *mockMediaStreamTrack) Kind() MediaDeviceType {
|
||||
return track.kind
|
||||
func (track *mockMediaStreamTrack) Kind() webrtc.RTPCodecType {
|
||||
switch track.kind {
|
||||
case AudioInput:
|
||||
return webrtc.RTPCodecTypeAudio
|
||||
case VideoInput:
|
||||
return webrtc.RTPCodecTypeVideo
|
||||
default:
|
||||
panic("invalid track kind")
|
||||
}
|
||||
}
|
||||
|
||||
func (track *mockMediaStreamTrack) OnEnded(handler func(error)) {
|
||||
}
|
||||
|
||||
func (track *mockMediaStreamTrack) Bind(pc *webrtc.PeerConnection) (*webrtc.Track, error) {
|
||||
return nil, nil
|
||||
func (track *mockMediaStreamTrack) Bind(ctx webrtc.TrackLocalContext) (webrtc.RTPCodecParameters, error) {
|
||||
return webrtc.RTPCodecParameters{}, nil
|
||||
}
|
||||
|
||||
func (track *mockMediaStreamTrack) Unbind(pc *webrtc.PeerConnection) error {
|
||||
func (track *mockMediaStreamTrack) Unbind(ctx webrtc.TrackLocalContext) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (track *mockMediaStreamTrack) NewRTPReader(codecName string, mtu int) (RTPReadCloser, error) {
|
||||
func (track *mockMediaStreamTrack) NewRTPReader(codecName string, ssrc uint32, mtu int) (RTPReadCloser, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (track *mockMediaStreamTrack) NewEncodedReader(codecName string) (io.ReadCloser, error) {
|
||||
func (track *mockMediaStreamTrack) NewEncodedReader(codecName string) (EncodedReadCloser, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (track *mockMediaStreamTrack) NewEncodedIOReader(codecName string) (io.ReadCloser, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
|
2
meta.go
2
meta.go
@@ -14,7 +14,7 @@ func detectCurrentVideoProp(broadcaster *video.Broadcaster) (prop.Media, error)
|
||||
// buffered frame or a new frame from the source. This also implies that no frame will be lost
|
||||
// in any case.
|
||||
metaReader := broadcaster.NewReader(false)
|
||||
metaReader = video.DetectChanges(0, func(p prop.Media) { currentProp = p })(metaReader)
|
||||
metaReader = video.DetectChanges(0, 0, func(p prop.Media) { currentProp = p })(metaReader)
|
||||
_, _, err := metaReader.Read()
|
||||
|
||||
return currentProp, err
|
||||
|
@@ -4,32 +4,83 @@ import (
|
||||
"github.com/pion/mediadevices/pkg/io/audio"
|
||||
"github.com/pion/mediadevices/pkg/io/video"
|
||||
"github.com/pion/mediadevices/pkg/prop"
|
||||
"github.com/pion/webrtc/v2"
|
||||
"github.com/pion/rtp"
|
||||
"github.com/pion/rtp/codecs"
|
||||
"github.com/pion/webrtc/v3"
|
||||
)
|
||||
|
||||
// RTPCodec wraps webrtc.RTPCodec. RTPCodec might extend webrtc.RTPCodec in the future.
|
||||
type RTPCodec struct {
|
||||
*webrtc.RTPCodec
|
||||
webrtc.RTPCodecParameters
|
||||
rtp.Payloader
|
||||
}
|
||||
|
||||
// NewRTPH264Codec is a helper to create an H264 codec
|
||||
func NewRTPH264Codec(clockrate uint32) *RTPCodec {
|
||||
return &RTPCodec{webrtc.NewRTPH264Codec(webrtc.DefaultPayloadTypeH264, clockrate)}
|
||||
return &RTPCodec{
|
||||
RTPCodecParameters: webrtc.RTPCodecParameters{
|
||||
RTPCodecCapability: webrtc.RTPCodecCapability{
|
||||
MimeType: webrtc.MimeTypeH264,
|
||||
ClockRate: 90000,
|
||||
Channels: 0,
|
||||
SDPFmtpLine: "level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f",
|
||||
RTCPFeedback: nil,
|
||||
},
|
||||
PayloadType: 125,
|
||||
},
|
||||
Payloader: &codecs.H264Payloader{},
|
||||
}
|
||||
}
|
||||
|
||||
// NewRTPVP8Codec is a helper to create an VP8 codec
|
||||
func NewRTPVP8Codec(clockrate uint32) *RTPCodec {
|
||||
return &RTPCodec{webrtc.NewRTPVP8Codec(webrtc.DefaultPayloadTypeVP8, clockrate)}
|
||||
return &RTPCodec{
|
||||
RTPCodecParameters: webrtc.RTPCodecParameters{
|
||||
RTPCodecCapability: webrtc.RTPCodecCapability{
|
||||
MimeType: webrtc.MimeTypeVP8,
|
||||
ClockRate: 90000,
|
||||
Channels: 0,
|
||||
SDPFmtpLine: "",
|
||||
RTCPFeedback: nil,
|
||||
},
|
||||
PayloadType: 96,
|
||||
},
|
||||
Payloader: &codecs.VP8Payloader{},
|
||||
}
|
||||
}
|
||||
|
||||
// NewRTPVP9Codec is a helper to create an VP9 codec
|
||||
func NewRTPVP9Codec(clockrate uint32) *RTPCodec {
|
||||
return &RTPCodec{webrtc.NewRTPVP9Codec(webrtc.DefaultPayloadTypeVP9, clockrate)}
|
||||
return &RTPCodec{
|
||||
RTPCodecParameters: webrtc.RTPCodecParameters{
|
||||
RTPCodecCapability: webrtc.RTPCodecCapability{
|
||||
MimeType: webrtc.MimeTypeVP9,
|
||||
ClockRate: 90000,
|
||||
Channels: 0,
|
||||
SDPFmtpLine: "",
|
||||
RTCPFeedback: nil,
|
||||
},
|
||||
PayloadType: 98,
|
||||
},
|
||||
Payloader: &codecs.VP9Payloader{},
|
||||
}
|
||||
}
|
||||
|
||||
// NewRTPOpusCodec is a helper to create an Opus codec
|
||||
func NewRTPOpusCodec(clockrate uint32) *RTPCodec {
|
||||
return &RTPCodec{webrtc.NewRTPOpusCodec(webrtc.DefaultPayloadTypeOpus, clockrate)}
|
||||
return &RTPCodec{
|
||||
RTPCodecParameters: webrtc.RTPCodecParameters{
|
||||
RTPCodecCapability: webrtc.RTPCodecCapability{
|
||||
MimeType: webrtc.MimeTypeOpus,
|
||||
ClockRate: 48000,
|
||||
Channels: 2,
|
||||
SDPFmtpLine: "minptime=10;useinbandfec=1",
|
||||
RTCPFeedback: nil,
|
||||
},
|
||||
PayloadType: 111,
|
||||
},
|
||||
Payloader: &codecs.OpusPayloader{},
|
||||
}
|
||||
}
|
||||
|
||||
// AudioEncoderBuilder is the interface that wraps basic operations that are
|
||||
|
1
pkg/codec/openh264/.gitignore
vendored
Normal file
1
pkg/codec/openh264/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
src
|
23
pkg/codec/openh264/LICENSE
Normal file
23
pkg/codec/openh264/LICENSE
Normal file
@@ -0,0 +1,23 @@
|
||||
Copyright (c) 2013, Cisco Systems
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
36
pkg/codec/openh264/build.sh
Executable file
36
pkg/codec/openh264/build.sh
Executable file
@@ -0,0 +1,36 @@
|
||||
GIT_URL=https://github.com/cisco/openh264.git
|
||||
VERSION=v2.1.1
|
||||
SRC_DIR=src
|
||||
LIB_DIR=lib
|
||||
INCLUDE_DIR=include/openh264
|
||||
ROOT_DIR=${PWD}
|
||||
LIB_PREFIX=libopenh264
|
||||
|
||||
OS=${MEDIADEVICES_TARGET_OS}
|
||||
ARCH=${MEDIADEVICES_TARGET_ARCH}
|
||||
|
||||
case ${MEDIADEVICES_TARGET_OS} in
|
||||
windows)
|
||||
OS=mingw_nt
|
||||
;;
|
||||
esac
|
||||
|
||||
case ${MEDIADEVICES_TARGET_ARCH} in
|
||||
armv6 | armv7 | armv8)
|
||||
ARCH=arm
|
||||
;;
|
||||
x64)
|
||||
ARCH=x86_64
|
||||
;;
|
||||
esac
|
||||
|
||||
mkdir -p ${LIB_DIR} ${INCLUDE_DIR}
|
||||
|
||||
git clone --depth=1 --branch=${VERSION} ${GIT_URL} ${SRC_DIR}
|
||||
cd ${SRC_DIR}
|
||||
${MEDIADEVICES_TOOLCHAIN_BIN} make -j2 ${LIB_PREFIX}.a OS=${OS} ARCH=${ARCH}
|
||||
${MEDIADEVICES_TOOLCHAIN_BIN} echo $PATH
|
||||
mv ${LIB_PREFIX}.a ${ROOT_DIR}/${LIB_DIR}/${LIB_PREFIX}_${MEDIADEVICES_TARGET_PLATFORM}.a
|
||||
mkdir -p ${ROOT_DIR}/${INCLUDE_DIR}
|
||||
cp codec/api/svc/*.h ${ROOT_DIR}/${INCLUDE_DIR}
|
||||
make clean
|
@@ -167,8 +167,8 @@ typedef enum {
|
||||
DECODER_OPTION_LEVEL, ///< get current AU level info,only is used in GetOption
|
||||
DECODER_OPTION_STATISTICS_LOG_INTERVAL,///< set log output interval
|
||||
DECODER_OPTION_IS_REF_PIC, ///< feedback current frame is ref pic or not
|
||||
DECODER_OPTION_NUM_OF_FRAMES_REMAINING_IN_BUFFER ///< number of frames remaining in decoder buffer when pictures are required to re-ordered into display-order.
|
||||
|
||||
DECODER_OPTION_NUM_OF_FRAMES_REMAINING_IN_BUFFER, ///< number of frames remaining in decoder buffer when pictures are required to re-ordered into display-order.
|
||||
DECODER_OPTION_NUM_OF_THREADS, ///< number of decoding threads. The maximum thread count is equal or less than lesser of (cpu core counts and 16).
|
||||
} DECODER_OPTION;
|
||||
|
||||
/**
|
@@ -201,6 +201,7 @@ typedef struct TagBufferInfo {
|
||||
union {
|
||||
SSysMEMBuffer sSystemBuffer; ///< memory info for one picture
|
||||
} UsrData; ///< output buffer info
|
||||
unsigned char* pDst[3]; //point to picture YUV data
|
||||
} SBufferInfo;
|
||||
|
||||
|
@@ -4,12 +4,12 @@
|
||||
|
||||
#include "codec_app_def.h"
|
||||
|
||||
static const OpenH264Version g_stCodecVersion = {2, 0, 0, 1905};
|
||||
static const char* const g_strCodecVer = "OpenH264 version:2.0.0.1905";
|
||||
static const OpenH264Version g_stCodecVersion = {2, 1, 0, 2002};
|
||||
static const char* const g_strCodecVer = "OpenH264 version:2.1.0.2002";
|
||||
|
||||
#define OPENH264_MAJOR (2)
|
||||
#define OPENH264_MINOR (0)
|
||||
#define OPENH264_MINOR (1)
|
||||
#define OPENH264_REVISION (0)
|
||||
#define OPENH264_RESERVED (1905)
|
||||
#define OPENH264_RESERVED (2002)
|
||||
|
||||
#endif // CODEC_VER_H
|
BIN
pkg/codec/openh264/lib/libopenh264_darwin_x64.a
Normal file
BIN
pkg/codec/openh264/lib/libopenh264_darwin_x64.a
Normal file
Binary file not shown.
BIN
pkg/codec/openh264/lib/libopenh264_linux_arm64.a
Normal file
BIN
pkg/codec/openh264/lib/libopenh264_linux_arm64.a
Normal file
Binary file not shown.
BIN
pkg/codec/openh264/lib/libopenh264_linux_armv7.a
Normal file
BIN
pkg/codec/openh264/lib/libopenh264_linux_armv7.a
Normal file
Binary file not shown.
BIN
pkg/codec/openh264/lib/libopenh264_linux_x64.a
Normal file
BIN
pkg/codec/openh264/lib/libopenh264_linux_x64.a
Normal file
Binary file not shown.
BIN
pkg/codec/openh264/lib/libopenh264_windows_x64.a
Normal file
BIN
pkg/codec/openh264/lib/libopenh264_windows_x64.a
Normal file
Binary file not shown.
@@ -1,7 +1,5 @@
|
||||
package openh264
|
||||
|
||||
// #cgo CFLAGS: -I${SRCDIR}/../../../cvendor/include
|
||||
// #cgo CXXFLAGS: -I${SRCDIR}/../../../cvendor/include
|
||||
// #include <string.h>
|
||||
// #include <openh264/codec_api.h>
|
||||
// #include <errno.h>
|
||||
|
@@ -1,6 +0,0 @@
|
||||
// +build !dynamic
|
||||
|
||||
package openh264
|
||||
|
||||
// #cgo LDFLAGS: ${SRCDIR}/../../../cvendor/lib/openh264/libopenh264.x86_64-darwin.a
|
||||
import "C"
|
@@ -1,6 +0,0 @@
|
||||
// +build !dynamic
|
||||
|
||||
package openh264
|
||||
|
||||
// #cgo LDFLAGS: ${SRCDIR}/../../../cvendor/lib/openh264/libopenh264.x86_64-linux.a
|
||||
import "C"
|
12
pkg/codec/openh264/openh264_static.go
Normal file
12
pkg/codec/openh264/openh264_static.go
Normal file
@@ -0,0 +1,12 @@
|
||||
// +build !dynamic
|
||||
|
||||
package openh264
|
||||
|
||||
//#cgo CFLAGS: -I${SRCDIR}/include
|
||||
//#cgo CXXFLAGS: -I${SRCDIR}/include
|
||||
//#cgo linux,arm LDFLAGS: ${SRCDIR}/lib/libopenh264_linux_armv7.a
|
||||
//#cgo linux,arm64 LDFLAGS: ${SRCDIR}/lib/libopenh264_linux_arm64.a
|
||||
//#cgo linux,amd64 LDFLAGS: ${SRCDIR}/lib/libopenh264_linux_x64.a
|
||||
//#cgo darwin,amd64 LDFLAGS: ${SRCDIR}/lib/libopenh264_darwin_x64.a
|
||||
//#cgo windows,amd64 LDFLAGS: ${SRCDIR}/lib/libopenh264_windows_x64.a -lssp
|
||||
import "C"
|
@@ -1,14 +0,0 @@
|
||||
// +build !dynamic
|
||||
|
||||
package openh264
|
||||
|
||||
// #cgo LDFLAGS: ${SRCDIR}/../../../cvendor/lib/openh264/libopenh264.x86_64-windows.a -lssp
|
||||
// #include <stdio.h>
|
||||
// #include <crtdefs.h>
|
||||
// #if __MINGW64_VERSION_MAJOR < 6
|
||||
// // Workaround for the breaking ABI change between MinGW 5 and 6
|
||||
// FILE *__cdecl __acrt_iob_func(unsigned index) { return &(__iob_func()[index]); }
|
||||
// typedef FILE *__cdecl (*_f__acrt_iob_func)(unsigned index);
|
||||
// _f__acrt_iob_func __MINGW_IMP_SYMBOL(__acrt_iob_func) = __acrt_iob_func;
|
||||
// #endif
|
||||
import "C"
|
1
pkg/codec/opus/.gitignore
vendored
Normal file
1
pkg/codec/opus/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
src
|
44
pkg/codec/opus/LICENSE
Normal file
44
pkg/codec/opus/LICENSE
Normal file
@@ -0,0 +1,44 @@
|
||||
Copyright 2001-2011 Xiph.Org, Skype Limited, Octasic,
|
||||
Jean-Marc Valin, Timothy B. Terriberry,
|
||||
CSIRO, Gregory Maxwell, Mark Borgerding,
|
||||
Erik de Castro Lopo
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
- Neither the name of Internet Society, IETF or IETF Trust, nor the
|
||||
names of specific contributors, may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Opus is subject to the royalty-free patent licenses which are
|
||||
specified at:
|
||||
|
||||
Xiph.Org Foundation:
|
||||
https://datatracker.ietf.org/ipr/1524/
|
||||
|
||||
Microsoft Corporation:
|
||||
https://datatracker.ietf.org/ipr/1914/
|
||||
|
||||
Broadcom Corporation:
|
||||
https://datatracker.ietf.org/ipr/1526/
|
19
pkg/codec/opus/build.sh
Executable file
19
pkg/codec/opus/build.sh
Executable file
@@ -0,0 +1,19 @@
|
||||
GIT_URL=https://github.com/xiph/opus.git
|
||||
VERSION=v1.3.1
|
||||
SRC_DIR=src
|
||||
LIB_DIR=lib
|
||||
INCLUDE_DIR=include
|
||||
ROOT_DIR=${PWD}
|
||||
LIB_PREFIX=libopus
|
||||
|
||||
mkdir -p ${LIB_DIR} ${INCLUDE_DIR}
|
||||
|
||||
git clone --depth=1 --branch=${VERSION} ${GIT_URL} ${SRC_DIR}
|
||||
cd ${SRC_DIR}
|
||||
${MEDIADEVICES_TOOLCHAIN_BIN} cmake -DOPUS_STACK_PROTECTOR=OFF .
|
||||
${MEDIADEVICES_TOOLCHAIN_BIN} make -j2
|
||||
mv ${LIB_PREFIX}.a ${ROOT_DIR}/${LIB_DIR}/${LIB_PREFIX}_${MEDIADEVICES_TARGET_PLATFORM}.a
|
||||
mkdir -p ${ROOT_DIR}/${INCLUDE_DIR}
|
||||
cp include/*.h ${ROOT_DIR}/${INCLUDE_DIR}
|
||||
git clean -dfx
|
||||
git reset --hard
|
981
pkg/codec/opus/include/opus.h
Normal file
981
pkg/codec/opus/include/opus.h
Normal file
@@ -0,0 +1,981 @@
|
||||
/* Copyright (c) 2010-2011 Xiph.Org Foundation, Skype Limited
|
||||
Written by Jean-Marc Valin and Koen Vos */
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file opus.h
|
||||
* @brief Opus reference implementation API
|
||||
*/
|
||||
|
||||
#ifndef OPUS_H
|
||||
#define OPUS_H
|
||||
|
||||
#include "opus_types.h"
|
||||
#include "opus_defines.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @mainpage Opus
|
||||
*
|
||||
* The Opus codec is designed for interactive speech and audio transmission over the Internet.
|
||||
* It is designed by the IETF Codec Working Group and incorporates technology from
|
||||
* Skype's SILK codec and Xiph.Org's CELT codec.
|
||||
*
|
||||
* The Opus codec is designed to handle a wide range of interactive audio applications,
|
||||
* including Voice over IP, videoconferencing, in-game chat, and even remote live music
|
||||
* performances. It can scale from low bit-rate narrowband speech to very high quality
|
||||
* stereo music. Its main features are:
|
||||
|
||||
* @li Sampling rates from 8 to 48 kHz
|
||||
* @li Bit-rates from 6 kb/s to 510 kb/s
|
||||
* @li Support for both constant bit-rate (CBR) and variable bit-rate (VBR)
|
||||
* @li Audio bandwidth from narrowband to full-band
|
||||
* @li Support for speech and music
|
||||
* @li Support for mono and stereo
|
||||
* @li Support for multichannel (up to 255 channels)
|
||||
* @li Frame sizes from 2.5 ms to 60 ms
|
||||
* @li Good loss robustness and packet loss concealment (PLC)
|
||||
* @li Floating point and fixed-point implementation
|
||||
*
|
||||
* Documentation sections:
|
||||
* @li @ref opus_encoder
|
||||
* @li @ref opus_decoder
|
||||
* @li @ref opus_repacketizer
|
||||
* @li @ref opus_multistream
|
||||
* @li @ref opus_libinfo
|
||||
* @li @ref opus_custom
|
||||
*/
|
||||
|
||||
/** @defgroup opus_encoder Opus Encoder
|
||||
* @{
|
||||
*
|
||||
* @brief This page describes the process and functions used to encode Opus.
|
||||
*
|
||||
* Since Opus is a stateful codec, the encoding process starts with creating an encoder
|
||||
* state. This can be done with:
|
||||
*
|
||||
* @code
|
||||
* int error;
|
||||
* OpusEncoder *enc;
|
||||
* enc = opus_encoder_create(Fs, channels, application, &error);
|
||||
* @endcode
|
||||
*
|
||||
* From this point, @c enc can be used for encoding an audio stream. An encoder state
|
||||
* @b must @b not be used for more than one stream at the same time. Similarly, the encoder
|
||||
* state @b must @b not be re-initialized for each frame.
|
||||
*
|
||||
* While opus_encoder_create() allocates memory for the state, it's also possible
|
||||
* to initialize pre-allocated memory:
|
||||
*
|
||||
* @code
|
||||
* int size;
|
||||
* int error;
|
||||
* OpusEncoder *enc;
|
||||
* size = opus_encoder_get_size(channels);
|
||||
* enc = malloc(size);
|
||||
* error = opus_encoder_init(enc, Fs, channels, application);
|
||||
* @endcode
|
||||
*
|
||||
* where opus_encoder_get_size() returns the required size for the encoder state. Note that
|
||||
* future versions of this code may change the size, so no assuptions should be made about it.
|
||||
*
|
||||
* The encoder state is always continuous in memory and only a shallow copy is sufficient
|
||||
* to copy it (e.g. memcpy())
|
||||
*
|
||||
* It is possible to change some of the encoder's settings using the opus_encoder_ctl()
|
||||
* interface. All these settings already default to the recommended value, so they should
|
||||
* only be changed when necessary. The most common settings one may want to change are:
|
||||
*
|
||||
* @code
|
||||
* opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrate));
|
||||
* opus_encoder_ctl(enc, OPUS_SET_COMPLEXITY(complexity));
|
||||
* opus_encoder_ctl(enc, OPUS_SET_SIGNAL(signal_type));
|
||||
* @endcode
|
||||
*
|
||||
* where
|
||||
*
|
||||
* @arg bitrate is in bits per second (b/s)
|
||||
* @arg complexity is a value from 1 to 10, where 1 is the lowest complexity and 10 is the highest
|
||||
* @arg signal_type is either OPUS_AUTO (default), OPUS_SIGNAL_VOICE, or OPUS_SIGNAL_MUSIC
|
||||
*
|
||||
* See @ref opus_encoderctls and @ref opus_genericctls for a complete list of parameters that can be set or queried. Most parameters can be set or changed at any time during a stream.
|
||||
*
|
||||
* To encode a frame, opus_encode() or opus_encode_float() must be called with exactly one frame (2.5, 5, 10, 20, 40 or 60 ms) of audio data:
|
||||
* @code
|
||||
* len = opus_encode(enc, audio_frame, frame_size, packet, max_packet);
|
||||
* @endcode
|
||||
*
|
||||
* where
|
||||
* <ul>
|
||||
* <li>audio_frame is the audio data in opus_int16 (or float for opus_encode_float())</li>
|
||||
* <li>frame_size is the duration of the frame in samples (per channel)</li>
|
||||
* <li>packet is the byte array to which the compressed data is written</li>
|
||||
* <li>max_packet is the maximum number of bytes that can be written in the packet (4000 bytes is recommended).
|
||||
* Do not use max_packet to control VBR target bitrate, instead use the #OPUS_SET_BITRATE CTL.</li>
|
||||
* </ul>
|
||||
*
|
||||
* opus_encode() and opus_encode_float() return the number of bytes actually written to the packet.
|
||||
* The return value <b>can be negative</b>, which indicates that an error has occurred. If the return value
|
||||
* is 2 bytes or less, then the packet does not need to be transmitted (DTX).
|
||||
*
|
||||
* Once the encoder state if no longer needed, it can be destroyed with
|
||||
*
|
||||
* @code
|
||||
* opus_encoder_destroy(enc);
|
||||
* @endcode
|
||||
*
|
||||
* If the encoder was created with opus_encoder_init() rather than opus_encoder_create(),
|
||||
* then no action is required aside from potentially freeing the memory that was manually
|
||||
* allocated for it (calling free(enc) for the example above)
|
||||
*
|
||||
*/
|
||||
|
||||
/** Opus encoder state.
|
||||
* This contains the complete state of an Opus encoder.
|
||||
* It is position independent and can be freely copied.
|
||||
* @see opus_encoder_create,opus_encoder_init
|
||||
*/
|
||||
typedef struct OpusEncoder OpusEncoder;
|
||||
|
||||
/** Gets the size of an <code>OpusEncoder</code> structure.
|
||||
* @param[in] channels <tt>int</tt>: Number of channels.
|
||||
* This must be 1 or 2.
|
||||
* @returns The size in bytes.
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_encoder_get_size(int channels);
|
||||
|
||||
/**
|
||||
*/
|
||||
|
||||
/** Allocates and initializes an encoder state.
|
||||
* There are three coding modes:
|
||||
*
|
||||
* @ref OPUS_APPLICATION_VOIP gives best quality at a given bitrate for voice
|
||||
* signals. It enhances the input signal by high-pass filtering and
|
||||
* emphasizing formants and harmonics. Optionally it includes in-band
|
||||
* forward error correction to protect against packet loss. Use this
|
||||
* mode for typical VoIP applications. Because of the enhancement,
|
||||
* even at high bitrates the output may sound different from the input.
|
||||
*
|
||||
* @ref OPUS_APPLICATION_AUDIO gives best quality at a given bitrate for most
|
||||
* non-voice signals like music. Use this mode for music and mixed
|
||||
* (music/voice) content, broadcast, and applications requiring less
|
||||
* than 15 ms of coding delay.
|
||||
*
|
||||
* @ref OPUS_APPLICATION_RESTRICTED_LOWDELAY configures low-delay mode that
|
||||
* disables the speech-optimized mode in exchange for slightly reduced delay.
|
||||
* This mode can only be set on an newly initialized or freshly reset encoder
|
||||
* because it changes the codec delay.
|
||||
*
|
||||
* This is useful when the caller knows that the speech-optimized modes will not be needed (use with caution).
|
||||
* @param [in] Fs <tt>opus_int32</tt>: Sampling rate of input signal (Hz)
|
||||
* This must be one of 8000, 12000, 16000,
|
||||
* 24000, or 48000.
|
||||
* @param [in] channels <tt>int</tt>: Number of channels (1 or 2) in input signal
|
||||
* @param [in] application <tt>int</tt>: Coding mode (@ref OPUS_APPLICATION_VOIP/@ref OPUS_APPLICATION_AUDIO/@ref OPUS_APPLICATION_RESTRICTED_LOWDELAY)
|
||||
* @param [out] error <tt>int*</tt>: @ref opus_errorcodes
|
||||
* @note Regardless of the sampling rate and number channels selected, the Opus encoder
|
||||
* can switch to a lower audio bandwidth or number of channels if the bitrate
|
||||
* selected is too low. This also means that it is safe to always use 48 kHz stereo input
|
||||
* and let the encoder optimize the encoding.
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusEncoder *opus_encoder_create(
|
||||
opus_int32 Fs,
|
||||
int channels,
|
||||
int application,
|
||||
int *error
|
||||
);
|
||||
|
||||
/** Initializes a previously allocated encoder state
|
||||
* The memory pointed to by st must be at least the size returned by opus_encoder_get_size().
|
||||
* This is intended for applications which use their own allocator instead of malloc.
|
||||
* @see opus_encoder_create(),opus_encoder_get_size()
|
||||
* To reset a previously initialized state, use the #OPUS_RESET_STATE CTL.
|
||||
* @param [in] st <tt>OpusEncoder*</tt>: Encoder state
|
||||
* @param [in] Fs <tt>opus_int32</tt>: Sampling rate of input signal (Hz)
|
||||
* This must be one of 8000, 12000, 16000,
|
||||
* 24000, or 48000.
|
||||
* @param [in] channels <tt>int</tt>: Number of channels (1 or 2) in input signal
|
||||
* @param [in] application <tt>int</tt>: Coding mode (OPUS_APPLICATION_VOIP/OPUS_APPLICATION_AUDIO/OPUS_APPLICATION_RESTRICTED_LOWDELAY)
|
||||
* @retval #OPUS_OK Success or @ref opus_errorcodes
|
||||
*/
|
||||
OPUS_EXPORT int opus_encoder_init(
|
||||
OpusEncoder *st,
|
||||
opus_int32 Fs,
|
||||
int channels,
|
||||
int application
|
||||
) OPUS_ARG_NONNULL(1);
|
||||
|
||||
/** Encodes an Opus frame.
|
||||
* @param [in] st <tt>OpusEncoder*</tt>: Encoder state
|
||||
* @param [in] pcm <tt>opus_int16*</tt>: Input signal (interleaved if 2 channels). length is frame_size*channels*sizeof(opus_int16)
|
||||
* @param [in] frame_size <tt>int</tt>: Number of samples per channel in the
|
||||
* input signal.
|
||||
* This must be an Opus frame size for
|
||||
* the encoder's sampling rate.
|
||||
* For example, at 48 kHz the permitted
|
||||
* values are 120, 240, 480, 960, 1920,
|
||||
* and 2880.
|
||||
* Passing in a duration of less than
|
||||
* 10 ms (480 samples at 48 kHz) will
|
||||
* prevent the encoder from using the LPC
|
||||
* or hybrid modes.
|
||||
* @param [out] data <tt>unsigned char*</tt>: Output payload.
|
||||
* This must contain storage for at
|
||||
* least \a max_data_bytes.
|
||||
* @param [in] max_data_bytes <tt>opus_int32</tt>: Size of the allocated
|
||||
* memory for the output
|
||||
* payload. This may be
|
||||
* used to impose an upper limit on
|
||||
* the instant bitrate, but should
|
||||
* not be used as the only bitrate
|
||||
* control. Use #OPUS_SET_BITRATE to
|
||||
* control the bitrate.
|
||||
* @returns The length of the encoded packet (in bytes) on success or a
|
||||
* negative error code (see @ref opus_errorcodes) on failure.
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_encode(
|
||||
OpusEncoder *st,
|
||||
const opus_int16 *pcm,
|
||||
int frame_size,
|
||||
unsigned char *data,
|
||||
opus_int32 max_data_bytes
|
||||
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
|
||||
|
||||
/** Encodes an Opus frame from floating point input.
|
||||
* @param [in] st <tt>OpusEncoder*</tt>: Encoder state
|
||||
* @param [in] pcm <tt>float*</tt>: Input in float format (interleaved if 2 channels), with a normal range of +/-1.0.
|
||||
* Samples with a range beyond +/-1.0 are supported but will
|
||||
* be clipped by decoders using the integer API and should
|
||||
* only be used if it is known that the far end supports
|
||||
* extended dynamic range.
|
||||
* length is frame_size*channels*sizeof(float)
|
||||
* @param [in] frame_size <tt>int</tt>: Number of samples per channel in the
|
||||
* input signal.
|
||||
* This must be an Opus frame size for
|
||||
* the encoder's sampling rate.
|
||||
* For example, at 48 kHz the permitted
|
||||
* values are 120, 240, 480, 960, 1920,
|
||||
* and 2880.
|
||||
* Passing in a duration of less than
|
||||
* 10 ms (480 samples at 48 kHz) will
|
||||
* prevent the encoder from using the LPC
|
||||
* or hybrid modes.
|
||||
* @param [out] data <tt>unsigned char*</tt>: Output payload.
|
||||
* This must contain storage for at
|
||||
* least \a max_data_bytes.
|
||||
* @param [in] max_data_bytes <tt>opus_int32</tt>: Size of the allocated
|
||||
* memory for the output
|
||||
* payload. This may be
|
||||
* used to impose an upper limit on
|
||||
* the instant bitrate, but should
|
||||
* not be used as the only bitrate
|
||||
* control. Use #OPUS_SET_BITRATE to
|
||||
* control the bitrate.
|
||||
* @returns The length of the encoded packet (in bytes) on success or a
|
||||
* negative error code (see @ref opus_errorcodes) on failure.
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_encode_float(
|
||||
OpusEncoder *st,
|
||||
const float *pcm,
|
||||
int frame_size,
|
||||
unsigned char *data,
|
||||
opus_int32 max_data_bytes
|
||||
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
|
||||
|
||||
/** Frees an <code>OpusEncoder</code> allocated by opus_encoder_create().
|
||||
* @param[in] st <tt>OpusEncoder*</tt>: State to be freed.
|
||||
*/
|
||||
OPUS_EXPORT void opus_encoder_destroy(OpusEncoder *st);
|
||||
|
||||
/** Perform a CTL function on an Opus encoder.
|
||||
*
|
||||
* Generally the request and subsequent arguments are generated
|
||||
* by a convenience macro.
|
||||
* @param st <tt>OpusEncoder*</tt>: Encoder state.
|
||||
* @param request This and all remaining parameters should be replaced by one
|
||||
* of the convenience macros in @ref opus_genericctls or
|
||||
* @ref opus_encoderctls.
|
||||
* @see opus_genericctls
|
||||
* @see opus_encoderctls
|
||||
*/
|
||||
OPUS_EXPORT int opus_encoder_ctl(OpusEncoder *st, int request, ...) OPUS_ARG_NONNULL(1);
|
||||
/**@}*/
|
||||
|
||||
/** @defgroup opus_decoder Opus Decoder
|
||||
* @{
|
||||
*
|
||||
* @brief This page describes the process and functions used to decode Opus.
|
||||
*
|
||||
* The decoding process also starts with creating a decoder
|
||||
* state. This can be done with:
|
||||
* @code
|
||||
* int error;
|
||||
* OpusDecoder *dec;
|
||||
* dec = opus_decoder_create(Fs, channels, &error);
|
||||
* @endcode
|
||||
* where
|
||||
* @li Fs is the sampling rate and must be 8000, 12000, 16000, 24000, or 48000
|
||||
* @li channels is the number of channels (1 or 2)
|
||||
* @li error will hold the error code in case of failure (or #OPUS_OK on success)
|
||||
* @li the return value is a newly created decoder state to be used for decoding
|
||||
*
|
||||
* While opus_decoder_create() allocates memory for the state, it's also possible
|
||||
* to initialize pre-allocated memory:
|
||||
* @code
|
||||
* int size;
|
||||
* int error;
|
||||
* OpusDecoder *dec;
|
||||
* size = opus_decoder_get_size(channels);
|
||||
* dec = malloc(size);
|
||||
* error = opus_decoder_init(dec, Fs, channels);
|
||||
* @endcode
|
||||
* where opus_decoder_get_size() returns the required size for the decoder state. Note that
|
||||
* future versions of this code may change the size, so no assuptions should be made about it.
|
||||
*
|
||||
* The decoder state is always continuous in memory and only a shallow copy is sufficient
|
||||
* to copy it (e.g. memcpy())
|
||||
*
|
||||
* To decode a frame, opus_decode() or opus_decode_float() must be called with a packet of compressed audio data:
|
||||
* @code
|
||||
* frame_size = opus_decode(dec, packet, len, decoded, max_size, 0);
|
||||
* @endcode
|
||||
* where
|
||||
*
|
||||
* @li packet is the byte array containing the compressed data
|
||||
* @li len is the exact number of bytes contained in the packet
|
||||
* @li decoded is the decoded audio data in opus_int16 (or float for opus_decode_float())
|
||||
* @li max_size is the max duration of the frame in samples (per channel) that can fit into the decoded_frame array
|
||||
*
|
||||
* opus_decode() and opus_decode_float() return the number of samples (per channel) decoded from the packet.
|
||||
* If that value is negative, then an error has occurred. This can occur if the packet is corrupted or if the audio
|
||||
* buffer is too small to hold the decoded audio.
|
||||
*
|
||||
* Opus is a stateful codec with overlapping blocks and as a result Opus
|
||||
* packets are not coded independently of each other. Packets must be
|
||||
* passed into the decoder serially and in the correct order for a correct
|
||||
* decode. Lost packets can be replaced with loss concealment by calling
|
||||
* the decoder with a null pointer and zero length for the missing packet.
|
||||
*
|
||||
* A single codec state may only be accessed from a single thread at
|
||||
* a time and any required locking must be performed by the caller. Separate
|
||||
* streams must be decoded with separate decoder states and can be decoded
|
||||
* in parallel unless the library was compiled with NONTHREADSAFE_PSEUDOSTACK
|
||||
* defined.
|
||||
*
|
||||
*/
|
||||
|
||||
/** Opus decoder state.
|
||||
* This contains the complete state of an Opus decoder.
|
||||
* It is position independent and can be freely copied.
|
||||
* @see opus_decoder_create,opus_decoder_init
|
||||
*/
|
||||
typedef struct OpusDecoder OpusDecoder;
|
||||
|
||||
/** Gets the size of an <code>OpusDecoder</code> structure.
|
||||
* @param [in] channels <tt>int</tt>: Number of channels.
|
||||
* This must be 1 or 2.
|
||||
* @returns The size in bytes.
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_decoder_get_size(int channels);
|
||||
|
||||
/** Allocates and initializes a decoder state.
|
||||
* @param [in] Fs <tt>opus_int32</tt>: Sample rate to decode at (Hz).
|
||||
* This must be one of 8000, 12000, 16000,
|
||||
* 24000, or 48000.
|
||||
* @param [in] channels <tt>int</tt>: Number of channels (1 or 2) to decode
|
||||
* @param [out] error <tt>int*</tt>: #OPUS_OK Success or @ref opus_errorcodes
|
||||
*
|
||||
* Internally Opus stores data at 48000 Hz, so that should be the default
|
||||
* value for Fs. However, the decoder can efficiently decode to buffers
|
||||
* at 8, 12, 16, and 24 kHz so if for some reason the caller cannot use
|
||||
* data at the full sample rate, or knows the compressed data doesn't
|
||||
* use the full frequency range, it can request decoding at a reduced
|
||||
* rate. Likewise, the decoder is capable of filling in either mono or
|
||||
* interleaved stereo pcm buffers, at the caller's request.
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusDecoder *opus_decoder_create(
|
||||
opus_int32 Fs,
|
||||
int channels,
|
||||
int *error
|
||||
);
|
||||
|
||||
/** Initializes a previously allocated decoder state.
|
||||
* The state must be at least the size returned by opus_decoder_get_size().
|
||||
* This is intended for applications which use their own allocator instead of malloc. @see opus_decoder_create,opus_decoder_get_size
|
||||
* To reset a previously initialized state, use the #OPUS_RESET_STATE CTL.
|
||||
* @param [in] st <tt>OpusDecoder*</tt>: Decoder state.
|
||||
* @param [in] Fs <tt>opus_int32</tt>: Sampling rate to decode to (Hz).
|
||||
* This must be one of 8000, 12000, 16000,
|
||||
* 24000, or 48000.
|
||||
* @param [in] channels <tt>int</tt>: Number of channels (1 or 2) to decode
|
||||
* @retval #OPUS_OK Success or @ref opus_errorcodes
|
||||
*/
|
||||
OPUS_EXPORT int opus_decoder_init(
|
||||
OpusDecoder *st,
|
||||
opus_int32 Fs,
|
||||
int channels
|
||||
) OPUS_ARG_NONNULL(1);
|
||||
|
||||
/** Decode an Opus packet.
|
||||
* @param [in] st <tt>OpusDecoder*</tt>: Decoder state
|
||||
* @param [in] data <tt>char*</tt>: Input payload. Use a NULL pointer to indicate packet loss
|
||||
* @param [in] len <tt>opus_int32</tt>: Number of bytes in payload*
|
||||
* @param [out] pcm <tt>opus_int16*</tt>: Output signal (interleaved if 2 channels). length
|
||||
* is frame_size*channels*sizeof(opus_int16)
|
||||
* @param [in] frame_size Number of samples per channel of available space in \a pcm.
|
||||
* If this is less than the maximum packet duration (120ms; 5760 for 48kHz), this function will
|
||||
* not be capable of decoding some packets. In the case of PLC (data==NULL) or FEC (decode_fec=1),
|
||||
* then frame_size needs to be exactly the duration of audio that is missing, otherwise the
|
||||
* decoder will not be in the optimal state to decode the next incoming packet. For the PLC and
|
||||
* FEC cases, frame_size <b>must</b> be a multiple of 2.5 ms.
|
||||
* @param [in] decode_fec <tt>int</tt>: Flag (0 or 1) to request that any in-band forward error correction data be
|
||||
* decoded. If no such data is available, the frame is decoded as if it were lost.
|
||||
* @returns Number of decoded samples or @ref opus_errorcodes
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_decode(
|
||||
OpusDecoder *st,
|
||||
const unsigned char *data,
|
||||
opus_int32 len,
|
||||
opus_int16 *pcm,
|
||||
int frame_size,
|
||||
int decode_fec
|
||||
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
|
||||
|
||||
/** Decode an Opus packet with floating point output.
|
||||
* @param [in] st <tt>OpusDecoder*</tt>: Decoder state
|
||||
* @param [in] data <tt>char*</tt>: Input payload. Use a NULL pointer to indicate packet loss
|
||||
* @param [in] len <tt>opus_int32</tt>: Number of bytes in payload
|
||||
* @param [out] pcm <tt>float*</tt>: Output signal (interleaved if 2 channels). length
|
||||
* is frame_size*channels*sizeof(float)
|
||||
* @param [in] frame_size Number of samples per channel of available space in \a pcm.
|
||||
* If this is less than the maximum packet duration (120ms; 5760 for 48kHz), this function will
|
||||
* not be capable of decoding some packets. In the case of PLC (data==NULL) or FEC (decode_fec=1),
|
||||
* then frame_size needs to be exactly the duration of audio that is missing, otherwise the
|
||||
* decoder will not be in the optimal state to decode the next incoming packet. For the PLC and
|
||||
* FEC cases, frame_size <b>must</b> be a multiple of 2.5 ms.
|
||||
* @param [in] decode_fec <tt>int</tt>: Flag (0 or 1) to request that any in-band forward error correction data be
|
||||
* decoded. If no such data is available the frame is decoded as if it were lost.
|
||||
* @returns Number of decoded samples or @ref opus_errorcodes
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_decode_float(
|
||||
OpusDecoder *st,
|
||||
const unsigned char *data,
|
||||
opus_int32 len,
|
||||
float *pcm,
|
||||
int frame_size,
|
||||
int decode_fec
|
||||
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
|
||||
|
||||
/** Perform a CTL function on an Opus decoder.
|
||||
*
|
||||
* Generally the request and subsequent arguments are generated
|
||||
* by a convenience macro.
|
||||
* @param st <tt>OpusDecoder*</tt>: Decoder state.
|
||||
* @param request This and all remaining parameters should be replaced by one
|
||||
* of the convenience macros in @ref opus_genericctls or
|
||||
* @ref opus_decoderctls.
|
||||
* @see opus_genericctls
|
||||
* @see opus_decoderctls
|
||||
*/
|
||||
OPUS_EXPORT int opus_decoder_ctl(OpusDecoder *st, int request, ...) OPUS_ARG_NONNULL(1);
|
||||
|
||||
/** Frees an <code>OpusDecoder</code> allocated by opus_decoder_create().
|
||||
* @param[in] st <tt>OpusDecoder*</tt>: State to be freed.
|
||||
*/
|
||||
OPUS_EXPORT void opus_decoder_destroy(OpusDecoder *st);
|
||||
|
||||
/** Parse an opus packet into one or more frames.
|
||||
* Opus_decode will perform this operation internally so most applications do
|
||||
* not need to use this function.
|
||||
* This function does not copy the frames, the returned pointers are pointers into
|
||||
* the input packet.
|
||||
* @param [in] data <tt>char*</tt>: Opus packet to be parsed
|
||||
* @param [in] len <tt>opus_int32</tt>: size of data
|
||||
* @param [out] out_toc <tt>char*</tt>: TOC pointer
|
||||
* @param [out] frames <tt>char*[48]</tt> encapsulated frames
|
||||
* @param [out] size <tt>opus_int16[48]</tt> sizes of the encapsulated frames
|
||||
* @param [out] payload_offset <tt>int*</tt>: returns the position of the payload within the packet (in bytes)
|
||||
* @returns number of frames
|
||||
*/
|
||||
OPUS_EXPORT int opus_packet_parse(
|
||||
const unsigned char *data,
|
||||
opus_int32 len,
|
||||
unsigned char *out_toc,
|
||||
const unsigned char *frames[48],
|
||||
opus_int16 size[48],
|
||||
int *payload_offset
|
||||
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(5);
|
||||
|
||||
/** Gets the bandwidth of an Opus packet.
|
||||
* @param [in] data <tt>char*</tt>: Opus packet
|
||||
* @retval OPUS_BANDWIDTH_NARROWBAND Narrowband (4kHz bandpass)
|
||||
* @retval OPUS_BANDWIDTH_MEDIUMBAND Mediumband (6kHz bandpass)
|
||||
* @retval OPUS_BANDWIDTH_WIDEBAND Wideband (8kHz bandpass)
|
||||
* @retval OPUS_BANDWIDTH_SUPERWIDEBAND Superwideband (12kHz bandpass)
|
||||
* @retval OPUS_BANDWIDTH_FULLBAND Fullband (20kHz bandpass)
|
||||
* @retval OPUS_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_get_bandwidth(const unsigned char *data) OPUS_ARG_NONNULL(1);
|
||||
|
||||
/** Gets the number of samples per frame from an Opus packet.
|
||||
* @param [in] data <tt>char*</tt>: Opus packet.
|
||||
* This must contain at least one byte of
|
||||
* data.
|
||||
* @param [in] Fs <tt>opus_int32</tt>: Sampling rate in Hz.
|
||||
* This must be a multiple of 400, or
|
||||
* inaccurate results will be returned.
|
||||
* @returns Number of samples per frame.
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_get_samples_per_frame(const unsigned char *data, opus_int32 Fs) OPUS_ARG_NONNULL(1);
|
||||
|
||||
/** Gets the number of channels from an Opus packet.
|
||||
* @param [in] data <tt>char*</tt>: Opus packet
|
||||
* @returns Number of channels
|
||||
* @retval OPUS_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_get_nb_channels(const unsigned char *data) OPUS_ARG_NONNULL(1);
|
||||
|
||||
/** Gets the number of frames in an Opus packet.
|
||||
* @param [in] packet <tt>char*</tt>: Opus packet
|
||||
* @param [in] len <tt>opus_int32</tt>: Length of packet
|
||||
* @returns Number of frames
|
||||
* @retval OPUS_BAD_ARG Insufficient data was passed to the function
|
||||
* @retval OPUS_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_get_nb_frames(const unsigned char packet[], opus_int32 len) OPUS_ARG_NONNULL(1);
|
||||
|
||||
/** Gets the number of samples of an Opus packet.
|
||||
* @param [in] packet <tt>char*</tt>: Opus packet
|
||||
* @param [in] len <tt>opus_int32</tt>: Length of packet
|
||||
* @param [in] Fs <tt>opus_int32</tt>: Sampling rate in Hz.
|
||||
* This must be a multiple of 400, or
|
||||
* inaccurate results will be returned.
|
||||
* @returns Number of samples
|
||||
* @retval OPUS_BAD_ARG Insufficient data was passed to the function
|
||||
* @retval OPUS_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_get_nb_samples(const unsigned char packet[], opus_int32 len, opus_int32 Fs) OPUS_ARG_NONNULL(1);
|
||||
|
||||
/** Gets the number of samples of an Opus packet.
|
||||
* @param [in] dec <tt>OpusDecoder*</tt>: Decoder state
|
||||
* @param [in] packet <tt>char*</tt>: Opus packet
|
||||
* @param [in] len <tt>opus_int32</tt>: Length of packet
|
||||
* @returns Number of samples
|
||||
* @retval OPUS_BAD_ARG Insufficient data was passed to the function
|
||||
* @retval OPUS_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_decoder_get_nb_samples(const OpusDecoder *dec, const unsigned char packet[], opus_int32 len) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2);
|
||||
|
||||
/** Applies soft-clipping to bring a float signal within the [-1,1] range. If
|
||||
* the signal is already in that range, nothing is done. If there are values
|
||||
* outside of [-1,1], then the signal is clipped as smoothly as possible to
|
||||
* both fit in the range and avoid creating excessive distortion in the
|
||||
* process.
|
||||
* @param [in,out] pcm <tt>float*</tt>: Input PCM and modified PCM
|
||||
* @param [in] frame_size <tt>int</tt> Number of samples per channel to process
|
||||
* @param [in] channels <tt>int</tt>: Number of channels
|
||||
* @param [in,out] softclip_mem <tt>float*</tt>: State memory for the soft clipping process (one float per channel, initialized to zero)
|
||||
*/
|
||||
OPUS_EXPORT void opus_pcm_soft_clip(float *pcm, int frame_size, int channels, float *softclip_mem);
|
||||
|
||||
|
||||
/**@}*/
|
||||
|
||||
/** @defgroup opus_repacketizer Repacketizer
|
||||
* @{
|
||||
*
|
||||
* The repacketizer can be used to merge multiple Opus packets into a single
|
||||
* packet or alternatively to split Opus packets that have previously been
|
||||
* merged. Splitting valid Opus packets is always guaranteed to succeed,
|
||||
* whereas merging valid packets only succeeds if all frames have the same
|
||||
* mode, bandwidth, and frame size, and when the total duration of the merged
|
||||
* packet is no more than 120 ms. The 120 ms limit comes from the
|
||||
* specification and limits decoder memory requirements at a point where
|
||||
* framing overhead becomes negligible.
|
||||
*
|
||||
* The repacketizer currently only operates on elementary Opus
|
||||
* streams. It will not manipualte multistream packets successfully, except in
|
||||
* the degenerate case where they consist of data from a single stream.
|
||||
*
|
||||
* The repacketizing process starts with creating a repacketizer state, either
|
||||
* by calling opus_repacketizer_create() or by allocating the memory yourself,
|
||||
* e.g.,
|
||||
* @code
|
||||
* OpusRepacketizer *rp;
|
||||
* rp = (OpusRepacketizer*)malloc(opus_repacketizer_get_size());
|
||||
* if (rp != NULL)
|
||||
* opus_repacketizer_init(rp);
|
||||
* @endcode
|
||||
*
|
||||
* Then the application should submit packets with opus_repacketizer_cat(),
|
||||
* extract new packets with opus_repacketizer_out() or
|
||||
* opus_repacketizer_out_range(), and then reset the state for the next set of
|
||||
* input packets via opus_repacketizer_init().
|
||||
*
|
||||
* For example, to split a sequence of packets into individual frames:
|
||||
* @code
|
||||
* unsigned char *data;
|
||||
* int len;
|
||||
* while (get_next_packet(&data, &len))
|
||||
* {
|
||||
* unsigned char out[1276];
|
||||
* opus_int32 out_len;
|
||||
* int nb_frames;
|
||||
* int err;
|
||||
* int i;
|
||||
* err = opus_repacketizer_cat(rp, data, len);
|
||||
* if (err != OPUS_OK)
|
||||
* {
|
||||
* release_packet(data);
|
||||
* return err;
|
||||
* }
|
||||
* nb_frames = opus_repacketizer_get_nb_frames(rp);
|
||||
* for (i = 0; i < nb_frames; i++)
|
||||
* {
|
||||
* out_len = opus_repacketizer_out_range(rp, i, i+1, out, sizeof(out));
|
||||
* if (out_len < 0)
|
||||
* {
|
||||
* release_packet(data);
|
||||
* return (int)out_len;
|
||||
* }
|
||||
* output_next_packet(out, out_len);
|
||||
* }
|
||||
* opus_repacketizer_init(rp);
|
||||
* release_packet(data);
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
* Alternatively, to combine a sequence of frames into packets that each
|
||||
* contain up to <code>TARGET_DURATION_MS</code> milliseconds of data:
|
||||
* @code
|
||||
* // The maximum number of packets with duration TARGET_DURATION_MS occurs
|
||||
* // when the frame size is 2.5 ms, for a total of (TARGET_DURATION_MS*2/5)
|
||||
* // packets.
|
||||
* unsigned char *data[(TARGET_DURATION_MS*2/5)+1];
|
||||
* opus_int32 len[(TARGET_DURATION_MS*2/5)+1];
|
||||
* int nb_packets;
|
||||
* unsigned char out[1277*(TARGET_DURATION_MS*2/2)];
|
||||
* opus_int32 out_len;
|
||||
* int prev_toc;
|
||||
* nb_packets = 0;
|
||||
* while (get_next_packet(data+nb_packets, len+nb_packets))
|
||||
* {
|
||||
* int nb_frames;
|
||||
* int err;
|
||||
* nb_frames = opus_packet_get_nb_frames(data[nb_packets], len[nb_packets]);
|
||||
* if (nb_frames < 1)
|
||||
* {
|
||||
* release_packets(data, nb_packets+1);
|
||||
* return nb_frames;
|
||||
* }
|
||||
* nb_frames += opus_repacketizer_get_nb_frames(rp);
|
||||
* // If adding the next packet would exceed our target, or it has an
|
||||
* // incompatible TOC sequence, output the packets we already have before
|
||||
* // submitting it.
|
||||
* // N.B., The nb_packets > 0 check ensures we've submitted at least one
|
||||
* // packet since the last call to opus_repacketizer_init(). Otherwise a
|
||||
* // single packet longer than TARGET_DURATION_MS would cause us to try to
|
||||
* // output an (invalid) empty packet. It also ensures that prev_toc has
|
||||
* // been set to a valid value. Additionally, len[nb_packets] > 0 is
|
||||
* // guaranteed by the call to opus_packet_get_nb_frames() above, so the
|
||||
* // reference to data[nb_packets][0] should be valid.
|
||||
* if (nb_packets > 0 && (
|
||||
* ((prev_toc & 0xFC) != (data[nb_packets][0] & 0xFC)) ||
|
||||
* opus_packet_get_samples_per_frame(data[nb_packets], 48000)*nb_frames >
|
||||
* TARGET_DURATION_MS*48))
|
||||
* {
|
||||
* out_len = opus_repacketizer_out(rp, out, sizeof(out));
|
||||
* if (out_len < 0)
|
||||
* {
|
||||
* release_packets(data, nb_packets+1);
|
||||
* return (int)out_len;
|
||||
* }
|
||||
* output_next_packet(out, out_len);
|
||||
* opus_repacketizer_init(rp);
|
||||
* release_packets(data, nb_packets);
|
||||
* data[0] = data[nb_packets];
|
||||
* len[0] = len[nb_packets];
|
||||
* nb_packets = 0;
|
||||
* }
|
||||
* err = opus_repacketizer_cat(rp, data[nb_packets], len[nb_packets]);
|
||||
* if (err != OPUS_OK)
|
||||
* {
|
||||
* release_packets(data, nb_packets+1);
|
||||
* return err;
|
||||
* }
|
||||
* prev_toc = data[nb_packets][0];
|
||||
* nb_packets++;
|
||||
* }
|
||||
* // Output the final, partial packet.
|
||||
* if (nb_packets > 0)
|
||||
* {
|
||||
* out_len = opus_repacketizer_out(rp, out, sizeof(out));
|
||||
* release_packets(data, nb_packets);
|
||||
* if (out_len < 0)
|
||||
* return (int)out_len;
|
||||
* output_next_packet(out, out_len);
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
* An alternate way of merging packets is to simply call opus_repacketizer_cat()
|
||||
* unconditionally until it fails. At that point, the merged packet can be
|
||||
* obtained with opus_repacketizer_out() and the input packet for which
|
||||
* opus_repacketizer_cat() needs to be re-added to a newly reinitialized
|
||||
* repacketizer state.
|
||||
*/
|
||||
|
||||
typedef struct OpusRepacketizer OpusRepacketizer;
|
||||
|
||||
/** Gets the size of an <code>OpusRepacketizer</code> structure.
|
||||
* @returns The size in bytes.
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_repacketizer_get_size(void);
|
||||
|
||||
/** (Re)initializes a previously allocated repacketizer state.
|
||||
* The state must be at least the size returned by opus_repacketizer_get_size().
|
||||
* This can be used for applications which use their own allocator instead of
|
||||
* malloc().
|
||||
* It must also be called to reset the queue of packets waiting to be
|
||||
* repacketized, which is necessary if the maximum packet duration of 120 ms
|
||||
* is reached or if you wish to submit packets with a different Opus
|
||||
* configuration (coding mode, audio bandwidth, frame size, or channel count).
|
||||
* Failure to do so will prevent a new packet from being added with
|
||||
* opus_repacketizer_cat().
|
||||
* @see opus_repacketizer_create
|
||||
* @see opus_repacketizer_get_size
|
||||
* @see opus_repacketizer_cat
|
||||
* @param rp <tt>OpusRepacketizer*</tt>: The repacketizer state to
|
||||
* (re)initialize.
|
||||
* @returns A pointer to the same repacketizer state that was passed in.
|
||||
*/
|
||||
OPUS_EXPORT OpusRepacketizer *opus_repacketizer_init(OpusRepacketizer *rp) OPUS_ARG_NONNULL(1);
|
||||
|
||||
/** Allocates memory and initializes the new repacketizer with
|
||||
* opus_repacketizer_init().
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusRepacketizer *opus_repacketizer_create(void);
|
||||
|
||||
/** Frees an <code>OpusRepacketizer</code> allocated by
|
||||
* opus_repacketizer_create().
|
||||
* @param[in] rp <tt>OpusRepacketizer*</tt>: State to be freed.
|
||||
*/
|
||||
OPUS_EXPORT void opus_repacketizer_destroy(OpusRepacketizer *rp);
|
||||
|
||||
/** Add a packet to the current repacketizer state.
|
||||
* This packet must match the configuration of any packets already submitted
|
||||
* for repacketization since the last call to opus_repacketizer_init().
|
||||
* This means that it must have the same coding mode, audio bandwidth, frame
|
||||
* size, and channel count.
|
||||
* This can be checked in advance by examining the top 6 bits of the first
|
||||
* byte of the packet, and ensuring they match the top 6 bits of the first
|
||||
* byte of any previously submitted packet.
|
||||
* The total duration of audio in the repacketizer state also must not exceed
|
||||
* 120 ms, the maximum duration of a single packet, after adding this packet.
|
||||
*
|
||||
* The contents of the current repacketizer state can be extracted into new
|
||||
* packets using opus_repacketizer_out() or opus_repacketizer_out_range().
|
||||
*
|
||||
* In order to add a packet with a different configuration or to add more
|
||||
* audio beyond 120 ms, you must clear the repacketizer state by calling
|
||||
* opus_repacketizer_init().
|
||||
* If a packet is too large to add to the current repacketizer state, no part
|
||||
* of it is added, even if it contains multiple frames, some of which might
|
||||
* fit.
|
||||
* If you wish to be able to add parts of such packets, you should first use
|
||||
* another repacketizer to split the packet into pieces and add them
|
||||
* individually.
|
||||
* @see opus_repacketizer_out_range
|
||||
* @see opus_repacketizer_out
|
||||
* @see opus_repacketizer_init
|
||||
* @param rp <tt>OpusRepacketizer*</tt>: The repacketizer state to which to
|
||||
* add the packet.
|
||||
* @param[in] data <tt>const unsigned char*</tt>: The packet data.
|
||||
* The application must ensure
|
||||
* this pointer remains valid
|
||||
* until the next call to
|
||||
* opus_repacketizer_init() or
|
||||
* opus_repacketizer_destroy().
|
||||
* @param len <tt>opus_int32</tt>: The number of bytes in the packet data.
|
||||
* @returns An error code indicating whether or not the operation succeeded.
|
||||
* @retval #OPUS_OK The packet's contents have been added to the repacketizer
|
||||
* state.
|
||||
* @retval #OPUS_INVALID_PACKET The packet did not have a valid TOC sequence,
|
||||
* the packet's TOC sequence was not compatible
|
||||
* with previously submitted packets (because
|
||||
* the coding mode, audio bandwidth, frame size,
|
||||
* or channel count did not match), or adding
|
||||
* this packet would increase the total amount of
|
||||
* audio stored in the repacketizer state to more
|
||||
* than 120 ms.
|
||||
*/
|
||||
OPUS_EXPORT int opus_repacketizer_cat(OpusRepacketizer *rp, const unsigned char *data, opus_int32 len) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2);
|
||||
|
||||
|
||||
/** Construct a new packet from data previously submitted to the repacketizer
|
||||
* state via opus_repacketizer_cat().
|
||||
* @param rp <tt>OpusRepacketizer*</tt>: The repacketizer state from which to
|
||||
* construct the new packet.
|
||||
* @param begin <tt>int</tt>: The index of the first frame in the current
|
||||
* repacketizer state to include in the output.
|
||||
* @param end <tt>int</tt>: One past the index of the last frame in the
|
||||
* current repacketizer state to include in the
|
||||
* output.
|
||||
* @param[out] data <tt>const unsigned char*</tt>: The buffer in which to
|
||||
* store the output packet.
|
||||
* @param maxlen <tt>opus_int32</tt>: The maximum number of bytes to store in
|
||||
* the output buffer. In order to guarantee
|
||||
* success, this should be at least
|
||||
* <code>1276</code> for a single frame,
|
||||
* or for multiple frames,
|
||||
* <code>1277*(end-begin)</code>.
|
||||
* However, <code>1*(end-begin)</code> plus
|
||||
* the size of all packet data submitted to
|
||||
* the repacketizer since the last call to
|
||||
* opus_repacketizer_init() or
|
||||
* opus_repacketizer_create() is also
|
||||
* sufficient, and possibly much smaller.
|
||||
* @returns The total size of the output packet on success, or an error code
|
||||
* on failure.
|
||||
* @retval #OPUS_BAD_ARG <code>[begin,end)</code> was an invalid range of
|
||||
* frames (begin < 0, begin >= end, or end >
|
||||
* opus_repacketizer_get_nb_frames()).
|
||||
* @retval #OPUS_BUFFER_TOO_SMALL \a maxlen was insufficient to contain the
|
||||
* complete output packet.
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_repacketizer_out_range(OpusRepacketizer *rp, int begin, int end, unsigned char *data, opus_int32 maxlen) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
|
||||
|
||||
/** Return the total number of frames contained in packet data submitted to
|
||||
* the repacketizer state so far via opus_repacketizer_cat() since the last
|
||||
* call to opus_repacketizer_init() or opus_repacketizer_create().
|
||||
* This defines the valid range of packets that can be extracted with
|
||||
* opus_repacketizer_out_range() or opus_repacketizer_out().
|
||||
* @param rp <tt>OpusRepacketizer*</tt>: The repacketizer state containing the
|
||||
* frames.
|
||||
* @returns The total number of frames contained in the packet data submitted
|
||||
* to the repacketizer state.
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_repacketizer_get_nb_frames(OpusRepacketizer *rp) OPUS_ARG_NONNULL(1);
|
||||
|
||||
/** Construct a new packet from data previously submitted to the repacketizer
|
||||
* state via opus_repacketizer_cat().
|
||||
* This is a convenience routine that returns all the data submitted so far
|
||||
* in a single packet.
|
||||
* It is equivalent to calling
|
||||
* @code
|
||||
* opus_repacketizer_out_range(rp, 0, opus_repacketizer_get_nb_frames(rp),
|
||||
* data, maxlen)
|
||||
* @endcode
|
||||
* @param rp <tt>OpusRepacketizer*</tt>: The repacketizer state from which to
|
||||
* construct the new packet.
|
||||
* @param[out] data <tt>const unsigned char*</tt>: The buffer in which to
|
||||
* store the output packet.
|
||||
* @param maxlen <tt>opus_int32</tt>: The maximum number of bytes to store in
|
||||
* the output buffer. In order to guarantee
|
||||
* success, this should be at least
|
||||
* <code>1277*opus_repacketizer_get_nb_frames(rp)</code>.
|
||||
* However,
|
||||
* <code>1*opus_repacketizer_get_nb_frames(rp)</code>
|
||||
* plus the size of all packet data
|
||||
* submitted to the repacketizer since the
|
||||
* last call to opus_repacketizer_init() or
|
||||
* opus_repacketizer_create() is also
|
||||
* sufficient, and possibly much smaller.
|
||||
* @returns The total size of the output packet on success, or an error code
|
||||
* on failure.
|
||||
* @retval #OPUS_BUFFER_TOO_SMALL \a maxlen was insufficient to contain the
|
||||
* complete output packet.
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_repacketizer_out(OpusRepacketizer *rp, unsigned char *data, opus_int32 maxlen) OPUS_ARG_NONNULL(1);
|
||||
|
||||
/** Pads a given Opus packet to a larger size (possibly changing the TOC sequence).
|
||||
* @param[in,out] data <tt>const unsigned char*</tt>: The buffer containing the
|
||||
* packet to pad.
|
||||
* @param len <tt>opus_int32</tt>: The size of the packet.
|
||||
* This must be at least 1.
|
||||
* @param new_len <tt>opus_int32</tt>: The desired size of the packet after padding.
|
||||
* This must be at least as large as len.
|
||||
* @returns an error code
|
||||
* @retval #OPUS_OK \a on success.
|
||||
* @retval #OPUS_BAD_ARG \a len was less than 1 or new_len was less than len.
|
||||
* @retval #OPUS_INVALID_PACKET \a data did not contain a valid Opus packet.
|
||||
*/
|
||||
OPUS_EXPORT int opus_packet_pad(unsigned char *data, opus_int32 len, opus_int32 new_len);
|
||||
|
||||
/** Remove all padding from a given Opus packet and rewrite the TOC sequence to
|
||||
* minimize space usage.
|
||||
* @param[in,out] data <tt>const unsigned char*</tt>: The buffer containing the
|
||||
* packet to strip.
|
||||
* @param len <tt>opus_int32</tt>: The size of the packet.
|
||||
* This must be at least 1.
|
||||
* @returns The new size of the output packet on success, or an error code
|
||||
* on failure.
|
||||
* @retval #OPUS_BAD_ARG \a len was less than 1.
|
||||
* @retval #OPUS_INVALID_PACKET \a data did not contain a valid Opus packet.
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_packet_unpad(unsigned char *data, opus_int32 len);
|
||||
|
||||
/** Pads a given Opus multi-stream packet to a larger size (possibly changing the TOC sequence).
|
||||
* @param[in,out] data <tt>const unsigned char*</tt>: The buffer containing the
|
||||
* packet to pad.
|
||||
* @param len <tt>opus_int32</tt>: The size of the packet.
|
||||
* This must be at least 1.
|
||||
* @param new_len <tt>opus_int32</tt>: The desired size of the packet after padding.
|
||||
* This must be at least 1.
|
||||
* @param nb_streams <tt>opus_int32</tt>: The number of streams (not channels) in the packet.
|
||||
* This must be at least as large as len.
|
||||
* @returns an error code
|
||||
* @retval #OPUS_OK \a on success.
|
||||
* @retval #OPUS_BAD_ARG \a len was less than 1.
|
||||
* @retval #OPUS_INVALID_PACKET \a data did not contain a valid Opus packet.
|
||||
*/
|
||||
OPUS_EXPORT int opus_multistream_packet_pad(unsigned char *data, opus_int32 len, opus_int32 new_len, int nb_streams);
|
||||
|
||||
/** Remove all padding from a given Opus multi-stream packet and rewrite the TOC sequence to
|
||||
* minimize space usage.
|
||||
* @param[in,out] data <tt>const unsigned char*</tt>: The buffer containing the
|
||||
* packet to strip.
|
||||
* @param len <tt>opus_int32</tt>: The size of the packet.
|
||||
* This must be at least 1.
|
||||
* @param nb_streams <tt>opus_int32</tt>: The number of streams (not channels) in the packet.
|
||||
* This must be at least 1.
|
||||
* @returns The new size of the output packet on success, or an error code
|
||||
* on failure.
|
||||
* @retval #OPUS_BAD_ARG \a len was less than 1 or new_len was less than len.
|
||||
* @retval #OPUS_INVALID_PACKET \a data did not contain a valid Opus packet.
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_multistream_packet_unpad(unsigned char *data, opus_int32 len, int nb_streams);
|
||||
|
||||
/**@}*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* OPUS_H */
|
342
pkg/codec/opus/include/opus_custom.h
Normal file
342
pkg/codec/opus/include/opus_custom.h
Normal file
@@ -0,0 +1,342 @@
|
||||
/* Copyright (c) 2007-2008 CSIRO
|
||||
Copyright (c) 2007-2009 Xiph.Org Foundation
|
||||
Copyright (c) 2008-2012 Gregory Maxwell
|
||||
Written by Jean-Marc Valin and Gregory Maxwell */
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
@file opus_custom.h
|
||||
@brief Opus-Custom reference implementation API
|
||||
*/
|
||||
|
||||
#ifndef OPUS_CUSTOM_H
|
||||
#define OPUS_CUSTOM_H
|
||||
|
||||
#include "opus_defines.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef CUSTOM_MODES
|
||||
# define OPUS_CUSTOM_EXPORT OPUS_EXPORT
|
||||
# define OPUS_CUSTOM_EXPORT_STATIC OPUS_EXPORT
|
||||
#else
|
||||
# define OPUS_CUSTOM_EXPORT
|
||||
# ifdef OPUS_BUILD
|
||||
# define OPUS_CUSTOM_EXPORT_STATIC static OPUS_INLINE
|
||||
# else
|
||||
# define OPUS_CUSTOM_EXPORT_STATIC
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/** @defgroup opus_custom Opus Custom
|
||||
* @{
|
||||
* Opus Custom is an optional part of the Opus specification and
|
||||
* reference implementation which uses a distinct API from the regular
|
||||
* API and supports frame sizes that are not normally supported.\ Use
|
||||
* of Opus Custom is discouraged for all but very special applications
|
||||
* for which a frame size different from 2.5, 5, 10, or 20 ms is needed
|
||||
* (for either complexity or latency reasons) and where interoperability
|
||||
* is less important.
|
||||
*
|
||||
* In addition to the interoperability limitations the use of Opus custom
|
||||
* disables a substantial chunk of the codec and generally lowers the
|
||||
* quality available at a given bitrate. Normally when an application needs
|
||||
* a different frame size from the codec it should buffer to match the
|
||||
* sizes but this adds a small amount of delay which may be important
|
||||
* in some very low latency applications. Some transports (especially
|
||||
* constant rate RF transports) may also work best with frames of
|
||||
* particular durations.
|
||||
*
|
||||
* Libopus only supports custom modes if they are enabled at compile time.
|
||||
*
|
||||
* The Opus Custom API is similar to the regular API but the
|
||||
* @ref opus_encoder_create and @ref opus_decoder_create calls take
|
||||
* an additional mode parameter which is a structure produced by
|
||||
* a call to @ref opus_custom_mode_create. Both the encoder and decoder
|
||||
* must create a mode using the same sample rate (fs) and frame size
|
||||
* (frame size) so these parameters must either be signaled out of band
|
||||
* or fixed in a particular implementation.
|
||||
*
|
||||
* Similar to regular Opus the custom modes support on the fly frame size
|
||||
* switching, but the sizes available depend on the particular frame size in
|
||||
* use. For some initial frame sizes on a single on the fly size is available.
|
||||
*/
|
||||
|
||||
/** Contains the state of an encoder. One encoder state is needed
|
||||
for each stream. It is initialized once at the beginning of the
|
||||
stream. Do *not* re-initialize the state for every frame.
|
||||
@brief Encoder state
|
||||
*/
|
||||
typedef struct OpusCustomEncoder OpusCustomEncoder;
|
||||
|
||||
/** State of the decoder. One decoder state is needed for each stream.
|
||||
It is initialized once at the beginning of the stream. Do *not*
|
||||
re-initialize the state for every frame.
|
||||
@brief Decoder state
|
||||
*/
|
||||
typedef struct OpusCustomDecoder OpusCustomDecoder;
|
||||
|
||||
/** The mode contains all the information necessary to create an
|
||||
encoder. Both the encoder and decoder need to be initialized
|
||||
with exactly the same mode, otherwise the output will be
|
||||
corrupted.
|
||||
@brief Mode configuration
|
||||
*/
|
||||
typedef struct OpusCustomMode OpusCustomMode;
|
||||
|
||||
/** Creates a new mode struct. This will be passed to an encoder or
|
||||
* decoder. The mode MUST NOT BE DESTROYED until the encoders and
|
||||
* decoders that use it are destroyed as well.
|
||||
* @param [in] Fs <tt>int</tt>: Sampling rate (8000 to 96000 Hz)
|
||||
* @param [in] frame_size <tt>int</tt>: Number of samples (per channel) to encode in each
|
||||
* packet (64 - 1024, prime factorization must contain zero or more 2s, 3s, or 5s and no other primes)
|
||||
* @param [out] error <tt>int*</tt>: Returned error code (if NULL, no error will be returned)
|
||||
* @return A newly created mode
|
||||
*/
|
||||
OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT OpusCustomMode *opus_custom_mode_create(opus_int32 Fs, int frame_size, int *error);
|
||||
|
||||
/** Destroys a mode struct. Only call this after all encoders and
|
||||
* decoders using this mode are destroyed as well.
|
||||
* @param [in] mode <tt>OpusCustomMode*</tt>: Mode to be freed.
|
||||
*/
|
||||
OPUS_CUSTOM_EXPORT void opus_custom_mode_destroy(OpusCustomMode *mode);
|
||||
|
||||
|
||||
#if !defined(OPUS_BUILD) || defined(CELT_ENCODER_C)
|
||||
|
||||
/* Encoder */
|
||||
/** Gets the size of an OpusCustomEncoder structure.
|
||||
* @param [in] mode <tt>OpusCustomMode *</tt>: Mode configuration
|
||||
* @param [in] channels <tt>int</tt>: Number of channels
|
||||
* @returns size
|
||||
*/
|
||||
OPUS_CUSTOM_EXPORT_STATIC OPUS_WARN_UNUSED_RESULT int opus_custom_encoder_get_size(
|
||||
const OpusCustomMode *mode,
|
||||
int channels
|
||||
) OPUS_ARG_NONNULL(1);
|
||||
|
||||
# ifdef CUSTOM_MODES
|
||||
/** Initializes a previously allocated encoder state
|
||||
* The memory pointed to by st must be the size returned by opus_custom_encoder_get_size.
|
||||
* This is intended for applications which use their own allocator instead of malloc.
|
||||
* @see opus_custom_encoder_create(),opus_custom_encoder_get_size()
|
||||
* To reset a previously initialized state use the OPUS_RESET_STATE CTL.
|
||||
* @param [in] st <tt>OpusCustomEncoder*</tt>: Encoder state
|
||||
* @param [in] mode <tt>OpusCustomMode *</tt>: Contains all the information about the characteristics of
|
||||
* the stream (must be the same characteristics as used for the
|
||||
* decoder)
|
||||
* @param [in] channels <tt>int</tt>: Number of channels
|
||||
* @return OPUS_OK Success or @ref opus_errorcodes
|
||||
*/
|
||||
OPUS_CUSTOM_EXPORT int opus_custom_encoder_init(
|
||||
OpusCustomEncoder *st,
|
||||
const OpusCustomMode *mode,
|
||||
int channels
|
||||
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
/** Creates a new encoder state. Each stream needs its own encoder
|
||||
* state (can't be shared across simultaneous streams).
|
||||
* @param [in] mode <tt>OpusCustomMode*</tt>: Contains all the information about the characteristics of
|
||||
* the stream (must be the same characteristics as used for the
|
||||
* decoder)
|
||||
* @param [in] channels <tt>int</tt>: Number of channels
|
||||
* @param [out] error <tt>int*</tt>: Returns an error code
|
||||
* @return Newly created encoder state.
|
||||
*/
|
||||
OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT OpusCustomEncoder *opus_custom_encoder_create(
|
||||
const OpusCustomMode *mode,
|
||||
int channels,
|
||||
int *error
|
||||
) OPUS_ARG_NONNULL(1);
|
||||
|
||||
|
||||
/** Destroys a an encoder state.
|
||||
* @param[in] st <tt>OpusCustomEncoder*</tt>: State to be freed.
|
||||
*/
|
||||
OPUS_CUSTOM_EXPORT void opus_custom_encoder_destroy(OpusCustomEncoder *st);
|
||||
|
||||
/** Encodes a frame of audio.
|
||||
* @param [in] st <tt>OpusCustomEncoder*</tt>: Encoder state
|
||||
* @param [in] pcm <tt>float*</tt>: PCM audio in float format, with a normal range of +/-1.0.
|
||||
* Samples with a range beyond +/-1.0 are supported but will
|
||||
* be clipped by decoders using the integer API and should
|
||||
* only be used if it is known that the far end supports
|
||||
* extended dynamic range. There must be exactly
|
||||
* frame_size samples per channel.
|
||||
* @param [in] frame_size <tt>int</tt>: Number of samples per frame of input signal
|
||||
* @param [out] compressed <tt>char *</tt>: The compressed data is written here. This may not alias pcm and must be at least maxCompressedBytes long.
|
||||
* @param [in] maxCompressedBytes <tt>int</tt>: Maximum number of bytes to use for compressing the frame
|
||||
* (can change from one frame to another)
|
||||
* @return Number of bytes written to "compressed".
|
||||
* If negative, an error has occurred (see error codes). It is IMPORTANT that
|
||||
* the length returned be somehow transmitted to the decoder. Otherwise, no
|
||||
* decoding is possible.
|
||||
*/
|
||||
OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT int opus_custom_encode_float(
|
||||
OpusCustomEncoder *st,
|
||||
const float *pcm,
|
||||
int frame_size,
|
||||
unsigned char *compressed,
|
||||
int maxCompressedBytes
|
||||
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
|
||||
|
||||
/** Encodes a frame of audio.
|
||||
* @param [in] st <tt>OpusCustomEncoder*</tt>: Encoder state
|
||||
* @param [in] pcm <tt>opus_int16*</tt>: PCM audio in signed 16-bit format (native endian).
|
||||
* There must be exactly frame_size samples per channel.
|
||||
* @param [in] frame_size <tt>int</tt>: Number of samples per frame of input signal
|
||||
* @param [out] compressed <tt>char *</tt>: The compressed data is written here. This may not alias pcm and must be at least maxCompressedBytes long.
|
||||
* @param [in] maxCompressedBytes <tt>int</tt>: Maximum number of bytes to use for compressing the frame
|
||||
* (can change from one frame to another)
|
||||
* @return Number of bytes written to "compressed".
|
||||
* If negative, an error has occurred (see error codes). It is IMPORTANT that
|
||||
* the length returned be somehow transmitted to the decoder. Otherwise, no
|
||||
* decoding is possible.
|
||||
*/
|
||||
OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT int opus_custom_encode(
|
||||
OpusCustomEncoder *st,
|
||||
const opus_int16 *pcm,
|
||||
int frame_size,
|
||||
unsigned char *compressed,
|
||||
int maxCompressedBytes
|
||||
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
|
||||
|
||||
/** Perform a CTL function on an Opus custom encoder.
|
||||
*
|
||||
* Generally the request and subsequent arguments are generated
|
||||
* by a convenience macro.
|
||||
* @see opus_encoderctls
|
||||
*/
|
||||
OPUS_CUSTOM_EXPORT int opus_custom_encoder_ctl(OpusCustomEncoder * OPUS_RESTRICT st, int request, ...) OPUS_ARG_NONNULL(1);
|
||||
|
||||
|
||||
#if !defined(OPUS_BUILD) || defined(CELT_DECODER_C)
|
||||
/* Decoder */
|
||||
|
||||
/** Gets the size of an OpusCustomDecoder structure.
|
||||
* @param [in] mode <tt>OpusCustomMode *</tt>: Mode configuration
|
||||
* @param [in] channels <tt>int</tt>: Number of channels
|
||||
* @returns size
|
||||
*/
|
||||
OPUS_CUSTOM_EXPORT_STATIC OPUS_WARN_UNUSED_RESULT int opus_custom_decoder_get_size(
|
||||
const OpusCustomMode *mode,
|
||||
int channels
|
||||
) OPUS_ARG_NONNULL(1);
|
||||
|
||||
/** Initializes a previously allocated decoder state
|
||||
* The memory pointed to by st must be the size returned by opus_custom_decoder_get_size.
|
||||
* This is intended for applications which use their own allocator instead of malloc.
|
||||
* @see opus_custom_decoder_create(),opus_custom_decoder_get_size()
|
||||
* To reset a previously initialized state use the OPUS_RESET_STATE CTL.
|
||||
* @param [in] st <tt>OpusCustomDecoder*</tt>: Decoder state
|
||||
* @param [in] mode <tt>OpusCustomMode *</tt>: Contains all the information about the characteristics of
|
||||
* the stream (must be the same characteristics as used for the
|
||||
* encoder)
|
||||
* @param [in] channels <tt>int</tt>: Number of channels
|
||||
* @return OPUS_OK Success or @ref opus_errorcodes
|
||||
*/
|
||||
OPUS_CUSTOM_EXPORT_STATIC int opus_custom_decoder_init(
|
||||
OpusCustomDecoder *st,
|
||||
const OpusCustomMode *mode,
|
||||
int channels
|
||||
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/** Creates a new decoder state. Each stream needs its own decoder state (can't
|
||||
* be shared across simultaneous streams).
|
||||
* @param [in] mode <tt>OpusCustomMode</tt>: Contains all the information about the characteristics of the
|
||||
* stream (must be the same characteristics as used for the encoder)
|
||||
* @param [in] channels <tt>int</tt>: Number of channels
|
||||
* @param [out] error <tt>int*</tt>: Returns an error code
|
||||
* @return Newly created decoder state.
|
||||
*/
|
||||
OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT OpusCustomDecoder *opus_custom_decoder_create(
|
||||
const OpusCustomMode *mode,
|
||||
int channels,
|
||||
int *error
|
||||
) OPUS_ARG_NONNULL(1);
|
||||
|
||||
/** Destroys a an decoder state.
|
||||
* @param[in] st <tt>OpusCustomDecoder*</tt>: State to be freed.
|
||||
*/
|
||||
OPUS_CUSTOM_EXPORT void opus_custom_decoder_destroy(OpusCustomDecoder *st);
|
||||
|
||||
/** Decode an opus custom frame with floating point output
|
||||
* @param [in] st <tt>OpusCustomDecoder*</tt>: Decoder state
|
||||
* @param [in] data <tt>char*</tt>: Input payload. Use a NULL pointer to indicate packet loss
|
||||
* @param [in] len <tt>int</tt>: Number of bytes in payload
|
||||
* @param [out] pcm <tt>float*</tt>: Output signal (interleaved if 2 channels). length
|
||||
* is frame_size*channels*sizeof(float)
|
||||
* @param [in] frame_size Number of samples per channel of available space in *pcm.
|
||||
* @returns Number of decoded samples or @ref opus_errorcodes
|
||||
*/
|
||||
OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT int opus_custom_decode_float(
|
||||
OpusCustomDecoder *st,
|
||||
const unsigned char *data,
|
||||
int len,
|
||||
float *pcm,
|
||||
int frame_size
|
||||
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
|
||||
|
||||
/** Decode an opus custom frame
|
||||
* @param [in] st <tt>OpusCustomDecoder*</tt>: Decoder state
|
||||
* @param [in] data <tt>char*</tt>: Input payload. Use a NULL pointer to indicate packet loss
|
||||
* @param [in] len <tt>int</tt>: Number of bytes in payload
|
||||
* @param [out] pcm <tt>opus_int16*</tt>: Output signal (interleaved if 2 channels). length
|
||||
* is frame_size*channels*sizeof(opus_int16)
|
||||
* @param [in] frame_size Number of samples per channel of available space in *pcm.
|
||||
* @returns Number of decoded samples or @ref opus_errorcodes
|
||||
*/
|
||||
OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT int opus_custom_decode(
|
||||
OpusCustomDecoder *st,
|
||||
const unsigned char *data,
|
||||
int len,
|
||||
opus_int16 *pcm,
|
||||
int frame_size
|
||||
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
|
||||
|
||||
/** Perform a CTL function on an Opus custom decoder.
|
||||
*
|
||||
* Generally the request and subsequent arguments are generated
|
||||
* by a convenience macro.
|
||||
* @see opus_genericctls
|
||||
*/
|
||||
OPUS_CUSTOM_EXPORT int opus_custom_decoder_ctl(OpusCustomDecoder * OPUS_RESTRICT st, int request, ...) OPUS_ARG_NONNULL(1);
|
||||
|
||||
/**@}*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* OPUS_CUSTOM_H */
|
799
pkg/codec/opus/include/opus_defines.h
Normal file
799
pkg/codec/opus/include/opus_defines.h
Normal file
@@ -0,0 +1,799 @@
|
||||
/* Copyright (c) 2010-2011 Xiph.Org Foundation, Skype Limited
|
||||
Written by Jean-Marc Valin and Koen Vos */
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file opus_defines.h
|
||||
* @brief Opus reference implementation constants
|
||||
*/
|
||||
|
||||
#ifndef OPUS_DEFINES_H
|
||||
#define OPUS_DEFINES_H
|
||||
|
||||
#include "opus_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @defgroup opus_errorcodes Error codes
|
||||
* @{
|
||||
*/
|
||||
/** No error @hideinitializer*/
|
||||
#define OPUS_OK 0
|
||||
/** One or more invalid/out of range arguments @hideinitializer*/
|
||||
#define OPUS_BAD_ARG -1
|
||||
/** Not enough bytes allocated in the buffer @hideinitializer*/
|
||||
#define OPUS_BUFFER_TOO_SMALL -2
|
||||
/** An internal error was detected @hideinitializer*/
|
||||
#define OPUS_INTERNAL_ERROR -3
|
||||
/** The compressed data passed is corrupted @hideinitializer*/
|
||||
#define OPUS_INVALID_PACKET -4
|
||||
/** Invalid/unsupported request number @hideinitializer*/
|
||||
#define OPUS_UNIMPLEMENTED -5
|
||||
/** An encoder or decoder structure is invalid or already freed @hideinitializer*/
|
||||
#define OPUS_INVALID_STATE -6
|
||||
/** Memory allocation has failed @hideinitializer*/
|
||||
#define OPUS_ALLOC_FAIL -7
|
||||
/**@}*/
|
||||
|
||||
/** @cond OPUS_INTERNAL_DOC */
|
||||
/**Export control for opus functions */
|
||||
|
||||
#ifndef OPUS_EXPORT
|
||||
# if defined(WIN32)
|
||||
# if defined(OPUS_BUILD) && defined(DLL_EXPORT)
|
||||
# define OPUS_EXPORT __declspec(dllexport)
|
||||
# else
|
||||
# define OPUS_EXPORT
|
||||
# endif
|
||||
# elif defined(__GNUC__) && defined(OPUS_BUILD)
|
||||
# define OPUS_EXPORT __attribute__ ((visibility ("default")))
|
||||
# else
|
||||
# define OPUS_EXPORT
|
||||
# endif
|
||||
#endif
|
||||
|
||||
# if !defined(OPUS_GNUC_PREREQ)
|
||||
# if defined(__GNUC__)&&defined(__GNUC_MINOR__)
|
||||
# define OPUS_GNUC_PREREQ(_maj,_min) \
|
||||
((__GNUC__<<16)+__GNUC_MINOR__>=((_maj)<<16)+(_min))
|
||||
# else
|
||||
# define OPUS_GNUC_PREREQ(_maj,_min) 0
|
||||
# endif
|
||||
# endif
|
||||
|
||||
#if (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) )
|
||||
# if OPUS_GNUC_PREREQ(3,0)
|
||||
# define OPUS_RESTRICT __restrict__
|
||||
# elif (defined(_MSC_VER) && _MSC_VER >= 1400)
|
||||
# define OPUS_RESTRICT __restrict
|
||||
# else
|
||||
# define OPUS_RESTRICT
|
||||
# endif
|
||||
#else
|
||||
# define OPUS_RESTRICT restrict
|
||||
#endif
|
||||
|
||||
#if (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) )
|
||||
# if OPUS_GNUC_PREREQ(2,7)
|
||||
# define OPUS_INLINE __inline__
|
||||
# elif (defined(_MSC_VER))
|
||||
# define OPUS_INLINE __inline
|
||||
# else
|
||||
# define OPUS_INLINE
|
||||
# endif
|
||||
#else
|
||||
# define OPUS_INLINE inline
|
||||
#endif
|
||||
|
||||
/**Warning attributes for opus functions
|
||||
* NONNULL is not used in OPUS_BUILD to avoid the compiler optimizing out
|
||||
* some paranoid null checks. */
|
||||
#if defined(__GNUC__) && OPUS_GNUC_PREREQ(3, 4)
|
||||
# define OPUS_WARN_UNUSED_RESULT __attribute__ ((__warn_unused_result__))
|
||||
#else
|
||||
# define OPUS_WARN_UNUSED_RESULT
|
||||
#endif
|
||||
#if !defined(OPUS_BUILD) && defined(__GNUC__) && OPUS_GNUC_PREREQ(3, 4)
|
||||
# define OPUS_ARG_NONNULL(_x) __attribute__ ((__nonnull__(_x)))
|
||||
#else
|
||||
# define OPUS_ARG_NONNULL(_x)
|
||||
#endif
|
||||
|
||||
/** These are the actual Encoder CTL ID numbers.
|
||||
* They should not be used directly by applications.
|
||||
* In general, SETs should be even and GETs should be odd.*/
|
||||
#define OPUS_SET_APPLICATION_REQUEST 4000
|
||||
#define OPUS_GET_APPLICATION_REQUEST 4001
|
||||
#define OPUS_SET_BITRATE_REQUEST 4002
|
||||
#define OPUS_GET_BITRATE_REQUEST 4003
|
||||
#define OPUS_SET_MAX_BANDWIDTH_REQUEST 4004
|
||||
#define OPUS_GET_MAX_BANDWIDTH_REQUEST 4005
|
||||
#define OPUS_SET_VBR_REQUEST 4006
|
||||
#define OPUS_GET_VBR_REQUEST 4007
|
||||
#define OPUS_SET_BANDWIDTH_REQUEST 4008
|
||||
#define OPUS_GET_BANDWIDTH_REQUEST 4009
|
||||
#define OPUS_SET_COMPLEXITY_REQUEST 4010
|
||||
#define OPUS_GET_COMPLEXITY_REQUEST 4011
|
||||
#define OPUS_SET_INBAND_FEC_REQUEST 4012
|
||||
#define OPUS_GET_INBAND_FEC_REQUEST 4013
|
||||
#define OPUS_SET_PACKET_LOSS_PERC_REQUEST 4014
|
||||
#define OPUS_GET_PACKET_LOSS_PERC_REQUEST 4015
|
||||
#define OPUS_SET_DTX_REQUEST 4016
|
||||
#define OPUS_GET_DTX_REQUEST 4017
|
||||
#define OPUS_SET_VBR_CONSTRAINT_REQUEST 4020
|
||||
#define OPUS_GET_VBR_CONSTRAINT_REQUEST 4021
|
||||
#define OPUS_SET_FORCE_CHANNELS_REQUEST 4022
|
||||
#define OPUS_GET_FORCE_CHANNELS_REQUEST 4023
|
||||
#define OPUS_SET_SIGNAL_REQUEST 4024
|
||||
#define OPUS_GET_SIGNAL_REQUEST 4025
|
||||
#define OPUS_GET_LOOKAHEAD_REQUEST 4027
|
||||
/* #define OPUS_RESET_STATE 4028 */
|
||||
#define OPUS_GET_SAMPLE_RATE_REQUEST 4029
|
||||
#define OPUS_GET_FINAL_RANGE_REQUEST 4031
|
||||
#define OPUS_GET_PITCH_REQUEST 4033
|
||||
#define OPUS_SET_GAIN_REQUEST 4034
|
||||
#define OPUS_GET_GAIN_REQUEST 4045 /* Should have been 4035 */
|
||||
#define OPUS_SET_LSB_DEPTH_REQUEST 4036
|
||||
#define OPUS_GET_LSB_DEPTH_REQUEST 4037
|
||||
#define OPUS_GET_LAST_PACKET_DURATION_REQUEST 4039
|
||||
#define OPUS_SET_EXPERT_FRAME_DURATION_REQUEST 4040
|
||||
#define OPUS_GET_EXPERT_FRAME_DURATION_REQUEST 4041
|
||||
#define OPUS_SET_PREDICTION_DISABLED_REQUEST 4042
|
||||
#define OPUS_GET_PREDICTION_DISABLED_REQUEST 4043
|
||||
/* Don't use 4045, it's already taken by OPUS_GET_GAIN_REQUEST */
|
||||
#define OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST 4046
|
||||
#define OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST 4047
|
||||
#define OPUS_GET_IN_DTX_REQUEST 4049
|
||||
|
||||
/** Defines for the presence of extended APIs. */
|
||||
#define OPUS_HAVE_OPUS_PROJECTION_H
|
||||
|
||||
/* Macros to trigger compilation errors when the wrong types are provided to a CTL */
|
||||
#define __opus_check_int(x) (((void)((x) == (opus_int32)0)), (opus_int32)(x))
|
||||
#define __opus_check_int_ptr(ptr) ((ptr) + ((ptr) - (opus_int32*)(ptr)))
|
||||
#define __opus_check_uint_ptr(ptr) ((ptr) + ((ptr) - (opus_uint32*)(ptr)))
|
||||
#define __opus_check_val16_ptr(ptr) ((ptr) + ((ptr) - (opus_val16*)(ptr)))
|
||||
/** @endcond */
|
||||
|
||||
/** @defgroup opus_ctlvalues Pre-defined values for CTL interface
|
||||
* @see opus_genericctls, opus_encoderctls
|
||||
* @{
|
||||
*/
|
||||
/* Values for the various encoder CTLs */
|
||||
#define OPUS_AUTO -1000 /**<Auto/default setting @hideinitializer*/
|
||||
#define OPUS_BITRATE_MAX -1 /**<Maximum bitrate @hideinitializer*/
|
||||
|
||||
/** Best for most VoIP/videoconference applications where listening quality and intelligibility matter most
|
||||
* @hideinitializer */
|
||||
#define OPUS_APPLICATION_VOIP 2048
|
||||
/** Best for broadcast/high-fidelity application where the decoded audio should be as close as possible to the input
|
||||
* @hideinitializer */
|
||||
#define OPUS_APPLICATION_AUDIO 2049
|
||||
/** Only use when lowest-achievable latency is what matters most. Voice-optimized modes cannot be used.
|
||||
* @hideinitializer */
|
||||
#define OPUS_APPLICATION_RESTRICTED_LOWDELAY 2051
|
||||
|
||||
#define OPUS_SIGNAL_VOICE 3001 /**< Signal being encoded is voice */
|
||||
#define OPUS_SIGNAL_MUSIC 3002 /**< Signal being encoded is music */
|
||||
#define OPUS_BANDWIDTH_NARROWBAND 1101 /**< 4 kHz bandpass @hideinitializer*/
|
||||
#define OPUS_BANDWIDTH_MEDIUMBAND 1102 /**< 6 kHz bandpass @hideinitializer*/
|
||||
#define OPUS_BANDWIDTH_WIDEBAND 1103 /**< 8 kHz bandpass @hideinitializer*/
|
||||
#define OPUS_BANDWIDTH_SUPERWIDEBAND 1104 /**<12 kHz bandpass @hideinitializer*/
|
||||
#define OPUS_BANDWIDTH_FULLBAND 1105 /**<20 kHz bandpass @hideinitializer*/
|
||||
|
||||
#define OPUS_FRAMESIZE_ARG 5000 /**< Select frame size from the argument (default) */
|
||||
#define OPUS_FRAMESIZE_2_5_MS 5001 /**< Use 2.5 ms frames */
|
||||
#define OPUS_FRAMESIZE_5_MS 5002 /**< Use 5 ms frames */
|
||||
#define OPUS_FRAMESIZE_10_MS 5003 /**< Use 10 ms frames */
|
||||
#define OPUS_FRAMESIZE_20_MS 5004 /**< Use 20 ms frames */
|
||||
#define OPUS_FRAMESIZE_40_MS 5005 /**< Use 40 ms frames */
|
||||
#define OPUS_FRAMESIZE_60_MS 5006 /**< Use 60 ms frames */
|
||||
#define OPUS_FRAMESIZE_80_MS 5007 /**< Use 80 ms frames */
|
||||
#define OPUS_FRAMESIZE_100_MS 5008 /**< Use 100 ms frames */
|
||||
#define OPUS_FRAMESIZE_120_MS 5009 /**< Use 120 ms frames */
|
||||
|
||||
/**@}*/
|
||||
|
||||
|
||||
/** @defgroup opus_encoderctls Encoder related CTLs
|
||||
*
|
||||
* These are convenience macros for use with the \c opus_encode_ctl
|
||||
* interface. They are used to generate the appropriate series of
|
||||
* arguments for that call, passing the correct type, size and so
|
||||
* on as expected for each particular request.
|
||||
*
|
||||
* Some usage examples:
|
||||
*
|
||||
* @code
|
||||
* int ret;
|
||||
* ret = opus_encoder_ctl(enc_ctx, OPUS_SET_BANDWIDTH(OPUS_AUTO));
|
||||
* if (ret != OPUS_OK) return ret;
|
||||
*
|
||||
* opus_int32 rate;
|
||||
* opus_encoder_ctl(enc_ctx, OPUS_GET_BANDWIDTH(&rate));
|
||||
*
|
||||
* opus_encoder_ctl(enc_ctx, OPUS_RESET_STATE);
|
||||
* @endcode
|
||||
*
|
||||
* @see opus_genericctls, opus_encoder
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** Configures the encoder's computational complexity.
|
||||
* The supported range is 0-10 inclusive with 10 representing the highest complexity.
|
||||
* @see OPUS_GET_COMPLEXITY
|
||||
* @param[in] x <tt>opus_int32</tt>: Allowed values: 0-10, inclusive.
|
||||
*
|
||||
* @hideinitializer */
|
||||
#define OPUS_SET_COMPLEXITY(x) OPUS_SET_COMPLEXITY_REQUEST, __opus_check_int(x)
|
||||
/** Gets the encoder's complexity configuration.
|
||||
* @see OPUS_SET_COMPLEXITY
|
||||
* @param[out] x <tt>opus_int32 *</tt>: Returns a value in the range 0-10,
|
||||
* inclusive.
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_COMPLEXITY(x) OPUS_GET_COMPLEXITY_REQUEST, __opus_check_int_ptr(x)
|
||||
|
||||
/** Configures the bitrate in the encoder.
|
||||
* Rates from 500 to 512000 bits per second are meaningful, as well as the
|
||||
* special values #OPUS_AUTO and #OPUS_BITRATE_MAX.
|
||||
* The value #OPUS_BITRATE_MAX can be used to cause the codec to use as much
|
||||
* rate as it can, which is useful for controlling the rate by adjusting the
|
||||
* output buffer size.
|
||||
* @see OPUS_GET_BITRATE
|
||||
* @param[in] x <tt>opus_int32</tt>: Bitrate in bits per second. The default
|
||||
* is determined based on the number of
|
||||
* channels and the input sampling rate.
|
||||
* @hideinitializer */
|
||||
#define OPUS_SET_BITRATE(x) OPUS_SET_BITRATE_REQUEST, __opus_check_int(x)
|
||||
/** Gets the encoder's bitrate configuration.
|
||||
* @see OPUS_SET_BITRATE
|
||||
* @param[out] x <tt>opus_int32 *</tt>: Returns the bitrate in bits per second.
|
||||
* The default is determined based on the
|
||||
* number of channels and the input
|
||||
* sampling rate.
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_BITRATE(x) OPUS_GET_BITRATE_REQUEST, __opus_check_int_ptr(x)
|
||||
|
||||
/** Enables or disables variable bitrate (VBR) in the encoder.
|
||||
* The configured bitrate may not be met exactly because frames must
|
||||
* be an integer number of bytes in length.
|
||||
* @see OPUS_GET_VBR
|
||||
* @see OPUS_SET_VBR_CONSTRAINT
|
||||
* @param[in] x <tt>opus_int32</tt>: Allowed values:
|
||||
* <dl>
|
||||
* <dt>0</dt><dd>Hard CBR. For LPC/hybrid modes at very low bit-rate, this can
|
||||
* cause noticeable quality degradation.</dd>
|
||||
* <dt>1</dt><dd>VBR (default). The exact type of VBR is controlled by
|
||||
* #OPUS_SET_VBR_CONSTRAINT.</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_SET_VBR(x) OPUS_SET_VBR_REQUEST, __opus_check_int(x)
|
||||
/** Determine if variable bitrate (VBR) is enabled in the encoder.
|
||||
* @see OPUS_SET_VBR
|
||||
* @see OPUS_GET_VBR_CONSTRAINT
|
||||
* @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
|
||||
* <dl>
|
||||
* <dt>0</dt><dd>Hard CBR.</dd>
|
||||
* <dt>1</dt><dd>VBR (default). The exact type of VBR may be retrieved via
|
||||
* #OPUS_GET_VBR_CONSTRAINT.</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_VBR(x) OPUS_GET_VBR_REQUEST, __opus_check_int_ptr(x)
|
||||
|
||||
/** Enables or disables constrained VBR in the encoder.
|
||||
* This setting is ignored when the encoder is in CBR mode.
|
||||
* @warning Only the MDCT mode of Opus currently heeds the constraint.
|
||||
* Speech mode ignores it completely, hybrid mode may fail to obey it
|
||||
* if the LPC layer uses more bitrate than the constraint would have
|
||||
* permitted.
|
||||
* @see OPUS_GET_VBR_CONSTRAINT
|
||||
* @see OPUS_SET_VBR
|
||||
* @param[in] x <tt>opus_int32</tt>: Allowed values:
|
||||
* <dl>
|
||||
* <dt>0</dt><dd>Unconstrained VBR.</dd>
|
||||
* <dt>1</dt><dd>Constrained VBR (default). This creates a maximum of one
|
||||
* frame of buffering delay assuming a transport with a
|
||||
* serialization speed of the nominal bitrate.</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_SET_VBR_CONSTRAINT(x) OPUS_SET_VBR_CONSTRAINT_REQUEST, __opus_check_int(x)
|
||||
/** Determine if constrained VBR is enabled in the encoder.
|
||||
* @see OPUS_SET_VBR_CONSTRAINT
|
||||
* @see OPUS_GET_VBR
|
||||
* @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
|
||||
* <dl>
|
||||
* <dt>0</dt><dd>Unconstrained VBR.</dd>
|
||||
* <dt>1</dt><dd>Constrained VBR (default).</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_VBR_CONSTRAINT(x) OPUS_GET_VBR_CONSTRAINT_REQUEST, __opus_check_int_ptr(x)
|
||||
|
||||
/** Configures mono/stereo forcing in the encoder.
|
||||
* This can force the encoder to produce packets encoded as either mono or
|
||||
* stereo, regardless of the format of the input audio. This is useful when
|
||||
* the caller knows that the input signal is currently a mono source embedded
|
||||
* in a stereo stream.
|
||||
* @see OPUS_GET_FORCE_CHANNELS
|
||||
* @param[in] x <tt>opus_int32</tt>: Allowed values:
|
||||
* <dl>
|
||||
* <dt>#OPUS_AUTO</dt><dd>Not forced (default)</dd>
|
||||
* <dt>1</dt> <dd>Forced mono</dd>
|
||||
* <dt>2</dt> <dd>Forced stereo</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_SET_FORCE_CHANNELS(x) OPUS_SET_FORCE_CHANNELS_REQUEST, __opus_check_int(x)
|
||||
/** Gets the encoder's forced channel configuration.
|
||||
* @see OPUS_SET_FORCE_CHANNELS
|
||||
* @param[out] x <tt>opus_int32 *</tt>:
|
||||
* <dl>
|
||||
* <dt>#OPUS_AUTO</dt><dd>Not forced (default)</dd>
|
||||
* <dt>1</dt> <dd>Forced mono</dd>
|
||||
* <dt>2</dt> <dd>Forced stereo</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_FORCE_CHANNELS(x) OPUS_GET_FORCE_CHANNELS_REQUEST, __opus_check_int_ptr(x)
|
||||
|
||||
/** Configures the maximum bandpass that the encoder will select automatically.
|
||||
* Applications should normally use this instead of #OPUS_SET_BANDWIDTH
|
||||
* (leaving that set to the default, #OPUS_AUTO). This allows the
|
||||
* application to set an upper bound based on the type of input it is
|
||||
* providing, but still gives the encoder the freedom to reduce the bandpass
|
||||
* when the bitrate becomes too low, for better overall quality.
|
||||
* @see OPUS_GET_MAX_BANDWIDTH
|
||||
* @param[in] x <tt>opus_int32</tt>: Allowed values:
|
||||
* <dl>
|
||||
* <dt>OPUS_BANDWIDTH_NARROWBAND</dt> <dd>4 kHz passband</dd>
|
||||
* <dt>OPUS_BANDWIDTH_MEDIUMBAND</dt> <dd>6 kHz passband</dd>
|
||||
* <dt>OPUS_BANDWIDTH_WIDEBAND</dt> <dd>8 kHz passband</dd>
|
||||
* <dt>OPUS_BANDWIDTH_SUPERWIDEBAND</dt><dd>12 kHz passband</dd>
|
||||
* <dt>OPUS_BANDWIDTH_FULLBAND</dt> <dd>20 kHz passband (default)</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_SET_MAX_BANDWIDTH(x) OPUS_SET_MAX_BANDWIDTH_REQUEST, __opus_check_int(x)
|
||||
|
||||
/** Gets the encoder's configured maximum allowed bandpass.
|
||||
* @see OPUS_SET_MAX_BANDWIDTH
|
||||
* @param[out] x <tt>opus_int32 *</tt>: Allowed values:
|
||||
* <dl>
|
||||
* <dt>#OPUS_BANDWIDTH_NARROWBAND</dt> <dd>4 kHz passband</dd>
|
||||
* <dt>#OPUS_BANDWIDTH_MEDIUMBAND</dt> <dd>6 kHz passband</dd>
|
||||
* <dt>#OPUS_BANDWIDTH_WIDEBAND</dt> <dd>8 kHz passband</dd>
|
||||
* <dt>#OPUS_BANDWIDTH_SUPERWIDEBAND</dt><dd>12 kHz passband</dd>
|
||||
* <dt>#OPUS_BANDWIDTH_FULLBAND</dt> <dd>20 kHz passband (default)</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_MAX_BANDWIDTH(x) OPUS_GET_MAX_BANDWIDTH_REQUEST, __opus_check_int_ptr(x)
|
||||
|
||||
/** Sets the encoder's bandpass to a specific value.
|
||||
* This prevents the encoder from automatically selecting the bandpass based
|
||||
* on the available bitrate. If an application knows the bandpass of the input
|
||||
* audio it is providing, it should normally use #OPUS_SET_MAX_BANDWIDTH
|
||||
* instead, which still gives the encoder the freedom to reduce the bandpass
|
||||
* when the bitrate becomes too low, for better overall quality.
|
||||
* @see OPUS_GET_BANDWIDTH
|
||||
* @param[in] x <tt>opus_int32</tt>: Allowed values:
|
||||
* <dl>
|
||||
* <dt>#OPUS_AUTO</dt> <dd>(default)</dd>
|
||||
* <dt>#OPUS_BANDWIDTH_NARROWBAND</dt> <dd>4 kHz passband</dd>
|
||||
* <dt>#OPUS_BANDWIDTH_MEDIUMBAND</dt> <dd>6 kHz passband</dd>
|
||||
* <dt>#OPUS_BANDWIDTH_WIDEBAND</dt> <dd>8 kHz passband</dd>
|
||||
* <dt>#OPUS_BANDWIDTH_SUPERWIDEBAND</dt><dd>12 kHz passband</dd>
|
||||
* <dt>#OPUS_BANDWIDTH_FULLBAND</dt> <dd>20 kHz passband</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_SET_BANDWIDTH(x) OPUS_SET_BANDWIDTH_REQUEST, __opus_check_int(x)
|
||||
|
||||
/** Configures the type of signal being encoded.
|
||||
* This is a hint which helps the encoder's mode selection.
|
||||
* @see OPUS_GET_SIGNAL
|
||||
* @param[in] x <tt>opus_int32</tt>: Allowed values:
|
||||
* <dl>
|
||||
* <dt>#OPUS_AUTO</dt> <dd>(default)</dd>
|
||||
* <dt>#OPUS_SIGNAL_VOICE</dt><dd>Bias thresholds towards choosing LPC or Hybrid modes.</dd>
|
||||
* <dt>#OPUS_SIGNAL_MUSIC</dt><dd>Bias thresholds towards choosing MDCT modes.</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_SET_SIGNAL(x) OPUS_SET_SIGNAL_REQUEST, __opus_check_int(x)
|
||||
/** Gets the encoder's configured signal type.
|
||||
* @see OPUS_SET_SIGNAL
|
||||
* @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
|
||||
* <dl>
|
||||
* <dt>#OPUS_AUTO</dt> <dd>(default)</dd>
|
||||
* <dt>#OPUS_SIGNAL_VOICE</dt><dd>Bias thresholds towards choosing LPC or Hybrid modes.</dd>
|
||||
* <dt>#OPUS_SIGNAL_MUSIC</dt><dd>Bias thresholds towards choosing MDCT modes.</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_SIGNAL(x) OPUS_GET_SIGNAL_REQUEST, __opus_check_int_ptr(x)
|
||||
|
||||
|
||||
/** Configures the encoder's intended application.
|
||||
* The initial value is a mandatory argument to the encoder_create function.
|
||||
* @see OPUS_GET_APPLICATION
|
||||
* @param[in] x <tt>opus_int32</tt>: Returns one of the following values:
|
||||
* <dl>
|
||||
* <dt>#OPUS_APPLICATION_VOIP</dt>
|
||||
* <dd>Process signal for improved speech intelligibility.</dd>
|
||||
* <dt>#OPUS_APPLICATION_AUDIO</dt>
|
||||
* <dd>Favor faithfulness to the original input.</dd>
|
||||
* <dt>#OPUS_APPLICATION_RESTRICTED_LOWDELAY</dt>
|
||||
* <dd>Configure the minimum possible coding delay by disabling certain modes
|
||||
* of operation.</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_SET_APPLICATION(x) OPUS_SET_APPLICATION_REQUEST, __opus_check_int(x)
|
||||
/** Gets the encoder's configured application.
|
||||
* @see OPUS_SET_APPLICATION
|
||||
* @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
|
||||
* <dl>
|
||||
* <dt>#OPUS_APPLICATION_VOIP</dt>
|
||||
* <dd>Process signal for improved speech intelligibility.</dd>
|
||||
* <dt>#OPUS_APPLICATION_AUDIO</dt>
|
||||
* <dd>Favor faithfulness to the original input.</dd>
|
||||
* <dt>#OPUS_APPLICATION_RESTRICTED_LOWDELAY</dt>
|
||||
* <dd>Configure the minimum possible coding delay by disabling certain modes
|
||||
* of operation.</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_APPLICATION(x) OPUS_GET_APPLICATION_REQUEST, __opus_check_int_ptr(x)
|
||||
|
||||
/** Gets the total samples of delay added by the entire codec.
|
||||
* This can be queried by the encoder and then the provided number of samples can be
|
||||
* skipped on from the start of the decoder's output to provide time aligned input
|
||||
* and output. From the perspective of a decoding application the real data begins this many
|
||||
* samples late.
|
||||
*
|
||||
* The decoder contribution to this delay is identical for all decoders, but the
|
||||
* encoder portion of the delay may vary from implementation to implementation,
|
||||
* version to version, or even depend on the encoder's initial configuration.
|
||||
* Applications needing delay compensation should call this CTL rather than
|
||||
* hard-coding a value.
|
||||
* @param[out] x <tt>opus_int32 *</tt>: Number of lookahead samples
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_LOOKAHEAD(x) OPUS_GET_LOOKAHEAD_REQUEST, __opus_check_int_ptr(x)
|
||||
|
||||
/** Configures the encoder's use of inband forward error correction (FEC).
|
||||
* @note This is only applicable to the LPC layer
|
||||
* @see OPUS_GET_INBAND_FEC
|
||||
* @param[in] x <tt>opus_int32</tt>: Allowed values:
|
||||
* <dl>
|
||||
* <dt>0</dt><dd>Disable inband FEC (default).</dd>
|
||||
* <dt>1</dt><dd>Enable inband FEC.</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_SET_INBAND_FEC(x) OPUS_SET_INBAND_FEC_REQUEST, __opus_check_int(x)
|
||||
/** Gets encoder's configured use of inband forward error correction.
|
||||
* @see OPUS_SET_INBAND_FEC
|
||||
* @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
|
||||
* <dl>
|
||||
* <dt>0</dt><dd>Inband FEC disabled (default).</dd>
|
||||
* <dt>1</dt><dd>Inband FEC enabled.</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_INBAND_FEC(x) OPUS_GET_INBAND_FEC_REQUEST, __opus_check_int_ptr(x)
|
||||
|
||||
/** Configures the encoder's expected packet loss percentage.
|
||||
* Higher values trigger progressively more loss resistant behavior in the encoder
|
||||
* at the expense of quality at a given bitrate in the absence of packet loss, but
|
||||
* greater quality under loss.
|
||||
* @see OPUS_GET_PACKET_LOSS_PERC
|
||||
* @param[in] x <tt>opus_int32</tt>: Loss percentage in the range 0-100, inclusive (default: 0).
|
||||
* @hideinitializer */
|
||||
#define OPUS_SET_PACKET_LOSS_PERC(x) OPUS_SET_PACKET_LOSS_PERC_REQUEST, __opus_check_int(x)
|
||||
/** Gets the encoder's configured packet loss percentage.
|
||||
* @see OPUS_SET_PACKET_LOSS_PERC
|
||||
* @param[out] x <tt>opus_int32 *</tt>: Returns the configured loss percentage
|
||||
* in the range 0-100, inclusive (default: 0).
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_PACKET_LOSS_PERC(x) OPUS_GET_PACKET_LOSS_PERC_REQUEST, __opus_check_int_ptr(x)
|
||||
|
||||
/** Configures the encoder's use of discontinuous transmission (DTX).
|
||||
* @note This is only applicable to the LPC layer
|
||||
* @see OPUS_GET_DTX
|
||||
* @param[in] x <tt>opus_int32</tt>: Allowed values:
|
||||
* <dl>
|
||||
* <dt>0</dt><dd>Disable DTX (default).</dd>
|
||||
* <dt>1</dt><dd>Enabled DTX.</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_SET_DTX(x) OPUS_SET_DTX_REQUEST, __opus_check_int(x)
|
||||
/** Gets encoder's configured use of discontinuous transmission.
|
||||
* @see OPUS_SET_DTX
|
||||
* @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
|
||||
* <dl>
|
||||
* <dt>0</dt><dd>DTX disabled (default).</dd>
|
||||
* <dt>1</dt><dd>DTX enabled.</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_DTX(x) OPUS_GET_DTX_REQUEST, __opus_check_int_ptr(x)
|
||||
/** Configures the depth of signal being encoded.
|
||||
*
|
||||
* This is a hint which helps the encoder identify silence and near-silence.
|
||||
* It represents the number of significant bits of linear intensity below
|
||||
* which the signal contains ignorable quantization or other noise.
|
||||
*
|
||||
* For example, OPUS_SET_LSB_DEPTH(14) would be an appropriate setting
|
||||
* for G.711 u-law input. OPUS_SET_LSB_DEPTH(16) would be appropriate
|
||||
* for 16-bit linear pcm input with opus_encode_float().
|
||||
*
|
||||
* When using opus_encode() instead of opus_encode_float(), or when libopus
|
||||
* is compiled for fixed-point, the encoder uses the minimum of the value
|
||||
* set here and the value 16.
|
||||
*
|
||||
* @see OPUS_GET_LSB_DEPTH
|
||||
* @param[in] x <tt>opus_int32</tt>: Input precision in bits, between 8 and 24
|
||||
* (default: 24).
|
||||
* @hideinitializer */
|
||||
#define OPUS_SET_LSB_DEPTH(x) OPUS_SET_LSB_DEPTH_REQUEST, __opus_check_int(x)
|
||||
/** Gets the encoder's configured signal depth.
|
||||
* @see OPUS_SET_LSB_DEPTH
|
||||
* @param[out] x <tt>opus_int32 *</tt>: Input precision in bits, between 8 and
|
||||
* 24 (default: 24).
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_LSB_DEPTH(x) OPUS_GET_LSB_DEPTH_REQUEST, __opus_check_int_ptr(x)
|
||||
|
||||
/** Configures the encoder's use of variable duration frames.
|
||||
* When variable duration is enabled, the encoder is free to use a shorter frame
|
||||
* size than the one requested in the opus_encode*() call.
|
||||
* It is then the user's responsibility
|
||||
* to verify how much audio was encoded by checking the ToC byte of the encoded
|
||||
* packet. The part of the audio that was not encoded needs to be resent to the
|
||||
* encoder for the next call. Do not use this option unless you <b>really</b>
|
||||
* know what you are doing.
|
||||
* @see OPUS_GET_EXPERT_FRAME_DURATION
|
||||
* @param[in] x <tt>opus_int32</tt>: Allowed values:
|
||||
* <dl>
|
||||
* <dt>OPUS_FRAMESIZE_ARG</dt><dd>Select frame size from the argument (default).</dd>
|
||||
* <dt>OPUS_FRAMESIZE_2_5_MS</dt><dd>Use 2.5 ms frames.</dd>
|
||||
* <dt>OPUS_FRAMESIZE_5_MS</dt><dd>Use 5 ms frames.</dd>
|
||||
* <dt>OPUS_FRAMESIZE_10_MS</dt><dd>Use 10 ms frames.</dd>
|
||||
* <dt>OPUS_FRAMESIZE_20_MS</dt><dd>Use 20 ms frames.</dd>
|
||||
* <dt>OPUS_FRAMESIZE_40_MS</dt><dd>Use 40 ms frames.</dd>
|
||||
* <dt>OPUS_FRAMESIZE_60_MS</dt><dd>Use 60 ms frames.</dd>
|
||||
* <dt>OPUS_FRAMESIZE_80_MS</dt><dd>Use 80 ms frames.</dd>
|
||||
* <dt>OPUS_FRAMESIZE_100_MS</dt><dd>Use 100 ms frames.</dd>
|
||||
* <dt>OPUS_FRAMESIZE_120_MS</dt><dd>Use 120 ms frames.</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_SET_EXPERT_FRAME_DURATION(x) OPUS_SET_EXPERT_FRAME_DURATION_REQUEST, __opus_check_int(x)
|
||||
/** Gets the encoder's configured use of variable duration frames.
|
||||
* @see OPUS_SET_EXPERT_FRAME_DURATION
|
||||
* @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
|
||||
* <dl>
|
||||
* <dt>OPUS_FRAMESIZE_ARG</dt><dd>Select frame size from the argument (default).</dd>
|
||||
* <dt>OPUS_FRAMESIZE_2_5_MS</dt><dd>Use 2.5 ms frames.</dd>
|
||||
* <dt>OPUS_FRAMESIZE_5_MS</dt><dd>Use 5 ms frames.</dd>
|
||||
* <dt>OPUS_FRAMESIZE_10_MS</dt><dd>Use 10 ms frames.</dd>
|
||||
* <dt>OPUS_FRAMESIZE_20_MS</dt><dd>Use 20 ms frames.</dd>
|
||||
* <dt>OPUS_FRAMESIZE_40_MS</dt><dd>Use 40 ms frames.</dd>
|
||||
* <dt>OPUS_FRAMESIZE_60_MS</dt><dd>Use 60 ms frames.</dd>
|
||||
* <dt>OPUS_FRAMESIZE_80_MS</dt><dd>Use 80 ms frames.</dd>
|
||||
* <dt>OPUS_FRAMESIZE_100_MS</dt><dd>Use 100 ms frames.</dd>
|
||||
* <dt>OPUS_FRAMESIZE_120_MS</dt><dd>Use 120 ms frames.</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_EXPERT_FRAME_DURATION(x) OPUS_GET_EXPERT_FRAME_DURATION_REQUEST, __opus_check_int_ptr(x)
|
||||
|
||||
/** If set to 1, disables almost all use of prediction, making frames almost
|
||||
* completely independent. This reduces quality.
|
||||
* @see OPUS_GET_PREDICTION_DISABLED
|
||||
* @param[in] x <tt>opus_int32</tt>: Allowed values:
|
||||
* <dl>
|
||||
* <dt>0</dt><dd>Enable prediction (default).</dd>
|
||||
* <dt>1</dt><dd>Disable prediction.</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_SET_PREDICTION_DISABLED(x) OPUS_SET_PREDICTION_DISABLED_REQUEST, __opus_check_int(x)
|
||||
/** Gets the encoder's configured prediction status.
|
||||
* @see OPUS_SET_PREDICTION_DISABLED
|
||||
* @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
|
||||
* <dl>
|
||||
* <dt>0</dt><dd>Prediction enabled (default).</dd>
|
||||
* <dt>1</dt><dd>Prediction disabled.</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_PREDICTION_DISABLED(x) OPUS_GET_PREDICTION_DISABLED_REQUEST, __opus_check_int_ptr(x)
|
||||
|
||||
/**@}*/
|
||||
|
||||
/** @defgroup opus_genericctls Generic CTLs
|
||||
*
|
||||
* These macros are used with the \c opus_decoder_ctl and
|
||||
* \c opus_encoder_ctl calls to generate a particular
|
||||
* request.
|
||||
*
|
||||
* When called on an \c OpusDecoder they apply to that
|
||||
* particular decoder instance. When called on an
|
||||
* \c OpusEncoder they apply to the corresponding setting
|
||||
* on that encoder instance, if present.
|
||||
*
|
||||
* Some usage examples:
|
||||
*
|
||||
* @code
|
||||
* int ret;
|
||||
* opus_int32 pitch;
|
||||
* ret = opus_decoder_ctl(dec_ctx, OPUS_GET_PITCH(&pitch));
|
||||
* if (ret == OPUS_OK) return ret;
|
||||
*
|
||||
* opus_encoder_ctl(enc_ctx, OPUS_RESET_STATE);
|
||||
* opus_decoder_ctl(dec_ctx, OPUS_RESET_STATE);
|
||||
*
|
||||
* opus_int32 enc_bw, dec_bw;
|
||||
* opus_encoder_ctl(enc_ctx, OPUS_GET_BANDWIDTH(&enc_bw));
|
||||
* opus_decoder_ctl(dec_ctx, OPUS_GET_BANDWIDTH(&dec_bw));
|
||||
* if (enc_bw != dec_bw) {
|
||||
* printf("packet bandwidth mismatch!\n");
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
* @see opus_encoder, opus_decoder_ctl, opus_encoder_ctl, opus_decoderctls, opus_encoderctls
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** Resets the codec state to be equivalent to a freshly initialized state.
|
||||
* This should be called when switching streams in order to prevent
|
||||
* the back to back decoding from giving different results from
|
||||
* one at a time decoding.
|
||||
* @hideinitializer */
|
||||
#define OPUS_RESET_STATE 4028
|
||||
|
||||
/** Gets the final state of the codec's entropy coder.
|
||||
* This is used for testing purposes,
|
||||
* The encoder and decoder state should be identical after coding a payload
|
||||
* (assuming no data corruption or software bugs)
|
||||
*
|
||||
* @param[out] x <tt>opus_uint32 *</tt>: Entropy coder state
|
||||
*
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_FINAL_RANGE(x) OPUS_GET_FINAL_RANGE_REQUEST, __opus_check_uint_ptr(x)
|
||||
|
||||
/** Gets the encoder's configured bandpass or the decoder's last bandpass.
|
||||
* @see OPUS_SET_BANDWIDTH
|
||||
* @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
|
||||
* <dl>
|
||||
* <dt>#OPUS_AUTO</dt> <dd>(default)</dd>
|
||||
* <dt>#OPUS_BANDWIDTH_NARROWBAND</dt> <dd>4 kHz passband</dd>
|
||||
* <dt>#OPUS_BANDWIDTH_MEDIUMBAND</dt> <dd>6 kHz passband</dd>
|
||||
* <dt>#OPUS_BANDWIDTH_WIDEBAND</dt> <dd>8 kHz passband</dd>
|
||||
* <dt>#OPUS_BANDWIDTH_SUPERWIDEBAND</dt><dd>12 kHz passband</dd>
|
||||
* <dt>#OPUS_BANDWIDTH_FULLBAND</dt> <dd>20 kHz passband</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_BANDWIDTH(x) OPUS_GET_BANDWIDTH_REQUEST, __opus_check_int_ptr(x)
|
||||
|
||||
/** Gets the sampling rate the encoder or decoder was initialized with.
|
||||
* This simply returns the <code>Fs</code> value passed to opus_encoder_init()
|
||||
* or opus_decoder_init().
|
||||
* @param[out] x <tt>opus_int32 *</tt>: Sampling rate of encoder or decoder.
|
||||
* @hideinitializer
|
||||
*/
|
||||
#define OPUS_GET_SAMPLE_RATE(x) OPUS_GET_SAMPLE_RATE_REQUEST, __opus_check_int_ptr(x)
|
||||
|
||||
/** If set to 1, disables the use of phase inversion for intensity stereo,
|
||||
* improving the quality of mono downmixes, but slightly reducing normal
|
||||
* stereo quality. Disabling phase inversion in the decoder does not comply
|
||||
* with RFC 6716, although it does not cause any interoperability issue and
|
||||
* is expected to become part of the Opus standard once RFC 6716 is updated
|
||||
* by draft-ietf-codec-opus-update.
|
||||
* @see OPUS_GET_PHASE_INVERSION_DISABLED
|
||||
* @param[in] x <tt>opus_int32</tt>: Allowed values:
|
||||
* <dl>
|
||||
* <dt>0</dt><dd>Enable phase inversion (default).</dd>
|
||||
* <dt>1</dt><dd>Disable phase inversion.</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_SET_PHASE_INVERSION_DISABLED(x) OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST, __opus_check_int(x)
|
||||
/** Gets the encoder's configured phase inversion status.
|
||||
* @see OPUS_SET_PHASE_INVERSION_DISABLED
|
||||
* @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
|
||||
* <dl>
|
||||
* <dt>0</dt><dd>Stereo phase inversion enabled (default).</dd>
|
||||
* <dt>1</dt><dd>Stereo phase inversion disabled.</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_PHASE_INVERSION_DISABLED(x) OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST, __opus_check_int_ptr(x)
|
||||
/** Gets the DTX state of the encoder.
|
||||
* Returns whether the last encoded frame was either a comfort noise update
|
||||
* during DTX or not encoded because of DTX.
|
||||
* @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
|
||||
* <dl>
|
||||
* <dt>0</dt><dd>The encoder is not in DTX.</dd>
|
||||
* <dt>1</dt><dd>The encoder is in DTX.</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_IN_DTX(x) OPUS_GET_IN_DTX_REQUEST, __opus_check_int_ptr(x)
|
||||
|
||||
/**@}*/
|
||||
|
||||
/** @defgroup opus_decoderctls Decoder related CTLs
|
||||
* @see opus_genericctls, opus_encoderctls, opus_decoder
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** Configures decoder gain adjustment.
|
||||
* Scales the decoded output by a factor specified in Q8 dB units.
|
||||
* This has a maximum range of -32768 to 32767 inclusive, and returns
|
||||
* OPUS_BAD_ARG otherwise. The default is zero indicating no adjustment.
|
||||
* This setting survives decoder reset.
|
||||
*
|
||||
* gain = pow(10, x/(20.0*256))
|
||||
*
|
||||
* @param[in] x <tt>opus_int32</tt>: Amount to scale PCM signal by in Q8 dB units.
|
||||
* @hideinitializer */
|
||||
#define OPUS_SET_GAIN(x) OPUS_SET_GAIN_REQUEST, __opus_check_int(x)
|
||||
/** Gets the decoder's configured gain adjustment. @see OPUS_SET_GAIN
|
||||
*
|
||||
* @param[out] x <tt>opus_int32 *</tt>: Amount to scale PCM signal by in Q8 dB units.
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_GAIN(x) OPUS_GET_GAIN_REQUEST, __opus_check_int_ptr(x)
|
||||
|
||||
/** Gets the duration (in samples) of the last packet successfully decoded or concealed.
|
||||
* @param[out] x <tt>opus_int32 *</tt>: Number of samples (at current sampling rate).
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_LAST_PACKET_DURATION(x) OPUS_GET_LAST_PACKET_DURATION_REQUEST, __opus_check_int_ptr(x)
|
||||
|
||||
/** Gets the pitch of the last decoded frame, if available.
|
||||
* This can be used for any post-processing algorithm requiring the use of pitch,
|
||||
* e.g. time stretching/shortening. If the last frame was not voiced, or if the
|
||||
* pitch was not coded in the frame, then zero is returned.
|
||||
*
|
||||
* This CTL is only implemented for decoder instances.
|
||||
*
|
||||
* @param[out] x <tt>opus_int32 *</tt>: pitch period at 48 kHz (or 0 if not available)
|
||||
*
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_PITCH(x) OPUS_GET_PITCH_REQUEST, __opus_check_int_ptr(x)
|
||||
|
||||
/**@}*/
|
||||
|
||||
/** @defgroup opus_libinfo Opus library information functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** Converts an opus error code into a human readable string.
|
||||
*
|
||||
* @param[in] error <tt>int</tt>: Error number
|
||||
* @returns Error string
|
||||
*/
|
||||
OPUS_EXPORT const char *opus_strerror(int error);
|
||||
|
||||
/** Gets the libopus version string.
|
||||
*
|
||||
* Applications may look for the substring "-fixed" in the version string to
|
||||
* determine whether they have a fixed-point or floating-point build at
|
||||
* runtime.
|
||||
*
|
||||
* @returns Version string
|
||||
*/
|
||||
OPUS_EXPORT const char *opus_get_version_string(void);
|
||||
/**@}*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* OPUS_DEFINES_H */
|
660
pkg/codec/opus/include/opus_multistream.h
Normal file
660
pkg/codec/opus/include/opus_multistream.h
Normal file
@@ -0,0 +1,660 @@
|
||||
/* Copyright (c) 2011 Xiph.Org Foundation
|
||||
Written by Jean-Marc Valin */
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file opus_multistream.h
|
||||
* @brief Opus reference implementation multistream API
|
||||
*/
|
||||
|
||||
#ifndef OPUS_MULTISTREAM_H
|
||||
#define OPUS_MULTISTREAM_H
|
||||
|
||||
#include "opus.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @cond OPUS_INTERNAL_DOC */
|
||||
|
||||
/** Macros to trigger compilation errors when the wrong types are provided to a
|
||||
* CTL. */
|
||||
/**@{*/
|
||||
#define __opus_check_encstate_ptr(ptr) ((ptr) + ((ptr) - (OpusEncoder**)(ptr)))
|
||||
#define __opus_check_decstate_ptr(ptr) ((ptr) + ((ptr) - (OpusDecoder**)(ptr)))
|
||||
/**@}*/
|
||||
|
||||
/** These are the actual encoder and decoder CTL ID numbers.
|
||||
* They should not be used directly by applications.
|
||||
* In general, SETs should be even and GETs should be odd.*/
|
||||
/**@{*/
|
||||
#define OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST 5120
|
||||
#define OPUS_MULTISTREAM_GET_DECODER_STATE_REQUEST 5122
|
||||
/**@}*/
|
||||
|
||||
/** @endcond */
|
||||
|
||||
/** @defgroup opus_multistream_ctls Multistream specific encoder and decoder CTLs
|
||||
*
|
||||
* These are convenience macros that are specific to the
|
||||
* opus_multistream_encoder_ctl() and opus_multistream_decoder_ctl()
|
||||
* interface.
|
||||
* The CTLs from @ref opus_genericctls, @ref opus_encoderctls, and
|
||||
* @ref opus_decoderctls may be applied to a multistream encoder or decoder as
|
||||
* well.
|
||||
* In addition, you may retrieve the encoder or decoder state for an specific
|
||||
* stream via #OPUS_MULTISTREAM_GET_ENCODER_STATE or
|
||||
* #OPUS_MULTISTREAM_GET_DECODER_STATE and apply CTLs to it individually.
|
||||
*/
|
||||
/**@{*/
|
||||
|
||||
/** Gets the encoder state for an individual stream of a multistream encoder.
|
||||
* @param[in] x <tt>opus_int32</tt>: The index of the stream whose encoder you
|
||||
* wish to retrieve.
|
||||
* This must be non-negative and less than
|
||||
* the <code>streams</code> parameter used
|
||||
* to initialize the encoder.
|
||||
* @param[out] y <tt>OpusEncoder**</tt>: Returns a pointer to the given
|
||||
* encoder state.
|
||||
* @retval OPUS_BAD_ARG The index of the requested stream was out of range.
|
||||
* @hideinitializer
|
||||
*/
|
||||
#define OPUS_MULTISTREAM_GET_ENCODER_STATE(x,y) OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST, __opus_check_int(x), __opus_check_encstate_ptr(y)
|
||||
|
||||
/** Gets the decoder state for an individual stream of a multistream decoder.
|
||||
* @param[in] x <tt>opus_int32</tt>: The index of the stream whose decoder you
|
||||
* wish to retrieve.
|
||||
* This must be non-negative and less than
|
||||
* the <code>streams</code> parameter used
|
||||
* to initialize the decoder.
|
||||
* @param[out] y <tt>OpusDecoder**</tt>: Returns a pointer to the given
|
||||
* decoder state.
|
||||
* @retval OPUS_BAD_ARG The index of the requested stream was out of range.
|
||||
* @hideinitializer
|
||||
*/
|
||||
#define OPUS_MULTISTREAM_GET_DECODER_STATE(x,y) OPUS_MULTISTREAM_GET_DECODER_STATE_REQUEST, __opus_check_int(x), __opus_check_decstate_ptr(y)
|
||||
|
||||
/**@}*/
|
||||
|
||||
/** @defgroup opus_multistream Opus Multistream API
|
||||
* @{
|
||||
*
|
||||
* The multistream API allows individual Opus streams to be combined into a
|
||||
* single packet, enabling support for up to 255 channels. Unlike an
|
||||
* elementary Opus stream, the encoder and decoder must negotiate the channel
|
||||
* configuration before the decoder can successfully interpret the data in the
|
||||
* packets produced by the encoder. Some basic information, such as packet
|
||||
* duration, can be computed without any special negotiation.
|
||||
*
|
||||
* The format for multistream Opus packets is defined in
|
||||
* <a href="https://tools.ietf.org/html/rfc7845">RFC 7845</a>
|
||||
* and is based on the self-delimited Opus framing described in Appendix B of
|
||||
* <a href="https://tools.ietf.org/html/rfc6716">RFC 6716</a>.
|
||||
* Normal Opus packets are just a degenerate case of multistream Opus packets,
|
||||
* and can be encoded or decoded with the multistream API by setting
|
||||
* <code>streams</code> to <code>1</code> when initializing the encoder or
|
||||
* decoder.
|
||||
*
|
||||
* Multistream Opus streams can contain up to 255 elementary Opus streams.
|
||||
* These may be either "uncoupled" or "coupled", indicating that the decoder
|
||||
* is configured to decode them to either 1 or 2 channels, respectively.
|
||||
* The streams are ordered so that all coupled streams appear at the
|
||||
* beginning.
|
||||
*
|
||||
* A <code>mapping</code> table defines which decoded channel <code>i</code>
|
||||
* should be used for each input/output (I/O) channel <code>j</code>. This table is
|
||||
* typically provided as an unsigned char array.
|
||||
* Let <code>i = mapping[j]</code> be the index for I/O channel <code>j</code>.
|
||||
* If <code>i < 2*coupled_streams</code>, then I/O channel <code>j</code> is
|
||||
* encoded as the left channel of stream <code>(i/2)</code> if <code>i</code>
|
||||
* is even, or as the right channel of stream <code>(i/2)</code> if
|
||||
* <code>i</code> is odd. Otherwise, I/O channel <code>j</code> is encoded as
|
||||
* mono in stream <code>(i - coupled_streams)</code>, unless it has the special
|
||||
* value 255, in which case it is omitted from the encoding entirely (the
|
||||
* decoder will reproduce it as silence). Each value <code>i</code> must either
|
||||
* be the special value 255 or be less than <code>streams + coupled_streams</code>.
|
||||
*
|
||||
* The output channels specified by the encoder
|
||||
* should use the
|
||||
* <a href="https://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-810004.3.9">Vorbis
|
||||
* channel ordering</a>. A decoder may wish to apply an additional permutation
|
||||
* to the mapping the encoder used to achieve a different output channel
|
||||
* order (e.g. for outputing in WAV order).
|
||||
*
|
||||
* Each multistream packet contains an Opus packet for each stream, and all of
|
||||
* the Opus packets in a single multistream packet must have the same
|
||||
* duration. Therefore the duration of a multistream packet can be extracted
|
||||
* from the TOC sequence of the first stream, which is located at the
|
||||
* beginning of the packet, just like an elementary Opus stream:
|
||||
*
|
||||
* @code
|
||||
* int nb_samples;
|
||||
* int nb_frames;
|
||||
* nb_frames = opus_packet_get_nb_frames(data, len);
|
||||
* if (nb_frames < 1)
|
||||
* return nb_frames;
|
||||
* nb_samples = opus_packet_get_samples_per_frame(data, 48000) * nb_frames;
|
||||
* @endcode
|
||||
*
|
||||
* The general encoding and decoding process proceeds exactly the same as in
|
||||
* the normal @ref opus_encoder and @ref opus_decoder APIs.
|
||||
* See their documentation for an overview of how to use the corresponding
|
||||
* multistream functions.
|
||||
*/
|
||||
|
||||
/** Opus multistream encoder state.
|
||||
* This contains the complete state of a multistream Opus encoder.
|
||||
* It is position independent and can be freely copied.
|
||||
* @see opus_multistream_encoder_create
|
||||
* @see opus_multistream_encoder_init
|
||||
*/
|
||||
typedef struct OpusMSEncoder OpusMSEncoder;
|
||||
|
||||
/** Opus multistream decoder state.
|
||||
* This contains the complete state of a multistream Opus decoder.
|
||||
* It is position independent and can be freely copied.
|
||||
* @see opus_multistream_decoder_create
|
||||
* @see opus_multistream_decoder_init
|
||||
*/
|
||||
typedef struct OpusMSDecoder OpusMSDecoder;
|
||||
|
||||
/**\name Multistream encoder functions */
|
||||
/**@{*/
|
||||
|
||||
/** Gets the size of an OpusMSEncoder structure.
|
||||
* @param streams <tt>int</tt>: The total number of streams to encode from the
|
||||
* input.
|
||||
* This must be no more than 255.
|
||||
* @param coupled_streams <tt>int</tt>: Number of coupled (2 channel) streams
|
||||
* to encode.
|
||||
* This must be no larger than the total
|
||||
* number of streams.
|
||||
* Additionally, The total number of
|
||||
* encoded channels (<code>streams +
|
||||
* coupled_streams</code>) must be no
|
||||
* more than 255.
|
||||
* @returns The size in bytes on success, or a negative error code
|
||||
* (see @ref opus_errorcodes) on error.
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_multistream_encoder_get_size(
|
||||
int streams,
|
||||
int coupled_streams
|
||||
);
|
||||
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_multistream_surround_encoder_get_size(
|
||||
int channels,
|
||||
int mapping_family
|
||||
);
|
||||
|
||||
|
||||
/** Allocates and initializes a multistream encoder state.
|
||||
* Call opus_multistream_encoder_destroy() to release
|
||||
* this object when finished.
|
||||
* @param Fs <tt>opus_int32</tt>: Sampling rate of the input signal (in Hz).
|
||||
* This must be one of 8000, 12000, 16000,
|
||||
* 24000, or 48000.
|
||||
* @param channels <tt>int</tt>: Number of channels in the input signal.
|
||||
* This must be at most 255.
|
||||
* It may be greater than the number of
|
||||
* coded channels (<code>streams +
|
||||
* coupled_streams</code>).
|
||||
* @param streams <tt>int</tt>: The total number of streams to encode from the
|
||||
* input.
|
||||
* This must be no more than the number of channels.
|
||||
* @param coupled_streams <tt>int</tt>: Number of coupled (2 channel) streams
|
||||
* to encode.
|
||||
* This must be no larger than the total
|
||||
* number of streams.
|
||||
* Additionally, The total number of
|
||||
* encoded channels (<code>streams +
|
||||
* coupled_streams</code>) must be no
|
||||
* more than the number of input channels.
|
||||
* @param[in] mapping <code>const unsigned char[channels]</code>: Mapping from
|
||||
* encoded channels to input channels, as described in
|
||||
* @ref opus_multistream. As an extra constraint, the
|
||||
* multistream encoder does not allow encoding coupled
|
||||
* streams for which one channel is unused since this
|
||||
* is never a good idea.
|
||||
* @param application <tt>int</tt>: The target encoder application.
|
||||
* This must be one of the following:
|
||||
* <dl>
|
||||
* <dt>#OPUS_APPLICATION_VOIP</dt>
|
||||
* <dd>Process signal for improved speech intelligibility.</dd>
|
||||
* <dt>#OPUS_APPLICATION_AUDIO</dt>
|
||||
* <dd>Favor faithfulness to the original input.</dd>
|
||||
* <dt>#OPUS_APPLICATION_RESTRICTED_LOWDELAY</dt>
|
||||
* <dd>Configure the minimum possible coding delay by disabling certain modes
|
||||
* of operation.</dd>
|
||||
* </dl>
|
||||
* @param[out] error <tt>int *</tt>: Returns #OPUS_OK on success, or an error
|
||||
* code (see @ref opus_errorcodes) on
|
||||
* failure.
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusMSEncoder *opus_multistream_encoder_create(
|
||||
opus_int32 Fs,
|
||||
int channels,
|
||||
int streams,
|
||||
int coupled_streams,
|
||||
const unsigned char *mapping,
|
||||
int application,
|
||||
int *error
|
||||
) OPUS_ARG_NONNULL(5);
|
||||
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusMSEncoder *opus_multistream_surround_encoder_create(
|
||||
opus_int32 Fs,
|
||||
int channels,
|
||||
int mapping_family,
|
||||
int *streams,
|
||||
int *coupled_streams,
|
||||
unsigned char *mapping,
|
||||
int application,
|
||||
int *error
|
||||
) OPUS_ARG_NONNULL(4) OPUS_ARG_NONNULL(5) OPUS_ARG_NONNULL(6);
|
||||
|
||||
/** Initialize a previously allocated multistream encoder state.
|
||||
* The memory pointed to by \a st must be at least the size returned by
|
||||
* opus_multistream_encoder_get_size().
|
||||
* This is intended for applications which use their own allocator instead of
|
||||
* malloc.
|
||||
* To reset a previously initialized state, use the #OPUS_RESET_STATE CTL.
|
||||
* @see opus_multistream_encoder_create
|
||||
* @see opus_multistream_encoder_get_size
|
||||
* @param st <tt>OpusMSEncoder*</tt>: Multistream encoder state to initialize.
|
||||
* @param Fs <tt>opus_int32</tt>: Sampling rate of the input signal (in Hz).
|
||||
* This must be one of 8000, 12000, 16000,
|
||||
* 24000, or 48000.
|
||||
* @param channels <tt>int</tt>: Number of channels in the input signal.
|
||||
* This must be at most 255.
|
||||
* It may be greater than the number of
|
||||
* coded channels (<code>streams +
|
||||
* coupled_streams</code>).
|
||||
* @param streams <tt>int</tt>: The total number of streams to encode from the
|
||||
* input.
|
||||
* This must be no more than the number of channels.
|
||||
* @param coupled_streams <tt>int</tt>: Number of coupled (2 channel) streams
|
||||
* to encode.
|
||||
* This must be no larger than the total
|
||||
* number of streams.
|
||||
* Additionally, The total number of
|
||||
* encoded channels (<code>streams +
|
||||
* coupled_streams</code>) must be no
|
||||
* more than the number of input channels.
|
||||
* @param[in] mapping <code>const unsigned char[channels]</code>: Mapping from
|
||||
* encoded channels to input channels, as described in
|
||||
* @ref opus_multistream. As an extra constraint, the
|
||||
* multistream encoder does not allow encoding coupled
|
||||
* streams for which one channel is unused since this
|
||||
* is never a good idea.
|
||||
* @param application <tt>int</tt>: The target encoder application.
|
||||
* This must be one of the following:
|
||||
* <dl>
|
||||
* <dt>#OPUS_APPLICATION_VOIP</dt>
|
||||
* <dd>Process signal for improved speech intelligibility.</dd>
|
||||
* <dt>#OPUS_APPLICATION_AUDIO</dt>
|
||||
* <dd>Favor faithfulness to the original input.</dd>
|
||||
* <dt>#OPUS_APPLICATION_RESTRICTED_LOWDELAY</dt>
|
||||
* <dd>Configure the minimum possible coding delay by disabling certain modes
|
||||
* of operation.</dd>
|
||||
* </dl>
|
||||
* @returns #OPUS_OK on success, or an error code (see @ref opus_errorcodes)
|
||||
* on failure.
|
||||
*/
|
||||
OPUS_EXPORT int opus_multistream_encoder_init(
|
||||
OpusMSEncoder *st,
|
||||
opus_int32 Fs,
|
||||
int channels,
|
||||
int streams,
|
||||
int coupled_streams,
|
||||
const unsigned char *mapping,
|
||||
int application
|
||||
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(6);
|
||||
|
||||
OPUS_EXPORT int opus_multistream_surround_encoder_init(
|
||||
OpusMSEncoder *st,
|
||||
opus_int32 Fs,
|
||||
int channels,
|
||||
int mapping_family,
|
||||
int *streams,
|
||||
int *coupled_streams,
|
||||
unsigned char *mapping,
|
||||
int application
|
||||
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(5) OPUS_ARG_NONNULL(6) OPUS_ARG_NONNULL(7);
|
||||
|
||||
/** Encodes a multistream Opus frame.
|
||||
* @param st <tt>OpusMSEncoder*</tt>: Multistream encoder state.
|
||||
* @param[in] pcm <tt>const opus_int16*</tt>: The input signal as interleaved
|
||||
* samples.
|
||||
* This must contain
|
||||
* <code>frame_size*channels</code>
|
||||
* samples.
|
||||
* @param frame_size <tt>int</tt>: Number of samples per channel in the input
|
||||
* signal.
|
||||
* This must be an Opus frame size for the
|
||||
* encoder's sampling rate.
|
||||
* For example, at 48 kHz the permitted values
|
||||
* are 120, 240, 480, 960, 1920, and 2880.
|
||||
* Passing in a duration of less than 10 ms
|
||||
* (480 samples at 48 kHz) will prevent the
|
||||
* encoder from using the LPC or hybrid modes.
|
||||
* @param[out] data <tt>unsigned char*</tt>: Output payload.
|
||||
* This must contain storage for at
|
||||
* least \a max_data_bytes.
|
||||
* @param [in] max_data_bytes <tt>opus_int32</tt>: Size of the allocated
|
||||
* memory for the output
|
||||
* payload. This may be
|
||||
* used to impose an upper limit on
|
||||
* the instant bitrate, but should
|
||||
* not be used as the only bitrate
|
||||
* control. Use #OPUS_SET_BITRATE to
|
||||
* control the bitrate.
|
||||
* @returns The length of the encoded packet (in bytes) on success or a
|
||||
* negative error code (see @ref opus_errorcodes) on failure.
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_multistream_encode(
|
||||
OpusMSEncoder *st,
|
||||
const opus_int16 *pcm,
|
||||
int frame_size,
|
||||
unsigned char *data,
|
||||
opus_int32 max_data_bytes
|
||||
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
|
||||
|
||||
/** Encodes a multistream Opus frame from floating point input.
|
||||
* @param st <tt>OpusMSEncoder*</tt>: Multistream encoder state.
|
||||
* @param[in] pcm <tt>const float*</tt>: The input signal as interleaved
|
||||
* samples with a normal range of
|
||||
* +/-1.0.
|
||||
* Samples with a range beyond +/-1.0
|
||||
* are supported but will be clipped by
|
||||
* decoders using the integer API and
|
||||
* should only be used if it is known
|
||||
* that the far end supports extended
|
||||
* dynamic range.
|
||||
* This must contain
|
||||
* <code>frame_size*channels</code>
|
||||
* samples.
|
||||
* @param frame_size <tt>int</tt>: Number of samples per channel in the input
|
||||
* signal.
|
||||
* This must be an Opus frame size for the
|
||||
* encoder's sampling rate.
|
||||
* For example, at 48 kHz the permitted values
|
||||
* are 120, 240, 480, 960, 1920, and 2880.
|
||||
* Passing in a duration of less than 10 ms
|
||||
* (480 samples at 48 kHz) will prevent the
|
||||
* encoder from using the LPC or hybrid modes.
|
||||
* @param[out] data <tt>unsigned char*</tt>: Output payload.
|
||||
* This must contain storage for at
|
||||
* least \a max_data_bytes.
|
||||
* @param [in] max_data_bytes <tt>opus_int32</tt>: Size of the allocated
|
||||
* memory for the output
|
||||
* payload. This may be
|
||||
* used to impose an upper limit on
|
||||
* the instant bitrate, but should
|
||||
* not be used as the only bitrate
|
||||
* control. Use #OPUS_SET_BITRATE to
|
||||
* control the bitrate.
|
||||
* @returns The length of the encoded packet (in bytes) on success or a
|
||||
* negative error code (see @ref opus_errorcodes) on failure.
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_multistream_encode_float(
|
||||
OpusMSEncoder *st,
|
||||
const float *pcm,
|
||||
int frame_size,
|
||||
unsigned char *data,
|
||||
opus_int32 max_data_bytes
|
||||
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
|
||||
|
||||
/** Frees an <code>OpusMSEncoder</code> allocated by
|
||||
* opus_multistream_encoder_create().
|
||||
* @param st <tt>OpusMSEncoder*</tt>: Multistream encoder state to be freed.
|
||||
*/
|
||||
OPUS_EXPORT void opus_multistream_encoder_destroy(OpusMSEncoder *st);
|
||||
|
||||
/** Perform a CTL function on a multistream Opus encoder.
|
||||
*
|
||||
* Generally the request and subsequent arguments are generated by a
|
||||
* convenience macro.
|
||||
* @param st <tt>OpusMSEncoder*</tt>: Multistream encoder state.
|
||||
* @param request This and all remaining parameters should be replaced by one
|
||||
* of the convenience macros in @ref opus_genericctls,
|
||||
* @ref opus_encoderctls, or @ref opus_multistream_ctls.
|
||||
* @see opus_genericctls
|
||||
* @see opus_encoderctls
|
||||
* @see opus_multistream_ctls
|
||||
*/
|
||||
OPUS_EXPORT int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...) OPUS_ARG_NONNULL(1);
|
||||
|
||||
/**@}*/
|
||||
|
||||
/**\name Multistream decoder functions */
|
||||
/**@{*/
|
||||
|
||||
/** Gets the size of an <code>OpusMSDecoder</code> structure.
|
||||
* @param streams <tt>int</tt>: The total number of streams coded in the
|
||||
* input.
|
||||
* This must be no more than 255.
|
||||
* @param coupled_streams <tt>int</tt>: Number streams to decode as coupled
|
||||
* (2 channel) streams.
|
||||
* This must be no larger than the total
|
||||
* number of streams.
|
||||
* Additionally, The total number of
|
||||
* coded channels (<code>streams +
|
||||
* coupled_streams</code>) must be no
|
||||
* more than 255.
|
||||
* @returns The size in bytes on success, or a negative error code
|
||||
* (see @ref opus_errorcodes) on error.
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_multistream_decoder_get_size(
|
||||
int streams,
|
||||
int coupled_streams
|
||||
);
|
||||
|
||||
/** Allocates and initializes a multistream decoder state.
|
||||
* Call opus_multistream_decoder_destroy() to release
|
||||
* this object when finished.
|
||||
* @param Fs <tt>opus_int32</tt>: Sampling rate to decode at (in Hz).
|
||||
* This must be one of 8000, 12000, 16000,
|
||||
* 24000, or 48000.
|
||||
* @param channels <tt>int</tt>: Number of channels to output.
|
||||
* This must be at most 255.
|
||||
* It may be different from the number of coded
|
||||
* channels (<code>streams +
|
||||
* coupled_streams</code>).
|
||||
* @param streams <tt>int</tt>: The total number of streams coded in the
|
||||
* input.
|
||||
* This must be no more than 255.
|
||||
* @param coupled_streams <tt>int</tt>: Number of streams to decode as coupled
|
||||
* (2 channel) streams.
|
||||
* This must be no larger than the total
|
||||
* number of streams.
|
||||
* Additionally, The total number of
|
||||
* coded channels (<code>streams +
|
||||
* coupled_streams</code>) must be no
|
||||
* more than 255.
|
||||
* @param[in] mapping <code>const unsigned char[channels]</code>: Mapping from
|
||||
* coded channels to output channels, as described in
|
||||
* @ref opus_multistream.
|
||||
* @param[out] error <tt>int *</tt>: Returns #OPUS_OK on success, or an error
|
||||
* code (see @ref opus_errorcodes) on
|
||||
* failure.
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusMSDecoder *opus_multistream_decoder_create(
|
||||
opus_int32 Fs,
|
||||
int channels,
|
||||
int streams,
|
||||
int coupled_streams,
|
||||
const unsigned char *mapping,
|
||||
int *error
|
||||
) OPUS_ARG_NONNULL(5);
|
||||
|
||||
/** Intialize a previously allocated decoder state object.
|
||||
* The memory pointed to by \a st must be at least the size returned by
|
||||
* opus_multistream_encoder_get_size().
|
||||
* This is intended for applications which use their own allocator instead of
|
||||
* malloc.
|
||||
* To reset a previously initialized state, use the #OPUS_RESET_STATE CTL.
|
||||
* @see opus_multistream_decoder_create
|
||||
* @see opus_multistream_deocder_get_size
|
||||
* @param st <tt>OpusMSEncoder*</tt>: Multistream encoder state to initialize.
|
||||
* @param Fs <tt>opus_int32</tt>: Sampling rate to decode at (in Hz).
|
||||
* This must be one of 8000, 12000, 16000,
|
||||
* 24000, or 48000.
|
||||
* @param channels <tt>int</tt>: Number of channels to output.
|
||||
* This must be at most 255.
|
||||
* It may be different from the number of coded
|
||||
* channels (<code>streams +
|
||||
* coupled_streams</code>).
|
||||
* @param streams <tt>int</tt>: The total number of streams coded in the
|
||||
* input.
|
||||
* This must be no more than 255.
|
||||
* @param coupled_streams <tt>int</tt>: Number of streams to decode as coupled
|
||||
* (2 channel) streams.
|
||||
* This must be no larger than the total
|
||||
* number of streams.
|
||||
* Additionally, The total number of
|
||||
* coded channels (<code>streams +
|
||||
* coupled_streams</code>) must be no
|
||||
* more than 255.
|
||||
* @param[in] mapping <code>const unsigned char[channels]</code>: Mapping from
|
||||
* coded channels to output channels, as described in
|
||||
* @ref opus_multistream.
|
||||
* @returns #OPUS_OK on success, or an error code (see @ref opus_errorcodes)
|
||||
* on failure.
|
||||
*/
|
||||
OPUS_EXPORT int opus_multistream_decoder_init(
|
||||
OpusMSDecoder *st,
|
||||
opus_int32 Fs,
|
||||
int channels,
|
||||
int streams,
|
||||
int coupled_streams,
|
||||
const unsigned char *mapping
|
||||
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(6);
|
||||
|
||||
/** Decode a multistream Opus packet.
|
||||
* @param st <tt>OpusMSDecoder*</tt>: Multistream decoder state.
|
||||
* @param[in] data <tt>const unsigned char*</tt>: Input payload.
|
||||
* Use a <code>NULL</code>
|
||||
* pointer to indicate packet
|
||||
* loss.
|
||||
* @param len <tt>opus_int32</tt>: Number of bytes in payload.
|
||||
* @param[out] pcm <tt>opus_int16*</tt>: Output signal, with interleaved
|
||||
* samples.
|
||||
* This must contain room for
|
||||
* <code>frame_size*channels</code>
|
||||
* samples.
|
||||
* @param frame_size <tt>int</tt>: The number of samples per channel of
|
||||
* available space in \a pcm.
|
||||
* If this is less than the maximum packet duration
|
||||
* (120 ms; 5760 for 48kHz), this function will not be capable
|
||||
* of decoding some packets. In the case of PLC (data==NULL)
|
||||
* or FEC (decode_fec=1), then frame_size needs to be exactly
|
||||
* the duration of audio that is missing, otherwise the
|
||||
* decoder will not be in the optimal state to decode the
|
||||
* next incoming packet. For the PLC and FEC cases, frame_size
|
||||
* <b>must</b> be a multiple of 2.5 ms.
|
||||
* @param decode_fec <tt>int</tt>: Flag (0 or 1) to request that any in-band
|
||||
* forward error correction data be decoded.
|
||||
* If no such data is available, the frame is
|
||||
* decoded as if it were lost.
|
||||
* @returns Number of samples decoded on success or a negative error code
|
||||
* (see @ref opus_errorcodes) on failure.
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_multistream_decode(
|
||||
OpusMSDecoder *st,
|
||||
const unsigned char *data,
|
||||
opus_int32 len,
|
||||
opus_int16 *pcm,
|
||||
int frame_size,
|
||||
int decode_fec
|
||||
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
|
||||
|
||||
/** Decode a multistream Opus packet with floating point output.
|
||||
* @param st <tt>OpusMSDecoder*</tt>: Multistream decoder state.
|
||||
* @param[in] data <tt>const unsigned char*</tt>: Input payload.
|
||||
* Use a <code>NULL</code>
|
||||
* pointer to indicate packet
|
||||
* loss.
|
||||
* @param len <tt>opus_int32</tt>: Number of bytes in payload.
|
||||
* @param[out] pcm <tt>opus_int16*</tt>: Output signal, with interleaved
|
||||
* samples.
|
||||
* This must contain room for
|
||||
* <code>frame_size*channels</code>
|
||||
* samples.
|
||||
* @param frame_size <tt>int</tt>: The number of samples per channel of
|
||||
* available space in \a pcm.
|
||||
* If this is less than the maximum packet duration
|
||||
* (120 ms; 5760 for 48kHz), this function will not be capable
|
||||
* of decoding some packets. In the case of PLC (data==NULL)
|
||||
* or FEC (decode_fec=1), then frame_size needs to be exactly
|
||||
* the duration of audio that is missing, otherwise the
|
||||
* decoder will not be in the optimal state to decode the
|
||||
* next incoming packet. For the PLC and FEC cases, frame_size
|
||||
* <b>must</b> be a multiple of 2.5 ms.
|
||||
* @param decode_fec <tt>int</tt>: Flag (0 or 1) to request that any in-band
|
||||
* forward error correction data be decoded.
|
||||
* If no such data is available, the frame is
|
||||
* decoded as if it were lost.
|
||||
* @returns Number of samples decoded on success or a negative error code
|
||||
* (see @ref opus_errorcodes) on failure.
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_multistream_decode_float(
|
||||
OpusMSDecoder *st,
|
||||
const unsigned char *data,
|
||||
opus_int32 len,
|
||||
float *pcm,
|
||||
int frame_size,
|
||||
int decode_fec
|
||||
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
|
||||
|
||||
/** Perform a CTL function on a multistream Opus decoder.
|
||||
*
|
||||
* Generally the request and subsequent arguments are generated by a
|
||||
* convenience macro.
|
||||
* @param st <tt>OpusMSDecoder*</tt>: Multistream decoder state.
|
||||
* @param request This and all remaining parameters should be replaced by one
|
||||
* of the convenience macros in @ref opus_genericctls,
|
||||
* @ref opus_decoderctls, or @ref opus_multistream_ctls.
|
||||
* @see opus_genericctls
|
||||
* @see opus_decoderctls
|
||||
* @see opus_multistream_ctls
|
||||
*/
|
||||
OPUS_EXPORT int opus_multistream_decoder_ctl(OpusMSDecoder *st, int request, ...) OPUS_ARG_NONNULL(1);
|
||||
|
||||
/** Frees an <code>OpusMSDecoder</code> allocated by
|
||||
* opus_multistream_decoder_create().
|
||||
* @param st <tt>OpusMSDecoder</tt>: Multistream decoder state to be freed.
|
||||
*/
|
||||
OPUS_EXPORT void opus_multistream_decoder_destroy(OpusMSDecoder *st);
|
||||
|
||||
/**@}*/
|
||||
|
||||
/**@}*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* OPUS_MULTISTREAM_H */
|
568
pkg/codec/opus/include/opus_projection.h
Normal file
568
pkg/codec/opus/include/opus_projection.h
Normal file
@@ -0,0 +1,568 @@
|
||||
/* Copyright (c) 2017 Google Inc.
|
||||
Written by Andrew Allen */
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file opus_projection.h
|
||||
* @brief Opus projection reference API
|
||||
*/
|
||||
|
||||
#ifndef OPUS_PROJECTION_H
|
||||
#define OPUS_PROJECTION_H
|
||||
|
||||
#include "opus_multistream.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @cond OPUS_INTERNAL_DOC */
|
||||
|
||||
/** These are the actual encoder and decoder CTL ID numbers.
|
||||
* They should not be used directly by applications.c
|
||||
* In general, SETs should be even and GETs should be odd.*/
|
||||
/**@{*/
|
||||
#define OPUS_PROJECTION_GET_DEMIXING_MATRIX_GAIN_REQUEST 6001
|
||||
#define OPUS_PROJECTION_GET_DEMIXING_MATRIX_SIZE_REQUEST 6003
|
||||
#define OPUS_PROJECTION_GET_DEMIXING_MATRIX_REQUEST 6005
|
||||
/**@}*/
|
||||
|
||||
|
||||
/** @endcond */
|
||||
|
||||
/** @defgroup opus_projection_ctls Projection specific encoder and decoder CTLs
|
||||
*
|
||||
* These are convenience macros that are specific to the
|
||||
* opus_projection_encoder_ctl() and opus_projection_decoder_ctl()
|
||||
* interface.
|
||||
* The CTLs from @ref opus_genericctls, @ref opus_encoderctls,
|
||||
* @ref opus_decoderctls, and @ref opus_multistream_ctls may be applied to a
|
||||
* projection encoder or decoder as well.
|
||||
*/
|
||||
/**@{*/
|
||||
|
||||
/** Gets the gain (in dB. S7.8-format) of the demixing matrix from the encoder.
|
||||
* @param[out] x <tt>opus_int32 *</tt>: Returns the gain (in dB. S7.8-format)
|
||||
* of the demixing matrix.
|
||||
* @hideinitializer
|
||||
*/
|
||||
#define OPUS_PROJECTION_GET_DEMIXING_MATRIX_GAIN(x) OPUS_PROJECTION_GET_DEMIXING_MATRIX_GAIN_REQUEST, __opus_check_int_ptr(x)
|
||||
|
||||
|
||||
/** Gets the size in bytes of the demixing matrix from the encoder.
|
||||
* @param[out] x <tt>opus_int32 *</tt>: Returns the size in bytes of the
|
||||
* demixing matrix.
|
||||
* @hideinitializer
|
||||
*/
|
||||
#define OPUS_PROJECTION_GET_DEMIXING_MATRIX_SIZE(x) OPUS_PROJECTION_GET_DEMIXING_MATRIX_SIZE_REQUEST, __opus_check_int_ptr(x)
|
||||
|
||||
|
||||
/** Copies the demixing matrix to the supplied pointer location.
|
||||
* @param[out] x <tt>unsigned char *</tt>: Returns the demixing matrix to the
|
||||
* supplied pointer location.
|
||||
* @param y <tt>opus_int32</tt>: The size in bytes of the reserved memory at the
|
||||
* pointer location.
|
||||
* @hideinitializer
|
||||
*/
|
||||
#define OPUS_PROJECTION_GET_DEMIXING_MATRIX(x,y) OPUS_PROJECTION_GET_DEMIXING_MATRIX_REQUEST, x, __opus_check_int(y)
|
||||
|
||||
|
||||
/**@}*/
|
||||
|
||||
/** Opus projection encoder state.
|
||||
* This contains the complete state of a projection Opus encoder.
|
||||
* It is position independent and can be freely copied.
|
||||
* @see opus_projection_ambisonics_encoder_create
|
||||
*/
|
||||
typedef struct OpusProjectionEncoder OpusProjectionEncoder;
|
||||
|
||||
|
||||
/** Opus projection decoder state.
|
||||
* This contains the complete state of a projection Opus decoder.
|
||||
* It is position independent and can be freely copied.
|
||||
* @see opus_projection_decoder_create
|
||||
* @see opus_projection_decoder_init
|
||||
*/
|
||||
typedef struct OpusProjectionDecoder OpusProjectionDecoder;
|
||||
|
||||
|
||||
/**\name Projection encoder functions */
|
||||
/**@{*/
|
||||
|
||||
/** Gets the size of an OpusProjectionEncoder structure.
|
||||
* @param channels <tt>int</tt>: The total number of input channels to encode.
|
||||
* This must be no more than 255.
|
||||
* @param mapping_family <tt>int</tt>: The mapping family to use for selecting
|
||||
* the appropriate projection.
|
||||
* @returns The size in bytes on success, or a negative error code
|
||||
* (see @ref opus_errorcodes) on error.
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_projection_ambisonics_encoder_get_size(
|
||||
int channels,
|
||||
int mapping_family
|
||||
);
|
||||
|
||||
|
||||
/** Allocates and initializes a projection encoder state.
|
||||
* Call opus_projection_encoder_destroy() to release
|
||||
* this object when finished.
|
||||
* @param Fs <tt>opus_int32</tt>: Sampling rate of the input signal (in Hz).
|
||||
* This must be one of 8000, 12000, 16000,
|
||||
* 24000, or 48000.
|
||||
* @param channels <tt>int</tt>: Number of channels in the input signal.
|
||||
* This must be at most 255.
|
||||
* It may be greater than the number of
|
||||
* coded channels (<code>streams +
|
||||
* coupled_streams</code>).
|
||||
* @param mapping_family <tt>int</tt>: The mapping family to use for selecting
|
||||
* the appropriate projection.
|
||||
* @param[out] streams <tt>int *</tt>: The total number of streams that will
|
||||
* be encoded from the input.
|
||||
* @param[out] coupled_streams <tt>int *</tt>: Number of coupled (2 channel)
|
||||
* streams that will be encoded from the input.
|
||||
* @param application <tt>int</tt>: The target encoder application.
|
||||
* This must be one of the following:
|
||||
* <dl>
|
||||
* <dt>#OPUS_APPLICATION_VOIP</dt>
|
||||
* <dd>Process signal for improved speech intelligibility.</dd>
|
||||
* <dt>#OPUS_APPLICATION_AUDIO</dt>
|
||||
* <dd>Favor faithfulness to the original input.</dd>
|
||||
* <dt>#OPUS_APPLICATION_RESTRICTED_LOWDELAY</dt>
|
||||
* <dd>Configure the minimum possible coding delay by disabling certain modes
|
||||
* of operation.</dd>
|
||||
* </dl>
|
||||
* @param[out] error <tt>int *</tt>: Returns #OPUS_OK on success, or an error
|
||||
* code (see @ref opus_errorcodes) on
|
||||
* failure.
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusProjectionEncoder *opus_projection_ambisonics_encoder_create(
|
||||
opus_int32 Fs,
|
||||
int channels,
|
||||
int mapping_family,
|
||||
int *streams,
|
||||
int *coupled_streams,
|
||||
int application,
|
||||
int *error
|
||||
) OPUS_ARG_NONNULL(4) OPUS_ARG_NONNULL(5);
|
||||
|
||||
|
||||
/** Initialize a previously allocated projection encoder state.
|
||||
* The memory pointed to by \a st must be at least the size returned by
|
||||
* opus_projection_ambisonics_encoder_get_size().
|
||||
* This is intended for applications which use their own allocator instead of
|
||||
* malloc.
|
||||
* To reset a previously initialized state, use the #OPUS_RESET_STATE CTL.
|
||||
* @see opus_projection_ambisonics_encoder_create
|
||||
* @see opus_projection_ambisonics_encoder_get_size
|
||||
* @param st <tt>OpusProjectionEncoder*</tt>: Projection encoder state to initialize.
|
||||
* @param Fs <tt>opus_int32</tt>: Sampling rate of the input signal (in Hz).
|
||||
* This must be one of 8000, 12000, 16000,
|
||||
* 24000, or 48000.
|
||||
* @param channels <tt>int</tt>: Number of channels in the input signal.
|
||||
* This must be at most 255.
|
||||
* It may be greater than the number of
|
||||
* coded channels (<code>streams +
|
||||
* coupled_streams</code>).
|
||||
* @param streams <tt>int</tt>: The total number of streams to encode from the
|
||||
* input.
|
||||
* This must be no more than the number of channels.
|
||||
* @param coupled_streams <tt>int</tt>: Number of coupled (2 channel) streams
|
||||
* to encode.
|
||||
* This must be no larger than the total
|
||||
* number of streams.
|
||||
* Additionally, The total number of
|
||||
* encoded channels (<code>streams +
|
||||
* coupled_streams</code>) must be no
|
||||
* more than the number of input channels.
|
||||
* @param application <tt>int</tt>: The target encoder application.
|
||||
* This must be one of the following:
|
||||
* <dl>
|
||||
* <dt>#OPUS_APPLICATION_VOIP</dt>
|
||||
* <dd>Process signal for improved speech intelligibility.</dd>
|
||||
* <dt>#OPUS_APPLICATION_AUDIO</dt>
|
||||
* <dd>Favor faithfulness to the original input.</dd>
|
||||
* <dt>#OPUS_APPLICATION_RESTRICTED_LOWDELAY</dt>
|
||||
* <dd>Configure the minimum possible coding delay by disabling certain modes
|
||||
* of operation.</dd>
|
||||
* </dl>
|
||||
* @returns #OPUS_OK on success, or an error code (see @ref opus_errorcodes)
|
||||
* on failure.
|
||||
*/
|
||||
OPUS_EXPORT int opus_projection_ambisonics_encoder_init(
|
||||
OpusProjectionEncoder *st,
|
||||
opus_int32 Fs,
|
||||
int channels,
|
||||
int mapping_family,
|
||||
int *streams,
|
||||
int *coupled_streams,
|
||||
int application
|
||||
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(5) OPUS_ARG_NONNULL(6);
|
||||
|
||||
|
||||
/** Encodes a projection Opus frame.
|
||||
* @param st <tt>OpusProjectionEncoder*</tt>: Projection encoder state.
|
||||
* @param[in] pcm <tt>const opus_int16*</tt>: The input signal as interleaved
|
||||
* samples.
|
||||
* This must contain
|
||||
* <code>frame_size*channels</code>
|
||||
* samples.
|
||||
* @param frame_size <tt>int</tt>: Number of samples per channel in the input
|
||||
* signal.
|
||||
* This must be an Opus frame size for the
|
||||
* encoder's sampling rate.
|
||||
* For example, at 48 kHz the permitted values
|
||||
* are 120, 240, 480, 960, 1920, and 2880.
|
||||
* Passing in a duration of less than 10 ms
|
||||
* (480 samples at 48 kHz) will prevent the
|
||||
* encoder from using the LPC or hybrid modes.
|
||||
* @param[out] data <tt>unsigned char*</tt>: Output payload.
|
||||
* This must contain storage for at
|
||||
* least \a max_data_bytes.
|
||||
* @param [in] max_data_bytes <tt>opus_int32</tt>: Size of the allocated
|
||||
* memory for the output
|
||||
* payload. This may be
|
||||
* used to impose an upper limit on
|
||||
* the instant bitrate, but should
|
||||
* not be used as the only bitrate
|
||||
* control. Use #OPUS_SET_BITRATE to
|
||||
* control the bitrate.
|
||||
* @returns The length of the encoded packet (in bytes) on success or a
|
||||
* negative error code (see @ref opus_errorcodes) on failure.
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_projection_encode(
|
||||
OpusProjectionEncoder *st,
|
||||
const opus_int16 *pcm,
|
||||
int frame_size,
|
||||
unsigned char *data,
|
||||
opus_int32 max_data_bytes
|
||||
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
|
||||
|
||||
|
||||
/** Encodes a projection Opus frame from floating point input.
|
||||
* @param st <tt>OpusProjectionEncoder*</tt>: Projection encoder state.
|
||||
* @param[in] pcm <tt>const float*</tt>: The input signal as interleaved
|
||||
* samples with a normal range of
|
||||
* +/-1.0.
|
||||
* Samples with a range beyond +/-1.0
|
||||
* are supported but will be clipped by
|
||||
* decoders using the integer API and
|
||||
* should only be used if it is known
|
||||
* that the far end supports extended
|
||||
* dynamic range.
|
||||
* This must contain
|
||||
* <code>frame_size*channels</code>
|
||||
* samples.
|
||||
* @param frame_size <tt>int</tt>: Number of samples per channel in the input
|
||||
* signal.
|
||||
* This must be an Opus frame size for the
|
||||
* encoder's sampling rate.
|
||||
* For example, at 48 kHz the permitted values
|
||||
* are 120, 240, 480, 960, 1920, and 2880.
|
||||
* Passing in a duration of less than 10 ms
|
||||
* (480 samples at 48 kHz) will prevent the
|
||||
* encoder from using the LPC or hybrid modes.
|
||||
* @param[out] data <tt>unsigned char*</tt>: Output payload.
|
||||
* This must contain storage for at
|
||||
* least \a max_data_bytes.
|
||||
* @param [in] max_data_bytes <tt>opus_int32</tt>: Size of the allocated
|
||||
* memory for the output
|
||||
* payload. This may be
|
||||
* used to impose an upper limit on
|
||||
* the instant bitrate, but should
|
||||
* not be used as the only bitrate
|
||||
* control. Use #OPUS_SET_BITRATE to
|
||||
* control the bitrate.
|
||||
* @returns The length of the encoded packet (in bytes) on success or a
|
||||
* negative error code (see @ref opus_errorcodes) on failure.
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_projection_encode_float(
|
||||
OpusProjectionEncoder *st,
|
||||
const float *pcm,
|
||||
int frame_size,
|
||||
unsigned char *data,
|
||||
opus_int32 max_data_bytes
|
||||
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
|
||||
|
||||
|
||||
/** Frees an <code>OpusProjectionEncoder</code> allocated by
|
||||
* opus_projection_ambisonics_encoder_create().
|
||||
* @param st <tt>OpusProjectionEncoder*</tt>: Projection encoder state to be freed.
|
||||
*/
|
||||
OPUS_EXPORT void opus_projection_encoder_destroy(OpusProjectionEncoder *st);
|
||||
|
||||
|
||||
/** Perform a CTL function on a projection Opus encoder.
|
||||
*
|
||||
* Generally the request and subsequent arguments are generated by a
|
||||
* convenience macro.
|
||||
* @param st <tt>OpusProjectionEncoder*</tt>: Projection encoder state.
|
||||
* @param request This and all remaining parameters should be replaced by one
|
||||
* of the convenience macros in @ref opus_genericctls,
|
||||
* @ref opus_encoderctls, @ref opus_multistream_ctls, or
|
||||
* @ref opus_projection_ctls
|
||||
* @see opus_genericctls
|
||||
* @see opus_encoderctls
|
||||
* @see opus_multistream_ctls
|
||||
* @see opus_projection_ctls
|
||||
*/
|
||||
OPUS_EXPORT int opus_projection_encoder_ctl(OpusProjectionEncoder *st, int request, ...) OPUS_ARG_NONNULL(1);
|
||||
|
||||
|
||||
/**@}*/
|
||||
|
||||
/**\name Projection decoder functions */
|
||||
/**@{*/
|
||||
|
||||
/** Gets the size of an <code>OpusProjectionDecoder</code> structure.
|
||||
* @param channels <tt>int</tt>: The total number of output channels.
|
||||
* This must be no more than 255.
|
||||
* @param streams <tt>int</tt>: The total number of streams coded in the
|
||||
* input.
|
||||
* This must be no more than 255.
|
||||
* @param coupled_streams <tt>int</tt>: Number streams to decode as coupled
|
||||
* (2 channel) streams.
|
||||
* This must be no larger than the total
|
||||
* number of streams.
|
||||
* Additionally, The total number of
|
||||
* coded channels (<code>streams +
|
||||
* coupled_streams</code>) must be no
|
||||
* more than 255.
|
||||
* @returns The size in bytes on success, or a negative error code
|
||||
* (see @ref opus_errorcodes) on error.
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_projection_decoder_get_size(
|
||||
int channels,
|
||||
int streams,
|
||||
int coupled_streams
|
||||
);
|
||||
|
||||
|
||||
/** Allocates and initializes a projection decoder state.
|
||||
* Call opus_projection_decoder_destroy() to release
|
||||
* this object when finished.
|
||||
* @param Fs <tt>opus_int32</tt>: Sampling rate to decode at (in Hz).
|
||||
* This must be one of 8000, 12000, 16000,
|
||||
* 24000, or 48000.
|
||||
* @param channels <tt>int</tt>: Number of channels to output.
|
||||
* This must be at most 255.
|
||||
* It may be different from the number of coded
|
||||
* channels (<code>streams +
|
||||
* coupled_streams</code>).
|
||||
* @param streams <tt>int</tt>: The total number of streams coded in the
|
||||
* input.
|
||||
* This must be no more than 255.
|
||||
* @param coupled_streams <tt>int</tt>: Number of streams to decode as coupled
|
||||
* (2 channel) streams.
|
||||
* This must be no larger than the total
|
||||
* number of streams.
|
||||
* Additionally, The total number of
|
||||
* coded channels (<code>streams +
|
||||
* coupled_streams</code>) must be no
|
||||
* more than 255.
|
||||
* @param[in] demixing_matrix <tt>const unsigned char[demixing_matrix_size]</tt>: Demixing matrix
|
||||
* that mapping from coded channels to output channels,
|
||||
* as described in @ref opus_projection and
|
||||
* @ref opus_projection_ctls.
|
||||
* @param demixing_matrix_size <tt>opus_int32</tt>: The size in bytes of the
|
||||
* demixing matrix, as
|
||||
* described in @ref
|
||||
* opus_projection_ctls.
|
||||
* @param[out] error <tt>int *</tt>: Returns #OPUS_OK on success, or an error
|
||||
* code (see @ref opus_errorcodes) on
|
||||
* failure.
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusProjectionDecoder *opus_projection_decoder_create(
|
||||
opus_int32 Fs,
|
||||
int channels,
|
||||
int streams,
|
||||
int coupled_streams,
|
||||
unsigned char *demixing_matrix,
|
||||
opus_int32 demixing_matrix_size,
|
||||
int *error
|
||||
) OPUS_ARG_NONNULL(5);
|
||||
|
||||
|
||||
/** Intialize a previously allocated projection decoder state object.
|
||||
* The memory pointed to by \a st must be at least the size returned by
|
||||
* opus_projection_decoder_get_size().
|
||||
* This is intended for applications which use their own allocator instead of
|
||||
* malloc.
|
||||
* To reset a previously initialized state, use the #OPUS_RESET_STATE CTL.
|
||||
* @see opus_projection_decoder_create
|
||||
* @see opus_projection_deocder_get_size
|
||||
* @param st <tt>OpusProjectionDecoder*</tt>: Projection encoder state to initialize.
|
||||
* @param Fs <tt>opus_int32</tt>: Sampling rate to decode at (in Hz).
|
||||
* This must be one of 8000, 12000, 16000,
|
||||
* 24000, or 48000.
|
||||
* @param channels <tt>int</tt>: Number of channels to output.
|
||||
* This must be at most 255.
|
||||
* It may be different from the number of coded
|
||||
* channels (<code>streams +
|
||||
* coupled_streams</code>).
|
||||
* @param streams <tt>int</tt>: The total number of streams coded in the
|
||||
* input.
|
||||
* This must be no more than 255.
|
||||
* @param coupled_streams <tt>int</tt>: Number of streams to decode as coupled
|
||||
* (2 channel) streams.
|
||||
* This must be no larger than the total
|
||||
* number of streams.
|
||||
* Additionally, The total number of
|
||||
* coded channels (<code>streams +
|
||||
* coupled_streams</code>) must be no
|
||||
* more than 255.
|
||||
* @param[in] demixing_matrix <tt>const unsigned char[demixing_matrix_size]</tt>: Demixing matrix
|
||||
* that mapping from coded channels to output channels,
|
||||
* as described in @ref opus_projection and
|
||||
* @ref opus_projection_ctls.
|
||||
* @param demixing_matrix_size <tt>opus_int32</tt>: The size in bytes of the
|
||||
* demixing matrix, as
|
||||
* described in @ref
|
||||
* opus_projection_ctls.
|
||||
* @returns #OPUS_OK on success, or an error code (see @ref opus_errorcodes)
|
||||
* on failure.
|
||||
*/
|
||||
OPUS_EXPORT int opus_projection_decoder_init(
|
||||
OpusProjectionDecoder *st,
|
||||
opus_int32 Fs,
|
||||
int channels,
|
||||
int streams,
|
||||
int coupled_streams,
|
||||
unsigned char *demixing_matrix,
|
||||
opus_int32 demixing_matrix_size
|
||||
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(6);
|
||||
|
||||
|
||||
/** Decode a projection Opus packet.
|
||||
* @param st <tt>OpusProjectionDecoder*</tt>: Projection decoder state.
|
||||
* @param[in] data <tt>const unsigned char*</tt>: Input payload.
|
||||
* Use a <code>NULL</code>
|
||||
* pointer to indicate packet
|
||||
* loss.
|
||||
* @param len <tt>opus_int32</tt>: Number of bytes in payload.
|
||||
* @param[out] pcm <tt>opus_int16*</tt>: Output signal, with interleaved
|
||||
* samples.
|
||||
* This must contain room for
|
||||
* <code>frame_size*channels</code>
|
||||
* samples.
|
||||
* @param frame_size <tt>int</tt>: The number of samples per channel of
|
||||
* available space in \a pcm.
|
||||
* If this is less than the maximum packet duration
|
||||
* (120 ms; 5760 for 48kHz), this function will not be capable
|
||||
* of decoding some packets. In the case of PLC (data==NULL)
|
||||
* or FEC (decode_fec=1), then frame_size needs to be exactly
|
||||
* the duration of audio that is missing, otherwise the
|
||||
* decoder will not be in the optimal state to decode the
|
||||
* next incoming packet. For the PLC and FEC cases, frame_size
|
||||
* <b>must</b> be a multiple of 2.5 ms.
|
||||
* @param decode_fec <tt>int</tt>: Flag (0 or 1) to request that any in-band
|
||||
* forward error correction data be decoded.
|
||||
* If no such data is available, the frame is
|
||||
* decoded as if it were lost.
|
||||
* @returns Number of samples decoded on success or a negative error code
|
||||
* (see @ref opus_errorcodes) on failure.
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_projection_decode(
|
||||
OpusProjectionDecoder *st,
|
||||
const unsigned char *data,
|
||||
opus_int32 len,
|
||||
opus_int16 *pcm,
|
||||
int frame_size,
|
||||
int decode_fec
|
||||
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
|
||||
|
||||
|
||||
/** Decode a projection Opus packet with floating point output.
|
||||
* @param st <tt>OpusProjectionDecoder*</tt>: Projection decoder state.
|
||||
* @param[in] data <tt>const unsigned char*</tt>: Input payload.
|
||||
* Use a <code>NULL</code>
|
||||
* pointer to indicate packet
|
||||
* loss.
|
||||
* @param len <tt>opus_int32</tt>: Number of bytes in payload.
|
||||
* @param[out] pcm <tt>opus_int16*</tt>: Output signal, with interleaved
|
||||
* samples.
|
||||
* This must contain room for
|
||||
* <code>frame_size*channels</code>
|
||||
* samples.
|
||||
* @param frame_size <tt>int</tt>: The number of samples per channel of
|
||||
* available space in \a pcm.
|
||||
* If this is less than the maximum packet duration
|
||||
* (120 ms; 5760 for 48kHz), this function will not be capable
|
||||
* of decoding some packets. In the case of PLC (data==NULL)
|
||||
* or FEC (decode_fec=1), then frame_size needs to be exactly
|
||||
* the duration of audio that is missing, otherwise the
|
||||
* decoder will not be in the optimal state to decode the
|
||||
* next incoming packet. For the PLC and FEC cases, frame_size
|
||||
* <b>must</b> be a multiple of 2.5 ms.
|
||||
* @param decode_fec <tt>int</tt>: Flag (0 or 1) to request that any in-band
|
||||
* forward error correction data be decoded.
|
||||
* If no such data is available, the frame is
|
||||
* decoded as if it were lost.
|
||||
* @returns Number of samples decoded on success or a negative error code
|
||||
* (see @ref opus_errorcodes) on failure.
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_projection_decode_float(
|
||||
OpusProjectionDecoder *st,
|
||||
const unsigned char *data,
|
||||
opus_int32 len,
|
||||
float *pcm,
|
||||
int frame_size,
|
||||
int decode_fec
|
||||
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
|
||||
|
||||
|
||||
/** Perform a CTL function on a projection Opus decoder.
|
||||
*
|
||||
* Generally the request and subsequent arguments are generated by a
|
||||
* convenience macro.
|
||||
* @param st <tt>OpusProjectionDecoder*</tt>: Projection decoder state.
|
||||
* @param request This and all remaining parameters should be replaced by one
|
||||
* of the convenience macros in @ref opus_genericctls,
|
||||
* @ref opus_decoderctls, @ref opus_multistream_ctls, or
|
||||
* @ref opus_projection_ctls.
|
||||
* @see opus_genericctls
|
||||
* @see opus_decoderctls
|
||||
* @see opus_multistream_ctls
|
||||
* @see opus_projection_ctls
|
||||
*/
|
||||
OPUS_EXPORT int opus_projection_decoder_ctl(OpusProjectionDecoder *st, int request, ...) OPUS_ARG_NONNULL(1);
|
||||
|
||||
|
||||
/** Frees an <code>OpusProjectionDecoder</code> allocated by
|
||||
* opus_projection_decoder_create().
|
||||
* @param st <tt>OpusProjectionDecoder</tt>: Projection decoder state to be freed.
|
||||
*/
|
||||
OPUS_EXPORT void opus_projection_decoder_destroy(OpusProjectionDecoder *st);
|
||||
|
||||
|
||||
/**@}*/
|
||||
|
||||
/**@}*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* OPUS_PROJECTION_H */
|
166
pkg/codec/opus/include/opus_types.h
Normal file
166
pkg/codec/opus/include/opus_types.h
Normal file
@@ -0,0 +1,166 @@
|
||||
/* (C) COPYRIGHT 1994-2002 Xiph.Org Foundation */
|
||||
/* Modified by Jean-Marc Valin */
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/* opus_types.h based on ogg_types.h from libogg */
|
||||
|
||||
/**
|
||||
@file opus_types.h
|
||||
@brief Opus reference implementation types
|
||||
*/
|
||||
#ifndef OPUS_TYPES_H
|
||||
#define OPUS_TYPES_H
|
||||
|
||||
#define opus_int int /* used for counters etc; at least 16 bits */
|
||||
#define opus_int64 long long
|
||||
#define opus_int8 signed char
|
||||
|
||||
#define opus_uint unsigned int /* used for counters etc; at least 16 bits */
|
||||
#define opus_uint64 unsigned long long
|
||||
#define opus_uint8 unsigned char
|
||||
|
||||
/* Use the real stdint.h if it's there (taken from Paul Hsieh's pstdint.h) */
|
||||
#if (defined(__STDC__) && __STDC__ && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || (defined(__GNUC__) && (defined(_STDINT_H) || defined(_STDINT_H_)) || defined (HAVE_STDINT_H))
|
||||
#include <stdint.h>
|
||||
# undef opus_int64
|
||||
# undef opus_int8
|
||||
# undef opus_uint64
|
||||
# undef opus_uint8
|
||||
typedef int8_t opus_int8;
|
||||
typedef uint8_t opus_uint8;
|
||||
typedef int16_t opus_int16;
|
||||
typedef uint16_t opus_uint16;
|
||||
typedef int32_t opus_int32;
|
||||
typedef uint32_t opus_uint32;
|
||||
typedef int64_t opus_int64;
|
||||
typedef uint64_t opus_uint64;
|
||||
#elif defined(_WIN32)
|
||||
|
||||
# if defined(__CYGWIN__)
|
||||
# include <_G_config.h>
|
||||
typedef _G_int32_t opus_int32;
|
||||
typedef _G_uint32_t opus_uint32;
|
||||
typedef _G_int16 opus_int16;
|
||||
typedef _G_uint16 opus_uint16;
|
||||
# elif defined(__MINGW32__)
|
||||
typedef short opus_int16;
|
||||
typedef unsigned short opus_uint16;
|
||||
typedef int opus_int32;
|
||||
typedef unsigned int opus_uint32;
|
||||
# elif defined(__MWERKS__)
|
||||
typedef int opus_int32;
|
||||
typedef unsigned int opus_uint32;
|
||||
typedef short opus_int16;
|
||||
typedef unsigned short opus_uint16;
|
||||
# else
|
||||
/* MSVC/Borland */
|
||||
typedef __int32 opus_int32;
|
||||
typedef unsigned __int32 opus_uint32;
|
||||
typedef __int16 opus_int16;
|
||||
typedef unsigned __int16 opus_uint16;
|
||||
# endif
|
||||
|
||||
#elif defined(__MACOS__)
|
||||
|
||||
# include <sys/types.h>
|
||||
typedef SInt16 opus_int16;
|
||||
typedef UInt16 opus_uint16;
|
||||
typedef SInt32 opus_int32;
|
||||
typedef UInt32 opus_uint32;
|
||||
|
||||
#elif (defined(__APPLE__) && defined(__MACH__)) /* MacOS X Framework build */
|
||||
|
||||
# include <sys/types.h>
|
||||
typedef int16_t opus_int16;
|
||||
typedef u_int16_t opus_uint16;
|
||||
typedef int32_t opus_int32;
|
||||
typedef u_int32_t opus_uint32;
|
||||
|
||||
#elif defined(__BEOS__)
|
||||
|
||||
/* Be */
|
||||
# include <inttypes.h>
|
||||
typedef int16 opus_int16;
|
||||
typedef u_int16 opus_uint16;
|
||||
typedef int32_t opus_int32;
|
||||
typedef u_int32_t opus_uint32;
|
||||
|
||||
#elif defined (__EMX__)
|
||||
|
||||
/* OS/2 GCC */
|
||||
typedef short opus_int16;
|
||||
typedef unsigned short opus_uint16;
|
||||
typedef int opus_int32;
|
||||
typedef unsigned int opus_uint32;
|
||||
|
||||
#elif defined (DJGPP)
|
||||
|
||||
/* DJGPP */
|
||||
typedef short opus_int16;
|
||||
typedef unsigned short opus_uint16;
|
||||
typedef int opus_int32;
|
||||
typedef unsigned int opus_uint32;
|
||||
|
||||
#elif defined(R5900)
|
||||
|
||||
/* PS2 EE */
|
||||
typedef int opus_int32;
|
||||
typedef unsigned opus_uint32;
|
||||
typedef short opus_int16;
|
||||
typedef unsigned short opus_uint16;
|
||||
|
||||
#elif defined(__SYMBIAN32__)
|
||||
|
||||
/* Symbian GCC */
|
||||
typedef signed short opus_int16;
|
||||
typedef unsigned short opus_uint16;
|
||||
typedef signed int opus_int32;
|
||||
typedef unsigned int opus_uint32;
|
||||
|
||||
#elif defined(CONFIG_TI_C54X) || defined (CONFIG_TI_C55X)
|
||||
|
||||
typedef short opus_int16;
|
||||
typedef unsigned short opus_uint16;
|
||||
typedef long opus_int32;
|
||||
typedef unsigned long opus_uint32;
|
||||
|
||||
#elif defined(CONFIG_TI_C6X)
|
||||
|
||||
typedef short opus_int16;
|
||||
typedef unsigned short opus_uint16;
|
||||
typedef int opus_int32;
|
||||
typedef unsigned int opus_uint32;
|
||||
|
||||
#else
|
||||
|
||||
/* Give up, take a reasonable guess */
|
||||
typedef short opus_int16;
|
||||
typedef unsigned short opus_uint16;
|
||||
typedef int opus_int32;
|
||||
typedef unsigned int opus_uint32;
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* OPUS_TYPES_H */
|
BIN
pkg/codec/opus/lib/libopus_darwin_x64.a
Normal file
BIN
pkg/codec/opus/lib/libopus_darwin_x64.a
Normal file
Binary file not shown.
BIN
pkg/codec/opus/lib/libopus_linux_arm64.a
Normal file
BIN
pkg/codec/opus/lib/libopus_linux_arm64.a
Normal file
Binary file not shown.
BIN
pkg/codec/opus/lib/libopus_linux_armv7.a
Normal file
BIN
pkg/codec/opus/lib/libopus_linux_armv7.a
Normal file
Binary file not shown.
BIN
pkg/codec/opus/lib/libopus_linux_x64.a
Normal file
BIN
pkg/codec/opus/lib/libopus_linux_x64.a
Normal file
Binary file not shown.
BIN
pkg/codec/opus/lib/libopus_windows_x64.a
Normal file
BIN
pkg/codec/opus/lib/libopus_windows_x64.a
Normal file
Binary file not shown.
@@ -5,7 +5,6 @@ import (
|
||||
"fmt"
|
||||
"math"
|
||||
|
||||
"github.com/lherman-cs/opus"
|
||||
"github.com/pion/mediadevices/pkg/codec"
|
||||
"github.com/pion/mediadevices/pkg/io/audio"
|
||||
"github.com/pion/mediadevices/pkg/prop"
|
||||
@@ -13,15 +12,27 @@ import (
|
||||
"github.com/pion/mediadevices/pkg/wave/mixer"
|
||||
)
|
||||
|
||||
/*
|
||||
#include <opus.h>
|
||||
|
||||
int bridge_encoder_set_bitrate(OpusEncoder *e, opus_int32 bitrate)
|
||||
{
|
||||
return opus_encoder_ctl(e, OPUS_SET_BITRATE(bitrate));
|
||||
}
|
||||
*/
|
||||
import "C"
|
||||
|
||||
type encoder struct {
|
||||
engine *opus.Encoder
|
||||
inBuff wave.Audio
|
||||
reader audio.Reader
|
||||
engine *C.OpusEncoder
|
||||
}
|
||||
|
||||
var latencies = []float64{5, 10, 20, 40, 60}
|
||||
|
||||
func newEncoder(r audio.Reader, p prop.Media, params Params) (codec.ReadCloser, error) {
|
||||
var cerror C.int
|
||||
|
||||
if p.SampleRate == 0 {
|
||||
return nil, fmt.Errorf("opus: inProp.SampleRate is required")
|
||||
}
|
||||
@@ -55,12 +66,14 @@ func newEncoder(r audio.Reader, p prop.Media, params Params) (codec.ReadCloser,
|
||||
|
||||
channels := p.ChannelCount
|
||||
|
||||
engine, err := opus.NewEncoder(p.SampleRate, channels, opus.AppVoIP)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := engine.SetBitrate(params.BitRate); err != nil {
|
||||
return nil, err
|
||||
engine := C.opus_encoder_create(
|
||||
C.opus_int32(p.SampleRate),
|
||||
C.int(channels),
|
||||
C.OPUS_APPLICATION_VOIP,
|
||||
&cerror,
|
||||
)
|
||||
if cerror != C.OPUS_OK {
|
||||
return nil, errors.New("failed to create encoder engine")
|
||||
}
|
||||
|
||||
rMix := audio.NewChannelMixer(channels, params.ChannelMixer)
|
||||
@@ -69,6 +82,12 @@ func newEncoder(r audio.Reader, p prop.Media, params Params) (codec.ReadCloser,
|
||||
engine: engine,
|
||||
reader: rMix(rBuf(r)),
|
||||
}
|
||||
|
||||
err := e.SetBitRate(params.BitRate)
|
||||
if err != nil {
|
||||
e.Close()
|
||||
return nil, err
|
||||
}
|
||||
return &e, nil
|
||||
}
|
||||
|
||||
@@ -79,20 +98,45 @@ func (e *encoder) Read() ([]byte, func(), error) {
|
||||
}
|
||||
|
||||
encoded := make([]byte, 1024)
|
||||
var n C.opus_int32
|
||||
switch b := buff.(type) {
|
||||
case *wave.Int16Interleaved:
|
||||
n, err := e.engine.Encode(b.Data, encoded)
|
||||
return encoded[:n:n], func() {}, err
|
||||
n = C.opus_encode(
|
||||
e.engine,
|
||||
(*C.opus_int16)(&b.Data[0]),
|
||||
C.int(b.ChunkInfo().Len),
|
||||
(*C.uchar)(&encoded[0]),
|
||||
C.opus_int32(cap(encoded)),
|
||||
)
|
||||
case *wave.Float32Interleaved:
|
||||
n, err := e.engine.EncodeFloat32(b.Data, encoded)
|
||||
return encoded[:n:n], func() {}, err
|
||||
n = C.opus_encode_float(
|
||||
e.engine,
|
||||
(*C.float)(&b.Data[0]),
|
||||
C.int(b.ChunkInfo().Len),
|
||||
(*C.uchar)(&encoded[0]),
|
||||
C.opus_int32(cap(encoded)),
|
||||
)
|
||||
default:
|
||||
return nil, func() {}, errors.New("unknown type of audio buffer")
|
||||
}
|
||||
err = errors.New("unknown type of audio buffer")
|
||||
}
|
||||
|
||||
func (e *encoder) SetBitRate(b int) error {
|
||||
panic("SetBitRate is not implemented")
|
||||
if n < 0 {
|
||||
err = errors.New("failed to encode")
|
||||
}
|
||||
|
||||
return encoded[:n:n], func() {}, err
|
||||
}
|
||||
|
||||
func (e *encoder) SetBitRate(bitRate int) error {
|
||||
cerror := C.bridge_encoder_set_bitrate(
|
||||
e.engine,
|
||||
C.int(bitRate),
|
||||
)
|
||||
if cerror != C.OPUS_OK {
|
||||
return fmt.Errorf("failed to set encoder's bitrate to %d", bitRate)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *encoder) ForceKeyFrame() error {
|
||||
@@ -100,5 +144,7 @@ func (e *encoder) ForceKeyFrame() error {
|
||||
}
|
||||
|
||||
func (e *encoder) Close() error {
|
||||
C.opus_encoder_destroy(e.engine)
|
||||
e.engine = nil
|
||||
return nil
|
||||
}
|
||||
|
6
pkg/codec/opus/opus_pkgconfig.go
Normal file
6
pkg/codec/opus/opus_pkgconfig.go
Normal file
@@ -0,0 +1,6 @@
|
||||
// +build dynamic
|
||||
|
||||
package opus
|
||||
|
||||
// #cgo pkg-config: opus
|
||||
import "C"
|
12
pkg/codec/opus/opus_static.go
Normal file
12
pkg/codec/opus/opus_static.go
Normal file
@@ -0,0 +1,12 @@
|
||||
// +build !dynamic
|
||||
|
||||
package opus
|
||||
|
||||
//#cgo CFLAGS: -I${SRCDIR}/include
|
||||
//#cgo CXXFLAGS: -I${SRCDIR}/include
|
||||
//#cgo linux,arm LDFLAGS: ${SRCDIR}/lib/libopus_linux_armv7.a -lm
|
||||
//#cgo linux,arm64 LDFLAGS: ${SRCDIR}/lib/libopus_linux_arm64.a -lm
|
||||
//#cgo linux,amd64 LDFLAGS: ${SRCDIR}/lib/libopus_linux_x64.a -lm
|
||||
//#cgo darwin,amd64 LDFLAGS: ${SRCDIR}/lib/libopus_darwin_x64.a
|
||||
//#cgo windows,amd64 LDFLAGS: ${SRCDIR}/lib/libopus_windows_x64.a
|
||||
import "C"
|
@@ -66,6 +66,7 @@ func (d *dummy) AudioRecord(p prop.Media) (audio.Reader, error) {
|
||||
wave.ChunkInfo{
|
||||
Channels: p.ChannelCount,
|
||||
Len: nSample,
|
||||
SamplingRate: p.SampleRate,
|
||||
},
|
||||
)
|
||||
|
||||
|
@@ -144,7 +144,14 @@ func (m *microphone) AudioRecord(inputProp prop.Media) (audio.Reader, error) {
|
||||
|
||||
decodedChunk, err := decoder.Decode(hostEndian, chunk, inputProp.ChannelCount)
|
||||
// FIXME: the decoder should also fill this information
|
||||
decodedChunk.(*wave.Float32Interleaved).Size.SamplingRate = inputProp.SampleRate
|
||||
switch decodedChunk := decodedChunk.(type) {
|
||||
case *wave.Float32Interleaved:
|
||||
decodedChunk.Size.SamplingRate = inputProp.SampleRate
|
||||
case *wave.Int16Interleaved:
|
||||
decodedChunk.Size.SamplingRate = inputProp.SampleRate
|
||||
default:
|
||||
panic("unsupported format")
|
||||
}
|
||||
return decodedChunk, func() {}, err
|
||||
})
|
||||
|
||||
|
@@ -2,6 +2,7 @@ package video
|
||||
|
||||
import (
|
||||
"image"
|
||||
"math"
|
||||
"time"
|
||||
|
||||
"github.com/pion/mediadevices/pkg/prop"
|
||||
@@ -9,7 +10,7 @@ import (
|
||||
|
||||
// DetectChanges will detect frame and video property changes. For video property detection,
|
||||
// since it's time related, interval will be used to determine the sample rate.
|
||||
func DetectChanges(interval time.Duration, onChange func(prop.Media)) TransformFunc {
|
||||
func DetectChanges(interval time.Duration, fpsDiffTolerance float64, onChange func(prop.Media)) TransformFunc {
|
||||
return func(r Reader) Reader {
|
||||
var currentProp prop.Media
|
||||
var lastTaken time.Time
|
||||
@@ -40,12 +41,13 @@ func DetectChanges(interval time.Duration, onChange func(prop.Media)) TransformF
|
||||
elapsed := now.Sub(lastTaken)
|
||||
if elapsed >= interval {
|
||||
fps := float32(float64(frames) / elapsed.Seconds())
|
||||
// TODO: maybe add some epsilon so that small changes will not mark as dirty
|
||||
currentProp.FrameRate = fps
|
||||
frames = 0
|
||||
lastTaken = now
|
||||
if math.Abs(float64(currentProp.FrameRate-fps)) > fpsDiffTolerance {
|
||||
currentProp.FrameRate = fps
|
||||
dirty = true
|
||||
}
|
||||
}
|
||||
|
||||
if dirty {
|
||||
onChange(currentProp)
|
||||
|
@@ -28,7 +28,7 @@ func BenchmarkDetectChanges(b *testing.B) {
|
||||
src := src
|
||||
b.Run(fmt.Sprintf("WithDetectChanges%d", n), func(b *testing.B) {
|
||||
for i := 0; i < n; i++ {
|
||||
src = DetectChanges(time.Microsecond, func(p prop.Media) {})(src)
|
||||
src = DetectChanges(time.Microsecond, 0, func(p prop.Media) {})(src)
|
||||
}
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
@@ -74,6 +74,27 @@ func TestDetectChanges(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
SlowDownAfterThrottle := func(rate float32, factor float64, after time.Duration) TransformFunc {
|
||||
return func(r Reader) Reader {
|
||||
sleep := float64(time.Second) / float64(rate)
|
||||
start := time.Now()
|
||||
f := 1.0
|
||||
return ReaderFunc(func() (image.Image, func(), error) {
|
||||
for {
|
||||
img, _, err := r.Read()
|
||||
if err != nil {
|
||||
return nil, func() {}, err
|
||||
}
|
||||
if time.Since(start) > after {
|
||||
f = factor
|
||||
}
|
||||
time.Sleep(time.Duration(sleep * f))
|
||||
return img, func() {}, nil
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
t.Run("OnChangeCalledBeforeFirstFrame", func(t *testing.T) {
|
||||
var detectBeforeFirstFrame bool
|
||||
var expected prop.Media
|
||||
@@ -81,7 +102,7 @@ func TestDetectChanges(t *testing.T) {
|
||||
expected.Width = 1920
|
||||
expected.Height = 1080
|
||||
src, _ := buildSource(expected)
|
||||
src = DetectChanges(time.Second, func(p prop.Media) {
|
||||
src = DetectChanges(time.Second, 0, func(p prop.Media) {
|
||||
actual = p
|
||||
detectBeforeFirstFrame = true
|
||||
})(src)
|
||||
@@ -104,7 +125,7 @@ func TestDetectChanges(t *testing.T) {
|
||||
expected.Width = 1920
|
||||
expected.Height = 1080
|
||||
src, update := buildSource(expected)
|
||||
src = DetectChanges(time.Second, func(p prop.Media) {
|
||||
src = DetectChanges(time.Second, 0, func(p prop.Media) {
|
||||
actual = p
|
||||
})(src)
|
||||
|
||||
@@ -137,7 +158,7 @@ func TestDetectChanges(t *testing.T) {
|
||||
expected.FrameRate = 30
|
||||
src, _ := buildSource(expected)
|
||||
src = Throttle(expected.FrameRate)(src)
|
||||
src = DetectChanges(time.Second*5, func(p prop.Media) {
|
||||
src = DetectChanges(time.Second*5, 0, func(p prop.Media) {
|
||||
actual = p
|
||||
count++
|
||||
})(src)
|
||||
@@ -155,4 +176,31 @@ func TestDetectChanges(t *testing.T) {
|
||||
assertEq(t, actual, expected, frame, checkFrameRate)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("OnChangeNotCalledForToleratedFrameRateVariation", func(t *testing.T) {
|
||||
// https://github.com/pion/mediadevices/issues/198
|
||||
if runtime.GOOS == "darwin" {
|
||||
t.Skip("Skipping because Darwin CI is not reliable for timing related tests.")
|
||||
}
|
||||
|
||||
var expected prop.Media
|
||||
var count int
|
||||
expected.Width = 1920
|
||||
expected.Height = 1080
|
||||
expected.FrameRate = 30
|
||||
src, _ := buildSource(expected)
|
||||
src = SlowDownAfterThrottle(expected.FrameRate, 1.1, time.Second)(src)
|
||||
src = DetectChanges(time.Second, 5, func(p prop.Media) {
|
||||
count++
|
||||
})(src)
|
||||
for start := time.Now(); time.Since(start) < 3*time.Second; {
|
||||
src.Read()
|
||||
}
|
||||
// onChange is called once before first frame: prop.FrameRate still 0.
|
||||
// onChange is called again after receiving frames during the specified interval: prop.FrameRate is properly calculated
|
||||
// So if the frame rate only changes within the specified tolerance, onChange should no longer be called.
|
||||
if count > 2 {
|
||||
t.Fatalf("onChange was called more than twice.")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@@ -1,117 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
import shutil
|
||||
import sys
|
||||
|
||||
TOOLCHAINS = {
|
||||
'windows': 'x86_64-w64-mingw32'
|
||||
}
|
||||
|
||||
TARGET_OS = os.environ.get('GOOS', '')
|
||||
VALID_TARGETS = TOOLCHAINS.keys()
|
||||
if TARGET_OS not in VALID_TARGETS:
|
||||
sys.exit(f'{TARGET_OS} is not in supported targets: {",".join(VALID_TARGETS)}')
|
||||
|
||||
TOOLCHAIN = TOOLCHAINS[TARGET_OS]
|
||||
|
||||
'''
|
||||
Format:
|
||||
|
||||
Git Dependency:
|
||||
name: <dependency_name>
|
||||
url: <repository_url>
|
||||
version: <git_tag>
|
||||
protocol: 'git'
|
||||
cmd: <command_how_to_install>
|
||||
|
||||
HTTP Dependency:
|
||||
name: <dependency_name>
|
||||
url: <http_url>
|
||||
extension: <file_extension_that_will_be_downloaded>
|
||||
protocol: 'http'
|
||||
cmd: <command_how_to_install>
|
||||
'''
|
||||
DEPENDENCIES = []
|
||||
ROOT_DIR = '/tmp'
|
||||
|
||||
|
||||
def log(name, description):
|
||||
print(f'{name}: {description}')
|
||||
|
||||
|
||||
def run_cmd(command):
|
||||
p = subprocess.run(command, shell=True, capture_output=True)
|
||||
|
||||
# If a command fails, exit with the return code with the error message.
|
||||
if p.returncode != 0:
|
||||
sys.exit(p.stderr.decode('utf-8'))
|
||||
|
||||
return p
|
||||
|
||||
|
||||
def pull_from_git(dependency):
|
||||
name = dependency['name']
|
||||
url = dependency['url']
|
||||
version = dependency['version']
|
||||
|
||||
run_cmd(f'git clone --branch={version} --depth=1 {url} {name}')
|
||||
install(dependency)
|
||||
|
||||
|
||||
def pull_from_http(dependency):
|
||||
name = dependency['name']
|
||||
url = dependency['url']
|
||||
extension = dependency['extension']
|
||||
tar_name = f'{name}.{extension}'
|
||||
|
||||
run_cmd(f'curl -L {url} > {tar_name}')
|
||||
shutil.unpack_archive(tar_name, name)
|
||||
|
||||
extracted = os.listdir(name)
|
||||
|
||||
# If it's being wrapped with another folder, we move them
|
||||
# one level higher so that we have all the source codes in the root
|
||||
if len(extracted) == 1:
|
||||
pwd = os.getcwd()
|
||||
package_folder = os.path.join(pwd, name)
|
||||
wrapper_folder = os.path.join(package_folder, extracted[0])
|
||||
if os.path.isdir(wrapper_folder):
|
||||
for to_move in os.listdir(wrapper_folder):
|
||||
src = os.path.join(name, wrapper_folder, to_move)
|
||||
dst = os.path.join(package_folder, to_move)
|
||||
shutil.move(src, dst)
|
||||
|
||||
install(dependency)
|
||||
|
||||
|
||||
def pull(dependency):
|
||||
protocol = dependency['protocol']
|
||||
name = dependency['name']
|
||||
handlers = {
|
||||
'http': pull_from_http,
|
||||
'git': pull_from_git,
|
||||
}
|
||||
|
||||
log(name, f'pulling with {protocol} protocol')
|
||||
return handlers[protocol](dependency)
|
||||
|
||||
|
||||
def install(dependency):
|
||||
name = dependency['name']
|
||||
cmd = dependency['cmd']
|
||||
|
||||
log(name, f'installing')
|
||||
os.chdir(os.path.join(ROOT_DIR, name))
|
||||
run_cmd(cmd)
|
||||
|
||||
|
||||
os.chdir(ROOT_DIR)
|
||||
for dependency in DEPENDENCIES:
|
||||
pull(dependency)
|
||||
|
||||
print()
|
||||
print('installed dependencies:')
|
||||
p = run_cmd('pkg-config --list-all')
|
||||
print(p.stdout.decode('utf-8'))
|
308
track.go
308
track.go
@@ -2,19 +2,24 @@ package mediadevices
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"image"
|
||||
"io"
|
||||
"math/rand"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/pion/mediadevices/pkg/codec"
|
||||
"github.com/pion/mediadevices/pkg/driver"
|
||||
"github.com/pion/mediadevices/pkg/io/audio"
|
||||
"github.com/pion/mediadevices/pkg/io/video"
|
||||
"github.com/pion/mediadevices/pkg/wave"
|
||||
"github.com/pion/rtp"
|
||||
"github.com/pion/webrtc/v2"
|
||||
"github.com/pion/webrtc/v2/pkg/media"
|
||||
"github.com/pion/webrtc/v3"
|
||||
)
|
||||
|
||||
const (
|
||||
rtpOutboundMTU = 1200
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -48,18 +53,22 @@ type Track interface {
|
||||
// If the error is already occured before registering, the handler will be
|
||||
// immediately called.
|
||||
OnEnded(func(error))
|
||||
Kind() MediaDeviceType
|
||||
Kind() webrtc.RTPCodecType
|
||||
// StreamID is the group this track belongs too. This must be unique
|
||||
StreamID() string
|
||||
// Bind binds the current track source to the given peer connection. In Pion/webrtc v3, the bind
|
||||
// call will happen automatically after the SDP negotiation. Users won't need to call this manually.
|
||||
Bind(*webrtc.PeerConnection) (*webrtc.Track, error)
|
||||
Bind(webrtc.TrackLocalContext) (webrtc.RTPCodecParameters, error)
|
||||
// Unbind is the clean up operation that should be called after Bind. Similar to Bind, unbind will
|
||||
// be called automatically in the future.
|
||||
Unbind(*webrtc.PeerConnection) error
|
||||
// be called automatically in Pion/webrtc v3.
|
||||
Unbind(webrtc.TrackLocalContext) error
|
||||
// NewRTPReader creates a new reader from the source. The reader will encode the source, and packetize
|
||||
// the encoded data in RTP format with given mtu size.
|
||||
NewRTPReader(codecName string, mtu int) (RTPReadCloser, error)
|
||||
NewRTPReader(codecName string, ssrc uint32, mtu int) (RTPReadCloser, error)
|
||||
// NewEncodedReader creates a EncodedReadCloser that reads the encoded data in codecName format
|
||||
NewEncodedReader(codecName string) (EncodedReadCloser, error)
|
||||
// NewEncodedReader creates a new Go standard io.ReadCloser that reads the encoded data in codecName format
|
||||
NewEncodedReader(codecName string) (io.ReadCloser, error)
|
||||
NewEncodedIOReader(codecName string) (io.ReadCloser, error)
|
||||
}
|
||||
|
||||
type baseTrack struct {
|
||||
@@ -70,7 +79,7 @@ type baseTrack struct {
|
||||
endOnce sync.Once
|
||||
kind MediaDeviceType
|
||||
selector *CodecSelector
|
||||
activePeerConnections map[*webrtc.PeerConnection]chan<- chan<- struct{}
|
||||
activePeerConnections map[string]chan<- chan<- struct{}
|
||||
}
|
||||
|
||||
func newBaseTrack(source Source, kind MediaDeviceType, selector *CodecSelector) *baseTrack {
|
||||
@@ -78,13 +87,30 @@ func newBaseTrack(source Source, kind MediaDeviceType, selector *CodecSelector)
|
||||
Source: source,
|
||||
kind: kind,
|
||||
selector: selector,
|
||||
activePeerConnections: make(map[*webrtc.PeerConnection]chan<- chan<- struct{}),
|
||||
activePeerConnections: make(map[string]chan<- chan<- struct{}),
|
||||
}
|
||||
}
|
||||
|
||||
// Kind returns track's kind
|
||||
func (track *baseTrack) Kind() MediaDeviceType {
|
||||
return track.kind
|
||||
func (track *baseTrack) Kind() webrtc.RTPCodecType {
|
||||
switch track.kind {
|
||||
case VideoInput:
|
||||
return webrtc.RTPCodecTypeVideo
|
||||
case AudioInput:
|
||||
return webrtc.RTPCodecTypeAudio
|
||||
default:
|
||||
panic("invalid track kind: only support VideoInput and AudioInput")
|
||||
}
|
||||
}
|
||||
|
||||
func (track *baseTrack) StreamID() string {
|
||||
// TODO: StreamID should be used to group multiple tracks. Should get this information from mediastream instead.
|
||||
generator, err := uuid.NewRandom()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return generator.String()
|
||||
}
|
||||
|
||||
// OnEnded sets an error handler. When a track has been created and started, if an
|
||||
@@ -117,20 +143,35 @@ func (track *baseTrack) onError(err error) {
|
||||
}
|
||||
}
|
||||
|
||||
func (track *baseTrack) bind(pc *webrtc.PeerConnection, encodedReader codec.ReadCloser, selectedCodec *codec.RTPCodec, sample samplerFunc) (*webrtc.Track, error) {
|
||||
func (track *baseTrack) bind(ctx webrtc.TrackLocalContext, specializedTrack Track) (webrtc.RTPCodecParameters, error) {
|
||||
track.mu.Lock()
|
||||
defer track.mu.Unlock()
|
||||
|
||||
webrtcTrack, err := pc.NewTrack(selectedCodec.PayloadType, rand.Uint32(), track.ID(), selectedCodec.MimeType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
signalCh := make(chan chan<- struct{})
|
||||
track.activePeerConnections[ctx.ID()] = signalCh
|
||||
|
||||
var encodedReader RTPReadCloser
|
||||
var selectedCodec webrtc.RTPCodecParameters
|
||||
var err error
|
||||
var errReasons []string
|
||||
for _, wantedCodec := range ctx.CodecParameters() {
|
||||
logger.Debugf("trying to build %s rtp reader", wantedCodec.MimeType)
|
||||
encodedReader, err = specializedTrack.NewRTPReader(wantedCodec.MimeType, uint32(ctx.SSRC()), rtpOutboundMTU)
|
||||
if err == nil {
|
||||
selectedCodec = wantedCodec
|
||||
break
|
||||
}
|
||||
|
||||
signalCh := make(chan chan<- struct{})
|
||||
track.activePeerConnections[pc] = signalCh
|
||||
errReasons = append(errReasons, fmt.Sprintf("%s: %s", wantedCodec.MimeType, err))
|
||||
}
|
||||
|
||||
if encodedReader == nil {
|
||||
return webrtc.RTPCodecParameters{}, errors.New(strings.Join(errReasons, "\n\n"))
|
||||
}
|
||||
|
||||
go func() {
|
||||
var doneCh chan<- struct{}
|
||||
writer := ctx.WriteStream()
|
||||
defer func() {
|
||||
encodedReader.Close()
|
||||
|
||||
@@ -148,32 +189,30 @@ func (track *baseTrack) bind(pc *webrtc.PeerConnection, encodedReader codec.Read
|
||||
default:
|
||||
}
|
||||
|
||||
buff, _, err := encodedReader.Read()
|
||||
pkts, _, err := encodedReader.Read()
|
||||
if err != nil {
|
||||
// explicitly ignore this error since the higher level should've reported this
|
||||
return
|
||||
}
|
||||
|
||||
for _, pkt := range pkts {
|
||||
_, err = writer.WriteRTP(&pkt.Header, pkt.Payload)
|
||||
if err != nil {
|
||||
track.onError(err)
|
||||
return
|
||||
}
|
||||
|
||||
sampleCount := sample()
|
||||
err = webrtcTrack.WriteSample(media.Sample{
|
||||
Data: buff,
|
||||
Samples: sampleCount,
|
||||
})
|
||||
if err != nil {
|
||||
track.onError(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
return webrtcTrack, nil
|
||||
return selectedCodec, nil
|
||||
}
|
||||
|
||||
func (track *baseTrack) unbind(pc *webrtc.PeerConnection) error {
|
||||
func (track *baseTrack) unbind(ctx webrtc.TrackLocalContext) error {
|
||||
track.mu.Lock()
|
||||
defer track.mu.Unlock()
|
||||
|
||||
ch, ok := track.activePeerConnections[pc]
|
||||
ch, ok := track.activePeerConnections[ctx.ID()]
|
||||
if !ok {
|
||||
return errNotFoundPeerConnection
|
||||
}
|
||||
@@ -181,35 +220,10 @@ func (track *baseTrack) unbind(pc *webrtc.PeerConnection) error {
|
||||
doneCh := make(chan struct{})
|
||||
ch <- doneCh
|
||||
<-doneCh
|
||||
delete(track.activePeerConnections, pc)
|
||||
delete(track.activePeerConnections, ctx.ID())
|
||||
return nil
|
||||
}
|
||||
|
||||
func (track *baseTrack) newEncodedReader(reader codec.ReadCloser) (io.ReadCloser, error) {
|
||||
var encoded []byte
|
||||
release := func() {}
|
||||
return &encodedReadCloserImpl{
|
||||
readFn: func(b []byte) (int, error) {
|
||||
var err error
|
||||
|
||||
if len(encoded) == 0 {
|
||||
release()
|
||||
encoded, release, err = reader.Read()
|
||||
if err != nil {
|
||||
reader.Close()
|
||||
track.onError(err)
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
|
||||
n := copy(b, encoded)
|
||||
encoded = encoded[n:]
|
||||
return n, nil
|
||||
},
|
||||
closeFn: reader.Close,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func newTrackFromDriver(d driver.Driver, constraints MediaTrackConstraints, selector *CodecSelector) (Track, error) {
|
||||
if err := d.Open(); err != nil {
|
||||
return nil, err
|
||||
@@ -271,42 +285,61 @@ func (track *VideoTrack) Transform(fns ...video.TransformFunc) {
|
||||
track.Broadcaster.ReplaceSource(video.Merge(fns...)(src))
|
||||
}
|
||||
|
||||
func (track *VideoTrack) Bind(pc *webrtc.PeerConnection) (*webrtc.Track, error) {
|
||||
func (track *VideoTrack) Bind(ctx webrtc.TrackLocalContext) (webrtc.RTPCodecParameters, error) {
|
||||
return track.bind(ctx, track)
|
||||
}
|
||||
|
||||
func (track *VideoTrack) Unbind(ctx webrtc.TrackLocalContext) error {
|
||||
return track.unbind(ctx)
|
||||
}
|
||||
|
||||
func (track *VideoTrack) newEncodedReader(codecNames ...string) (EncodedReadCloser, *codec.RTPCodec, error) {
|
||||
reader := track.NewReader(false)
|
||||
inputProp, err := detectCurrentVideoProp(track.Broadcaster)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
wantCodecs := pc.GetRegisteredRTPCodecs(webrtc.RTPCodecTypeVideo)
|
||||
encodedReader, selectedCodec, err := track.selector.selectVideoCodec(reader, inputProp, wantCodecs...)
|
||||
encodedReader, selectedCodec, err := track.selector.selectVideoCodecByNames(reader, inputProp, codecNames...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return track.bind(pc, encodedReader, selectedCodec, newVideoSampler(selectedCodec.ClockRate))
|
||||
}
|
||||
|
||||
func (track *VideoTrack) Unbind(pc *webrtc.PeerConnection) error {
|
||||
return track.unbind(pc)
|
||||
}
|
||||
|
||||
func (track *VideoTrack) NewRTPReader(codecName string, mtu int) (RTPReadCloser, error) {
|
||||
reader := track.NewReader(false)
|
||||
inputProp, err := detectCurrentVideoProp(track.Broadcaster)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
encodedReader, selectedCodec, err := track.selector.selectVideoCodecByNames(reader, inputProp, codecName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
sample := newVideoSampler(selectedCodec.ClockRate)
|
||||
|
||||
// FIXME: not sure the best way to get unique ssrc. We probably should have a global keeper that can generate a random ID and does book keeping?
|
||||
packetizer := rtp.NewPacketizer(mtu, selectedCodec.PayloadType, rand.Uint32(), selectedCodec.Payloader, rtp.NewRandomSequencer(), selectedCodec.ClockRate)
|
||||
return &encodedReadCloserImpl{
|
||||
readFn: func() (EncodedBuffer, func(), error) {
|
||||
data, release, err := encodedReader.Read()
|
||||
buffer := EncodedBuffer{
|
||||
Data: data,
|
||||
Samples: sample(),
|
||||
}
|
||||
return buffer, release, err
|
||||
},
|
||||
closeFn: encodedReader.Close,
|
||||
}, selectedCodec, nil
|
||||
}
|
||||
|
||||
func (track *VideoTrack) NewEncodedReader(codecName string) (EncodedReadCloser, error) {
|
||||
reader, _, err := track.newEncodedReader(codecName)
|
||||
return reader, err
|
||||
}
|
||||
|
||||
func (track *VideoTrack) NewEncodedIOReader(codecName string) (io.ReadCloser, error) {
|
||||
encodedReader, _, err := track.newEncodedReader(codecName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return newEncodedIOReadCloserImpl(encodedReader), nil
|
||||
}
|
||||
|
||||
func (track *VideoTrack) NewRTPReader(codecName string, ssrc uint32, mtu int) (RTPReadCloser, error) {
|
||||
encodedReader, selectedCodec, err := track.newEncodedReader(codecName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
packetizer := rtp.NewPacketizer(mtu, uint8(selectedCodec.PayloadType), ssrc, selectedCodec.Payloader, rtp.NewRandomSequencer(), selectedCodec.ClockRate)
|
||||
|
||||
return &rtpReadCloserImpl{
|
||||
readFn: func() ([]*rtp.Packet, func(), error) {
|
||||
@@ -318,29 +351,13 @@ func (track *VideoTrack) NewRTPReader(codecName string, mtu int) (RTPReadCloser,
|
||||
}
|
||||
defer release()
|
||||
|
||||
samples := sample()
|
||||
pkts := packetizer.Packetize(encoded, samples)
|
||||
pkts := packetizer.Packetize(encoded.Data, encoded.Samples)
|
||||
return pkts, release, err
|
||||
},
|
||||
closeFn: encodedReader.Close,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (track *VideoTrack) NewEncodedReader(codecName string) (io.ReadCloser, error) {
|
||||
reader := track.NewReader(false)
|
||||
inputProp, err := detectCurrentVideoProp(track.Broadcaster)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
encodedReader, _, err := track.selector.selectVideoCodecByNames(reader, inputProp, codecName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return track.newEncodedReader(encodedReader)
|
||||
}
|
||||
|
||||
// AudioTrack is a specific track type that contains audio source which allows multiple readers to access, and
|
||||
// manipulate.
|
||||
type AudioTrack struct {
|
||||
@@ -388,42 +405,61 @@ func (track *AudioTrack) Transform(fns ...audio.TransformFunc) {
|
||||
track.Broadcaster.ReplaceSource(audio.Merge(fns...)(src))
|
||||
}
|
||||
|
||||
func (track *AudioTrack) Bind(pc *webrtc.PeerConnection) (*webrtc.Track, error) {
|
||||
func (track *AudioTrack) Bind(ctx webrtc.TrackLocalContext) (webrtc.RTPCodecParameters, error) {
|
||||
return track.bind(ctx, track)
|
||||
}
|
||||
|
||||
func (track *AudioTrack) Unbind(ctx webrtc.TrackLocalContext) error {
|
||||
return track.unbind(ctx)
|
||||
}
|
||||
|
||||
func (track *AudioTrack) newEncodedReader(codecNames ...string) (EncodedReadCloser, *codec.RTPCodec, error) {
|
||||
reader := track.NewReader(false)
|
||||
inputProp, err := detectCurrentAudioProp(track.Broadcaster)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
wantCodecs := pc.GetRegisteredRTPCodecs(webrtc.RTPCodecTypeAudio)
|
||||
encodedReader, selectedCodec, err := track.selector.selectAudioCodec(reader, inputProp, wantCodecs...)
|
||||
encodedReader, selectedCodec, err := track.selector.selectAudioCodecByNames(reader, inputProp, codecNames...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return track.bind(pc, encodedReader, selectedCodec, newAudioSampler(selectedCodec.ClockRate, inputProp.Latency))
|
||||
}
|
||||
|
||||
func (track *AudioTrack) Unbind(pc *webrtc.PeerConnection) error {
|
||||
return track.unbind(pc)
|
||||
}
|
||||
|
||||
func (track *AudioTrack) NewRTPReader(codecName string, mtu int) (RTPReadCloser, error) {
|
||||
reader := track.NewReader(false)
|
||||
inputProp, err := detectCurrentAudioProp(track.Broadcaster)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
encodedReader, selectedCodec, err := track.selector.selectAudioCodecByNames(reader, inputProp, codecName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
sample := newAudioSampler(selectedCodec.ClockRate, inputProp.Latency)
|
||||
|
||||
// FIXME: not sure the best way to get unique ssrc. We probably should have a global keeper that can generate a random ID and does book keeping?
|
||||
packetizer := rtp.NewPacketizer(mtu, selectedCodec.PayloadType, rand.Uint32(), selectedCodec.Payloader, rtp.NewRandomSequencer(), selectedCodec.ClockRate)
|
||||
return &encodedReadCloserImpl{
|
||||
readFn: func() (EncodedBuffer, func(), error) {
|
||||
data, release, err := encodedReader.Read()
|
||||
buffer := EncodedBuffer{
|
||||
Data: data,
|
||||
Samples: sample(),
|
||||
}
|
||||
return buffer, release, err
|
||||
},
|
||||
closeFn: encodedReader.Close,
|
||||
}, selectedCodec, nil
|
||||
}
|
||||
|
||||
func (track *AudioTrack) NewEncodedReader(codecName string) (EncodedReadCloser, error) {
|
||||
reader, _, err := track.newEncodedReader(codecName)
|
||||
return reader, err
|
||||
}
|
||||
|
||||
func (track *AudioTrack) NewEncodedIOReader(codecName string) (io.ReadCloser, error) {
|
||||
encodedReader, _, err := track.newEncodedReader(codecName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return newEncodedIOReadCloserImpl(encodedReader), nil
|
||||
}
|
||||
|
||||
func (track *AudioTrack) NewRTPReader(codecName string, ssrc uint32, mtu int) (RTPReadCloser, error) {
|
||||
encodedReader, selectedCodec, err := track.newEncodedReader(codecName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
packetizer := rtp.NewPacketizer(mtu, uint8(selectedCodec.PayloadType), ssrc, selectedCodec.Payloader, rtp.NewRandomSequencer(), selectedCodec.ClockRate)
|
||||
|
||||
return &rtpReadCloserImpl{
|
||||
readFn: func() ([]*rtp.Packet, func(), error) {
|
||||
@@ -435,25 +471,9 @@ func (track *AudioTrack) NewRTPReader(codecName string, mtu int) (RTPReadCloser,
|
||||
}
|
||||
defer release()
|
||||
|
||||
samples := sample()
|
||||
pkts := packetizer.Packetize(encoded, samples)
|
||||
pkts := packetizer.Packetize(encoded.Data, encoded.Samples)
|
||||
return pkts, release, err
|
||||
},
|
||||
closeFn: encodedReader.Close,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (track *AudioTrack) NewEncodedReader(codecName string) (io.ReadCloser, error) {
|
||||
reader := track.NewReader(false)
|
||||
inputProp, err := detectCurrentAudioProp(track.Broadcaster)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
encodedReader, _, err := track.selector.selectAudioCodecByNames(reader, inputProp, codecName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return track.newEncodedReader(encodedReader)
|
||||
}
|
||||
|
@@ -1,33 +0,0 @@
|
||||
FROM fedora
|
||||
|
||||
ENV PYTHONUNBUFFERED=1 \
|
||||
# Somehow libopus.dll is installed under /usr/local/bin, so we need to add this
|
||||
# path to WINEPATH so that wine can find this library
|
||||
WINEPATH=/usr/local/bin \
|
||||
# Go and C default environments
|
||||
GOOS=windows \
|
||||
GOARCH=amd64 \
|
||||
CGO_ENABLED=1 \
|
||||
GO111MODULE=on \
|
||||
CC=x86_64-w64-mingw32-gcc \
|
||||
CXX=x86_64-w64-mingw32-g++
|
||||
|
||||
COPY scripts /usr/bin/
|
||||
|
||||
RUN dnf install -y \
|
||||
diffutils \
|
||||
golang \
|
||||
make \
|
||||
mingw64-gcc \
|
||||
mingw64-gcc-c++ \
|
||||
mingw64-opus && \
|
||||
nasm \
|
||||
pkg-config \
|
||||
python3 \
|
||||
wine \
|
||||
dnf clean all && \
|
||||
install-dependencies && \
|
||||
rm -rf /tmp/*
|
||||
|
||||
VOLUME /go/src/github.com/pion/mediadevices
|
||||
WORKDIR /go/src/github.com/pion/mediadevices
|
Reference in New Issue
Block a user