Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
57137412b5 |
@@ -1,5 +1 @@
|
||||
*pro.user
|
||||
|
||||
|
||||
**/.vs/
|
||||
build/
|
||||
@@ -1,6 +1,9 @@
|
||||
[submodule "moonlight-common-c/moonlight-common-c"]
|
||||
path = moonlight-common-c/moonlight-common-c
|
||||
url = https://github.com/moonlight-stream/moonlight-common-c.git
|
||||
[submodule "opus/opus"]
|
||||
path = opus/opus
|
||||
url = https://github.com/xiph/opus.git
|
||||
[submodule "qmdnsengine/qmdnsengine"]
|
||||
path = qmdnsengine/qmdnsengine
|
||||
url = https://github.com/cgutman/qmdnsengine.git
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
language: cpp
|
||||
|
||||
git:
|
||||
depth: 1
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- os: osx
|
||||
compiler: clang
|
||||
- os: linux
|
||||
sudo: required
|
||||
dist: xenial
|
||||
compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- sourceline: 'ppa:beineri/opt-qt596-xenial'
|
||||
- sourceline: 'ppa:jonathonf/ffmpeg-4'
|
||||
packages:
|
||||
- qt59base
|
||||
- qt59quickcontrols2
|
||||
- qt59svg
|
||||
- libesd0-dev
|
||||
- libgl-dev
|
||||
- libopus-dev
|
||||
- libavcodec-dev
|
||||
- libavutil-dev
|
||||
- libva-dev
|
||||
- libvdpau-dev
|
||||
|
||||
install:
|
||||
- '[ "$TRAVIS_OS_NAME" != osx ] || brew install qt5'
|
||||
- '[ "$TRAVIS_OS_NAME" != osx ] || brew link --force qt5'
|
||||
- if [[ "$TRAVIS_OS_NAME" = "linux" ]]; then export SDL2_VER=2.0.8 && wget https://www.libsdl.org/release/SDL2-$SDL2_VER.tar.gz && tar -xvf SDL2-$SDL2_VER.tar.gz && cd SDL2-$SDL2_VER && ./configure && make && sudo make install && cd ..; fi
|
||||
|
||||
before_script:
|
||||
- '[ "$TRAVIS_OS_NAME" != "linux" ] || source /opt/qt59/bin/qt59-env.sh'
|
||||
- qmake -v
|
||||
- '[[ "$TRAVIS_OS_NAME" != linux || "$CXX" != clang++ ]] || export QMAKESPEC=linux-clang'
|
||||
- '[[ "$TRAVIS_OS_NAME" != linux || "$CXX" != g++ ]] || export QMAKESPEC=linux-g++'
|
||||
- '[ "$TRAVIS_OS_NAME" != osx ] || export QMAKESPEC=macx-clang'
|
||||
|
||||
script:
|
||||
- qmake moonlight-qt.pro -spec $QMAKESPEC
|
||||
- make debug
|
||||
- make release
|
||||
@@ -1,31 +1,20 @@
|
||||
# Moonlight PC
|
||||
|
||||
[Moonlight PC](http://moonlight-stream.com) is an open source implementation of NVIDIA's GameStream, as used by the NVIDIA Shield, but built to run on Windows, Mac, and Linux. This client is the successor to [Moonlight Chrome](https://github.com/moonlight-stream/moonlight-chrome) for streaming on PC.
|
||||
[Moonlight PC](http://moonlight-stream.com) is an open source implementation of NVIDIA's GameStream, as used by the NVIDIA Shield, but built to run on Windows, Mac, and Linux.
|
||||
|
||||
Moonlight also has mobile versions for [Android](https://github.com/moonlight-stream/moonlight-android) and [iOS](https://github.com/moonlight-stream/moonlight-ios).
|
||||
|
||||
See the [releases page](https://github.com/moonlight-stream/moonlight-qt/releases) for download links for Windows and Mac. For Linux, we're on [Flathub](https://flathub.org/apps/details/com.moonlight_stream.Moonlight).
|
||||
|
||||
You can follow development on our [Discord server](https://discord.gg/6ERtzFY).
|
||||
|
||||
[](https://ci.appveyor.com/project/cgutman/moonlight-qt/branch/master)
|
||||
[](https://travis-ci.org/moonlight-stream/moonlight-qt)
|
||||
|
||||
## Features
|
||||
- Hardware accelerated video decoding on Windows, Mac, and Linux
|
||||
- Supports streaming at up to 120 FPS on high refresh rate monitors
|
||||
- Supports streaming at 720p, 1080p, 1440p, or 4K
|
||||
- 5.1 surround sound audio
|
||||
- HEVC support for better image quality at reduced bandwidth
|
||||
- Keyboard and mouse support
|
||||
- Gamepad support with SDL gamepad mappings
|
||||
This is a work-in-progress port and is only suitable for development use at this point.
|
||||
|
||||
## Building
|
||||
1. Install the latest Qt SDK (and optionally, the Qt Creator IDE) from https://www.qt.io/download (select MSVC toolchain on Windows)
|
||||
2. Run `git submodule update --init --recursive` from within `moonlight-qt/`
|
||||
3. Open the project in Qt Creator or build from qmake on the command line
|
||||
1. Install the latest Qt SDK (and optionally, the Qt Creator IDE) from https://www.qt.io/download
|
||||
3. Run `git submodule update --init --recursive` from within `moonlight-qt/`
|
||||
4. Open the project in Qt Creator or build from qmake on the command line
|
||||
|
||||
## Contribute
|
||||
|
||||
This project is being actively developed at [XDA Developers](http://forum.xda-developers.com/showthread.php?t=2505510)
|
||||
|
||||
1. Fork us
|
||||
2. Write code
|
||||
3. Send Pull Requests
|
||||
|
||||
@@ -3,28 +3,24 @@
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>Moonlight</string>
|
||||
<string>moonlight-qt</string>
|
||||
<key>CFBundleGetInfoString</key>
|
||||
<string>Stream games from your NVIDIA GameStream-enabled PC</string>
|
||||
<string>Created by Qt/QMake</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>moonlight</string>
|
||||
<string>macos</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.moonlight-stream.Moonlight</string>
|
||||
<key>NSHighResolutionCapable</key>
|
||||
<true/>
|
||||
<string>com.yourcompany.moonlight-qt</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>10.10</string>
|
||||
<key>NOTE</key>
|
||||
<string>This file was generated by Qt/QMake.</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>NSApplication</string>
|
||||
<key>NSSupportsAutomaticGraphicsSwitching</key>
|
||||
<true/>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>0.1.0</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>Moonlight</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
@@ -1,16 +1,7 @@
|
||||
QT += core quick network quickcontrols2 svg
|
||||
QT += core quick network quickcontrols2
|
||||
CONFIG += c++11
|
||||
|
||||
unix:!macx {
|
||||
TARGET = moonlight
|
||||
} else {
|
||||
# On macOS, this is the name displayed in the global menu bar
|
||||
TARGET = Moonlight
|
||||
}
|
||||
|
||||
# Support debug and release builds from command line for CI
|
||||
CONFIG += debug_and_release
|
||||
|
||||
TARGET = moonlight-qt
|
||||
TEMPLATE = app
|
||||
|
||||
# The following define makes your compiler emit warnings if you use
|
||||
@@ -37,36 +28,20 @@ win32 {
|
||||
LIBS += ws2_32.lib winmm.lib dxva2.lib ole32.lib
|
||||
}
|
||||
macx {
|
||||
INCLUDEPATH += $$PWD/../libs/mac/include $$PWD/../libs/mac/Frameworks/SDL2.framework/Versions/A/Headers
|
||||
LIBS += -L$$PWD/../libs/mac/lib -F$$PWD/../libs/mac/Frameworks
|
||||
INCLUDEPATH += $$PWD/../libs/mac/include
|
||||
LIBS += -L$$PWD/../libs/mac/lib
|
||||
}
|
||||
|
||||
unix:!macx {
|
||||
CONFIG += link_pkgconfig
|
||||
PKGCONFIG += openssl sdl2 opus
|
||||
LIBS += -ldl
|
||||
|
||||
packagesExist(libavcodec) {
|
||||
PKGCONFIG += libavcodec libavutil
|
||||
CONFIG += ffmpeg
|
||||
|
||||
packagesExist(libva) {
|
||||
CONFIG += libva
|
||||
}
|
||||
|
||||
packagesExist(vdpau) {
|
||||
CONFIG += libvdpau
|
||||
}
|
||||
}
|
||||
PKGCONFIG += openssl sdl2 libavcodec libavdevice libavformat libavutil
|
||||
}
|
||||
win32 {
|
||||
LIBS += -llibssl -llibcrypto -lSDL2 -lavcodec -lavutil -lopus
|
||||
CONFIG += ffmpeg
|
||||
LIBS += -llibssl -llibcrypto -lSDL2 -lavcodec -lavdevice -lavformat -lavutil
|
||||
}
|
||||
macx {
|
||||
LIBS += -lssl -lcrypto -lavcodec.58 -lavutil.56 -lopus -framework SDL2
|
||||
LIBS += -lobjc -framework VideoToolbox -framework AVFoundation -framework CoreVideo -framework CoreGraphics -framework CoreMedia -framework AppKit
|
||||
CONFIG += ffmpeg
|
||||
LIBS += -lssl -lcrypto -lSDL2 -lavcodec.58 -lavdevice.58 -lavformat.58 -lavutil.56
|
||||
LIBS += -lobjc -framework VideoToolbox -framework AVFoundation -framework CoreVideo -framework CoreMedia -framework AppKit
|
||||
}
|
||||
|
||||
SOURCES += \
|
||||
@@ -80,9 +55,17 @@ SOURCES += \
|
||||
streaming/input.cpp \
|
||||
streaming/session.cpp \
|
||||
streaming/audio.cpp \
|
||||
streaming/video/ffmpeg.cpp \
|
||||
gui/computermodel.cpp \
|
||||
gui/appmodel.cpp \
|
||||
streaming/streamutils.cpp
|
||||
streaming/video/ffmpeg-renderers/sdl.cpp
|
||||
|
||||
win32 {
|
||||
SOURCES += streaming/video/ffmpeg-renderers/dxva2.cpp
|
||||
}
|
||||
macx {
|
||||
SOURCES += streaming/video/avfoundation.mm
|
||||
}
|
||||
|
||||
HEADERS += \
|
||||
utils.h \
|
||||
@@ -97,53 +80,14 @@ HEADERS += \
|
||||
gui/computermodel.h \
|
||||
gui/appmodel.h \
|
||||
streaming/video/decoder.h \
|
||||
streaming/streamutils.h
|
||||
streaming/video/ffmpeg.h \
|
||||
streaming/video/ffmpeg-renderers/renderer.h
|
||||
|
||||
# Platform-specific renderers and decoders
|
||||
ffmpeg {
|
||||
message(FFmpeg decoder selected)
|
||||
|
||||
DEFINES += HAVE_FFMPEG
|
||||
SOURCES += \
|
||||
streaming/video/ffmpeg.cpp \
|
||||
streaming/video/ffmpeg-renderers/sdl.cpp
|
||||
HEADERS += \
|
||||
streaming/video/ffmpeg.h \
|
||||
streaming/video/ffmpeg-renderers/renderer.h
|
||||
}
|
||||
libva {
|
||||
message(VAAPI renderer selected)
|
||||
|
||||
DEFINES += HAVE_LIBVA
|
||||
SOURCES += streaming/video/ffmpeg-renderers/vaapi.cpp
|
||||
HEADERS += streaming/video/ffmpeg-renderers/vaapi.h
|
||||
}
|
||||
libvdpau {
|
||||
message(VDPAU renderer selected)
|
||||
|
||||
DEFINES += HAVE_LIBVDPAU
|
||||
SOURCES += streaming/video/ffmpeg-renderers/vdpau.cpp
|
||||
HEADERS += streaming/video/ffmpeg-renderers/vdpau.h
|
||||
}
|
||||
config_SLVideo {
|
||||
message(SLVideo decoder/renderer selected)
|
||||
|
||||
DEFINES += HAVE_SLVIDEO
|
||||
LIBS += -lSLVideo
|
||||
SOURCES += streaming/video/sl.cpp
|
||||
HEADERS += streaming/video/sl.h
|
||||
}
|
||||
win32 {
|
||||
message(DXVA2 renderer selected)
|
||||
|
||||
SOURCES += streaming/video/ffmpeg-renderers/dxva2.cpp
|
||||
HEADERS += streaming/video/ffmpeg-renderers/dxva2.h
|
||||
}
|
||||
macx {
|
||||
message(VideoToolbox renderer selected)
|
||||
|
||||
SOURCES += streaming/video/ffmpeg-renderers/vt.mm
|
||||
HEADERS += streaming/video/ffmpeg-renderers/vt.h
|
||||
HEADERS += streaming/video/avfoundation.h
|
||||
}
|
||||
|
||||
RESOURCES += \
|
||||
@@ -163,6 +107,13 @@ else:unix: LIBS += -L$$OUT_PWD/../moonlight-common-c/ -lmoonlight-common-c
|
||||
INCLUDEPATH += $$PWD/../moonlight-common-c/moonlight-common-c/src
|
||||
DEPENDPATH += $$PWD/../moonlight-common-c/moonlight-common-c/src
|
||||
|
||||
win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../opus/release/ -lopus
|
||||
else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../opus/debug/ -lopus
|
||||
else:unix: LIBS += -L$$OUT_PWD/../opus/ -lopus
|
||||
|
||||
INCLUDEPATH += $$PWD/../opus/opus/include
|
||||
DEPENDPATH += $$PWD/../opus/opus/include
|
||||
|
||||
win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../qmdnsengine/release/ -lqmdnsengine
|
||||
else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../qmdnsengine/debug/ -lqmdnsengine
|
||||
else:unix: LIBS += -L$$OUT_PWD/../qmdnsengine/ -lqmdnsengine
|
||||
@@ -170,36 +121,14 @@ else:unix: LIBS += -L$$OUT_PWD/../qmdnsengine/ -lqmdnsengine
|
||||
INCLUDEPATH += $$PWD/../qmdnsengine/qmdnsengine/src/include $$PWD/../qmdnsengine
|
||||
DEPENDPATH += $$PWD/../qmdnsengine/qmdnsengine/src/include $$PWD/../qmdnsengine
|
||||
|
||||
unix:!macx: {
|
||||
isEmpty(PREFIX) {
|
||||
PREFIX = /usr/local
|
||||
}
|
||||
isEmpty(BINDIR) {
|
||||
BINDIR = bin
|
||||
}
|
||||
# Default rules for deployment.
|
||||
qnx: target.path = /tmp/$${TARGET}/bin
|
||||
else: unix:!android: target.path = /opt/$${TARGET}/bin
|
||||
!isEmpty(target.path): INSTALLS += target
|
||||
|
||||
target.path = $$PREFIX/$$BINDIR/
|
||||
|
||||
desktop.files = deploy/linux/com.moonlight_stream.Moonlight.desktop
|
||||
desktop.path = $$PREFIX/share/applications/
|
||||
|
||||
icons.files = res/moonlight.svg
|
||||
icons.path = $$PREFIX/share/icons/hicolor/scalable/apps/
|
||||
|
||||
appdata.files = deploy/linux/com.moonlight_stream.Moonlight.appdata.xml
|
||||
appdata.path = $$PREFIX/share/metainfo/
|
||||
|
||||
INSTALLS += target desktop icons appdata
|
||||
}
|
||||
win32 {
|
||||
RC_ICONS = moonlight.ico
|
||||
}
|
||||
macx {
|
||||
QMAKE_INFO_PLIST = $$PWD/Info.plist
|
||||
|
||||
APP_BUNDLE_RESOURCES.files = moonlight.icns
|
||||
APP_BUNDLE_RESOURCES.path = Contents/Resources
|
||||
QMAKE_BUNDLE_DATA += APP_BUNDLE_RESOURCES
|
||||
APP_QML_FILES.files = res/macos.icns
|
||||
APP_QML_FILES.path = Contents/Resources
|
||||
QMAKE_BUNDLE_DATA += APP_QML_FILES
|
||||
}
|
||||
|
||||
VERSION = 0.1.0
|
||||
|
||||
@@ -51,8 +51,6 @@ NvComputer::NvComputer(QSettings& settings)
|
||||
this->appVersion = nullptr;
|
||||
this->maxLumaPixelsHEVC = 0;
|
||||
this->serverCodecModeSupport = 0;
|
||||
this->pendingQuit = false;
|
||||
this->gpuModel = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -135,21 +133,19 @@ NvComputer::NvComputer(QString address, QString serverInfo)
|
||||
this->currentGameId = NvHTTP::getCurrentGame(serverInfo);
|
||||
this->appVersion = NvHTTP::getXmlString(serverInfo, "appversion");
|
||||
this->gfeVersion = NvHTTP::getXmlString(serverInfo, "GfeVersion");
|
||||
this->gpuModel = NvHTTP::getXmlString(serverInfo, "gputype");
|
||||
this->activeAddress = address;
|
||||
this->state = NvComputer::CS_ONLINE;
|
||||
this->pendingQuit = false;
|
||||
}
|
||||
|
||||
bool NvComputer::wake()
|
||||
{
|
||||
if (state == NvComputer::CS_ONLINE) {
|
||||
qWarning() << name << "is already online";
|
||||
qWarning() << name << " is already online";
|
||||
return true;
|
||||
}
|
||||
|
||||
if (macAddress.isNull()) {
|
||||
qWarning() << name << "has no MAC address stored";
|
||||
qWarning() << name << " has no MAC address stored";
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -188,7 +184,7 @@ bool NvComputer::wake()
|
||||
// Send to all ports
|
||||
for (quint16 port : WOL_PORTS) {
|
||||
if (sock.writeDatagram(wolPayload, address, port)) {
|
||||
qInfo().nospace().noquote() << "Send WoL packet to " << name << " via " << address.toString() << ":" << port;
|
||||
qDebug() << "Send WoL packet to " << name << " via " << address.toString() << ":" << port;
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
@@ -268,7 +264,6 @@ bool NvComputer::update(NvComputer& that)
|
||||
ASSIGN_IF_CHANGED(gfeVersion);
|
||||
ASSIGN_IF_CHANGED(appVersion);
|
||||
ASSIGN_IF_CHANGED(maxLumaPixelsHEVC);
|
||||
ASSIGN_IF_CHANGED(gpuModel);
|
||||
ASSIGN_IF_CHANGED_AND_NONEMPTY(appList);
|
||||
ASSIGN_IF_CHANGED_AND_NONEMPTY(displayModes);
|
||||
return changed;
|
||||
@@ -291,56 +286,6 @@ ComputerManager::ComputerManager(QObject *parent)
|
||||
settings.endArray();
|
||||
}
|
||||
|
||||
ComputerManager::~ComputerManager()
|
||||
{
|
||||
QWriteLocker lock(&m_Lock);
|
||||
|
||||
// Delete machines that haven't been resolved yet
|
||||
while (!m_PendingResolution.isEmpty()) {
|
||||
MdnsPendingComputer* computer = m_PendingResolution.first();
|
||||
delete computer;
|
||||
m_PendingResolution.removeFirst();
|
||||
}
|
||||
|
||||
// Delete the browser to stop discovery
|
||||
delete m_MdnsBrowser;
|
||||
m_MdnsBrowser = nullptr;
|
||||
|
||||
{
|
||||
QMutableMapIterator<QString, QThread*> i(m_PollThreads);
|
||||
|
||||
// Interrupt all polling threads
|
||||
while (i.hasNext()) {
|
||||
i.next();
|
||||
i.value()->requestInterruption();
|
||||
}
|
||||
|
||||
// Wait for all threads to terminate before destroying
|
||||
// the NvComputer objects.
|
||||
i.toFront();
|
||||
while (i.hasNext()) {
|
||||
i.next();
|
||||
|
||||
QThread* thread = i.value();
|
||||
thread->wait();
|
||||
delete thread;
|
||||
|
||||
i.remove();
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
QMutableMapIterator<QString, NvComputer*> i(m_KnownHosts);
|
||||
|
||||
// Destroy all NvComputer objects
|
||||
while (i.hasNext()) {
|
||||
i.next();
|
||||
delete i.value();
|
||||
i.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ComputerManager::saveHosts()
|
||||
{
|
||||
QSettings settings;
|
||||
@@ -367,7 +312,7 @@ void ComputerManager::startPolling()
|
||||
m_MdnsBrowser = new QMdnsEngine::Browser(&m_MdnsServer, "_nvstream._tcp.local.", &m_MdnsCache);
|
||||
connect(m_MdnsBrowser, &QMdnsEngine::Browser::serviceAdded,
|
||||
this, [this](const QMdnsEngine::Service& service) {
|
||||
qInfo() << "Discovered mDNS host:" << service.hostname();
|
||||
qDebug() << "Discovered mDNS host: " << service.hostname();
|
||||
|
||||
MdnsPendingComputer* pendingComputer = new MdnsPendingComputer(&m_MdnsServer, &m_MdnsCache, service);
|
||||
connect(pendingComputer, SIGNAL(resolvedv4(MdnsPendingComputer*,QHostAddress)),
|
||||
@@ -386,7 +331,7 @@ void ComputerManager::startPolling()
|
||||
void ComputerManager::handleMdnsServiceResolved(MdnsPendingComputer* computer,
|
||||
const QHostAddress& address)
|
||||
{
|
||||
qInfo() << "Resolved" << computer->hostname() << "to" << address.toString();
|
||||
qDebug() << "Resolved " << computer->hostname() << " to " << address.toString();
|
||||
|
||||
addNewHost(address.toString(), true);
|
||||
|
||||
@@ -451,15 +396,6 @@ void ComputerManager::pairHost(NvComputer* computer, QString pin)
|
||||
QThreadPool::globalInstance()->start(pairing);
|
||||
}
|
||||
|
||||
void ComputerManager::quitRunningApp(NvComputer* computer)
|
||||
{
|
||||
QWriteLocker lock(&computer->lock);
|
||||
computer->pendingQuit = true;
|
||||
|
||||
PendingQuitTask* quit = new PendingQuitTask(this, computer);
|
||||
QThreadPool::globalInstance()->start(quit);
|
||||
}
|
||||
|
||||
void ComputerManager::stopPollingAsync()
|
||||
{
|
||||
QWriteLocker lock(&m_Lock);
|
||||
@@ -511,11 +447,6 @@ ComputerManager::handleComputerStateChanged(NvComputer* computer)
|
||||
{
|
||||
emit computerStateChanged(computer);
|
||||
|
||||
if (computer->pendingQuit && computer->currentGameId == 0) {
|
||||
computer->pendingQuit = false;
|
||||
emit quitAppCompleted(QVariant());
|
||||
}
|
||||
|
||||
// Save updated hosts to QSettings
|
||||
saveHosts();
|
||||
}
|
||||
|
||||
@@ -16,14 +16,10 @@
|
||||
class NvComputer
|
||||
{
|
||||
friend class PcMonitorThread;
|
||||
friend class ComputerManager;
|
||||
friend class PendingQuitTask;
|
||||
|
||||
private:
|
||||
void sortAppList();
|
||||
|
||||
bool pendingQuit;
|
||||
|
||||
public:
|
||||
explicit NvComputer(QString address, QString serverInfo);
|
||||
|
||||
@@ -65,7 +61,6 @@ public:
|
||||
QVector<NvDisplayMode> displayModes;
|
||||
int maxLumaPixelsHEVC;
|
||||
int serverCodecModeSupport;
|
||||
QString gpuModel;
|
||||
|
||||
// Persisted traits
|
||||
QString localAddress;
|
||||
@@ -153,26 +148,31 @@ private:
|
||||
int pollsSinceLastAppListFetch = POLLS_PER_APPLIST_FETCH;
|
||||
while (!isInterruptionRequested()) {
|
||||
bool stateChanged = false;
|
||||
bool online = false;
|
||||
for (int i = 0; i < TRIES_BEFORE_OFFLINING && !online; i++) {
|
||||
for (int i = 0; i < TRIES_BEFORE_OFFLINING; i++) {
|
||||
for (auto& address : m_Computer->uniqueAddresses()) {
|
||||
if (isInterruptionRequested()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (tryPollComputer(address, stateChanged)) {
|
||||
online = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// No need to continue retrying if we're online
|
||||
if (m_Computer->state == NvComputer::CS_ONLINE) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if we failed after all retry attempts
|
||||
// Note: we don't need to acquire the read lock here,
|
||||
// because we're on the writing thread.
|
||||
if (!online && m_Computer->state != NvComputer::CS_OFFLINE) {
|
||||
m_Computer->state = NvComputer::CS_OFFLINE;
|
||||
stateChanged = true;
|
||||
if (m_Computer->state != NvComputer::CS_ONLINE) {
|
||||
if (m_Computer->state != NvComputer::CS_OFFLINE) {
|
||||
m_Computer->state = NvComputer::CS_OFFLINE;
|
||||
stateChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Grab the applist if it's empty or it's been long enough that we need to refresh
|
||||
@@ -249,8 +249,6 @@ class ComputerManager : public QObject
|
||||
public:
|
||||
explicit ComputerManager(QObject *parent = nullptr);
|
||||
|
||||
virtual ~ComputerManager();
|
||||
|
||||
Q_INVOKABLE void startPolling();
|
||||
|
||||
Q_INVOKABLE void stopPollingAsync();
|
||||
@@ -259,8 +257,6 @@ public:
|
||||
|
||||
void pairHost(NvComputer* computer, QString pin);
|
||||
|
||||
void quitRunningApp(NvComputer* computer);
|
||||
|
||||
QVector<NvComputer*> getComputers();
|
||||
|
||||
// computer is deleted inside this call
|
||||
@@ -273,8 +269,6 @@ signals:
|
||||
|
||||
void computerAddCompleted(QVariant success);
|
||||
|
||||
void quitAppCompleted(QVariant error);
|
||||
|
||||
private slots:
|
||||
void handleComputerStateChanged(NvComputer* computer);
|
||||
|
||||
@@ -342,49 +336,6 @@ private:
|
||||
QString m_Pin;
|
||||
};
|
||||
|
||||
class PendingQuitTask : public QObject, public QRunnable
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
PendingQuitTask(ComputerManager* computerManager, NvComputer* computer)
|
||||
: m_Computer(computer)
|
||||
{
|
||||
connect(this, &PendingQuitTask::quitAppFailed,
|
||||
computerManager, &ComputerManager::quitAppCompleted);
|
||||
}
|
||||
|
||||
signals:
|
||||
void quitAppFailed(QString error);
|
||||
|
||||
private:
|
||||
void run()
|
||||
{
|
||||
NvHTTP http(m_Computer->activeAddress);
|
||||
|
||||
try {
|
||||
if (m_Computer->currentGameId != 0) {
|
||||
http.quitApp();
|
||||
}
|
||||
} catch (const GfeHttpResponseException& e) {
|
||||
{
|
||||
QWriteLocker lock(&m_Computer->lock);
|
||||
m_Computer->pendingQuit = false;
|
||||
}
|
||||
if (e.getStatusCode() == 599) {
|
||||
// 599 is a special code we make a custom message for
|
||||
emit quitAppFailed("The running game wasn't started by this PC. "
|
||||
"You must quit the game on the host PC manually or use the device that originally started the game.");
|
||||
}
|
||||
else {
|
||||
emit quitAppFailed(e.toQString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NvComputer* m_Computer;
|
||||
};
|
||||
|
||||
class PendingAddTask : public QObject, public QRunnable
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
#include "utils.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QRandomGenerator64>
|
||||
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/rand.h>
|
||||
|
||||
#define SER_UNIQUEID "uniqueid"
|
||||
#define SER_CERT "certificate"
|
||||
@@ -101,7 +101,7 @@ void IdentityManager::createCredentials(QSettings& settings)
|
||||
settings.setValue(SER_CERT, m_CachedPemCert);
|
||||
settings.setValue(SER_KEY, m_CachedPrivateKey);
|
||||
|
||||
qInfo() << "Wrote new identity credentials to settings";
|
||||
qDebug() << "Wrote new identity credentials to settings";
|
||||
}
|
||||
|
||||
IdentityManager::IdentityManager()
|
||||
@@ -112,7 +112,7 @@ IdentityManager::IdentityManager()
|
||||
m_CachedPrivateKey = settings.value(SER_KEY).toByteArray();
|
||||
|
||||
if (m_CachedPemCert.isEmpty() || m_CachedPrivateKey.isEmpty()) {
|
||||
qInfo() << "No existing credentials found";
|
||||
qDebug() << "No existing credentials found";
|
||||
createCredentials(settings);
|
||||
}
|
||||
else if (getSslCertificate().isNull()) {
|
||||
@@ -157,14 +157,10 @@ IdentityManager::getSslKey()
|
||||
|
||||
// We must write out our PEM in the old PKCS1 format for SecureTransport
|
||||
// on macOS/iOS to be able to read it.
|
||||
#ifdef Q_OS_DARWIN
|
||||
PEM_write_bio_PrivateKey_traditional(bio, pk, nullptr, nullptr, 0, nullptr, 0);
|
||||
#else
|
||||
PEM_write_bio_PrivateKey(bio, pk, nullptr, nullptr, 0, nullptr, 0);
|
||||
#endif
|
||||
|
||||
BUF_MEM* mem;
|
||||
BIO_get_mem_ptr(bio, &mem);
|
||||
PEM_write_bio_PrivateKey_traditional(bio, pk, nullptr, nullptr, 0, nullptr, 0);
|
||||
|
||||
m_CachedSslKey = QSslKey(QByteArray::fromRawData(mem->data, (int)mem->length), QSsl::Rsa);
|
||||
|
||||
BIO_free(bio);
|
||||
@@ -191,15 +187,14 @@ IdentityManager::getUniqueId()
|
||||
// Load the unique ID from settings
|
||||
m_CachedUniqueId = settings.value(SER_UNIQUEID).toString();
|
||||
if (!m_CachedUniqueId.isEmpty() && !m_CachedUniqueId.isNull()) {
|
||||
qInfo() << "Loaded unique ID from settings:" << m_CachedUniqueId;
|
||||
qDebug() << "Loaded unique ID from settings: " << m_CachedUniqueId;
|
||||
}
|
||||
else {
|
||||
// Generate a new unique ID in base 16
|
||||
uint64_t uid;
|
||||
RAND_bytes(reinterpret_cast<unsigned char*>(&uid), sizeof(uid));
|
||||
m_CachedUniqueId = QString::number(uid, 16);
|
||||
m_CachedUniqueId = QString::number(
|
||||
QRandomGenerator64::securelySeeded().generate64(), 16);
|
||||
|
||||
qInfo() << "Generated new unique ID:" << m_CachedUniqueId;
|
||||
qDebug() << "Generated new unique ID: " << m_CachedUniqueId;
|
||||
|
||||
settings.setValue(SER_UNIQUEID, m_CachedUniqueId);
|
||||
}
|
||||
|
||||
@@ -67,7 +67,6 @@ NvHTTP::getServerInfo()
|
||||
serverInfo = openConnectionToString(m_BaseUrlHttps,
|
||||
"serverinfo",
|
||||
nullptr,
|
||||
true,
|
||||
true);
|
||||
// Throws if the request failed
|
||||
verifyResponseStatus(serverInfo);
|
||||
@@ -80,7 +79,6 @@ NvHTTP::getServerInfo()
|
||||
serverInfo = openConnectionToString(m_BaseUrlHttp,
|
||||
"serverinfo",
|
||||
nullptr,
|
||||
true,
|
||||
true);
|
||||
verifyResponseStatus(serverInfo);
|
||||
}
|
||||
@@ -125,11 +123,6 @@ NvHTTP::launchApp(int appId,
|
||||
bool localAudio,
|
||||
int gamepadMask)
|
||||
{
|
||||
int riKeyId;
|
||||
|
||||
memcpy(&riKeyId, streamConfig->remoteInputAesIv, sizeof(riKeyId));
|
||||
riKeyId = qFromBigEndian(riKeyId);
|
||||
|
||||
QString response =
|
||||
openConnectionToString(m_BaseUrlHttps,
|
||||
"launch",
|
||||
@@ -139,7 +132,7 @@ NvHTTP::launchApp(int appId,
|
||||
QString::number(streamConfig->fps)+
|
||||
"&additionalStates=1&sops="+QString::number(sops ? 1 : 0)+
|
||||
"&rikey="+QByteArray(streamConfig->remoteInputAesKey, sizeof(streamConfig->remoteInputAesKey)).toHex()+
|
||||
"&rikeyid="+QString::number(riKeyId)+
|
||||
"&rikeyid="+QString::number(qFromBigEndian(*(int*)streamConfig->remoteInputAesIv))+
|
||||
(streamConfig->enableHdr ?
|
||||
"&hdrMode=1&clientHdrCapVersion=0&clientHdrCapSupportedFlagsInUint32=0&clientHdrCapMetaDataId=NV_STATIC_METADATA_TYPE_1&clientHdrCapDisplayData=0x0x0x0x0x0x0x0x0x0x0" :
|
||||
"")+
|
||||
@@ -156,16 +149,11 @@ NvHTTP::launchApp(int appId,
|
||||
void
|
||||
NvHTTP::resumeApp(PSTREAM_CONFIGURATION streamConfig)
|
||||
{
|
||||
int riKeyId;
|
||||
|
||||
memcpy(&riKeyId, streamConfig->remoteInputAesIv, sizeof(riKeyId));
|
||||
riKeyId = qFromBigEndian(riKeyId);
|
||||
|
||||
QString response =
|
||||
openConnectionToString(m_BaseUrlHttps,
|
||||
"resume",
|
||||
"rikey="+QString(QByteArray(streamConfig->remoteInputAesKey, sizeof(streamConfig->remoteInputAesKey)).toHex())+
|
||||
"&rikeyid="+QString::number(riKeyId)+
|
||||
"&rikeyid="+QString::number(qFromBigEndian(*(int*)streamConfig->remoteInputAesIv))+
|
||||
"&surroundAudioInfo="+getSurroundAudioInfoString(streamConfig->audioConfiguration),
|
||||
false);
|
||||
|
||||
@@ -227,7 +215,6 @@ NvHTTP::getAppList()
|
||||
QString appxml = openConnectionToString(m_BaseUrlHttps,
|
||||
"applist",
|
||||
nullptr,
|
||||
true,
|
||||
true);
|
||||
verifyResponseStatus(appxml);
|
||||
|
||||
@@ -278,10 +265,7 @@ NvHTTP::verifyResponseStatus(QString xml)
|
||||
else
|
||||
{
|
||||
QString statusMessage = xmlReader.attributes().value("status_message").toString();
|
||||
if (statusCode != 401) {
|
||||
// 401 is expected for unpaired PCs when we fetch serverinfo over HTTPS
|
||||
qWarning() << "Request failed:" << statusCode << statusMessage;
|
||||
}
|
||||
qDebug() << "Request failed: " << statusCode << " " << statusMessage;
|
||||
throw GfeHttpResponseException(statusCode, statusMessage);
|
||||
}
|
||||
}
|
||||
@@ -341,15 +325,12 @@ QString
|
||||
NvHTTP::openConnectionToString(QUrl baseUrl,
|
||||
QString command,
|
||||
QString arguments,
|
||||
bool enableTimeout,
|
||||
bool suppressLogging)
|
||||
bool enableTimeout)
|
||||
{
|
||||
QNetworkReply* reply = openConnection(baseUrl, command, arguments, enableTimeout, suppressLogging);
|
||||
QNetworkReply* reply = openConnection(baseUrl, command, arguments, enableTimeout);
|
||||
QString ret;
|
||||
|
||||
QTextStream stream(reply);
|
||||
stream.setCodec("UTF-8");
|
||||
ret = stream.readAll();
|
||||
ret = QTextStream(reply).readAll();
|
||||
delete reply;
|
||||
|
||||
return ret;
|
||||
@@ -359,8 +340,7 @@ QNetworkReply*
|
||||
NvHTTP::openConnection(QUrl baseUrl,
|
||||
QString command,
|
||||
QString arguments,
|
||||
bool enableTimeout,
|
||||
bool suppressLogging)
|
||||
bool enableTimeout)
|
||||
{
|
||||
// Build a URL for the request
|
||||
QUrl url(baseUrl);
|
||||
@@ -386,17 +366,13 @@ NvHTTP::openConnection(QUrl baseUrl,
|
||||
{
|
||||
QTimer::singleShot(REQUEST_TIMEOUT_MS, &loop, SLOT(quit()));
|
||||
}
|
||||
if (!suppressLogging) {
|
||||
qInfo() << "Executing request:" << url.toString();
|
||||
}
|
||||
qDebug() << "Executing request: " << url.toString();
|
||||
loop.exec(QEventLoop::ExcludeUserInputEvents);
|
||||
|
||||
// Abort the request if it timed out
|
||||
if (!reply->isFinished())
|
||||
{
|
||||
if (!suppressLogging) {
|
||||
qWarning() << "Aborting timed out request for" << url.toString();
|
||||
}
|
||||
qDebug() << "Aborting timed out request for " << url.toString();
|
||||
reply->abort();
|
||||
}
|
||||
|
||||
@@ -407,9 +383,7 @@ NvHTTP::openConnection(QUrl baseUrl,
|
||||
// Handle error
|
||||
if (reply->error() != QNetworkReply::NoError)
|
||||
{
|
||||
if (!suppressLogging) {
|
||||
qWarning() << command << " request failed with error " << reply->error();
|
||||
}
|
||||
qDebug() << command << " request failed with error " << reply->error();
|
||||
GfeHttpResponseException exception(reply->error(), reply->errorString());
|
||||
delete reply;
|
||||
throw exception;
|
||||
|
||||
@@ -107,8 +107,7 @@ public:
|
||||
openConnectionToString(QUrl baseUrl,
|
||||
QString command,
|
||||
QString arguments,
|
||||
bool enableTimeout,
|
||||
bool suppressLogging = false);
|
||||
bool enableTimeout);
|
||||
|
||||
static
|
||||
QVector<int>
|
||||
@@ -144,8 +143,7 @@ private:
|
||||
openConnection(QUrl baseUrl,
|
||||
QString command,
|
||||
QString arguments,
|
||||
bool enableTimeout,
|
||||
bool suppressLogging = false);
|
||||
bool enableTimeout);
|
||||
|
||||
QString m_Address;
|
||||
QNetworkAccessManager m_Nam;
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#include "nvpairingmanager.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include <QRandomGenerator>
|
||||
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/aes.h>
|
||||
#include <openssl/rand.h>
|
||||
@@ -19,7 +21,7 @@ NvPairingManager::NvPairingManager(QString address) :
|
||||
BIO_free_all(bio);
|
||||
if (m_Cert == nullptr)
|
||||
{
|
||||
throw std::runtime_error("Unable to load certificate");
|
||||
throw new std::runtime_error("Unable to load certificate");
|
||||
}
|
||||
|
||||
QByteArray pk = IdentityManager::get()->getPrivateKey();
|
||||
@@ -30,7 +32,7 @@ NvPairingManager::NvPairingManager(QString address) :
|
||||
BIO_free_all(bio);
|
||||
if (m_PrivateKey == nullptr)
|
||||
{
|
||||
throw std::runtime_error("Unable to load private key");
|
||||
throw new std::runtime_error("Unable to load private key");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,16 +89,14 @@ NvPairingManager::getSignatureFromPemCert(QByteArray certificate)
|
||||
X509* cert = PEM_read_bio_X509(bio, nullptr, nullptr, nullptr);
|
||||
BIO_free_all(bio);
|
||||
|
||||
#if (OPENSSL_VERSION_NUMBER < 0x10002000L)
|
||||
ASN1_BIT_STRING *asnSignature = cert->signature;
|
||||
#elif (OPENSSL_VERSION_NUMBER < 0x10100000L)
|
||||
ASN1_BIT_STRING *asnSignature;
|
||||
X509_get0_signature(&asnSignature, NULL, cert);
|
||||
#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
|
||||
ASN1_BIT_STRING *asnSignature;
|
||||
#else
|
||||
const ASN1_BIT_STRING *asnSignature;
|
||||
X509_get0_signature(&asnSignature, NULL, cert);
|
||||
const ASN1_BIT_STRING *asnSignature;
|
||||
#endif
|
||||
|
||||
X509_get0_signature(&asnSignature, NULL, cert);
|
||||
|
||||
QByteArray signature(reinterpret_cast<char*>(asnSignature->data), asnSignature->length);
|
||||
|
||||
X509_free(cert);
|
||||
@@ -164,7 +164,7 @@ NvPairingManager::PairState
|
||||
NvPairingManager::pair(QString appVersion, QString pin)
|
||||
{
|
||||
int serverMajorVersion = NvHTTP::parseQuad(appVersion).at(0);
|
||||
qInfo() << "Pairing with server generation:" << serverMajorVersion;
|
||||
qDebug() << "Pairing with server generation: " << serverMajorVersion;
|
||||
|
||||
QCryptographicHash::Algorithm hashAlgo;
|
||||
int hashLength;
|
||||
@@ -196,14 +196,14 @@ NvPairingManager::pair(QString appVersion, QString pin)
|
||||
NvHTTP::verifyResponseStatus(getCert);
|
||||
if (NvHTTP::getXmlString(getCert, "paired") != "1")
|
||||
{
|
||||
qCritical() << "Failed pairing at stage #1";
|
||||
qDebug() << "Failed pairing at stage #1";
|
||||
return PairState::FAILED;
|
||||
}
|
||||
|
||||
QByteArray serverCert = NvHTTP::getXmlStringFromHex(getCert, "plaincert");
|
||||
if (serverCert == nullptr)
|
||||
{
|
||||
qCritical() << "Server likely already pairing";
|
||||
qDebug() << "Server likely already pairing";
|
||||
m_Http.openConnectionToString(m_Http.m_BaseUrlHttp, "unpair", nullptr, true);
|
||||
return PairState::ALREADY_IN_PROGRESS;
|
||||
}
|
||||
@@ -218,7 +218,7 @@ NvPairingManager::pair(QString appVersion, QString pin)
|
||||
NvHTTP::verifyResponseStatus(challengeXml);
|
||||
if (NvHTTP::getXmlString(challengeXml, "paired") != "1")
|
||||
{
|
||||
qCritical() << "Failed pairing at stage #2";
|
||||
qDebug() << "Failed pairing at stage #2";
|
||||
m_Http.openConnectionToString(m_Http.m_BaseUrlHttp, "unpair", nullptr, true);
|
||||
return PairState::FAILED;
|
||||
}
|
||||
@@ -228,15 +228,13 @@ NvPairingManager::pair(QString appVersion, QString pin)
|
||||
QByteArray challengeResponse;
|
||||
QByteArray serverResponse(challengeResponseData.data(), hashLength);
|
||||
|
||||
#if (OPENSSL_VERSION_NUMBER < 0x10002000L)
|
||||
ASN1_BIT_STRING *asnSignature = m_Cert->signature;
|
||||
#elif (OPENSSL_VERSION_NUMBER < 0x10100000L)
|
||||
#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
|
||||
ASN1_BIT_STRING *asnSignature;
|
||||
X509_get0_signature(&asnSignature, NULL, m_Cert);
|
||||
#else
|
||||
#else
|
||||
const ASN1_BIT_STRING *asnSignature;
|
||||
#endif
|
||||
|
||||
X509_get0_signature(&asnSignature, NULL, m_Cert);
|
||||
#endif
|
||||
|
||||
challengeResponse.append(challengeResponseData.data() + hashLength, 16);
|
||||
challengeResponse.append(reinterpret_cast<char*>(asnSignature->data), asnSignature->length);
|
||||
@@ -251,7 +249,7 @@ NvPairingManager::pair(QString appVersion, QString pin)
|
||||
NvHTTP::verifyResponseStatus(respXml);
|
||||
if (NvHTTP::getXmlString(respXml, "paired") != "1")
|
||||
{
|
||||
qCritical() << "Failed pairing at stage #3";
|
||||
qDebug() << "Failed pairing at stage #3";
|
||||
m_Http.openConnectionToString(m_Http.m_BaseUrlHttp, "unpair", nullptr, true);
|
||||
return PairState::FAILED;
|
||||
}
|
||||
@@ -264,7 +262,7 @@ NvPairingManager::pair(QString appVersion, QString pin)
|
||||
serverSignature,
|
||||
serverCert))
|
||||
{
|
||||
qCritical() << "MITM detected";
|
||||
qDebug() << "MITM detected";
|
||||
m_Http.openConnectionToString(m_Http.m_BaseUrlHttp, "unpair", nullptr, true);
|
||||
return PairState::FAILED;
|
||||
}
|
||||
@@ -275,7 +273,7 @@ NvPairingManager::pair(QString appVersion, QString pin)
|
||||
expectedResponseData.append(serverSecret);
|
||||
if (QCryptographicHash::hash(expectedResponseData, hashAlgo) != serverResponse)
|
||||
{
|
||||
qCritical() << "Incorrect PIN";
|
||||
qDebug() << "Incorrect PIN";
|
||||
m_Http.openConnectionToString(m_Http.m_BaseUrlHttp, "unpair", nullptr, true);
|
||||
return PairState::PIN_WRONG;
|
||||
}
|
||||
@@ -292,7 +290,7 @@ NvPairingManager::pair(QString appVersion, QString pin)
|
||||
NvHTTP::verifyResponseStatus(secretRespXml);
|
||||
if (NvHTTP::getXmlString(secretRespXml, "paired") != "1")
|
||||
{
|
||||
qCritical() << "Failed pairing at stage #4";
|
||||
qDebug() << "Failed pairing at stage #4";
|
||||
m_Http.openConnectionToString(m_Http.m_BaseUrlHttp, "unpair", nullptr, true);
|
||||
return PairState::FAILED;
|
||||
}
|
||||
@@ -304,7 +302,7 @@ NvPairingManager::pair(QString appVersion, QString pin)
|
||||
NvHTTP::verifyResponseStatus(pairChallengeXml);
|
||||
if (NvHTTP::getXmlString(pairChallengeXml, "paired") != "1")
|
||||
{
|
||||
qCritical() << "Failed pairing at stage #5";
|
||||
qDebug() << "Failed pairing at stage #5";
|
||||
m_Http.openConnectionToString(m_Http.m_BaseUrlHttp, "unpair", nullptr, true);
|
||||
return PairState::FAILED;
|
||||
}
|
||||
|
||||
@@ -1,88 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<component type="desktop">
|
||||
<id>com.moonlight_stream.Moonlight</id>
|
||||
<metadata_license>CC0-1.0</metadata_license>
|
||||
<project_license>GPL-3.0+</project_license>
|
||||
<name>Moonlight</name>
|
||||
<summary>Stream games from your NVIDIA GameStream-enabled PC</summary>
|
||||
|
||||
<description>
|
||||
<p>Moonlight can stream games and other applications from a PC with an NVIDIA GeForce GTX 600-series or higher GPU and GeForce Experience installed.</p>
|
||||
<p>Features include:</p>
|
||||
<ul>
|
||||
<li>Streaming at up to 4K resolution</li>
|
||||
<li>Support for up to 120 FPS streaming on high refresh rate monitors</li>
|
||||
<li>Hardware accelerated video decoding with VAAPI and VDPAU support</li>
|
||||
<li>5.1 surround sound audio support</li>
|
||||
<li>HEVC support for better video compression efficiency</li>
|
||||
<li>Gamepad support with SDL mapping compatibility</li>
|
||||
</ul>
|
||||
</description>
|
||||
|
||||
<url type="homepage">https://moonlight-stream.com</url>
|
||||
<url type="bugtracker">https://github.com/moonlight-stream/moonlight-qt/issues</url>
|
||||
<url type="help">https://github.com/moonlight-stream/moonlight-docs/wiki/Setup-Guide</url>
|
||||
|
||||
<screenshots>
|
||||
<screenshot type="default">
|
||||
<image>https://moonlight-stream.com/appstream_resources/moonlight_screenshot_1.png</image>
|
||||
</screenshot>
|
||||
<screenshot>
|
||||
<image>https://moonlight-stream.com/appstream_resources/moonlight_screenshot_2.png</image>
|
||||
</screenshot>
|
||||
</screenshots>
|
||||
|
||||
<releases>
|
||||
<release version="0.1.0" date="2018-08-05">
|
||||
<description>
|
||||
<p>New features:</p>
|
||||
<ul>
|
||||
<li>Allow streaming at the client's native resolution</li>
|
||||
<li>VDPAU hardware decoding support for NVIDIA GPUs</li>
|
||||
<li>Updated UI to replace status text with icons</li>
|
||||
<li>Stream window is now resizable</li>
|
||||
<li>Display warnings during game launch for configuration issues</li>
|
||||
</ul>
|
||||
<p>Bugfixes:</p>
|
||||
<ul>
|
||||
<li>Gamepad input now works even if the app doesn't have focus</li>
|
||||
<li>Fixed streaming black screen if the host supported HEVC but the client didn't</li>
|
||||
<li>Fixed broken video scaling causing extra stretching and off-center video</li>
|
||||
<li>Fixed gamepad input issue causing some Y axis inputs to be reversed</li>
|
||||
</ul>
|
||||
</description>
|
||||
</release>
|
||||
<release version="0.0.5" date="2018-08-01">
|
||||
<description>
|
||||
<p>Changes from 0.0.4:</p>
|
||||
<ul>
|
||||
<li>Fixed a bug causing increased frame drops and input lag</li>
|
||||
<li>Added support for quitting running games</li>
|
||||
<li>Added support for waking sleeping PCs with Wake-on-LAN</li>
|
||||
<li>Increased the FPS limit to 120 FPS</li>
|
||||
</ul>
|
||||
</description>
|
||||
</release>
|
||||
<release version="0.0.4a" date="2018-07-30">
|
||||
<description>
|
||||
<p>Initial pre-alpha release for Linux. Please file bugs!</p>
|
||||
</description>
|
||||
</release>
|
||||
</releases>
|
||||
|
||||
<categories>
|
||||
<category>Game</category>
|
||||
<category>Qt</category>
|
||||
</categories>
|
||||
|
||||
<developer_name>Moonlight Game Streaming Team</developer_name>
|
||||
<update_contact>[email protected]</update_contact>
|
||||
|
||||
<launchable type="desktop-id">com.moonlight_stream.Moonlight.desktop</launchable>
|
||||
|
||||
<provides>
|
||||
<binary>moonlight</binary>
|
||||
</provides>
|
||||
|
||||
<content_rating type="oars-1.0" />
|
||||
</component>
|
||||
@@ -1,9 +0,0 @@
|
||||
[Desktop Entry]
|
||||
Name=Moonlight
|
||||
Comment=Stream games from your NVIDIA GameStream-enabled PC
|
||||
Exec=moonlight
|
||||
Icon=moonlight
|
||||
Terminal=false
|
||||
Type=Application
|
||||
Categories=Qt;Game;
|
||||
Keywords=nvidia;gamestream;stream;
|
||||
@@ -1,5 +1,4 @@
|
||||
import QtQuick 2.9
|
||||
import QtQuick.Dialogs 1.3
|
||||
import QtQuick.Controls 2.2
|
||||
|
||||
import AppModel 1.0
|
||||
@@ -13,7 +12,7 @@ GridView {
|
||||
id: appGrid
|
||||
anchors.fill: parent
|
||||
anchors.leftMargin: (parent.width % (cellWidth + anchors.rightMargin)) / 2
|
||||
anchors.topMargin: 20
|
||||
anchors.topMargin: 5
|
||||
anchors.rightMargin: 5
|
||||
anchors.bottomMargin: 5
|
||||
cellWidth: 225; cellHeight: 350;
|
||||
@@ -51,6 +50,12 @@ GridView {
|
||||
delegate: Item {
|
||||
width: 200; height: 300;
|
||||
|
||||
Component.onCompleted: {
|
||||
if (model.running) {
|
||||
appNameText.text = "<font color=\"green\">Running</font><font color=\"white\"> - </font>" + appNameText.text
|
||||
}
|
||||
}
|
||||
|
||||
Image {
|
||||
id: appIcon
|
||||
anchors.horizontalCenter: parent.horizontalCenter;
|
||||
@@ -61,110 +66,29 @@ GridView {
|
||||
}
|
||||
}
|
||||
|
||||
Image {
|
||||
id: runningIcon
|
||||
anchors.centerIn: appIcon
|
||||
visible: model.running
|
||||
source: "qrc:/res/baseline-play_circle_filled_white-48px.svg"
|
||||
sourceSize {
|
||||
width: 75
|
||||
height: 75
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
id: appNameText
|
||||
text: model.name
|
||||
color: "white"
|
||||
|
||||
width: parent.width
|
||||
height: 125
|
||||
height: 100
|
||||
anchors.top: appIcon.bottom
|
||||
font.pointSize: 22
|
||||
font.pointSize: 26
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
wrapMode: Text.Wrap
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
|
||||
function launchOrResumeSelectedApp()
|
||||
{
|
||||
var runningIndex = appModel.getRunningAppIndex()
|
||||
if (runningIndex >= 0 && runningIndex !== index) {
|
||||
quitAppDialog.appName = appModel.getRunningAppName()
|
||||
quitAppDialog.segueToStream = true
|
||||
quitAppDialog.open()
|
||||
return
|
||||
}
|
||||
|
||||
var component = Qt.createComponent("StreamSegue.qml")
|
||||
var segue = component.createObject(stackView)
|
||||
segue.appName = model.name
|
||||
segue.session = appModel.createSessionForApp(index)
|
||||
stackView.push(segue)
|
||||
}
|
||||
|
||||
MessageDialog {
|
||||
id: quitAppDialog
|
||||
modality:Qt.WindowModal
|
||||
property string appName : "";
|
||||
property bool segueToStream : false
|
||||
text:"Are you sure you want to quit " + appName +"? Any unsaved progress will be lost."
|
||||
standardButtons: StandardButton.Yes | StandardButton.No
|
||||
onYes: {
|
||||
var component = Qt.createComponent("QuitSegue.qml")
|
||||
var segue = component.createObject(stackView)
|
||||
segue.appName = appName
|
||||
if (segueToStream) {
|
||||
// Store the session and app name if we're going to stream after
|
||||
// successfully quitting the old app.
|
||||
segue.nextAppName = model.name
|
||||
segue.nextSession = appModel.createSessionForApp(index)
|
||||
}
|
||||
else {
|
||||
segue.nextAppName = null
|
||||
segue.nextSession = null
|
||||
}
|
||||
|
||||
stackView.push(segue)
|
||||
|
||||
// Trigger the quit after pushing the quit segue on screen
|
||||
appModel.quitRunningApp()
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||
onClicked: {
|
||||
if (mouse.button === Qt.LeftButton) {
|
||||
// Nothing is running or this app is running
|
||||
launchOrResumeSelectedApp()
|
||||
}
|
||||
else {
|
||||
// Right click
|
||||
appContextMenu.open()
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO: Check if a different game is running
|
||||
|
||||
Menu {
|
||||
id: appContextMenu
|
||||
MenuItem {
|
||||
text: model.running ? "Resume Game" : "Launch Game"
|
||||
onTriggered: {
|
||||
appContextMenu.close()
|
||||
launchOrResumeSelectedApp()
|
||||
}
|
||||
height: visible ? implicitHeight : 0
|
||||
}
|
||||
MenuItem {
|
||||
text: "Quit Game"
|
||||
onTriggered: {
|
||||
quitAppDialog.appName = appModel.getRunningAppName()
|
||||
quitAppDialog.segueToStream = false
|
||||
quitAppDialog.open()
|
||||
}
|
||||
visible: model.running
|
||||
height: visible ? implicitHeight : 0
|
||||
var component = Qt.createComponent("StreamSegue.qml")
|
||||
var segue = component.createObject(stackView)
|
||||
segue.appname = model.name
|
||||
segue.session = appModel.createSessionForApp(index)
|
||||
stackView.push(segue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ import QtQuick.Layouts 1.3
|
||||
import ComputerModel 1.0
|
||||
|
||||
import ComputerManager 1.0
|
||||
import StreamingPreferences 1.0
|
||||
|
||||
GridView {
|
||||
property ComputerModel computerModel : createModel()
|
||||
@@ -14,7 +13,7 @@ GridView {
|
||||
id: pcGrid
|
||||
anchors.fill: parent
|
||||
anchors.leftMargin: (parent.width % (cellWidth + anchors.rightMargin)) / 2
|
||||
anchors.topMargin: 20
|
||||
anchors.topMargin: 5
|
||||
anchors.rightMargin: 5
|
||||
anchors.bottomMargin: 5
|
||||
cellWidth: 350; cellHeight: 350;
|
||||
@@ -26,17 +25,9 @@ GridView {
|
||||
// routine to run, but only if we start as invisible
|
||||
visible: false
|
||||
|
||||
StreamingPreferences {
|
||||
id: prefs
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
// Setup signals on CM
|
||||
ComputerManager.computerAddCompleted.connect(addComplete)
|
||||
|
||||
if (!prefs.hasAnyHardwareAcceleration()) {
|
||||
noHwDecoderDialog.open()
|
||||
}
|
||||
}
|
||||
|
||||
onVisibleChanged: {
|
||||
@@ -81,14 +72,14 @@ GridView {
|
||||
return model
|
||||
}
|
||||
|
||||
model: computerModel
|
||||
model: createModel()
|
||||
|
||||
delegate: Item {
|
||||
width: 300; height: 300;
|
||||
|
||||
Image {
|
||||
id: pcIcon
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.horizontalCenter: parent.horizontalCenter;
|
||||
source: {
|
||||
model.addPc ? "qrc:/res/ic_add_to_queue_white_48px.svg" : "qrc:/res/ic_tv_white_48px.svg"
|
||||
}
|
||||
@@ -98,30 +89,6 @@ GridView {
|
||||
}
|
||||
}
|
||||
|
||||
Image {
|
||||
// TODO: Tooltip
|
||||
id: stateIcon
|
||||
anchors.horizontalCenter: pcIcon.horizontalCenter
|
||||
anchors.verticalCenter: pcIcon.verticalCenter
|
||||
anchors.verticalCenterOffset: -10
|
||||
visible: !model.addPc && !model.statusUnknown && (!model.online || !model.paired)
|
||||
source: !model.online ? "qrc:/res/baseline-warning-24px.svg" : "qrc:/res/baseline-lock-24px.svg"
|
||||
sourceSize {
|
||||
width: 75
|
||||
height: 75
|
||||
}
|
||||
}
|
||||
|
||||
BusyIndicator {
|
||||
id: statusUnknownSpinner
|
||||
anchors.horizontalCenter: pcIcon.horizontalCenter
|
||||
anchors.verticalCenter: pcIcon.verticalCenter
|
||||
anchors.verticalCenterOffset: -10
|
||||
width: 75
|
||||
height: 75
|
||||
visible: !model.addPc && model.statusUnknown
|
||||
}
|
||||
|
||||
Text {
|
||||
id: pcNameText
|
||||
text: model.name
|
||||
@@ -134,70 +101,76 @@ GridView {
|
||||
wrapMode: Text.Wrap
|
||||
}
|
||||
|
||||
Menu {
|
||||
id: pcContextMenu
|
||||
MenuItem {
|
||||
text: "Wake PC"
|
||||
onTriggered: computerModel.wakeComputer(index)
|
||||
visible: !model.addPc && !model.online && model.wakeable
|
||||
height: visible ? implicitHeight : 0
|
||||
}
|
||||
MenuItem {
|
||||
text: "Delete PC"
|
||||
onTriggered: {
|
||||
deletePcDialog.pcIndex = index
|
||||
// get confirmation first, actual closing is called from the dialog
|
||||
deletePcDialog.open()
|
||||
Text {
|
||||
function getStatusText(model)
|
||||
{
|
||||
if (model.online) {
|
||||
var text = "<font color=\"green\">Online</font>"
|
||||
text += "<font color=\"white\"> - </font>"
|
||||
if (model.paired) {
|
||||
text += "<font color=\"skyblue\">Paired</font>"
|
||||
}
|
||||
else if (model.busy) {
|
||||
text += "<font color=\"red\">Busy</font>"
|
||||
}
|
||||
else {
|
||||
text += "<font color=\"red\">Not Paired</font>"
|
||||
}
|
||||
return text
|
||||
}
|
||||
else {
|
||||
return "<font color=\"red\">Offline</font>";
|
||||
}
|
||||
}
|
||||
|
||||
id: pcPairedText
|
||||
text: getStatusText(model)
|
||||
visible: !model.addPc
|
||||
|
||||
width: parent.width
|
||||
anchors.top: pcNameText.bottom
|
||||
font.pointSize: 24
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
acceptedButtons: Qt.LeftButton | Qt.RightButton;
|
||||
onClicked: {
|
||||
if(mouse.button === Qt.LeftButton) {
|
||||
if (model.addPc) {
|
||||
addPcDialog.open()
|
||||
if (model.addPc) {
|
||||
addPcDialog.open()
|
||||
}
|
||||
else if (model.online) {
|
||||
if (model.paired) {
|
||||
// go to game view
|
||||
var component = Qt.createComponent("AppView.qml")
|
||||
var appView = component.createObject(stackView)
|
||||
appView.computerIndex = index
|
||||
appView.objectName = model.name
|
||||
stackView.push(appView)
|
||||
}
|
||||
else if (model.online) {
|
||||
if (model.paired) {
|
||||
// go to game view
|
||||
var component = Qt.createComponent("AppView.qml")
|
||||
var appView = component.createObject(stackView)
|
||||
appView.computerIndex = index
|
||||
appView.objectName = model.name
|
||||
stackView.push(appView)
|
||||
else {
|
||||
if (!model.busy) {
|
||||
var pin = ("0000" + Math.floor(Math.random() * 10000)).slice(-4)
|
||||
|
||||
// Stop polling, since pairing may make GFE unresponsive
|
||||
ComputerManager.stopPollingAsync()
|
||||
|
||||
// Kick off pairing in the background
|
||||
computerModel.pairComputer(index, pin)
|
||||
|
||||
// Display the pairing dialog
|
||||
pairDialog.pin = pin
|
||||
pairDialog.open()
|
||||
}
|
||||
else {
|
||||
if (!model.busy) {
|
||||
var pin = ("0000" + Math.floor(Math.random() * 10000)).slice(-4)
|
||||
|
||||
// Stop polling, since pairing may make GFE unresponsive
|
||||
ComputerManager.stopPollingAsync()
|
||||
|
||||
// Kick off pairing in the background
|
||||
computerModel.pairComputer(index, pin)
|
||||
|
||||
// Display the pairing dialog
|
||||
pairDialog.pin = pin
|
||||
pairDialog.open()
|
||||
}
|
||||
else {
|
||||
// cannot pair while something is streaming or attempting to pair
|
||||
errorDialog.text = "This PC is currently busy. Make sure to quit any running games and try again."
|
||||
errorDialog.open()
|
||||
}
|
||||
// cannot pair while something is streaming or attempting to pair
|
||||
errorDialog.text = "This PC is currently busy. Make sure to quit any running games and try again."
|
||||
errorDialog.open()
|
||||
}
|
||||
} else if(!model.online) {
|
||||
pcContextMenu.open()
|
||||
}
|
||||
|
||||
}
|
||||
else { // right click
|
||||
if(!model.addPc) { // but only for actual PCs, not the add-pc option
|
||||
pcContextMenu.open()
|
||||
}
|
||||
else {
|
||||
// TODO: Wake on LAN and delete PC options
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -211,19 +184,6 @@ GridView {
|
||||
standardButtons: StandardButton.Ok
|
||||
}
|
||||
|
||||
MessageDialog {
|
||||
id: noHwDecoderDialog
|
||||
modality:Qt.WindowModal
|
||||
icon: StandardIcon.Warning
|
||||
standardButtons: StandardButton.Ok | StandardButton.Help
|
||||
text: "No functioning hardware accelerated H.264 video decoder was detected by Moonlight. " +
|
||||
"Your streaming performance may be severely degraded in this configuration. " +
|
||||
"Click the Help button for more information on solving this problem."
|
||||
onHelp: {
|
||||
Qt.openUrlExternally("https://github.com/moonlight-stream/moonlight-docs/wiki/Fixing-Hardware-Decoding-Problems");
|
||||
}
|
||||
}
|
||||
|
||||
MessageDialog {
|
||||
id: pairDialog
|
||||
// don't allow edits to the rest of the window while open
|
||||
@@ -236,19 +196,6 @@ GridView {
|
||||
}
|
||||
}
|
||||
|
||||
MessageDialog {
|
||||
id: deletePcDialog
|
||||
// don't allow edits to the rest of the window while open
|
||||
modality:Qt.WindowModal
|
||||
property int pcIndex : -1;
|
||||
text:"Are you sure you want to remove this PC?"
|
||||
standardButtons: StandardButton.Yes | StandardButton.No
|
||||
onYes: {
|
||||
console.log("deleting PC pairing for PC at index: " + pcIndex)
|
||||
computerModel.deleteComputer(pcIndex);
|
||||
}
|
||||
}
|
||||
|
||||
Dialog {
|
||||
id: addPcDialog
|
||||
property string label: "Enter the IP address of your GameStream PC"
|
||||
|
||||
@@ -1,86 +0,0 @@
|
||||
import QtQuick 2.0
|
||||
import QtQuick.Controls 2.2
|
||||
import QtQuick.Dialogs 1.3
|
||||
|
||||
import ComputerManager 1.0
|
||||
import Session 1.0
|
||||
|
||||
Item {
|
||||
property string appName
|
||||
property Session nextSession : null
|
||||
property string nextAppName : ""
|
||||
|
||||
property string stageText : "Quitting " + appName + "..."
|
||||
|
||||
anchors.fill: parent
|
||||
|
||||
// The StackView will trigger a visibility change when
|
||||
// we're pushed onto it, causing our onVisibleChanged
|
||||
// routine to run, but only if we start as invisible
|
||||
visible: false
|
||||
|
||||
function quitAppCompleted(error)
|
||||
{
|
||||
// Display a failed dialog if we got an error
|
||||
if (error !== undefined) {
|
||||
errorDialog.text = error
|
||||
errorDialog.open()
|
||||
}
|
||||
|
||||
// Exit this view
|
||||
stackView.pop()
|
||||
|
||||
// If we're supposed to launch another game after this, do so now
|
||||
if (error === undefined && nextSession !== null) {
|
||||
var component = Qt.createComponent("StreamSegue.qml")
|
||||
var segue = component.createObject(stackView)
|
||||
segue.appName = nextAppName
|
||||
segue.session = nextSession
|
||||
stackView.push(segue)
|
||||
}
|
||||
}
|
||||
|
||||
onVisibleChanged: {
|
||||
if (visible) {
|
||||
// Connect the quit completion signal
|
||||
ComputerManager.quitAppCompleted.connect(quitAppCompleted)
|
||||
|
||||
// We must be polling or we won't get the quitAppCompleted() callback
|
||||
ComputerManager.startPolling()
|
||||
}
|
||||
else {
|
||||
// Disconnect the signal
|
||||
ComputerManager.quitAppCompleted.disconnect(quitAppCompleted)
|
||||
|
||||
// Stop polling when this view is not on top
|
||||
ComputerManager.stopPollingAsync()
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
anchors.centerIn: parent
|
||||
spacing: 5
|
||||
|
||||
BusyIndicator {
|
||||
id: stageSpinner
|
||||
}
|
||||
|
||||
Label {
|
||||
id: stageLabel
|
||||
height: stageSpinner.height
|
||||
text: stageText
|
||||
font.pointSize: 20
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
|
||||
wrapMode: Text.Wrap
|
||||
color: "white"
|
||||
}
|
||||
}
|
||||
|
||||
MessageDialog {
|
||||
id: errorDialog
|
||||
modality:Qt.WindowModal
|
||||
icon: StandardIcon.Critical
|
||||
standardButtons: StandardButton.Ok
|
||||
}
|
||||
}
|
||||
@@ -16,13 +16,14 @@ ScrollView {
|
||||
}
|
||||
|
||||
Column {
|
||||
padding: 10
|
||||
id: settingsColumn1
|
||||
width: settingsPage.width / 2 - padding
|
||||
x: 10
|
||||
y: 10
|
||||
width: settingsPage.width
|
||||
height: 400
|
||||
|
||||
GroupBox {
|
||||
id: basicSettingsGroupBox
|
||||
width: (parent.width - 2 * parent.padding)
|
||||
width: (parent.width - 20)
|
||||
padding: 12
|
||||
title: "<font color=\"skyblue\">Basic Settings</font>"
|
||||
font.pointSize: 12
|
||||
@@ -34,7 +35,7 @@ ScrollView {
|
||||
Label {
|
||||
width: parent.width
|
||||
id: resFPStitle
|
||||
text: qsTr("Resolution and FPS")
|
||||
text: qsTr("Resolution and FPS target")
|
||||
font.pointSize: 12
|
||||
wrapMode: Text.Wrap
|
||||
color: "white"
|
||||
@@ -43,153 +44,84 @@ ScrollView {
|
||||
Label {
|
||||
width: parent.width
|
||||
id: resFPSdesc
|
||||
text: qsTr("Setting values too high for your PC may cause lag, stuttering, or errors.")
|
||||
text: qsTr("Setting values too high for your device may cause lag or crashes")
|
||||
font.pointSize: 9
|
||||
wrapMode: Text.Wrap
|
||||
color: "white"
|
||||
}
|
||||
|
||||
Row {
|
||||
spacing: 5
|
||||
|
||||
ComboBox {
|
||||
// ignore setting the index at first, and actually set it when the component is loaded
|
||||
Component.onCompleted: {
|
||||
// Add native resolutions for all attached displays
|
||||
for (var displayIndex = 0;; displayIndex++) {
|
||||
var screenRect = prefs.getDisplayResolution(displayIndex)
|
||||
if (screenRect.width === 0) {
|
||||
// Exceeded max count of displays
|
||||
break
|
||||
}
|
||||
|
||||
var indexToAdd = 0
|
||||
for (var j = 0; j < resolutionComboBox.count; j++) {
|
||||
var existing_width = parseInt(resolutionListModel.get(j).video_width);
|
||||
var existing_height = parseInt(resolutionListModel.get(j).video_height);
|
||||
|
||||
if (screenRect.width === existing_width && screenRect.height === existing_height) {
|
||||
// Duplicate entry, skip
|
||||
indexToAdd = -1
|
||||
break
|
||||
}
|
||||
else if (screenRect.width * screenRect.height > existing_width * existing_height) {
|
||||
// Candidate entrypoint after this entry
|
||||
indexToAdd = j + 1
|
||||
}
|
||||
}
|
||||
|
||||
// Insert this display's resolution if it's not a duplicate
|
||||
if (indexToAdd >= 0) {
|
||||
resolutionListModel.insert(indexToAdd,
|
||||
{
|
||||
"text": "Native ("+screenRect.width+"x"+screenRect.height+")",
|
||||
"video_width": ""+screenRect.width,
|
||||
"video_height": ""+screenRect.height
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// load the saved width/height, and iterate through the ComboBox until a match is found
|
||||
// and set it to that index.
|
||||
var saved_width = prefs.width
|
||||
var saved_height = prefs.height
|
||||
currentIndex = 0
|
||||
for (var i = 0; i < resolutionComboBox.count; i++) {
|
||||
var el_width = parseInt(resolutionListModel.get(i).video_width);
|
||||
var el_height = parseInt(resolutionListModel.get(i).video_height);
|
||||
|
||||
// Pick the highest value lesser or equal to the saved resolution
|
||||
if (saved_width * saved_height >= el_width * el_height) {
|
||||
currentIndex = i
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
id: resolutionComboBox
|
||||
width: 200
|
||||
textRole: "text"
|
||||
model: ListModel {
|
||||
id: resolutionListModel
|
||||
// Other elements may be added at runtime
|
||||
// based on attached display resolution
|
||||
ListElement {
|
||||
text: "720p"
|
||||
video_width: "1280"
|
||||
video_height: "720"
|
||||
}
|
||||
ListElement {
|
||||
text: "1080p"
|
||||
video_width: "1920"
|
||||
video_height: "1080"
|
||||
}
|
||||
ListElement {
|
||||
text: "1440p"
|
||||
video_width: "2560"
|
||||
video_height: "1440"
|
||||
}
|
||||
ListElement {
|
||||
text: "4K"
|
||||
video_width: "3840"
|
||||
video_height: "2160"
|
||||
}
|
||||
}
|
||||
// ::onActivated must be used, as it only listens for when the index is changed by a human
|
||||
onActivated : {
|
||||
prefs.width = parseInt(resolutionListModel.get(currentIndex).video_width)
|
||||
prefs.height = parseInt(resolutionListModel.get(currentIndex).video_height)
|
||||
|
||||
prefs.bitrateKbps = prefs.getDefaultBitrate(prefs.width, prefs.height, prefs.fps);
|
||||
slider.value = prefs.bitrateKbps
|
||||
ComboBox {
|
||||
// ignore setting the index at first, and actually set it when the component is loaded
|
||||
Component.onCompleted: {
|
||||
// load the saved width/height/fps, and iterate through the ComboBox until a match is found
|
||||
// set it to that index.
|
||||
var saved_width = prefs.width
|
||||
var saved_height = prefs.height
|
||||
var saved_fps = prefs.fps
|
||||
currentIndex = 0
|
||||
for(var i = 0; i < resolutionComboBox.count; i++) {
|
||||
var el_width = parseInt(resolutionListModel.get(i).video_width);
|
||||
var el_height = parseInt(resolutionListModel.get(i).video_height);
|
||||
var el_fps = parseInt(resolutionListModel.get(i).video_fps);
|
||||
if(saved_width === el_width &&
|
||||
saved_height === el_height &&
|
||||
saved_fps === el_fps) {
|
||||
currentIndex = i
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ComboBox {
|
||||
// ignore setting the index at first, and actually set it when the component is loaded
|
||||
Component.onCompleted: {
|
||||
// Get the max supported FPS on this system
|
||||
var max_fps = prefs.getMaximumStreamingFrameRate();
|
||||
|
||||
// Use 64 as the cutoff for adding a separate option to
|
||||
// handle wonky displays that report just over 60 Hz.
|
||||
if (max_fps > 64) {
|
||||
fpsListModel.append({"text": max_fps+" FPS", "video_fps": ""+max_fps})
|
||||
}
|
||||
|
||||
var saved_fps = prefs.fps
|
||||
currentIndex = 0
|
||||
for (var i = 0; i < fpsComboBox.count; i++) {
|
||||
var el_fps = parseInt(fpsListModel.get(i).video_fps);
|
||||
|
||||
// Pick the highest value lesser or equal to the saved FPS
|
||||
if (saved_fps >= el_fps) {
|
||||
currentIndex = i
|
||||
}
|
||||
}
|
||||
id: resolutionComboBox
|
||||
width: Math.min(bitrateDesc.implicitWidth, parent.width)
|
||||
font.pointSize: 9
|
||||
textRole: "text"
|
||||
model: ListModel {
|
||||
id: resolutionListModel
|
||||
ListElement {
|
||||
text: "720p 30 FPS"
|
||||
video_width: "1280"
|
||||
video_height: "720"
|
||||
video_fps: "30"
|
||||
}
|
||||
|
||||
id: fpsComboBox
|
||||
textRole: "text"
|
||||
model: ListModel {
|
||||
id: fpsListModel
|
||||
ListElement {
|
||||
text: "30 FPS"
|
||||
video_fps: "30"
|
||||
}
|
||||
ListElement {
|
||||
text: "60 FPS"
|
||||
video_fps: "60"
|
||||
}
|
||||
// A higher value may be added at runtime
|
||||
// based on the attached display refresh rate
|
||||
ListElement {
|
||||
text: "720p 60 FPS"
|
||||
video_width: "1280"
|
||||
video_height: "720"
|
||||
video_fps: "60"
|
||||
}
|
||||
// ::onActivated must be used, as it only listens for when the index is changed by a human
|
||||
onActivated : {
|
||||
prefs.fps = parseInt(fpsListModel.get(currentIndex).video_fps)
|
||||
|
||||
prefs.bitrateKbps = prefs.getDefaultBitrate(prefs.width, prefs.height, prefs.fps);
|
||||
slider.value = prefs.bitrateKbps
|
||||
ListElement {
|
||||
text: "1080p 30 FPS"
|
||||
video_width: "1920"
|
||||
video_height: "1080"
|
||||
video_fps: "30"
|
||||
}
|
||||
ListElement {
|
||||
text: "1080p 60 FPS"
|
||||
video_width: "1920"
|
||||
video_height: "1080"
|
||||
video_fps: "60"
|
||||
}
|
||||
ListElement {
|
||||
text: "4K 30 FPS"
|
||||
video_width: "3840"
|
||||
video_height: "2160"
|
||||
video_fps: "30"
|
||||
}
|
||||
ListElement {
|
||||
text: "4K 60 FPS"
|
||||
video_width: "3840"
|
||||
video_height: "2160"
|
||||
video_fps: "60"
|
||||
}
|
||||
}
|
||||
// ::onActivated must be used, as it only listens for when the index is changed by a human
|
||||
onActivated : {
|
||||
prefs.width = parseInt(resolutionListModel.get(currentIndex).video_width)
|
||||
prefs.height = parseInt(resolutionListModel.get(currentIndex).video_height)
|
||||
prefs.fps = parseInt(resolutionListModel.get(currentIndex).video_fps)
|
||||
|
||||
prefs.bitrateKbps = prefs.getDefaultBitrate(prefs.width, prefs.height, prefs.fps);
|
||||
slider.value = prefs.bitrateKbps
|
||||
}
|
||||
}
|
||||
|
||||
@@ -219,7 +151,7 @@ ScrollView {
|
||||
|
||||
stepSize: 500
|
||||
from : 500
|
||||
to: 150000
|
||||
to: 100000
|
||||
|
||||
snapMode: "SnapOnRelease"
|
||||
width: Math.min(bitrateDesc.implicitWidth, parent.width)
|
||||
@@ -245,7 +177,7 @@ ScrollView {
|
||||
GroupBox {
|
||||
|
||||
id: audioSettingsGroupBox
|
||||
width: (parent.width - 2 * parent.padding)
|
||||
width: (parent.width - 20)
|
||||
padding: 12
|
||||
title: "<font color=\"skyblue\">Audio Settings</font>"
|
||||
font.pointSize: 12
|
||||
@@ -254,65 +186,24 @@ ScrollView {
|
||||
anchors.fill: parent
|
||||
spacing: 5
|
||||
|
||||
Label {
|
||||
width: parent.width
|
||||
id: resAudioTitle
|
||||
text: qsTr("Audio configuration")
|
||||
font.pointSize: 12
|
||||
wrapMode: Text.Wrap
|
||||
color: "white"
|
||||
}
|
||||
CheckBox {
|
||||
id: surroundSoundCheck
|
||||
text: "<font color=\"white\">Enable 5.1 surround sound</font>"
|
||||
font.pointSize: 12
|
||||
|
||||
ComboBox {
|
||||
// ignore setting the index at first, and actually set it when the component is loaded
|
||||
Component.onCompleted: {
|
||||
var saved_audio = prefs.audioConfig
|
||||
currentIndex = 0
|
||||
for(var i = 0; i < audioListModel.count; i++) {
|
||||
var el_audio= audioListModel.get(i).val;
|
||||
if(saved_audio === el_audio) {
|
||||
currentIndex = i
|
||||
}
|
||||
}
|
||||
}
|
||||
// the backend actually supports auto/stereo/5.1. We'll expose stereo/5.1
|
||||
checked: prefs.audioConfig === StreamingPreferences.AC_FORCE_SURROUND
|
||||
|
||||
id: audioComboBox
|
||||
width: Math.min(bitrateDesc.implicitWidth, parent.width)
|
||||
textRole: "text"
|
||||
model: ListModel {
|
||||
id: audioListModel
|
||||
ListElement {
|
||||
text: "Autodetect"
|
||||
val: StreamingPreferences.AC_AUTO
|
||||
}
|
||||
ListElement {
|
||||
text: "Stereo"
|
||||
val: StreamingPreferences.AC_FORCE_STEREO
|
||||
}
|
||||
ListElement {
|
||||
text: "5.1 surround sound"
|
||||
val: StreamingPreferences.AC_FORCE_SURROUND
|
||||
}
|
||||
}
|
||||
// ::onActivated must be used, as it only listens for when the index is changed by a human
|
||||
onActivated : {
|
||||
prefs.audioConfig = audioListModel.get(currentIndex).val
|
||||
onCheckedChanged: {
|
||||
prefs.audioConfig = checked ? StreamingPreferences.AC_FORCE_SURROUND : StreamingPreferences.AC_FORCE_STEREO
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
padding: 10
|
||||
anchors.left: settingsColumn1.right
|
||||
id: settingsColumn2
|
||||
width: settingsPage.width / 2 - padding
|
||||
|
||||
GroupBox {
|
||||
id: gamepadSettingsGroupBox
|
||||
width: (parent.width - parent.padding)
|
||||
width: (parent.width - 20)
|
||||
padding: 12
|
||||
title: "<font color=\"skyblue\">Gamepad Settings</font>"
|
||||
font.pointSize: 12
|
||||
@@ -330,12 +221,38 @@ ScrollView {
|
||||
prefs.multiController = checked
|
||||
}
|
||||
}
|
||||
CheckBox {
|
||||
id: mouseEmulationCheck
|
||||
text: "<font color=\"white\">Mouse emulation via gamepad</font>"
|
||||
font.pointSize: 12
|
||||
// TODO: make this actually do anything
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GroupBox {
|
||||
id: onScreenControlsGroupBox
|
||||
width: (parent.width - 20)
|
||||
padding: 12
|
||||
title: "<font color=\"skyblue\">On-screen Controls Settings</font>"
|
||||
font.pointSize: 12
|
||||
|
||||
Column {
|
||||
anchors.fill: parent
|
||||
spacing: 5
|
||||
|
||||
CheckBox {
|
||||
id: onScreenControlsCheck
|
||||
text: "<font color=\"white\">Show on-screen controls</font>"
|
||||
font.pointSize: 12
|
||||
// TODO: make this actually do anything
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GroupBox {
|
||||
id: hostSettingsGroupBox
|
||||
width: (parent.width - parent.padding)
|
||||
width: (parent.width - 20)
|
||||
padding: 12
|
||||
title: "<font color=\"skyblue\">Host Settings</font>"
|
||||
font.pointSize: 12
|
||||
@@ -368,7 +285,7 @@ ScrollView {
|
||||
|
||||
GroupBox {
|
||||
id: advancedSettingsGroupBox
|
||||
width: (parent.width - parent.padding)
|
||||
width: (parent.width - 20)
|
||||
padding: 12
|
||||
title: "<font color=\"skyblue\">Advanced Settings</font>"
|
||||
font.pointSize: 12
|
||||
@@ -377,105 +294,11 @@ ScrollView {
|
||||
anchors.fill: parent
|
||||
spacing: 5
|
||||
|
||||
Label {
|
||||
width: parent.width
|
||||
id: resVDSTitle
|
||||
text: qsTr("Video decoder")
|
||||
font.pointSize: 12
|
||||
wrapMode: Text.Wrap
|
||||
color: "white"
|
||||
CheckBox {
|
||||
id: neverDropFramesCheck
|
||||
text: "<font color=\"white\">Never drop frames</font>"
|
||||
font.pointSize: 12
|
||||
}
|
||||
|
||||
ComboBox {
|
||||
// ignore setting the index at first, and actually set it when the component is loaded
|
||||
Component.onCompleted: {
|
||||
var saved_vds = prefs.videoDecoderSelection
|
||||
currentIndex = 0
|
||||
for(var i = 0; i < decoderListModel.count; i++) {
|
||||
var el_vds = decoderListModel.get(i).val;
|
||||
if(saved_vds === el_vds) {
|
||||
currentIndex = i
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
id: decoderComboBox
|
||||
width: Math.min(bitrateDesc.implicitWidth, parent.width)
|
||||
textRole: "text"
|
||||
model: ListModel {
|
||||
id: decoderListModel
|
||||
ListElement {
|
||||
text: "Automatic (Recommended)"
|
||||
val: StreamingPreferences.VDS_AUTO
|
||||
}
|
||||
ListElement {
|
||||
text: "Force software decoding"
|
||||
val: StreamingPreferences.VDS_FORCE_SOFTWARE
|
||||
}
|
||||
ListElement {
|
||||
text: "Force hardware decoding"
|
||||
val: StreamingPreferences.VDS_FORCE_HARDWARE
|
||||
}
|
||||
}
|
||||
// ::onActivated must be used, as it only listens for when the index is changed by a human
|
||||
onActivated : {
|
||||
prefs.videoDecoderSelection = decoderListModel.get(currentIndex).val
|
||||
}
|
||||
}
|
||||
|
||||
Label {
|
||||
width: parent.width
|
||||
id: resVCCTitle
|
||||
text: qsTr("Video codec")
|
||||
font.pointSize: 12
|
||||
wrapMode: Text.Wrap
|
||||
color: "white"
|
||||
}
|
||||
|
||||
ComboBox {
|
||||
// ignore setting the index at first, and actually set it when the component is loaded
|
||||
Component.onCompleted: {
|
||||
var saved_vcc = prefs.videoCodecConfig
|
||||
currentIndex = 0
|
||||
for(var i = 0; i < codecListModel.count; i++) {
|
||||
var el_vcc = codecListModel.get(i).val;
|
||||
if(saved_vcc === el_vcc) {
|
||||
currentIndex = i
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
id: codecComboBox
|
||||
width: Math.min(bitrateDesc.implicitWidth, parent.width)
|
||||
textRole: "text"
|
||||
model: ListModel {
|
||||
id: codecListModel
|
||||
ListElement {
|
||||
text: "Automatic (Recommended)"
|
||||
val: StreamingPreferences.VCC_AUTO
|
||||
}
|
||||
ListElement {
|
||||
text: "Force H.264"
|
||||
val: StreamingPreferences.VCC_FORCE_H264
|
||||
}
|
||||
ListElement {
|
||||
text: "Force HEVC"
|
||||
val: StreamingPreferences.VCC_FORCE_HEVC
|
||||
}
|
||||
// HDR seems to be broken in GFE 3.14.1, and even when that's fixed
|
||||
// we'll probably need to gate this feature on OS support in our
|
||||
// renderers.
|
||||
/* ListElement {
|
||||
text: "Force HEVC HDR"
|
||||
val: StreamingPreferences.VCC_FORCE_HEVC_HDR
|
||||
} */
|
||||
}
|
||||
// ::onActivated must be used, as it only listens for when the index is changed by a human
|
||||
onActivated : {
|
||||
prefs.videoCodecConfig = codecListModel.get(currentIndex).val
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,8 +6,8 @@ import Session 1.0
|
||||
|
||||
Item {
|
||||
property Session session
|
||||
property string appName
|
||||
property string stageText : "Starting " + appName + "..."
|
||||
property string appname
|
||||
property string stageText : "Starting " + appname + "..."
|
||||
|
||||
anchors.fill: parent
|
||||
|
||||
@@ -47,13 +47,7 @@ Item {
|
||||
|
||||
function displayLaunchWarning(text)
|
||||
{
|
||||
// This toast appears for 3 seconds, just shorter than how long
|
||||
// Session will wait for it to be displayed. This gives it time
|
||||
// to transition to invisible before continuing.
|
||||
var toast = Qt.createQmlObject('import QtQuick.Controls 2.3; ToolTip {}', parent, '')
|
||||
toast.text = text
|
||||
toast.timeout = 3000
|
||||
toast.visible = true
|
||||
// TODO: toast
|
||||
}
|
||||
|
||||
onVisibleChanged: {
|
||||
|
||||
@@ -19,32 +19,6 @@ void AppModel::initialize(ComputerManager* computerManager, int computerIndex)
|
||||
m_CurrentGameId = m_Computer->currentGameId;
|
||||
}
|
||||
|
||||
int AppModel::getRunningAppIndex()
|
||||
{
|
||||
if (m_CurrentGameId != 0) {
|
||||
for (int i = 0; i < m_Apps.count(); i++) {
|
||||
if (m_Apps[i].id == m_CurrentGameId) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
QString AppModel::getRunningAppName()
|
||||
{
|
||||
if (m_CurrentGameId != 0) {
|
||||
for (int i = 0; i < m_Apps.count(); i++) {
|
||||
if (m_Apps[i].id == m_CurrentGameId) {
|
||||
return m_Apps[i].name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Session* AppModel::createSessionForApp(int appIndex)
|
||||
{
|
||||
Q_ASSERT(appIndex < m_Apps.count());
|
||||
@@ -96,11 +70,6 @@ QHash<int, QByteArray> AppModel::roleNames() const
|
||||
return names;
|
||||
}
|
||||
|
||||
void AppModel::quitRunningApp()
|
||||
{
|
||||
m_ComputerManager->quitRunningApp(m_Computer);
|
||||
}
|
||||
|
||||
void AppModel::handleComputerStateChanged(NvComputer* computer)
|
||||
{
|
||||
// Ignore updates for computers that aren't ours
|
||||
@@ -154,15 +123,10 @@ void AppModel::handleBoxArtLoaded(NvComputer* computer, NvApp app, QUrl /* image
|
||||
Q_ASSERT(computer == m_Computer);
|
||||
|
||||
int index = m_Apps.indexOf(app);
|
||||
Q_ASSERT(index >= 0);
|
||||
|
||||
// Make sure we're not delivering a callback to an app that's already been removed
|
||||
if (index >= 0) {
|
||||
// Let our view know the box art data has changed for this app
|
||||
emit dataChanged(createIndex(index, 0),
|
||||
createIndex(index, 0),
|
||||
QVector<int>() << BoxArtRole);
|
||||
}
|
||||
else {
|
||||
qWarning() << "App not found for box art callback:" << app.name;
|
||||
}
|
||||
// Let our view know the box art data has changed for this app
|
||||
emit dataChanged(createIndex(index, 0),
|
||||
createIndex(index, 0),
|
||||
QVector<int>() << BoxArtRole);
|
||||
}
|
||||
|
||||
@@ -25,12 +25,6 @@ public:
|
||||
|
||||
Q_INVOKABLE Session* createSessionForApp(int appIndex);
|
||||
|
||||
Q_INVOKABLE int getRunningAppIndex();
|
||||
|
||||
Q_INVOKABLE QString getRunningAppName();
|
||||
|
||||
Q_INVOKABLE void quitRunningApp();
|
||||
|
||||
QVariant data(const QModelIndex &index, int role) const override;
|
||||
|
||||
int rowCount(const QModelIndex &parent) const override;
|
||||
|
||||
@@ -46,12 +46,8 @@ QVariant ComputerModel::data(const QModelIndex& index, int role) const
|
||||
return computer->pairState == NvComputer::PS_PAIRED;
|
||||
case BusyRole:
|
||||
return computer->currentGameId != 0;
|
||||
case WakeableRole:
|
||||
return !computer->macAddress.isEmpty();
|
||||
case AddPcRole:
|
||||
return false;
|
||||
case StatusUnknownRole:
|
||||
return computer->state == NvComputer::CS_UNKNOWN;
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
@@ -78,8 +74,6 @@ QHash<int, QByteArray> ComputerModel::roleNames() const
|
||||
names[PairedRole] = "paired";
|
||||
names[BusyRole] = "busy";
|
||||
names[AddPcRole] = "addPc";
|
||||
names[WakeableRole] = "wakeable";
|
||||
names[StatusUnknownRole] = "statusUnknown";
|
||||
|
||||
return names;
|
||||
}
|
||||
|
||||
@@ -13,8 +13,6 @@ class ComputerModel : public QAbstractListModel
|
||||
OnlineRole,
|
||||
PairedRole,
|
||||
BusyRole,
|
||||
WakeableRole,
|
||||
StatusUnknownRole,
|
||||
AddPcRole
|
||||
};
|
||||
|
||||
|
||||
@@ -80,9 +80,6 @@ ApplicationWindow {
|
||||
}
|
||||
|
||||
ToolButton {
|
||||
// TODO: Implement gamepad mapping then unhide this button
|
||||
visible: false
|
||||
|
||||
icon.source: "qrc:/res/ic_videogame_asset_white_48px.svg"
|
||||
onClicked: navigateTo("qrc:/gui/GamepadMapper.qml", "Gamepad Mapping")
|
||||
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
#include <QQmlApplicationEngine>
|
||||
#include <QIcon>
|
||||
#include <QQuickStyle>
|
||||
#include <QMutex>
|
||||
#include <QtDebug>
|
||||
|
||||
// Don't let SDL hook our main function, since Qt is already
|
||||
// doing the same thing. This needs to be before any headers
|
||||
@@ -16,134 +14,8 @@
|
||||
#include "streaming/session.hpp"
|
||||
#include "settings/streamingpreferences.h"
|
||||
|
||||
#if !defined(QT_DEBUG) && defined(Q_OS_WIN32)
|
||||
// Log to file for release Windows builds
|
||||
#define USE_CUSTOM_LOGGER
|
||||
#define LOG_TO_FILE
|
||||
#elif defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN)
|
||||
// Use stdout logger on all Linux/BSD builds
|
||||
#define USE_CUSTOM_LOGGER
|
||||
#elif !defined(QT_DEBUG) && defined(Q_OS_DARWIN)
|
||||
// Log to file for release Mac builds
|
||||
#define USE_CUSTOM_LOGGER
|
||||
#define LOG_TO_FILE
|
||||
#else
|
||||
// For debug Windows and Mac builds, use default logger
|
||||
#endif
|
||||
|
||||
#ifdef USE_CUSTOM_LOGGER
|
||||
static QTime s_LoggerTime;
|
||||
static QTextStream s_LoggerStream(stdout);
|
||||
static QMutex s_LoggerLock;
|
||||
#ifdef LOG_TO_FILE
|
||||
#define MAX_LOG_LINES 10000
|
||||
static int s_LogLinesWritten = 0;
|
||||
static bool s_LogLimitReached = false;
|
||||
static QFile* s_LoggerFile;
|
||||
#endif
|
||||
|
||||
void logToLoggerStream(QString& message)
|
||||
{
|
||||
QMutexLocker lock(&s_LoggerLock);
|
||||
|
||||
#ifdef LOG_TO_FILE
|
||||
if (s_LogLimitReached) {
|
||||
return;
|
||||
}
|
||||
else if (s_LogLinesWritten == MAX_LOG_LINES) {
|
||||
s_LoggerStream << "Log size limit reached!" << endl;
|
||||
s_LogLimitReached = true;
|
||||
return;
|
||||
}
|
||||
else {
|
||||
s_LogLinesWritten++;
|
||||
}
|
||||
#endif
|
||||
|
||||
s_LoggerStream << message << endl;
|
||||
}
|
||||
|
||||
void sdlLogToDiskHandler(void*, int category, SDL_LogPriority priority, const char* message)
|
||||
{
|
||||
QString priorityTxt;
|
||||
|
||||
switch (priority) {
|
||||
case SDL_LOG_PRIORITY_VERBOSE:
|
||||
priorityTxt = "Verbose";
|
||||
break;
|
||||
case SDL_LOG_PRIORITY_DEBUG:
|
||||
priorityTxt = "Debug";
|
||||
break;
|
||||
case SDL_LOG_PRIORITY_INFO:
|
||||
priorityTxt = "Info";
|
||||
break;
|
||||
case SDL_LOG_PRIORITY_WARN:
|
||||
priorityTxt = "Warn";
|
||||
break;
|
||||
case SDL_LOG_PRIORITY_ERROR:
|
||||
priorityTxt = "Error";
|
||||
break;
|
||||
case SDL_LOG_PRIORITY_CRITICAL:
|
||||
priorityTxt = "Critical";
|
||||
break;
|
||||
default:
|
||||
priorityTxt = "Unknown";
|
||||
break;
|
||||
}
|
||||
|
||||
QTime logTime = QTime::fromMSecsSinceStartOfDay(s_LoggerTime.elapsed());
|
||||
QString txt = QString("%1 - SDL %2 (%3): %4").arg(logTime.toString()).arg(priorityTxt).arg(category).arg(message);
|
||||
|
||||
logToLoggerStream(txt);
|
||||
}
|
||||
|
||||
void qtLogToDiskHandler(QtMsgType type, const QMessageLogContext&, const QString& msg)
|
||||
{
|
||||
QString typeTxt;
|
||||
|
||||
switch (type) {
|
||||
case QtDebugMsg:
|
||||
typeTxt = "Debug";
|
||||
break;
|
||||
case QtInfoMsg:
|
||||
typeTxt = "Info";
|
||||
break;
|
||||
case QtWarningMsg:
|
||||
typeTxt = "Warning";
|
||||
break;
|
||||
case QtCriticalMsg:
|
||||
typeTxt = "Critical";
|
||||
break;
|
||||
case QtFatalMsg:
|
||||
typeTxt = "Fatal";
|
||||
break;
|
||||
}
|
||||
|
||||
QTime logTime = QTime::fromMSecsSinceStartOfDay(s_LoggerTime.elapsed());
|
||||
QString txt = QString("%1 - Qt %2: %3").arg(logTime.toString()).arg(typeTxt).arg(msg);
|
||||
|
||||
logToLoggerStream(txt);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
#ifdef USE_CUSTOM_LOGGER
|
||||
#ifdef LOG_TO_FILE
|
||||
QDir tempDir(QDir::tempPath());
|
||||
s_LoggerFile = new QFile(tempDir.filePath(QString("Moonlight-%1.log").arg(QDateTime::currentSecsSinceEpoch())));
|
||||
if (s_LoggerFile->open(QIODevice::WriteOnly)) {
|
||||
qInfo() << "Redirecting log output to " << s_LoggerFile->fileName();
|
||||
s_LoggerStream.setDevice(s_LoggerFile);
|
||||
}
|
||||
#endif
|
||||
|
||||
s_LoggerTime.start();
|
||||
qInstallMessageHandler(qtLogToDiskHandler);
|
||||
SDL_LogSetOutputFunction(sdlLogToDiskHandler, nullptr);
|
||||
#endif
|
||||
|
||||
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
||||
|
||||
// This avoids using the default keychain for SSL, which may cause
|
||||
@@ -181,8 +53,12 @@ int main(int argc, char *argv[])
|
||||
if (engine.rootObjects().isEmpty())
|
||||
return -1;
|
||||
|
||||
// Ensure that SDL is always initialized since we may need to use it
|
||||
// for non-streaming purposes (like checking on audio devices)
|
||||
SDL_SetMainReady();
|
||||
if (SDL_Init(0) != 0) {
|
||||
if (SDL_Init(SDL_INIT_VIDEO |
|
||||
SDL_INIT_AUDIO |
|
||||
SDL_INIT_GAMECONTROLLER) != 0) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"SDL_Init() failed: %s",
|
||||
SDL_GetError());
|
||||
|
||||
|
Before Width: | Height: | Size: 345 KiB |
|
Before Width: | Height: | Size: 5.4 KiB |
@@ -6,6 +6,5 @@
|
||||
<file>gui/SettingsView.qml</file>
|
||||
<file>gui/StreamSegue.qml</file>
|
||||
<file>gui/GamepadMapper.qml</file>
|
||||
<file>gui/QuitSegue.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="#FFFFFF" width="24" height="24" viewBox="0 0 24 24">
|
||||
<path d="M0 0h24v24H0z" fill="none"/>
|
||||
<path d="M18 8h-1V6c0-2.76-2.24-5-5-5S7 3.24 7 6v2H6c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V10c0-1.1-.9-2-2-2zm-6 9c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2zm3.1-9H8.9V6c0-1.71 1.39-3.1 3.1-3.1 1.71 0 3.1 1.39 3.1 3.1v2z"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 390 B |
@@ -1,4 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 48 48" fill="#fff">
|
||||
<path d="M0 0h48v48H0z" fill="none"/>
|
||||
<path d="M24 4C12.95 4 4 12.95 4 24s8.95 20 20 20 20-8.95 20-20S35.05 4 24 4zm-4 29V15l12 9-12 9z"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 250 B |
@@ -1,4 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="#FFFFFF" width="24" height="24" viewBox="0 0 24 24">
|
||||
<path d="M0 0h24v24H0z" fill="none"/>
|
||||
<path d="M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 215 B |
@@ -1,69 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
id="svg3761"
|
||||
viewBox="0 0 680 680"
|
||||
height="680"
|
||||
width="680"
|
||||
version="1.0">
|
||||
<metadata
|
||||
id="metadata3767">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs3765" />
|
||||
<g
|
||||
id="g3759"
|
||||
transform="translate(-135,491) scale(0.100000,-0.100000)">
|
||||
<circle
|
||||
id="circle3741"
|
||||
fill="#565C64"
|
||||
r="3400"
|
||||
cy="1505"
|
||||
cx="4755" />
|
||||
<path
|
||||
id="path3743"
|
||||
style="fill:#ffffff"
|
||||
d="M4550 4230 c-582 -48 -1123 -271 -1568 -646 l-84 -70 869 -869 c477 -477 871 -868 876 -868 4 0 6 552 5 1228 l-3 1227 -25 1 c-14 0 -45 -1 -70 -3z" />
|
||||
<path
|
||||
id="path3745"
|
||||
style="fill:#ffffff"
|
||||
d="M4867 4230 c-10 -9 -9 -2453 1 -2453 4 0 398 391 875 868 l869 869 -84 70 c-344 290 -749 492 -1178 587 -166 36 -469 74 -483 59z" />
|
||||
<path
|
||||
id="path3747"
|
||||
style="fill:#ffffff"
|
||||
d="M2673 3275 c-241 -285 -412 -595 -526 -953 -63 -196 -111 -458 -119 -640 l-3 -70 1228 -3 c675 -1 1227 1 1227 5 0 5 -391 399 -868 876 l-869 869 -70 -84z" />
|
||||
<path
|
||||
id="path3749"
|
||||
style="fill:#ffffff"
|
||||
d="M5898 2490 c-478 -477 -868 -871 -868 -876 0 -4 552 -6 1228 -5 l1227 3 -3 70 c-14 326 -124 729 -287 1055 -91 182 -259 430 -387 573 l-43 48 -867 -868z" />
|
||||
<path
|
||||
id="path3751"
|
||||
style="fill:#ffffff"
|
||||
d="M2026 1388 c-7 -11 10 -198 30 -321 76 -486 291 -952 617 -1338 l70 -84 869 869 c477 477 868 871 868 875 0 11 -2448 10 -2454 -1z" />
|
||||
<path
|
||||
id="path3753"
|
||||
style="fill:#ffffff"
|
||||
d="M5030 1390 c0 -5 391 -399 868 -876 l869 -869 70 84 c241 285 412 595 526 953 63 196 111 458 119 640 l3 70 -1227 3 c-676 1 -1228 -1 -1228 -5z" />
|
||||
<path
|
||||
id="path3755"
|
||||
style="fill:#ffffff"
|
||||
d="M3767 359 l-869 -869 84 -70 c285 -241 595 -412 953 -526 196 -63 458 -111 640 -119 l70 -3 3 1228 c1 675 -1 1227 -5 1227 -5 0 -399 -391 -876 -868z" />
|
||||
<path
|
||||
id="path3757"
|
||||
style="fill:#ffffff"
|
||||
d="M4862 0 l3 -1228 70 3 c182 8 444 56 640 119 358 114 668 285 953 526 l84 70 -869 869 c-477 477 -871 868 -876 868 -4 0 -6 -552 -5 -1227z" />
|
||||
<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" version="1.0">
|
||||
<defs>
|
||||
<filter id="f1" y="-40%" width="120%" height="220%">
|
||||
<feOffset xmlns="http://www.w3.org/2000/svg" result="offOut" in="SourceAlpha" dy="-100"/>
|
||||
<feGaussianBlur result="blurOut" in="offOut" stdDeviation="200"/>
|
||||
<feBlend in="SourceGraphic" in2="blurOut" mode="normal"/>
|
||||
</filter>
|
||||
</defs>
|
||||
<!-- -105, 521 are within 0.5 pixel-perfect -->
|
||||
<!-- offsetting more to show shadow -->
|
||||
<g transform="translate(-95,530) scale(0.100000,-0.100000)" filter="url(#f1)">
|
||||
<circle cx="4755" cy="1505" r="3700" fill="#565C64">
|
||||
</circle>
|
||||
<path d="M4550 4230 c-582 -48 -1123 -271 -1568 -646 l-84 -70 869 -869 c477 -477 871 -868 876 -868 4 0 6 552 5 1228 l-3 1227 -25 1 c-14 0 -45 -1 -70 -3z" style="fill:#ffffff"/>
|
||||
<path xmlns="http://www.w3.org/2000/svg" d="M4867 4230 c-10 -9 -9 -2453 1 -2453 4 0 398 391 875 868 l869 869 -84 70 c-344 290 -749 492 -1178 587 -166 36 -469 74 -483 59z" style="fill:#ffffff"/>
|
||||
<path d="M2673 3275 c-241 -285 -412 -595 -526 -953 -63 -196 -111 -458 -119 -640 l-3 -70 1228 -3 c675 -1 1227 1 1227 5 0 5 -391 399 -868 876 l-869 869 -70 -84z" style="fill:#ffffff"/>
|
||||
<path d="M5898 2490 c-478 -477 -868 -871 -868 -876 0 -4 552 -6 1228 -5 l1227 3 -3 70 c-14 326 -124 729 -287 1055 -91 182 -259 430 -387 573 l-43 48 -867 -868z" style="fill:#ffffff"/>
|
||||
<path d="M2026 1388 c-7 -11 10 -198 30 -321 76 -486 291 -952 617 -1338 l70 -84 869 869 c477 477 868 871 868 875 0 11 -2448 10 -2454 -1z" style="fill:#ffffff"/>
|
||||
<path d="M5030 1390 c0 -5 391 -399 868 -876 l869 -869 70 84 c241 285 412 595 526 953 63 196 111 458 119 640 l3 70 -1227 3 c-676 1 -1228 -1 -1228 -5z" style="fill:#ffffff"/>
|
||||
<path d="M3767 359 l-869 -869 84 -70 c285 -241 595 -412 953 -526 196 -63 458 -111 640 -119 l70 -3 3 1228 c1 675 -1 1227 -5 1227 -5 0 -399 -391 -876 -868z" style="fill:#ffffff"/>
|
||||
<path d="M4862 0 l3 -1228 70 3 c182 8 444 56 640 119 358 114 668 285 953 526 l84 70 -869 869 c-477 477 -871 868 -876 868 -4 0 -6 -552 -5 -1227z" style="fill:#ffffff"/>
|
||||
</g>
|
||||
</svg>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.2 KiB |
@@ -5,9 +5,6 @@
|
||||
<file>res/ic_videogame_asset_white_48px.svg</file>
|
||||
<file>res/ic_tv_white_48px.svg</file>
|
||||
<file>res/ic_add_to_queue_white_48px.svg</file>
|
||||
<file>res/baseline-lock-24px.svg</file>
|
||||
<file>res/baseline-play_circle_filled_white-48px.svg</file>
|
||||
<file>res/baseline-warning-24px.svg</file>
|
||||
<file>res/no_app_image.png</file>
|
||||
<file>res/settings.svg</file>
|
||||
<file>res/arrow_left.svg</file>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#include "streamingpreferences.h"
|
||||
#include "streaming/session.hpp"
|
||||
|
||||
#include <QSettings>
|
||||
|
||||
@@ -58,88 +57,24 @@ void StreamingPreferences::save()
|
||||
settings.setValue(SER_VIDEODEC, static_cast<int>(videoDecoderSelection));
|
||||
}
|
||||
|
||||
bool StreamingPreferences::hasAnyHardwareAcceleration()
|
||||
{
|
||||
// Always use VDS_AUTO to avoid spamming the user with warnings
|
||||
// if they've forced software decoding.
|
||||
return Session::isHardwareDecodeAvailable(VDS_AUTO,
|
||||
VIDEO_FORMAT_H264,
|
||||
1920, 1080, 60);
|
||||
}
|
||||
|
||||
int StreamingPreferences::getMaximumStreamingFrameRate()
|
||||
{
|
||||
// Never let the maximum drop below 60 FPS
|
||||
int maxFrameRate = 60;
|
||||
|
||||
if (SDL_InitSubSystem(SDL_INIT_VIDEO) != 0) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"SDL_InitSubSystem(SDL_INIT_VIDEO) failed: %s",
|
||||
SDL_GetError());
|
||||
return maxFrameRate;
|
||||
}
|
||||
|
||||
for (int i = 0; i < SDL_GetNumVideoDisplays(); i++) {
|
||||
SDL_DisplayMode mode;
|
||||
if (SDL_GetCurrentDisplayMode(i, &mode) == 0) {
|
||||
// Cap the frame rate at 120 FPS. Past this, the encoders start
|
||||
// to max out and drop frames.
|
||||
maxFrameRate = qMax(maxFrameRate, qMin(120, mode.refresh_rate));
|
||||
}
|
||||
}
|
||||
|
||||
SDL_QuitSubSystem(SDL_INIT_VIDEO);
|
||||
|
||||
return maxFrameRate;
|
||||
}
|
||||
|
||||
QRect StreamingPreferences::getDisplayResolution(int displayIndex)
|
||||
{
|
||||
if (SDL_InitSubSystem(SDL_INIT_VIDEO) != 0) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"SDL_InitSubSystem(SDL_INIT_VIDEO) failed: %s",
|
||||
SDL_GetError());
|
||||
return QRect();
|
||||
}
|
||||
|
||||
if (displayIndex >= SDL_GetNumVideoDisplays()) {
|
||||
SDL_QuitSubSystem(SDL_INIT_VIDEO);
|
||||
return QRect();
|
||||
}
|
||||
|
||||
SDL_DisplayMode mode;
|
||||
int err = SDL_GetCurrentDisplayMode(displayIndex, &mode);
|
||||
SDL_QuitSubSystem(SDL_INIT_VIDEO);
|
||||
|
||||
if (err == 0) {
|
||||
return QRect(0, 0, mode.w, mode.h);
|
||||
}
|
||||
else {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"SDL_GetCurrentDisplayMode() failed: %s",
|
||||
SDL_GetError());
|
||||
return QRect();
|
||||
}
|
||||
}
|
||||
|
||||
int StreamingPreferences::getDefaultBitrate(int width, int height, int fps)
|
||||
{
|
||||
// This table prefers 16:10 resolutions because they are
|
||||
// only slightly more pixels than the 16:9 equivalents, so
|
||||
// we don't want to bump those 16:10 resolutions up to the
|
||||
// next 16:9 slot.
|
||||
|
||||
// This covers 1280x720 and 1280x800 too
|
||||
if (width * height <= 1366 * 768) {
|
||||
return static_cast<int>(5000 * (fps / 30.0));
|
||||
if (width * height * fps <= 1280 * 720 * 30) {
|
||||
return 5000;
|
||||
}
|
||||
else if (width * height <= 1920 * 1200) {
|
||||
return static_cast<int>(10000 * (fps / 30.0));
|
||||
else if (width * height * fps <= 1280 * 720 * 60) {
|
||||
return 10000;
|
||||
}
|
||||
else if (width * height <= 2560 * 1600) {
|
||||
return static_cast<int>(20000 * (fps / 30.0));
|
||||
else if (width * height * fps <= 1920 * 1080 * 30) {
|
||||
return 10000;
|
||||
}
|
||||
else /* if (width * height <= 3840 * 2160) */ {
|
||||
return static_cast<int>(40000 * (fps / 30.0));
|
||||
else if (width * height * fps <= 1920 * 1080 * 60) {
|
||||
return 20000;
|
||||
}
|
||||
else if (width * height * fps <= 3840 * 2160 * 30) {
|
||||
return 40000;
|
||||
}
|
||||
else /* if (width * height * fps <= 3840 * 2160 * 60) */ {
|
||||
return 80000;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <QRect>
|
||||
|
||||
class StreamingPreferences : public QObject
|
||||
{
|
||||
@@ -15,12 +14,6 @@ public:
|
||||
|
||||
Q_INVOKABLE void save();
|
||||
|
||||
Q_INVOKABLE static bool hasAnyHardwareAcceleration();
|
||||
|
||||
Q_INVOKABLE static int getMaximumStreamingFrameRate();
|
||||
|
||||
Q_INVOKABLE QRect getDisplayResolution(int displayIndex);
|
||||
|
||||
void reload();
|
||||
|
||||
enum AudioConfig
|
||||
|
||||
@@ -23,14 +23,6 @@ int Session::sdlDetermineAudioConfiguration()
|
||||
{
|
||||
SDL_AudioSpec want, have;
|
||||
SDL_AudioDeviceID dev;
|
||||
int ret;
|
||||
|
||||
if (SDL_InitSubSystem(SDL_INIT_AUDIO) != 0) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"SDL_InitSubSystem(SDL_INIT_AUDIO) failed: %s",
|
||||
SDL_GetError());
|
||||
return AUDIO_CONFIGURATION_STEREO;
|
||||
}
|
||||
|
||||
SDL_zero(want);
|
||||
want.freq = 48000;
|
||||
@@ -46,8 +38,7 @@ int Session::sdlDetermineAudioConfiguration()
|
||||
"Failed to open audio device");
|
||||
// We'll probably have issues during audio stream init, but we'll
|
||||
// try anyway
|
||||
ret = AUDIO_CONFIGURATION_STEREO;
|
||||
goto Exit;
|
||||
return AUDIO_CONFIGURATION_STEREO;
|
||||
}
|
||||
|
||||
SDL_CloseAudioDevice(dev);
|
||||
@@ -59,15 +50,11 @@ int Session::sdlDetermineAudioConfiguration()
|
||||
// We don't support quadraphonic or 7.1 surround, but SDL
|
||||
// should be able to downmix or upmix better from 5.1 than
|
||||
// from stereo, so use 5.1 in non-stereo cases.
|
||||
ret = AUDIO_CONFIGURATION_51_SURROUND;
|
||||
return AUDIO_CONFIGURATION_51_SURROUND;
|
||||
}
|
||||
else {
|
||||
ret = AUDIO_CONFIGURATION_STEREO;
|
||||
return AUDIO_CONFIGURATION_STEREO;
|
||||
}
|
||||
|
||||
Exit:
|
||||
SDL_QuitSubSystem(SDL_INIT_AUDIO);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int Session::sdlAudioInit(int /* audioConfiguration */,
|
||||
@@ -77,14 +64,6 @@ int Session::sdlAudioInit(int /* audioConfiguration */,
|
||||
SDL_AudioSpec want, have;
|
||||
int error;
|
||||
|
||||
SDL_assert(!SDL_WasInit(SDL_INIT_AUDIO));
|
||||
if (SDL_InitSubSystem(SDL_INIT_AUDIO) != 0) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"SDL_InitSubSystem(SDL_INIT_AUDIO) failed: %s",
|
||||
SDL_GetError());
|
||||
return AUDIO_CONFIGURATION_STEREO;
|
||||
}
|
||||
|
||||
SDL_zero(want);
|
||||
want.freq = opusConfig->sampleRate;
|
||||
want.format = AUDIO_S16;
|
||||
@@ -101,7 +80,6 @@ int Session::sdlAudioInit(int /* audioConfiguration */,
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Failed to open audio device: %s",
|
||||
SDL_GetError());
|
||||
SDL_QuitSubSystem(SDL_INIT_AUDIO);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -117,7 +95,6 @@ int Session::sdlAudioInit(int /* audioConfiguration */,
|
||||
error);
|
||||
SDL_CloseAudioDevice(s_AudioDevice);
|
||||
s_AudioDevice = 0;
|
||||
SDL_QuitSubSystem(SDL_INIT_AUDIO);
|
||||
return -2;
|
||||
}
|
||||
|
||||
@@ -127,7 +104,7 @@ int Session::sdlAudioInit(int /* audioConfiguration */,
|
||||
// pending data count. Get a baseline so we
|
||||
// can exclude that data.
|
||||
s_BaselinePendingData = 0;
|
||||
#ifdef Q_OS_WIN32
|
||||
#ifdef _WIN32
|
||||
for (int i = 0; i < 100; i++) {
|
||||
s_BaselinePendingData = qMax(s_BaselinePendingData, SDL_GetQueuedAudioSize(s_AudioDevice));
|
||||
SDL_Delay(10);
|
||||
@@ -142,10 +119,6 @@ int Session::sdlAudioInit(int /* audioConfiguration */,
|
||||
s_SampleIndex = 0;
|
||||
s_PendingDrops = s_PendingHardDrops = 0;
|
||||
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Audio stream has %d channels",
|
||||
opusConfig->channelCount);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -167,10 +140,7 @@ void Session::sdlAudioCleanup()
|
||||
s_AudioDevice = 0;
|
||||
|
||||
opus_multistream_decoder_destroy(s_OpusDecoder);
|
||||
s_OpusDecoder = nullptr;
|
||||
|
||||
SDL_QuitSubSystem(SDL_INIT_AUDIO);
|
||||
SDL_assert(!SDL_WasInit(SDL_INIT_AUDIO));
|
||||
s_OpusDecoder = NULL;
|
||||
}
|
||||
|
||||
void Session::sdlAudioDecodeAndPlaySample(char* sampleData, int sampleLength)
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
#include <SDL.h>
|
||||
#include "streaming/session.hpp"
|
||||
|
||||
#include <QtGlobal>
|
||||
|
||||
#define VK_0 0x30
|
||||
#define VK_A 0x41
|
||||
|
||||
@@ -11,7 +9,7 @@
|
||||
#ifndef VK_F1
|
||||
#define VK_F1 0x70
|
||||
#define VK_F13 0x7C
|
||||
#define VK_NUMPAD0 0x60
|
||||
#define VK_NUMPAD1 0x61
|
||||
#endif
|
||||
|
||||
const int SdlInputHandler::k_ButtonMap[] = {
|
||||
@@ -25,18 +23,6 @@ const int SdlInputHandler::k_ButtonMap[] = {
|
||||
SdlInputHandler::SdlInputHandler(bool multiController)
|
||||
: m_MultiController(multiController)
|
||||
{
|
||||
// Allow gamepad input when the app doesn't have focus
|
||||
SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1");
|
||||
|
||||
// We need to reinit this each time, since you only get
|
||||
// an initial set of gamepad arrival events once per init.
|
||||
SDL_assert(!SDL_WasInit(SDL_INIT_GAMECONTROLLER));
|
||||
if (SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER) != 0) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER) failed: %s",
|
||||
SDL_GetError());
|
||||
}
|
||||
|
||||
if (!m_MultiController) {
|
||||
// Player 1 is always present in non-MC mode
|
||||
m_GamepadMask = 0x1;
|
||||
@@ -52,9 +38,6 @@ SdlInputHandler::~SdlInputHandler()
|
||||
SDL_GameControllerClose(m_GamepadState[i].controller);
|
||||
}
|
||||
}
|
||||
|
||||
SDL_QuitSubSystem(SDL_INIT_GAMECONTROLLER);
|
||||
SDL_assert(!SDL_WasInit(SDL_INIT_GAMECONTROLLER));
|
||||
}
|
||||
|
||||
void SdlInputHandler::handleKeyEvent(SDL_KeyboardEvent* event)
|
||||
@@ -68,26 +51,26 @@ void SdlInputHandler::handleKeyEvent(SDL_KeyboardEvent* event)
|
||||
(event->keysym.mod & KMOD_ALT) &&
|
||||
(event->keysym.mod & KMOD_SHIFT)) {
|
||||
|
||||
// Force raise all keys in the combo to avoid
|
||||
// leaving them down after disconnecting
|
||||
LiSendKeyboardEvent(0xA0, KEY_ACTION_UP, 0);
|
||||
LiSendKeyboardEvent(0xA1, KEY_ACTION_UP, 0);
|
||||
LiSendKeyboardEvent(0xA2, KEY_ACTION_UP, 0);
|
||||
LiSendKeyboardEvent(0xA3, KEY_ACTION_UP, 0);
|
||||
LiSendKeyboardEvent(0xA4, KEY_ACTION_UP, 0);
|
||||
LiSendKeyboardEvent(0xA5, KEY_ACTION_UP, 0);
|
||||
|
||||
// Check for quit combo (Ctrl+Alt+Shift+Q)
|
||||
if (event->keysym.sym == SDLK_q) {
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Detected quit key combo");
|
||||
|
||||
// Uncapture the mouse to avoid processing any
|
||||
// further keyboard input
|
||||
SDL_SetRelativeMouseMode(SDL_FALSE);
|
||||
// Force raise all keys in the combo to avoid
|
||||
// leaving them down after disconnecting
|
||||
LiSendKeyboardEvent(0xA0, KEY_ACTION_UP, 0);
|
||||
LiSendKeyboardEvent(0xA1, KEY_ACTION_UP, 0);
|
||||
LiSendKeyboardEvent(0xA2, KEY_ACTION_UP, 0);
|
||||
LiSendKeyboardEvent(0xA3, KEY_ACTION_UP, 0);
|
||||
LiSendKeyboardEvent(0xA4, KEY_ACTION_UP, 0);
|
||||
LiSendKeyboardEvent(0xA5, KEY_ACTION_UP, 0);
|
||||
|
||||
SDL_Event event;
|
||||
|
||||
// Drain the event queue of any additional input
|
||||
// that might be processed before our quit message.
|
||||
while (SDL_PollEvent(&event));
|
||||
|
||||
// Push a quit event to the main loop
|
||||
event.type = SDL_QUIT;
|
||||
event.quit.timestamp = SDL_GetTicks();
|
||||
@@ -105,7 +88,12 @@ void SdlInputHandler::handleKeyEvent(SDL_KeyboardEvent* event)
|
||||
else if (event->keysym.sym == SDLK_x) {
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Detected full-screen toggle combo");
|
||||
Session::s_ActiveSession->toggleFullscreen();
|
||||
if (SDL_GetWindowFlags(Session::s_ActiveSession->m_Window) & SDL_WINDOW_FULLSCREEN) {
|
||||
SDL_SetWindowFullscreen(Session::s_ActiveSession->m_Window, 0);
|
||||
}
|
||||
else {
|
||||
SDL_SetWindowFullscreen(Session::s_ActiveSession->m_Window, SDL_WINDOW_FULLSCREEN);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -127,199 +115,195 @@ void SdlInputHandler::handleKeyEvent(SDL_KeyboardEvent* event)
|
||||
modifiers |= MODIFIER_SHIFT;
|
||||
}
|
||||
|
||||
// Set keycode. We explicitly use scancode here because GFE will try to correct
|
||||
// for AZERTY layouts on the host but it depends on receiving VK_ values matching
|
||||
// a QWERTY layout to work.
|
||||
if (event->keysym.scancode >= SDL_SCANCODE_1 && event->keysym.scancode <= SDL_SCANCODE_9) {
|
||||
// SDL defines SDL_SCANCODE_0 > SDL_SCANCODE_9, so we need to handle that manually
|
||||
keyCode = (event->keysym.scancode - SDL_SCANCODE_1) + VK_0 + 1;
|
||||
// Set keycode
|
||||
if (event->keysym.sym >= SDLK_0 && event->keysym.sym <= SDLK_9) {
|
||||
keyCode = (event->keysym.sym - SDLK_0) + VK_0;
|
||||
}
|
||||
else if (event->keysym.scancode >= SDL_SCANCODE_A && event->keysym.scancode <= SDL_SCANCODE_Z) {
|
||||
keyCode = (event->keysym.scancode - SDL_SCANCODE_A) + VK_A;
|
||||
else if (event->keysym.sym >= SDLK_a && event->keysym.sym <= SDLK_z) {
|
||||
keyCode = (event->keysym.sym - SDLK_a) + VK_A;
|
||||
}
|
||||
else if (event->keysym.scancode >= SDL_SCANCODE_F1 && event->keysym.scancode <= SDL_SCANCODE_F12) {
|
||||
keyCode = (event->keysym.scancode - SDL_SCANCODE_F1) + VK_F1;
|
||||
else if (event->keysym.sym >= SDLK_F1 && event->keysym.sym <= SDLK_F12) {
|
||||
keyCode = (event->keysym.sym - SDLK_F1) + VK_F1;
|
||||
}
|
||||
else if (event->keysym.scancode >= SDL_SCANCODE_F13 && event->keysym.scancode <= SDL_SCANCODE_F24) {
|
||||
keyCode = (event->keysym.scancode - SDL_SCANCODE_F13) + VK_F13;
|
||||
else if (event->keysym.sym >= SDLK_F13 && event->keysym.sym <= SDLK_F24) {
|
||||
keyCode = (event->keysym.sym - SDLK_F13) + VK_F13;
|
||||
}
|
||||
else if (event->keysym.scancode >= SDL_SCANCODE_KP_1 && event->keysym.scancode <= SDL_SCANCODE_KP_9) {
|
||||
// SDL defines SDL_SCANCODE_KP_0 > SDL_SCANCODE_KP_9, so we need to handle that manually
|
||||
keyCode = (event->keysym.scancode - SDL_SCANCODE_KP_1) + VK_NUMPAD0 + 1;
|
||||
else if (event->keysym.sym >= SDLK_KP_1 && event->keysym.sym <= SDLK_KP_9) {
|
||||
// SDL defines SDLK_KP_0 > SDLK_KP_9, so we need to handle that manually
|
||||
keyCode = (event->keysym.sym - SDLK_KP_1) + VK_NUMPAD1;
|
||||
}
|
||||
else {
|
||||
switch (event->keysym.scancode) {
|
||||
case SDL_SCANCODE_BACKSPACE:
|
||||
switch (event->keysym.sym) {
|
||||
case SDLK_BACKSPACE:
|
||||
keyCode = 0x08;
|
||||
break;
|
||||
case SDL_SCANCODE_TAB:
|
||||
case SDLK_TAB:
|
||||
keyCode = 0x09;
|
||||
break;
|
||||
case SDL_SCANCODE_CLEAR:
|
||||
case SDLK_CLEAR:
|
||||
keyCode = 0x0C;
|
||||
break;
|
||||
case SDL_SCANCODE_RETURN:
|
||||
case SDLK_RETURN:
|
||||
keyCode = 0x0D;
|
||||
break;
|
||||
case SDL_SCANCODE_PAUSE:
|
||||
case SDLK_PAUSE:
|
||||
keyCode = 0x13;
|
||||
break;
|
||||
case SDL_SCANCODE_CAPSLOCK:
|
||||
case SDLK_CAPSLOCK:
|
||||
keyCode = 0x14;
|
||||
break;
|
||||
case SDL_SCANCODE_ESCAPE:
|
||||
case SDLK_ESCAPE:
|
||||
keyCode = 0x1B;
|
||||
break;
|
||||
case SDL_SCANCODE_SPACE:
|
||||
case SDLK_SPACE:
|
||||
keyCode = 0x20;
|
||||
break;
|
||||
case SDL_SCANCODE_PAGEUP:
|
||||
case SDLK_PAGEUP:
|
||||
keyCode = 0x21;
|
||||
break;
|
||||
case SDL_SCANCODE_PAGEDOWN:
|
||||
case SDLK_PAGEDOWN:
|
||||
keyCode = 0x22;
|
||||
break;
|
||||
case SDL_SCANCODE_END:
|
||||
case SDLK_END:
|
||||
keyCode = 0x23;
|
||||
break;
|
||||
case SDL_SCANCODE_HOME:
|
||||
case SDLK_HOME:
|
||||
keyCode = 0x24;
|
||||
break;
|
||||
case SDL_SCANCODE_LEFT:
|
||||
case SDLK_LEFT:
|
||||
keyCode = 0x25;
|
||||
break;
|
||||
case SDL_SCANCODE_UP:
|
||||
case SDLK_UP:
|
||||
keyCode = 0x26;
|
||||
break;
|
||||
case SDL_SCANCODE_RIGHT:
|
||||
case SDLK_RIGHT:
|
||||
keyCode = 0x27;
|
||||
break;
|
||||
case SDL_SCANCODE_DOWN:
|
||||
case SDLK_DOWN:
|
||||
keyCode = 0x28;
|
||||
break;
|
||||
case SDL_SCANCODE_SELECT:
|
||||
case SDLK_SELECT:
|
||||
keyCode = 0x29;
|
||||
break;
|
||||
case SDL_SCANCODE_EXECUTE:
|
||||
case SDLK_EXECUTE:
|
||||
keyCode = 0x2B;
|
||||
break;
|
||||
case SDL_SCANCODE_PRINTSCREEN:
|
||||
case SDLK_PRINTSCREEN:
|
||||
keyCode = 0x2C;
|
||||
break;
|
||||
case SDL_SCANCODE_INSERT:
|
||||
case SDLK_INSERT:
|
||||
keyCode = 0x2D;
|
||||
break;
|
||||
case SDL_SCANCODE_DELETE:
|
||||
case SDLK_DELETE:
|
||||
keyCode = 0x2E;
|
||||
break;
|
||||
case SDL_SCANCODE_HELP:
|
||||
case SDLK_HELP:
|
||||
keyCode = 0x2F;
|
||||
break;
|
||||
case SDL_SCANCODE_KP_0:
|
||||
// See comment above about why we only handle SDL_SCANCODE_KP_0 here
|
||||
keyCode = VK_NUMPAD0;
|
||||
case SDLK_KP_0:
|
||||
// See comment above about why we only handle KP_0 here
|
||||
keyCode = 0x60;
|
||||
break;
|
||||
case SDL_SCANCODE_0:
|
||||
// See comment above about why we only handle SDL_SCANCODE_0 here
|
||||
keyCode = VK_0;
|
||||
break;
|
||||
case SDL_SCANCODE_KP_MULTIPLY:
|
||||
case SDLK_KP_MULTIPLY:
|
||||
keyCode = 0x6A;
|
||||
break;
|
||||
case SDL_SCANCODE_KP_PLUS:
|
||||
case SDLK_KP_PLUS:
|
||||
keyCode = 0x6B;
|
||||
break;
|
||||
case SDL_SCANCODE_KP_COMMA:
|
||||
case SDLK_KP_COMMA:
|
||||
keyCode = 0x6C;
|
||||
break;
|
||||
case SDL_SCANCODE_KP_MINUS:
|
||||
case SDLK_KP_MINUS:
|
||||
keyCode = 0x6D;
|
||||
break;
|
||||
case SDL_SCANCODE_KP_DECIMAL:
|
||||
case SDLK_KP_DECIMAL:
|
||||
keyCode = 0x6E;
|
||||
break;
|
||||
case SDL_SCANCODE_KP_DIVIDE:
|
||||
case SDLK_KP_DIVIDE:
|
||||
keyCode = 0x6F;
|
||||
break;
|
||||
case SDL_SCANCODE_NUMLOCKCLEAR:
|
||||
case SDLK_NUMLOCKCLEAR:
|
||||
keyCode = 0x90;
|
||||
break;
|
||||
case SDL_SCANCODE_SCROLLLOCK:
|
||||
case SDLK_SCROLLLOCK:
|
||||
keyCode = 0x91;
|
||||
break;
|
||||
case SDL_SCANCODE_LSHIFT:
|
||||
case SDLK_LSHIFT:
|
||||
keyCode = 0xA0;
|
||||
break;
|
||||
case SDL_SCANCODE_RSHIFT:
|
||||
case SDLK_RSHIFT:
|
||||
keyCode = 0xA1;
|
||||
break;
|
||||
case SDL_SCANCODE_LCTRL:
|
||||
case SDLK_LCTRL:
|
||||
keyCode = 0xA2;
|
||||
break;
|
||||
case SDL_SCANCODE_RCTRL:
|
||||
case SDLK_RCTRL:
|
||||
keyCode = 0xA3;
|
||||
break;
|
||||
case SDL_SCANCODE_LALT:
|
||||
case SDLK_LALT:
|
||||
keyCode = 0xA4;
|
||||
break;
|
||||
case SDL_SCANCODE_RALT:
|
||||
case SDLK_RALT:
|
||||
keyCode = 0xA5;
|
||||
break;
|
||||
case SDL_SCANCODE_AC_BACK:
|
||||
case SDLK_AC_BACK:
|
||||
keyCode = 0xA6;
|
||||
break;
|
||||
case SDL_SCANCODE_AC_FORWARD:
|
||||
case SDLK_AC_FORWARD:
|
||||
keyCode = 0xA7;
|
||||
break;
|
||||
case SDL_SCANCODE_AC_REFRESH:
|
||||
case SDLK_AC_REFRESH:
|
||||
keyCode = 0xA8;
|
||||
break;
|
||||
case SDL_SCANCODE_AC_STOP:
|
||||
case SDLK_AC_STOP:
|
||||
keyCode = 0xA9;
|
||||
break;
|
||||
case SDL_SCANCODE_AC_SEARCH:
|
||||
case SDLK_AC_SEARCH:
|
||||
keyCode = 0xAA;
|
||||
break;
|
||||
case SDL_SCANCODE_AC_BOOKMARKS:
|
||||
case SDLK_AC_BOOKMARKS:
|
||||
keyCode = 0xAB;
|
||||
break;
|
||||
case SDL_SCANCODE_AC_HOME:
|
||||
case SDLK_AC_HOME:
|
||||
keyCode = 0xAC;
|
||||
break;
|
||||
case SDL_SCANCODE_SEMICOLON:
|
||||
case SDLK_SEMICOLON:
|
||||
keyCode = 0xBA;
|
||||
break;
|
||||
case SDL_SCANCODE_COMMA:
|
||||
case SDLK_PLUS:
|
||||
keyCode = 0xBB;
|
||||
break;
|
||||
case SDLK_COMMA:
|
||||
keyCode = 0xBC;
|
||||
break;
|
||||
case SDL_SCANCODE_MINUS:
|
||||
case SDLK_MINUS:
|
||||
keyCode = 0xBD;
|
||||
break;
|
||||
case SDL_SCANCODE_PERIOD:
|
||||
case SDLK_PERIOD:
|
||||
keyCode = 0xBE;
|
||||
break;
|
||||
case SDL_SCANCODE_SLASH:
|
||||
case SDLK_SLASH:
|
||||
keyCode = 0xBF;
|
||||
break;
|
||||
case SDL_SCANCODE_GRAVE:
|
||||
case SDLK_BACKQUOTE:
|
||||
keyCode = 0xC0;
|
||||
break;
|
||||
case SDL_SCANCODE_LEFTBRACKET:
|
||||
case SDLK_LEFTBRACKET:
|
||||
keyCode = 0xDB;
|
||||
break;
|
||||
case SDL_SCANCODE_BACKSLASH:
|
||||
case SDLK_BACKSLASH:
|
||||
keyCode = 0xDC;
|
||||
break;
|
||||
case SDL_SCANCODE_RIGHTBRACKET:
|
||||
case SDLK_RIGHTBRACKET:
|
||||
keyCode = 0xDD;
|
||||
break;
|
||||
case SDL_SCANCODE_APOSTROPHE:
|
||||
case SDLK_QUOTE:
|
||||
keyCode = 0xDE;
|
||||
break;
|
||||
default:
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Unhandled button event: %d",
|
||||
event->keysym.scancode);
|
||||
event->keysym.sym);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -443,18 +427,13 @@ void SdlInputHandler::handleControllerAxisEvent(SDL_ControllerAxisEvent* event)
|
||||
state->lsX = event->value;
|
||||
break;
|
||||
case SDL_CONTROLLER_AXIS_LEFTY:
|
||||
// Signed values have one more negative value than
|
||||
// positive value, so inverting the sign on -32768
|
||||
// could actually cause the value to overflow and
|
||||
// wrap around to be negative again. Avoid that by
|
||||
// capping the value at 32767.
|
||||
state->lsY = -qMax(event->value, (short)-32767);
|
||||
state->lsY = -event->value;
|
||||
break;
|
||||
case SDL_CONTROLLER_AXIS_RIGHTX:
|
||||
state->rsX = event->value;
|
||||
break;
|
||||
case SDL_CONTROLLER_AXIS_RIGHTY:
|
||||
state->rsY = -qMax(event->value, (short)-32767);
|
||||
state->rsY = -event->value;
|
||||
break;
|
||||
case SDL_CONTROLLER_AXIS_TRIGGERLEFT:
|
||||
state->lt = (unsigned char)(event->value * 255UL / 32767);
|
||||
|
||||
@@ -5,38 +5,16 @@
|
||||
#include <SDL.h>
|
||||
#include "utils.h"
|
||||
|
||||
#ifdef HAVE_FFMPEG
|
||||
#ifdef __APPLE__
|
||||
#include "video/avfoundation.h"
|
||||
#endif
|
||||
|
||||
#include "video/ffmpeg.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SLVIDEO
|
||||
#include "video/sl.h"
|
||||
#endif
|
||||
|
||||
#if defined(Q_OS_WIN32) || defined(Q_OS_DARWIN)
|
||||
// Using full-screen desktop allows us to avoid needing to enable V-sync on Windows
|
||||
// and it also avoids some strange flickering issues on my Win7 test machine
|
||||
// with Intel HD 5500 graphics. It also allows Spaces to work on macOS.
|
||||
#define SDL_OS_FULLSCREEN_FLAG SDL_WINDOW_FULLSCREEN_DESKTOP
|
||||
#else
|
||||
#define SDL_OS_FULLSCREEN_FLAG SDL_WINDOW_FULLSCREEN
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_WIN32
|
||||
// Scaling the icon down on Win32 looks dreadful, so render at lower res
|
||||
#define ICON_SIZE 32
|
||||
#else
|
||||
#define ICON_SIZE 64
|
||||
#endif
|
||||
|
||||
#include <openssl/rand.h>
|
||||
|
||||
#include <QRandomGenerator>
|
||||
#include <QtEndian>
|
||||
#include <QCoreApplication>
|
||||
#include <QThreadPool>
|
||||
#include <QSvgRenderer>
|
||||
#include <QPainter>
|
||||
#include <QImage>
|
||||
|
||||
CONNECTION_LISTENER_CALLBACKS Session::k_ConnCallbacks = {
|
||||
Session::clStageStarting,
|
||||
@@ -108,22 +86,21 @@ bool Session::chooseDecoder(StreamingPreferences::VideoDecoderSelection vds,
|
||||
SDL_Window* window, int videoFormat, int width, int height,
|
||||
int frameRate, IVideoDecoder*& chosenDecoder)
|
||||
{
|
||||
#ifdef HAVE_SLVIDEO
|
||||
chosenDecoder = new SLVideoDecoder();
|
||||
#ifdef __APPLE__
|
||||
chosenDecoder = AVFoundationDecoderFactory::createDecoder();
|
||||
if (chosenDecoder->initialize(vds, window, videoFormat, width, height, frameRate)) {
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"SLVideo video decoder chosen");
|
||||
"AVFoundation-based video decoder chosen");
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Unable to load SLVideo decoder");
|
||||
"Unable to load AVFoundation decoder");
|
||||
delete chosenDecoder;
|
||||
chosenDecoder = nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_FFMPEG
|
||||
chosenDecoder = new FFmpegVideoDecoder();
|
||||
if (chosenDecoder->initialize(vds, window, videoFormat, width, height, frameRate)) {
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
||||
@@ -136,11 +113,6 @@ bool Session::chooseDecoder(StreamingPreferences::VideoDecoderSelection vds,
|
||||
delete chosenDecoder;
|
||||
chosenDecoder = nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_FFMPEG) && !defined(HAVE_SLVIDEO)
|
||||
#error No video decoding libraries available!
|
||||
#endif
|
||||
|
||||
// If we reach this, we didn't initialize any decoders successfully
|
||||
return false;
|
||||
@@ -148,17 +120,12 @@ bool Session::chooseDecoder(StreamingPreferences::VideoDecoderSelection vds,
|
||||
|
||||
int Session::drSetup(int videoFormat, int width, int height, int frameRate, void *, int)
|
||||
{
|
||||
s_ActiveSession->m_ActiveVideoFormat = videoFormat;
|
||||
s_ActiveSession->m_ActiveVideoWidth = width;
|
||||
s_ActiveSession->m_ActiveVideoHeight = height;
|
||||
s_ActiveSession->m_ActiveVideoFrameRate = frameRate;
|
||||
|
||||
// Defer decoder setup until we've started streaming so we
|
||||
// don't have to hide and show the SDL window (which seems to
|
||||
// cause pointer hiding to break on Windows).
|
||||
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Video stream is %dx%dx%d (format 0x%x)",
|
||||
width, height, frameRate, videoFormat);
|
||||
if (!chooseDecoder(s_ActiveSession->m_Preferences.videoDecoderSelection,
|
||||
s_ActiveSession->m_Window,
|
||||
videoFormat, width, height, frameRate,
|
||||
s_ActiveSession->m_VideoDecoder)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -169,16 +136,7 @@ int Session::drSubmitDecodeUnit(PDECODE_UNIT du)
|
||||
// from underneath the session when we initiate destruction.
|
||||
// We need to destroy the decoder on the main thread to satisfy
|
||||
// some API constraints (like DXVA2).
|
||||
|
||||
SDL_AtomicLock(&s_ActiveSession->m_DecoderLock);
|
||||
|
||||
if (s_ActiveSession->m_NeedsIdr) {
|
||||
// If we reset our decoder, we'll need to request an IDR frame
|
||||
s_ActiveSession->m_NeedsIdr = false;
|
||||
SDL_AtomicUnlock(&s_ActiveSession->m_DecoderLock);
|
||||
return DR_NEED_IDR;
|
||||
}
|
||||
|
||||
IVideoDecoder* decoder = s_ActiveSession->m_VideoDecoder;
|
||||
if (decoder != nullptr) {
|
||||
int ret = decoder->submitDecodeUnit(du);
|
||||
@@ -196,35 +154,23 @@ bool Session::isHardwareDecodeAvailable(StreamingPreferences::VideoDecoderSelect
|
||||
{
|
||||
IVideoDecoder* decoder;
|
||||
|
||||
if (SDL_InitSubSystem(SDL_INIT_VIDEO) != 0) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"SDL_InitSubSystem(SDL_INIT_VIDEO) failed: %s",
|
||||
SDL_GetError());
|
||||
return false;
|
||||
}
|
||||
|
||||
SDL_Window* window = SDL_CreateWindow("", 0, 0, width, height, SDL_WINDOW_HIDDEN);
|
||||
if (!window) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Failed to create window for hardware decode test: %s",
|
||||
SDL_GetError());
|
||||
SDL_QuitSubSystem(SDL_INIT_VIDEO);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!chooseDecoder(vds, window, videoFormat, width, height, frameRate, decoder)) {
|
||||
SDL_DestroyWindow(window);
|
||||
SDL_QuitSubSystem(SDL_INIT_VIDEO);
|
||||
return false;
|
||||
}
|
||||
|
||||
SDL_DestroyWindow(window);
|
||||
|
||||
bool ret = decoder->isHardwareAccelerated();
|
||||
|
||||
delete decoder;
|
||||
SDL_QuitSubSystem(SDL_INIT_VIDEO);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -233,11 +179,8 @@ Session::Session(NvComputer* computer, NvApp& app)
|
||||
m_App(app),
|
||||
m_Window(nullptr),
|
||||
m_VideoDecoder(nullptr),
|
||||
m_DecoderLock(0),
|
||||
m_NeedsIdr(false)
|
||||
m_DecoderLock(0)
|
||||
{
|
||||
qDebug() << "Server GPU:" << m_Computer->gpuModel;
|
||||
|
||||
LiInitializeVideoCallbacks(&m_VideoCallbacks);
|
||||
m_VideoCallbacks.setup = drSetup;
|
||||
m_VideoCallbacks.submitDecodeUnit = drSubmitDecodeUnit;
|
||||
@@ -246,11 +189,7 @@ Session::Session(NvComputer* computer, NvApp& app)
|
||||
m_VideoCallbacks.capabilities |= CAPABILITY_DIRECT_SUBMIT;
|
||||
|
||||
// Slice up to 4 times for parallel decode, once slice per core
|
||||
int slices = qMin(MAX_SLICES, SDL_GetCPUCount());
|
||||
m_VideoCallbacks.capabilities |= CAPABILITY_SLICES_PER_FRAME(slices);
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Encoder configured for %d slices per frame",
|
||||
slices);
|
||||
m_VideoCallbacks.capabilities |= CAPABILITY_SLICES_PER_FRAME(qMin(MAX_SLICES, SDL_GetCPUCount()));
|
||||
|
||||
LiInitializeStreamConfiguration(&m_StreamConfig);
|
||||
m_StreamConfig.width = m_Preferences.width;
|
||||
@@ -258,21 +197,14 @@ Session::Session(NvComputer* computer, NvApp& app)
|
||||
m_StreamConfig.fps = m_Preferences.fps;
|
||||
m_StreamConfig.bitrate = m_Preferences.bitrateKbps;
|
||||
m_StreamConfig.hevcBitratePercentageMultiplier = 75;
|
||||
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Video bitrate: %d kbps",
|
||||
m_StreamConfig.bitrate);
|
||||
|
||||
RAND_bytes(reinterpret_cast<unsigned char*>(m_StreamConfig.remoteInputAesKey),
|
||||
sizeof(m_StreamConfig.remoteInputAesKey));
|
||||
|
||||
// Only the first 4 bytes are populated in the RI key IV
|
||||
RAND_bytes(reinterpret_cast<unsigned char*>(m_StreamConfig.remoteInputAesIv), 4);
|
||||
|
||||
for (unsigned int i = 0; i < sizeof(m_StreamConfig.remoteInputAesKey); i++) {
|
||||
m_StreamConfig.remoteInputAesKey[i] =
|
||||
(char)(QRandomGenerator::global()->generate() % 256);
|
||||
}
|
||||
*(int*)m_StreamConfig.remoteInputAesIv = qToBigEndian(QRandomGenerator::global()->generate());
|
||||
switch (m_Preferences.audioConfig)
|
||||
{
|
||||
case StreamingPreferences::AC_AUTO:
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Autodetecting audio configuration");
|
||||
m_StreamConfig.audioConfiguration = sdlDetermineAudioConfiguration();
|
||||
break;
|
||||
case StreamingPreferences::AC_FORCE_STEREO:
|
||||
@@ -283,10 +215,6 @@ Session::Session(NvComputer* computer, NvApp& app)
|
||||
break;
|
||||
}
|
||||
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Audio configuration: %d",
|
||||
m_StreamConfig.audioConfiguration);
|
||||
|
||||
switch (m_Preferences.videoCodecConfig)
|
||||
{
|
||||
case StreamingPreferences::VCC_AUTO:
|
||||
@@ -328,54 +256,28 @@ Session::Session(NvComputer* computer, NvApp& app)
|
||||
}
|
||||
}
|
||||
|
||||
void Session::emitLaunchWarning(QString text)
|
||||
{
|
||||
// Emit the warning to the UI
|
||||
emit displayLaunchWarning(text);
|
||||
|
||||
// Wait a little bit so the user can actually read what we just said.
|
||||
// This wait is a little longer than the actual toast timeout (3 seconds)
|
||||
// to allow it to transition off the screen before continuing.
|
||||
uint32_t start = SDL_GetTicks();
|
||||
while (!SDL_TICKS_PASSED(SDL_GetTicks(), start + 3500)) {
|
||||
// Pump the UI loop while we wait
|
||||
SDL_Delay(5);
|
||||
QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
|
||||
}
|
||||
}
|
||||
|
||||
bool Session::validateLaunch()
|
||||
{
|
||||
QStringList warningList;
|
||||
|
||||
if (m_Preferences.videoDecoderSelection == StreamingPreferences::VDS_FORCE_SOFTWARE) {
|
||||
emitLaunchWarning("Your settings selection to force software decoding may cause poor streaming performance.");
|
||||
}
|
||||
|
||||
if (m_StreamConfig.supportsHevc) {
|
||||
bool hevcForced = m_Preferences.videoCodecConfig == StreamingPreferences::VCC_FORCE_HEVC ||
|
||||
m_Preferences.videoCodecConfig == StreamingPreferences::VCC_FORCE_HEVC_HDR;
|
||||
|
||||
if (!isHardwareDecodeAvailable(m_Preferences.videoDecoderSelection,
|
||||
VIDEO_FORMAT_H265,
|
||||
m_StreamConfig.width,
|
||||
m_StreamConfig.height,
|
||||
m_StreamConfig.fps) &&
|
||||
m_Preferences.videoDecoderSelection != StreamingPreferences::VDS_FORCE_SOFTWARE) {
|
||||
if (hevcForced) {
|
||||
emitLaunchWarning("Using software decoding due to your selection to force HEVC. This may cause poor streaming performance.");
|
||||
}
|
||||
else {
|
||||
emitLaunchWarning("This PC's GPU doesn't support HEVC decoding.");
|
||||
m_StreamConfig.supportsHevc = false;
|
||||
if (m_Preferences.videoCodecConfig == StreamingPreferences::VCC_FORCE_HEVC ||
|
||||
m_Preferences.videoCodecConfig == StreamingPreferences::VCC_FORCE_HEVC_HDR) {
|
||||
if (m_Computer->maxLumaPixelsHEVC == 0) {
|
||||
emit displayLaunchWarning("Your host PC GPU doesn't support HEVC. "
|
||||
"A GeForce GTX 900-series (Maxwell) or later GPU is required for HEVC streaming.");
|
||||
}
|
||||
}
|
||||
|
||||
if (hevcForced) {
|
||||
if (m_Computer->maxLumaPixelsHEVC == 0) {
|
||||
emitLaunchWarning("Your host PC GPU doesn't support HEVC. "
|
||||
"A GeForce GTX 900-series (Maxwell) or later GPU is required for HEVC streaming.");
|
||||
}
|
||||
else if (!isHardwareDecodeAvailable(m_Preferences.videoDecoderSelection,
|
||||
VIDEO_FORMAT_H265,
|
||||
m_StreamConfig.width,
|
||||
m_StreamConfig.height,
|
||||
m_StreamConfig.fps)) {
|
||||
// NOTE: HEVC currently uses only 1 slice regardless of what
|
||||
// we provide in CAPABILITY_SLICES_PER_FRAME(), so we should
|
||||
// never use it for software decoding (unless common-c starts
|
||||
// respecting it for HEVC).
|
||||
m_StreamConfig.supportsHevc = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -385,19 +287,19 @@ bool Session::validateLaunch()
|
||||
|
||||
// Check that the app supports HDR
|
||||
if (!m_App.hdrSupported) {
|
||||
emitLaunchWarning(m_App.name + " doesn't support HDR10.");
|
||||
emit displayLaunchWarning(m_App.name + " doesn't support HDR10.");
|
||||
}
|
||||
// Check that the server GPU supports HDR
|
||||
else if (!(m_Computer->serverCodecModeSupport & 0x200)) {
|
||||
emitLaunchWarning("Your host PC GPU doesn't support HDR streaming. "
|
||||
"A GeForce GTX 1000-series (Pascal) or later GPU is required for HDR streaming.");
|
||||
emit displayLaunchWarning("Your host PC GPU doesn't support HDR streaming. "
|
||||
"A GeForce GTX 1000-series (Pascal) or later GPU is required for HDR streaming.");
|
||||
}
|
||||
else if (!isHardwareDecodeAvailable(m_Preferences.videoDecoderSelection,
|
||||
VIDEO_FORMAT_H265_MAIN10,
|
||||
m_StreamConfig.width,
|
||||
m_StreamConfig.height,
|
||||
m_StreamConfig.fps)) {
|
||||
emitLaunchWarning("This PC's GPU doesn't support HEVC Main10 decoding for HDR streaming.");
|
||||
emit displayLaunchWarning("Your client PC GPU doesn't support HEVC Main10 decoding for HDR streaming.");
|
||||
}
|
||||
else {
|
||||
// TODO: Also validate display capabilites
|
||||
@@ -410,7 +312,7 @@ bool Session::validateLaunch()
|
||||
if (m_StreamConfig.width >= 3840) {
|
||||
// Only allow 4K on GFE 3.x+
|
||||
if (m_Computer->gfeVersion.isNull() || m_Computer->gfeVersion.startsWith("2.")) {
|
||||
emitLaunchWarning("GeForce Experience 3.0 or higher is required for 4K streaming.");
|
||||
emit displayLaunchWarning("GeForce Experience 3.0 or higher is required for 4K streaming.");
|
||||
|
||||
m_StreamConfig.width = 1920;
|
||||
m_StreamConfig.height = 1080;
|
||||
@@ -418,8 +320,8 @@ bool Session::validateLaunch()
|
||||
// This list is sorted from least to greatest
|
||||
else if (m_Computer->displayModes.last().width < 3840 ||
|
||||
(m_Computer->displayModes.last().refreshRate < 60 && m_StreamConfig.fps >= 60)) {
|
||||
emitLaunchWarning("Your host PC GPU doesn't support 4K streaming. "
|
||||
"A GeForce GTX 900-series (Maxwell) or later GPU is required for 4K streaming.");
|
||||
emit displayLaunchWarning("Your host PC GPU doesn't support 4K streaming. "
|
||||
"A GeForce GTX 900-series (Maxwell) or later GPU is required for 4K streaming.");
|
||||
|
||||
m_StreamConfig.width = 1920;
|
||||
m_StreamConfig.height = 1080;
|
||||
@@ -437,6 +339,9 @@ class DeferredSessionCleanupTask : public QRunnable
|
||||
{
|
||||
// Finish cleanup of the connection state
|
||||
LiStopConnection();
|
||||
if (Session::s_ActiveSession->m_Window != nullptr) {
|
||||
SDL_DestroyWindow(Session::s_ActiveSession->m_Window);
|
||||
}
|
||||
|
||||
// Allow another session to start now that we're cleaned up
|
||||
Session::s_ActiveSession = nullptr;
|
||||
@@ -444,130 +349,6 @@ class DeferredSessionCleanupTask : public QRunnable
|
||||
}
|
||||
};
|
||||
|
||||
void Session::getWindowDimensions(bool fullScreen,
|
||||
int& x, int& y,
|
||||
int& width, int& height)
|
||||
{
|
||||
int displayIndex = 0;
|
||||
|
||||
// If there's a display matching this exact resolution, pick that
|
||||
// one (for native full-screen streaming). Otherwise, assume
|
||||
// display 0 for now. TODO: Default to the screen that the Qt window is on
|
||||
if (fullScreen) {
|
||||
for (int i = 0; i < SDL_GetNumVideoDisplays(); i++) {
|
||||
SDL_DisplayMode mode;
|
||||
if (SDL_GetCurrentDisplayMode(i, &mode) == 0 &&
|
||||
m_ActiveVideoWidth == mode.w &&
|
||||
m_ActiveVideoHeight == mode.h) {
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Found exact resolution match on display: %d",
|
||||
i);
|
||||
displayIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_Window != nullptr) {
|
||||
displayIndex = SDL_GetWindowDisplayIndex(m_Window);
|
||||
if (displayIndex < 0) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"SDL_GetWindowDisplayIndex() failed: %s",
|
||||
SDL_GetError());
|
||||
|
||||
// Assume display 0
|
||||
displayIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (fullScreen) {
|
||||
SDL_DisplayMode currentMode;
|
||||
|
||||
if (SDL_GetCurrentDisplayMode(displayIndex, ¤tMode) == 0) {
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Using current display mode: %dx%dx%d",
|
||||
currentMode.w, currentMode.h, currentMode.refresh_rate);
|
||||
width = currentMode.w;
|
||||
height = currentMode.h;
|
||||
}
|
||||
else {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Unable to get current display mode: %s",
|
||||
SDL_GetError());
|
||||
width = m_StreamConfig.width;
|
||||
height = m_StreamConfig.height;
|
||||
}
|
||||
|
||||
// Full-screen modes always start at the origin
|
||||
x = y = SDL_WINDOWPOS_UNDEFINED_DISPLAY(displayIndex);
|
||||
}
|
||||
else {
|
||||
SDL_Rect usableBounds;
|
||||
if (SDL_GetDisplayUsableBounds(displayIndex, &usableBounds) == 0) {
|
||||
width = usableBounds.w;
|
||||
height = usableBounds.h;
|
||||
x = usableBounds.x;
|
||||
y = usableBounds.y;
|
||||
|
||||
if (m_Window != nullptr) {
|
||||
int top, left, bottom, right;
|
||||
|
||||
if (SDL_GetWindowBordersSize(m_Window, &top, &left, &bottom, &right) < 0) {
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Unable to get window border size");
|
||||
return;
|
||||
}
|
||||
|
||||
x += left;
|
||||
y += top;
|
||||
|
||||
width -= left + right;
|
||||
height -= top + bottom;
|
||||
|
||||
// If the stream window can fit within the usable drawing area with 1:1
|
||||
// scaling, do that rather than filling the screen.
|
||||
if (m_StreamConfig.width < width && m_StreamConfig.height < height) {
|
||||
width = m_StreamConfig.width;
|
||||
height = m_StreamConfig.height;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"SDL_GetDisplayUsableBounds() failed: %s",
|
||||
SDL_GetError());
|
||||
|
||||
width = m_StreamConfig.width;
|
||||
height = m_StreamConfig.height;
|
||||
x = y = SDL_WINDOWPOS_UNDEFINED_DISPLAY(displayIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Session::toggleFullscreen()
|
||||
{
|
||||
bool fullScreen = !(SDL_GetWindowFlags(m_Window) & SDL_OS_FULLSCREEN_FLAG);
|
||||
|
||||
int x, y, width, height;
|
||||
|
||||
// If we're leaving full screen, toggle out before setting our size and position
|
||||
// that way we have accurate display size metrics (not the size our stream changed it to).
|
||||
if (!fullScreen) {
|
||||
SDL_SetWindowFullscreen(m_Window, 0);
|
||||
SDL_SetWindowResizable(m_Window, SDL_TRUE);
|
||||
}
|
||||
|
||||
getWindowDimensions(fullScreen, x, y, width, height);
|
||||
|
||||
SDL_SetWindowPosition(m_Window, x, y);
|
||||
SDL_SetWindowSize(m_Window, width, height);
|
||||
|
||||
if (fullScreen) {
|
||||
SDL_SetWindowResizable(m_Window, SDL_FALSE);
|
||||
SDL_SetWindowFullscreen(m_Window, SDL_OS_FULLSCREEN_FLAG);
|
||||
}
|
||||
}
|
||||
|
||||
void Session::exec()
|
||||
{
|
||||
// Check for validation errors/warnings and emit
|
||||
@@ -594,18 +375,6 @@ void Session::exec()
|
||||
Q_ASSERT(m_Computer->currentGameId == 0 ||
|
||||
m_Computer->currentGameId == m_App.id);
|
||||
|
||||
bool enableGameOptimizations = false;
|
||||
for (const NvDisplayMode &mode : m_Computer->displayModes) {
|
||||
if (mode.width == m_StreamConfig.width &&
|
||||
mode.height == m_StreamConfig.height) {
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Found host supported resolution: %dx%d",
|
||||
mode.width, mode.height);
|
||||
enableGameOptimizations = prefs.gameOptimizations;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
NvHTTP http(m_Computer->activeAddress);
|
||||
if (m_Computer->currentGameId != 0) {
|
||||
@@ -613,7 +382,7 @@ void Session::exec()
|
||||
}
|
||||
else {
|
||||
http.launchApp(m_App.id, &m_StreamConfig,
|
||||
enableGameOptimizations,
|
||||
prefs.gameOptimizations,
|
||||
prefs.playAudioOnHost,
|
||||
inputHandler.getAttachedGamepadMask());
|
||||
}
|
||||
@@ -623,12 +392,64 @@ void Session::exec()
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_assert(!SDL_WasInit(SDL_INIT_VIDEO));
|
||||
if (SDL_InitSubSystem(SDL_INIT_VIDEO) != 0) {
|
||||
int flags = SDL_WINDOW_HIDDEN;
|
||||
int width, height;
|
||||
if (m_Preferences.fullScreen) {
|
||||
SDL_DisplayMode desired, closest;
|
||||
|
||||
SDL_zero(desired);
|
||||
desired.w = m_StreamConfig.width;
|
||||
desired.h = m_StreamConfig.height;
|
||||
desired.refresh_rate = m_StreamConfig.fps;
|
||||
|
||||
if (SDL_GetClosestDisplayMode(0, &desired, &closest)) {
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Closest match for %dx%dx%d is %dx%dx%d",
|
||||
desired.w, desired.h, desired.refresh_rate,
|
||||
closest.w, closest.h, closest.refresh_rate);
|
||||
width = closest.w;
|
||||
height = closest.h;
|
||||
}
|
||||
else if (SDL_GetCurrentDisplayMode(0, &closest) == 0) {
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Using current display mode: %dx%dx%d",
|
||||
closest.w, closest.h, closest.refresh_rate);
|
||||
width = closest.w;
|
||||
height = closest.h;
|
||||
}
|
||||
else {
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Unable to get current or closest display mode");
|
||||
width = m_StreamConfig.width;
|
||||
height = m_StreamConfig.height;
|
||||
}
|
||||
|
||||
flags |= SDL_WINDOW_FULLSCREEN;
|
||||
}
|
||||
else {
|
||||
SDL_DisplayMode current;
|
||||
|
||||
width = m_StreamConfig.width;
|
||||
height = m_StreamConfig.height;
|
||||
|
||||
if (SDL_GetCurrentDisplayMode(0, ¤t) == 0) {
|
||||
if (current.w <= m_StreamConfig.width || current.h <= m_StreamConfig.height) {
|
||||
// If we match or exceed the dimensions of the display, maximize the window
|
||||
flags |= SDL_WINDOW_MAXIMIZED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_Window = SDL_CreateWindow("Moonlight",
|
||||
SDL_WINDOWPOS_UNDEFINED,
|
||||
SDL_WINDOWPOS_UNDEFINED,
|
||||
width,
|
||||
height,
|
||||
flags);
|
||||
if (!m_Window) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"SDL_InitSubSystem(SDL_INIT_VIDEO) failed: %s",
|
||||
"SDL_CreateWindow() failed: %s",
|
||||
SDL_GetError());
|
||||
emit displayLaunchError(QString::fromLocal8Bit(SDL_GetError()));
|
||||
s_ActiveSessionSemaphore.release();
|
||||
return;
|
||||
}
|
||||
@@ -656,7 +477,6 @@ void Session::exec()
|
||||
// We already displayed an error dialog in the stage failure
|
||||
// listener.
|
||||
s_ActiveSessionSemaphore.release();
|
||||
SDL_QuitSubSystem(SDL_INIT_VIDEO);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -664,71 +484,11 @@ void Session::exec()
|
||||
emit connectionStarted();
|
||||
QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
|
||||
|
||||
int x, y, width, height;
|
||||
getWindowDimensions(m_Preferences.fullScreen,
|
||||
x, y, width, height);
|
||||
// Show the streaming window
|
||||
SDL_ShowWindow(m_Window);
|
||||
|
||||
m_Window = SDL_CreateWindow("Moonlight",
|
||||
x,
|
||||
y,
|
||||
width,
|
||||
height,
|
||||
m_Preferences.fullScreen ?
|
||||
SDL_OS_FULLSCREEN_FLAG : 0);
|
||||
if (!m_Window) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"SDL_CreateWindow() failed: %s",
|
||||
SDL_GetError());
|
||||
s_ActiveSessionSemaphore.release();
|
||||
SDL_QuitSubSystem(SDL_INIT_VIDEO);
|
||||
return;
|
||||
}
|
||||
|
||||
// For non-full screen windows, call getWindowDimensions()
|
||||
// again after creating a window to allow it to account
|
||||
// for window chrome size.
|
||||
if (!m_Preferences.fullScreen) {
|
||||
getWindowDimensions(false, x, y, width, height);
|
||||
|
||||
SDL_SetWindowPosition(m_Window, x, y);
|
||||
SDL_SetWindowSize(m_Window, width, height);
|
||||
|
||||
// Passing SDL_WINDOW_RESIZABLE to set this during window
|
||||
// creation causes our window to be full screen for some reason
|
||||
SDL_SetWindowResizable(m_Window, SDL_TRUE);
|
||||
}
|
||||
|
||||
QSvgRenderer svgIconRenderer(QString(":/res/moonlight.svg"));
|
||||
QImage svgImage(ICON_SIZE, ICON_SIZE, QImage::Format_RGBA8888);
|
||||
svgImage.fill(0);
|
||||
|
||||
QPainter svgPainter(&svgImage);
|
||||
svgIconRenderer.render(&svgPainter);
|
||||
SDL_Surface* iconSurface = SDL_CreateRGBSurfaceWithFormatFrom((void*)svgImage.constBits(),
|
||||
svgImage.width(),
|
||||
svgImage.height(),
|
||||
32,
|
||||
4 * svgImage.width(),
|
||||
SDL_PIXELFORMAT_RGBA32);
|
||||
#ifndef Q_OS_DARWIN
|
||||
// Other platforms seem to preserve our Qt icon when creating a new window
|
||||
if (iconSurface != nullptr) {
|
||||
SDL_SetWindowIcon(m_Window, iconSurface);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef QT_DEBUG
|
||||
// Capture the mouse by default on release builds only.
|
||||
// This prevents the mouse from becoming trapped inside
|
||||
// Moonlight when it's halted at a debug break.
|
||||
// Capture the mouse
|
||||
SDL_SetRelativeMouseMode(SDL_TRUE);
|
||||
#endif
|
||||
|
||||
// Stop text input. SDL enables it by default
|
||||
// when we initialize the video subsystem, but this
|
||||
// causes an IME popup when certain keys are held down
|
||||
// on macOS.
|
||||
SDL_StopTextInput();
|
||||
|
||||
// Disable the screen saver
|
||||
SDL_DisableScreenSaver();
|
||||
@@ -744,15 +504,7 @@ void Session::exec()
|
||||
// Hijack this thread to be the SDL main thread. We have to do this
|
||||
// because we want to suspend all Qt processing until the stream is over.
|
||||
SDL_Event event;
|
||||
for (;;) {
|
||||
// We explicitly use SDL_PollEvent() and SDL_Delay() because
|
||||
// SDL_WaitEvent() has an internal SDL_Delay(10) inside which
|
||||
// blocks this thread too long for high polling rate mice and high
|
||||
// refresh rate displays.
|
||||
if (!SDL_PollEvent(&event)) {
|
||||
SDL_Delay(1);
|
||||
continue;
|
||||
}
|
||||
while (SDL_WaitEvent(&event)) {
|
||||
switch (event.type) {
|
||||
case SDL_QUIT:
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
||||
@@ -777,41 +529,6 @@ void Session::exec()
|
||||
m_VideoDecoder->renderFrame(&event.user);
|
||||
break;
|
||||
}
|
||||
|
||||
case SDL_WINDOWEVENT:
|
||||
// We want to recreate the decoder for resizes (full-screen toggles) and the initial shown event.
|
||||
// We use SDL_WINDOWEVENT_SIZE_CHANGED rather than SDL_WINDOWEVENT_RESIZED because the latter doesn't
|
||||
// seem to fire when switching from windowed to full-screen on X11.
|
||||
if (event.window.event != SDL_WINDOWEVENT_SIZE_CHANGED && event.window.event != SDL_WINDOWEVENT_SHOWN) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Fall through
|
||||
case SDL_RENDER_DEVICE_RESET:
|
||||
case SDL_RENDER_TARGETS_RESET:
|
||||
SDL_AtomicLock(&m_DecoderLock);
|
||||
|
||||
// Destroy the old decoder
|
||||
delete m_VideoDecoder;
|
||||
|
||||
// Chose a new decoder (hopefully the same one, but possibly
|
||||
// not if a GPU was removed or something).
|
||||
if (!chooseDecoder(m_Preferences.videoDecoderSelection,
|
||||
m_Window, m_ActiveVideoFormat, m_ActiveVideoWidth,
|
||||
m_ActiveVideoHeight, m_ActiveVideoFrameRate,
|
||||
s_ActiveSession->m_VideoDecoder)) {
|
||||
SDL_AtomicUnlock(&m_DecoderLock);
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Failed to recreate decoder after reset");
|
||||
goto DispatchDeferredCleanup;
|
||||
}
|
||||
|
||||
// Request an IDR frame to complete the reset
|
||||
m_NeedsIdr = true;
|
||||
|
||||
SDL_AtomicUnlock(&m_DecoderLock);
|
||||
break;
|
||||
|
||||
case SDL_KEYUP:
|
||||
case SDL_KEYDOWN:
|
||||
inputHandler.handleKeyEvent(&event.key);
|
||||
@@ -849,6 +566,9 @@ DispatchDeferredCleanup:
|
||||
// so we can return to the Qt GUI ASAP.
|
||||
SDL_SetRelativeMouseMode(SDL_FALSE);
|
||||
SDL_EnableScreenSaver();
|
||||
if (m_Window != nullptr) {
|
||||
SDL_HideWindow(m_Window);
|
||||
}
|
||||
|
||||
// Destroy the decoder, since this must be done on the main thread
|
||||
SDL_AtomicLock(&m_DecoderLock);
|
||||
@@ -856,13 +576,6 @@ DispatchDeferredCleanup:
|
||||
m_VideoDecoder = nullptr;
|
||||
SDL_AtomicUnlock(&m_DecoderLock);
|
||||
|
||||
SDL_DestroyWindow(m_Window);
|
||||
if (iconSurface != nullptr) {
|
||||
SDL_FreeSurface(iconSurface);
|
||||
}
|
||||
SDL_QuitSubSystem(SDL_INIT_VIDEO);
|
||||
SDL_assert(!SDL_WasInit(SDL_INIT_VIDEO));
|
||||
|
||||
// Cleanup can take a while, so dispatch it to a worker thread.
|
||||
// When it is complete, it will release our s_ActiveSessionSemaphore
|
||||
// reference.
|
||||
|
||||
@@ -21,10 +21,6 @@ public:
|
||||
|
||||
Q_INVOKABLE void exec();
|
||||
|
||||
static
|
||||
bool isHardwareDecodeAvailable(StreamingPreferences::VideoDecoderSelection vds,
|
||||
int videoFormat, int width, int height, int frameRate);
|
||||
|
||||
signals:
|
||||
void stageStarting(QString stage);
|
||||
|
||||
@@ -39,17 +35,13 @@ signals:
|
||||
private:
|
||||
bool validateLaunch();
|
||||
|
||||
void emitLaunchWarning(QString text);
|
||||
|
||||
int getDecoderCapabilities();
|
||||
|
||||
int sdlDetermineAudioConfiguration();
|
||||
|
||||
void getWindowDimensions(bool fullScreen,
|
||||
int& x, int& y,
|
||||
int& width, int& height);
|
||||
|
||||
void toggleFullscreen();
|
||||
static
|
||||
bool isHardwareDecodeAvailable(StreamingPreferences::VideoDecoderSelection vds,
|
||||
int videoFormat, int width, int height, int frameRate);
|
||||
|
||||
static
|
||||
bool chooseDecoder(StreamingPreferences::VideoDecoderSelection vds,
|
||||
@@ -102,12 +94,6 @@ private:
|
||||
SDL_Window* m_Window;
|
||||
IVideoDecoder* m_VideoDecoder;
|
||||
SDL_SpinLock m_DecoderLock;
|
||||
bool m_NeedsIdr;
|
||||
|
||||
int m_ActiveVideoFormat;
|
||||
int m_ActiveVideoWidth;
|
||||
int m_ActiveVideoHeight;
|
||||
int m_ActiveVideoFrameRate;
|
||||
|
||||
static SDL_AudioDeviceID s_AudioDevice;
|
||||
static OpusMSDecoder* s_OpusDecoder;
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
#include "streamutils.h"
|
||||
|
||||
void StreamUtils::scaleSourceToDestinationSurface(SDL_Rect* src, SDL_Rect* dst)
|
||||
{
|
||||
int dstH = dst->w * src->h / src->w;
|
||||
int dstW = dst->h * src->w / src->h;
|
||||
|
||||
if (dstH > dst->h) {
|
||||
dst->y = 0;
|
||||
dst->x = (dst->w - dstW) / 2;
|
||||
dst->w = dstW;
|
||||
SDL_assert(dst->w * src->h / src->w <= dst->h);
|
||||
}
|
||||
else {
|
||||
dst->x = 0;
|
||||
dst->y = (dst->h - dstH) / 2;
|
||||
dst->h = dstH;
|
||||
SDL_assert(dst->h * src->w / src->h <= dst->w);
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <SDL.h>
|
||||
|
||||
class StreamUtils
|
||||
{
|
||||
public:
|
||||
static
|
||||
void scaleSourceToDestinationSurface(SDL_Rect* src, SDL_Rect* dst);
|
||||
};
|
||||
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include "decoder.h"
|
||||
|
||||
// A factory is required to avoid pulling in
|
||||
// incompatible Objective-C headers.
|
||||
class AVFoundationDecoderFactory {
|
||||
public:
|
||||
static
|
||||
IVideoDecoder* createDecoder();
|
||||
};
|
||||
@@ -0,0 +1,521 @@
|
||||
#include "avfoundation.h"
|
||||
|
||||
#include <SDL_syswm.h>
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import <VideoToolbox/VideoToolbox.h>
|
||||
#import <AVFoundation/AVFoundation.h>
|
||||
#import <CoreVideo/CoreVideo.h>
|
||||
|
||||
#define FRAME_START_PREFIX_SIZE 4
|
||||
#define NALU_START_PREFIX_SIZE 3
|
||||
#define NAL_LENGTH_PREFIX_SIZE 4
|
||||
|
||||
#define FUTURE_FRAMES_IN_VSYNC 3
|
||||
|
||||
class AVFoundationDecoder : public IVideoDecoder
|
||||
{
|
||||
public:
|
||||
AVFoundationDecoder()
|
||||
: m_DisplayLayer(nullptr),
|
||||
m_FormatDesc(nullptr),
|
||||
m_SpsData(nullptr),
|
||||
m_PpsData(nullptr),
|
||||
m_VpsData(nullptr),
|
||||
m_View(nullptr),
|
||||
m_NeedsIdr(false),
|
||||
m_DisplayLink(nullptr),
|
||||
m_VsyncTime(0),
|
||||
m_LastVsyncTime(0),
|
||||
m_VsyncStatsLock(0)
|
||||
{
|
||||
SDL_zero(m_FrameCountOnVsync);
|
||||
}
|
||||
|
||||
virtual ~AVFoundationDecoder()
|
||||
{
|
||||
if (m_FormatDesc != nullptr) {
|
||||
CFRelease(m_FormatDesc);
|
||||
}
|
||||
|
||||
if (m_DisplayLink != nullptr) {
|
||||
CVDisplayLinkStop(m_DisplayLink);
|
||||
CVDisplayLinkRelease(m_DisplayLink);
|
||||
}
|
||||
|
||||
delete m_SpsData;
|
||||
delete m_PpsData;
|
||||
delete m_VpsData;
|
||||
}
|
||||
|
||||
static
|
||||
CVReturn
|
||||
displayLinkOutputCallback(
|
||||
CVDisplayLinkRef,
|
||||
const CVTimeStamp*,
|
||||
const CVTimeStamp* vsyncTime,
|
||||
CVOptionFlags,
|
||||
CVOptionFlags*,
|
||||
void *displayLinkContext)
|
||||
{
|
||||
AVFoundationDecoder* me = reinterpret_cast<AVFoundationDecoder*>(displayLinkContext);
|
||||
|
||||
SDL_AtomicLock(&me->m_VsyncStatsLock);
|
||||
me->m_LastVsyncTime = me->m_VsyncTime;
|
||||
me->m_VsyncTime = vsyncTime->hostTime;
|
||||
|
||||
int framesThisVsync = *(volatile int*)&me->m_FrameCountOnVsync[0];
|
||||
|
||||
memmove(&me->m_FrameCountOnVsync[0],
|
||||
&me->m_FrameCountOnVsync[1],
|
||||
sizeof(me->m_FrameCountOnVsync) - sizeof(me->m_FrameCountOnVsync[0]));
|
||||
me->m_FrameCountOnVsync[FUTURE_FRAMES_IN_VSYNC - 1] = 0;
|
||||
SDL_AtomicUnlock(&me->m_VsyncStatsLock);
|
||||
|
||||
if (framesThisVsync != 1)
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"V-Sync interval frames: %d",
|
||||
framesThisVsync);
|
||||
|
||||
return kCVReturnSuccess;
|
||||
}
|
||||
|
||||
virtual bool initialize(StreamingPreferences::VideoDecoderSelection vds,
|
||||
SDL_Window* window,
|
||||
int videoFormat,
|
||||
int, int, int) override
|
||||
{
|
||||
m_VideoFormat = videoFormat;
|
||||
|
||||
// Fail if the user wants software decode only
|
||||
if (vds == StreamingPreferences::VDS_FORCE_SOFTWARE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (videoFormat & VIDEO_FORMAT_MASK_H264) {
|
||||
// Prior to 10.13, we'll just assume everything has
|
||||
// H.264 support and fail open to allow VT decode.
|
||||
#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 101300
|
||||
if (__builtin_available(macOS 10.13, *)) {
|
||||
if (!VTIsHardwareDecodeSupported(kCMVideoCodecType_H264)) {
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"No HW accelerated H.264 decode via VT");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Assuming H.264 HW decode on < macOS 10.13");
|
||||
}
|
||||
}
|
||||
else if (videoFormat & VIDEO_FORMAT_MASK_H265) {
|
||||
#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 101300
|
||||
if (__builtin_available(macOS 10.13, *)) {
|
||||
if (!VTIsHardwareDecodeSupported(kCMVideoCodecType_HEVC)) {
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"No HW accelerated HEVC decode via VT");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
// Fail closed for HEVC if we're not on 10.13+
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"No HEVC support on < macOS 10.13");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_SysWMinfo info;
|
||||
|
||||
SDL_VERSION(&info.version);
|
||||
|
||||
if (!SDL_GetWindowWMInfo(window, &info)) {
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"SDL_GetWindowWMInfo() failed: %s",
|
||||
SDL_GetError());
|
||||
return false;
|
||||
}
|
||||
|
||||
SDL_assert(info.subsystem == SDL_SYSWM_COCOA);
|
||||
|
||||
// SDL adds its own content view to listen for events.
|
||||
// We need to add a subview for our display layer.
|
||||
NSView* contentView = info.info.cocoa.window.contentView;
|
||||
m_View = [[NSView alloc] initWithFrame:contentView.bounds];
|
||||
m_View.wantsLayer = YES;
|
||||
[contentView addSubview: m_View];
|
||||
|
||||
setupDisplayLayer();
|
||||
|
||||
CVDisplayLinkCreateWithActiveCGDisplays(&m_DisplayLink);
|
||||
CVDisplayLinkSetOutputCallback(m_DisplayLink, displayLinkOutputCallback, (void*)this);
|
||||
CVDisplayLinkStart(m_DisplayLink);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool isHardwareAccelerated() override
|
||||
{
|
||||
// We only use AVFoundation for HW acceleration
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual int submitDecodeUnit(PDECODE_UNIT du) override
|
||||
{
|
||||
OSStatus status;
|
||||
|
||||
unsigned char* data = (unsigned char*)malloc(du->fullLength);
|
||||
if (!data) {
|
||||
return DR_NEED_IDR;
|
||||
}
|
||||
|
||||
PLENTRY entry = du->bufferList;
|
||||
int pictureDataLength = 0;
|
||||
while (entry != nullptr) {
|
||||
if (entry->bufferType == BUFFER_TYPE_VPS) {
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Got VPS");
|
||||
delete m_VpsData;
|
||||
m_VpsData = new QByteArray(&entry->data[FRAME_START_PREFIX_SIZE], entry->length - FRAME_START_PREFIX_SIZE);
|
||||
|
||||
// We got a new VPS so wait for a new SPS to match it
|
||||
delete m_SpsData;
|
||||
delete m_PpsData;
|
||||
m_SpsData = m_PpsData = nullptr;
|
||||
}
|
||||
else if (entry->bufferType == BUFFER_TYPE_SPS) {
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Got SPS");
|
||||
delete m_SpsData;
|
||||
m_SpsData = new QByteArray(&entry->data[FRAME_START_PREFIX_SIZE], entry->length - FRAME_START_PREFIX_SIZE);
|
||||
|
||||
// We got a new SPS so wait for a new PPS to match it
|
||||
delete m_PpsData;
|
||||
m_PpsData = nullptr;
|
||||
}
|
||||
else if (entry->bufferType == BUFFER_TYPE_PPS) {
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Got PPS");
|
||||
delete m_PpsData;
|
||||
m_PpsData = new QByteArray(&entry->data[FRAME_START_PREFIX_SIZE], entry->length - FRAME_START_PREFIX_SIZE);
|
||||
}
|
||||
else {
|
||||
// Picture data
|
||||
SDL_assert(entry->bufferType == BUFFER_TYPE_PICDATA);
|
||||
memcpy(&data[pictureDataLength],
|
||||
entry->data,
|
||||
entry->length);
|
||||
pictureDataLength += entry->length;
|
||||
}
|
||||
|
||||
entry = entry->next;
|
||||
}
|
||||
|
||||
SDL_assert(pictureDataLength <= du->fullLength);
|
||||
|
||||
if (du->frameType == FRAME_TYPE_IDR) {
|
||||
m_NeedsIdr = false;
|
||||
|
||||
if (m_FormatDesc != nullptr) {
|
||||
CFRelease(m_FormatDesc);
|
||||
}
|
||||
|
||||
if (m_VideoFormat & VIDEO_FORMAT_MASK_H264) {
|
||||
const uint8_t* const parameterSetPointers[] = { (uint8_t*)m_SpsData->data(),
|
||||
(uint8_t*)m_PpsData->data() };
|
||||
const size_t parameterSetSizes[] = { (size_t)m_SpsData->length(),
|
||||
(size_t)m_PpsData->length() };
|
||||
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Constructing new H264 format description");
|
||||
status = CMVideoFormatDescriptionCreateFromH264ParameterSets(kCFAllocatorDefault,
|
||||
2, /* count of parameter sets */
|
||||
parameterSetPointers,
|
||||
parameterSetSizes,
|
||||
NAL_LENGTH_PREFIX_SIZE,
|
||||
&m_FormatDesc);
|
||||
if (status != noErr) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Failed to create H264 format description: %d",
|
||||
(int)status);
|
||||
m_FormatDesc = NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 101300
|
||||
const uint8_t* const parameterSetPointers[] = { (uint8_t*)m_VpsData->data(),
|
||||
(uint8_t*)m_SpsData->data(),
|
||||
(uint8_t*)m_PpsData->data() };
|
||||
const size_t parameterSetSizes[] = { (size_t)m_VpsData->length(),
|
||||
(size_t)m_SpsData->length(),
|
||||
(size_t)m_PpsData->length() };
|
||||
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Constructing new HEVC format description");
|
||||
|
||||
if (__builtin_available(macOS 10.13, *)) {
|
||||
status = CMVideoFormatDescriptionCreateFromHEVCParameterSets(kCFAllocatorDefault,
|
||||
3, /* count of parameter sets */
|
||||
parameterSetPointers,
|
||||
parameterSetSizes,
|
||||
NAL_LENGTH_PREFIX_SIZE,
|
||||
nil,
|
||||
&m_FormatDesc);
|
||||
if (status != noErr) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Failed to create HEVC format description: %d",
|
||||
(int)status);
|
||||
m_FormatDesc = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
// This means Moonlight-common-c decided to give us an HEVC stream
|
||||
// even though we said we couldn't support it. All we can do is abort().
|
||||
abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_FormatDesc == nullptr || m_NeedsIdr) {
|
||||
// Can't decode if we haven't gotten our parameter sets yet
|
||||
free(data);
|
||||
return DR_NEED_IDR;
|
||||
}
|
||||
|
||||
// Now we're decoding actual frame data here
|
||||
CMBlockBufferRef blockBuffer;
|
||||
|
||||
status = CMBlockBufferCreateEmpty(NULL, 0, 0, &blockBuffer);
|
||||
if (status != noErr) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"CMBlockBufferCreateEmpty failed: %d",
|
||||
(int)status);
|
||||
free(data);
|
||||
return DR_NEED_IDR;
|
||||
}
|
||||
|
||||
int lastOffset = -1;
|
||||
for (int i = 0; i < pictureDataLength - FRAME_START_PREFIX_SIZE; i++) {
|
||||
// Search for a NALU
|
||||
if (data[i] == 0 && data[i+1] == 0 && data[i+2] == 1) {
|
||||
// It's the start of a new NALU
|
||||
if (lastOffset != -1) {
|
||||
// We've seen a start before this so enqueue that NALU
|
||||
updateBufferForRange(blockBuffer, data, lastOffset, i - lastOffset);
|
||||
}
|
||||
|
||||
lastOffset = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (lastOffset != -1) {
|
||||
// Enqueue the remaining data
|
||||
updateBufferForRange(blockBuffer, data, lastOffset, pictureDataLength - lastOffset);
|
||||
}
|
||||
|
||||
// From now on, CMBlockBuffer owns the data pointer and will free it when it's released
|
||||
|
||||
CMSampleBufferRef sampleBuffer;
|
||||
|
||||
CMSampleTimingInfo time = {
|
||||
.decodeTimeStamp = kCMTimeInvalid,
|
||||
.duration = kCMTimeInvalid
|
||||
};
|
||||
|
||||
SDL_AtomicLock(&m_VsyncStatsLock);
|
||||
// Find a slot to put this frame
|
||||
for (int i = 0; i < FUTURE_FRAMES_IN_VSYNC; i++) {
|
||||
if (m_FrameCountOnVsync[i] == 0) {
|
||||
time.presentationTimeStamp =
|
||||
CMTimeMake(m_VsyncTime + (i + 1) * (m_VsyncTime - m_LastVsyncTime),
|
||||
1000 * 1000 * 1000);
|
||||
m_FrameCountOnVsync[i]++;
|
||||
}
|
||||
}
|
||||
SDL_AtomicUnlock(&m_VsyncStatsLock);
|
||||
|
||||
status = CMSampleBufferCreate(kCFAllocatorDefault,
|
||||
blockBuffer,
|
||||
true, NULL,
|
||||
NULL, m_FormatDesc, 1, 1,
|
||||
&time, 0, NULL,
|
||||
&sampleBuffer);
|
||||
if (status != noErr) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"CMSampleBufferCreate failed: %d",
|
||||
(int)status);
|
||||
CFRelease(blockBuffer);
|
||||
return DR_NEED_IDR;
|
||||
}
|
||||
|
||||
// Submit for callback on the main thread
|
||||
queueFrame(sampleBuffer, (void*)(long)du->frameType);
|
||||
|
||||
return DR_OK;
|
||||
}
|
||||
|
||||
// This is called on the main thread, so it's safe to interact with
|
||||
// the AVSampleBufferDisplayLayer here.
|
||||
void submitBuffer(CMSampleBufferRef sampleBuffer, int frameType)
|
||||
{
|
||||
if (m_DisplayLayer.status == AVQueuedSampleBufferRenderingStatusFailed) {
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Resetting failed AVSampleBufferDisplay layer");
|
||||
setupDisplayLayer();
|
||||
CFRelease(sampleBuffer);
|
||||
return;
|
||||
}
|
||||
|
||||
CFArrayRef attachments = CMSampleBufferGetSampleAttachmentsArray(sampleBuffer, YES);
|
||||
CFMutableDictionaryRef dict = (CFMutableDictionaryRef)CFArrayGetValueAtIndex(attachments, 0);
|
||||
|
||||
CFDictionarySetValue(dict, kCMSampleAttachmentKey_IsDependedOnByOthers, kCFBooleanTrue);
|
||||
|
||||
if (frameType == FRAME_TYPE_PFRAME) {
|
||||
// P-frame
|
||||
CFDictionarySetValue(dict, kCMSampleAttachmentKey_NotSync, kCFBooleanTrue);
|
||||
CFDictionarySetValue(dict, kCMSampleAttachmentKey_DependsOnOthers, kCFBooleanTrue);
|
||||
} else {
|
||||
// I-frame
|
||||
CFDictionarySetValue(dict, kCMSampleAttachmentKey_NotSync, kCFBooleanFalse);
|
||||
CFDictionarySetValue(dict, kCMSampleAttachmentKey_DependsOnOthers, kCFBooleanFalse);
|
||||
}
|
||||
|
||||
[m_DisplayLayer enqueueSampleBuffer:sampleBuffer];
|
||||
|
||||
CFRelease(sampleBuffer);
|
||||
}
|
||||
|
||||
virtual void renderFrame(SDL_UserEvent* event) override
|
||||
{
|
||||
submitBuffer((CMSampleBufferRef)event->data1, (int)(long)event->data2);
|
||||
}
|
||||
|
||||
virtual void dropFrame(SDL_UserEvent* event) override
|
||||
{
|
||||
// Submit anyway and let the drop happen in the render pipeline
|
||||
submitBuffer((CMSampleBufferRef)event->data1, (int)(long)event->data2);
|
||||
}
|
||||
|
||||
private:
|
||||
void setupDisplayLayer()
|
||||
{
|
||||
CALayer* oldLayer = m_DisplayLayer;
|
||||
|
||||
m_DisplayLayer = [[AVSampleBufferDisplayLayer alloc] init];
|
||||
m_DisplayLayer.bounds = m_View.bounds;
|
||||
m_DisplayLayer.position = CGPointMake(CGRectGetMidX(m_View.bounds), CGRectGetMidY(m_View.bounds));
|
||||
m_DisplayLayer.videoGravity = AVLayerVideoGravityResizeAspect;
|
||||
|
||||
CALayer* viewLayer = m_View.layer;
|
||||
if (oldLayer != nil) {
|
||||
[viewLayer replaceSublayer:oldLayer with:m_DisplayLayer];
|
||||
}
|
||||
else {
|
||||
[viewLayer addSublayer:m_DisplayLayer];
|
||||
}
|
||||
|
||||
// Wait for another IDR frame
|
||||
m_NeedsIdr = true;
|
||||
|
||||
delete m_SpsData;
|
||||
delete m_PpsData;
|
||||
delete m_VpsData;
|
||||
|
||||
m_SpsData = m_PpsData = m_VpsData = nullptr;
|
||||
}
|
||||
|
||||
void updateBufferForRange(CMBlockBufferRef existingBuffer, unsigned char* data, int offset, int nalLength)
|
||||
{
|
||||
OSStatus status;
|
||||
size_t oldOffset = CMBlockBufferGetDataLength(existingBuffer);
|
||||
|
||||
// If we're at index 1 (first NALU in frame), enqueue this buffer to the memory block
|
||||
// so it can handle freeing it when the block buffer is destroyed
|
||||
if (offset == 1) {
|
||||
int dataLength = nalLength - NALU_START_PREFIX_SIZE;
|
||||
|
||||
// Pass the real buffer pointer directly (no offset)
|
||||
// This will give it to the block buffer to free when it's released.
|
||||
// All further calls to CMBlockBufferAppendMemoryBlock will do so
|
||||
// at an offset and will not be asking the buffer to be freed.
|
||||
status = CMBlockBufferAppendMemoryBlock(existingBuffer, data,
|
||||
nalLength + 1, // Add 1 for the offset we decremented
|
||||
kCFAllocatorDefault,
|
||||
NULL, 0, nalLength + 1, 0);
|
||||
if (status != noErr) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"CMBlockBufferReplaceDataBytes failed: %d",
|
||||
(int)status);
|
||||
return;
|
||||
}
|
||||
|
||||
// Write the length prefix to existing buffer
|
||||
const uint8_t lengthBytes[] = {(uint8_t)(dataLength >> 24), (uint8_t)(dataLength >> 16),
|
||||
(uint8_t)(dataLength >> 8), (uint8_t)dataLength};
|
||||
status = CMBlockBufferReplaceDataBytes(lengthBytes, existingBuffer,
|
||||
oldOffset, NAL_LENGTH_PREFIX_SIZE);
|
||||
if (status != noErr) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"CMBlockBufferReplaceDataBytes failed: %d",
|
||||
(int)status);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// Append a 4 byte buffer to this block for the length prefix
|
||||
status = CMBlockBufferAppendMemoryBlock(existingBuffer, NULL,
|
||||
NAL_LENGTH_PREFIX_SIZE,
|
||||
kCFAllocatorDefault, NULL, 0,
|
||||
NAL_LENGTH_PREFIX_SIZE, 0);
|
||||
if (status != noErr) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"CMBlockBufferAppendMemoryBlock failed: %d",
|
||||
(int)status);
|
||||
return;
|
||||
}
|
||||
|
||||
// Write the length prefix to the new buffer
|
||||
int dataLength = nalLength - NALU_START_PREFIX_SIZE;
|
||||
const uint8_t lengthBytes[] = {(uint8_t)(dataLength >> 24), (uint8_t)(dataLength >> 16),
|
||||
(uint8_t)(dataLength >> 8), (uint8_t)dataLength};
|
||||
status = CMBlockBufferReplaceDataBytes(lengthBytes, existingBuffer,
|
||||
oldOffset, NAL_LENGTH_PREFIX_SIZE);
|
||||
if (status != noErr) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"CMBlockBufferReplaceDataBytes failed: %d",
|
||||
(int)status);
|
||||
return;
|
||||
}
|
||||
|
||||
// Attach the buffer by reference to the block buffer
|
||||
status = CMBlockBufferAppendMemoryBlock(existingBuffer, &data[offset+NALU_START_PREFIX_SIZE],
|
||||
dataLength,
|
||||
kCFAllocatorNull, // Don't deallocate data on free
|
||||
NULL, 0, dataLength, 0);
|
||||
if (status != noErr) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"CMBlockBufferReplaceDataBytes failed: %d",
|
||||
(int)status);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AVSampleBufferDisplayLayer* m_DisplayLayer;
|
||||
CMVideoFormatDescriptionRef m_FormatDesc;
|
||||
int m_VideoFormat;
|
||||
QByteArray* m_SpsData;
|
||||
QByteArray* m_PpsData;
|
||||
QByteArray* m_VpsData;
|
||||
NSView* m_View;
|
||||
bool m_NeedsIdr;
|
||||
CVDisplayLinkRef m_DisplayLink;
|
||||
uint64_t m_VsyncTime, m_LastVsyncTime;
|
||||
int m_FrameCountOnVsync[FUTURE_FRAMES_IN_VSYNC];
|
||||
SDL_SpinLock m_VsyncStatsLock;
|
||||
};
|
||||
|
||||
IVideoDecoder* AVFoundationDecoderFactory::createDecoder() {
|
||||
return new AVFoundationDecoder();
|
||||
}
|
||||
@@ -1,7 +1,5 @@
|
||||
#include <initguid.h>
|
||||
#include <Initguid.h>
|
||||
#include "dxva2.h"
|
||||
#include "../ffmpeg.h"
|
||||
#include <streaming/streamutils.h>
|
||||
|
||||
#include <Limelight.h>
|
||||
|
||||
@@ -10,16 +8,16 @@ DEFINE_GUID(DXVADDI_Intel_ModeH264_E, 0x604F8E68,0x4951,0x4C54,0x88,0xFE,0xAB,0x
|
||||
#define SAFE_COM_RELEASE(x) if (x) { (x)->Release(); }
|
||||
|
||||
DXVA2Renderer::DXVA2Renderer() :
|
||||
m_FrameIndex(0),
|
||||
m_SurfacesUsed(0),
|
||||
m_SdlRenderer(nullptr),
|
||||
m_DecService(nullptr),
|
||||
m_Decoder(nullptr),
|
||||
m_SurfacesUsed(0),
|
||||
m_Pool(nullptr),
|
||||
m_Device(nullptr),
|
||||
m_RenderTarget(nullptr),
|
||||
m_ProcService(nullptr),
|
||||
m_Processor(nullptr),
|
||||
m_FrameIndex(0)
|
||||
m_Processor(nullptr)
|
||||
{
|
||||
RtlZeroMemory(m_DecSurfaces, sizeof(m_DecSurfaces));
|
||||
RtlZeroMemory(&m_DXVAContext, sizeof(m_DXVAContext));
|
||||
@@ -77,8 +75,11 @@ bool DXVA2Renderer::prepareDecoderContext(AVCodecContext* context)
|
||||
|
||||
context->hwaccel_context = &m_DXVAContext;
|
||||
|
||||
context->get_format = ffGetFormat;
|
||||
context->get_buffer2 = ffGetBuffer2;
|
||||
|
||||
context->opaque = this;
|
||||
|
||||
m_Pool = av_buffer_pool_init2(ARRAYSIZE(m_DecSurfaces), this, ffPoolAlloc, nullptr);
|
||||
if (!m_Pool) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
@@ -86,15 +87,12 @@ bool DXVA2Renderer::prepareDecoderContext(AVCodecContext* context)
|
||||
return false;
|
||||
}
|
||||
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Using DXVA2 accelerated renderer");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int DXVA2Renderer::ffGetBuffer2(AVCodecContext* context, AVFrame* frame, int)
|
||||
{
|
||||
DXVA2Renderer* me = (DXVA2Renderer*)((FFmpegVideoDecoder*)context->opaque)->getRenderer();
|
||||
DXVA2Renderer* me = reinterpret_cast<DXVA2Renderer*>(context->opaque);
|
||||
|
||||
frame->buf[0] = av_buffer_pool_get(me->m_Pool);
|
||||
if (!frame->buf[0]) {
|
||||
@@ -103,20 +101,31 @@ int DXVA2Renderer::ffGetBuffer2(AVCodecContext* context, AVFrame* frame, int)
|
||||
|
||||
frame->data[3] = frame->buf[0]->data;
|
||||
frame->format = AV_PIX_FMT_DXVA2_VLD;
|
||||
frame->width = me->m_VideoWidth;
|
||||
frame->height = me->m_VideoHeight;
|
||||
frame->width = me->m_Width;
|
||||
frame->height = me->m_Height;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
enum AVPixelFormat DXVA2Renderer::ffGetFormat(AVCodecContext*,
|
||||
const enum AVPixelFormat* pixFmts)
|
||||
{
|
||||
const enum AVPixelFormat *p;
|
||||
|
||||
for (p = pixFmts; *p != -1; p++) {
|
||||
if (*p == AV_PIX_FMT_DXVA2_VLD)
|
||||
return *p;
|
||||
}
|
||||
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Failed to find DXVA2 HW surface format");
|
||||
return AV_PIX_FMT_NONE;
|
||||
}
|
||||
|
||||
bool DXVA2Renderer::initializeDecoder()
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
if (isDecoderBlacklisted()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
hr = DXVA2CreateVideoService(m_Device, IID_IDirectXVideoDecoderService,
|
||||
reinterpret_cast<void**>(&m_DecService));
|
||||
if (FAILED(hr)) {
|
||||
@@ -199,11 +208,18 @@ bool DXVA2Renderer::initializeDecoder()
|
||||
return false;
|
||||
}
|
||||
|
||||
// Alignment was already taken care of
|
||||
SDL_assert(m_Desc.SampleWidth % 16 == 0);
|
||||
SDL_assert(m_Desc.SampleHeight % 16 == 0);
|
||||
hr = m_DecService->CreateSurface(m_Desc.SampleWidth,
|
||||
m_Desc.SampleHeight,
|
||||
int alignment;
|
||||
|
||||
// HEVC using DXVA requires 128B alignment
|
||||
if (m_VideoFormat & VIDEO_FORMAT_MASK_H265) {
|
||||
alignment = 128;
|
||||
}
|
||||
else {
|
||||
alignment = 16;
|
||||
}
|
||||
|
||||
hr = m_DecService->CreateSurface(FFALIGN(m_Width, alignment),
|
||||
FFALIGN(m_Height, alignment),
|
||||
ARRAYSIZE(m_DecSurfaces) - 1,
|
||||
m_Desc.Format,
|
||||
D3DPOOL_DEFAULT,
|
||||
@@ -246,9 +262,6 @@ bool DXVA2Renderer::initializeRenderer()
|
||||
D3DSURFACE_DESC renderTargetDesc;
|
||||
m_RenderTarget->GetDesc(&renderTargetDesc);
|
||||
|
||||
m_DisplayWidth = renderTargetDesc.Width;
|
||||
m_DisplayHeight = renderTargetDesc.Height;
|
||||
|
||||
hr = DXVA2CreateVideoService(m_Device, IID_IDirectXVideoProcessorService,
|
||||
reinterpret_cast<void**>(&m_ProcService));
|
||||
|
||||
@@ -289,14 +302,6 @@ bool DXVA2Renderer::initializeRenderer()
|
||||
caps.VideoProcessorOperations);
|
||||
continue;
|
||||
}
|
||||
else if (!(caps.VideoProcessorOperations & DXVA2_VideoProcess_StretchX) ||
|
||||
!(caps.VideoProcessorOperations & DXVA2_VideoProcess_StretchY)) {
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Device %d can't stretch video: %x",
|
||||
i,
|
||||
caps.VideoProcessorOperations);
|
||||
continue;
|
||||
}
|
||||
|
||||
m_ProcService->GetProcAmpRange(guids[i], &m_Desc, renderTargetDesc.Format, DXVA2_ProcAmp_Brightness, &m_BrightnessRange);
|
||||
m_ProcService->GetProcAmpRange(guids[i], &m_Desc, renderTargetDesc.Format, DXVA2_ProcAmp_Contrast, &m_ContrastRange);
|
||||
@@ -333,117 +338,24 @@ bool DXVA2Renderer::initializeRenderer()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DXVA2Renderer::isDecoderBlacklisted()
|
||||
{
|
||||
IDirect3D9* d3d9;
|
||||
HRESULT hr;
|
||||
bool result = false;
|
||||
|
||||
// TODO: Update for HEVC Main10
|
||||
SDL_assert(m_VideoFormat != VIDEO_FORMAT_H265_MAIN10);
|
||||
|
||||
hr = m_Device->GetDirect3D(&d3d9);
|
||||
if (SUCCEEDED(hr)) {
|
||||
D3DCAPS9 caps;
|
||||
|
||||
hr = m_Device->GetDeviceCaps(&caps);
|
||||
if (SUCCEEDED(hr)) {
|
||||
D3DADAPTER_IDENTIFIER9 id;
|
||||
|
||||
hr = d3d9->GetAdapterIdentifier(caps.AdapterOrdinal, 0, &id);
|
||||
if (SUCCEEDED(hr)) {
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Detected GPU: %s (%x:%x)",
|
||||
id.Description,
|
||||
id.VendorId,
|
||||
id.DeviceId);
|
||||
|
||||
if (id.VendorId == 0x8086) {
|
||||
// Intel seems to encode the series in the high byte of
|
||||
// the device ID. We want to avoid the "Partial" acceleration
|
||||
// support explicitly. Those will claim to have HW acceleration
|
||||
// but perform badly.
|
||||
// https://en.wikipedia.org/wiki/Intel_Graphics_Technology#Capabilities_(GPU_video_acceleration)
|
||||
// https://raw.githubusercontent.com/GameTechDev/gpudetect/master/IntelGfx.cfg
|
||||
switch (id.DeviceId & 0xFF00) {
|
||||
case 0x0400: // Haswell
|
||||
case 0x0A00: // Haswell
|
||||
case 0x0D00: // Haswell
|
||||
case 0x1600: // Broadwell
|
||||
case 0x2200: // Cherry Trail and Braswell
|
||||
// Blacklist these for HEVC to avoid hybrid decode
|
||||
result = (m_VideoFormat & VIDEO_FORMAT_MASK_H265) != 0;
|
||||
break;
|
||||
default:
|
||||
// Everything else is fine with whatever it says it supports
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (id.VendorId == 0x10DE) {
|
||||
// For NVIDIA, we wait to avoid those GPUs with Feature Set E
|
||||
// for HEVC decoding, since that's hybrid.
|
||||
// https://en.wikipedia.org/wiki/Nvidia_PureVideo
|
||||
// http://envytools.readthedocs.io/en/latest/hw/pciid.html (missing GM200)
|
||||
if ((id.DeviceId >= 0x1340 && id.DeviceId <= 0x137F) || // GM108
|
||||
(id.DeviceId >= 0x1380 && id.DeviceId <= 0x13BF) || // GM107
|
||||
(id.DeviceId >= 0x13C0 && id.DeviceId <= 0x13FF) || // GM204
|
||||
(id.DeviceId >= 0x1617 && id.DeviceId <= 0x161A) || // GM204
|
||||
(id.DeviceId == 0x1667) || // GM204
|
||||
(id.DeviceId >= 0x17C0 && id.DeviceId <= 0x17FF)) { // GM200
|
||||
// Avoid HEVC on Feature Set E GPUs
|
||||
result = (m_VideoFormat & VIDEO_FORMAT_MASK_H265) != 0;
|
||||
}
|
||||
else {
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
else if (id.VendorId == 0x1002) {
|
||||
// AMD doesn't seem to do hybrid acceleration?
|
||||
result = false;
|
||||
}
|
||||
else {
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Unrecognized vendor ID: %x",
|
||||
id.VendorId);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"GetDeviceCaps() failed: %x", hr);
|
||||
}
|
||||
|
||||
d3d9->Release();
|
||||
}
|
||||
else {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"GetDirect3D() failed: %x", hr);
|
||||
}
|
||||
|
||||
if (result) {
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"GPU blacklisted for format %x",
|
||||
m_VideoFormat);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool DXVA2Renderer::initialize(SDL_Window* window, int videoFormat, int width, int height)
|
||||
{
|
||||
m_VideoFormat = videoFormat;
|
||||
m_VideoWidth = width;
|
||||
m_VideoHeight = height;
|
||||
m_Width = width;
|
||||
m_Height = height;
|
||||
|
||||
// FFmpeg will be decoding on different threads than the main thread that we're
|
||||
// currently running on right now. We must set this hint so SDL will pass
|
||||
// D3DCREATE_MULTITHREADED to IDirect3D9::CreateDevice().
|
||||
SDL_SetHint(SDL_HINT_RENDER_DIRECT3D_THREADSAFE, "1");
|
||||
|
||||
// We require full-screen desktop mode to avoid having to enable V-sync
|
||||
// to synchronize frame delivery (which has a much higher latency penalty).
|
||||
m_SdlRenderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
|
||||
// We want VSYNC when running in full-screen. DWM will give us
|
||||
// tear-free video when running composited (windowed) without any
|
||||
// extra latency waiting for VSYNC.
|
||||
m_SdlRenderer = SDL_CreateRenderer(window, -1,
|
||||
SDL_RENDERER_ACCELERATED |
|
||||
((SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN) ?
|
||||
SDL_RENDERER_PRESENTVSYNC : 0));
|
||||
if (!m_SdlRenderer) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"SDL_CreateRenderer() failed: %s",
|
||||
@@ -453,31 +365,15 @@ bool DXVA2Renderer::initialize(SDL_Window* window, int videoFormat, int width, i
|
||||
|
||||
m_Device = SDL_RenderGetD3D9Device(m_SdlRenderer);
|
||||
|
||||
// Draw a black frame until the video stream starts rendering
|
||||
SDL_SetRenderDrawColor(m_SdlRenderer, 0, 0, 0, SDL_ALPHA_OPAQUE);
|
||||
SDL_RenderClear(m_SdlRenderer);
|
||||
SDL_RenderPresent(m_SdlRenderer);
|
||||
|
||||
RtlZeroMemory(&m_Desc, sizeof(m_Desc));
|
||||
|
||||
int alignment;
|
||||
|
||||
// HEVC using DXVA requires 128B alignment
|
||||
if (m_VideoFormat & VIDEO_FORMAT_MASK_H265) {
|
||||
alignment = 128;
|
||||
}
|
||||
else {
|
||||
alignment = 16;
|
||||
}
|
||||
|
||||
m_Desc.SampleWidth = FFALIGN(m_VideoWidth, alignment);
|
||||
m_Desc.SampleHeight = FFALIGN(m_VideoHeight, alignment);
|
||||
m_Desc.SampleFormat.VideoChromaSubsampling = DXVA2_VideoChromaSubsampling_Unknown;
|
||||
m_Desc.SampleFormat.NominalRange = DXVA2_NominalRange_Unknown;
|
||||
m_Desc.SampleFormat.VideoTransferMatrix = DXVA2_VideoTransferMatrix_Unknown;
|
||||
m_Desc.SampleFormat.VideoLighting = DXVA2_VideoLighting_Unknown;
|
||||
m_Desc.SampleFormat.VideoPrimaries = DXVA2_VideoPrimaries_Unknown;
|
||||
m_Desc.SampleFormat.VideoTransferFunction = DXVA2_VideoTransFunc_Unknown;
|
||||
m_Desc.SampleWidth = m_Width;
|
||||
m_Desc.SampleHeight = m_Height;
|
||||
m_Desc.SampleFormat.VideoChromaSubsampling = DXVA2_VideoChromaSubsampling_ProgressiveChroma;
|
||||
m_Desc.SampleFormat.NominalRange = DXVA2_NominalRange_0_255;
|
||||
m_Desc.SampleFormat.VideoTransferMatrix = DXVA2_VideoTransferMatrix_BT709;
|
||||
m_Desc.SampleFormat.VideoLighting = DXVA2_VideoLighting_dim;
|
||||
m_Desc.SampleFormat.VideoPrimaries = DXVA2_VideoPrimaries_BT709;
|
||||
m_Desc.SampleFormat.VideoTransferFunction = DXVA2_VideoTransFunc_709;
|
||||
m_Desc.SampleFormat.SampleFormat = DXVA2_SampleProgressiveFrame;
|
||||
m_Desc.Format = (D3DFORMAT)MAKEFOURCC('N','V','1','2');
|
||||
|
||||
@@ -497,126 +393,43 @@ void DXVA2Renderer::renderFrame(AVFrame* frame)
|
||||
IDirect3DSurface9* surface = reinterpret_cast<IDirect3DSurface9*>(frame->data[3]);
|
||||
HRESULT hr;
|
||||
|
||||
switch (frame->color_range) {
|
||||
case AVCOL_RANGE_JPEG:
|
||||
m_Desc.SampleFormat.NominalRange = DXVA2_NominalRange_0_255;
|
||||
break;
|
||||
case AVCOL_RANGE_MPEG:
|
||||
m_Desc.SampleFormat.NominalRange = DXVA2_NominalRange_16_235;
|
||||
hr = m_Device->TestCooperativeLevel();
|
||||
switch (hr) {
|
||||
case D3D_OK:
|
||||
break;
|
||||
case D3DERR_DEVICELOST:
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"D3D device lost!");
|
||||
return;
|
||||
case D3DERR_DEVICENOTRESET:
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"D3D device not reset!");
|
||||
return;
|
||||
default:
|
||||
m_Desc.SampleFormat.NominalRange = DXVA2_NominalRange_Unknown;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (frame->color_primaries) {
|
||||
case AVCOL_PRI_BT709:
|
||||
m_Desc.SampleFormat.VideoPrimaries = DXVA2_VideoPrimaries_BT709;
|
||||
break;
|
||||
case AVCOL_PRI_BT470M:
|
||||
m_Desc.SampleFormat.VideoPrimaries = DXVA2_VideoPrimaries_BT470_2_SysM;
|
||||
break;
|
||||
case AVCOL_PRI_BT470BG:
|
||||
m_Desc.SampleFormat.VideoPrimaries = DXVA2_VideoPrimaries_BT470_2_SysBG;
|
||||
break;
|
||||
case AVCOL_PRI_SMPTE170M:
|
||||
m_Desc.SampleFormat.VideoPrimaries = DXVA2_VideoPrimaries_SMPTE170M;
|
||||
break;
|
||||
case AVCOL_PRI_SMPTE240M:
|
||||
m_Desc.SampleFormat.VideoPrimaries = DXVA2_VideoPrimaries_SMPTE240M;
|
||||
break;
|
||||
default:
|
||||
m_Desc.SampleFormat.VideoPrimaries = DXVA2_VideoPrimaries_Unknown;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (frame->color_trc) {
|
||||
case AVCOL_TRC_SMPTE170M:
|
||||
case AVCOL_TRC_BT709:
|
||||
m_Desc.SampleFormat.VideoTransferFunction = DXVA2_VideoTransFunc_709;
|
||||
break;
|
||||
case AVCOL_TRC_LINEAR:
|
||||
m_Desc.SampleFormat.VideoTransferFunction = DXVA2_VideoTransFunc_10;
|
||||
break;
|
||||
case AVCOL_TRC_GAMMA22:
|
||||
m_Desc.SampleFormat.VideoTransferFunction = DXVA2_VideoTransFunc_22;
|
||||
break;
|
||||
case AVCOL_TRC_GAMMA28:
|
||||
m_Desc.SampleFormat.VideoTransferFunction = DXVA2_VideoTransFunc_28;
|
||||
break;
|
||||
case AVCOL_TRC_SMPTE240M:
|
||||
m_Desc.SampleFormat.VideoTransferFunction = DXVA2_VideoTransFunc_240M;
|
||||
break;
|
||||
case AVCOL_TRC_IEC61966_2_1:
|
||||
m_Desc.SampleFormat.VideoTransferFunction = DXVA2_VideoTransFunc_sRGB;
|
||||
break;
|
||||
default:
|
||||
m_Desc.SampleFormat.VideoTransferFunction = DXVA2_VideoTransFunc_Unknown;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (frame->colorspace) {
|
||||
case AVCOL_SPC_BT709:
|
||||
m_Desc.SampleFormat.VideoTransferMatrix = DXVA2_VideoTransferMatrix_BT709;
|
||||
break;
|
||||
case AVCOL_SPC_BT470BG:
|
||||
case AVCOL_SPC_SMPTE170M:
|
||||
m_Desc.SampleFormat.VideoTransferMatrix = DXVA2_VideoTransferMatrix_BT601;
|
||||
break;
|
||||
case AVCOL_SPC_SMPTE240M:
|
||||
m_Desc.SampleFormat.VideoTransferMatrix = DXVA2_VideoTransferMatrix_SMPTE240M;
|
||||
break;
|
||||
default:
|
||||
m_Desc.SampleFormat.VideoTransferMatrix = DXVA2_VideoTransferMatrix_Unknown;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (frame->chroma_location) {
|
||||
case AVCHROMA_LOC_LEFT:
|
||||
m_Desc.SampleFormat.VideoChromaSubsampling = DXVA2_VideoChromaSubsampling_Horizontally_Cosited |
|
||||
DXVA2_VideoChromaSubsampling_Vertically_AlignedChromaPlanes;
|
||||
break;
|
||||
case AVCHROMA_LOC_CENTER:
|
||||
m_Desc.SampleFormat.VideoChromaSubsampling = DXVA2_VideoChromaSubsampling_Vertically_AlignedChromaPlanes;
|
||||
break;
|
||||
case AVCHROMA_LOC_TOPLEFT:
|
||||
m_Desc.SampleFormat.VideoChromaSubsampling = DXVA2_VideoChromaSubsampling_Horizontally_Cosited |
|
||||
DXVA2_VideoChromaSubsampling_Vertically_Cosited;
|
||||
break;
|
||||
default:
|
||||
m_Desc.SampleFormat.VideoChromaSubsampling = DXVA2_VideoChromaSubsampling_Unknown;
|
||||
break;
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Unknown D3D error: %x",
|
||||
hr);
|
||||
return;
|
||||
}
|
||||
|
||||
DXVA2_VideoSample sample = {};
|
||||
sample.Start = m_FrameIndex;
|
||||
sample.End = m_FrameIndex + 1;
|
||||
sample.SrcSurface = surface;
|
||||
sample.SrcRect.right = m_VideoWidth;
|
||||
sample.SrcRect.bottom = m_VideoHeight;
|
||||
sample.SrcRect.right = m_Desc.SampleWidth;
|
||||
sample.SrcRect.bottom = m_Desc.SampleHeight;
|
||||
sample.DstRect = sample.SrcRect;
|
||||
sample.SampleFormat = m_Desc.SampleFormat;
|
||||
sample.PlanarAlpha = DXVA2_Fixed32OpaqueAlpha();
|
||||
|
||||
// Center in frame and preserve aspect ratio
|
||||
SDL_Rect src, dst;
|
||||
src.x = src.y = 0;
|
||||
src.w = m_VideoWidth;
|
||||
src.h = m_VideoHeight;
|
||||
dst.x = dst.y = 0;
|
||||
dst.w = m_DisplayWidth;
|
||||
dst.h = m_DisplayHeight;
|
||||
|
||||
StreamUtils::scaleSourceToDestinationSurface(&src, &dst);
|
||||
|
||||
sample.DstRect.left = dst.x;
|
||||
sample.DstRect.right = dst.x + dst.w;
|
||||
sample.DstRect.top = dst.y;
|
||||
sample.DstRect.bottom = dst.y + dst.h;
|
||||
|
||||
DXVA2_VideoProcessBltParams bltParams = {};
|
||||
|
||||
bltParams.TargetFrame = m_FrameIndex++;
|
||||
bltParams.TargetRect = sample.DstRect;
|
||||
bltParams.TargetRect.right = m_Desc.SampleWidth;
|
||||
bltParams.TargetRect.bottom = m_Desc.SampleHeight;
|
||||
bltParams.BackgroundColor.Y = 0x1000;
|
||||
bltParams.BackgroundColor.Cb = 0x8000;
|
||||
bltParams.BackgroundColor.Cr = 0x8000;
|
||||
bltParams.BackgroundColor.Alpha = 0xFFFF;
|
||||
|
||||
bltParams.DestFormat.SampleFormat = DXVA2_SampleProgressiveFrame;
|
||||
@@ -628,33 +441,12 @@ void DXVA2Renderer::renderFrame(AVFrame* frame)
|
||||
|
||||
bltParams.Alpha = DXVA2_Fixed32OpaqueAlpha();
|
||||
|
||||
if (SDL_RenderClear(m_SdlRenderer) != 0) {
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"SDL_RenderClear() failed: %s",
|
||||
SDL_GetError());
|
||||
av_frame_free(&frame);
|
||||
|
||||
// We're going to cheat a little bit here. It seems SDL's
|
||||
// renderer may flake out in scenarios like moving the window
|
||||
// between monitors, so generate a synthetic reset event for
|
||||
// the main loop to consume.
|
||||
SDL_Event event;
|
||||
event.type = SDL_RENDER_TARGETS_RESET;
|
||||
SDL_PushEvent(&event);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
hr = m_Processor->VideoProcessBlt(m_RenderTarget, &bltParams, &sample, 1, nullptr);
|
||||
av_frame_free(&frame);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"VideoProcessBlt() failed: %x",
|
||||
hr);
|
||||
}
|
||||
|
||||
// We must try to present to trigger SDL's logic to recover the render target,
|
||||
// even if VideoProcessBlt() fails.
|
||||
SDL_RenderPresent(m_SdlRenderer);
|
||||
m_Device->Present(nullptr, nullptr, nullptr, nullptr);
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@ public:
|
||||
private:
|
||||
bool initializeDecoder();
|
||||
bool initializeRenderer();
|
||||
bool isDecoderBlacklisted();
|
||||
|
||||
static
|
||||
AVBufferRef* ffPoolAlloc(void* opaque, int size);
|
||||
@@ -35,12 +34,13 @@ private:
|
||||
static
|
||||
int ffGetBuffer2(AVCodecContext* context, AVFrame* frame, int flags);
|
||||
|
||||
int m_VideoFormat;
|
||||
int m_VideoWidth;
|
||||
int m_VideoHeight;
|
||||
static
|
||||
enum AVPixelFormat ffGetFormat(AVCodecContext*,
|
||||
const enum AVPixelFormat* pixFmts);
|
||||
|
||||
int m_DisplayWidth;
|
||||
int m_DisplayHeight;
|
||||
int m_VideoFormat;
|
||||
int m_Width;
|
||||
int m_Height;
|
||||
|
||||
SDL_Renderer* m_SdlRenderer;
|
||||
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
#include "renderer.h"
|
||||
|
||||
#include <Limelight.h>
|
||||
|
||||
SdlRenderer::SdlRenderer()
|
||||
: m_Renderer(nullptr),
|
||||
m_Texture(nullptr)
|
||||
@@ -23,10 +21,6 @@ SdlRenderer::~SdlRenderer()
|
||||
bool SdlRenderer::prepareDecoderContext(AVCodecContext*)
|
||||
{
|
||||
/* Nothing to do */
|
||||
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Using SDL software renderer");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -47,11 +41,6 @@ bool SdlRenderer::initialize(SDL_Window* window,
|
||||
// logical rendering surface size is equal to the stream size
|
||||
SDL_RenderSetLogicalSize(m_Renderer, width, height);
|
||||
|
||||
// Draw a black frame until the video stream starts rendering
|
||||
SDL_SetRenderDrawColor(m_Renderer, 0, 0, 0, SDL_ALPHA_OPAQUE);
|
||||
SDL_RenderClear(m_Renderer);
|
||||
SDL_RenderPresent(m_Renderer);
|
||||
|
||||
m_Texture = SDL_CreateTexture(m_Renderer,
|
||||
SDL_PIXELFORMAT_YV12,
|
||||
SDL_TEXTUREACCESS_STREAMING,
|
||||
@@ -76,10 +65,6 @@ void SdlRenderer::renderFrame(AVFrame* frame)
|
||||
frame->linesize[1],
|
||||
frame->data[2],
|
||||
frame->linesize[2]);
|
||||
|
||||
// Done with the frame now
|
||||
av_frame_free(&frame);
|
||||
|
||||
SDL_RenderClear(m_Renderer);
|
||||
SDL_RenderCopy(m_Renderer, m_Texture, nullptr, nullptr);
|
||||
SDL_RenderPresent(m_Renderer);
|
||||
|
||||
@@ -1,133 +0,0 @@
|
||||
#include "vaapi.h"
|
||||
#include <streaming/streamutils.h>
|
||||
|
||||
#include <dlfcn.h>
|
||||
|
||||
#include <SDL_syswm.h>
|
||||
|
||||
VAAPIRenderer::VAAPIRenderer()
|
||||
: m_HwContext(nullptr),
|
||||
m_X11VaLibHandle(nullptr),
|
||||
m_vaPutSurface(nullptr)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
VAAPIRenderer::~VAAPIRenderer()
|
||||
{
|
||||
if (m_HwContext != nullptr) {
|
||||
av_buffer_unref(&m_HwContext);
|
||||
}
|
||||
|
||||
if (m_X11VaLibHandle != nullptr) {
|
||||
dlclose(m_X11VaLibHandle);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
VAAPIRenderer::initialize(SDL_Window* window, int, int width, int height)
|
||||
{
|
||||
int err;
|
||||
SDL_SysWMinfo info;
|
||||
|
||||
m_VideoWidth = width;
|
||||
m_VideoHeight = height;
|
||||
|
||||
SDL_GetWindowSize(window, &m_DisplayWidth, &m_DisplayHeight);
|
||||
|
||||
SDL_VERSION(&info.version);
|
||||
|
||||
if (!SDL_GetWindowWMInfo(window, &info)) {
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"SDL_GetWindowWMInfo() failed: %s",
|
||||
SDL_GetError());
|
||||
return false;
|
||||
}
|
||||
|
||||
SDL_assert(info.subsystem == SDL_SYSWM_X11);
|
||||
|
||||
if (info.subsystem == SDL_SYSWM_X11) {
|
||||
m_XWindow = info.info.x11.window;
|
||||
|
||||
m_X11VaLibHandle = dlopen("libva-x11.so", RTLD_LAZY);
|
||||
if (!m_X11VaLibHandle) {
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"dlopen(libva.so) failed: %s",
|
||||
dlerror());
|
||||
return false;
|
||||
}
|
||||
|
||||
m_vaPutSurface = (vaPutSurface_t)dlsym(m_X11VaLibHandle, "vaPutSurface");
|
||||
}
|
||||
else if (info.subsystem == SDL_SYSWM_WAYLAND) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"VAAPI backend does not currently support Wayland");
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Unsupported VAAPI rendering subsystem: %d",
|
||||
info.subsystem);
|
||||
return false;
|
||||
}
|
||||
|
||||
err = av_hwdevice_ctx_create(&m_HwContext,
|
||||
AV_HWDEVICE_TYPE_VAAPI,
|
||||
nullptr, nullptr, 0);
|
||||
if (err < 0) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Failed to create VAAPI context: %d",
|
||||
err);
|
||||
return false;
|
||||
}
|
||||
|
||||
// This quirk is set for the VDPAU wrapper which doesn't work with our VAAPI renderer
|
||||
if (((AVVAAPIDeviceContext*)((AVHWDeviceContext*)(m_HwContext->data))->hwctx)->driver_quirks & AV_VAAPI_DRIVER_QUIRK_SURFACE_ATTRIBUTES) {
|
||||
// Fail and let our VDPAU renderer pick this up
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Avoiding VDPAU wrapper for VAAPI decoding");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
VAAPIRenderer::prepareDecoderContext(AVCodecContext* context)
|
||||
{
|
||||
context->hw_device_ctx = av_buffer_ref(m_HwContext);
|
||||
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Using VAAPI accelerated renderer");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
VAAPIRenderer::renderFrame(AVFrame* frame)
|
||||
{
|
||||
VASurfaceID surface = (VASurfaceID)(uintptr_t)frame->data[3];
|
||||
AVHWDeviceContext* deviceContext = (AVHWDeviceContext*)m_HwContext->data;
|
||||
AVVAAPIDeviceContext* vaDeviceContext = (AVVAAPIDeviceContext*)deviceContext->hwctx;
|
||||
|
||||
SDL_Rect src, dst;
|
||||
src.x = src.y = 0;
|
||||
src.w = m_VideoWidth;
|
||||
src.h = m_VideoHeight;
|
||||
dst.x = dst.y = 0;
|
||||
dst.w = m_DisplayWidth;
|
||||
dst.h = m_DisplayHeight;
|
||||
|
||||
StreamUtils::scaleSourceToDestinationSurface(&src, &dst);
|
||||
|
||||
m_vaPutSurface(vaDeviceContext->display,
|
||||
surface,
|
||||
m_XWindow,
|
||||
0, 0,
|
||||
m_VideoWidth, m_VideoHeight,
|
||||
dst.x, dst.y,
|
||||
dst.w, dst.h,
|
||||
NULL, 0, 0);
|
||||
|
||||
av_frame_free(&frame);
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "renderer.h"
|
||||
|
||||
extern "C" {
|
||||
#include <va/va.h>
|
||||
#include <va/va_x11.h>
|
||||
#include <libavutil/hwcontext_vaapi.h>
|
||||
}
|
||||
|
||||
class VAAPIRenderer : public IFFmpegRenderer
|
||||
{
|
||||
typedef VAStatus (*vaPutSurface_t)(
|
||||
VADisplay dpy,
|
||||
VASurfaceID surface,
|
||||
Drawable draw, /* X Drawable */
|
||||
short srcx,
|
||||
short srcy,
|
||||
unsigned short srcw,
|
||||
unsigned short srch,
|
||||
short destx,
|
||||
short desty,
|
||||
unsigned short destw,
|
||||
unsigned short desth,
|
||||
VARectangle *cliprects,
|
||||
unsigned int number_cliprects,
|
||||
unsigned int flags
|
||||
);
|
||||
|
||||
public:
|
||||
VAAPIRenderer();
|
||||
virtual ~VAAPIRenderer();
|
||||
virtual bool initialize(SDL_Window* window,
|
||||
int videoFormat,
|
||||
int width,
|
||||
int height);
|
||||
virtual bool prepareDecoderContext(AVCodecContext* context);
|
||||
virtual void renderFrame(AVFrame* frame);
|
||||
|
||||
private:
|
||||
Window m_XWindow;
|
||||
AVBufferRef* m_HwContext;
|
||||
void* m_X11VaLibHandle;
|
||||
vaPutSurface_t m_vaPutSurface;
|
||||
int m_VideoWidth;
|
||||
int m_VideoHeight;
|
||||
int m_DisplayWidth;
|
||||
int m_DisplayHeight;
|
||||
};
|
||||
@@ -1,332 +0,0 @@
|
||||
#include "vdpau.h"
|
||||
#include <streaming/streamutils.h>
|
||||
|
||||
#include <SDL_syswm.h>
|
||||
|
||||
#define BAIL_ON_FAIL(status, something) if ((status) != VDP_STATUS_OK) { \
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, \
|
||||
#something " failed: %d", (status)); \
|
||||
return false; \
|
||||
}
|
||||
|
||||
#define GET_PROC_ADDRESS(id, func) status = vdpauCtx->get_proc_address(m_Device, id, (void**)func); \
|
||||
BAIL_ON_FAIL(status, id)
|
||||
|
||||
const VdpRGBAFormat VDPAURenderer::k_OutputFormats[] = {
|
||||
VDP_RGBA_FORMAT_B8G8R8A8,
|
||||
VDP_RGBA_FORMAT_R8G8B8A8
|
||||
};
|
||||
|
||||
VDPAURenderer::VDPAURenderer()
|
||||
: m_HwContext(nullptr),
|
||||
m_PresentationQueueTarget(0),
|
||||
m_PresentationQueue(0),
|
||||
m_VideoMixer(0),
|
||||
m_NextSurfaceIndex(0)
|
||||
{
|
||||
SDL_zero(m_OutputSurface);
|
||||
}
|
||||
|
||||
VDPAURenderer::~VDPAURenderer()
|
||||
{
|
||||
if (m_PresentationQueue != 0) {
|
||||
m_VdpPresentationQueueDestroy(m_PresentationQueue);
|
||||
}
|
||||
|
||||
if (m_VideoMixer != 0) {
|
||||
m_VdpVideoMixerDestroy(m_VideoMixer);
|
||||
}
|
||||
|
||||
if (m_PresentationQueueTarget != 0) {
|
||||
m_VdpPresentationQueueTargetDestroy(m_PresentationQueueTarget);
|
||||
}
|
||||
|
||||
for (int i = 0; i < OUTPUT_SURFACE_COUNT; i++) {
|
||||
if (m_OutputSurface[i] != 0) {
|
||||
m_VdpOutputSurfaceDestroy(m_OutputSurface[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// This must be done last as it frees VDPAU context required to call
|
||||
// the functions above.
|
||||
if (m_HwContext != nullptr) {
|
||||
av_buffer_unref(&m_HwContext);
|
||||
}
|
||||
}
|
||||
|
||||
bool VDPAURenderer::initialize(SDL_Window* window, int, int width, int height)
|
||||
{
|
||||
int err;
|
||||
VdpStatus status;
|
||||
SDL_SysWMinfo info;
|
||||
|
||||
m_VideoWidth = width;
|
||||
m_VideoHeight = height;
|
||||
|
||||
err = av_hwdevice_ctx_create(&m_HwContext,
|
||||
AV_HWDEVICE_TYPE_VDPAU,
|
||||
nullptr, nullptr, 0);
|
||||
if (err < 0) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Failed to create VDPAU context: %d",
|
||||
err);
|
||||
return false;
|
||||
}
|
||||
|
||||
AVHWDeviceContext* devCtx = (AVHWDeviceContext*)m_HwContext->data;
|
||||
AVVDPAUDeviceContext* vdpauCtx = (AVVDPAUDeviceContext*)devCtx->hwctx;
|
||||
m_Device = vdpauCtx->device;
|
||||
|
||||
GET_PROC_ADDRESS(VDP_FUNC_ID_GET_ERROR_STRING, &m_VdpGetErrorString);
|
||||
GET_PROC_ADDRESS(VDP_FUNC_ID_PRESENTATION_QUEUE_TARGET_DESTROY, &m_VdpPresentationQueueTargetDestroy);
|
||||
GET_PROC_ADDRESS(VDP_FUNC_ID_VIDEO_MIXER_CREATE, &m_VdpVideoMixerCreate);
|
||||
GET_PROC_ADDRESS(VDP_FUNC_ID_VIDEO_MIXER_DESTROY, &m_VdpVideoMixerDestroy);
|
||||
GET_PROC_ADDRESS(VDP_FUNC_ID_VIDEO_MIXER_RENDER, &m_VdpVideoMixerRender);
|
||||
GET_PROC_ADDRESS(VDP_FUNC_ID_PRESENTATION_QUEUE_CREATE, &m_VdpPresentationQueueCreate);
|
||||
GET_PROC_ADDRESS(VDP_FUNC_ID_PRESENTATION_QUEUE_DESTROY, &m_VdpPresentationQueueDestroy);
|
||||
GET_PROC_ADDRESS(VDP_FUNC_ID_PRESENTATION_QUEUE_DISPLAY, &m_VdpPresentationQueueDisplay);
|
||||
GET_PROC_ADDRESS(VDP_FUNC_ID_PRESENTATION_QUEUE_SET_BACKGROUND_COLOR, &m_VdpPresentationQueueSetBackgroundColor);
|
||||
GET_PROC_ADDRESS(VDP_FUNC_ID_PRESENTATION_QUEUE_BLOCK_UNTIL_SURFACE_IDLE, &m_VdpPresentationQueueBlockUntilSurfaceIdle);
|
||||
GET_PROC_ADDRESS(VDP_FUNC_ID_OUTPUT_SURFACE_CREATE, &m_VdpOutputSurfaceCreate);
|
||||
GET_PROC_ADDRESS(VDP_FUNC_ID_OUTPUT_SURFACE_DESTROY, &m_VdpOutputSurfaceDestroy);
|
||||
GET_PROC_ADDRESS(VDP_FUNC_ID_OUTPUT_SURFACE_QUERY_CAPABILITIES, &m_VdpOutputSurfaceQueryCapabilities);
|
||||
GET_PROC_ADDRESS(VDP_FUNC_ID_VIDEO_SURFACE_GET_PARAMETERS, &m_VdpVideoSurfaceGetParameters);
|
||||
|
||||
SDL_GetWindowSize(window, (int*)&m_DisplayWidth, (int*)&m_DisplayHeight);
|
||||
|
||||
SDL_VERSION(&info.version);
|
||||
|
||||
if (!SDL_GetWindowWMInfo(window, &info)) {
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"SDL_GetWindowWMInfo() failed: %s",
|
||||
SDL_GetError());
|
||||
return false;
|
||||
}
|
||||
|
||||
SDL_assert(info.subsystem == SDL_SYSWM_X11);
|
||||
|
||||
if (info.subsystem == SDL_SYSWM_X11) {
|
||||
GET_PROC_ADDRESS(VDP_FUNC_ID_PRESENTATION_QUEUE_TARGET_CREATE_X11,
|
||||
&m_VdpPresentationQueueTargetCreateX11);
|
||||
status = m_VdpPresentationQueueTargetCreateX11(m_Device,
|
||||
info.info.x11.window,
|
||||
&m_PresentationQueueTarget);
|
||||
if (status != VDP_STATUS_OK) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"VdpPresentationQueueTargetCreateX11() failed: %s",
|
||||
m_VdpGetErrorString(status));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (info.subsystem == SDL_SYSWM_WAYLAND) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"VDPAU backend does not currently support Wayland");
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Unsupported VDPAU rendering subsystem: %d",
|
||||
info.subsystem);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Try our available output formats to find something the GPU supports
|
||||
bool foundFormat = false;
|
||||
for (int i = 0; i < OUTPUT_SURFACE_FORMAT_COUNT; i++) {
|
||||
VdpBool supported;
|
||||
uint32_t maxWidth, maxHeight;
|
||||
status = m_VdpOutputSurfaceQueryCapabilities(m_Device, k_OutputFormats[i],
|
||||
&supported, &maxWidth, &maxHeight);
|
||||
if (status != VDP_STATUS_OK) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"VdpOutputSurfaceQueryCapabilities() failed: %s",
|
||||
m_VdpGetErrorString(status));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (supported) {
|
||||
if (m_DisplayWidth <= maxWidth && m_DisplayHeight <= maxHeight) {
|
||||
m_OutputSurfaceFormat = k_OutputFormats[i];
|
||||
foundFormat = true;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Display size not within capabilities %dx%d vs %dx%d",
|
||||
m_DisplayWidth, m_DisplayWidth,
|
||||
maxWidth, maxHeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!foundFormat) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"No compatible output surface format found!");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create the output surfaces
|
||||
for (int i = 0; i < OUTPUT_SURFACE_COUNT; i++) {
|
||||
// It seems there's some lazy freeing going on or something in VDPAU
|
||||
// because we can get VDP_STATUS_RESOURCES, then wait a bit and it'll
|
||||
// complete without a problem.
|
||||
int tries = 1;
|
||||
do {
|
||||
status = m_VdpOutputSurfaceCreate(m_Device, m_OutputSurfaceFormat,
|
||||
m_DisplayWidth, m_DisplayHeight,
|
||||
&m_OutputSurface[i]);
|
||||
if (status != VDP_STATUS_OK) {
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"VdpOutputSurfaceCreate() try #%d: %s",
|
||||
tries,
|
||||
m_VdpGetErrorString(status));
|
||||
SDL_Delay(250);
|
||||
}
|
||||
} while (status == VDP_STATUS_RESOURCES && ++tries <= 10);
|
||||
|
||||
if (status != VDP_STATUS_OK) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"VdpOutputSurfaceCreate() failed: %s",
|
||||
m_VdpGetErrorString(status));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
status = m_VdpPresentationQueueCreate(m_Device, m_PresentationQueueTarget,
|
||||
&m_PresentationQueue);
|
||||
if (status != VDP_STATUS_OK) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"VdpPresentationQueueCreate() failed: %s",
|
||||
m_VdpGetErrorString(status));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set the background to opaque black
|
||||
VdpColor color = {0.0, 0.0, 0.0, 1.0};
|
||||
m_VdpPresentationQueueSetBackgroundColor(m_PresentationQueue, &color);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VDPAURenderer::prepareDecoderContext(AVCodecContext* context)
|
||||
{
|
||||
context->hw_device_ctx = av_buffer_ref(m_HwContext);
|
||||
|
||||
// Allow HEVC usage on VDPAU. This was disabled by FFmpeg due to
|
||||
// GL interop issues, but we use VDPAU for rendering so it's no issue.
|
||||
// https://github.com/FFmpeg/FFmpeg/commit/64ecb78b7179cab2dbdf835463104679dbb7c895
|
||||
context->hwaccel_flags |= AV_HWACCEL_FLAG_ALLOW_PROFILE_MISMATCH;
|
||||
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Using VDPAU accelerated renderer");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void VDPAURenderer::renderFrame(AVFrame* frame)
|
||||
{
|
||||
VdpStatus status;
|
||||
VdpVideoSurface videoSurface = (VdpVideoSurface)(uintptr_t)frame->data[3];
|
||||
|
||||
// This is safe without locking because this is always called on the main thread
|
||||
VdpOutputSurface chosenSurface = m_OutputSurface[m_NextSurfaceIndex];
|
||||
m_NextSurfaceIndex = (m_NextSurfaceIndex + 1) % OUTPUT_SURFACE_COUNT;
|
||||
|
||||
// We need to create the mixer on the fly, because we don't know the dimensions
|
||||
// of our video surfaces in advance of decoding
|
||||
if (m_VideoMixer == 0) {
|
||||
VdpChromaType chroma;
|
||||
uint32_t videoSurfaceWidth, videoSurfaceHeight;
|
||||
status = m_VdpVideoSurfaceGetParameters(videoSurface, &chroma, &videoSurfaceWidth, &videoSurfaceHeight);
|
||||
if (status != VDP_STATUS_OK) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"VdpVideoSurfaceGetParameters() failed: %s",
|
||||
m_VdpGetErrorString(status));
|
||||
av_frame_free(&frame);
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"VDPAU surface size: %dx%d",
|
||||
videoSurfaceWidth, videoSurfaceHeight);
|
||||
|
||||
#define PARAM_COUNT 2
|
||||
const VdpVideoMixerParameter params[PARAM_COUNT] = {
|
||||
VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH,
|
||||
VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT,
|
||||
};
|
||||
const void* const paramValues[PARAM_COUNT] = {
|
||||
&videoSurfaceWidth,
|
||||
&videoSurfaceHeight,
|
||||
};
|
||||
|
||||
status = m_VdpVideoMixerCreate(m_Device, 0, nullptr,
|
||||
PARAM_COUNT, params, paramValues,
|
||||
&m_VideoMixer);
|
||||
if (status != VDP_STATUS_OK) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"VdpVideoMixerCreate() failed: %s",
|
||||
m_VdpGetErrorString(status));
|
||||
av_frame_free(&frame);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Wait for this frame to be off the screen
|
||||
VdpTime pts;
|
||||
m_VdpPresentationQueueBlockUntilSurfaceIdle(m_PresentationQueue, chosenSurface, &pts);
|
||||
|
||||
VdpRect sourceRect, outputRect;
|
||||
|
||||
SDL_Rect src, dst;
|
||||
src.x = src.y = 0;
|
||||
src.w = m_VideoWidth;
|
||||
src.h = m_VideoHeight;
|
||||
dst.x = dst.y = 0;
|
||||
dst.w = m_DisplayWidth;
|
||||
dst.h = m_DisplayHeight;
|
||||
|
||||
StreamUtils::scaleSourceToDestinationSurface(&src, &dst);
|
||||
|
||||
outputRect.x0 = dst.x;
|
||||
outputRect.x1 = dst.x + dst.w;
|
||||
outputRect.y0 = dst.y;
|
||||
outputRect.y1 = dst.y + dst.h;
|
||||
|
||||
sourceRect.x0 = sourceRect.y0 = 0;
|
||||
sourceRect.x1 = m_VideoWidth;
|
||||
sourceRect.y1 = m_VideoHeight;
|
||||
|
||||
// Render the next frame into the output surface
|
||||
status = m_VdpVideoMixerRender(m_VideoMixer,
|
||||
VDP_INVALID_HANDLE, nullptr,
|
||||
VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME,
|
||||
0, nullptr,
|
||||
videoSurface,
|
||||
0, nullptr,
|
||||
&sourceRect,
|
||||
chosenSurface,
|
||||
&outputRect,
|
||||
nullptr,
|
||||
0,
|
||||
nullptr);
|
||||
|
||||
// The decoder can have this surface back now
|
||||
av_frame_free(&frame);
|
||||
|
||||
if (status != VDP_STATUS_OK) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"VdpVideoMixerRender() failed: %s",
|
||||
m_VdpGetErrorString(status));
|
||||
return;
|
||||
}
|
||||
|
||||
// Queue the frame for display immediately
|
||||
status = m_VdpPresentationQueueDisplay(m_PresentationQueue, chosenSurface, 0, 0, 0);
|
||||
if (status != VDP_STATUS_OK) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"VdpPresentationQueueDisplay() failed: %s",
|
||||
m_VdpGetErrorString(status));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "renderer.h"
|
||||
|
||||
extern "C" {
|
||||
#include <vdpau/vdpau.h>
|
||||
#include <vdpau/vdpau_x11.h>
|
||||
#include <libavutil/hwcontext_vdpau.h>
|
||||
}
|
||||
|
||||
class VDPAURenderer : public IFFmpegRenderer
|
||||
{
|
||||
public:
|
||||
VDPAURenderer();
|
||||
virtual ~VDPAURenderer();
|
||||
virtual bool initialize(SDL_Window* window,
|
||||
int videoFormat,
|
||||
int width,
|
||||
int height);
|
||||
virtual bool prepareDecoderContext(AVCodecContext* context);
|
||||
virtual void renderFrame(AVFrame* frame);
|
||||
|
||||
private:
|
||||
uint32_t m_VideoWidth, m_VideoHeight;
|
||||
uint32_t m_DisplayWidth, m_DisplayHeight;
|
||||
AVBufferRef* m_HwContext;
|
||||
VdpPresentationQueueTarget m_PresentationQueueTarget;
|
||||
VdpPresentationQueue m_PresentationQueue;
|
||||
VdpVideoMixer m_VideoMixer;
|
||||
VdpRGBAFormat m_OutputSurfaceFormat;
|
||||
VdpDevice m_Device;
|
||||
|
||||
#define OUTPUT_SURFACE_COUNT 3
|
||||
VdpOutputSurface m_OutputSurface[OUTPUT_SURFACE_COUNT];
|
||||
int m_NextSurfaceIndex;
|
||||
|
||||
#define OUTPUT_SURFACE_FORMAT_COUNT 2
|
||||
static const VdpRGBAFormat k_OutputFormats[OUTPUT_SURFACE_FORMAT_COUNT];
|
||||
|
||||
VdpGetErrorString* m_VdpGetErrorString;
|
||||
VdpPresentationQueueTargetDestroy* m_VdpPresentationQueueTargetDestroy;
|
||||
VdpVideoMixerCreate* m_VdpVideoMixerCreate;
|
||||
VdpVideoMixerDestroy* m_VdpVideoMixerDestroy;
|
||||
VdpVideoMixerRender* m_VdpVideoMixerRender;
|
||||
VdpPresentationQueueCreate* m_VdpPresentationQueueCreate;
|
||||
VdpPresentationQueueDestroy* m_VdpPresentationQueueDestroy;
|
||||
VdpPresentationQueueDisplay* m_VdpPresentationQueueDisplay;
|
||||
VdpPresentationQueueSetBackgroundColor* m_VdpPresentationQueueSetBackgroundColor;
|
||||
VdpPresentationQueueBlockUntilSurfaceIdle* m_VdpPresentationQueueBlockUntilSurfaceIdle;
|
||||
VdpOutputSurfaceCreate* m_VdpOutputSurfaceCreate;
|
||||
VdpOutputSurfaceDestroy* m_VdpOutputSurfaceDestroy;
|
||||
VdpOutputSurfaceQueryCapabilities* m_VdpOutputSurfaceQueryCapabilities;
|
||||
VdpVideoSurfaceGetParameters* m_VdpVideoSurfaceGetParameters;
|
||||
|
||||
// X11 stuff
|
||||
VdpPresentationQueueTargetCreateX11* m_VdpPresentationQueueTargetCreateX11;
|
||||
};
|
||||
|
||||
|
||||
@@ -7,14 +7,9 @@
|
||||
#include <SDL_syswm.h>
|
||||
#include <Limelight.h>
|
||||
|
||||
#include <QQueue>
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import <VideoToolbox/VideoToolbox.h>
|
||||
#import <AVFoundation/AVFoundation.h>
|
||||
#import <CoreVideo/CoreVideo.h>
|
||||
|
||||
#define FRAME_HISTORY_ENTRIES 8
|
||||
|
||||
class VTRenderer : public IFFmpegRenderer
|
||||
{
|
||||
@@ -23,10 +18,9 @@ public:
|
||||
: m_HwContext(nullptr),
|
||||
m_DisplayLayer(nullptr),
|
||||
m_FormatDesc(nullptr),
|
||||
m_View(nullptr),
|
||||
m_DisplayLink(nullptr),
|
||||
m_FrameQueueLock(0)
|
||||
m_View(nullptr)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
virtual ~VTRenderer()
|
||||
@@ -38,132 +32,8 @@ public:
|
||||
if (m_FormatDesc != nullptr) {
|
||||
CFRelease(m_FormatDesc);
|
||||
}
|
||||
|
||||
if (m_DisplayLink != nullptr) {
|
||||
CVDisplayLinkStop(m_DisplayLink);
|
||||
CVDisplayLinkRelease(m_DisplayLink);
|
||||
}
|
||||
|
||||
while (!m_FrameQueue.isEmpty()) {
|
||||
AVFrame* frame = m_FrameQueue.dequeue();
|
||||
av_frame_free(&frame);
|
||||
}
|
||||
|
||||
if (m_View != nullptr) {
|
||||
[m_View removeFromSuperview];
|
||||
}
|
||||
}
|
||||
|
||||
void drawFrame(uint64_t vsyncTime)
|
||||
{
|
||||
OSStatus status;
|
||||
|
||||
SDL_AtomicLock(&m_FrameQueueLock);
|
||||
|
||||
int frameDropTarget;
|
||||
|
||||
// If the queue length history entries are large, be strict
|
||||
// about dropping excess frames.
|
||||
frameDropTarget = 1;
|
||||
for (int i = 0; i < m_FrameQueueHistory.count(); i++) {
|
||||
if (m_FrameQueueHistory[i] <= 1) {
|
||||
// Be lenient as long as the queue length
|
||||
// resolves before the end of frame history
|
||||
frameDropTarget = 3;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_FrameQueueHistory.count() == FRAME_HISTORY_ENTRIES) {
|
||||
m_FrameQueueHistory.dequeue();
|
||||
}
|
||||
|
||||
m_FrameQueueHistory.enqueue(m_FrameQueue.count());
|
||||
|
||||
// Catch up if we're several frames ahead
|
||||
while (m_FrameQueue.count() > frameDropTarget) {
|
||||
AVFrame* frame = m_FrameQueue.dequeue();
|
||||
av_frame_free(&frame);
|
||||
}
|
||||
|
||||
if (m_FrameQueue.isEmpty()) {
|
||||
SDL_AtomicUnlock(&m_FrameQueueLock);
|
||||
return;
|
||||
}
|
||||
|
||||
// Grab the first frame
|
||||
AVFrame* frame = m_FrameQueue.dequeue();
|
||||
SDL_AtomicUnlock(&m_FrameQueueLock);
|
||||
|
||||
CVPixelBufferRef pixBuf = reinterpret_cast<CVPixelBufferRef>(frame->data[3]);
|
||||
|
||||
// If the format has changed or doesn't exist yet, construct it with the
|
||||
// pixel buffer data
|
||||
if (!m_FormatDesc || !CMVideoFormatDescriptionMatchesImageBuffer(m_FormatDesc, pixBuf)) {
|
||||
if (m_FormatDesc != nullptr) {
|
||||
CFRelease(m_FormatDesc);
|
||||
}
|
||||
status = CMVideoFormatDescriptionCreateForImageBuffer(kCFAllocatorDefault,
|
||||
pixBuf, &m_FormatDesc);
|
||||
if (status != noErr) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"CMVideoFormatDescriptionCreateForImageBuffer() failed: %d",
|
||||
status);
|
||||
av_frame_free(&frame);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Queue this sample for the next v-sync
|
||||
CMSampleTimingInfo timingInfo = {
|
||||
.duration = kCMTimeInvalid,
|
||||
.decodeTimeStamp = kCMTimeInvalid,
|
||||
.presentationTimeStamp = CMTimeMake(vsyncTime, 1000 * 1000 * 1000)
|
||||
};
|
||||
|
||||
CMSampleBufferRef sampleBuffer;
|
||||
status = CMSampleBufferCreateReadyWithImageBuffer(kCFAllocatorDefault,
|
||||
pixBuf,
|
||||
m_FormatDesc,
|
||||
&timingInfo,
|
||||
&sampleBuffer);
|
||||
if (status != noErr) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"CMSampleBufferCreateReadyWithImageBuffer() failed: %d",
|
||||
status);
|
||||
av_frame_free(&frame);
|
||||
return;
|
||||
}
|
||||
|
||||
[m_DisplayLayer enqueueSampleBuffer:sampleBuffer];
|
||||
|
||||
CFRelease(sampleBuffer);
|
||||
av_frame_free(&frame);
|
||||
}
|
||||
|
||||
static
|
||||
CVReturn
|
||||
displayLinkOutputCallback(
|
||||
CVDisplayLinkRef,
|
||||
const CVTimeStamp* now,
|
||||
const CVTimeStamp* /* vsyncTime */,
|
||||
CVOptionFlags,
|
||||
CVOptionFlags*,
|
||||
void *displayLinkContext)
|
||||
{
|
||||
VTRenderer* me = reinterpret_cast<VTRenderer*>(displayLinkContext);
|
||||
|
||||
// In my testing on macOS 10.13, this callback is invoked about 24 ms
|
||||
// prior to the specified v-sync time (now - vsyncTime). Since this is
|
||||
// greater than the standard v-sync interval (16 ms = 60 FPS), we will
|
||||
// draw using the current host time, rather than the actual v-sync target
|
||||
// time. Because the CVDisplayLink is in sync with the actual v-sync
|
||||
// interval, even if many ms prior, we can safely use the current host time
|
||||
// and get a consistent callback for each v-sync. This reduces video latency
|
||||
// by at least 1 frame vs. rendering with the actual vsyncTime.
|
||||
me->drawFrame(now->hostTime);
|
||||
|
||||
return kCVReturnSuccess;
|
||||
}
|
||||
|
||||
virtual bool initialize(SDL_Window* window,
|
||||
int videoFormat,
|
||||
@@ -243,34 +113,60 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
CVDisplayLinkCreateWithActiveCGDisplays(&m_DisplayLink);
|
||||
CVDisplayLinkSetOutputCallback(m_DisplayLink, displayLinkOutputCallback, this);
|
||||
CVDisplayLinkStart(m_DisplayLink);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool prepareDecoderContext(AVCodecContext* context) override
|
||||
{
|
||||
context->hw_device_ctx = av_buffer_ref(m_HwContext);
|
||||
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Using VideoToolbox accelerated renderer");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void renderFrame(AVFrame* frame) override
|
||||
{
|
||||
CVPixelBufferRef pixBuf = reinterpret_cast<CVPixelBufferRef>(frame->data[3]);
|
||||
OSStatus status;
|
||||
|
||||
if (m_DisplayLayer.status == AVQueuedSampleBufferRenderingStatusFailed) {
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Resetting failed AVSampleBufferDisplay layer");
|
||||
setupDisplayLayer();
|
||||
}
|
||||
|
||||
SDL_AtomicLock(&m_FrameQueueLock);
|
||||
m_FrameQueue.enqueue(frame);
|
||||
SDL_AtomicUnlock(&m_FrameQueueLock);
|
||||
// If the format has changed or doesn't exist yet, construct it with the
|
||||
// pixel buffer data
|
||||
if (!m_FormatDesc || !CMVideoFormatDescriptionMatchesImageBuffer(m_FormatDesc, pixBuf)) {
|
||||
status = CMVideoFormatDescriptionCreateForImageBuffer(kCFAllocatorDefault,
|
||||
pixBuf, &m_FormatDesc);
|
||||
if (status != noErr) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"CMVideoFormatDescriptionCreateForImageBuffer() failed: %d",
|
||||
status);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
CMSampleBufferRef sampleBuffer;
|
||||
status = CMSampleBufferCreateReadyWithImageBuffer(kCFAllocatorDefault,
|
||||
pixBuf,
|
||||
m_FormatDesc,
|
||||
&kCMTimingInfoInvalid,
|
||||
&sampleBuffer);
|
||||
if (status != noErr) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"CMSampleBufferCreateReadyWithImageBuffer() failed: %d",
|
||||
status);
|
||||
return;
|
||||
}
|
||||
|
||||
CFArrayRef attachments = CMSampleBufferGetSampleAttachmentsArray(sampleBuffer, true);
|
||||
CFMutableDictionaryRef dict = (CFMutableDictionaryRef)CFArrayGetValueAtIndex(attachments, 0);
|
||||
|
||||
CFDictionarySetValue(dict, kCMSampleAttachmentKey_DisplayImmediately, kCFBooleanTrue);
|
||||
|
||||
[m_DisplayLayer enqueueSampleBuffer:sampleBuffer];
|
||||
|
||||
CFRelease(sampleBuffer);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -296,10 +192,6 @@ private:
|
||||
AVSampleBufferDisplayLayer* m_DisplayLayer;
|
||||
CMVideoFormatDescriptionRef m_FormatDesc;
|
||||
NSView* m_View;
|
||||
CVDisplayLinkRef m_DisplayLink;
|
||||
QQueue<AVFrame*> m_FrameQueue;
|
||||
QQueue<int> m_FrameQueueHistory;
|
||||
SDL_SpinLock m_FrameQueueLock;
|
||||
};
|
||||
|
||||
IFFmpegRenderer* VTRendererFactory::createRenderer() {
|
||||
|
||||
@@ -1,51 +1,87 @@
|
||||
#include <Limelight.h>
|
||||
#include "ffmpeg.h"
|
||||
|
||||
#ifdef Q_OS_WIN32
|
||||
#ifdef _WIN32
|
||||
#include "ffmpeg-renderers/dxva2.h"
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_DARWIN
|
||||
#include "ffmpeg-renderers/vt.h"
|
||||
#endif
|
||||
bool FFmpegVideoDecoder::chooseDecoder(
|
||||
StreamingPreferences::VideoDecoderSelection vds,
|
||||
SDL_Window* window,
|
||||
int videoFormat,
|
||||
int width, int height,
|
||||
AVCodec*& chosenDecoder,
|
||||
const AVCodecHWConfig*& chosenHwConfig,
|
||||
IFFmpegRenderer*& newRenderer)
|
||||
{
|
||||
if (videoFormat & VIDEO_FORMAT_MASK_H264) {
|
||||
chosenDecoder = avcodec_find_decoder(AV_CODEC_ID_H264);
|
||||
}
|
||||
else if (videoFormat & VIDEO_FORMAT_MASK_H265) {
|
||||
chosenDecoder = avcodec_find_decoder(AV_CODEC_ID_HEVC);
|
||||
}
|
||||
else {
|
||||
Q_ASSERT(false);
|
||||
chosenDecoder = nullptr;
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBVA
|
||||
#include "ffmpeg-renderers/vaapi.h"
|
||||
#endif
|
||||
if (!chosenDecoder) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Unable to find decoder for format: %x",
|
||||
videoFormat);
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBVDPAU
|
||||
#include "ffmpeg-renderers/vdpau.h"
|
||||
#endif
|
||||
for (int i = 0;; i++) {
|
||||
const AVCodecHWConfig *config = avcodec_get_hw_config(chosenDecoder, i);
|
||||
if (!config || vds == StreamingPreferences::VDS_FORCE_SOFTWARE) {
|
||||
// No matching hardware acceleration support.
|
||||
// This is not an error.
|
||||
chosenHwConfig = nullptr;
|
||||
newRenderer = new SdlRenderer();
|
||||
if (vds != StreamingPreferences::VDS_FORCE_HARDWARE &&
|
||||
newRenderer->initialize(window, videoFormat, width, height)) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
delete newRenderer;
|
||||
newRenderer = nullptr;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// This is gross but it allows us to use sizeof()
|
||||
#include "ffmpeg_videosamples.cpp"
|
||||
if (!(config->methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Look for acceleration types we support
|
||||
switch (config->device_type) {
|
||||
#ifdef _WIN32
|
||||
case AV_HWDEVICE_TYPE_DXVA2:
|
||||
newRenderer = new DXVA2Renderer();
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
if (newRenderer->initialize(window, videoFormat, width, height)) {
|
||||
chosenHwConfig = config;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
// Failed to initialize
|
||||
delete newRenderer;
|
||||
newRenderer = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool FFmpegVideoDecoder::isHardwareAccelerated()
|
||||
{
|
||||
return m_HwDecodeCfg != nullptr;
|
||||
}
|
||||
|
||||
enum AVPixelFormat FFmpegVideoDecoder::ffGetFormat(AVCodecContext* context,
|
||||
const enum AVPixelFormat* pixFmts)
|
||||
{
|
||||
FFmpegVideoDecoder* decoder = (FFmpegVideoDecoder*)context->opaque;
|
||||
const enum AVPixelFormat *p;
|
||||
|
||||
for (p = pixFmts; *p != -1; p++) {
|
||||
// Only match our hardware decoding codec or SW pixel
|
||||
// format (if not using hardware decoding). It's crucial
|
||||
// to override the default get_format() which will try
|
||||
// to gracefully fall back to software decode and break us.
|
||||
if (*p == (decoder->m_HwDecodeCfg ?
|
||||
decoder->m_HwDecodeCfg->pix_fmt :
|
||||
context->pix_fmt)) {
|
||||
return *p;
|
||||
}
|
||||
}
|
||||
|
||||
return AV_PIX_FMT_NONE;
|
||||
}
|
||||
|
||||
FFmpegVideoDecoder::FFmpegVideoDecoder()
|
||||
: m_VideoDecoderCtx(nullptr),
|
||||
m_DecodeBuffer(1024 * 1024, 0),
|
||||
@@ -53,7 +89,6 @@ FFmpegVideoDecoder::FFmpegVideoDecoder()
|
||||
m_Renderer(nullptr)
|
||||
{
|
||||
av_init_packet(&m_Pkt);
|
||||
SDL_AtomicSet(&m_QueuedFrames, 0);
|
||||
|
||||
// Use linear filtering when renderer scaling is required
|
||||
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1");
|
||||
@@ -61,46 +96,32 @@ FFmpegVideoDecoder::FFmpegVideoDecoder()
|
||||
|
||||
FFmpegVideoDecoder::~FFmpegVideoDecoder()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
avcodec_close(m_VideoDecoderCtx);
|
||||
av_free(m_VideoDecoderCtx);
|
||||
m_VideoDecoderCtx = nullptr;
|
||||
|
||||
IFFmpegRenderer* FFmpegVideoDecoder::getRenderer()
|
||||
{
|
||||
return m_Renderer;
|
||||
}
|
||||
|
||||
void FFmpegVideoDecoder::reset()
|
||||
{
|
||||
// Drop any frames still queued to ensure
|
||||
// they are properly freed.
|
||||
SDL_Event event;
|
||||
|
||||
while (SDL_AtomicGet(&m_QueuedFrames) > 0) {
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Waiting for %d frames to return",
|
||||
SDL_AtomicGet(&m_QueuedFrames));
|
||||
|
||||
if (SDL_PeepEvents(&event,
|
||||
1,
|
||||
SDL_GETEVENT,
|
||||
SDL_USEREVENT,
|
||||
SDL_USEREVENT) == 1) {
|
||||
dropFrame(&event.user);
|
||||
}
|
||||
else {
|
||||
SDL_Delay(100);
|
||||
SDL_PumpEvents();
|
||||
}
|
||||
}
|
||||
|
||||
avcodec_free_context(&m_VideoDecoderCtx);
|
||||
m_HwDecodeCfg = nullptr;
|
||||
|
||||
delete m_Renderer;
|
||||
m_Renderer = nullptr;
|
||||
}
|
||||
|
||||
bool FFmpegVideoDecoder::completeInitialization(AVCodec* decoder, int videoFormat, int width, int height, bool testOnly)
|
||||
bool FFmpegVideoDecoder::initialize(
|
||||
StreamingPreferences::VideoDecoderSelection vds,
|
||||
SDL_Window* window,
|
||||
int videoFormat,
|
||||
int width,
|
||||
int height,
|
||||
int)
|
||||
{
|
||||
AVCodec* decoder;
|
||||
|
||||
if (!chooseDecoder(vds, window, videoFormat, width, height,
|
||||
decoder, m_HwDecodeCfg, m_Renderer)) {
|
||||
// Error logged in chooseDecoder()
|
||||
return false;
|
||||
}
|
||||
|
||||
m_VideoDecoderCtx = avcodec_alloc_context3(decoder);
|
||||
if (!m_VideoDecoderCtx) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
@@ -125,20 +146,12 @@ bool FFmpegVideoDecoder::completeInitialization(AVCodec* decoder, int videoForma
|
||||
m_VideoDecoderCtx->width = width;
|
||||
m_VideoDecoderCtx->height = height;
|
||||
m_VideoDecoderCtx->pix_fmt = AV_PIX_FMT_YUV420P; // FIXME: HDR
|
||||
m_VideoDecoderCtx->get_format = ffGetFormat;
|
||||
|
||||
// Allow the renderer to attach data to this decoder
|
||||
if (!m_Renderer->prepareDecoderContext(m_VideoDecoderCtx)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Nobody must override our ffGetFormat
|
||||
SDL_assert(m_VideoDecoderCtx->get_format == ffGetFormat);
|
||||
|
||||
// Stash a pointer to this object in the context
|
||||
SDL_assert(m_VideoDecoderCtx->opaque == nullptr);
|
||||
m_VideoDecoderCtx->opaque = this;
|
||||
|
||||
int err = avcodec_open2(m_VideoDecoderCtx, decoder, nullptr);
|
||||
if (err < 0) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
@@ -147,148 +160,9 @@ bool FFmpegVideoDecoder::completeInitialization(AVCodec* decoder, int videoForma
|
||||
return false;
|
||||
}
|
||||
|
||||
// FFMpeg doesn't completely initialize the codec until the codec
|
||||
// config data comes in. This would be too late for us to change
|
||||
// our minds on the selected video codec, so we'll do a trial run
|
||||
// now to see if things will actually work when the video stream
|
||||
// comes in.
|
||||
if (testOnly) {
|
||||
if (videoFormat & VIDEO_FORMAT_MASK_H264) {
|
||||
m_Pkt.data = (uint8_t*)k_H264TestFrame;
|
||||
m_Pkt.size = sizeof(k_H264TestFrame);
|
||||
}
|
||||
else {
|
||||
m_Pkt.data = (uint8_t*)k_HEVCTestFrame;
|
||||
m_Pkt.size = sizeof(k_HEVCTestFrame);
|
||||
}
|
||||
|
||||
err = avcodec_send_packet(m_VideoDecoderCtx, &m_Pkt);
|
||||
if (err < 0) {
|
||||
char errorstring[512];
|
||||
av_strerror(err, errorstring, sizeof(errorstring));
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Test decode failed: %s", errorstring);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef QT_DEBUG
|
||||
// Restore default log level before streaming
|
||||
av_log_set_level(AV_LOG_INFO);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
IFFmpegRenderer* FFmpegVideoDecoder::createAcceleratedRenderer(const AVCodecHWConfig* hwDecodeCfg)
|
||||
{
|
||||
if (!(hwDecodeCfg->methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Look for acceleration types we support
|
||||
switch (hwDecodeCfg->device_type) {
|
||||
#ifdef Q_OS_WIN32
|
||||
case AV_HWDEVICE_TYPE_DXVA2:
|
||||
return new DXVA2Renderer();
|
||||
#endif
|
||||
#ifdef Q_OS_DARWIN
|
||||
case AV_HWDEVICE_TYPE_VIDEOTOOLBOX:
|
||||
return VTRendererFactory::createRenderer();
|
||||
#endif
|
||||
#ifdef HAVE_LIBVA
|
||||
case AV_HWDEVICE_TYPE_VAAPI:
|
||||
return new VAAPIRenderer();
|
||||
#endif
|
||||
#ifdef HAVE_LIBVDPAU
|
||||
case AV_HWDEVICE_TYPE_VDPAU:
|
||||
return new VDPAURenderer();
|
||||
#endif
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool FFmpegVideoDecoder::initialize(
|
||||
StreamingPreferences::VideoDecoderSelection vds,
|
||||
SDL_Window* window,
|
||||
int videoFormat,
|
||||
int width,
|
||||
int height,
|
||||
int)
|
||||
{
|
||||
AVCodec* decoder;
|
||||
|
||||
#ifdef QT_DEBUG
|
||||
// Increase log level during initialization
|
||||
av_log_set_level(AV_LOG_DEBUG);
|
||||
#endif
|
||||
|
||||
if (videoFormat & VIDEO_FORMAT_MASK_H264) {
|
||||
decoder = avcodec_find_decoder(AV_CODEC_ID_H264);
|
||||
}
|
||||
else if (videoFormat & VIDEO_FORMAT_MASK_H265) {
|
||||
decoder = avcodec_find_decoder(AV_CODEC_ID_HEVC);
|
||||
}
|
||||
else {
|
||||
Q_ASSERT(false);
|
||||
decoder = nullptr;
|
||||
}
|
||||
|
||||
if (!decoder) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Unable to find decoder for format: %x",
|
||||
videoFormat);
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0;; i++) {
|
||||
const AVCodecHWConfig *config = avcodec_get_hw_config(decoder, i);
|
||||
if (!config || vds == StreamingPreferences::VDS_FORCE_SOFTWARE) {
|
||||
// No matching hardware acceleration support.
|
||||
// This is not an error.
|
||||
m_HwDecodeCfg = nullptr;
|
||||
m_Renderer = new SdlRenderer();
|
||||
if (vds != StreamingPreferences::VDS_FORCE_HARDWARE &&
|
||||
m_Renderer->initialize(window, videoFormat, width, height) &&
|
||||
completeInitialization(decoder, videoFormat, width, height, false)) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
reset();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
m_Renderer = createAcceleratedRenderer(config);
|
||||
if (!m_Renderer) {
|
||||
continue;
|
||||
}
|
||||
|
||||
m_HwDecodeCfg = config;
|
||||
// Submit test frame to ensure this codec really works
|
||||
if (m_Renderer->initialize(window, videoFormat, width, height) &&
|
||||
completeInitialization(decoder, videoFormat, width, height, true)) {
|
||||
// OK, it worked, so now let's initialize it for real
|
||||
reset();
|
||||
if ((m_Renderer = createAcceleratedRenderer(config)) != nullptr &&
|
||||
m_Renderer->initialize(window, videoFormat, width, height) &&
|
||||
completeInitialization(decoder, videoFormat, width, height, false)) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Decoder failed to initialize after successful test");
|
||||
reset();
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Failed to initialize or test frame failed, so keep looking
|
||||
reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int FFmpegVideoDecoder::submitDecodeUnit(PDECODE_UNIT du)
|
||||
{
|
||||
PLENTRY entry = du->bufferList;
|
||||
@@ -314,6 +188,8 @@ int FFmpegVideoDecoder::submitDecodeUnit(PDECODE_UNIT du)
|
||||
|
||||
err = avcodec_send_packet(m_VideoDecoderCtx, &m_Pkt);
|
||||
if (err < 0) {
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Decoding failed: %d", err);
|
||||
char errorstring[512];
|
||||
av_strerror(err, errorstring, sizeof(errorstring));
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
||||
@@ -332,9 +208,14 @@ int FFmpegVideoDecoder::submitDecodeUnit(PDECODE_UNIT du)
|
||||
|
||||
err = avcodec_receive_frame(m_VideoDecoderCtx, frame);
|
||||
if (err == 0) {
|
||||
// Queue the frame for rendering from the main thread
|
||||
SDL_AtomicIncRef(&m_QueuedFrames);
|
||||
queueFrame(frame);
|
||||
SDL_Event event;
|
||||
|
||||
event.type = SDL_USEREVENT;
|
||||
event.user.code = SDL_CODE_FRAME_READY;
|
||||
event.user.data1 = frame;
|
||||
|
||||
// The main thread will handle freeing this
|
||||
SDL_PushEvent(&event);
|
||||
}
|
||||
else {
|
||||
av_frame_free(&frame);
|
||||
@@ -348,7 +229,7 @@ void FFmpegVideoDecoder::renderFrame(SDL_UserEvent* event)
|
||||
{
|
||||
AVFrame* frame = reinterpret_cast<AVFrame*>(event->data1);
|
||||
m_Renderer->renderFrame(frame);
|
||||
SDL_AtomicDecRef(&m_QueuedFrames);
|
||||
av_frame_free(&frame);
|
||||
}
|
||||
|
||||
// Called on main thread
|
||||
@@ -356,5 +237,4 @@ void FFmpegVideoDecoder::dropFrame(SDL_UserEvent* event)
|
||||
{
|
||||
AVFrame* frame = reinterpret_cast<AVFrame*>(event->data1);
|
||||
av_frame_free(&frame);
|
||||
SDL_AtomicDecRef(&m_QueuedFrames);
|
||||
}
|
||||
|
||||
@@ -22,27 +22,20 @@ public:
|
||||
virtual void renderFrame(SDL_UserEvent* event) override;
|
||||
virtual void dropFrame(SDL_UserEvent* event) override;
|
||||
|
||||
virtual IFFmpegRenderer* getRenderer();
|
||||
|
||||
private:
|
||||
bool completeInitialization(AVCodec* decoder, int videoFormat,
|
||||
int width, int height, bool testOnly);
|
||||
|
||||
IFFmpegRenderer* createAcceleratedRenderer(const AVCodecHWConfig* hwDecodeCfg);
|
||||
|
||||
void reset();
|
||||
|
||||
static
|
||||
enum AVPixelFormat ffGetFormat(AVCodecContext* context,
|
||||
const enum AVPixelFormat* pixFmts);
|
||||
bool
|
||||
chooseDecoder(
|
||||
StreamingPreferences::VideoDecoderSelection vds,
|
||||
SDL_Window* window,
|
||||
int videoFormat,
|
||||
int width, int height,
|
||||
AVCodec*& chosenDecoder,
|
||||
const AVCodecHWConfig*& chosenHwConfig,
|
||||
IFFmpegRenderer*& newRenderer);
|
||||
|
||||
AVPacket m_Pkt;
|
||||
AVCodecContext* m_VideoDecoderCtx;
|
||||
QByteArray m_DecodeBuffer;
|
||||
const AVCodecHWConfig* m_HwDecodeCfg;
|
||||
IFFmpegRenderer* m_Renderer;
|
||||
SDL_atomic_t m_QueuedFrames;
|
||||
|
||||
static const uint8_t k_H264TestFrame[];
|
||||
static const uint8_t k_HEVCTestFrame[];
|
||||
};
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
#include "ffmpeg.h"
|
||||
|
||||
// 720p 60 FPS H.264 with 1 reference frame
|
||||
const uint8_t FFmpegVideoDecoder::k_H264TestFrame[] = {
|
||||
0x00, 0x00, 0x00, 0x01, 0x67, 0x64, 0x00, 0x20, 0xac, 0x2b, 0x40, 0x28, 0x02, 0xdd, 0x80, 0xb5, 0x06, 0x06, 0x06, 0xa5, 0x00, 0x00, 0x03, 0x03, 0xe8, 0x00, 0x01, 0xd4, 0xc0, 0x8f, 0x4a, 0xa0,
|
||||
0x00, 0x00, 0x00, 0x01, 0x68, 0xee, 0x3c, 0xb0,
|
||||
0x00, 0x00, 0x00, 0x01, 0x65, 0xb8, 0x02, 0x01, 0x67, 0x25, 0x1b, 0xf4, 0xfa, 0x7d, 0x40, 0x1a, 0x78, 0xe5, 0x10, 0x52, 0xc2, 0xee, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0xc6, 0xef, 0xbb, 0x81, 0x85, 0x2d, 0x47, 0xda, 0xca, 0x4c, 0x00, 0x00, 0x03, 0x00, 0x02, 0x7b, 0xcf, 0x80, 0x00, 0x45, 0x40, 0x01, 0x8d, 0xa6, 0x00, 0x01, 0x64, 0x00, 0x0e, 0x03, 0xc8, 0x00, 0x0e, 0x10, 0x00, 0xbd, 0xc5, 0x00, 0x01, 0x11, 0x00, 0x0e, 0xa3, 0x80, 0x00, 0x38, 0xa0,
|
||||
0x00, 0x00, 0x01, 0x65, 0x00, 0x6e, 0x2e, 0x00, 0x83, 0x7f, 0xb4, 0x8e, 0x79, 0xa5, 0xff, 0x84, 0x3f, 0x7f, 0x34, 0x3f, 0x97, 0x1b, 0xaf, 0x31, 0x5f, 0x6e, 0xaa, 0xb6, 0xac, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x78, 0x36, 0x9d, 0xa4, 0x65, 0xf9, 0x1e, 0x5b, 0x3a, 0xb0, 0x40, 0x00, 0x00, 0x03, 0x00, 0x00, 0x41, 0x80, 0x00, 0xc5, 0xc8, 0x00, 0x00, 0xfa, 0x00, 0x03, 0x24, 0x00, 0x0e, 0x20, 0x00, 0x3f, 0x80, 0x01, 0x32, 0x00, 0x08, 0x68, 0x00, 0x3e, 0xc0, 0x03, 0x8a,
|
||||
0x00, 0x00, 0x01, 0x65, 0x00, 0x37, 0x0b, 0x80, 0x21, 0x7f, 0xe3, 0x85, 0x1c, 0xd9, 0xff, 0xe1, 0x1b, 0x01, 0xfa, 0xc0, 0x3e, 0x11, 0x7e, 0xfe, 0x45, 0x5c, 0x43, 0x69, 0x31, 0x4b, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x02, 0x24, 0xae, 0x1a, 0xbb, 0xae, 0x75, 0x9e, 0x35, 0xae, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x03, 0x64, 0x00, 0x09, 0x98, 0x00, 0x1e, 0xc0, 0x00, 0x64, 0x80, 0x01, 0xc4, 0x00, 0x07, 0xf0, 0x00, 0x42, 0xf0, 0x00, 0x00, 0xe1, 0x98, 0x00, 0x05, 0x4b, 0x28, 0x00, 0x06, 0x04,
|
||||
0x00, 0x00, 0x01, 0x65, 0x00, 0x14, 0xa2, 0xe0, 0x08, 0x5f, 0xe3, 0x85, 0x1c, 0xd9, 0xff, 0xe1, 0x1b, 0x01, 0xfa, 0xc0, 0x3e, 0x11, 0x7e, 0xfe, 0x45, 0x5c, 0x43, 0x69, 0x31, 0x4b, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x02, 0x24, 0xb9, 0x7d, 0xb4, 0x70, 0x4d, 0x15, 0xc5, 0x0a, 0x4e, 0x60, 0x00, 0x00, 0x03, 0x00, 0x00, 0x26, 0xa8, 0xb0, 0x00, 0x13, 0xcd, 0xcc, 0x00, 0x07, 0x48, 0x88, 0x00, 0x06, 0x29, 0x69, 0x00, 0x01, 0x16, 0xac, 0x80, 0x00, 0x9e, 0x4e, 0x80, 0x00, 0x3f, 0x84, 0x20, 0x00, 0x6f, 0x41, 0xa0, 0x00, 0x20, 0x00, 0x02, 0x16, 0xb8, 0x00, 0x08, 0x08
|
||||
};
|
||||
|
||||
// 720p 60 FPS HEVC with 1 reference frame
|
||||
const uint8_t FFmpegVideoDecoder::k_HEVCTestFrame[] = {
|
||||
0x00, 0x00, 0x00, 0x01, 0x40, 0x01, 0x0c, 0x01, 0xff, 0xff, 0x01, 0x40, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x78, 0xac, 0x09,
|
||||
0x00, 0x00, 0x00, 0x01, 0x42, 0x01, 0x01, 0x01, 0x40, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x78, 0xa0, 0x02, 0x80, 0x80, 0x2e, 0x1f, 0x13, 0x96, 0xb4, 0xa4, 0x25, 0x92, 0xe3, 0x01, 0x6a, 0x0c, 0x0c, 0x0d, 0x48, 0x20, 0x00, 0x00, 0x03, 0x00, 0x20, 0x00, 0x00, 0x07, 0x85, 0xf1, 0xa2, 0xd0,
|
||||
0x00, 0x00, 0x00, 0x01, 0x44, 0x01, 0xc0, 0xf7, 0xc0, 0xcc, 0x90,
|
||||
0x00, 0x00, 0x00, 0x01, 0x2a, 0x01, 0xac, 0x0c, 0xf0, 0xe6, 0xf6, 0x5e, 0xff, 0xd9, 0x97, 0xeb, 0x44, 0x7d, 0x1f, 0xa4, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x03, 0x52, 0x7c, 0x4e, 0x5b, 0xfe, 0xbe, 0xc2, 0x87, 0x20, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x2b, 0x60,
|
||||
};
|
||||
@@ -1,106 +0,0 @@
|
||||
#include "sl.h"
|
||||
|
||||
SLVideoDecoder::SLVideoDecoder()
|
||||
: m_VideoContext(nullptr),
|
||||
m_VideoStream(nullptr)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
SLVideoDecoder::~SLVideoDecoder()
|
||||
{
|
||||
if (m_VideoStream != nullptr) {
|
||||
SLVideo_FreeStream(m_VideoStream);
|
||||
}
|
||||
|
||||
if (m_VideoContext != nullptr) {
|
||||
SLVideo_FreeContext(m_VideoContext);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
SLVideoDecoder::isHardwareAccelerated()
|
||||
{
|
||||
// SLVideo is always hardware accelerated
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
SLVideoDecoder::initialize(StreamingPreferences::VideoDecoderSelection vds,
|
||||
SDL_Window*,
|
||||
int videoFormat, int, int, int frameRate)
|
||||
{
|
||||
// SLVideo only supports hardware decoding
|
||||
if (vds == StreamingPreferences::VDS_FORCE_SOFTWARE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// SLVideo only supports H.264
|
||||
if (videoFormat != VIDEO_FORMAT_H264) {
|
||||
return false;
|
||||
}
|
||||
|
||||
m_VideoContext = SLVideo_CreateContext();
|
||||
if (!m_VideoContext) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"SLVideo_CreateContext() failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create a low latency H.264 stream
|
||||
m_VideoStream = SLVideo_CreateStream(m_VideoContext, k_ESLVideoFormatH264, 1);
|
||||
if (!m_VideoStream) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"SLVideo_CreateStream() failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
SLVideo_SetStreamTargetFramerate(m_VideoStream, frameRate, 1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int
|
||||
SLVideoDecoder::submitDecodeUnit(PDECODE_UNIT du)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = SLVideo_BeginFrame(m_VideoStream, du->fullLength);
|
||||
if (err < 0) {
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"SLVideo_BeginFrame() failed: %d",
|
||||
err);
|
||||
|
||||
// Need an IDR frame to resync
|
||||
return DR_NEED_IDR;
|
||||
}
|
||||
|
||||
PLENTRY entry = du->bufferList;
|
||||
while (entry != nullptr) {
|
||||
err = SLVideo_WriteFrameData(m_VideoStream,
|
||||
entry->data,
|
||||
entry->length);
|
||||
if (err < 0) {
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"SLVideo_WriteFrameData() failed: %d",
|
||||
err);
|
||||
|
||||
// Need an IDR frame to resync
|
||||
return DR_NEED_IDR;
|
||||
}
|
||||
|
||||
entry = entry->next;
|
||||
}
|
||||
|
||||
err = SLVideo_SubmitFrame(m_VideoStream);
|
||||
if (err < 0) {
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"SLVideo_SubmitFrame() failed: %d",
|
||||
err);
|
||||
|
||||
// Need an IDR frame to resync
|
||||
return DR_NEED_IDR;
|
||||
}
|
||||
|
||||
return DR_OK;
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "decoder.h"
|
||||
|
||||
#include <SLVideo.h>
|
||||
|
||||
class SLVideoDecoder : public IVideoDecoder
|
||||
{
|
||||
public:
|
||||
SLVideoDecoder();
|
||||
virtual ~SLVideoDecoder();
|
||||
virtual bool initialize(StreamingPreferences::VideoDecoderSelection vds,
|
||||
SDL_Window* window,
|
||||
int videoFormat,
|
||||
int width,
|
||||
int height,
|
||||
int frameRate);
|
||||
virtual bool isHardwareAccelerated();
|
||||
virtual int submitDecodeUnit(PDECODE_UNIT du);
|
||||
|
||||
// Unused since rendering is done directly from the decode thread
|
||||
virtual void renderFrame(SDL_UserEvent*) {}
|
||||
virtual void dropFrame(SDL_UserEvent*) {}
|
||||
|
||||
private:
|
||||
CSLVideoContext* m_VideoContext;
|
||||
CSLVideoStream* m_VideoStream;
|
||||
};
|
||||
@@ -1,5 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#define THROW_BAD_ALLOC_IF_NULL(x) \
|
||||
if ((x) == nullptr) throw std::bad_alloc()
|
||||
if ((x) == nullptr) throw new std::bad_alloc()
|
||||
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
SOURCES = main.cpp
|
||||
LIBS += -lSLVideo
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
#include <SLVideo.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
SLVideo_CreateContext();
|
||||
return 0;
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
Versions/Current/Headers
|
||||
@@ -1 +0,0 @@
|
||||
Versions/Current/Resources
|
||||
@@ -1 +0,0 @@
|
||||
Versions/Current/SDL2
|
||||
@@ -1,46 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>BuildMachineOSBuild</key>
|
||||
<string>17C88</string>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>English</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>SDL2</string>
|
||||
<key>CFBundleGetInfoString</key>
|
||||
<string>http://www.libsdl.org</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>org.libsdl.SDL2</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>Simple DirectMedia Layer</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>2.0.8</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>SDLX</string>
|
||||
<key>CFBundleSupportedPlatforms</key>
|
||||
<array>
|
||||
<string>MacOSX</string>
|
||||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>2.0.8</string>
|
||||
<key>DTCompiler</key>
|
||||
<string>com.apple.compilers.llvm.clang.1_0</string>
|
||||
<key>DTPlatformBuild</key>
|
||||
<string>9C40b</string>
|
||||
<key>DTPlatformVersion</key>
|
||||
<string>GM</string>
|
||||
<key>DTSDKBuild</key>
|
||||
<string>17C76</string>
|
||||
<key>DTSDKName</key>
|
||||
<string>macosx10.13</string>
|
||||
<key>DTXcode</key>
|
||||
<string>0920</string>
|
||||
<key>DTXcodeBuild</key>
|
||||
<string>9C40b</string>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -1,792 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>files</key>
|
||||
<dict>
|
||||
<key>Resources/Info.plist</key>
|
||||
<data>
|
||||
dts8ape5zBg3+8u8BQ5kWqp9cC8=
|
||||
</data>
|
||||
</dict>
|
||||
<key>files2</key>
|
||||
<dict>
|
||||
<key>Headers/SDL.h</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
wiqwnVgtbgjGPAOFejxz8yw7geU=
|
||||
</data>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
LLwzMAHn2OsCr2SVR7M71KeQf+TiJpHk/KKojzQdRlI=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Headers/SDL_assert.h</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
zWoE6/P7ZWAYr4J+EVgDAK+kot8=
|
||||
</data>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
tuS18C7A11akqH9MWT0WWCb6q7kcF97Ui5OFwNtSF/k=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Headers/SDL_atomic.h</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
/q15zvR2djPgTRkySENYqzisn64=
|
||||
</data>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
n9rGA8zXFxasUnN0ytgLLWmW2CDCtKBeGJZcfB+nfRc=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Headers/SDL_audio.h</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
9uJv81fH9Op/f3sF7/GVuNYQNOc=
|
||||
</data>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
KDokTSV3kZuHCQFFrRum3VoTP1QSW2xAghjceoIArXY=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Headers/SDL_bits.h</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
yp8Jj93ZE224v1+u++cOexlp9RY=
|
||||
</data>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
kQTBxFYnOjKSlti4H7pAYZWdkH0BpQ9Eq54E/r/nlVY=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Headers/SDL_blendmode.h</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
kgTnzOrp0kqeI8lzDgQyT/gCGiM=
|
||||
</data>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
d/8B0iLh4aFeoaPEFqQ4C6x4ISlDJCKrybaKuHCJHL4=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Headers/SDL_clipboard.h</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
qq1r82AS7fHG8G94+jvL41iKEyA=
|
||||
</data>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
+r0LOXHGRf2Q9+FkqRU6i++1zEzsE5sWXxxMGrsSyKk=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Headers/SDL_config.h</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
nJnfliCMDJUfOG8t4QYt5U9tFBY=
|
||||
</data>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
qkVvxnI+XRMTIdbzQ9tV+ERRc75r/EzWu0qRTgt5K5c=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Headers/SDL_config_macosx.h</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
D0LXp0FibaaLSE6877hbyqf2Jb8=
|
||||
</data>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
pCQLXwJ6HaGZiG5vr9njJtgNcIV9p0mxcSJtYoj147A=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Headers/SDL_copying.h</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
0DKOkPvRlLo00X7iE2fL4i8XBww=
|
||||
</data>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
nHJ8cj/FeSfLoRm5gRiDk73eyYlKn7u1BfbqkB2ofLg=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Headers/SDL_cpuinfo.h</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
2wleDfJFmCBrEssrE9rcuaiqOLQ=
|
||||
</data>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
MEpF0mFQFLhuTV+5uSB++q8tT2z5heESxyP1HuzuKxc=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Headers/SDL_endian.h</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
WmJrxu+b1MkjtE6ttCymwH4EVC0=
|
||||
</data>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
77hv0QIqlra/8gcQF81aAwP21/ZAANKiIaJRV1QK8mk=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Headers/SDL_error.h</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
HMprigJ3u4PqQ7B+gD1UUbTSrJ8=
|
||||
</data>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
errosoVYCD45UvQVzL4Lmfq4eCQg92a6xUZ062DGEL4=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Headers/SDL_events.h</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
ptgRA0IBsCg5za/lwhTOPGNmekY=
|
||||
</data>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
lwISPqzee6nV4HCHaMzZCVJJAtFZmoi8cYlJkY41wKA=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Headers/SDL_filesystem.h</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
9rIKoCtsAONdgfT/4QKm3a56hV0=
|
||||
</data>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
l5nBvMglAIFEWf357KMyQ+E7cr4GqO9XNwevA04+VmQ=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Headers/SDL_gamecontroller.h</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
sUaSBwOprX7A696W6u2oOtIne+Y=
|
||||
</data>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
VZDstHk/V+tZik3q3xnDCAG3AfA+BoHk9lB406mKtxU=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Headers/SDL_gesture.h</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
d80fR6I92r+G26xckkQzTRj/tj4=
|
||||
</data>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
/5+tOQWQ9raopqBCExlH9ClAA/fVAfEBIrd/WlpaqIE=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Headers/SDL_haptic.h</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
95rNclZzbsuV6pyeG8cbIETgS84=
|
||||
</data>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
O4RUmC9HMqsjAf22Ru6z5j9HaYTsc7SxOnzOXPR3kz0=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Headers/SDL_hints.h</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
UjEgXfZiLUmQTh9G+Bkx8Y1Ov6k=
|
||||
</data>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
DqFPmBXNg9BovdIAlipnBKZo5mcQJCrLmhyIM/O+tvU=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Headers/SDL_joystick.h</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
97SJSCx+xjRHUQ6ilndhP8TZ110=
|
||||
</data>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
xYWL+BS5f9NGr7eeP+vL0kD5K6O99PXgOWLT2Bx2dRQ=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Headers/SDL_keyboard.h</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
RsaE9DMLq9lFsYokvdaQ8nhIkfY=
|
||||
</data>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
tpZGEHU3TKCozcYf4MA9gA5bXNPSxx9rqqBaPttgr+4=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Headers/SDL_keycode.h</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
9nIqgM67nCJUdjV3iiiviT8DFhk=
|
||||
</data>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
SpMclG+epmPQibi3fNsQe1lBUxZPJOOu4DfQjpTZYgw=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Headers/SDL_loadso.h</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
m+OEcfHbykTuEo6P3/y/kuV1xjk=
|
||||
</data>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
Yg3OrZpF17uC69TwprPyrpn3+su3YAaaA1hTNXAHxLw=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Headers/SDL_log.h</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
HcUUwymYqVSfgz2LdtuUqZSwjUY=
|
||||
</data>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
j4F34jvgNTEcHQQoPbBBugi4RKQLhGM+x4ndXdtDc0E=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Headers/SDL_main.h</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
7I0GPDiLKlavuXuoepYsl2mS6CI=
|
||||
</data>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
qwXROmpXppMPodetUGE0s/7HHmwfu3taLUeiiu+APk0=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Headers/SDL_messagebox.h</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
MEB/oCw7dyinbrBmQQqh46/uRVk=
|
||||
</data>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
DSuDS/nAzfEi2kO06DEpxRLj5V1++p2DYYA9Oou8ewQ=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Headers/SDL_mouse.h</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
I2UksqoB5v6RX64Ddwea9dW0sO0=
|
||||
</data>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
gFMH6bBzvJCff8F7FMWlP6o6TydFmiXEu0daWp166wk=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Headers/SDL_mutex.h</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
H6Q1bWPDKu2RsALoLzTBzPTrPkk=
|
||||
</data>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
WKU8g7bVD3KpQEgvXuUGrPcG5hgg+LwQBgzLQCeSVTg=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Headers/SDL_name.h</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
doLASBj4oiSiP6MW9wQblnyPN1E=
|
||||
</data>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
M0b8pslMMsWZp1KDVUdqX7ml3DKUVcwiTcfwGbhopvA=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Headers/SDL_opengl.h</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
ZN9vVzyxx542ZCZ4nmASJKJ7qFM=
|
||||
</data>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
dazK6AC8BOZXW9m9761qsuoqe3eJozPIbSc1YEY3UVE=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Headers/SDL_opengl_glext.h</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
nqPX1ObCVYyVzW3VbD3C/1vaTRE=
|
||||
</data>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
IULBL/m+rBc3UQPqu68w6FDM/Mda58oybFnlyn3OkjE=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Headers/SDL_opengles.h</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
aVEa5N2CHg93ZxdDuKfDtFnCbU8=
|
||||
</data>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
3CmcA5B4ydtkVin3NvNmYVHfgnhJJAVYNVw1YKM0Mko=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Headers/SDL_opengles2.h</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
yQ5nSugeN94hMSNhsIOmlAstJhY=
|
||||
</data>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
8H2lt37zXZs68UfBlqDGqSJTQ2+Slu7qywggJ2mIosI=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Headers/SDL_opengles2_gl2.h</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
g4y04zPFy1H/qujSNGRd0vB7ClQ=
|
||||
</data>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
9GAwK0cg8YPrZHWVqMGpyVwKFz3Ay9VHiyz70jzWltA=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Headers/SDL_opengles2_gl2ext.h</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
bTlnL+42kbi+n/gH//X2p0pqeuM=
|
||||
</data>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
5404JOHXH4pGO60gR/uLhz9zW6fKy9jvdMw5i1WTcpo=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Headers/SDL_opengles2_gl2platform.h</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
ByFMXJFtjcRglS/e0+DujyjC3dM=
|
||||
</data>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
wlKRTsmTMrnniYqSvQklJfb9VF07J0MDpqzYOcfiDDY=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Headers/SDL_opengles2_khrplatform.h</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
NLpJq9uBqjOpWhXISOQHPnTp/XQ=
|
||||
</data>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
djHeDyzmR0e/2JNIbqpBqgi56MXlxlAbgcBFxuvwSyo=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Headers/SDL_pixels.h</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
q2Uas2PGwUNo30Wiqomvrb03mp4=
|
||||
</data>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
fpczDM4z7VLJW6FMvRTygnypORPdk2q89S1kCbS2fpM=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Headers/SDL_platform.h</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
aM0ptLXVxYx4yXLsNYOssy/jx9Y=
|
||||
</data>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
R6MDdJ2ZUd9FGKReGdJE6YyHwqczb99jK9/IDW59AmI=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Headers/SDL_power.h</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
NqkQCWzmodWGdUFUZmzR9B/TApc=
|
||||
</data>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
VkJkbp+5Wd4WYDemJiu8R/emdH4PZSNPweoPmzRkfxM=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Headers/SDL_quit.h</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
eOEJzybg3UBfe83rKNfky9XAVGM=
|
||||
</data>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
mN/T7PjHVtVce+/m7tIWIH8p8lylLWPuJAkCsbEvjhg=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Headers/SDL_rect.h</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
B7oWq3VOxrWbVn0YV8xpvXG6dic=
|
||||
</data>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
dCsZcEfdmcr1RuOycWAtHnnQs5BWk8lw0Ubnv/aUwG4=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Headers/SDL_render.h</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
ATenWUmKg6AEbv2SbCy9JfT8jCw=
|
||||
</data>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
EYiKPX5wRIcWkCyROlT59wuiDupZ6yp0+YsDWOrhtnQ=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Headers/SDL_revision.h</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
XBn2NI8Qm53MeZGaXVB3fQrs0uc=
|
||||
</data>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
FHG6Lqi1wMmjow+JjxKYy/LAoqP+iDH8QYuJS1zr6T4=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Headers/SDL_rwops.h</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
ULSy/1QoNQhBu3kk75qXo30Wcvs=
|
||||
</data>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
KewlZ14FJ6CfLjd7EDc1KlVSiUhIt2P9d3p2VEJuUUA=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Headers/SDL_scancode.h</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
FAcbPIsuPOYbsldZL4m0AFUeoW4=
|
||||
</data>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
5VaZC9IfMuNgz3h6OJn9Q/IGB/+cpymxIrjkluCWzOo=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Headers/SDL_shape.h</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
S5Ty+gKktVyifkoYT0K7E48JqdI=
|
||||
</data>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
LVwSnfZBuKL1bW2zy4rt0vRPmH2/ZxfmP0xB9pLVEOE=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Headers/SDL_stdinc.h</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
qBTB0Yqh+34vD3n3dN9ry9GwqJM=
|
||||
</data>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
TDMriI0PPYF73lvh6suExzpMldCmX1SkLgg+wkBqt7A=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Headers/SDL_surface.h</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
bssTKTIF4Yw/3a6fyF7GhaVrdU0=
|
||||
</data>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
zRF/b8bCqjClZnbPorqjhlWw9aujM9RwnVemHyiC2yM=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Headers/SDL_system.h</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
n2WodCV+WpbfpFSKUUKpB/i5ZPw=
|
||||
</data>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
3W0Z/Fdwbc7dTyR+v4g6eVE58XcEYLTzDGO+RMwcmJc=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Headers/SDL_syswm.h</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
QoebSqgb1XslKPBwMiUOM6daVKo=
|
||||
</data>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
rCqmdvdibhT5MBOnvKCT0gK7Howb5uLewC321yLYr5U=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Headers/SDL_thread.h</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
fXCWQD4MIniqvdB6pWVwlxNS9jk=
|
||||
</data>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
18iJ1yFzOTeiM30JwK3GMlbgUqzNDIQiw3ZLLr3M+XQ=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Headers/SDL_timer.h</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
qfzyWhIh36SK6BAcdd50D/MfdGo=
|
||||
</data>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
5Qe92nVkUnHbxgbGwxkyglvVKajhfgVhxPei6dhr4c0=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Headers/SDL_touch.h</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
yyJt6piMAcoFWhFqsHk9mo3MtaI=
|
||||
</data>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
9mQ2V937DAO6OjcQFMboFrnJEiqdk+2uHBzdvMYUnd0=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Headers/SDL_types.h</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
oVg7CzABdDKtxCWINHaUvBRbRZ0=
|
||||
</data>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
8uZym5ly46CZ4VQZCz/Y/cH4THoDS8kGqrvB+Ux/254=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Headers/SDL_version.h</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
nKLee2vSNZZK9p94Up9o87OoiDE=
|
||||
</data>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
F3dpo9XlvebIS2NLJ1ovH+W7fG3bzb01F8OKUeqd+U0=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Headers/SDL_video.h</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
UFZPU1U3CDog3RBKdd5wu9LFQZk=
|
||||
</data>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
6/OCq92BIQnGHBLmlGX4nUNnfLM7LzPoMp+lPlYY4ew=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Headers/SDL_vulkan.h</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
eLdIezOR2pV1ai5rLBrtiR3NAok=
|
||||
</data>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
iCB8avj2P0+ZkjVGfTchu5BAd7BJ+LeC1fJ9BU+80IE=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Headers/begin_code.h</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
6RX1yuMtg6N9G2iCtCjjKzPCkuU=
|
||||
</data>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
JQ71zTwAp3EzI22aBP3w80YYEcxNBRF8/0DkqO39oDo=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Headers/close_code.h</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
IDKa63p9RAIkSpPXA0mU/dzgBWQ=
|
||||
</data>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
oF0I0dcQDvLcuEIgqx9wEQiuqHR5KLoq1zhL/AK5geg=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Resources/Info.plist</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
dts8ape5zBg3+8u8BQ5kWqp9cC8=
|
||||
</data>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
ZCgx1szeVwObsPiq6VoZh8Q9ym7l+7WXzv0HTSoFT0U=
|
||||
</data>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>rules</key>
|
||||
<dict>
|
||||
<key>^Resources/</key>
|
||||
<true/>
|
||||
<key>^Resources/.*\.lproj/</key>
|
||||
<dict>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>1000</real>
|
||||
</dict>
|
||||
<key>^Resources/.*\.lproj/locversion.plist$</key>
|
||||
<dict>
|
||||
<key>omit</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>1100</real>
|
||||
</dict>
|
||||
<key>^Resources/Base\.lproj/</key>
|
||||
<dict>
|
||||
<key>weight</key>
|
||||
<real>1010</real>
|
||||
</dict>
|
||||
<key>^version.plist$</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>rules2</key>
|
||||
<dict>
|
||||
<key>.*\.dSYM($|/)</key>
|
||||
<dict>
|
||||
<key>weight</key>
|
||||
<real>11</real>
|
||||
</dict>
|
||||
<key>^(.*/)?\.DS_Store$</key>
|
||||
<dict>
|
||||
<key>omit</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>2000</real>
|
||||
</dict>
|
||||
<key>^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/</key>
|
||||
<dict>
|
||||
<key>nested</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>10</real>
|
||||
</dict>
|
||||
<key>^.*</key>
|
||||
<true/>
|
||||
<key>^Info\.plist$</key>
|
||||
<dict>
|
||||
<key>omit</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>20</real>
|
||||
</dict>
|
||||
<key>^PkgInfo$</key>
|
||||
<dict>
|
||||
<key>omit</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>20</real>
|
||||
</dict>
|
||||
<key>^Resources/</key>
|
||||
<dict>
|
||||
<key>weight</key>
|
||||
<real>20</real>
|
||||
</dict>
|
||||
<key>^Resources/.*\.lproj/</key>
|
||||
<dict>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>1000</real>
|
||||
</dict>
|
||||
<key>^Resources/.*\.lproj/locversion.plist$</key>
|
||||
<dict>
|
||||
<key>omit</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>1100</real>
|
||||
</dict>
|
||||
<key>^Resources/Base\.lproj/</key>
|
||||
<dict>
|
||||
<key>weight</key>
|
||||
<real>1010</real>
|
||||
</dict>
|
||||
<key>^[^/]+$</key>
|
||||
<dict>
|
||||
<key>nested</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>10</real>
|
||||
</dict>
|
||||
<key>^embedded\.provisionprofile$</key>
|
||||
<dict>
|
||||
<key>weight</key>
|
||||
<real>20</real>
|
||||
</dict>
|
||||
<key>^version\.plist$</key>
|
||||
<dict>
|
||||
<key>weight</key>
|
||||
<real>20</real>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -1 +0,0 @@
|
||||
A
|
||||
@@ -0,0 +1,514 @@
|
||||
/*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef AVDEVICE_AVDEVICE_H
|
||||
#define AVDEVICE_AVDEVICE_H
|
||||
|
||||
#include "version.h"
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @ingroup lavd
|
||||
* Main libavdevice API header
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup lavd libavdevice
|
||||
* Special devices muxing/demuxing library.
|
||||
*
|
||||
* Libavdevice is a complementary library to @ref libavf "libavformat". It
|
||||
* provides various "special" platform-specific muxers and demuxers, e.g. for
|
||||
* grabbing devices, audio capture and playback etc. As a consequence, the
|
||||
* (de)muxers in libavdevice are of the AVFMT_NOFILE type (they use their own
|
||||
* I/O functions). The filename passed to avformat_open_input() often does not
|
||||
* refer to an actually existing file, but has some special device-specific
|
||||
* meaning - e.g. for xcbgrab it is the display name.
|
||||
*
|
||||
* To use libavdevice, simply call avdevice_register_all() to register all
|
||||
* compiled muxers and demuxers. They all use standard libavformat API.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "libavutil/log.h"
|
||||
#include "libavutil/opt.h"
|
||||
#include "libavutil/dict.h"
|
||||
#include "libavformat/avformat.h"
|
||||
|
||||
/**
|
||||
* Return the LIBAVDEVICE_VERSION_INT constant.
|
||||
*/
|
||||
unsigned avdevice_version(void);
|
||||
|
||||
/**
|
||||
* Return the libavdevice build-time configuration.
|
||||
*/
|
||||
const char *avdevice_configuration(void);
|
||||
|
||||
/**
|
||||
* Return the libavdevice license.
|
||||
*/
|
||||
const char *avdevice_license(void);
|
||||
|
||||
/**
|
||||
* Initialize libavdevice and register all the input and output devices.
|
||||
*/
|
||||
void avdevice_register_all(void);
|
||||
|
||||
/**
|
||||
* Audio input devices iterator.
|
||||
*
|
||||
* If d is NULL, returns the first registered input audio/video device,
|
||||
* if d is non-NULL, returns the next registered input audio/video device after d
|
||||
* or NULL if d is the last one.
|
||||
*/
|
||||
AVInputFormat *av_input_audio_device_next(AVInputFormat *d);
|
||||
|
||||
/**
|
||||
* Video input devices iterator.
|
||||
*
|
||||
* If d is NULL, returns the first registered input audio/video device,
|
||||
* if d is non-NULL, returns the next registered input audio/video device after d
|
||||
* or NULL if d is the last one.
|
||||
*/
|
||||
AVInputFormat *av_input_video_device_next(AVInputFormat *d);
|
||||
|
||||
/**
|
||||
* Audio output devices iterator.
|
||||
*
|
||||
* If d is NULL, returns the first registered output audio/video device,
|
||||
* if d is non-NULL, returns the next registered output audio/video device after d
|
||||
* or NULL if d is the last one.
|
||||
*/
|
||||
AVOutputFormat *av_output_audio_device_next(AVOutputFormat *d);
|
||||
|
||||
/**
|
||||
* Video output devices iterator.
|
||||
*
|
||||
* If d is NULL, returns the first registered output audio/video device,
|
||||
* if d is non-NULL, returns the next registered output audio/video device after d
|
||||
* or NULL if d is the last one.
|
||||
*/
|
||||
AVOutputFormat *av_output_video_device_next(AVOutputFormat *d);
|
||||
|
||||
typedef struct AVDeviceRect {
|
||||
int x; /**< x coordinate of top left corner */
|
||||
int y; /**< y coordinate of top left corner */
|
||||
int width; /**< width */
|
||||
int height; /**< height */
|
||||
} AVDeviceRect;
|
||||
|
||||
/**
|
||||
* Message types used by avdevice_app_to_dev_control_message().
|
||||
*/
|
||||
enum AVAppToDevMessageType {
|
||||
/**
|
||||
* Dummy message.
|
||||
*/
|
||||
AV_APP_TO_DEV_NONE = MKBETAG('N','O','N','E'),
|
||||
|
||||
/**
|
||||
* Window size change message.
|
||||
*
|
||||
* Message is sent to the device every time the application changes the size
|
||||
* of the window device renders to.
|
||||
* Message should also be sent right after window is created.
|
||||
*
|
||||
* data: AVDeviceRect: new window size.
|
||||
*/
|
||||
AV_APP_TO_DEV_WINDOW_SIZE = MKBETAG('G','E','O','M'),
|
||||
|
||||
/**
|
||||
* Repaint request message.
|
||||
*
|
||||
* Message is sent to the device when window has to be repainted.
|
||||
*
|
||||
* data: AVDeviceRect: area required to be repainted.
|
||||
* NULL: whole area is required to be repainted.
|
||||
*/
|
||||
AV_APP_TO_DEV_WINDOW_REPAINT = MKBETAG('R','E','P','A'),
|
||||
|
||||
/**
|
||||
* Request pause/play.
|
||||
*
|
||||
* Application requests pause/unpause playback.
|
||||
* Mostly usable with devices that have internal buffer.
|
||||
* By default devices are not paused.
|
||||
*
|
||||
* data: NULL
|
||||
*/
|
||||
AV_APP_TO_DEV_PAUSE = MKBETAG('P', 'A', 'U', ' '),
|
||||
AV_APP_TO_DEV_PLAY = MKBETAG('P', 'L', 'A', 'Y'),
|
||||
AV_APP_TO_DEV_TOGGLE_PAUSE = MKBETAG('P', 'A', 'U', 'T'),
|
||||
|
||||
/**
|
||||
* Volume control message.
|
||||
*
|
||||
* Set volume level. It may be device-dependent if volume
|
||||
* is changed per stream or system wide. Per stream volume
|
||||
* change is expected when possible.
|
||||
*
|
||||
* data: double: new volume with range of 0.0 - 1.0.
|
||||
*/
|
||||
AV_APP_TO_DEV_SET_VOLUME = MKBETAG('S', 'V', 'O', 'L'),
|
||||
|
||||
/**
|
||||
* Mute control messages.
|
||||
*
|
||||
* Change mute state. It may be device-dependent if mute status
|
||||
* is changed per stream or system wide. Per stream mute status
|
||||
* change is expected when possible.
|
||||
*
|
||||
* data: NULL.
|
||||
*/
|
||||
AV_APP_TO_DEV_MUTE = MKBETAG(' ', 'M', 'U', 'T'),
|
||||
AV_APP_TO_DEV_UNMUTE = MKBETAG('U', 'M', 'U', 'T'),
|
||||
AV_APP_TO_DEV_TOGGLE_MUTE = MKBETAG('T', 'M', 'U', 'T'),
|
||||
|
||||
/**
|
||||
* Get volume/mute messages.
|
||||
*
|
||||
* Force the device to send AV_DEV_TO_APP_VOLUME_LEVEL_CHANGED or
|
||||
* AV_DEV_TO_APP_MUTE_STATE_CHANGED command respectively.
|
||||
*
|
||||
* data: NULL.
|
||||
*/
|
||||
AV_APP_TO_DEV_GET_VOLUME = MKBETAG('G', 'V', 'O', 'L'),
|
||||
AV_APP_TO_DEV_GET_MUTE = MKBETAG('G', 'M', 'U', 'T'),
|
||||
};
|
||||
|
||||
/**
|
||||
* Message types used by avdevice_dev_to_app_control_message().
|
||||
*/
|
||||
enum AVDevToAppMessageType {
|
||||
/**
|
||||
* Dummy message.
|
||||
*/
|
||||
AV_DEV_TO_APP_NONE = MKBETAG('N','O','N','E'),
|
||||
|
||||
/**
|
||||
* Create window buffer message.
|
||||
*
|
||||
* Device requests to create a window buffer. Exact meaning is device-
|
||||
* and application-dependent. Message is sent before rendering first
|
||||
* frame and all one-shot initializations should be done here.
|
||||
* Application is allowed to ignore preferred window buffer size.
|
||||
*
|
||||
* @note: Application is obligated to inform about window buffer size
|
||||
* with AV_APP_TO_DEV_WINDOW_SIZE message.
|
||||
*
|
||||
* data: AVDeviceRect: preferred size of the window buffer.
|
||||
* NULL: no preferred size of the window buffer.
|
||||
*/
|
||||
AV_DEV_TO_APP_CREATE_WINDOW_BUFFER = MKBETAG('B','C','R','E'),
|
||||
|
||||
/**
|
||||
* Prepare window buffer message.
|
||||
*
|
||||
* Device requests to prepare a window buffer for rendering.
|
||||
* Exact meaning is device- and application-dependent.
|
||||
* Message is sent before rendering of each frame.
|
||||
*
|
||||
* data: NULL.
|
||||
*/
|
||||
AV_DEV_TO_APP_PREPARE_WINDOW_BUFFER = MKBETAG('B','P','R','E'),
|
||||
|
||||
/**
|
||||
* Display window buffer message.
|
||||
*
|
||||
* Device requests to display a window buffer.
|
||||
* Message is sent when new frame is ready to be displayed.
|
||||
* Usually buffers need to be swapped in handler of this message.
|
||||
*
|
||||
* data: NULL.
|
||||
*/
|
||||
AV_DEV_TO_APP_DISPLAY_WINDOW_BUFFER = MKBETAG('B','D','I','S'),
|
||||
|
||||
/**
|
||||
* Destroy window buffer message.
|
||||
*
|
||||
* Device requests to destroy a window buffer.
|
||||
* Message is sent when device is about to be destroyed and window
|
||||
* buffer is not required anymore.
|
||||
*
|
||||
* data: NULL.
|
||||
*/
|
||||
AV_DEV_TO_APP_DESTROY_WINDOW_BUFFER = MKBETAG('B','D','E','S'),
|
||||
|
||||
/**
|
||||
* Buffer fullness status messages.
|
||||
*
|
||||
* Device signals buffer overflow/underflow.
|
||||
*
|
||||
* data: NULL.
|
||||
*/
|
||||
AV_DEV_TO_APP_BUFFER_OVERFLOW = MKBETAG('B','O','F','L'),
|
||||
AV_DEV_TO_APP_BUFFER_UNDERFLOW = MKBETAG('B','U','F','L'),
|
||||
|
||||
/**
|
||||
* Buffer readable/writable.
|
||||
*
|
||||
* Device informs that buffer is readable/writable.
|
||||
* When possible, device informs how many bytes can be read/write.
|
||||
*
|
||||
* @warning Device may not inform when number of bytes than can be read/write changes.
|
||||
*
|
||||
* data: int64_t: amount of bytes available to read/write.
|
||||
* NULL: amount of bytes available to read/write is not known.
|
||||
*/
|
||||
AV_DEV_TO_APP_BUFFER_READABLE = MKBETAG('B','R','D',' '),
|
||||
AV_DEV_TO_APP_BUFFER_WRITABLE = MKBETAG('B','W','R',' '),
|
||||
|
||||
/**
|
||||
* Mute state change message.
|
||||
*
|
||||
* Device informs that mute state has changed.
|
||||
*
|
||||
* data: int: 0 for not muted state, non-zero for muted state.
|
||||
*/
|
||||
AV_DEV_TO_APP_MUTE_STATE_CHANGED = MKBETAG('C','M','U','T'),
|
||||
|
||||
/**
|
||||
* Volume level change message.
|
||||
*
|
||||
* Device informs that volume level has changed.
|
||||
*
|
||||
* data: double: new volume with range of 0.0 - 1.0.
|
||||
*/
|
||||
AV_DEV_TO_APP_VOLUME_LEVEL_CHANGED = MKBETAG('C','V','O','L'),
|
||||
};
|
||||
|
||||
/**
|
||||
* Send control message from application to device.
|
||||
*
|
||||
* @param s device context.
|
||||
* @param type message type.
|
||||
* @param data message data. Exact type depends on message type.
|
||||
* @param data_size size of message data.
|
||||
* @return >= 0 on success, negative on error.
|
||||
* AVERROR(ENOSYS) when device doesn't implement handler of the message.
|
||||
*/
|
||||
int avdevice_app_to_dev_control_message(struct AVFormatContext *s,
|
||||
enum AVAppToDevMessageType type,
|
||||
void *data, size_t data_size);
|
||||
|
||||
/**
|
||||
* Send control message from device to application.
|
||||
*
|
||||
* @param s device context.
|
||||
* @param type message type.
|
||||
* @param data message data. Can be NULL.
|
||||
* @param data_size size of message data.
|
||||
* @return >= 0 on success, negative on error.
|
||||
* AVERROR(ENOSYS) when application doesn't implement handler of the message.
|
||||
*/
|
||||
int avdevice_dev_to_app_control_message(struct AVFormatContext *s,
|
||||
enum AVDevToAppMessageType type,
|
||||
void *data, size_t data_size);
|
||||
|
||||
/**
|
||||
* Following API allows user to probe device capabilities (supported codecs,
|
||||
* pixel formats, sample formats, resolutions, channel counts, etc).
|
||||
* It is build on top op AVOption API.
|
||||
* Queried capabilities make it possible to set up converters of video or audio
|
||||
* parameters that fit to the device.
|
||||
*
|
||||
* List of capabilities that can be queried:
|
||||
* - Capabilities valid for both audio and video devices:
|
||||
* - codec: supported audio/video codecs.
|
||||
* type: AV_OPT_TYPE_INT (AVCodecID value)
|
||||
* - Capabilities valid for audio devices:
|
||||
* - sample_format: supported sample formats.
|
||||
* type: AV_OPT_TYPE_INT (AVSampleFormat value)
|
||||
* - sample_rate: supported sample rates.
|
||||
* type: AV_OPT_TYPE_INT
|
||||
* - channels: supported number of channels.
|
||||
* type: AV_OPT_TYPE_INT
|
||||
* - channel_layout: supported channel layouts.
|
||||
* type: AV_OPT_TYPE_INT64
|
||||
* - Capabilities valid for video devices:
|
||||
* - pixel_format: supported pixel formats.
|
||||
* type: AV_OPT_TYPE_INT (AVPixelFormat value)
|
||||
* - window_size: supported window sizes (describes size of the window size presented to the user).
|
||||
* type: AV_OPT_TYPE_IMAGE_SIZE
|
||||
* - frame_size: supported frame sizes (describes size of provided video frames).
|
||||
* type: AV_OPT_TYPE_IMAGE_SIZE
|
||||
* - fps: supported fps values
|
||||
* type: AV_OPT_TYPE_RATIONAL
|
||||
*
|
||||
* Value of the capability may be set by user using av_opt_set() function
|
||||
* and AVDeviceCapabilitiesQuery object. Following queries will
|
||||
* limit results to the values matching already set capabilities.
|
||||
* For example, setting a codec may impact number of formats or fps values
|
||||
* returned during next query. Setting invalid value may limit results to zero.
|
||||
*
|
||||
* Example of the usage basing on opengl output device:
|
||||
*
|
||||
* @code
|
||||
* AVFormatContext *oc = NULL;
|
||||
* AVDeviceCapabilitiesQuery *caps = NULL;
|
||||
* AVOptionRanges *ranges;
|
||||
* int ret;
|
||||
*
|
||||
* if ((ret = avformat_alloc_output_context2(&oc, NULL, "opengl", NULL)) < 0)
|
||||
* goto fail;
|
||||
* if (avdevice_capabilities_create(&caps, oc, NULL) < 0)
|
||||
* goto fail;
|
||||
*
|
||||
* //query codecs
|
||||
* if (av_opt_query_ranges(&ranges, caps, "codec", AV_OPT_MULTI_COMPONENT_RANGE)) < 0)
|
||||
* goto fail;
|
||||
* //pick codec here and set it
|
||||
* av_opt_set(caps, "codec", AV_CODEC_ID_RAWVIDEO, 0);
|
||||
*
|
||||
* //query format
|
||||
* if (av_opt_query_ranges(&ranges, caps, "pixel_format", AV_OPT_MULTI_COMPONENT_RANGE)) < 0)
|
||||
* goto fail;
|
||||
* //pick format here and set it
|
||||
* av_opt_set(caps, "pixel_format", AV_PIX_FMT_YUV420P, 0);
|
||||
*
|
||||
* //query and set more capabilities
|
||||
*
|
||||
* fail:
|
||||
* //clean up code
|
||||
* avdevice_capabilities_free(&query, oc);
|
||||
* avformat_free_context(oc);
|
||||
* @endcode
|
||||
*/
|
||||
|
||||
/**
|
||||
* Structure describes device capabilities.
|
||||
*
|
||||
* It is used by devices in conjunction with av_device_capabilities AVOption table
|
||||
* to implement capabilities probing API based on AVOption API. Should not be used directly.
|
||||
*/
|
||||
typedef struct AVDeviceCapabilitiesQuery {
|
||||
const AVClass *av_class;
|
||||
AVFormatContext *device_context;
|
||||
enum AVCodecID codec;
|
||||
enum AVSampleFormat sample_format;
|
||||
enum AVPixelFormat pixel_format;
|
||||
int sample_rate;
|
||||
int channels;
|
||||
int64_t channel_layout;
|
||||
int window_width;
|
||||
int window_height;
|
||||
int frame_width;
|
||||
int frame_height;
|
||||
AVRational fps;
|
||||
} AVDeviceCapabilitiesQuery;
|
||||
|
||||
/**
|
||||
* AVOption table used by devices to implement device capabilities API. Should not be used by a user.
|
||||
*/
|
||||
extern const AVOption av_device_capabilities[];
|
||||
|
||||
/**
|
||||
* Initialize capabilities probing API based on AVOption API.
|
||||
*
|
||||
* avdevice_capabilities_free() must be called when query capabilities API is
|
||||
* not used anymore.
|
||||
*
|
||||
* @param[out] caps Device capabilities data. Pointer to a NULL pointer must be passed.
|
||||
* @param s Context of the device.
|
||||
* @param device_options An AVDictionary filled with device-private options.
|
||||
* On return this parameter will be destroyed and replaced with a dict
|
||||
* containing options that were not found. May be NULL.
|
||||
* The same options must be passed later to avformat_write_header() for output
|
||||
* devices or avformat_open_input() for input devices, or at any other place
|
||||
* that affects device-private options.
|
||||
*
|
||||
* @return >= 0 on success, negative otherwise.
|
||||
*/
|
||||
int avdevice_capabilities_create(AVDeviceCapabilitiesQuery **caps, AVFormatContext *s,
|
||||
AVDictionary **device_options);
|
||||
|
||||
/**
|
||||
* Free resources created by avdevice_capabilities_create()
|
||||
*
|
||||
* @param caps Device capabilities data to be freed.
|
||||
* @param s Context of the device.
|
||||
*/
|
||||
void avdevice_capabilities_free(AVDeviceCapabilitiesQuery **caps, AVFormatContext *s);
|
||||
|
||||
/**
|
||||
* Structure describes basic parameters of the device.
|
||||
*/
|
||||
typedef struct AVDeviceInfo {
|
||||
char *device_name; /**< device name, format depends on device */
|
||||
char *device_description; /**< human friendly name */
|
||||
} AVDeviceInfo;
|
||||
|
||||
/**
|
||||
* List of devices.
|
||||
*/
|
||||
typedef struct AVDeviceInfoList {
|
||||
AVDeviceInfo **devices; /**< list of autodetected devices */
|
||||
int nb_devices; /**< number of autodetected devices */
|
||||
int default_device; /**< index of default device or -1 if no default */
|
||||
} AVDeviceInfoList;
|
||||
|
||||
/**
|
||||
* List devices.
|
||||
*
|
||||
* Returns available device names and their parameters.
|
||||
*
|
||||
* @note: Some devices may accept system-dependent device names that cannot be
|
||||
* autodetected. The list returned by this function cannot be assumed to
|
||||
* be always completed.
|
||||
*
|
||||
* @param s device context.
|
||||
* @param[out] device_list list of autodetected devices.
|
||||
* @return count of autodetected devices, negative on error.
|
||||
*/
|
||||
int avdevice_list_devices(struct AVFormatContext *s, AVDeviceInfoList **device_list);
|
||||
|
||||
/**
|
||||
* Convenient function to free result of avdevice_list_devices().
|
||||
*
|
||||
* @param devices device list to be freed.
|
||||
*/
|
||||
void avdevice_free_list_devices(AVDeviceInfoList **device_list);
|
||||
|
||||
/**
|
||||
* List devices.
|
||||
*
|
||||
* Returns available device names and their parameters.
|
||||
* These are convinient wrappers for avdevice_list_devices().
|
||||
* Device context is allocated and deallocated internally.
|
||||
*
|
||||
* @param device device format. May be NULL if device name is set.
|
||||
* @param device_name device name. May be NULL if device format is set.
|
||||
* @param device_options An AVDictionary filled with device-private options. May be NULL.
|
||||
* The same options must be passed later to avformat_write_header() for output
|
||||
* devices or avformat_open_input() for input devices, or at any other place
|
||||
* that affects device-private options.
|
||||
* @param[out] device_list list of autodetected devices
|
||||
* @return count of autodetected devices, negative on error.
|
||||
* @note device argument takes precedence over device_name when both are set.
|
||||
*/
|
||||
int avdevice_list_input_sources(struct AVInputFormat *device, const char *device_name,
|
||||
AVDictionary *device_options, AVDeviceInfoList **device_list);
|
||||
int avdevice_list_output_sinks(struct AVOutputFormat *device, const char *device_name,
|
||||
AVDictionary *device_options, AVDeviceInfoList **device_list);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* AVDEVICE_AVDEVICE_H */
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef AVDEVICE_VERSION_H
|
||||
#define AVDEVICE_VERSION_H
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @ingroup lavd
|
||||
* Libavdevice version macros
|
||||
*/
|
||||
|
||||
#include "libavutil/version.h"
|
||||
|
||||
#define LIBAVDEVICE_VERSION_MAJOR 58
|
||||
#define LIBAVDEVICE_VERSION_MINOR 4
|
||||
#define LIBAVDEVICE_VERSION_MICRO 101
|
||||
|
||||
#define LIBAVDEVICE_VERSION_INT AV_VERSION_INT(LIBAVDEVICE_VERSION_MAJOR, \
|
||||
LIBAVDEVICE_VERSION_MINOR, \
|
||||
LIBAVDEVICE_VERSION_MICRO)
|
||||
#define LIBAVDEVICE_VERSION AV_VERSION(LIBAVDEVICE_VERSION_MAJOR, \
|
||||
LIBAVDEVICE_VERSION_MINOR, \
|
||||
LIBAVDEVICE_VERSION_MICRO)
|
||||
#define LIBAVDEVICE_BUILD LIBAVDEVICE_VERSION_INT
|
||||
|
||||
#define LIBAVDEVICE_IDENT "Lavd" AV_STRINGIFY(LIBAVDEVICE_VERSION)
|
||||
|
||||
/**
|
||||
* FF_API_* defines may be placed below to indicate public API that will be
|
||||
* dropped at a future version bump. The defines themselves are not part of
|
||||
* the public API and may change, break or disappear at any time.
|
||||
*/
|
||||
|
||||
#endif /* AVDEVICE_VERSION_H */
|
||||
@@ -0,0 +1,1168 @@
|
||||
/*
|
||||
* filter layer
|
||||
* Copyright (c) 2007 Bobby Bingham
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef AVFILTER_AVFILTER_H
|
||||
#define AVFILTER_AVFILTER_H
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @ingroup lavfi
|
||||
* Main libavfilter public API header
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup lavfi libavfilter
|
||||
* Graph-based frame editing library.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "libavutil/attributes.h"
|
||||
#include "libavutil/avutil.h"
|
||||
#include "libavutil/buffer.h"
|
||||
#include "libavutil/dict.h"
|
||||
#include "libavutil/frame.h"
|
||||
#include "libavutil/log.h"
|
||||
#include "libavutil/samplefmt.h"
|
||||
#include "libavutil/pixfmt.h"
|
||||
#include "libavutil/rational.h"
|
||||
|
||||
#include "libavfilter/version.h"
|
||||
|
||||
/**
|
||||
* Return the LIBAVFILTER_VERSION_INT constant.
|
||||
*/
|
||||
unsigned avfilter_version(void);
|
||||
|
||||
/**
|
||||
* Return the libavfilter build-time configuration.
|
||||
*/
|
||||
const char *avfilter_configuration(void);
|
||||
|
||||
/**
|
||||
* Return the libavfilter license.
|
||||
*/
|
||||
const char *avfilter_license(void);
|
||||
|
||||
typedef struct AVFilterContext AVFilterContext;
|
||||
typedef struct AVFilterLink AVFilterLink;
|
||||
typedef struct AVFilterPad AVFilterPad;
|
||||
typedef struct AVFilterFormats AVFilterFormats;
|
||||
|
||||
/**
|
||||
* Get the number of elements in a NULL-terminated array of AVFilterPads (e.g.
|
||||
* AVFilter.inputs/outputs).
|
||||
*/
|
||||
int avfilter_pad_count(const AVFilterPad *pads);
|
||||
|
||||
/**
|
||||
* Get the name of an AVFilterPad.
|
||||
*
|
||||
* @param pads an array of AVFilterPads
|
||||
* @param pad_idx index of the pad in the array it; is the caller's
|
||||
* responsibility to ensure the index is valid
|
||||
*
|
||||
* @return name of the pad_idx'th pad in pads
|
||||
*/
|
||||
const char *avfilter_pad_get_name(const AVFilterPad *pads, int pad_idx);
|
||||
|
||||
/**
|
||||
* Get the type of an AVFilterPad.
|
||||
*
|
||||
* @param pads an array of AVFilterPads
|
||||
* @param pad_idx index of the pad in the array; it is the caller's
|
||||
* responsibility to ensure the index is valid
|
||||
*
|
||||
* @return type of the pad_idx'th pad in pads
|
||||
*/
|
||||
enum AVMediaType avfilter_pad_get_type(const AVFilterPad *pads, int pad_idx);
|
||||
|
||||
/**
|
||||
* The number of the filter inputs is not determined just by AVFilter.inputs.
|
||||
* The filter might add additional inputs during initialization depending on the
|
||||
* options supplied to it.
|
||||
*/
|
||||
#define AVFILTER_FLAG_DYNAMIC_INPUTS (1 << 0)
|
||||
/**
|
||||
* The number of the filter outputs is not determined just by AVFilter.outputs.
|
||||
* The filter might add additional outputs during initialization depending on
|
||||
* the options supplied to it.
|
||||
*/
|
||||
#define AVFILTER_FLAG_DYNAMIC_OUTPUTS (1 << 1)
|
||||
/**
|
||||
* The filter supports multithreading by splitting frames into multiple parts
|
||||
* and processing them concurrently.
|
||||
*/
|
||||
#define AVFILTER_FLAG_SLICE_THREADS (1 << 2)
|
||||
/**
|
||||
* Some filters support a generic "enable" expression option that can be used
|
||||
* to enable or disable a filter in the timeline. Filters supporting this
|
||||
* option have this flag set. When the enable expression is false, the default
|
||||
* no-op filter_frame() function is called in place of the filter_frame()
|
||||
* callback defined on each input pad, thus the frame is passed unchanged to
|
||||
* the next filters.
|
||||
*/
|
||||
#define AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC (1 << 16)
|
||||
/**
|
||||
* Same as AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, except that the filter will
|
||||
* have its filter_frame() callback(s) called as usual even when the enable
|
||||
* expression is false. The filter will disable filtering within the
|
||||
* filter_frame() callback(s) itself, for example executing code depending on
|
||||
* the AVFilterContext->is_disabled value.
|
||||
*/
|
||||
#define AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL (1 << 17)
|
||||
/**
|
||||
* Handy mask to test whether the filter supports or no the timeline feature
|
||||
* (internally or generically).
|
||||
*/
|
||||
#define AVFILTER_FLAG_SUPPORT_TIMELINE (AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL)
|
||||
|
||||
/**
|
||||
* Filter definition. This defines the pads a filter contains, and all the
|
||||
* callback functions used to interact with the filter.
|
||||
*/
|
||||
typedef struct AVFilter {
|
||||
/**
|
||||
* Filter name. Must be non-NULL and unique among filters.
|
||||
*/
|
||||
const char *name;
|
||||
|
||||
/**
|
||||
* A description of the filter. May be NULL.
|
||||
*
|
||||
* You should use the NULL_IF_CONFIG_SMALL() macro to define it.
|
||||
*/
|
||||
const char *description;
|
||||
|
||||
/**
|
||||
* List of inputs, terminated by a zeroed element.
|
||||
*
|
||||
* NULL if there are no (static) inputs. Instances of filters with
|
||||
* AVFILTER_FLAG_DYNAMIC_INPUTS set may have more inputs than present in
|
||||
* this list.
|
||||
*/
|
||||
const AVFilterPad *inputs;
|
||||
/**
|
||||
* List of outputs, terminated by a zeroed element.
|
||||
*
|
||||
* NULL if there are no (static) outputs. Instances of filters with
|
||||
* AVFILTER_FLAG_DYNAMIC_OUTPUTS set may have more outputs than present in
|
||||
* this list.
|
||||
*/
|
||||
const AVFilterPad *outputs;
|
||||
|
||||
/**
|
||||
* A class for the private data, used to declare filter private AVOptions.
|
||||
* This field is NULL for filters that do not declare any options.
|
||||
*
|
||||
* If this field is non-NULL, the first member of the filter private data
|
||||
* must be a pointer to AVClass, which will be set by libavfilter generic
|
||||
* code to this class.
|
||||
*/
|
||||
const AVClass *priv_class;
|
||||
|
||||
/**
|
||||
* A combination of AVFILTER_FLAG_*
|
||||
*/
|
||||
int flags;
|
||||
|
||||
/*****************************************************************
|
||||
* All fields below this line are not part of the public API. They
|
||||
* may not be used outside of libavfilter and can be changed and
|
||||
* removed at will.
|
||||
* New public fields should be added right above.
|
||||
*****************************************************************
|
||||
*/
|
||||
|
||||
/**
|
||||
* Filter pre-initialization function
|
||||
*
|
||||
* This callback will be called immediately after the filter context is
|
||||
* allocated, to allow allocating and initing sub-objects.
|
||||
*
|
||||
* If this callback is not NULL, the uninit callback will be called on
|
||||
* allocation failure.
|
||||
*
|
||||
* @return 0 on success,
|
||||
* AVERROR code on failure (but the code will be
|
||||
* dropped and treated as ENOMEM by the calling code)
|
||||
*/
|
||||
int (*preinit)(AVFilterContext *ctx);
|
||||
|
||||
/**
|
||||
* Filter initialization function.
|
||||
*
|
||||
* This callback will be called only once during the filter lifetime, after
|
||||
* all the options have been set, but before links between filters are
|
||||
* established and format negotiation is done.
|
||||
*
|
||||
* Basic filter initialization should be done here. Filters with dynamic
|
||||
* inputs and/or outputs should create those inputs/outputs here based on
|
||||
* provided options. No more changes to this filter's inputs/outputs can be
|
||||
* done after this callback.
|
||||
*
|
||||
* This callback must not assume that the filter links exist or frame
|
||||
* parameters are known.
|
||||
*
|
||||
* @ref AVFilter.uninit "uninit" is guaranteed to be called even if
|
||||
* initialization fails, so this callback does not have to clean up on
|
||||
* failure.
|
||||
*
|
||||
* @return 0 on success, a negative AVERROR on failure
|
||||
*/
|
||||
int (*init)(AVFilterContext *ctx);
|
||||
|
||||
/**
|
||||
* Should be set instead of @ref AVFilter.init "init" by the filters that
|
||||
* want to pass a dictionary of AVOptions to nested contexts that are
|
||||
* allocated during init.
|
||||
*
|
||||
* On return, the options dict should be freed and replaced with one that
|
||||
* contains all the options which could not be processed by this filter (or
|
||||
* with NULL if all the options were processed).
|
||||
*
|
||||
* Otherwise the semantics is the same as for @ref AVFilter.init "init".
|
||||
*/
|
||||
int (*init_dict)(AVFilterContext *ctx, AVDictionary **options);
|
||||
|
||||
/**
|
||||
* Filter uninitialization function.
|
||||
*
|
||||
* Called only once right before the filter is freed. Should deallocate any
|
||||
* memory held by the filter, release any buffer references, etc. It does
|
||||
* not need to deallocate the AVFilterContext.priv memory itself.
|
||||
*
|
||||
* This callback may be called even if @ref AVFilter.init "init" was not
|
||||
* called or failed, so it must be prepared to handle such a situation.
|
||||
*/
|
||||
void (*uninit)(AVFilterContext *ctx);
|
||||
|
||||
/**
|
||||
* Query formats supported by the filter on its inputs and outputs.
|
||||
*
|
||||
* This callback is called after the filter is initialized (so the inputs
|
||||
* and outputs are fixed), shortly before the format negotiation. This
|
||||
* callback may be called more than once.
|
||||
*
|
||||
* This callback must set AVFilterLink.out_formats on every input link and
|
||||
* AVFilterLink.in_formats on every output link to a list of pixel/sample
|
||||
* formats that the filter supports on that link. For audio links, this
|
||||
* filter must also set @ref AVFilterLink.in_samplerates "in_samplerates" /
|
||||
* @ref AVFilterLink.out_samplerates "out_samplerates" and
|
||||
* @ref AVFilterLink.in_channel_layouts "in_channel_layouts" /
|
||||
* @ref AVFilterLink.out_channel_layouts "out_channel_layouts" analogously.
|
||||
*
|
||||
* This callback may be NULL for filters with one input, in which case
|
||||
* libavfilter assumes that it supports all input formats and preserves
|
||||
* them on output.
|
||||
*
|
||||
* @return zero on success, a negative value corresponding to an
|
||||
* AVERROR code otherwise
|
||||
*/
|
||||
int (*query_formats)(AVFilterContext *);
|
||||
|
||||
int priv_size; ///< size of private data to allocate for the filter
|
||||
|
||||
int flags_internal; ///< Additional flags for avfilter internal use only.
|
||||
|
||||
/**
|
||||
* Used by the filter registration system. Must not be touched by any other
|
||||
* code.
|
||||
*/
|
||||
struct AVFilter *next;
|
||||
|
||||
/**
|
||||
* Make the filter instance process a command.
|
||||
*
|
||||
* @param cmd the command to process, for handling simplicity all commands must be alphanumeric only
|
||||
* @param arg the argument for the command
|
||||
* @param res a buffer with size res_size where the filter(s) can return a response. This must not change when the command is not supported.
|
||||
* @param flags if AVFILTER_CMD_FLAG_FAST is set and the command would be
|
||||
* time consuming then a filter should treat it like an unsupported command
|
||||
*
|
||||
* @returns >=0 on success otherwise an error code.
|
||||
* AVERROR(ENOSYS) on unsupported commands
|
||||
*/
|
||||
int (*process_command)(AVFilterContext *, const char *cmd, const char *arg, char *res, int res_len, int flags);
|
||||
|
||||
/**
|
||||
* Filter initialization function, alternative to the init()
|
||||
* callback. Args contains the user-supplied parameters, opaque is
|
||||
* used for providing binary data.
|
||||
*/
|
||||
int (*init_opaque)(AVFilterContext *ctx, void *opaque);
|
||||
|
||||
/**
|
||||
* Filter activation function.
|
||||
*
|
||||
* Called when any processing is needed from the filter, instead of any
|
||||
* filter_frame and request_frame on pads.
|
||||
*
|
||||
* The function must examine inlinks and outlinks and perform a single
|
||||
* step of processing. If there is nothing to do, the function must do
|
||||
* nothing and not return an error. If more steps are or may be
|
||||
* possible, it must use ff_filter_set_ready() to schedule another
|
||||
* activation.
|
||||
*/
|
||||
int (*activate)(AVFilterContext *ctx);
|
||||
} AVFilter;
|
||||
|
||||
/**
|
||||
* Process multiple parts of the frame concurrently.
|
||||
*/
|
||||
#define AVFILTER_THREAD_SLICE (1 << 0)
|
||||
|
||||
typedef struct AVFilterInternal AVFilterInternal;
|
||||
|
||||
/** An instance of a filter */
|
||||
struct AVFilterContext {
|
||||
const AVClass *av_class; ///< needed for av_log() and filters common options
|
||||
|
||||
const AVFilter *filter; ///< the AVFilter of which this is an instance
|
||||
|
||||
char *name; ///< name of this filter instance
|
||||
|
||||
AVFilterPad *input_pads; ///< array of input pads
|
||||
AVFilterLink **inputs; ///< array of pointers to input links
|
||||
unsigned nb_inputs; ///< number of input pads
|
||||
|
||||
AVFilterPad *output_pads; ///< array of output pads
|
||||
AVFilterLink **outputs; ///< array of pointers to output links
|
||||
unsigned nb_outputs; ///< number of output pads
|
||||
|
||||
void *priv; ///< private data for use by the filter
|
||||
|
||||
struct AVFilterGraph *graph; ///< filtergraph this filter belongs to
|
||||
|
||||
/**
|
||||
* Type of multithreading being allowed/used. A combination of
|
||||
* AVFILTER_THREAD_* flags.
|
||||
*
|
||||
* May be set by the caller before initializing the filter to forbid some
|
||||
* or all kinds of multithreading for this filter. The default is allowing
|
||||
* everything.
|
||||
*
|
||||
* When the filter is initialized, this field is combined using bit AND with
|
||||
* AVFilterGraph.thread_type to get the final mask used for determining
|
||||
* allowed threading types. I.e. a threading type needs to be set in both
|
||||
* to be allowed.
|
||||
*
|
||||
* After the filter is initialized, libavfilter sets this field to the
|
||||
* threading type that is actually used (0 for no multithreading).
|
||||
*/
|
||||
int thread_type;
|
||||
|
||||
/**
|
||||
* An opaque struct for libavfilter internal use.
|
||||
*/
|
||||
AVFilterInternal *internal;
|
||||
|
||||
struct AVFilterCommand *command_queue;
|
||||
|
||||
char *enable_str; ///< enable expression string
|
||||
void *enable; ///< parsed expression (AVExpr*)
|
||||
double *var_values; ///< variable values for the enable expression
|
||||
int is_disabled; ///< the enabled state from the last expression evaluation
|
||||
|
||||
/**
|
||||
* For filters which will create hardware frames, sets the device the
|
||||
* filter should create them in. All other filters will ignore this field:
|
||||
* in particular, a filter which consumes or processes hardware frames will
|
||||
* instead use the hw_frames_ctx field in AVFilterLink to carry the
|
||||
* hardware context information.
|
||||
*/
|
||||
AVBufferRef *hw_device_ctx;
|
||||
|
||||
/**
|
||||
* Max number of threads allowed in this filter instance.
|
||||
* If <= 0, its value is ignored.
|
||||
* Overrides global number of threads set per filter graph.
|
||||
*/
|
||||
int nb_threads;
|
||||
|
||||
/**
|
||||
* Ready status of the filter.
|
||||
* A non-0 value means that the filter needs activating;
|
||||
* a higher value suggests a more urgent activation.
|
||||
*/
|
||||
unsigned ready;
|
||||
|
||||
/**
|
||||
* Sets the number of extra hardware frames which the filter will
|
||||
* allocate on its output links for use in following filters or by
|
||||
* the caller.
|
||||
*
|
||||
* Some hardware filters require all frames that they will use for
|
||||
* output to be defined in advance before filtering starts. For such
|
||||
* filters, any hardware frame pools used for output must therefore be
|
||||
* of fixed size. The extra frames set here are on top of any number
|
||||
* that the filter needs internally in order to operate normally.
|
||||
*
|
||||
* This field must be set before the graph containing this filter is
|
||||
* configured.
|
||||
*/
|
||||
int extra_hw_frames;
|
||||
};
|
||||
|
||||
/**
|
||||
* A link between two filters. This contains pointers to the source and
|
||||
* destination filters between which this link exists, and the indexes of
|
||||
* the pads involved. In addition, this link also contains the parameters
|
||||
* which have been negotiated and agreed upon between the filter, such as
|
||||
* image dimensions, format, etc.
|
||||
*
|
||||
* Applications must not normally access the link structure directly.
|
||||
* Use the buffersrc and buffersink API instead.
|
||||
* In the future, access to the header may be reserved for filters
|
||||
* implementation.
|
||||
*/
|
||||
struct AVFilterLink {
|
||||
AVFilterContext *src; ///< source filter
|
||||
AVFilterPad *srcpad; ///< output pad on the source filter
|
||||
|
||||
AVFilterContext *dst; ///< dest filter
|
||||
AVFilterPad *dstpad; ///< input pad on the dest filter
|
||||
|
||||
enum AVMediaType type; ///< filter media type
|
||||
|
||||
/* These parameters apply only to video */
|
||||
int w; ///< agreed upon image width
|
||||
int h; ///< agreed upon image height
|
||||
AVRational sample_aspect_ratio; ///< agreed upon sample aspect ratio
|
||||
/* These parameters apply only to audio */
|
||||
uint64_t channel_layout; ///< channel layout of current buffer (see libavutil/channel_layout.h)
|
||||
int sample_rate; ///< samples per second
|
||||
|
||||
int format; ///< agreed upon media format
|
||||
|
||||
/**
|
||||
* Define the time base used by the PTS of the frames/samples
|
||||
* which will pass through this link.
|
||||
* During the configuration stage, each filter is supposed to
|
||||
* change only the output timebase, while the timebase of the
|
||||
* input link is assumed to be an unchangeable property.
|
||||
*/
|
||||
AVRational time_base;
|
||||
|
||||
/*****************************************************************
|
||||
* All fields below this line are not part of the public API. They
|
||||
* may not be used outside of libavfilter and can be changed and
|
||||
* removed at will.
|
||||
* New public fields should be added right above.
|
||||
*****************************************************************
|
||||
*/
|
||||
/**
|
||||
* Lists of formats and channel layouts supported by the input and output
|
||||
* filters respectively. These lists are used for negotiating the format
|
||||
* to actually be used, which will be loaded into the format and
|
||||
* channel_layout members, above, when chosen.
|
||||
*
|
||||
*/
|
||||
AVFilterFormats *in_formats;
|
||||
AVFilterFormats *out_formats;
|
||||
|
||||
/**
|
||||
* Lists of channel layouts and sample rates used for automatic
|
||||
* negotiation.
|
||||
*/
|
||||
AVFilterFormats *in_samplerates;
|
||||
AVFilterFormats *out_samplerates;
|
||||
struct AVFilterChannelLayouts *in_channel_layouts;
|
||||
struct AVFilterChannelLayouts *out_channel_layouts;
|
||||
|
||||
/**
|
||||
* Audio only, the destination filter sets this to a non-zero value to
|
||||
* request that buffers with the given number of samples should be sent to
|
||||
* it. AVFilterPad.needs_fifo must also be set on the corresponding input
|
||||
* pad.
|
||||
* Last buffer before EOF will be padded with silence.
|
||||
*/
|
||||
int request_samples;
|
||||
|
||||
/** stage of the initialization of the link properties (dimensions, etc) */
|
||||
enum {
|
||||
AVLINK_UNINIT = 0, ///< not started
|
||||
AVLINK_STARTINIT, ///< started, but incomplete
|
||||
AVLINK_INIT ///< complete
|
||||
} init_state;
|
||||
|
||||
/**
|
||||
* Graph the filter belongs to.
|
||||
*/
|
||||
struct AVFilterGraph *graph;
|
||||
|
||||
/**
|
||||
* Current timestamp of the link, as defined by the most recent
|
||||
* frame(s), in link time_base units.
|
||||
*/
|
||||
int64_t current_pts;
|
||||
|
||||
/**
|
||||
* Current timestamp of the link, as defined by the most recent
|
||||
* frame(s), in AV_TIME_BASE units.
|
||||
*/
|
||||
int64_t current_pts_us;
|
||||
|
||||
/**
|
||||
* Index in the age array.
|
||||
*/
|
||||
int age_index;
|
||||
|
||||
/**
|
||||
* Frame rate of the stream on the link, or 1/0 if unknown or variable;
|
||||
* if left to 0/0, will be automatically copied from the first input
|
||||
* of the source filter if it exists.
|
||||
*
|
||||
* Sources should set it to the best estimation of the real frame rate.
|
||||
* If the source frame rate is unknown or variable, set this to 1/0.
|
||||
* Filters should update it if necessary depending on their function.
|
||||
* Sinks can use it to set a default output frame rate.
|
||||
* It is similar to the r_frame_rate field in AVStream.
|
||||
*/
|
||||
AVRational frame_rate;
|
||||
|
||||
/**
|
||||
* Buffer partially filled with samples to achieve a fixed/minimum size.
|
||||
*/
|
||||
AVFrame *partial_buf;
|
||||
|
||||
/**
|
||||
* Size of the partial buffer to allocate.
|
||||
* Must be between min_samples and max_samples.
|
||||
*/
|
||||
int partial_buf_size;
|
||||
|
||||
/**
|
||||
* Minimum number of samples to filter at once. If filter_frame() is
|
||||
* called with fewer samples, it will accumulate them in partial_buf.
|
||||
* This field and the related ones must not be changed after filtering
|
||||
* has started.
|
||||
* If 0, all related fields are ignored.
|
||||
*/
|
||||
int min_samples;
|
||||
|
||||
/**
|
||||
* Maximum number of samples to filter at once. If filter_frame() is
|
||||
* called with more samples, it will split them.
|
||||
*/
|
||||
int max_samples;
|
||||
|
||||
/**
|
||||
* Number of channels.
|
||||
*/
|
||||
int channels;
|
||||
|
||||
/**
|
||||
* Link processing flags.
|
||||
*/
|
||||
unsigned flags;
|
||||
|
||||
/**
|
||||
* Number of past frames sent through the link.
|
||||
*/
|
||||
int64_t frame_count_in, frame_count_out;
|
||||
|
||||
/**
|
||||
* A pointer to a FFFramePool struct.
|
||||
*/
|
||||
void *frame_pool;
|
||||
|
||||
/**
|
||||
* True if a frame is currently wanted on the output of this filter.
|
||||
* Set when ff_request_frame() is called by the output,
|
||||
* cleared when a frame is filtered.
|
||||
*/
|
||||
int frame_wanted_out;
|
||||
|
||||
/**
|
||||
* For hwaccel pixel formats, this should be a reference to the
|
||||
* AVHWFramesContext describing the frames.
|
||||
*/
|
||||
AVBufferRef *hw_frames_ctx;
|
||||
|
||||
#ifndef FF_INTERNAL_FIELDS
|
||||
|
||||
/**
|
||||
* Internal structure members.
|
||||
* The fields below this limit are internal for libavfilter's use
|
||||
* and must in no way be accessed by applications.
|
||||
*/
|
||||
char reserved[0xF000];
|
||||
|
||||
#else /* FF_INTERNAL_FIELDS */
|
||||
|
||||
/**
|
||||
* Queue of frames waiting to be filtered.
|
||||
*/
|
||||
FFFrameQueue fifo;
|
||||
|
||||
/**
|
||||
* If set, the source filter can not generate a frame as is.
|
||||
* The goal is to avoid repeatedly calling the request_frame() method on
|
||||
* the same link.
|
||||
*/
|
||||
int frame_blocked_in;
|
||||
|
||||
/**
|
||||
* Link input status.
|
||||
* If not zero, all attempts of filter_frame will fail with the
|
||||
* corresponding code.
|
||||
*/
|
||||
int status_in;
|
||||
|
||||
/**
|
||||
* Timestamp of the input status change.
|
||||
*/
|
||||
int64_t status_in_pts;
|
||||
|
||||
/**
|
||||
* Link output status.
|
||||
* If not zero, all attempts of request_frame will fail with the
|
||||
* corresponding code.
|
||||
*/
|
||||
int status_out;
|
||||
|
||||
#endif /* FF_INTERNAL_FIELDS */
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Link two filters together.
|
||||
*
|
||||
* @param src the source filter
|
||||
* @param srcpad index of the output pad on the source filter
|
||||
* @param dst the destination filter
|
||||
* @param dstpad index of the input pad on the destination filter
|
||||
* @return zero on success
|
||||
*/
|
||||
int avfilter_link(AVFilterContext *src, unsigned srcpad,
|
||||
AVFilterContext *dst, unsigned dstpad);
|
||||
|
||||
/**
|
||||
* Free the link in *link, and set its pointer to NULL.
|
||||
*/
|
||||
void avfilter_link_free(AVFilterLink **link);
|
||||
|
||||
#if FF_API_FILTER_GET_SET
|
||||
/**
|
||||
* Get the number of channels of a link.
|
||||
* @deprecated Use av_buffersink_get_channels()
|
||||
*/
|
||||
attribute_deprecated
|
||||
int avfilter_link_get_channels(AVFilterLink *link);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Set the closed field of a link.
|
||||
* @deprecated applications are not supposed to mess with links, they should
|
||||
* close the sinks.
|
||||
*/
|
||||
attribute_deprecated
|
||||
void avfilter_link_set_closed(AVFilterLink *link, int closed);
|
||||
|
||||
/**
|
||||
* Negotiate the media format, dimensions, etc of all inputs to a filter.
|
||||
*
|
||||
* @param filter the filter to negotiate the properties for its inputs
|
||||
* @return zero on successful negotiation
|
||||
*/
|
||||
int avfilter_config_links(AVFilterContext *filter);
|
||||
|
||||
#define AVFILTER_CMD_FLAG_ONE 1 ///< Stop once a filter understood the command (for target=all for example), fast filters are favored automatically
|
||||
#define AVFILTER_CMD_FLAG_FAST 2 ///< Only execute command when its fast (like a video out that supports contrast adjustment in hw)
|
||||
|
||||
/**
|
||||
* Make the filter instance process a command.
|
||||
* It is recommended to use avfilter_graph_send_command().
|
||||
*/
|
||||
int avfilter_process_command(AVFilterContext *filter, const char *cmd, const char *arg, char *res, int res_len, int flags);
|
||||
|
||||
/**
|
||||
* Iterate over all registered filters.
|
||||
*
|
||||
* @param opaque a pointer where libavfilter will store the iteration state. Must
|
||||
* point to NULL to start the iteration.
|
||||
*
|
||||
* @return the next registered filter or NULL when the iteration is
|
||||
* finished
|
||||
*/
|
||||
const AVFilter *av_filter_iterate(void **opaque);
|
||||
|
||||
#if FF_API_NEXT
|
||||
/** Initialize the filter system. Register all builtin filters. */
|
||||
attribute_deprecated
|
||||
void avfilter_register_all(void);
|
||||
|
||||
/**
|
||||
* Register a filter. This is only needed if you plan to use
|
||||
* avfilter_get_by_name later to lookup the AVFilter structure by name. A
|
||||
* filter can still by instantiated with avfilter_graph_alloc_filter even if it
|
||||
* is not registered.
|
||||
*
|
||||
* @param filter the filter to register
|
||||
* @return 0 if the registration was successful, a negative value
|
||||
* otherwise
|
||||
*/
|
||||
attribute_deprecated
|
||||
int avfilter_register(AVFilter *filter);
|
||||
|
||||
/**
|
||||
* Iterate over all registered filters.
|
||||
* @return If prev is non-NULL, next registered filter after prev or NULL if
|
||||
* prev is the last filter. If prev is NULL, return the first registered filter.
|
||||
*/
|
||||
attribute_deprecated
|
||||
const AVFilter *avfilter_next(const AVFilter *prev);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Get a filter definition matching the given name.
|
||||
*
|
||||
* @param name the filter name to find
|
||||
* @return the filter definition, if any matching one is registered.
|
||||
* NULL if none found.
|
||||
*/
|
||||
const AVFilter *avfilter_get_by_name(const char *name);
|
||||
|
||||
|
||||
/**
|
||||
* Initialize a filter with the supplied parameters.
|
||||
*
|
||||
* @param ctx uninitialized filter context to initialize
|
||||
* @param args Options to initialize the filter with. This must be a
|
||||
* ':'-separated list of options in the 'key=value' form.
|
||||
* May be NULL if the options have been set directly using the
|
||||
* AVOptions API or there are no options that need to be set.
|
||||
* @return 0 on success, a negative AVERROR on failure
|
||||
*/
|
||||
int avfilter_init_str(AVFilterContext *ctx, const char *args);
|
||||
|
||||
/**
|
||||
* Initialize a filter with the supplied dictionary of options.
|
||||
*
|
||||
* @param ctx uninitialized filter context to initialize
|
||||
* @param options An AVDictionary filled with options for this filter. On
|
||||
* return this parameter will be destroyed and replaced with
|
||||
* a dict containing options that were not found. This dictionary
|
||||
* must be freed by the caller.
|
||||
* May be NULL, then this function is equivalent to
|
||||
* avfilter_init_str() with the second parameter set to NULL.
|
||||
* @return 0 on success, a negative AVERROR on failure
|
||||
*
|
||||
* @note This function and avfilter_init_str() do essentially the same thing,
|
||||
* the difference is in manner in which the options are passed. It is up to the
|
||||
* calling code to choose whichever is more preferable. The two functions also
|
||||
* behave differently when some of the provided options are not declared as
|
||||
* supported by the filter. In such a case, avfilter_init_str() will fail, but
|
||||
* this function will leave those extra options in the options AVDictionary and
|
||||
* continue as usual.
|
||||
*/
|
||||
int avfilter_init_dict(AVFilterContext *ctx, AVDictionary **options);
|
||||
|
||||
/**
|
||||
* Free a filter context. This will also remove the filter from its
|
||||
* filtergraph's list of filters.
|
||||
*
|
||||
* @param filter the filter to free
|
||||
*/
|
||||
void avfilter_free(AVFilterContext *filter);
|
||||
|
||||
/**
|
||||
* Insert a filter in the middle of an existing link.
|
||||
*
|
||||
* @param link the link into which the filter should be inserted
|
||||
* @param filt the filter to be inserted
|
||||
* @param filt_srcpad_idx the input pad on the filter to connect
|
||||
* @param filt_dstpad_idx the output pad on the filter to connect
|
||||
* @return zero on success
|
||||
*/
|
||||
int avfilter_insert_filter(AVFilterLink *link, AVFilterContext *filt,
|
||||
unsigned filt_srcpad_idx, unsigned filt_dstpad_idx);
|
||||
|
||||
/**
|
||||
* @return AVClass for AVFilterContext.
|
||||
*
|
||||
* @see av_opt_find().
|
||||
*/
|
||||
const AVClass *avfilter_get_class(void);
|
||||
|
||||
typedef struct AVFilterGraphInternal AVFilterGraphInternal;
|
||||
|
||||
/**
|
||||
* A function pointer passed to the @ref AVFilterGraph.execute callback to be
|
||||
* executed multiple times, possibly in parallel.
|
||||
*
|
||||
* @param ctx the filter context the job belongs to
|
||||
* @param arg an opaque parameter passed through from @ref
|
||||
* AVFilterGraph.execute
|
||||
* @param jobnr the index of the job being executed
|
||||
* @param nb_jobs the total number of jobs
|
||||
*
|
||||
* @return 0 on success, a negative AVERROR on error
|
||||
*/
|
||||
typedef int (avfilter_action_func)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs);
|
||||
|
||||
/**
|
||||
* A function executing multiple jobs, possibly in parallel.
|
||||
*
|
||||
* @param ctx the filter context to which the jobs belong
|
||||
* @param func the function to be called multiple times
|
||||
* @param arg the argument to be passed to func
|
||||
* @param ret a nb_jobs-sized array to be filled with return values from each
|
||||
* invocation of func
|
||||
* @param nb_jobs the number of jobs to execute
|
||||
*
|
||||
* @return 0 on success, a negative AVERROR on error
|
||||
*/
|
||||
typedef int (avfilter_execute_func)(AVFilterContext *ctx, avfilter_action_func *func,
|
||||
void *arg, int *ret, int nb_jobs);
|
||||
|
||||
typedef struct AVFilterGraph {
|
||||
const AVClass *av_class;
|
||||
AVFilterContext **filters;
|
||||
unsigned nb_filters;
|
||||
|
||||
char *scale_sws_opts; ///< sws options to use for the auto-inserted scale filters
|
||||
#if FF_API_LAVR_OPTS
|
||||
attribute_deprecated char *resample_lavr_opts; ///< libavresample options to use for the auto-inserted resample filters
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Type of multithreading allowed for filters in this graph. A combination
|
||||
* of AVFILTER_THREAD_* flags.
|
||||
*
|
||||
* May be set by the caller at any point, the setting will apply to all
|
||||
* filters initialized after that. The default is allowing everything.
|
||||
*
|
||||
* When a filter in this graph is initialized, this field is combined using
|
||||
* bit AND with AVFilterContext.thread_type to get the final mask used for
|
||||
* determining allowed threading types. I.e. a threading type needs to be
|
||||
* set in both to be allowed.
|
||||
*/
|
||||
int thread_type;
|
||||
|
||||
/**
|
||||
* Maximum number of threads used by filters in this graph. May be set by
|
||||
* the caller before adding any filters to the filtergraph. Zero (the
|
||||
* default) means that the number of threads is determined automatically.
|
||||
*/
|
||||
int nb_threads;
|
||||
|
||||
/**
|
||||
* Opaque object for libavfilter internal use.
|
||||
*/
|
||||
AVFilterGraphInternal *internal;
|
||||
|
||||
/**
|
||||
* Opaque user data. May be set by the caller to an arbitrary value, e.g. to
|
||||
* be used from callbacks like @ref AVFilterGraph.execute.
|
||||
* Libavfilter will not touch this field in any way.
|
||||
*/
|
||||
void *opaque;
|
||||
|
||||
/**
|
||||
* This callback may be set by the caller immediately after allocating the
|
||||
* graph and before adding any filters to it, to provide a custom
|
||||
* multithreading implementation.
|
||||
*
|
||||
* If set, filters with slice threading capability will call this callback
|
||||
* to execute multiple jobs in parallel.
|
||||
*
|
||||
* If this field is left unset, libavfilter will use its internal
|
||||
* implementation, which may or may not be multithreaded depending on the
|
||||
* platform and build options.
|
||||
*/
|
||||
avfilter_execute_func *execute;
|
||||
|
||||
char *aresample_swr_opts; ///< swr options to use for the auto-inserted aresample filters, Access ONLY through AVOptions
|
||||
|
||||
/**
|
||||
* Private fields
|
||||
*
|
||||
* The following fields are for internal use only.
|
||||
* Their type, offset, number and semantic can change without notice.
|
||||
*/
|
||||
|
||||
AVFilterLink **sink_links;
|
||||
int sink_links_count;
|
||||
|
||||
unsigned disable_auto_convert;
|
||||
} AVFilterGraph;
|
||||
|
||||
/**
|
||||
* Allocate a filter graph.
|
||||
*
|
||||
* @return the allocated filter graph on success or NULL.
|
||||
*/
|
||||
AVFilterGraph *avfilter_graph_alloc(void);
|
||||
|
||||
/**
|
||||
* Create a new filter instance in a filter graph.
|
||||
*
|
||||
* @param graph graph in which the new filter will be used
|
||||
* @param filter the filter to create an instance of
|
||||
* @param name Name to give to the new instance (will be copied to
|
||||
* AVFilterContext.name). This may be used by the caller to identify
|
||||
* different filters, libavfilter itself assigns no semantics to
|
||||
* this parameter. May be NULL.
|
||||
*
|
||||
* @return the context of the newly created filter instance (note that it is
|
||||
* also retrievable directly through AVFilterGraph.filters or with
|
||||
* avfilter_graph_get_filter()) on success or NULL on failure.
|
||||
*/
|
||||
AVFilterContext *avfilter_graph_alloc_filter(AVFilterGraph *graph,
|
||||
const AVFilter *filter,
|
||||
const char *name);
|
||||
|
||||
/**
|
||||
* Get a filter instance identified by instance name from graph.
|
||||
*
|
||||
* @param graph filter graph to search through.
|
||||
* @param name filter instance name (should be unique in the graph).
|
||||
* @return the pointer to the found filter instance or NULL if it
|
||||
* cannot be found.
|
||||
*/
|
||||
AVFilterContext *avfilter_graph_get_filter(AVFilterGraph *graph, const char *name);
|
||||
|
||||
/**
|
||||
* Create and add a filter instance into an existing graph.
|
||||
* The filter instance is created from the filter filt and inited
|
||||
* with the parameters args and opaque.
|
||||
*
|
||||
* In case of success put in *filt_ctx the pointer to the created
|
||||
* filter instance, otherwise set *filt_ctx to NULL.
|
||||
*
|
||||
* @param name the instance name to give to the created filter instance
|
||||
* @param graph_ctx the filter graph
|
||||
* @return a negative AVERROR error code in case of failure, a non
|
||||
* negative value otherwise
|
||||
*/
|
||||
int avfilter_graph_create_filter(AVFilterContext **filt_ctx, const AVFilter *filt,
|
||||
const char *name, const char *args, void *opaque,
|
||||
AVFilterGraph *graph_ctx);
|
||||
|
||||
/**
|
||||
* Enable or disable automatic format conversion inside the graph.
|
||||
*
|
||||
* Note that format conversion can still happen inside explicitly inserted
|
||||
* scale and aresample filters.
|
||||
*
|
||||
* @param flags any of the AVFILTER_AUTO_CONVERT_* constants
|
||||
*/
|
||||
void avfilter_graph_set_auto_convert(AVFilterGraph *graph, unsigned flags);
|
||||
|
||||
enum {
|
||||
AVFILTER_AUTO_CONVERT_ALL = 0, /**< all automatic conversions enabled */
|
||||
AVFILTER_AUTO_CONVERT_NONE = -1, /**< all automatic conversions disabled */
|
||||
};
|
||||
|
||||
/**
|
||||
* Check validity and configure all the links and formats in the graph.
|
||||
*
|
||||
* @param graphctx the filter graph
|
||||
* @param log_ctx context used for logging
|
||||
* @return >= 0 in case of success, a negative AVERROR code otherwise
|
||||
*/
|
||||
int avfilter_graph_config(AVFilterGraph *graphctx, void *log_ctx);
|
||||
|
||||
/**
|
||||
* Free a graph, destroy its links, and set *graph to NULL.
|
||||
* If *graph is NULL, do nothing.
|
||||
*/
|
||||
void avfilter_graph_free(AVFilterGraph **graph);
|
||||
|
||||
/**
|
||||
* A linked-list of the inputs/outputs of the filter chain.
|
||||
*
|
||||
* This is mainly useful for avfilter_graph_parse() / avfilter_graph_parse2(),
|
||||
* where it is used to communicate open (unlinked) inputs and outputs from and
|
||||
* to the caller.
|
||||
* This struct specifies, per each not connected pad contained in the graph, the
|
||||
* filter context and the pad index required for establishing a link.
|
||||
*/
|
||||
typedef struct AVFilterInOut {
|
||||
/** unique name for this input/output in the list */
|
||||
char *name;
|
||||
|
||||
/** filter context associated to this input/output */
|
||||
AVFilterContext *filter_ctx;
|
||||
|
||||
/** index of the filt_ctx pad to use for linking */
|
||||
int pad_idx;
|
||||
|
||||
/** next input/input in the list, NULL if this is the last */
|
||||
struct AVFilterInOut *next;
|
||||
} AVFilterInOut;
|
||||
|
||||
/**
|
||||
* Allocate a single AVFilterInOut entry.
|
||||
* Must be freed with avfilter_inout_free().
|
||||
* @return allocated AVFilterInOut on success, NULL on failure.
|
||||
*/
|
||||
AVFilterInOut *avfilter_inout_alloc(void);
|
||||
|
||||
/**
|
||||
* Free the supplied list of AVFilterInOut and set *inout to NULL.
|
||||
* If *inout is NULL, do nothing.
|
||||
*/
|
||||
void avfilter_inout_free(AVFilterInOut **inout);
|
||||
|
||||
/**
|
||||
* Add a graph described by a string to a graph.
|
||||
*
|
||||
* @note The caller must provide the lists of inputs and outputs,
|
||||
* which therefore must be known before calling the function.
|
||||
*
|
||||
* @note The inputs parameter describes inputs of the already existing
|
||||
* part of the graph; i.e. from the point of view of the newly created
|
||||
* part, they are outputs. Similarly the outputs parameter describes
|
||||
* outputs of the already existing filters, which are provided as
|
||||
* inputs to the parsed filters.
|
||||
*
|
||||
* @param graph the filter graph where to link the parsed graph context
|
||||
* @param filters string to be parsed
|
||||
* @param inputs linked list to the inputs of the graph
|
||||
* @param outputs linked list to the outputs of the graph
|
||||
* @return zero on success, a negative AVERROR code on error
|
||||
*/
|
||||
int avfilter_graph_parse(AVFilterGraph *graph, const char *filters,
|
||||
AVFilterInOut *inputs, AVFilterInOut *outputs,
|
||||
void *log_ctx);
|
||||
|
||||
/**
|
||||
* Add a graph described by a string to a graph.
|
||||
*
|
||||
* In the graph filters description, if the input label of the first
|
||||
* filter is not specified, "in" is assumed; if the output label of
|
||||
* the last filter is not specified, "out" is assumed.
|
||||
*
|
||||
* @param graph the filter graph where to link the parsed graph context
|
||||
* @param filters string to be parsed
|
||||
* @param inputs pointer to a linked list to the inputs of the graph, may be NULL.
|
||||
* If non-NULL, *inputs is updated to contain the list of open inputs
|
||||
* after the parsing, should be freed with avfilter_inout_free().
|
||||
* @param outputs pointer to a linked list to the outputs of the graph, may be NULL.
|
||||
* If non-NULL, *outputs is updated to contain the list of open outputs
|
||||
* after the parsing, should be freed with avfilter_inout_free().
|
||||
* @return non negative on success, a negative AVERROR code on error
|
||||
*/
|
||||
int avfilter_graph_parse_ptr(AVFilterGraph *graph, const char *filters,
|
||||
AVFilterInOut **inputs, AVFilterInOut **outputs,
|
||||
void *log_ctx);
|
||||
|
||||
/**
|
||||
* Add a graph described by a string to a graph.
|
||||
*
|
||||
* @param[in] graph the filter graph where to link the parsed graph context
|
||||
* @param[in] filters string to be parsed
|
||||
* @param[out] inputs a linked list of all free (unlinked) inputs of the
|
||||
* parsed graph will be returned here. It is to be freed
|
||||
* by the caller using avfilter_inout_free().
|
||||
* @param[out] outputs a linked list of all free (unlinked) outputs of the
|
||||
* parsed graph will be returned here. It is to be freed by the
|
||||
* caller using avfilter_inout_free().
|
||||
* @return zero on success, a negative AVERROR code on error
|
||||
*
|
||||
* @note This function returns the inputs and outputs that are left
|
||||
* unlinked after parsing the graph and the caller then deals with
|
||||
* them.
|
||||
* @note This function makes no reference whatsoever to already
|
||||
* existing parts of the graph and the inputs parameter will on return
|
||||
* contain inputs of the newly parsed part of the graph. Analogously
|
||||
* the outputs parameter will contain outputs of the newly created
|
||||
* filters.
|
||||
*/
|
||||
int avfilter_graph_parse2(AVFilterGraph *graph, const char *filters,
|
||||
AVFilterInOut **inputs,
|
||||
AVFilterInOut **outputs);
|
||||
|
||||
/**
|
||||
* Send a command to one or more filter instances.
|
||||
*
|
||||
* @param graph the filter graph
|
||||
* @param target the filter(s) to which the command should be sent
|
||||
* "all" sends to all filters
|
||||
* otherwise it can be a filter or filter instance name
|
||||
* which will send the command to all matching filters.
|
||||
* @param cmd the command to send, for handling simplicity all commands must be alphanumeric only
|
||||
* @param arg the argument for the command
|
||||
* @param res a buffer with size res_size where the filter(s) can return a response.
|
||||
*
|
||||
* @returns >=0 on success otherwise an error code.
|
||||
* AVERROR(ENOSYS) on unsupported commands
|
||||
*/
|
||||
int avfilter_graph_send_command(AVFilterGraph *graph, const char *target, const char *cmd, const char *arg, char *res, int res_len, int flags);
|
||||
|
||||
/**
|
||||
* Queue a command for one or more filter instances.
|
||||
*
|
||||
* @param graph the filter graph
|
||||
* @param target the filter(s) to which the command should be sent
|
||||
* "all" sends to all filters
|
||||
* otherwise it can be a filter or filter instance name
|
||||
* which will send the command to all matching filters.
|
||||
* @param cmd the command to sent, for handling simplicity all commands must be alphanumeric only
|
||||
* @param arg the argument for the command
|
||||
* @param ts time at which the command should be sent to the filter
|
||||
*
|
||||
* @note As this executes commands after this function returns, no return code
|
||||
* from the filter is provided, also AVFILTER_CMD_FLAG_ONE is not supported.
|
||||
*/
|
||||
int avfilter_graph_queue_command(AVFilterGraph *graph, const char *target, const char *cmd, const char *arg, int flags, double ts);
|
||||
|
||||
|
||||
/**
|
||||
* Dump a graph into a human-readable string representation.
|
||||
*
|
||||
* @param graph the graph to dump
|
||||
* @param options formatting options; currently ignored
|
||||
* @return a string, or NULL in case of memory allocation failure;
|
||||
* the string must be freed using av_free
|
||||
*/
|
||||
char *avfilter_graph_dump(AVFilterGraph *graph, const char *options);
|
||||
|
||||
/**
|
||||
* Request a frame on the oldest sink link.
|
||||
*
|
||||
* If the request returns AVERROR_EOF, try the next.
|
||||
*
|
||||
* Note that this function is not meant to be the sole scheduling mechanism
|
||||
* of a filtergraph, only a convenience function to help drain a filtergraph
|
||||
* in a balanced way under normal circumstances.
|
||||
*
|
||||
* Also note that AVERROR_EOF does not mean that frames did not arrive on
|
||||
* some of the sinks during the process.
|
||||
* When there are multiple sink links, in case the requested link
|
||||
* returns an EOF, this may cause a filter to flush pending frames
|
||||
* which are sent to another sink link, although unrequested.
|
||||
*
|
||||
* @return the return value of ff_request_frame(),
|
||||
* or AVERROR_EOF if all links returned AVERROR_EOF
|
||||
*/
|
||||
int avfilter_graph_request_oldest(AVFilterGraph *graph);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* AVFILTER_AVFILTER_H */
|
||||
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef AVFILTER_BUFFERSINK_H
|
||||
#define AVFILTER_BUFFERSINK_H
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @ingroup lavfi_buffersink
|
||||
* memory buffer sink API for audio and video
|
||||
*/
|
||||
|
||||
#include "avfilter.h"
|
||||
|
||||
/**
|
||||
* @defgroup lavfi_buffersink Buffer sink API
|
||||
* @ingroup lavfi
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Get a frame with filtered data from sink and put it in frame.
|
||||
*
|
||||
* @param ctx pointer to a buffersink or abuffersink filter context.
|
||||
* @param frame pointer to an allocated frame that will be filled with data.
|
||||
* The data must be freed using av_frame_unref() / av_frame_free()
|
||||
* @param flags a combination of AV_BUFFERSINK_FLAG_* flags
|
||||
*
|
||||
* @return >= 0 in for success, a negative AVERROR code for failure.
|
||||
*/
|
||||
int av_buffersink_get_frame_flags(AVFilterContext *ctx, AVFrame *frame, int flags);
|
||||
|
||||
/**
|
||||
* Tell av_buffersink_get_buffer_ref() to read video/samples buffer
|
||||
* reference, but not remove it from the buffer. This is useful if you
|
||||
* need only to read a video/samples buffer, without to fetch it.
|
||||
*/
|
||||
#define AV_BUFFERSINK_FLAG_PEEK 1
|
||||
|
||||
/**
|
||||
* Tell av_buffersink_get_buffer_ref() not to request a frame from its input.
|
||||
* If a frame is already buffered, it is read (and removed from the buffer),
|
||||
* but if no frame is present, return AVERROR(EAGAIN).
|
||||
*/
|
||||
#define AV_BUFFERSINK_FLAG_NO_REQUEST 2
|
||||
|
||||
/**
|
||||
* Struct to use for initializing a buffersink context.
|
||||
*/
|
||||
typedef struct AVBufferSinkParams {
|
||||
const enum AVPixelFormat *pixel_fmts; ///< list of allowed pixel formats, terminated by AV_PIX_FMT_NONE
|
||||
} AVBufferSinkParams;
|
||||
|
||||
/**
|
||||
* Create an AVBufferSinkParams structure.
|
||||
*
|
||||
* Must be freed with av_free().
|
||||
*/
|
||||
AVBufferSinkParams *av_buffersink_params_alloc(void);
|
||||
|
||||
/**
|
||||
* Struct to use for initializing an abuffersink context.
|
||||
*/
|
||||
typedef struct AVABufferSinkParams {
|
||||
const enum AVSampleFormat *sample_fmts; ///< list of allowed sample formats, terminated by AV_SAMPLE_FMT_NONE
|
||||
const int64_t *channel_layouts; ///< list of allowed channel layouts, terminated by -1
|
||||
const int *channel_counts; ///< list of allowed channel counts, terminated by -1
|
||||
int all_channel_counts; ///< if not 0, accept any channel count or layout
|
||||
int *sample_rates; ///< list of allowed sample rates, terminated by -1
|
||||
} AVABufferSinkParams;
|
||||
|
||||
/**
|
||||
* Create an AVABufferSinkParams structure.
|
||||
*
|
||||
* Must be freed with av_free().
|
||||
*/
|
||||
AVABufferSinkParams *av_abuffersink_params_alloc(void);
|
||||
|
||||
/**
|
||||
* Set the frame size for an audio buffer sink.
|
||||
*
|
||||
* All calls to av_buffersink_get_buffer_ref will return a buffer with
|
||||
* exactly the specified number of samples, or AVERROR(EAGAIN) if there is
|
||||
* not enough. The last buffer at EOF will be padded with 0.
|
||||
*/
|
||||
void av_buffersink_set_frame_size(AVFilterContext *ctx, unsigned frame_size);
|
||||
|
||||
/**
|
||||
* @defgroup lavfi_buffersink_accessors Buffer sink accessors
|
||||
* Get the properties of the stream
|
||||
* @{
|
||||
*/
|
||||
|
||||
enum AVMediaType av_buffersink_get_type (const AVFilterContext *ctx);
|
||||
AVRational av_buffersink_get_time_base (const AVFilterContext *ctx);
|
||||
int av_buffersink_get_format (const AVFilterContext *ctx);
|
||||
|
||||
AVRational av_buffersink_get_frame_rate (const AVFilterContext *ctx);
|
||||
int av_buffersink_get_w (const AVFilterContext *ctx);
|
||||
int av_buffersink_get_h (const AVFilterContext *ctx);
|
||||
AVRational av_buffersink_get_sample_aspect_ratio (const AVFilterContext *ctx);
|
||||
|
||||
int av_buffersink_get_channels (const AVFilterContext *ctx);
|
||||
uint64_t av_buffersink_get_channel_layout (const AVFilterContext *ctx);
|
||||
int av_buffersink_get_sample_rate (const AVFilterContext *ctx);
|
||||
|
||||
AVBufferRef * av_buffersink_get_hw_frames_ctx (const AVFilterContext *ctx);
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* Get a frame with filtered data from sink and put it in frame.
|
||||
*
|
||||
* @param ctx pointer to a context of a buffersink or abuffersink AVFilter.
|
||||
* @param frame pointer to an allocated frame that will be filled with data.
|
||||
* The data must be freed using av_frame_unref() / av_frame_free()
|
||||
*
|
||||
* @return
|
||||
* - >= 0 if a frame was successfully returned.
|
||||
* - AVERROR(EAGAIN) if no frames are available at this point; more
|
||||
* input frames must be added to the filtergraph to get more output.
|
||||
* - AVERROR_EOF if there will be no more output frames on this sink.
|
||||
* - A different negative AVERROR code in other failure cases.
|
||||
*/
|
||||
int av_buffersink_get_frame(AVFilterContext *ctx, AVFrame *frame);
|
||||
|
||||
/**
|
||||
* Same as av_buffersink_get_frame(), but with the ability to specify the number
|
||||
* of samples read. This function is less efficient than
|
||||
* av_buffersink_get_frame(), because it copies the data around.
|
||||
*
|
||||
* @param ctx pointer to a context of the abuffersink AVFilter.
|
||||
* @param frame pointer to an allocated frame that will be filled with data.
|
||||
* The data must be freed using av_frame_unref() / av_frame_free()
|
||||
* frame will contain exactly nb_samples audio samples, except at
|
||||
* the end of stream, when it can contain less than nb_samples.
|
||||
*
|
||||
* @return The return codes have the same meaning as for
|
||||
* av_buffersink_get_samples().
|
||||
*
|
||||
* @warning do not mix this function with av_buffersink_get_frame(). Use only one or
|
||||
* the other with a single sink, not both.
|
||||
*/
|
||||
int av_buffersink_get_samples(AVFilterContext *ctx, AVFrame *frame, int nb_samples);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* AVFILTER_BUFFERSINK_H */
|
||||
@@ -0,0 +1,209 @@
|
||||
/*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef AVFILTER_BUFFERSRC_H
|
||||
#define AVFILTER_BUFFERSRC_H
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @ingroup lavfi_buffersrc
|
||||
* Memory buffer source API.
|
||||
*/
|
||||
|
||||
#include "avfilter.h"
|
||||
|
||||
/**
|
||||
* @defgroup lavfi_buffersrc Buffer source API
|
||||
* @ingroup lavfi
|
||||
* @{
|
||||
*/
|
||||
|
||||
enum {
|
||||
|
||||
/**
|
||||
* Do not check for format changes.
|
||||
*/
|
||||
AV_BUFFERSRC_FLAG_NO_CHECK_FORMAT = 1,
|
||||
|
||||
/**
|
||||
* Immediately push the frame to the output.
|
||||
*/
|
||||
AV_BUFFERSRC_FLAG_PUSH = 4,
|
||||
|
||||
/**
|
||||
* Keep a reference to the frame.
|
||||
* If the frame if reference-counted, create a new reference; otherwise
|
||||
* copy the frame data.
|
||||
*/
|
||||
AV_BUFFERSRC_FLAG_KEEP_REF = 8,
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the number of failed requests.
|
||||
*
|
||||
* A failed request is when the request_frame method is called while no
|
||||
* frame is present in the buffer.
|
||||
* The number is reset when a frame is added.
|
||||
*/
|
||||
unsigned av_buffersrc_get_nb_failed_requests(AVFilterContext *buffer_src);
|
||||
|
||||
/**
|
||||
* This structure contains the parameters describing the frames that will be
|
||||
* passed to this filter.
|
||||
*
|
||||
* It should be allocated with av_buffersrc_parameters_alloc() and freed with
|
||||
* av_free(). All the allocated fields in it remain owned by the caller.
|
||||
*/
|
||||
typedef struct AVBufferSrcParameters {
|
||||
/**
|
||||
* video: the pixel format, value corresponds to enum AVPixelFormat
|
||||
* audio: the sample format, value corresponds to enum AVSampleFormat
|
||||
*/
|
||||
int format;
|
||||
/**
|
||||
* The timebase to be used for the timestamps on the input frames.
|
||||
*/
|
||||
AVRational time_base;
|
||||
|
||||
/**
|
||||
* Video only, the display dimensions of the input frames.
|
||||
*/
|
||||
int width, height;
|
||||
|
||||
/**
|
||||
* Video only, the sample (pixel) aspect ratio.
|
||||
*/
|
||||
AVRational sample_aspect_ratio;
|
||||
|
||||
/**
|
||||
* Video only, the frame rate of the input video. This field must only be
|
||||
* set to a non-zero value if input stream has a known constant framerate
|
||||
* and should be left at its initial value if the framerate is variable or
|
||||
* unknown.
|
||||
*/
|
||||
AVRational frame_rate;
|
||||
|
||||
/**
|
||||
* Video with a hwaccel pixel format only. This should be a reference to an
|
||||
* AVHWFramesContext instance describing the input frames.
|
||||
*/
|
||||
AVBufferRef *hw_frames_ctx;
|
||||
|
||||
/**
|
||||
* Audio only, the audio sampling rate in samples per secon.
|
||||
*/
|
||||
int sample_rate;
|
||||
|
||||
/**
|
||||
* Audio only, the audio channel layout
|
||||
*/
|
||||
uint64_t channel_layout;
|
||||
} AVBufferSrcParameters;
|
||||
|
||||
/**
|
||||
* Allocate a new AVBufferSrcParameters instance. It should be freed by the
|
||||
* caller with av_free().
|
||||
*/
|
||||
AVBufferSrcParameters *av_buffersrc_parameters_alloc(void);
|
||||
|
||||
/**
|
||||
* Initialize the buffersrc or abuffersrc filter with the provided parameters.
|
||||
* This function may be called multiple times, the later calls override the
|
||||
* previous ones. Some of the parameters may also be set through AVOptions, then
|
||||
* whatever method is used last takes precedence.
|
||||
*
|
||||
* @param ctx an instance of the buffersrc or abuffersrc filter
|
||||
* @param param the stream parameters. The frames later passed to this filter
|
||||
* must conform to those parameters. All the allocated fields in
|
||||
* param remain owned by the caller, libavfilter will make internal
|
||||
* copies or references when necessary.
|
||||
* @return 0 on success, a negative AVERROR code on failure.
|
||||
*/
|
||||
int av_buffersrc_parameters_set(AVFilterContext *ctx, AVBufferSrcParameters *param);
|
||||
|
||||
/**
|
||||
* Add a frame to the buffer source.
|
||||
*
|
||||
* @param ctx an instance of the buffersrc filter
|
||||
* @param frame frame to be added. If the frame is reference counted, this
|
||||
* function will make a new reference to it. Otherwise the frame data will be
|
||||
* copied.
|
||||
*
|
||||
* @return 0 on success, a negative AVERROR on error
|
||||
*
|
||||
* This function is equivalent to av_buffersrc_add_frame_flags() with the
|
||||
* AV_BUFFERSRC_FLAG_KEEP_REF flag.
|
||||
*/
|
||||
av_warn_unused_result
|
||||
int av_buffersrc_write_frame(AVFilterContext *ctx, const AVFrame *frame);
|
||||
|
||||
/**
|
||||
* Add a frame to the buffer source.
|
||||
*
|
||||
* @param ctx an instance of the buffersrc filter
|
||||
* @param frame frame to be added. If the frame is reference counted, this
|
||||
* function will take ownership of the reference(s) and reset the frame.
|
||||
* Otherwise the frame data will be copied. If this function returns an error,
|
||||
* the input frame is not touched.
|
||||
*
|
||||
* @return 0 on success, a negative AVERROR on error.
|
||||
*
|
||||
* @note the difference between this function and av_buffersrc_write_frame() is
|
||||
* that av_buffersrc_write_frame() creates a new reference to the input frame,
|
||||
* while this function takes ownership of the reference passed to it.
|
||||
*
|
||||
* This function is equivalent to av_buffersrc_add_frame_flags() without the
|
||||
* AV_BUFFERSRC_FLAG_KEEP_REF flag.
|
||||
*/
|
||||
av_warn_unused_result
|
||||
int av_buffersrc_add_frame(AVFilterContext *ctx, AVFrame *frame);
|
||||
|
||||
/**
|
||||
* Add a frame to the buffer source.
|
||||
*
|
||||
* By default, if the frame is reference-counted, this function will take
|
||||
* ownership of the reference(s) and reset the frame. This can be controlled
|
||||
* using the flags.
|
||||
*
|
||||
* If this function returns an error, the input frame is not touched.
|
||||
*
|
||||
* @param buffer_src pointer to a buffer source context
|
||||
* @param frame a frame, or NULL to mark EOF
|
||||
* @param flags a combination of AV_BUFFERSRC_FLAG_*
|
||||
* @return >= 0 in case of success, a negative AVERROR code
|
||||
* in case of failure
|
||||
*/
|
||||
av_warn_unused_result
|
||||
int av_buffersrc_add_frame_flags(AVFilterContext *buffer_src,
|
||||
AVFrame *frame, int flags);
|
||||
|
||||
/**
|
||||
* Close the buffer source after EOF.
|
||||
*
|
||||
* This is similar to passing NULL to av_buffersrc_add_frame_flags()
|
||||
* except it takes the timestamp of the EOF, i.e. the timestamp of the end
|
||||
* of the last frame.
|
||||
*/
|
||||
int av_buffersrc_close(AVFilterContext *ctx, int64_t pts, unsigned flags);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* AVFILTER_BUFFERSRC_H */
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Version macros.
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef AVFILTER_VERSION_H
|
||||
#define AVFILTER_VERSION_H
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @ingroup lavfi
|
||||
* Libavfilter version macros
|
||||
*/
|
||||
|
||||
#include "libavutil/version.h"
|
||||
|
||||
#define LIBAVFILTER_VERSION_MAJOR 7
|
||||
#define LIBAVFILTER_VERSION_MINOR 25
|
||||
#define LIBAVFILTER_VERSION_MICRO 100
|
||||
|
||||
#define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
|
||||
LIBAVFILTER_VERSION_MINOR, \
|
||||
LIBAVFILTER_VERSION_MICRO)
|
||||
#define LIBAVFILTER_VERSION AV_VERSION(LIBAVFILTER_VERSION_MAJOR, \
|
||||
LIBAVFILTER_VERSION_MINOR, \
|
||||
LIBAVFILTER_VERSION_MICRO)
|
||||
#define LIBAVFILTER_BUILD LIBAVFILTER_VERSION_INT
|
||||
|
||||
#define LIBAVFILTER_IDENT "Lavfi" AV_STRINGIFY(LIBAVFILTER_VERSION)
|
||||
|
||||
/**
|
||||
* FF_API_* defines may be placed below to indicate public API that will be
|
||||
* dropped at a future version bump. The defines themselves are not part of
|
||||
* the public API and may change, break or disappear at any time.
|
||||
*/
|
||||
|
||||
#ifndef FF_API_OLD_FILTER_OPTS_ERROR
|
||||
#define FF_API_OLD_FILTER_OPTS_ERROR (LIBAVFILTER_VERSION_MAJOR < 8)
|
||||
#endif
|
||||
#ifndef FF_API_LAVR_OPTS
|
||||
#define FF_API_LAVR_OPTS (LIBAVFILTER_VERSION_MAJOR < 8)
|
||||
#endif
|
||||
#ifndef FF_API_FILTER_GET_SET
|
||||
#define FF_API_FILTER_GET_SET (LIBAVFILTER_VERSION_MAJOR < 8)
|
||||
#endif
|
||||
#ifndef FF_API_NEXT
|
||||
#define FF_API_NEXT (LIBAVFILTER_VERSION_MAJOR < 8)
|
||||
#endif
|
||||
|
||||
#endif /* AVFILTER_VERSION_H */
|
||||
@@ -0,0 +1,3085 @@
|
||||
/*
|
||||
* copyright (c) 2001 Fabrice Bellard
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef AVFORMAT_AVFORMAT_H
|
||||
#define AVFORMAT_AVFORMAT_H
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @ingroup libavf
|
||||
* Main libavformat public API header
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup libavf libavformat
|
||||
* I/O and Muxing/Demuxing Library
|
||||
*
|
||||
* Libavformat (lavf) is a library for dealing with various media container
|
||||
* formats. Its main two purposes are demuxing - i.e. splitting a media file
|
||||
* into component streams, and the reverse process of muxing - writing supplied
|
||||
* data in a specified container format. It also has an @ref lavf_io
|
||||
* "I/O module" which supports a number of protocols for accessing the data (e.g.
|
||||
* file, tcp, http and others). Before using lavf, you need to call
|
||||
* av_register_all() to register all compiled muxers, demuxers and protocols.
|
||||
* Unless you are absolutely sure you won't use libavformat's network
|
||||
* capabilities, you should also call avformat_network_init().
|
||||
*
|
||||
* A supported input format is described by an AVInputFormat struct, conversely
|
||||
* an output format is described by AVOutputFormat. You can iterate over all
|
||||
* registered input/output formats using the av_iformat_next() /
|
||||
* av_oformat_next() functions. The protocols layer is not part of the public
|
||||
* API, so you can only get the names of supported protocols with the
|
||||
* avio_enum_protocols() function.
|
||||
*
|
||||
* Main lavf structure used for both muxing and demuxing is AVFormatContext,
|
||||
* which exports all information about the file being read or written. As with
|
||||
* most Libavformat structures, its size is not part of public ABI, so it cannot be
|
||||
* allocated on stack or directly with av_malloc(). To create an
|
||||
* AVFormatContext, use avformat_alloc_context() (some functions, like
|
||||
* avformat_open_input() might do that for you).
|
||||
*
|
||||
* Most importantly an AVFormatContext contains:
|
||||
* @li the @ref AVFormatContext.iformat "input" or @ref AVFormatContext.oformat
|
||||
* "output" format. It is either autodetected or set by user for input;
|
||||
* always set by user for output.
|
||||
* @li an @ref AVFormatContext.streams "array" of AVStreams, which describe all
|
||||
* elementary streams stored in the file. AVStreams are typically referred to
|
||||
* using their index in this array.
|
||||
* @li an @ref AVFormatContext.pb "I/O context". It is either opened by lavf or
|
||||
* set by user for input, always set by user for output (unless you are dealing
|
||||
* with an AVFMT_NOFILE format).
|
||||
*
|
||||
* @section lavf_options Passing options to (de)muxers
|
||||
* It is possible to configure lavf muxers and demuxers using the @ref avoptions
|
||||
* mechanism. Generic (format-independent) libavformat options are provided by
|
||||
* AVFormatContext, they can be examined from a user program by calling
|
||||
* av_opt_next() / av_opt_find() on an allocated AVFormatContext (or its AVClass
|
||||
* from avformat_get_class()). Private (format-specific) options are provided by
|
||||
* AVFormatContext.priv_data if and only if AVInputFormat.priv_class /
|
||||
* AVOutputFormat.priv_class of the corresponding format struct is non-NULL.
|
||||
* Further options may be provided by the @ref AVFormatContext.pb "I/O context",
|
||||
* if its AVClass is non-NULL, and the protocols layer. See the discussion on
|
||||
* nesting in @ref avoptions documentation to learn how to access those.
|
||||
*
|
||||
* @section urls
|
||||
* URL strings in libavformat are made of a scheme/protocol, a ':', and a
|
||||
* scheme specific string. URLs without a scheme and ':' used for local files
|
||||
* are supported but deprecated. "file:" should be used for local files.
|
||||
*
|
||||
* It is important that the scheme string is not taken from untrusted
|
||||
* sources without checks.
|
||||
*
|
||||
* Note that some schemes/protocols are quite powerful, allowing access to
|
||||
* both local and remote files, parts of them, concatenations of them, local
|
||||
* audio and video devices and so on.
|
||||
*
|
||||
* @{
|
||||
*
|
||||
* @defgroup lavf_decoding Demuxing
|
||||
* @{
|
||||
* Demuxers read a media file and split it into chunks of data (@em packets). A
|
||||
* @ref AVPacket "packet" contains one or more encoded frames which belongs to a
|
||||
* single elementary stream. In the lavf API this process is represented by the
|
||||
* avformat_open_input() function for opening a file, av_read_frame() for
|
||||
* reading a single packet and finally avformat_close_input(), which does the
|
||||
* cleanup.
|
||||
*
|
||||
* @section lavf_decoding_open Opening a media file
|
||||
* The minimum information required to open a file is its URL, which
|
||||
* is passed to avformat_open_input(), as in the following code:
|
||||
* @code
|
||||
* const char *url = "file:in.mp3";
|
||||
* AVFormatContext *s = NULL;
|
||||
* int ret = avformat_open_input(&s, url, NULL, NULL);
|
||||
* if (ret < 0)
|
||||
* abort();
|
||||
* @endcode
|
||||
* The above code attempts to allocate an AVFormatContext, open the
|
||||
* specified file (autodetecting the format) and read the header, exporting the
|
||||
* information stored there into s. Some formats do not have a header or do not
|
||||
* store enough information there, so it is recommended that you call the
|
||||
* avformat_find_stream_info() function which tries to read and decode a few
|
||||
* frames to find missing information.
|
||||
*
|
||||
* In some cases you might want to preallocate an AVFormatContext yourself with
|
||||
* avformat_alloc_context() and do some tweaking on it before passing it to
|
||||
* avformat_open_input(). One such case is when you want to use custom functions
|
||||
* for reading input data instead of lavf internal I/O layer.
|
||||
* To do that, create your own AVIOContext with avio_alloc_context(), passing
|
||||
* your reading callbacks to it. Then set the @em pb field of your
|
||||
* AVFormatContext to newly created AVIOContext.
|
||||
*
|
||||
* Since the format of the opened file is in general not known until after
|
||||
* avformat_open_input() has returned, it is not possible to set demuxer private
|
||||
* options on a preallocated context. Instead, the options should be passed to
|
||||
* avformat_open_input() wrapped in an AVDictionary:
|
||||
* @code
|
||||
* AVDictionary *options = NULL;
|
||||
* av_dict_set(&options, "video_size", "640x480", 0);
|
||||
* av_dict_set(&options, "pixel_format", "rgb24", 0);
|
||||
*
|
||||
* if (avformat_open_input(&s, url, NULL, &options) < 0)
|
||||
* abort();
|
||||
* av_dict_free(&options);
|
||||
* @endcode
|
||||
* This code passes the private options 'video_size' and 'pixel_format' to the
|
||||
* demuxer. They would be necessary for e.g. the rawvideo demuxer, since it
|
||||
* cannot know how to interpret raw video data otherwise. If the format turns
|
||||
* out to be something different than raw video, those options will not be
|
||||
* recognized by the demuxer and therefore will not be applied. Such unrecognized
|
||||
* options are then returned in the options dictionary (recognized options are
|
||||
* consumed). The calling program can handle such unrecognized options as it
|
||||
* wishes, e.g.
|
||||
* @code
|
||||
* AVDictionaryEntry *e;
|
||||
* if (e = av_dict_get(options, "", NULL, AV_DICT_IGNORE_SUFFIX)) {
|
||||
* fprintf(stderr, "Option %s not recognized by the demuxer.\n", e->key);
|
||||
* abort();
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
* After you have finished reading the file, you must close it with
|
||||
* avformat_close_input(). It will free everything associated with the file.
|
||||
*
|
||||
* @section lavf_decoding_read Reading from an opened file
|
||||
* Reading data from an opened AVFormatContext is done by repeatedly calling
|
||||
* av_read_frame() on it. Each call, if successful, will return an AVPacket
|
||||
* containing encoded data for one AVStream, identified by
|
||||
* AVPacket.stream_index. This packet may be passed straight into the libavcodec
|
||||
* decoding functions avcodec_send_packet() or avcodec_decode_subtitle2() if the
|
||||
* caller wishes to decode the data.
|
||||
*
|
||||
* AVPacket.pts, AVPacket.dts and AVPacket.duration timing information will be
|
||||
* set if known. They may also be unset (i.e. AV_NOPTS_VALUE for
|
||||
* pts/dts, 0 for duration) if the stream does not provide them. The timing
|
||||
* information will be in AVStream.time_base units, i.e. it has to be
|
||||
* multiplied by the timebase to convert them to seconds.
|
||||
*
|
||||
* If AVPacket.buf is set on the returned packet, then the packet is
|
||||
* allocated dynamically and the user may keep it indefinitely.
|
||||
* Otherwise, if AVPacket.buf is NULL, the packet data is backed by a
|
||||
* static storage somewhere inside the demuxer and the packet is only valid
|
||||
* until the next av_read_frame() call or closing the file. If the caller
|
||||
* requires a longer lifetime, av_dup_packet() will make an av_malloc()ed copy
|
||||
* of it.
|
||||
* In both cases, the packet must be freed with av_packet_unref() when it is no
|
||||
* longer needed.
|
||||
*
|
||||
* @section lavf_decoding_seek Seeking
|
||||
* @}
|
||||
*
|
||||
* @defgroup lavf_encoding Muxing
|
||||
* @{
|
||||
* Muxers take encoded data in the form of @ref AVPacket "AVPackets" and write
|
||||
* it into files or other output bytestreams in the specified container format.
|
||||
*
|
||||
* The main API functions for muxing are avformat_write_header() for writing the
|
||||
* file header, av_write_frame() / av_interleaved_write_frame() for writing the
|
||||
* packets and av_write_trailer() for finalizing the file.
|
||||
*
|
||||
* At the beginning of the muxing process, the caller must first call
|
||||
* avformat_alloc_context() to create a muxing context. The caller then sets up
|
||||
* the muxer by filling the various fields in this context:
|
||||
*
|
||||
* - The @ref AVFormatContext.oformat "oformat" field must be set to select the
|
||||
* muxer that will be used.
|
||||
* - Unless the format is of the AVFMT_NOFILE type, the @ref AVFormatContext.pb
|
||||
* "pb" field must be set to an opened IO context, either returned from
|
||||
* avio_open2() or a custom one.
|
||||
* - Unless the format is of the AVFMT_NOSTREAMS type, at least one stream must
|
||||
* be created with the avformat_new_stream() function. The caller should fill
|
||||
* the @ref AVStream.codecpar "stream codec parameters" information, such as the
|
||||
* codec @ref AVCodecParameters.codec_type "type", @ref AVCodecParameters.codec_id
|
||||
* "id" and other parameters (e.g. width / height, the pixel or sample format,
|
||||
* etc.) as known. The @ref AVStream.time_base "stream timebase" should
|
||||
* be set to the timebase that the caller desires to use for this stream (note
|
||||
* that the timebase actually used by the muxer can be different, as will be
|
||||
* described later).
|
||||
* - It is advised to manually initialize only the relevant fields in
|
||||
* AVCodecParameters, rather than using @ref avcodec_parameters_copy() during
|
||||
* remuxing: there is no guarantee that the codec context values remain valid
|
||||
* for both input and output format contexts.
|
||||
* - The caller may fill in additional information, such as @ref
|
||||
* AVFormatContext.metadata "global" or @ref AVStream.metadata "per-stream"
|
||||
* metadata, @ref AVFormatContext.chapters "chapters", @ref
|
||||
* AVFormatContext.programs "programs", etc. as described in the
|
||||
* AVFormatContext documentation. Whether such information will actually be
|
||||
* stored in the output depends on what the container format and the muxer
|
||||
* support.
|
||||
*
|
||||
* When the muxing context is fully set up, the caller must call
|
||||
* avformat_write_header() to initialize the muxer internals and write the file
|
||||
* header. Whether anything actually is written to the IO context at this step
|
||||
* depends on the muxer, but this function must always be called. Any muxer
|
||||
* private options must be passed in the options parameter to this function.
|
||||
*
|
||||
* The data is then sent to the muxer by repeatedly calling av_write_frame() or
|
||||
* av_interleaved_write_frame() (consult those functions' documentation for
|
||||
* discussion on the difference between them; only one of them may be used with
|
||||
* a single muxing context, they should not be mixed). Do note that the timing
|
||||
* information on the packets sent to the muxer must be in the corresponding
|
||||
* AVStream's timebase. That timebase is set by the muxer (in the
|
||||
* avformat_write_header() step) and may be different from the timebase
|
||||
* requested by the caller.
|
||||
*
|
||||
* Once all the data has been written, the caller must call av_write_trailer()
|
||||
* to flush any buffered packets and finalize the output file, then close the IO
|
||||
* context (if any) and finally free the muxing context with
|
||||
* avformat_free_context().
|
||||
* @}
|
||||
*
|
||||
* @defgroup lavf_io I/O Read/Write
|
||||
* @{
|
||||
* @section lavf_io_dirlist Directory listing
|
||||
* The directory listing API makes it possible to list files on remote servers.
|
||||
*
|
||||
* Some of possible use cases:
|
||||
* - an "open file" dialog to choose files from a remote location,
|
||||
* - a recursive media finder providing a player with an ability to play all
|
||||
* files from a given directory.
|
||||
*
|
||||
* @subsection lavf_io_dirlist_open Opening a directory
|
||||
* At first, a directory needs to be opened by calling avio_open_dir()
|
||||
* supplied with a URL and, optionally, ::AVDictionary containing
|
||||
* protocol-specific parameters. The function returns zero or positive
|
||||
* integer and allocates AVIODirContext on success.
|
||||
*
|
||||
* @code
|
||||
* AVIODirContext *ctx = NULL;
|
||||
* if (avio_open_dir(&ctx, "smb://example.com/some_dir", NULL) < 0) {
|
||||
* fprintf(stderr, "Cannot open directory.\n");
|
||||
* abort();
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
* This code tries to open a sample directory using smb protocol without
|
||||
* any additional parameters.
|
||||
*
|
||||
* @subsection lavf_io_dirlist_read Reading entries
|
||||
* Each directory's entry (i.e. file, another directory, anything else
|
||||
* within ::AVIODirEntryType) is represented by AVIODirEntry.
|
||||
* Reading consecutive entries from an opened AVIODirContext is done by
|
||||
* repeatedly calling avio_read_dir() on it. Each call returns zero or
|
||||
* positive integer if successful. Reading can be stopped right after the
|
||||
* NULL entry has been read -- it means there are no entries left to be
|
||||
* read. The following code reads all entries from a directory associated
|
||||
* with ctx and prints their names to standard output.
|
||||
* @code
|
||||
* AVIODirEntry *entry = NULL;
|
||||
* for (;;) {
|
||||
* if (avio_read_dir(ctx, &entry) < 0) {
|
||||
* fprintf(stderr, "Cannot list directory.\n");
|
||||
* abort();
|
||||
* }
|
||||
* if (!entry)
|
||||
* break;
|
||||
* printf("%s\n", entry->name);
|
||||
* avio_free_directory_entry(&entry);
|
||||
* }
|
||||
* @endcode
|
||||
* @}
|
||||
*
|
||||
* @defgroup lavf_codec Demuxers
|
||||
* @{
|
||||
* @defgroup lavf_codec_native Native Demuxers
|
||||
* @{
|
||||
* @}
|
||||
* @defgroup lavf_codec_wrappers External library wrappers
|
||||
* @{
|
||||
* @}
|
||||
* @}
|
||||
* @defgroup lavf_protos I/O Protocols
|
||||
* @{
|
||||
* @}
|
||||
* @defgroup lavf_internal Internal
|
||||
* @{
|
||||
* @}
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <time.h>
|
||||
#include <stdio.h> /* FILE */
|
||||
#include "libavcodec/avcodec.h"
|
||||
#include "libavutil/dict.h"
|
||||
#include "libavutil/log.h"
|
||||
|
||||
#include "avio.h"
|
||||
#include "libavformat/version.h"
|
||||
|
||||
struct AVFormatContext;
|
||||
|
||||
struct AVDeviceInfoList;
|
||||
struct AVDeviceCapabilitiesQuery;
|
||||
|
||||
/**
|
||||
* @defgroup metadata_api Public Metadata API
|
||||
* @{
|
||||
* @ingroup libavf
|
||||
* The metadata API allows libavformat to export metadata tags to a client
|
||||
* application when demuxing. Conversely it allows a client application to
|
||||
* set metadata when muxing.
|
||||
*
|
||||
* Metadata is exported or set as pairs of key/value strings in the 'metadata'
|
||||
* fields of the AVFormatContext, AVStream, AVChapter and AVProgram structs
|
||||
* using the @ref lavu_dict "AVDictionary" API. Like all strings in FFmpeg,
|
||||
* metadata is assumed to be UTF-8 encoded Unicode. Note that metadata
|
||||
* exported by demuxers isn't checked to be valid UTF-8 in most cases.
|
||||
*
|
||||
* Important concepts to keep in mind:
|
||||
* - Keys are unique; there can never be 2 tags with the same key. This is
|
||||
* also meant semantically, i.e., a demuxer should not knowingly produce
|
||||
* several keys that are literally different but semantically identical.
|
||||
* E.g., key=Author5, key=Author6. In this example, all authors must be
|
||||
* placed in the same tag.
|
||||
* - Metadata is flat, not hierarchical; there are no subtags. If you
|
||||
* want to store, e.g., the email address of the child of producer Alice
|
||||
* and actor Bob, that could have key=alice_and_bobs_childs_email_address.
|
||||
* - Several modifiers can be applied to the tag name. This is done by
|
||||
* appending a dash character ('-') and the modifier name in the order
|
||||
* they appear in the list below -- e.g. foo-eng-sort, not foo-sort-eng.
|
||||
* - language -- a tag whose value is localized for a particular language
|
||||
* is appended with the ISO 639-2/B 3-letter language code.
|
||||
* For example: Author-ger=Michael, Author-eng=Mike
|
||||
* The original/default language is in the unqualified "Author" tag.
|
||||
* A demuxer should set a default if it sets any translated tag.
|
||||
* - sorting -- a modified version of a tag that should be used for
|
||||
* sorting will have '-sort' appended. E.g. artist="The Beatles",
|
||||
* artist-sort="Beatles, The".
|
||||
* - Some protocols and demuxers support metadata updates. After a successful
|
||||
* call to av_read_packet(), AVFormatContext.event_flags or AVStream.event_flags
|
||||
* will be updated to indicate if metadata changed. In order to detect metadata
|
||||
* changes on a stream, you need to loop through all streams in the AVFormatContext
|
||||
* and check their individual event_flags.
|
||||
*
|
||||
* - Demuxers attempt to export metadata in a generic format, however tags
|
||||
* with no generic equivalents are left as they are stored in the container.
|
||||
* Follows a list of generic tag names:
|
||||
*
|
||||
@verbatim
|
||||
album -- name of the set this work belongs to
|
||||
album_artist -- main creator of the set/album, if different from artist.
|
||||
e.g. "Various Artists" for compilation albums.
|
||||
artist -- main creator of the work
|
||||
comment -- any additional description of the file.
|
||||
composer -- who composed the work, if different from artist.
|
||||
copyright -- name of copyright holder.
|
||||
creation_time-- date when the file was created, preferably in ISO 8601.
|
||||
date -- date when the work was created, preferably in ISO 8601.
|
||||
disc -- number of a subset, e.g. disc in a multi-disc collection.
|
||||
encoder -- name/settings of the software/hardware that produced the file.
|
||||
encoded_by -- person/group who created the file.
|
||||
filename -- original name of the file.
|
||||
genre -- <self-evident>.
|
||||
language -- main language in which the work is performed, preferably
|
||||
in ISO 639-2 format. Multiple languages can be specified by
|
||||
separating them with commas.
|
||||
performer -- artist who performed the work, if different from artist.
|
||||
E.g for "Also sprach Zarathustra", artist would be "Richard
|
||||
Strauss" and performer "London Philharmonic Orchestra".
|
||||
publisher -- name of the label/publisher.
|
||||
service_name -- name of the service in broadcasting (channel name).
|
||||
service_provider -- name of the service provider in broadcasting.
|
||||
title -- name of the work.
|
||||
track -- number of this work in the set, can be in form current/total.
|
||||
variant_bitrate -- the total bitrate of the bitrate variant that the current stream is part of
|
||||
@endverbatim
|
||||
*
|
||||
* Look in the examples section for an application example how to use the Metadata API.
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* packet functions */
|
||||
|
||||
|
||||
/**
|
||||
* Allocate and read the payload of a packet and initialize its
|
||||
* fields with default values.
|
||||
*
|
||||
* @param s associated IO context
|
||||
* @param pkt packet
|
||||
* @param size desired payload size
|
||||
* @return >0 (read size) if OK, AVERROR_xxx otherwise
|
||||
*/
|
||||
int av_get_packet(AVIOContext *s, AVPacket *pkt, int size);
|
||||
|
||||
|
||||
/**
|
||||
* Read data and append it to the current content of the AVPacket.
|
||||
* If pkt->size is 0 this is identical to av_get_packet.
|
||||
* Note that this uses av_grow_packet and thus involves a realloc
|
||||
* which is inefficient. Thus this function should only be used
|
||||
* when there is no reasonable way to know (an upper bound of)
|
||||
* the final size.
|
||||
*
|
||||
* @param s associated IO context
|
||||
* @param pkt packet
|
||||
* @param size amount of data to read
|
||||
* @return >0 (read size) if OK, AVERROR_xxx otherwise, previous data
|
||||
* will not be lost even if an error occurs.
|
||||
*/
|
||||
int av_append_packet(AVIOContext *s, AVPacket *pkt, int size);
|
||||
|
||||
/*************************************************/
|
||||
/* input/output formats */
|
||||
|
||||
struct AVCodecTag;
|
||||
|
||||
/**
|
||||
* This structure contains the data a format has to probe a file.
|
||||
*/
|
||||
typedef struct AVProbeData {
|
||||
const char *filename;
|
||||
unsigned char *buf; /**< Buffer must have AVPROBE_PADDING_SIZE of extra allocated bytes filled with zero. */
|
||||
int buf_size; /**< Size of buf except extra allocated bytes */
|
||||
const char *mime_type; /**< mime_type, when known. */
|
||||
} AVProbeData;
|
||||
|
||||
#define AVPROBE_SCORE_RETRY (AVPROBE_SCORE_MAX/4)
|
||||
#define AVPROBE_SCORE_STREAM_RETRY (AVPROBE_SCORE_MAX/4-1)
|
||||
|
||||
#define AVPROBE_SCORE_EXTENSION 50 ///< score for file extension
|
||||
#define AVPROBE_SCORE_MIME 75 ///< score for file mime type
|
||||
#define AVPROBE_SCORE_MAX 100 ///< maximum score
|
||||
|
||||
#define AVPROBE_PADDING_SIZE 32 ///< extra allocated bytes at the end of the probe buffer
|
||||
|
||||
/// Demuxer will use avio_open, no opened file should be provided by the caller.
|
||||
#define AVFMT_NOFILE 0x0001
|
||||
#define AVFMT_NEEDNUMBER 0x0002 /**< Needs '%d' in filename. */
|
||||
#define AVFMT_SHOW_IDS 0x0008 /**< Show format stream IDs numbers. */
|
||||
#define AVFMT_GLOBALHEADER 0x0040 /**< Format wants global header. */
|
||||
#define AVFMT_NOTIMESTAMPS 0x0080 /**< Format does not need / have any timestamps. */
|
||||
#define AVFMT_GENERIC_INDEX 0x0100 /**< Use generic index building code. */
|
||||
#define AVFMT_TS_DISCONT 0x0200 /**< Format allows timestamp discontinuities. Note, muxers always require valid (monotone) timestamps */
|
||||
#define AVFMT_VARIABLE_FPS 0x0400 /**< Format allows variable fps. */
|
||||
#define AVFMT_NODIMENSIONS 0x0800 /**< Format does not need width/height */
|
||||
#define AVFMT_NOSTREAMS 0x1000 /**< Format does not require any streams */
|
||||
#define AVFMT_NOBINSEARCH 0x2000 /**< Format does not allow to fall back on binary search via read_timestamp */
|
||||
#define AVFMT_NOGENSEARCH 0x4000 /**< Format does not allow to fall back on generic search */
|
||||
#define AVFMT_NO_BYTE_SEEK 0x8000 /**< Format does not allow seeking by bytes */
|
||||
#define AVFMT_ALLOW_FLUSH 0x10000 /**< Format allows flushing. If not set, the muxer will not receive a NULL packet in the write_packet function. */
|
||||
#define AVFMT_TS_NONSTRICT 0x20000 /**< Format does not require strictly
|
||||
increasing timestamps, but they must
|
||||
still be monotonic */
|
||||
#define AVFMT_TS_NEGATIVE 0x40000 /**< Format allows muxing negative
|
||||
timestamps. If not set the timestamp
|
||||
will be shifted in av_write_frame and
|
||||
av_interleaved_write_frame so they
|
||||
start from 0.
|
||||
The user or muxer can override this through
|
||||
AVFormatContext.avoid_negative_ts
|
||||
*/
|
||||
|
||||
#define AVFMT_SEEK_TO_PTS 0x4000000 /**< Seeking is based on PTS */
|
||||
|
||||
/**
|
||||
* @addtogroup lavf_encoding
|
||||
* @{
|
||||
*/
|
||||
typedef struct AVOutputFormat {
|
||||
const char *name;
|
||||
/**
|
||||
* Descriptive name for the format, meant to be more human-readable
|
||||
* than name. You should use the NULL_IF_CONFIG_SMALL() macro
|
||||
* to define it.
|
||||
*/
|
||||
const char *long_name;
|
||||
const char *mime_type;
|
||||
const char *extensions; /**< comma-separated filename extensions */
|
||||
/* output support */
|
||||
enum AVCodecID audio_codec; /**< default audio codec */
|
||||
enum AVCodecID video_codec; /**< default video codec */
|
||||
enum AVCodecID subtitle_codec; /**< default subtitle codec */
|
||||
/**
|
||||
* can use flags: AVFMT_NOFILE, AVFMT_NEEDNUMBER,
|
||||
* AVFMT_GLOBALHEADER, AVFMT_NOTIMESTAMPS, AVFMT_VARIABLE_FPS,
|
||||
* AVFMT_NODIMENSIONS, AVFMT_NOSTREAMS, AVFMT_ALLOW_FLUSH,
|
||||
* AVFMT_TS_NONSTRICT, AVFMT_TS_NEGATIVE
|
||||
*/
|
||||
int flags;
|
||||
|
||||
/**
|
||||
* List of supported codec_id-codec_tag pairs, ordered by "better
|
||||
* choice first". The arrays are all terminated by AV_CODEC_ID_NONE.
|
||||
*/
|
||||
const struct AVCodecTag * const *codec_tag;
|
||||
|
||||
|
||||
const AVClass *priv_class; ///< AVClass for the private context
|
||||
|
||||
/*****************************************************************
|
||||
* No fields below this line are part of the public API. They
|
||||
* may not be used outside of libavformat and can be changed and
|
||||
* removed at will.
|
||||
* New public fields should be added right above.
|
||||
*****************************************************************
|
||||
*/
|
||||
struct AVOutputFormat *next;
|
||||
/**
|
||||
* size of private data so that it can be allocated in the wrapper
|
||||
*/
|
||||
int priv_data_size;
|
||||
|
||||
int (*write_header)(struct AVFormatContext *);
|
||||
/**
|
||||
* Write a packet. If AVFMT_ALLOW_FLUSH is set in flags,
|
||||
* pkt can be NULL in order to flush data buffered in the muxer.
|
||||
* When flushing, return 0 if there still is more data to flush,
|
||||
* or 1 if everything was flushed and there is no more buffered
|
||||
* data.
|
||||
*/
|
||||
int (*write_packet)(struct AVFormatContext *, AVPacket *pkt);
|
||||
int (*write_trailer)(struct AVFormatContext *);
|
||||
/**
|
||||
* Currently only used to set pixel format if not YUV420P.
|
||||
*/
|
||||
int (*interleave_packet)(struct AVFormatContext *, AVPacket *out,
|
||||
AVPacket *in, int flush);
|
||||
/**
|
||||
* Test if the given codec can be stored in this container.
|
||||
*
|
||||
* @return 1 if the codec is supported, 0 if it is not.
|
||||
* A negative number if unknown.
|
||||
* MKTAG('A', 'P', 'I', 'C') if the codec is only supported as AV_DISPOSITION_ATTACHED_PIC
|
||||
*/
|
||||
int (*query_codec)(enum AVCodecID id, int std_compliance);
|
||||
|
||||
void (*get_output_timestamp)(struct AVFormatContext *s, int stream,
|
||||
int64_t *dts, int64_t *wall);
|
||||
/**
|
||||
* Allows sending messages from application to device.
|
||||
*/
|
||||
int (*control_message)(struct AVFormatContext *s, int type,
|
||||
void *data, size_t data_size);
|
||||
|
||||
/**
|
||||
* Write an uncoded AVFrame.
|
||||
*
|
||||
* See av_write_uncoded_frame() for details.
|
||||
*
|
||||
* The library will free *frame afterwards, but the muxer can prevent it
|
||||
* by setting the pointer to NULL.
|
||||
*/
|
||||
int (*write_uncoded_frame)(struct AVFormatContext *, int stream_index,
|
||||
AVFrame **frame, unsigned flags);
|
||||
/**
|
||||
* Returns device list with it properties.
|
||||
* @see avdevice_list_devices() for more details.
|
||||
*/
|
||||
int (*get_device_list)(struct AVFormatContext *s, struct AVDeviceInfoList *device_list);
|
||||
/**
|
||||
* Initialize device capabilities submodule.
|
||||
* @see avdevice_capabilities_create() for more details.
|
||||
*/
|
||||
int (*create_device_capabilities)(struct AVFormatContext *s, struct AVDeviceCapabilitiesQuery *caps);
|
||||
/**
|
||||
* Free device capabilities submodule.
|
||||
* @see avdevice_capabilities_free() for more details.
|
||||
*/
|
||||
int (*free_device_capabilities)(struct AVFormatContext *s, struct AVDeviceCapabilitiesQuery *caps);
|
||||
enum AVCodecID data_codec; /**< default data codec */
|
||||
/**
|
||||
* Initialize format. May allocate data here, and set any AVFormatContext or
|
||||
* AVStream parameters that need to be set before packets are sent.
|
||||
* This method must not write output.
|
||||
*
|
||||
* Return 0 if streams were fully configured, 1 if not, negative AVERROR on failure
|
||||
*
|
||||
* Any allocations made here must be freed in deinit().
|
||||
*/
|
||||
int (*init)(struct AVFormatContext *);
|
||||
/**
|
||||
* Deinitialize format. If present, this is called whenever the muxer is being
|
||||
* destroyed, regardless of whether or not the header has been written.
|
||||
*
|
||||
* If a trailer is being written, this is called after write_trailer().
|
||||
*
|
||||
* This is called if init() fails as well.
|
||||
*/
|
||||
void (*deinit)(struct AVFormatContext *);
|
||||
/**
|
||||
* Set up any necessary bitstream filtering and extract any extra data needed
|
||||
* for the global header.
|
||||
* Return 0 if more packets from this stream must be checked; 1 if not.
|
||||
*/
|
||||
int (*check_bitstream)(struct AVFormatContext *, const AVPacket *pkt);
|
||||
} AVOutputFormat;
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup lavf_decoding
|
||||
* @{
|
||||
*/
|
||||
typedef struct AVInputFormat {
|
||||
/**
|
||||
* A comma separated list of short names for the format. New names
|
||||
* may be appended with a minor bump.
|
||||
*/
|
||||
const char *name;
|
||||
|
||||
/**
|
||||
* Descriptive name for the format, meant to be more human-readable
|
||||
* than name. You should use the NULL_IF_CONFIG_SMALL() macro
|
||||
* to define it.
|
||||
*/
|
||||
const char *long_name;
|
||||
|
||||
/**
|
||||
* Can use flags: AVFMT_NOFILE, AVFMT_NEEDNUMBER, AVFMT_SHOW_IDS,
|
||||
* AVFMT_GENERIC_INDEX, AVFMT_TS_DISCONT, AVFMT_NOBINSEARCH,
|
||||
* AVFMT_NOGENSEARCH, AVFMT_NO_BYTE_SEEK, AVFMT_SEEK_TO_PTS.
|
||||
*/
|
||||
int flags;
|
||||
|
||||
/**
|
||||
* If extensions are defined, then no probe is done. You should
|
||||
* usually not use extension format guessing because it is not
|
||||
* reliable enough
|
||||
*/
|
||||
const char *extensions;
|
||||
|
||||
const struct AVCodecTag * const *codec_tag;
|
||||
|
||||
const AVClass *priv_class; ///< AVClass for the private context
|
||||
|
||||
/**
|
||||
* Comma-separated list of mime types.
|
||||
* It is used check for matching mime types while probing.
|
||||
* @see av_probe_input_format2
|
||||
*/
|
||||
const char *mime_type;
|
||||
|
||||
/*****************************************************************
|
||||
* No fields below this line are part of the public API. They
|
||||
* may not be used outside of libavformat and can be changed and
|
||||
* removed at will.
|
||||
* New public fields should be added right above.
|
||||
*****************************************************************
|
||||
*/
|
||||
struct AVInputFormat *next;
|
||||
|
||||
/**
|
||||
* Raw demuxers store their codec ID here.
|
||||
*/
|
||||
int raw_codec_id;
|
||||
|
||||
/**
|
||||
* Size of private data so that it can be allocated in the wrapper.
|
||||
*/
|
||||
int priv_data_size;
|
||||
|
||||
/**
|
||||
* Tell if a given file has a chance of being parsed as this format.
|
||||
* The buffer provided is guaranteed to be AVPROBE_PADDING_SIZE bytes
|
||||
* big so you do not have to check for that unless you need more.
|
||||
*/
|
||||
int (*read_probe)(AVProbeData *);
|
||||
|
||||
/**
|
||||
* Read the format header and initialize the AVFormatContext
|
||||
* structure. Return 0 if OK. 'avformat_new_stream' should be
|
||||
* called to create new streams.
|
||||
*/
|
||||
int (*read_header)(struct AVFormatContext *);
|
||||
|
||||
/**
|
||||
* Read one packet and put it in 'pkt'. pts and flags are also
|
||||
* set. 'avformat_new_stream' can be called only if the flag
|
||||
* AVFMTCTX_NOHEADER is used and only in the calling thread (not in a
|
||||
* background thread).
|
||||
* @return 0 on success, < 0 on error.
|
||||
* When returning an error, pkt must not have been allocated
|
||||
* or must be freed before returning
|
||||
*/
|
||||
int (*read_packet)(struct AVFormatContext *, AVPacket *pkt);
|
||||
|
||||
/**
|
||||
* Close the stream. The AVFormatContext and AVStreams are not
|
||||
* freed by this function
|
||||
*/
|
||||
int (*read_close)(struct AVFormatContext *);
|
||||
|
||||
/**
|
||||
* Seek to a given timestamp relative to the frames in
|
||||
* stream component stream_index.
|
||||
* @param stream_index Must not be -1.
|
||||
* @param flags Selects which direction should be preferred if no exact
|
||||
* match is available.
|
||||
* @return >= 0 on success (but not necessarily the new offset)
|
||||
*/
|
||||
int (*read_seek)(struct AVFormatContext *,
|
||||
int stream_index, int64_t timestamp, int flags);
|
||||
|
||||
/**
|
||||
* Get the next timestamp in stream[stream_index].time_base units.
|
||||
* @return the timestamp or AV_NOPTS_VALUE if an error occurred
|
||||
*/
|
||||
int64_t (*read_timestamp)(struct AVFormatContext *s, int stream_index,
|
||||
int64_t *pos, int64_t pos_limit);
|
||||
|
||||
/**
|
||||
* Start/resume playing - only meaningful if using a network-based format
|
||||
* (RTSP).
|
||||
*/
|
||||
int (*read_play)(struct AVFormatContext *);
|
||||
|
||||
/**
|
||||
* Pause playing - only meaningful if using a network-based format
|
||||
* (RTSP).
|
||||
*/
|
||||
int (*read_pause)(struct AVFormatContext *);
|
||||
|
||||
/**
|
||||
* Seek to timestamp ts.
|
||||
* Seeking will be done so that the point from which all active streams
|
||||
* can be presented successfully will be closest to ts and within min/max_ts.
|
||||
* Active streams are all streams that have AVStream.discard < AVDISCARD_ALL.
|
||||
*/
|
||||
int (*read_seek2)(struct AVFormatContext *s, int stream_index, int64_t min_ts, int64_t ts, int64_t max_ts, int flags);
|
||||
|
||||
/**
|
||||
* Returns device list with it properties.
|
||||
* @see avdevice_list_devices() for more details.
|
||||
*/
|
||||
int (*get_device_list)(struct AVFormatContext *s, struct AVDeviceInfoList *device_list);
|
||||
|
||||
/**
|
||||
* Initialize device capabilities submodule.
|
||||
* @see avdevice_capabilities_create() for more details.
|
||||
*/
|
||||
int (*create_device_capabilities)(struct AVFormatContext *s, struct AVDeviceCapabilitiesQuery *caps);
|
||||
|
||||
/**
|
||||
* Free device capabilities submodule.
|
||||
* @see avdevice_capabilities_free() for more details.
|
||||
*/
|
||||
int (*free_device_capabilities)(struct AVFormatContext *s, struct AVDeviceCapabilitiesQuery *caps);
|
||||
} AVInputFormat;
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
enum AVStreamParseType {
|
||||
AVSTREAM_PARSE_NONE,
|
||||
AVSTREAM_PARSE_FULL, /**< full parsing and repack */
|
||||
AVSTREAM_PARSE_HEADERS, /**< Only parse headers, do not repack. */
|
||||
AVSTREAM_PARSE_TIMESTAMPS, /**< full parsing and interpolation of timestamps for frames not starting on a packet boundary */
|
||||
AVSTREAM_PARSE_FULL_ONCE, /**< full parsing and repack of the first frame only, only implemented for H.264 currently */
|
||||
AVSTREAM_PARSE_FULL_RAW, /**< full parsing and repack with timestamp and position generation by parser for raw
|
||||
this assumes that each packet in the file contains no demuxer level headers and
|
||||
just codec level data, otherwise position generation would fail */
|
||||
};
|
||||
|
||||
typedef struct AVIndexEntry {
|
||||
int64_t pos;
|
||||
int64_t timestamp; /**<
|
||||
* Timestamp in AVStream.time_base units, preferably the time from which on correctly decoded frames are available
|
||||
* when seeking to this entry. That means preferable PTS on keyframe based formats.
|
||||
* But demuxers can choose to store a different timestamp, if it is more convenient for the implementation or nothing better
|
||||
* is known
|
||||
*/
|
||||
#define AVINDEX_KEYFRAME 0x0001
|
||||
#define AVINDEX_DISCARD_FRAME 0x0002 /**
|
||||
* Flag is used to indicate which frame should be discarded after decoding.
|
||||
*/
|
||||
int flags:2;
|
||||
int size:30; //Yeah, trying to keep the size of this small to reduce memory requirements (it is 24 vs. 32 bytes due to possible 8-byte alignment).
|
||||
int min_distance; /**< Minimum distance between this and the previous keyframe, used to avoid unneeded searching. */
|
||||
} AVIndexEntry;
|
||||
|
||||
#define AV_DISPOSITION_DEFAULT 0x0001
|
||||
#define AV_DISPOSITION_DUB 0x0002
|
||||
#define AV_DISPOSITION_ORIGINAL 0x0004
|
||||
#define AV_DISPOSITION_COMMENT 0x0008
|
||||
#define AV_DISPOSITION_LYRICS 0x0010
|
||||
#define AV_DISPOSITION_KARAOKE 0x0020
|
||||
|
||||
/**
|
||||
* Track should be used during playback by default.
|
||||
* Useful for subtitle track that should be displayed
|
||||
* even when user did not explicitly ask for subtitles.
|
||||
*/
|
||||
#define AV_DISPOSITION_FORCED 0x0040
|
||||
#define AV_DISPOSITION_HEARING_IMPAIRED 0x0080 /**< stream for hearing impaired audiences */
|
||||
#define AV_DISPOSITION_VISUAL_IMPAIRED 0x0100 /**< stream for visual impaired audiences */
|
||||
#define AV_DISPOSITION_CLEAN_EFFECTS 0x0200 /**< stream without voice */
|
||||
/**
|
||||
* The stream is stored in the file as an attached picture/"cover art" (e.g.
|
||||
* APIC frame in ID3v2). The first (usually only) packet associated with it
|
||||
* will be returned among the first few packets read from the file unless
|
||||
* seeking takes place. It can also be accessed at any time in
|
||||
* AVStream.attached_pic.
|
||||
*/
|
||||
#define AV_DISPOSITION_ATTACHED_PIC 0x0400
|
||||
/**
|
||||
* The stream is sparse, and contains thumbnail images, often corresponding
|
||||
* to chapter markers. Only ever used with AV_DISPOSITION_ATTACHED_PIC.
|
||||
*/
|
||||
#define AV_DISPOSITION_TIMED_THUMBNAILS 0x0800
|
||||
|
||||
typedef struct AVStreamInternal AVStreamInternal;
|
||||
|
||||
/**
|
||||
* To specify text track kind (different from subtitles default).
|
||||
*/
|
||||
#define AV_DISPOSITION_CAPTIONS 0x10000
|
||||
#define AV_DISPOSITION_DESCRIPTIONS 0x20000
|
||||
#define AV_DISPOSITION_METADATA 0x40000
|
||||
#define AV_DISPOSITION_DEPENDENT 0x80000 ///< dependent audio stream (mix_type=0 in mpegts)
|
||||
#define AV_DISPOSITION_STILL_IMAGE 0x100000 ///< still images in video stream (still_picture_flag=1 in mpegts)
|
||||
|
||||
/**
|
||||
* Options for behavior on timestamp wrap detection.
|
||||
*/
|
||||
#define AV_PTS_WRAP_IGNORE 0 ///< ignore the wrap
|
||||
#define AV_PTS_WRAP_ADD_OFFSET 1 ///< add the format specific offset on wrap detection
|
||||
#define AV_PTS_WRAP_SUB_OFFSET -1 ///< subtract the format specific offset on wrap detection
|
||||
|
||||
/**
|
||||
* Stream structure.
|
||||
* New fields can be added to the end with minor version bumps.
|
||||
* Removal, reordering and changes to existing fields require a major
|
||||
* version bump.
|
||||
* sizeof(AVStream) must not be used outside libav*.
|
||||
*/
|
||||
typedef struct AVStream {
|
||||
int index; /**< stream index in AVFormatContext */
|
||||
/**
|
||||
* Format-specific stream ID.
|
||||
* decoding: set by libavformat
|
||||
* encoding: set by the user, replaced by libavformat if left unset
|
||||
*/
|
||||
int id;
|
||||
#if FF_API_LAVF_AVCTX
|
||||
/**
|
||||
* @deprecated use the codecpar struct instead
|
||||
*/
|
||||
attribute_deprecated
|
||||
AVCodecContext *codec;
|
||||
#endif
|
||||
void *priv_data;
|
||||
|
||||
/**
|
||||
* This is the fundamental unit of time (in seconds) in terms
|
||||
* of which frame timestamps are represented.
|
||||
*
|
||||
* decoding: set by libavformat
|
||||
* encoding: May be set by the caller before avformat_write_header() to
|
||||
* provide a hint to the muxer about the desired timebase. In
|
||||
* avformat_write_header(), the muxer will overwrite this field
|
||||
* with the timebase that will actually be used for the timestamps
|
||||
* written into the file (which may or may not be related to the
|
||||
* user-provided one, depending on the format).
|
||||
*/
|
||||
AVRational time_base;
|
||||
|
||||
/**
|
||||
* Decoding: pts of the first frame of the stream in presentation order, in stream time base.
|
||||
* Only set this if you are absolutely 100% sure that the value you set
|
||||
* it to really is the pts of the first frame.
|
||||
* This may be undefined (AV_NOPTS_VALUE).
|
||||
* @note The ASF header does NOT contain a correct start_time the ASF
|
||||
* demuxer must NOT set this.
|
||||
*/
|
||||
int64_t start_time;
|
||||
|
||||
/**
|
||||
* Decoding: duration of the stream, in stream time base.
|
||||
* If a source file does not specify a duration, but does specify
|
||||
* a bitrate, this value will be estimated from bitrate and file size.
|
||||
*
|
||||
* Encoding: May be set by the caller before avformat_write_header() to
|
||||
* provide a hint to the muxer about the estimated duration.
|
||||
*/
|
||||
int64_t duration;
|
||||
|
||||
int64_t nb_frames; ///< number of frames in this stream if known or 0
|
||||
|
||||
int disposition; /**< AV_DISPOSITION_* bit field */
|
||||
|
||||
enum AVDiscard discard; ///< Selects which packets can be discarded at will and do not need to be demuxed.
|
||||
|
||||
/**
|
||||
* sample aspect ratio (0 if unknown)
|
||||
* - encoding: Set by user.
|
||||
* - decoding: Set by libavformat.
|
||||
*/
|
||||
AVRational sample_aspect_ratio;
|
||||
|
||||
AVDictionary *metadata;
|
||||
|
||||
/**
|
||||
* Average framerate
|
||||
*
|
||||
* - demuxing: May be set by libavformat when creating the stream or in
|
||||
* avformat_find_stream_info().
|
||||
* - muxing: May be set by the caller before avformat_write_header().
|
||||
*/
|
||||
AVRational avg_frame_rate;
|
||||
|
||||
/**
|
||||
* For streams with AV_DISPOSITION_ATTACHED_PIC disposition, this packet
|
||||
* will contain the attached picture.
|
||||
*
|
||||
* decoding: set by libavformat, must not be modified by the caller.
|
||||
* encoding: unused
|
||||
*/
|
||||
AVPacket attached_pic;
|
||||
|
||||
/**
|
||||
* An array of side data that applies to the whole stream (i.e. the
|
||||
* container does not allow it to change between packets).
|
||||
*
|
||||
* There may be no overlap between the side data in this array and side data
|
||||
* in the packets. I.e. a given side data is either exported by the muxer
|
||||
* (demuxing) / set by the caller (muxing) in this array, then it never
|
||||
* appears in the packets, or the side data is exported / sent through
|
||||
* the packets (always in the first packet where the value becomes known or
|
||||
* changes), then it does not appear in this array.
|
||||
*
|
||||
* - demuxing: Set by libavformat when the stream is created.
|
||||
* - muxing: May be set by the caller before avformat_write_header().
|
||||
*
|
||||
* Freed by libavformat in avformat_free_context().
|
||||
*
|
||||
* @see av_format_inject_global_side_data()
|
||||
*/
|
||||
AVPacketSideData *side_data;
|
||||
/**
|
||||
* The number of elements in the AVStream.side_data array.
|
||||
*/
|
||||
int nb_side_data;
|
||||
|
||||
/**
|
||||
* Flags for the user to detect events happening on the stream. Flags must
|
||||
* be cleared by the user once the event has been handled.
|
||||
* A combination of AVSTREAM_EVENT_FLAG_*.
|
||||
*/
|
||||
int event_flags;
|
||||
#define AVSTREAM_EVENT_FLAG_METADATA_UPDATED 0x0001 ///< The call resulted in updated metadata.
|
||||
|
||||
/**
|
||||
* Real base framerate of the stream.
|
||||
* This is the lowest framerate with which all timestamps can be
|
||||
* represented accurately (it is the least common multiple of all
|
||||
* framerates in the stream). Note, this value is just a guess!
|
||||
* For example, if the time base is 1/90000 and all frames have either
|
||||
* approximately 3600 or 1800 timer ticks, then r_frame_rate will be 50/1.
|
||||
*/
|
||||
AVRational r_frame_rate;
|
||||
|
||||
#if FF_API_LAVF_FFSERVER
|
||||
/**
|
||||
* String containing pairs of key and values describing recommended encoder configuration.
|
||||
* Pairs are separated by ','.
|
||||
* Keys are separated from values by '='.
|
||||
*
|
||||
* @deprecated unused
|
||||
*/
|
||||
attribute_deprecated
|
||||
char *recommended_encoder_configuration;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Codec parameters associated with this stream. Allocated and freed by
|
||||
* libavformat in avformat_new_stream() and avformat_free_context()
|
||||
* respectively.
|
||||
*
|
||||
* - demuxing: filled by libavformat on stream creation or in
|
||||
* avformat_find_stream_info()
|
||||
* - muxing: filled by the caller before avformat_write_header()
|
||||
*/
|
||||
AVCodecParameters *codecpar;
|
||||
|
||||
/*****************************************************************
|
||||
* All fields below this line are not part of the public API. They
|
||||
* may not be used outside of libavformat and can be changed and
|
||||
* removed at will.
|
||||
* Internal note: be aware that physically removing these fields
|
||||
* will break ABI. Replace removed fields with dummy fields, and
|
||||
* add new fields to AVStreamInternal.
|
||||
*****************************************************************
|
||||
*/
|
||||
|
||||
#define MAX_STD_TIMEBASES (30*12+30+3+6)
|
||||
/**
|
||||
* Stream information used internally by avformat_find_stream_info()
|
||||
*/
|
||||
struct {
|
||||
int64_t last_dts;
|
||||
int64_t duration_gcd;
|
||||
int duration_count;
|
||||
int64_t rfps_duration_sum;
|
||||
double (*duration_error)[2][MAX_STD_TIMEBASES];
|
||||
int64_t codec_info_duration;
|
||||
int64_t codec_info_duration_fields;
|
||||
int frame_delay_evidence;
|
||||
|
||||
/**
|
||||
* 0 -> decoder has not been searched for yet.
|
||||
* >0 -> decoder found
|
||||
* <0 -> decoder with codec_id == -found_decoder has not been found
|
||||
*/
|
||||
int found_decoder;
|
||||
|
||||
int64_t last_duration;
|
||||
|
||||
/**
|
||||
* Those are used for average framerate estimation.
|
||||
*/
|
||||
int64_t fps_first_dts;
|
||||
int fps_first_dts_idx;
|
||||
int64_t fps_last_dts;
|
||||
int fps_last_dts_idx;
|
||||
|
||||
} *info;
|
||||
|
||||
int pts_wrap_bits; /**< number of bits in pts (used for wrapping control) */
|
||||
|
||||
// Timestamp generation support:
|
||||
/**
|
||||
* Timestamp corresponding to the last dts sync point.
|
||||
*
|
||||
* Initialized when AVCodecParserContext.dts_sync_point >= 0 and
|
||||
* a DTS is received from the underlying container. Otherwise set to
|
||||
* AV_NOPTS_VALUE by default.
|
||||
*/
|
||||
int64_t first_dts;
|
||||
int64_t cur_dts;
|
||||
int64_t last_IP_pts;
|
||||
int last_IP_duration;
|
||||
|
||||
/**
|
||||
* Number of packets to buffer for codec probing
|
||||
*/
|
||||
int probe_packets;
|
||||
|
||||
/**
|
||||
* Number of frames that have been demuxed during avformat_find_stream_info()
|
||||
*/
|
||||
int codec_info_nb_frames;
|
||||
|
||||
/* av_read_frame() support */
|
||||
enum AVStreamParseType need_parsing;
|
||||
struct AVCodecParserContext *parser;
|
||||
|
||||
/**
|
||||
* last packet in packet_buffer for this stream when muxing.
|
||||
*/
|
||||
struct AVPacketList *last_in_packet_buffer;
|
||||
AVProbeData probe_data;
|
||||
#define MAX_REORDER_DELAY 16
|
||||
int64_t pts_buffer[MAX_REORDER_DELAY+1];
|
||||
|
||||
AVIndexEntry *index_entries; /**< Only used if the format does not
|
||||
support seeking natively. */
|
||||
int nb_index_entries;
|
||||
unsigned int index_entries_allocated_size;
|
||||
|
||||
/**
|
||||
* Stream Identifier
|
||||
* This is the MPEG-TS stream identifier +1
|
||||
* 0 means unknown
|
||||
*/
|
||||
int stream_identifier;
|
||||
|
||||
/**
|
||||
* Details of the MPEG-TS program which created this stream.
|
||||
*/
|
||||
int program_num;
|
||||
int pmt_version;
|
||||
int pmt_stream_idx;
|
||||
|
||||
int64_t interleaver_chunk_size;
|
||||
int64_t interleaver_chunk_duration;
|
||||
|
||||
/**
|
||||
* stream probing state
|
||||
* -1 -> probing finished
|
||||
* 0 -> no probing requested
|
||||
* rest -> perform probing with request_probe being the minimum score to accept.
|
||||
* NOT PART OF PUBLIC API
|
||||
*/
|
||||
int request_probe;
|
||||
/**
|
||||
* Indicates that everything up to the next keyframe
|
||||
* should be discarded.
|
||||
*/
|
||||
int skip_to_keyframe;
|
||||
|
||||
/**
|
||||
* Number of samples to skip at the start of the frame decoded from the next packet.
|
||||
*/
|
||||
int skip_samples;
|
||||
|
||||
/**
|
||||
* If not 0, the number of samples that should be skipped from the start of
|
||||
* the stream (the samples are removed from packets with pts==0, which also
|
||||
* assumes negative timestamps do not happen).
|
||||
* Intended for use with formats such as mp3 with ad-hoc gapless audio
|
||||
* support.
|
||||
*/
|
||||
int64_t start_skip_samples;
|
||||
|
||||
/**
|
||||
* If not 0, the first audio sample that should be discarded from the stream.
|
||||
* This is broken by design (needs global sample count), but can't be
|
||||
* avoided for broken by design formats such as mp3 with ad-hoc gapless
|
||||
* audio support.
|
||||
*/
|
||||
int64_t first_discard_sample;
|
||||
|
||||
/**
|
||||
* The sample after last sample that is intended to be discarded after
|
||||
* first_discard_sample. Works on frame boundaries only. Used to prevent
|
||||
* early EOF if the gapless info is broken (considered concatenated mp3s).
|
||||
*/
|
||||
int64_t last_discard_sample;
|
||||
|
||||
/**
|
||||
* Number of internally decoded frames, used internally in libavformat, do not access
|
||||
* its lifetime differs from info which is why it is not in that structure.
|
||||
*/
|
||||
int nb_decoded_frames;
|
||||
|
||||
/**
|
||||
* Timestamp offset added to timestamps before muxing
|
||||
* NOT PART OF PUBLIC API
|
||||
*/
|
||||
int64_t mux_ts_offset;
|
||||
|
||||
/**
|
||||
* Internal data to check for wrapping of the time stamp
|
||||
*/
|
||||
int64_t pts_wrap_reference;
|
||||
|
||||
/**
|
||||
* Options for behavior, when a wrap is detected.
|
||||
*
|
||||
* Defined by AV_PTS_WRAP_ values.
|
||||
*
|
||||
* If correction is enabled, there are two possibilities:
|
||||
* If the first time stamp is near the wrap point, the wrap offset
|
||||
* will be subtracted, which will create negative time stamps.
|
||||
* Otherwise the offset will be added.
|
||||
*/
|
||||
int pts_wrap_behavior;
|
||||
|
||||
/**
|
||||
* Internal data to prevent doing update_initial_durations() twice
|
||||
*/
|
||||
int update_initial_durations_done;
|
||||
|
||||
/**
|
||||
* Internal data to generate dts from pts
|
||||
*/
|
||||
int64_t pts_reorder_error[MAX_REORDER_DELAY+1];
|
||||
uint8_t pts_reorder_error_count[MAX_REORDER_DELAY+1];
|
||||
|
||||
/**
|
||||
* Internal data to analyze DTS and detect faulty mpeg streams
|
||||
*/
|
||||
int64_t last_dts_for_order_check;
|
||||
uint8_t dts_ordered;
|
||||
uint8_t dts_misordered;
|
||||
|
||||
/**
|
||||
* Internal data to inject global side data
|
||||
*/
|
||||
int inject_global_side_data;
|
||||
|
||||
/**
|
||||
* display aspect ratio (0 if unknown)
|
||||
* - encoding: unused
|
||||
* - decoding: Set by libavformat to calculate sample_aspect_ratio internally
|
||||
*/
|
||||
AVRational display_aspect_ratio;
|
||||
|
||||
/**
|
||||
* An opaque field for libavformat internal usage.
|
||||
* Must not be accessed in any way by callers.
|
||||
*/
|
||||
AVStreamInternal *internal;
|
||||
} AVStream;
|
||||
|
||||
#if FF_API_FORMAT_GET_SET
|
||||
/**
|
||||
* Accessors for some AVStream fields. These used to be provided for ABI
|
||||
* compatibility, and do not need to be used anymore.
|
||||
*/
|
||||
attribute_deprecated
|
||||
AVRational av_stream_get_r_frame_rate(const AVStream *s);
|
||||
attribute_deprecated
|
||||
void av_stream_set_r_frame_rate(AVStream *s, AVRational r);
|
||||
#if FF_API_LAVF_FFSERVER
|
||||
attribute_deprecated
|
||||
char* av_stream_get_recommended_encoder_configuration(const AVStream *s);
|
||||
attribute_deprecated
|
||||
void av_stream_set_recommended_encoder_configuration(AVStream *s, char *configuration);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
struct AVCodecParserContext *av_stream_get_parser(const AVStream *s);
|
||||
|
||||
/**
|
||||
* Returns the pts of the last muxed packet + its duration
|
||||
*
|
||||
* the retuned value is undefined when used with a demuxer.
|
||||
*/
|
||||
int64_t av_stream_get_end_pts(const AVStream *st);
|
||||
|
||||
#define AV_PROGRAM_RUNNING 1
|
||||
|
||||
/**
|
||||
* New fields can be added to the end with minor version bumps.
|
||||
* Removal, reordering and changes to existing fields require a major
|
||||
* version bump.
|
||||
* sizeof(AVProgram) must not be used outside libav*.
|
||||
*/
|
||||
typedef struct AVProgram {
|
||||
int id;
|
||||
int flags;
|
||||
enum AVDiscard discard; ///< selects which program to discard and which to feed to the caller
|
||||
unsigned int *stream_index;
|
||||
unsigned int nb_stream_indexes;
|
||||
AVDictionary *metadata;
|
||||
|
||||
int program_num;
|
||||
int pmt_pid;
|
||||
int pcr_pid;
|
||||
int pmt_version;
|
||||
|
||||
/*****************************************************************
|
||||
* All fields below this line are not part of the public API. They
|
||||
* may not be used outside of libavformat and can be changed and
|
||||
* removed at will.
|
||||
* New public fields should be added right above.
|
||||
*****************************************************************
|
||||
*/
|
||||
int64_t start_time;
|
||||
int64_t end_time;
|
||||
|
||||
int64_t pts_wrap_reference; ///< reference dts for wrap detection
|
||||
int pts_wrap_behavior; ///< behavior on wrap detection
|
||||
} AVProgram;
|
||||
|
||||
#define AVFMTCTX_NOHEADER 0x0001 /**< signal that no header is present
|
||||
(streams are added dynamically) */
|
||||
#define AVFMTCTX_UNSEEKABLE 0x0002 /**< signal that the stream is definitely
|
||||
not seekable, and attempts to call the
|
||||
seek function will fail. For some
|
||||
network protocols (e.g. HLS), this can
|
||||
change dynamically at runtime. */
|
||||
|
||||
typedef struct AVChapter {
|
||||
int id; ///< unique ID to identify the chapter
|
||||
AVRational time_base; ///< time base in which the start/end timestamps are specified
|
||||
int64_t start, end; ///< chapter start/end time in time_base units
|
||||
AVDictionary *metadata;
|
||||
} AVChapter;
|
||||
|
||||
|
||||
/**
|
||||
* Callback used by devices to communicate with application.
|
||||
*/
|
||||
typedef int (*av_format_control_message)(struct AVFormatContext *s, int type,
|
||||
void *data, size_t data_size);
|
||||
|
||||
typedef int (*AVOpenCallback)(struct AVFormatContext *s, AVIOContext **pb, const char *url, int flags,
|
||||
const AVIOInterruptCB *int_cb, AVDictionary **options);
|
||||
|
||||
/**
|
||||
* The duration of a video can be estimated through various ways, and this enum can be used
|
||||
* to know how the duration was estimated.
|
||||
*/
|
||||
enum AVDurationEstimationMethod {
|
||||
AVFMT_DURATION_FROM_PTS, ///< Duration accurately estimated from PTSes
|
||||
AVFMT_DURATION_FROM_STREAM, ///< Duration estimated from a stream with a known duration
|
||||
AVFMT_DURATION_FROM_BITRATE ///< Duration estimated from bitrate (less accurate)
|
||||
};
|
||||
|
||||
typedef struct AVFormatInternal AVFormatInternal;
|
||||
|
||||
/**
|
||||
* Format I/O context.
|
||||
* New fields can be added to the end with minor version bumps.
|
||||
* Removal, reordering and changes to existing fields require a major
|
||||
* version bump.
|
||||
* sizeof(AVFormatContext) must not be used outside libav*, use
|
||||
* avformat_alloc_context() to create an AVFormatContext.
|
||||
*
|
||||
* Fields can be accessed through AVOptions (av_opt*),
|
||||
* the name string used matches the associated command line parameter name and
|
||||
* can be found in libavformat/options_table.h.
|
||||
* The AVOption/command line parameter names differ in some cases from the C
|
||||
* structure field names for historic reasons or brevity.
|
||||
*/
|
||||
typedef struct AVFormatContext {
|
||||
/**
|
||||
* A class for logging and @ref avoptions. Set by avformat_alloc_context().
|
||||
* Exports (de)muxer private options if they exist.
|
||||
*/
|
||||
const AVClass *av_class;
|
||||
|
||||
/**
|
||||
* The input container format.
|
||||
*
|
||||
* Demuxing only, set by avformat_open_input().
|
||||
*/
|
||||
struct AVInputFormat *iformat;
|
||||
|
||||
/**
|
||||
* The output container format.
|
||||
*
|
||||
* Muxing only, must be set by the caller before avformat_write_header().
|
||||
*/
|
||||
struct AVOutputFormat *oformat;
|
||||
|
||||
/**
|
||||
* Format private data. This is an AVOptions-enabled struct
|
||||
* if and only if iformat/oformat.priv_class is not NULL.
|
||||
*
|
||||
* - muxing: set by avformat_write_header()
|
||||
* - demuxing: set by avformat_open_input()
|
||||
*/
|
||||
void *priv_data;
|
||||
|
||||
/**
|
||||
* I/O context.
|
||||
*
|
||||
* - demuxing: either set by the user before avformat_open_input() (then
|
||||
* the user must close it manually) or set by avformat_open_input().
|
||||
* - muxing: set by the user before avformat_write_header(). The caller must
|
||||
* take care of closing / freeing the IO context.
|
||||
*
|
||||
* Do NOT set this field if AVFMT_NOFILE flag is set in
|
||||
* iformat/oformat.flags. In such a case, the (de)muxer will handle
|
||||
* I/O in some other way and this field will be NULL.
|
||||
*/
|
||||
AVIOContext *pb;
|
||||
|
||||
/* stream info */
|
||||
/**
|
||||
* Flags signalling stream properties. A combination of AVFMTCTX_*.
|
||||
* Set by libavformat.
|
||||
*/
|
||||
int ctx_flags;
|
||||
|
||||
/**
|
||||
* Number of elements in AVFormatContext.streams.
|
||||
*
|
||||
* Set by avformat_new_stream(), must not be modified by any other code.
|
||||
*/
|
||||
unsigned int nb_streams;
|
||||
/**
|
||||
* A list of all streams in the file. New streams are created with
|
||||
* avformat_new_stream().
|
||||
*
|
||||
* - demuxing: streams are created by libavformat in avformat_open_input().
|
||||
* If AVFMTCTX_NOHEADER is set in ctx_flags, then new streams may also
|
||||
* appear in av_read_frame().
|
||||
* - muxing: streams are created by the user before avformat_write_header().
|
||||
*
|
||||
* Freed by libavformat in avformat_free_context().
|
||||
*/
|
||||
AVStream **streams;
|
||||
|
||||
#if FF_API_FORMAT_FILENAME
|
||||
/**
|
||||
* input or output filename
|
||||
*
|
||||
* - demuxing: set by avformat_open_input()
|
||||
* - muxing: may be set by the caller before avformat_write_header()
|
||||
*
|
||||
* @deprecated Use url instead.
|
||||
*/
|
||||
attribute_deprecated
|
||||
char filename[1024];
|
||||
#endif
|
||||
|
||||
/**
|
||||
* input or output URL. Unlike the old filename field, this field has no
|
||||
* length restriction.
|
||||
*
|
||||
* - demuxing: set by avformat_open_input(), initialized to an empty
|
||||
* string if url parameter was NULL in avformat_open_input().
|
||||
* - muxing: may be set by the caller before calling avformat_write_header()
|
||||
* (or avformat_init_output() if that is called first) to a string
|
||||
* which is freeable by av_free(). Set to an empty string if it
|
||||
* was NULL in avformat_init_output().
|
||||
*
|
||||
* Freed by libavformat in avformat_free_context().
|
||||
*/
|
||||
char *url;
|
||||
|
||||
/**
|
||||
* Position of the first frame of the component, in
|
||||
* AV_TIME_BASE fractional seconds. NEVER set this value directly:
|
||||
* It is deduced from the AVStream values.
|
||||
*
|
||||
* Demuxing only, set by libavformat.
|
||||
*/
|
||||
int64_t start_time;
|
||||
|
||||
/**
|
||||
* Duration of the stream, in AV_TIME_BASE fractional
|
||||
* seconds. Only set this value if you know none of the individual stream
|
||||
* durations and also do not set any of them. This is deduced from the
|
||||
* AVStream values if not set.
|
||||
*
|
||||
* Demuxing only, set by libavformat.
|
||||
*/
|
||||
int64_t duration;
|
||||
|
||||
/**
|
||||
* Total stream bitrate in bit/s, 0 if not
|
||||
* available. Never set it directly if the file_size and the
|
||||
* duration are known as FFmpeg can compute it automatically.
|
||||
*/
|
||||
int64_t bit_rate;
|
||||
|
||||
unsigned int packet_size;
|
||||
int max_delay;
|
||||
|
||||
/**
|
||||
* Flags modifying the (de)muxer behaviour. A combination of AVFMT_FLAG_*.
|
||||
* Set by the user before avformat_open_input() / avformat_write_header().
|
||||
*/
|
||||
int flags;
|
||||
#define AVFMT_FLAG_GENPTS 0x0001 ///< Generate missing pts even if it requires parsing future frames.
|
||||
#define AVFMT_FLAG_IGNIDX 0x0002 ///< Ignore index.
|
||||
#define AVFMT_FLAG_NONBLOCK 0x0004 ///< Do not block when reading packets from input.
|
||||
#define AVFMT_FLAG_IGNDTS 0x0008 ///< Ignore DTS on frames that contain both DTS & PTS
|
||||
#define AVFMT_FLAG_NOFILLIN 0x0010 ///< Do not infer any values from other values, just return what is stored in the container
|
||||
#define AVFMT_FLAG_NOPARSE 0x0020 ///< Do not use AVParsers, you also must set AVFMT_FLAG_NOFILLIN as the fillin code works on frames and no parsing -> no frames. Also seeking to frames can not work if parsing to find frame boundaries has been disabled
|
||||
#define AVFMT_FLAG_NOBUFFER 0x0040 ///< Do not buffer frames when possible
|
||||
#define AVFMT_FLAG_CUSTOM_IO 0x0080 ///< The caller has supplied a custom AVIOContext, don't avio_close() it.
|
||||
#define AVFMT_FLAG_DISCARD_CORRUPT 0x0100 ///< Discard frames marked corrupted
|
||||
#define AVFMT_FLAG_FLUSH_PACKETS 0x0200 ///< Flush the AVIOContext every packet.
|
||||
/**
|
||||
* When muxing, try to avoid writing any random/volatile data to the output.
|
||||
* This includes any random IDs, real-time timestamps/dates, muxer version, etc.
|
||||
*
|
||||
* This flag is mainly intended for testing.
|
||||
*/
|
||||
#define AVFMT_FLAG_BITEXACT 0x0400
|
||||
#if FF_API_LAVF_MP4A_LATM
|
||||
#define AVFMT_FLAG_MP4A_LATM 0x8000 ///< Deprecated, does nothing.
|
||||
#endif
|
||||
#define AVFMT_FLAG_SORT_DTS 0x10000 ///< try to interleave outputted packets by dts (using this flag can slow demuxing down)
|
||||
#define AVFMT_FLAG_PRIV_OPT 0x20000 ///< Enable use of private options by delaying codec open (this could be made default once all code is converted)
|
||||
#if FF_API_LAVF_KEEPSIDE_FLAG
|
||||
#define AVFMT_FLAG_KEEP_SIDE_DATA 0x40000 ///< Deprecated, does nothing.
|
||||
#endif
|
||||
#define AVFMT_FLAG_FAST_SEEK 0x80000 ///< Enable fast, but inaccurate seeks for some formats
|
||||
#define AVFMT_FLAG_SHORTEST 0x100000 ///< Stop muxing when the shortest stream stops.
|
||||
#define AVFMT_FLAG_AUTO_BSF 0x200000 ///< Add bitstream filters as requested by the muxer
|
||||
|
||||
/**
|
||||
* Maximum size of the data read from input for determining
|
||||
* the input container format.
|
||||
* Demuxing only, set by the caller before avformat_open_input().
|
||||
*/
|
||||
int64_t probesize;
|
||||
|
||||
/**
|
||||
* Maximum duration (in AV_TIME_BASE units) of the data read
|
||||
* from input in avformat_find_stream_info().
|
||||
* Demuxing only, set by the caller before avformat_find_stream_info().
|
||||
* Can be set to 0 to let avformat choose using a heuristic.
|
||||
*/
|
||||
int64_t max_analyze_duration;
|
||||
|
||||
const uint8_t *key;
|
||||
int keylen;
|
||||
|
||||
unsigned int nb_programs;
|
||||
AVProgram **programs;
|
||||
|
||||
/**
|
||||
* Forced video codec_id.
|
||||
* Demuxing: Set by user.
|
||||
*/
|
||||
enum AVCodecID video_codec_id;
|
||||
|
||||
/**
|
||||
* Forced audio codec_id.
|
||||
* Demuxing: Set by user.
|
||||
*/
|
||||
enum AVCodecID audio_codec_id;
|
||||
|
||||
/**
|
||||
* Forced subtitle codec_id.
|
||||
* Demuxing: Set by user.
|
||||
*/
|
||||
enum AVCodecID subtitle_codec_id;
|
||||
|
||||
/**
|
||||
* Maximum amount of memory in bytes to use for the index of each stream.
|
||||
* If the index exceeds this size, entries will be discarded as
|
||||
* needed to maintain a smaller size. This can lead to slower or less
|
||||
* accurate seeking (depends on demuxer).
|
||||
* Demuxers for which a full in-memory index is mandatory will ignore
|
||||
* this.
|
||||
* - muxing: unused
|
||||
* - demuxing: set by user
|
||||
*/
|
||||
unsigned int max_index_size;
|
||||
|
||||
/**
|
||||
* Maximum amount of memory in bytes to use for buffering frames
|
||||
* obtained from realtime capture devices.
|
||||
*/
|
||||
unsigned int max_picture_buffer;
|
||||
|
||||
/**
|
||||
* Number of chapters in AVChapter array.
|
||||
* When muxing, chapters are normally written in the file header,
|
||||
* so nb_chapters should normally be initialized before write_header
|
||||
* is called. Some muxers (e.g. mov and mkv) can also write chapters
|
||||
* in the trailer. To write chapters in the trailer, nb_chapters
|
||||
* must be zero when write_header is called and non-zero when
|
||||
* write_trailer is called.
|
||||
* - muxing: set by user
|
||||
* - demuxing: set by libavformat
|
||||
*/
|
||||
unsigned int nb_chapters;
|
||||
AVChapter **chapters;
|
||||
|
||||
/**
|
||||
* Metadata that applies to the whole file.
|
||||
*
|
||||
* - demuxing: set by libavformat in avformat_open_input()
|
||||
* - muxing: may be set by the caller before avformat_write_header()
|
||||
*
|
||||
* Freed by libavformat in avformat_free_context().
|
||||
*/
|
||||
AVDictionary *metadata;
|
||||
|
||||
/**
|
||||
* Start time of the stream in real world time, in microseconds
|
||||
* since the Unix epoch (00:00 1st January 1970). That is, pts=0 in the
|
||||
* stream was captured at this real world time.
|
||||
* - muxing: Set by the caller before avformat_write_header(). If set to
|
||||
* either 0 or AV_NOPTS_VALUE, then the current wall-time will
|
||||
* be used.
|
||||
* - demuxing: Set by libavformat. AV_NOPTS_VALUE if unknown. Note that
|
||||
* the value may become known after some number of frames
|
||||
* have been received.
|
||||
*/
|
||||
int64_t start_time_realtime;
|
||||
|
||||
/**
|
||||
* The number of frames used for determining the framerate in
|
||||
* avformat_find_stream_info().
|
||||
* Demuxing only, set by the caller before avformat_find_stream_info().
|
||||
*/
|
||||
int fps_probe_size;
|
||||
|
||||
/**
|
||||
* Error recognition; higher values will detect more errors but may
|
||||
* misdetect some more or less valid parts as errors.
|
||||
* Demuxing only, set by the caller before avformat_open_input().
|
||||
*/
|
||||
int error_recognition;
|
||||
|
||||
/**
|
||||
* Custom interrupt callbacks for the I/O layer.
|
||||
*
|
||||
* demuxing: set by the user before avformat_open_input().
|
||||
* muxing: set by the user before avformat_write_header()
|
||||
* (mainly useful for AVFMT_NOFILE formats). The callback
|
||||
* should also be passed to avio_open2() if it's used to
|
||||
* open the file.
|
||||
*/
|
||||
AVIOInterruptCB interrupt_callback;
|
||||
|
||||
/**
|
||||
* Flags to enable debugging.
|
||||
*/
|
||||
int debug;
|
||||
#define FF_FDEBUG_TS 0x0001
|
||||
|
||||
/**
|
||||
* Maximum buffering duration for interleaving.
|
||||
*
|
||||
* To ensure all the streams are interleaved correctly,
|
||||
* av_interleaved_write_frame() will wait until it has at least one packet
|
||||
* for each stream before actually writing any packets to the output file.
|
||||
* When some streams are "sparse" (i.e. there are large gaps between
|
||||
* successive packets), this can result in excessive buffering.
|
||||
*
|
||||
* This field specifies the maximum difference between the timestamps of the
|
||||
* first and the last packet in the muxing queue, above which libavformat
|
||||
* will output a packet regardless of whether it has queued a packet for all
|
||||
* the streams.
|
||||
*
|
||||
* Muxing only, set by the caller before avformat_write_header().
|
||||
*/
|
||||
int64_t max_interleave_delta;
|
||||
|
||||
/**
|
||||
* Allow non-standard and experimental extension
|
||||
* @see AVCodecContext.strict_std_compliance
|
||||
*/
|
||||
int strict_std_compliance;
|
||||
|
||||
/**
|
||||
* Flags for the user to detect events happening on the file. Flags must
|
||||
* be cleared by the user once the event has been handled.
|
||||
* A combination of AVFMT_EVENT_FLAG_*.
|
||||
*/
|
||||
int event_flags;
|
||||
#define AVFMT_EVENT_FLAG_METADATA_UPDATED 0x0001 ///< The call resulted in updated metadata.
|
||||
|
||||
/**
|
||||
* Maximum number of packets to read while waiting for the first timestamp.
|
||||
* Decoding only.
|
||||
*/
|
||||
int max_ts_probe;
|
||||
|
||||
/**
|
||||
* Avoid negative timestamps during muxing.
|
||||
* Any value of the AVFMT_AVOID_NEG_TS_* constants.
|
||||
* Note, this only works when using av_interleaved_write_frame. (interleave_packet_per_dts is in use)
|
||||
* - muxing: Set by user
|
||||
* - demuxing: unused
|
||||
*/
|
||||
int avoid_negative_ts;
|
||||
#define AVFMT_AVOID_NEG_TS_AUTO -1 ///< Enabled when required by target format
|
||||
#define AVFMT_AVOID_NEG_TS_MAKE_NON_NEGATIVE 1 ///< Shift timestamps so they are non negative
|
||||
#define AVFMT_AVOID_NEG_TS_MAKE_ZERO 2 ///< Shift timestamps so that they start at 0
|
||||
|
||||
/**
|
||||
* Transport stream id.
|
||||
* This will be moved into demuxer private options. Thus no API/ABI compatibility
|
||||
*/
|
||||
int ts_id;
|
||||
|
||||
/**
|
||||
* Audio preload in microseconds.
|
||||
* Note, not all formats support this and unpredictable things may happen if it is used when not supported.
|
||||
* - encoding: Set by user
|
||||
* - decoding: unused
|
||||
*/
|
||||
int audio_preload;
|
||||
|
||||
/**
|
||||
* Max chunk time in microseconds.
|
||||
* Note, not all formats support this and unpredictable things may happen if it is used when not supported.
|
||||
* - encoding: Set by user
|
||||
* - decoding: unused
|
||||
*/
|
||||
int max_chunk_duration;
|
||||
|
||||
/**
|
||||
* Max chunk size in bytes
|
||||
* Note, not all formats support this and unpredictable things may happen if it is used when not supported.
|
||||
* - encoding: Set by user
|
||||
* - decoding: unused
|
||||
*/
|
||||
int max_chunk_size;
|
||||
|
||||
/**
|
||||
* forces the use of wallclock timestamps as pts/dts of packets
|
||||
* This has undefined results in the presence of B frames.
|
||||
* - encoding: unused
|
||||
* - decoding: Set by user
|
||||
*/
|
||||
int use_wallclock_as_timestamps;
|
||||
|
||||
/**
|
||||
* avio flags, used to force AVIO_FLAG_DIRECT.
|
||||
* - encoding: unused
|
||||
* - decoding: Set by user
|
||||
*/
|
||||
int avio_flags;
|
||||
|
||||
/**
|
||||
* The duration field can be estimated through various ways, and this field can be used
|
||||
* to know how the duration was estimated.
|
||||
* - encoding: unused
|
||||
* - decoding: Read by user
|
||||
*/
|
||||
enum AVDurationEstimationMethod duration_estimation_method;
|
||||
|
||||
/**
|
||||
* Skip initial bytes when opening stream
|
||||
* - encoding: unused
|
||||
* - decoding: Set by user
|
||||
*/
|
||||
int64_t skip_initial_bytes;
|
||||
|
||||
/**
|
||||
* Correct single timestamp overflows
|
||||
* - encoding: unused
|
||||
* - decoding: Set by user
|
||||
*/
|
||||
unsigned int correct_ts_overflow;
|
||||
|
||||
/**
|
||||
* Force seeking to any (also non key) frames.
|
||||
* - encoding: unused
|
||||
* - decoding: Set by user
|
||||
*/
|
||||
int seek2any;
|
||||
|
||||
/**
|
||||
* Flush the I/O context after each packet.
|
||||
* - encoding: Set by user
|
||||
* - decoding: unused
|
||||
*/
|
||||
int flush_packets;
|
||||
|
||||
/**
|
||||
* format probing score.
|
||||
* The maximal score is AVPROBE_SCORE_MAX, its set when the demuxer probes
|
||||
* the format.
|
||||
* - encoding: unused
|
||||
* - decoding: set by avformat, read by user
|
||||
*/
|
||||
int probe_score;
|
||||
|
||||
/**
|
||||
* number of bytes to read maximally to identify format.
|
||||
* - encoding: unused
|
||||
* - decoding: set by user
|
||||
*/
|
||||
int format_probesize;
|
||||
|
||||
/**
|
||||
* ',' separated list of allowed decoders.
|
||||
* If NULL then all are allowed
|
||||
* - encoding: unused
|
||||
* - decoding: set by user
|
||||
*/
|
||||
char *codec_whitelist;
|
||||
|
||||
/**
|
||||
* ',' separated list of allowed demuxers.
|
||||
* If NULL then all are allowed
|
||||
* - encoding: unused
|
||||
* - decoding: set by user
|
||||
*/
|
||||
char *format_whitelist;
|
||||
|
||||
/**
|
||||
* An opaque field for libavformat internal usage.
|
||||
* Must not be accessed in any way by callers.
|
||||
*/
|
||||
AVFormatInternal *internal;
|
||||
|
||||
/**
|
||||
* IO repositioned flag.
|
||||
* This is set by avformat when the underlaying IO context read pointer
|
||||
* is repositioned, for example when doing byte based seeking.
|
||||
* Demuxers can use the flag to detect such changes.
|
||||
*/
|
||||
int io_repositioned;
|
||||
|
||||
/**
|
||||
* Forced video codec.
|
||||
* This allows forcing a specific decoder, even when there are multiple with
|
||||
* the same codec_id.
|
||||
* Demuxing: Set by user
|
||||
*/
|
||||
AVCodec *video_codec;
|
||||
|
||||
/**
|
||||
* Forced audio codec.
|
||||
* This allows forcing a specific decoder, even when there are multiple with
|
||||
* the same codec_id.
|
||||
* Demuxing: Set by user
|
||||
*/
|
||||
AVCodec *audio_codec;
|
||||
|
||||
/**
|
||||
* Forced subtitle codec.
|
||||
* This allows forcing a specific decoder, even when there are multiple with
|
||||
* the same codec_id.
|
||||
* Demuxing: Set by user
|
||||
*/
|
||||
AVCodec *subtitle_codec;
|
||||
|
||||
/**
|
||||
* Forced data codec.
|
||||
* This allows forcing a specific decoder, even when there are multiple with
|
||||
* the same codec_id.
|
||||
* Demuxing: Set by user
|
||||
*/
|
||||
AVCodec *data_codec;
|
||||
|
||||
/**
|
||||
* Number of bytes to be written as padding in a metadata header.
|
||||
* Demuxing: Unused.
|
||||
* Muxing: Set by user via av_format_set_metadata_header_padding.
|
||||
*/
|
||||
int metadata_header_padding;
|
||||
|
||||
/**
|
||||
* User data.
|
||||
* This is a place for some private data of the user.
|
||||
*/
|
||||
void *opaque;
|
||||
|
||||
/**
|
||||
* Callback used by devices to communicate with application.
|
||||
*/
|
||||
av_format_control_message control_message_cb;
|
||||
|
||||
/**
|
||||
* Output timestamp offset, in microseconds.
|
||||
* Muxing: set by user
|
||||
*/
|
||||
int64_t output_ts_offset;
|
||||
|
||||
/**
|
||||
* dump format separator.
|
||||
* can be ", " or "\n " or anything else
|
||||
* - muxing: Set by user.
|
||||
* - demuxing: Set by user.
|
||||
*/
|
||||
uint8_t *dump_separator;
|
||||
|
||||
/**
|
||||
* Forced Data codec_id.
|
||||
* Demuxing: Set by user.
|
||||
*/
|
||||
enum AVCodecID data_codec_id;
|
||||
|
||||
#if FF_API_OLD_OPEN_CALLBACKS
|
||||
/**
|
||||
* Called to open further IO contexts when needed for demuxing.
|
||||
*
|
||||
* This can be set by the user application to perform security checks on
|
||||
* the URLs before opening them.
|
||||
* The function should behave like avio_open2(), AVFormatContext is provided
|
||||
* as contextual information and to reach AVFormatContext.opaque.
|
||||
*
|
||||
* If NULL then some simple checks are used together with avio_open2().
|
||||
*
|
||||
* Must not be accessed directly from outside avformat.
|
||||
* @See av_format_set_open_cb()
|
||||
*
|
||||
* Demuxing: Set by user.
|
||||
*
|
||||
* @deprecated Use io_open and io_close.
|
||||
*/
|
||||
attribute_deprecated
|
||||
int (*open_cb)(struct AVFormatContext *s, AVIOContext **p, const char *url, int flags, const AVIOInterruptCB *int_cb, AVDictionary **options);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* ',' separated list of allowed protocols.
|
||||
* - encoding: unused
|
||||
* - decoding: set by user
|
||||
*/
|
||||
char *protocol_whitelist;
|
||||
|
||||
/**
|
||||
* A callback for opening new IO streams.
|
||||
*
|
||||
* Whenever a muxer or a demuxer needs to open an IO stream (typically from
|
||||
* avformat_open_input() for demuxers, but for certain formats can happen at
|
||||
* other times as well), it will call this callback to obtain an IO context.
|
||||
*
|
||||
* @param s the format context
|
||||
* @param pb on success, the newly opened IO context should be returned here
|
||||
* @param url the url to open
|
||||
* @param flags a combination of AVIO_FLAG_*
|
||||
* @param options a dictionary of additional options, with the same
|
||||
* semantics as in avio_open2()
|
||||
* @return 0 on success, a negative AVERROR code on failure
|
||||
*
|
||||
* @note Certain muxers and demuxers do nesting, i.e. they open one or more
|
||||
* additional internal format contexts. Thus the AVFormatContext pointer
|
||||
* passed to this callback may be different from the one facing the caller.
|
||||
* It will, however, have the same 'opaque' field.
|
||||
*/
|
||||
int (*io_open)(struct AVFormatContext *s, AVIOContext **pb, const char *url,
|
||||
int flags, AVDictionary **options);
|
||||
|
||||
/**
|
||||
* A callback for closing the streams opened with AVFormatContext.io_open().
|
||||
*/
|
||||
void (*io_close)(struct AVFormatContext *s, AVIOContext *pb);
|
||||
|
||||
/**
|
||||
* ',' separated list of disallowed protocols.
|
||||
* - encoding: unused
|
||||
* - decoding: set by user
|
||||
*/
|
||||
char *protocol_blacklist;
|
||||
|
||||
/**
|
||||
* The maximum number of streams.
|
||||
* - encoding: unused
|
||||
* - decoding: set by user
|
||||
*/
|
||||
int max_streams;
|
||||
|
||||
/**
|
||||
* Skip duration calcuation in estimate_timings_from_pts.
|
||||
* - encoding: unused
|
||||
* - decoding: set by user
|
||||
*/
|
||||
int skip_estimate_duration_from_pts;
|
||||
} AVFormatContext;
|
||||
|
||||
#if FF_API_FORMAT_GET_SET
|
||||
/**
|
||||
* Accessors for some AVFormatContext fields. These used to be provided for ABI
|
||||
* compatibility, and do not need to be used anymore.
|
||||
*/
|
||||
attribute_deprecated
|
||||
int av_format_get_probe_score(const AVFormatContext *s);
|
||||
attribute_deprecated
|
||||
AVCodec * av_format_get_video_codec(const AVFormatContext *s);
|
||||
attribute_deprecated
|
||||
void av_format_set_video_codec(AVFormatContext *s, AVCodec *c);
|
||||
attribute_deprecated
|
||||
AVCodec * av_format_get_audio_codec(const AVFormatContext *s);
|
||||
attribute_deprecated
|
||||
void av_format_set_audio_codec(AVFormatContext *s, AVCodec *c);
|
||||
attribute_deprecated
|
||||
AVCodec * av_format_get_subtitle_codec(const AVFormatContext *s);
|
||||
attribute_deprecated
|
||||
void av_format_set_subtitle_codec(AVFormatContext *s, AVCodec *c);
|
||||
attribute_deprecated
|
||||
AVCodec * av_format_get_data_codec(const AVFormatContext *s);
|
||||
attribute_deprecated
|
||||
void av_format_set_data_codec(AVFormatContext *s, AVCodec *c);
|
||||
attribute_deprecated
|
||||
int av_format_get_metadata_header_padding(const AVFormatContext *s);
|
||||
attribute_deprecated
|
||||
void av_format_set_metadata_header_padding(AVFormatContext *s, int c);
|
||||
attribute_deprecated
|
||||
void * av_format_get_opaque(const AVFormatContext *s);
|
||||
attribute_deprecated
|
||||
void av_format_set_opaque(AVFormatContext *s, void *opaque);
|
||||
attribute_deprecated
|
||||
av_format_control_message av_format_get_control_message_cb(const AVFormatContext *s);
|
||||
attribute_deprecated
|
||||
void av_format_set_control_message_cb(AVFormatContext *s, av_format_control_message callback);
|
||||
#if FF_API_OLD_OPEN_CALLBACKS
|
||||
attribute_deprecated AVOpenCallback av_format_get_open_cb(const AVFormatContext *s);
|
||||
attribute_deprecated void av_format_set_open_cb(AVFormatContext *s, AVOpenCallback callback);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This function will cause global side data to be injected in the next packet
|
||||
* of each stream as well as after any subsequent seek.
|
||||
*/
|
||||
void av_format_inject_global_side_data(AVFormatContext *s);
|
||||
|
||||
/**
|
||||
* Returns the method used to set ctx->duration.
|
||||
*
|
||||
* @return AVFMT_DURATION_FROM_PTS, AVFMT_DURATION_FROM_STREAM, or AVFMT_DURATION_FROM_BITRATE.
|
||||
*/
|
||||
enum AVDurationEstimationMethod av_fmt_ctx_get_duration_estimation_method(const AVFormatContext* ctx);
|
||||
|
||||
typedef struct AVPacketList {
|
||||
AVPacket pkt;
|
||||
struct AVPacketList *next;
|
||||
} AVPacketList;
|
||||
|
||||
|
||||
/**
|
||||
* @defgroup lavf_core Core functions
|
||||
* @ingroup libavf
|
||||
*
|
||||
* Functions for querying libavformat capabilities, allocating core structures,
|
||||
* etc.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Return the LIBAVFORMAT_VERSION_INT constant.
|
||||
*/
|
||||
unsigned avformat_version(void);
|
||||
|
||||
/**
|
||||
* Return the libavformat build-time configuration.
|
||||
*/
|
||||
const char *avformat_configuration(void);
|
||||
|
||||
/**
|
||||
* Return the libavformat license.
|
||||
*/
|
||||
const char *avformat_license(void);
|
||||
|
||||
#if FF_API_NEXT
|
||||
/**
|
||||
* Initialize libavformat and register all the muxers, demuxers and
|
||||
* protocols. If you do not call this function, then you can select
|
||||
* exactly which formats you want to support.
|
||||
*
|
||||
* @see av_register_input_format()
|
||||
* @see av_register_output_format()
|
||||
*/
|
||||
attribute_deprecated
|
||||
void av_register_all(void);
|
||||
|
||||
attribute_deprecated
|
||||
void av_register_input_format(AVInputFormat *format);
|
||||
attribute_deprecated
|
||||
void av_register_output_format(AVOutputFormat *format);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Do global initialization of network libraries. This is optional,
|
||||
* and not recommended anymore.
|
||||
*
|
||||
* This functions only exists to work around thread-safety issues
|
||||
* with older GnuTLS or OpenSSL libraries. If libavformat is linked
|
||||
* to newer versions of those libraries, or if you do not use them,
|
||||
* calling this function is unnecessary. Otherwise, you need to call
|
||||
* this function before any other threads using them are started.
|
||||
*
|
||||
* This function will be deprecated once support for older GnuTLS and
|
||||
* OpenSSL libraries is removed, and this function has no purpose
|
||||
* anymore.
|
||||
*/
|
||||
int avformat_network_init(void);
|
||||
|
||||
/**
|
||||
* Undo the initialization done by avformat_network_init. Call it only
|
||||
* once for each time you called avformat_network_init.
|
||||
*/
|
||||
int avformat_network_deinit(void);
|
||||
|
||||
#if FF_API_NEXT
|
||||
/**
|
||||
* If f is NULL, returns the first registered input format,
|
||||
* if f is non-NULL, returns the next registered input format after f
|
||||
* or NULL if f is the last one.
|
||||
*/
|
||||
attribute_deprecated
|
||||
AVInputFormat *av_iformat_next(const AVInputFormat *f);
|
||||
|
||||
/**
|
||||
* If f is NULL, returns the first registered output format,
|
||||
* if f is non-NULL, returns the next registered output format after f
|
||||
* or NULL if f is the last one.
|
||||
*/
|
||||
attribute_deprecated
|
||||
AVOutputFormat *av_oformat_next(const AVOutputFormat *f);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Iterate over all registered muxers.
|
||||
*
|
||||
* @param opaque a pointer where libavformat will store the iteration state. Must
|
||||
* point to NULL to start the iteration.
|
||||
*
|
||||
* @return the next registered muxer or NULL when the iteration is
|
||||
* finished
|
||||
*/
|
||||
const AVOutputFormat *av_muxer_iterate(void **opaque);
|
||||
|
||||
/**
|
||||
* Iterate over all registered demuxers.
|
||||
*
|
||||
* @param opaque a pointer where libavformat will store the iteration state. Must
|
||||
* point to NULL to start the iteration.
|
||||
*
|
||||
* @return the next registered demuxer or NULL when the iteration is
|
||||
* finished
|
||||
*/
|
||||
const AVInputFormat *av_demuxer_iterate(void **opaque);
|
||||
|
||||
/**
|
||||
* Allocate an AVFormatContext.
|
||||
* avformat_free_context() can be used to free the context and everything
|
||||
* allocated by the framework within it.
|
||||
*/
|
||||
AVFormatContext *avformat_alloc_context(void);
|
||||
|
||||
/**
|
||||
* Free an AVFormatContext and all its streams.
|
||||
* @param s context to free
|
||||
*/
|
||||
void avformat_free_context(AVFormatContext *s);
|
||||
|
||||
/**
|
||||
* Get the AVClass for AVFormatContext. It can be used in combination with
|
||||
* AV_OPT_SEARCH_FAKE_OBJ for examining options.
|
||||
*
|
||||
* @see av_opt_find().
|
||||
*/
|
||||
const AVClass *avformat_get_class(void);
|
||||
|
||||
/**
|
||||
* Add a new stream to a media file.
|
||||
*
|
||||
* When demuxing, it is called by the demuxer in read_header(). If the
|
||||
* flag AVFMTCTX_NOHEADER is set in s.ctx_flags, then it may also
|
||||
* be called in read_packet().
|
||||
*
|
||||
* When muxing, should be called by the user before avformat_write_header().
|
||||
*
|
||||
* User is required to call avcodec_close() and avformat_free_context() to
|
||||
* clean up the allocation by avformat_new_stream().
|
||||
*
|
||||
* @param s media file handle
|
||||
* @param c If non-NULL, the AVCodecContext corresponding to the new stream
|
||||
* will be initialized to use this codec. This is needed for e.g. codec-specific
|
||||
* defaults to be set, so codec should be provided if it is known.
|
||||
*
|
||||
* @return newly created stream or NULL on error.
|
||||
*/
|
||||
AVStream *avformat_new_stream(AVFormatContext *s, const AVCodec *c);
|
||||
|
||||
/**
|
||||
* Wrap an existing array as stream side data.
|
||||
*
|
||||
* @param st stream
|
||||
* @param type side information type
|
||||
* @param data the side data array. It must be allocated with the av_malloc()
|
||||
* family of functions. The ownership of the data is transferred to
|
||||
* st.
|
||||
* @param size side information size
|
||||
* @return zero on success, a negative AVERROR code on failure. On failure,
|
||||
* the stream is unchanged and the data remains owned by the caller.
|
||||
*/
|
||||
int av_stream_add_side_data(AVStream *st, enum AVPacketSideDataType type,
|
||||
uint8_t *data, size_t size);
|
||||
|
||||
/**
|
||||
* Allocate new information from stream.
|
||||
*
|
||||
* @param stream stream
|
||||
* @param type desired side information type
|
||||
* @param size side information size
|
||||
* @return pointer to fresh allocated data or NULL otherwise
|
||||
*/
|
||||
uint8_t *av_stream_new_side_data(AVStream *stream,
|
||||
enum AVPacketSideDataType type, int size);
|
||||
/**
|
||||
* Get side information from stream.
|
||||
*
|
||||
* @param stream stream
|
||||
* @param type desired side information type
|
||||
* @param size pointer for side information size to store (optional)
|
||||
* @return pointer to data if present or NULL otherwise
|
||||
*/
|
||||
uint8_t *av_stream_get_side_data(const AVStream *stream,
|
||||
enum AVPacketSideDataType type, int *size);
|
||||
|
||||
AVProgram *av_new_program(AVFormatContext *s, int id);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Allocate an AVFormatContext for an output format.
|
||||
* avformat_free_context() can be used to free the context and
|
||||
* everything allocated by the framework within it.
|
||||
*
|
||||
* @param *ctx is set to the created format context, or to NULL in
|
||||
* case of failure
|
||||
* @param oformat format to use for allocating the context, if NULL
|
||||
* format_name and filename are used instead
|
||||
* @param format_name the name of output format to use for allocating the
|
||||
* context, if NULL filename is used instead
|
||||
* @param filename the name of the filename to use for allocating the
|
||||
* context, may be NULL
|
||||
* @return >= 0 in case of success, a negative AVERROR code in case of
|
||||
* failure
|
||||
*/
|
||||
int avformat_alloc_output_context2(AVFormatContext **ctx, AVOutputFormat *oformat,
|
||||
const char *format_name, const char *filename);
|
||||
|
||||
/**
|
||||
* @addtogroup lavf_decoding
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Find AVInputFormat based on the short name of the input format.
|
||||
*/
|
||||
AVInputFormat *av_find_input_format(const char *short_name);
|
||||
|
||||
/**
|
||||
* Guess the file format.
|
||||
*
|
||||
* @param pd data to be probed
|
||||
* @param is_opened Whether the file is already opened; determines whether
|
||||
* demuxers with or without AVFMT_NOFILE are probed.
|
||||
*/
|
||||
AVInputFormat *av_probe_input_format(AVProbeData *pd, int is_opened);
|
||||
|
||||
/**
|
||||
* Guess the file format.
|
||||
*
|
||||
* @param pd data to be probed
|
||||
* @param is_opened Whether the file is already opened; determines whether
|
||||
* demuxers with or without AVFMT_NOFILE are probed.
|
||||
* @param score_max A probe score larger that this is required to accept a
|
||||
* detection, the variable is set to the actual detection
|
||||
* score afterwards.
|
||||
* If the score is <= AVPROBE_SCORE_MAX / 4 it is recommended
|
||||
* to retry with a larger probe buffer.
|
||||
*/
|
||||
AVInputFormat *av_probe_input_format2(AVProbeData *pd, int is_opened, int *score_max);
|
||||
|
||||
/**
|
||||
* Guess the file format.
|
||||
*
|
||||
* @param is_opened Whether the file is already opened; determines whether
|
||||
* demuxers with or without AVFMT_NOFILE are probed.
|
||||
* @param score_ret The score of the best detection.
|
||||
*/
|
||||
AVInputFormat *av_probe_input_format3(AVProbeData *pd, int is_opened, int *score_ret);
|
||||
|
||||
/**
|
||||
* Probe a bytestream to determine the input format. Each time a probe returns
|
||||
* with a score that is too low, the probe buffer size is increased and another
|
||||
* attempt is made. When the maximum probe size is reached, the input format
|
||||
* with the highest score is returned.
|
||||
*
|
||||
* @param pb the bytestream to probe
|
||||
* @param fmt the input format is put here
|
||||
* @param url the url of the stream
|
||||
* @param logctx the log context
|
||||
* @param offset the offset within the bytestream to probe from
|
||||
* @param max_probe_size the maximum probe buffer size (zero for default)
|
||||
* @return the score in case of success, a negative value corresponding to an
|
||||
* the maximal score is AVPROBE_SCORE_MAX
|
||||
* AVERROR code otherwise
|
||||
*/
|
||||
int av_probe_input_buffer2(AVIOContext *pb, AVInputFormat **fmt,
|
||||
const char *url, void *logctx,
|
||||
unsigned int offset, unsigned int max_probe_size);
|
||||
|
||||
/**
|
||||
* Like av_probe_input_buffer2() but returns 0 on success
|
||||
*/
|
||||
int av_probe_input_buffer(AVIOContext *pb, AVInputFormat **fmt,
|
||||
const char *url, void *logctx,
|
||||
unsigned int offset, unsigned int max_probe_size);
|
||||
|
||||
/**
|
||||
* Open an input stream and read the header. The codecs are not opened.
|
||||
* The stream must be closed with avformat_close_input().
|
||||
*
|
||||
* @param ps Pointer to user-supplied AVFormatContext (allocated by avformat_alloc_context).
|
||||
* May be a pointer to NULL, in which case an AVFormatContext is allocated by this
|
||||
* function and written into ps.
|
||||
* Note that a user-supplied AVFormatContext will be freed on failure.
|
||||
* @param url URL of the stream to open.
|
||||
* @param fmt If non-NULL, this parameter forces a specific input format.
|
||||
* Otherwise the format is autodetected.
|
||||
* @param options A dictionary filled with AVFormatContext and demuxer-private options.
|
||||
* On return this parameter will be destroyed and replaced with a dict containing
|
||||
* options that were not found. May be NULL.
|
||||
*
|
||||
* @return 0 on success, a negative AVERROR on failure.
|
||||
*
|
||||
* @note If you want to use custom IO, preallocate the format context and set its pb field.
|
||||
*/
|
||||
int avformat_open_input(AVFormatContext **ps, const char *url, AVInputFormat *fmt, AVDictionary **options);
|
||||
|
||||
attribute_deprecated
|
||||
int av_demuxer_open(AVFormatContext *ic);
|
||||
|
||||
/**
|
||||
* Read packets of a media file to get stream information. This
|
||||
* is useful for file formats with no headers such as MPEG. This
|
||||
* function also computes the real framerate in case of MPEG-2 repeat
|
||||
* frame mode.
|
||||
* The logical file position is not changed by this function;
|
||||
* examined packets may be buffered for later processing.
|
||||
*
|
||||
* @param ic media file handle
|
||||
* @param options If non-NULL, an ic.nb_streams long array of pointers to
|
||||
* dictionaries, where i-th member contains options for
|
||||
* codec corresponding to i-th stream.
|
||||
* On return each dictionary will be filled with options that were not found.
|
||||
* @return >=0 if OK, AVERROR_xxx on error
|
||||
*
|
||||
* @note this function isn't guaranteed to open all the codecs, so
|
||||
* options being non-empty at return is a perfectly normal behavior.
|
||||
*
|
||||
* @todo Let the user decide somehow what information is needed so that
|
||||
* we do not waste time getting stuff the user does not need.
|
||||
*/
|
||||
int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options);
|
||||
|
||||
/**
|
||||
* Find the programs which belong to a given stream.
|
||||
*
|
||||
* @param ic media file handle
|
||||
* @param last the last found program, the search will start after this
|
||||
* program, or from the beginning if it is NULL
|
||||
* @param s stream index
|
||||
* @return the next program which belongs to s, NULL if no program is found or
|
||||
* the last program is not among the programs of ic.
|
||||
*/
|
||||
AVProgram *av_find_program_from_stream(AVFormatContext *ic, AVProgram *last, int s);
|
||||
|
||||
void av_program_add_stream_index(AVFormatContext *ac, int progid, unsigned int idx);
|
||||
|
||||
/**
|
||||
* Find the "best" stream in the file.
|
||||
* The best stream is determined according to various heuristics as the most
|
||||
* likely to be what the user expects.
|
||||
* If the decoder parameter is non-NULL, av_find_best_stream will find the
|
||||
* default decoder for the stream's codec; streams for which no decoder can
|
||||
* be found are ignored.
|
||||
*
|
||||
* @param ic media file handle
|
||||
* @param type stream type: video, audio, subtitles, etc.
|
||||
* @param wanted_stream_nb user-requested stream number,
|
||||
* or -1 for automatic selection
|
||||
* @param related_stream try to find a stream related (eg. in the same
|
||||
* program) to this one, or -1 if none
|
||||
* @param decoder_ret if non-NULL, returns the decoder for the
|
||||
* selected stream
|
||||
* @param flags flags; none are currently defined
|
||||
* @return the non-negative stream number in case of success,
|
||||
* AVERROR_STREAM_NOT_FOUND if no stream with the requested type
|
||||
* could be found,
|
||||
* AVERROR_DECODER_NOT_FOUND if streams were found but no decoder
|
||||
* @note If av_find_best_stream returns successfully and decoder_ret is not
|
||||
* NULL, then *decoder_ret is guaranteed to be set to a valid AVCodec.
|
||||
*/
|
||||
int av_find_best_stream(AVFormatContext *ic,
|
||||
enum AVMediaType type,
|
||||
int wanted_stream_nb,
|
||||
int related_stream,
|
||||
AVCodec **decoder_ret,
|
||||
int flags);
|
||||
|
||||
/**
|
||||
* Return the next frame of a stream.
|
||||
* This function returns what is stored in the file, and does not validate
|
||||
* that what is there are valid frames for the decoder. It will split what is
|
||||
* stored in the file into frames and return one for each call. It will not
|
||||
* omit invalid data between valid frames so as to give the decoder the maximum
|
||||
* information possible for decoding.
|
||||
*
|
||||
* If pkt->buf is NULL, then the packet is valid until the next
|
||||
* av_read_frame() or until avformat_close_input(). Otherwise the packet
|
||||
* is valid indefinitely. In both cases the packet must be freed with
|
||||
* av_packet_unref when it is no longer needed. For video, the packet contains
|
||||
* exactly one frame. For audio, it contains an integer number of frames if each
|
||||
* frame has a known fixed size (e.g. PCM or ADPCM data). If the audio frames
|
||||
* have a variable size (e.g. MPEG audio), then it contains one frame.
|
||||
*
|
||||
* pkt->pts, pkt->dts and pkt->duration are always set to correct
|
||||
* values in AVStream.time_base units (and guessed if the format cannot
|
||||
* provide them). pkt->pts can be AV_NOPTS_VALUE if the video format
|
||||
* has B-frames, so it is better to rely on pkt->dts if you do not
|
||||
* decompress the payload.
|
||||
*
|
||||
* @return 0 if OK, < 0 on error or end of file
|
||||
*/
|
||||
int av_read_frame(AVFormatContext *s, AVPacket *pkt);
|
||||
|
||||
/**
|
||||
* Seek to the keyframe at timestamp.
|
||||
* 'timestamp' in 'stream_index'.
|
||||
*
|
||||
* @param s media file handle
|
||||
* @param stream_index If stream_index is (-1), a default
|
||||
* stream is selected, and timestamp is automatically converted
|
||||
* from AV_TIME_BASE units to the stream specific time_base.
|
||||
* @param timestamp Timestamp in AVStream.time_base units
|
||||
* or, if no stream is specified, in AV_TIME_BASE units.
|
||||
* @param flags flags which select direction and seeking mode
|
||||
* @return >= 0 on success
|
||||
*/
|
||||
int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp,
|
||||
int flags);
|
||||
|
||||
/**
|
||||
* Seek to timestamp ts.
|
||||
* Seeking will be done so that the point from which all active streams
|
||||
* can be presented successfully will be closest to ts and within min/max_ts.
|
||||
* Active streams are all streams that have AVStream.discard < AVDISCARD_ALL.
|
||||
*
|
||||
* If flags contain AVSEEK_FLAG_BYTE, then all timestamps are in bytes and
|
||||
* are the file position (this may not be supported by all demuxers).
|
||||
* If flags contain AVSEEK_FLAG_FRAME, then all timestamps are in frames
|
||||
* in the stream with stream_index (this may not be supported by all demuxers).
|
||||
* Otherwise all timestamps are in units of the stream selected by stream_index
|
||||
* or if stream_index is -1, in AV_TIME_BASE units.
|
||||
* If flags contain AVSEEK_FLAG_ANY, then non-keyframes are treated as
|
||||
* keyframes (this may not be supported by all demuxers).
|
||||
* If flags contain AVSEEK_FLAG_BACKWARD, it is ignored.
|
||||
*
|
||||
* @param s media file handle
|
||||
* @param stream_index index of the stream which is used as time base reference
|
||||
* @param min_ts smallest acceptable timestamp
|
||||
* @param ts target timestamp
|
||||
* @param max_ts largest acceptable timestamp
|
||||
* @param flags flags
|
||||
* @return >=0 on success, error code otherwise
|
||||
*
|
||||
* @note This is part of the new seek API which is still under construction.
|
||||
* Thus do not use this yet. It may change at any time, do not expect
|
||||
* ABI compatibility yet!
|
||||
*/
|
||||
int avformat_seek_file(AVFormatContext *s, int stream_index, int64_t min_ts, int64_t ts, int64_t max_ts, int flags);
|
||||
|
||||
/**
|
||||
* Discard all internally buffered data. This can be useful when dealing with
|
||||
* discontinuities in the byte stream. Generally works only with formats that
|
||||
* can resync. This includes headerless formats like MPEG-TS/TS but should also
|
||||
* work with NUT, Ogg and in a limited way AVI for example.
|
||||
*
|
||||
* The set of streams, the detected duration, stream parameters and codecs do
|
||||
* not change when calling this function. If you want a complete reset, it's
|
||||
* better to open a new AVFormatContext.
|
||||
*
|
||||
* This does not flush the AVIOContext (s->pb). If necessary, call
|
||||
* avio_flush(s->pb) before calling this function.
|
||||
*
|
||||
* @param s media file handle
|
||||
* @return >=0 on success, error code otherwise
|
||||
*/
|
||||
int avformat_flush(AVFormatContext *s);
|
||||
|
||||
/**
|
||||
* Start playing a network-based stream (e.g. RTSP stream) at the
|
||||
* current position.
|
||||
*/
|
||||
int av_read_play(AVFormatContext *s);
|
||||
|
||||
/**
|
||||
* Pause a network-based stream (e.g. RTSP stream).
|
||||
*
|
||||
* Use av_read_play() to resume it.
|
||||
*/
|
||||
int av_read_pause(AVFormatContext *s);
|
||||
|
||||
/**
|
||||
* Close an opened input AVFormatContext. Free it and all its contents
|
||||
* and set *s to NULL.
|
||||
*/
|
||||
void avformat_close_input(AVFormatContext **s);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#define AVSEEK_FLAG_BACKWARD 1 ///< seek backward
|
||||
#define AVSEEK_FLAG_BYTE 2 ///< seeking based on position in bytes
|
||||
#define AVSEEK_FLAG_ANY 4 ///< seek to any frame, even non-keyframes
|
||||
#define AVSEEK_FLAG_FRAME 8 ///< seeking based on frame number
|
||||
|
||||
/**
|
||||
* @addtogroup lavf_encoding
|
||||
* @{
|
||||
*/
|
||||
|
||||
#define AVSTREAM_INIT_IN_WRITE_HEADER 0 ///< stream parameters initialized in avformat_write_header
|
||||
#define AVSTREAM_INIT_IN_INIT_OUTPUT 1 ///< stream parameters initialized in avformat_init_output
|
||||
|
||||
/**
|
||||
* Allocate the stream private data and write the stream header to
|
||||
* an output media file.
|
||||
*
|
||||
* @param s Media file handle, must be allocated with avformat_alloc_context().
|
||||
* Its oformat field must be set to the desired output format;
|
||||
* Its pb field must be set to an already opened AVIOContext.
|
||||
* @param options An AVDictionary filled with AVFormatContext and muxer-private options.
|
||||
* On return this parameter will be destroyed and replaced with a dict containing
|
||||
* options that were not found. May be NULL.
|
||||
*
|
||||
* @return AVSTREAM_INIT_IN_WRITE_HEADER on success if the codec had not already been fully initialized in avformat_init,
|
||||
* AVSTREAM_INIT_IN_INIT_OUTPUT on success if the codec had already been fully initialized in avformat_init,
|
||||
* negative AVERROR on failure.
|
||||
*
|
||||
* @see av_opt_find, av_dict_set, avio_open, av_oformat_next, avformat_init_output.
|
||||
*/
|
||||
av_warn_unused_result
|
||||
int avformat_write_header(AVFormatContext *s, AVDictionary **options);
|
||||
|
||||
/**
|
||||
* Allocate the stream private data and initialize the codec, but do not write the header.
|
||||
* May optionally be used before avformat_write_header to initialize stream parameters
|
||||
* before actually writing the header.
|
||||
* If using this function, do not pass the same options to avformat_write_header.
|
||||
*
|
||||
* @param s Media file handle, must be allocated with avformat_alloc_context().
|
||||
* Its oformat field must be set to the desired output format;
|
||||
* Its pb field must be set to an already opened AVIOContext.
|
||||
* @param options An AVDictionary filled with AVFormatContext and muxer-private options.
|
||||
* On return this parameter will be destroyed and replaced with a dict containing
|
||||
* options that were not found. May be NULL.
|
||||
*
|
||||
* @return AVSTREAM_INIT_IN_WRITE_HEADER on success if the codec requires avformat_write_header to fully initialize,
|
||||
* AVSTREAM_INIT_IN_INIT_OUTPUT on success if the codec has been fully initialized,
|
||||
* negative AVERROR on failure.
|
||||
*
|
||||
* @see av_opt_find, av_dict_set, avio_open, av_oformat_next, avformat_write_header.
|
||||
*/
|
||||
av_warn_unused_result
|
||||
int avformat_init_output(AVFormatContext *s, AVDictionary **options);
|
||||
|
||||
/**
|
||||
* Write a packet to an output media file.
|
||||
*
|
||||
* This function passes the packet directly to the muxer, without any buffering
|
||||
* or reordering. The caller is responsible for correctly interleaving the
|
||||
* packets if the format requires it. Callers that want libavformat to handle
|
||||
* the interleaving should call av_interleaved_write_frame() instead of this
|
||||
* function.
|
||||
*
|
||||
* @param s media file handle
|
||||
* @param pkt The packet containing the data to be written. Note that unlike
|
||||
* av_interleaved_write_frame(), this function does not take
|
||||
* ownership of the packet passed to it (though some muxers may make
|
||||
* an internal reference to the input packet).
|
||||
* <br>
|
||||
* This parameter can be NULL (at any time, not just at the end), in
|
||||
* order to immediately flush data buffered within the muxer, for
|
||||
* muxers that buffer up data internally before writing it to the
|
||||
* output.
|
||||
* <br>
|
||||
* Packet's @ref AVPacket.stream_index "stream_index" field must be
|
||||
* set to the index of the corresponding stream in @ref
|
||||
* AVFormatContext.streams "s->streams".
|
||||
* <br>
|
||||
* The timestamps (@ref AVPacket.pts "pts", @ref AVPacket.dts "dts")
|
||||
* must be set to correct values in the stream's timebase (unless the
|
||||
* output format is flagged with the AVFMT_NOTIMESTAMPS flag, then
|
||||
* they can be set to AV_NOPTS_VALUE).
|
||||
* The dts for subsequent packets passed to this function must be strictly
|
||||
* increasing when compared in their respective timebases (unless the
|
||||
* output format is flagged with the AVFMT_TS_NONSTRICT, then they
|
||||
* merely have to be nondecreasing). @ref AVPacket.duration
|
||||
* "duration") should also be set if known.
|
||||
* @return < 0 on error, = 0 if OK, 1 if flushed and there is no more data to flush
|
||||
*
|
||||
* @see av_interleaved_write_frame()
|
||||
*/
|
||||
int av_write_frame(AVFormatContext *s, AVPacket *pkt);
|
||||
|
||||
/**
|
||||
* Write a packet to an output media file ensuring correct interleaving.
|
||||
*
|
||||
* This function will buffer the packets internally as needed to make sure the
|
||||
* packets in the output file are properly interleaved in the order of
|
||||
* increasing dts. Callers doing their own interleaving should call
|
||||
* av_write_frame() instead of this function.
|
||||
*
|
||||
* Using this function instead of av_write_frame() can give muxers advance
|
||||
* knowledge of future packets, improving e.g. the behaviour of the mp4
|
||||
* muxer for VFR content in fragmenting mode.
|
||||
*
|
||||
* @param s media file handle
|
||||
* @param pkt The packet containing the data to be written.
|
||||
* <br>
|
||||
* If the packet is reference-counted, this function will take
|
||||
* ownership of this reference and unreference it later when it sees
|
||||
* fit.
|
||||
* The caller must not access the data through this reference after
|
||||
* this function returns. If the packet is not reference-counted,
|
||||
* libavformat will make a copy.
|
||||
* <br>
|
||||
* This parameter can be NULL (at any time, not just at the end), to
|
||||
* flush the interleaving queues.
|
||||
* <br>
|
||||
* Packet's @ref AVPacket.stream_index "stream_index" field must be
|
||||
* set to the index of the corresponding stream in @ref
|
||||
* AVFormatContext.streams "s->streams".
|
||||
* <br>
|
||||
* The timestamps (@ref AVPacket.pts "pts", @ref AVPacket.dts "dts")
|
||||
* must be set to correct values in the stream's timebase (unless the
|
||||
* output format is flagged with the AVFMT_NOTIMESTAMPS flag, then
|
||||
* they can be set to AV_NOPTS_VALUE).
|
||||
* The dts for subsequent packets in one stream must be strictly
|
||||
* increasing (unless the output format is flagged with the
|
||||
* AVFMT_TS_NONSTRICT, then they merely have to be nondecreasing).
|
||||
* @ref AVPacket.duration "duration") should also be set if known.
|
||||
*
|
||||
* @return 0 on success, a negative AVERROR on error. Libavformat will always
|
||||
* take care of freeing the packet, even if this function fails.
|
||||
*
|
||||
* @see av_write_frame(), AVFormatContext.max_interleave_delta
|
||||
*/
|
||||
int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt);
|
||||
|
||||
/**
|
||||
* Write an uncoded frame to an output media file.
|
||||
*
|
||||
* The frame must be correctly interleaved according to the container
|
||||
* specification; if not, then av_interleaved_write_frame() must be used.
|
||||
*
|
||||
* See av_interleaved_write_frame() for details.
|
||||
*/
|
||||
int av_write_uncoded_frame(AVFormatContext *s, int stream_index,
|
||||
AVFrame *frame);
|
||||
|
||||
/**
|
||||
* Write an uncoded frame to an output media file.
|
||||
*
|
||||
* If the muxer supports it, this function makes it possible to write an AVFrame
|
||||
* structure directly, without encoding it into a packet.
|
||||
* It is mostly useful for devices and similar special muxers that use raw
|
||||
* video or PCM data and will not serialize it into a byte stream.
|
||||
*
|
||||
* To test whether it is possible to use it with a given muxer and stream,
|
||||
* use av_write_uncoded_frame_query().
|
||||
*
|
||||
* The caller gives up ownership of the frame and must not access it
|
||||
* afterwards.
|
||||
*
|
||||
* @return >=0 for success, a negative code on error
|
||||
*/
|
||||
int av_interleaved_write_uncoded_frame(AVFormatContext *s, int stream_index,
|
||||
AVFrame *frame);
|
||||
|
||||
/**
|
||||
* Test whether a muxer supports uncoded frame.
|
||||
*
|
||||
* @return >=0 if an uncoded frame can be written to that muxer and stream,
|
||||
* <0 if not
|
||||
*/
|
||||
int av_write_uncoded_frame_query(AVFormatContext *s, int stream_index);
|
||||
|
||||
/**
|
||||
* Write the stream trailer to an output media file and free the
|
||||
* file private data.
|
||||
*
|
||||
* May only be called after a successful call to avformat_write_header.
|
||||
*
|
||||
* @param s media file handle
|
||||
* @return 0 if OK, AVERROR_xxx on error
|
||||
*/
|
||||
int av_write_trailer(AVFormatContext *s);
|
||||
|
||||
/**
|
||||
* Return the output format in the list of registered output formats
|
||||
* which best matches the provided parameters, or return NULL if
|
||||
* there is no match.
|
||||
*
|
||||
* @param short_name if non-NULL checks if short_name matches with the
|
||||
* names of the registered formats
|
||||
* @param filename if non-NULL checks if filename terminates with the
|
||||
* extensions of the registered formats
|
||||
* @param mime_type if non-NULL checks if mime_type matches with the
|
||||
* MIME type of the registered formats
|
||||
*/
|
||||
AVOutputFormat *av_guess_format(const char *short_name,
|
||||
const char *filename,
|
||||
const char *mime_type);
|
||||
|
||||
/**
|
||||
* Guess the codec ID based upon muxer and filename.
|
||||
*/
|
||||
enum AVCodecID av_guess_codec(AVOutputFormat *fmt, const char *short_name,
|
||||
const char *filename, const char *mime_type,
|
||||
enum AVMediaType type);
|
||||
|
||||
/**
|
||||
* Get timing information for the data currently output.
|
||||
* The exact meaning of "currently output" depends on the format.
|
||||
* It is mostly relevant for devices that have an internal buffer and/or
|
||||
* work in real time.
|
||||
* @param s media file handle
|
||||
* @param stream stream in the media file
|
||||
* @param[out] dts DTS of the last packet output for the stream, in stream
|
||||
* time_base units
|
||||
* @param[out] wall absolute time when that packet whas output,
|
||||
* in microsecond
|
||||
* @return 0 if OK, AVERROR(ENOSYS) if the format does not support it
|
||||
* Note: some formats or devices may not allow to measure dts and wall
|
||||
* atomically.
|
||||
*/
|
||||
int av_get_output_timestamp(struct AVFormatContext *s, int stream,
|
||||
int64_t *dts, int64_t *wall);
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @defgroup lavf_misc Utility functions
|
||||
* @ingroup libavf
|
||||
* @{
|
||||
*
|
||||
* Miscellaneous utility functions related to both muxing and demuxing
|
||||
* (or neither).
|
||||
*/
|
||||
|
||||
/**
|
||||
* Send a nice hexadecimal dump of a buffer to the specified file stream.
|
||||
*
|
||||
* @param f The file stream pointer where the dump should be sent to.
|
||||
* @param buf buffer
|
||||
* @param size buffer size
|
||||
*
|
||||
* @see av_hex_dump_log, av_pkt_dump2, av_pkt_dump_log2
|
||||
*/
|
||||
void av_hex_dump(FILE *f, const uint8_t *buf, int size);
|
||||
|
||||
/**
|
||||
* Send a nice hexadecimal dump of a buffer to the log.
|
||||
*
|
||||
* @param avcl A pointer to an arbitrary struct of which the first field is a
|
||||
* pointer to an AVClass struct.
|
||||
* @param level The importance level of the message, lower values signifying
|
||||
* higher importance.
|
||||
* @param buf buffer
|
||||
* @param size buffer size
|
||||
*
|
||||
* @see av_hex_dump, av_pkt_dump2, av_pkt_dump_log2
|
||||
*/
|
||||
void av_hex_dump_log(void *avcl, int level, const uint8_t *buf, int size);
|
||||
|
||||
/**
|
||||
* Send a nice dump of a packet to the specified file stream.
|
||||
*
|
||||
* @param f The file stream pointer where the dump should be sent to.
|
||||
* @param pkt packet to dump
|
||||
* @param dump_payload True if the payload must be displayed, too.
|
||||
* @param st AVStream that the packet belongs to
|
||||
*/
|
||||
void av_pkt_dump2(FILE *f, const AVPacket *pkt, int dump_payload, const AVStream *st);
|
||||
|
||||
|
||||
/**
|
||||
* Send a nice dump of a packet to the log.
|
||||
*
|
||||
* @param avcl A pointer to an arbitrary struct of which the first field is a
|
||||
* pointer to an AVClass struct.
|
||||
* @param level The importance level of the message, lower values signifying
|
||||
* higher importance.
|
||||
* @param pkt packet to dump
|
||||
* @param dump_payload True if the payload must be displayed, too.
|
||||
* @param st AVStream that the packet belongs to
|
||||
*/
|
||||
void av_pkt_dump_log2(void *avcl, int level, const AVPacket *pkt, int dump_payload,
|
||||
const AVStream *st);
|
||||
|
||||
/**
|
||||
* Get the AVCodecID for the given codec tag tag.
|
||||
* If no codec id is found returns AV_CODEC_ID_NONE.
|
||||
*
|
||||
* @param tags list of supported codec_id-codec_tag pairs, as stored
|
||||
* in AVInputFormat.codec_tag and AVOutputFormat.codec_tag
|
||||
* @param tag codec tag to match to a codec ID
|
||||
*/
|
||||
enum AVCodecID av_codec_get_id(const struct AVCodecTag * const *tags, unsigned int tag);
|
||||
|
||||
/**
|
||||
* Get the codec tag for the given codec id id.
|
||||
* If no codec tag is found returns 0.
|
||||
*
|
||||
* @param tags list of supported codec_id-codec_tag pairs, as stored
|
||||
* in AVInputFormat.codec_tag and AVOutputFormat.codec_tag
|
||||
* @param id codec ID to match to a codec tag
|
||||
*/
|
||||
unsigned int av_codec_get_tag(const struct AVCodecTag * const *tags, enum AVCodecID id);
|
||||
|
||||
/**
|
||||
* Get the codec tag for the given codec id.
|
||||
*
|
||||
* @param tags list of supported codec_id - codec_tag pairs, as stored
|
||||
* in AVInputFormat.codec_tag and AVOutputFormat.codec_tag
|
||||
* @param id codec id that should be searched for in the list
|
||||
* @param tag A pointer to the found tag
|
||||
* @return 0 if id was not found in tags, > 0 if it was found
|
||||
*/
|
||||
int av_codec_get_tag2(const struct AVCodecTag * const *tags, enum AVCodecID id,
|
||||
unsigned int *tag);
|
||||
|
||||
int av_find_default_stream_index(AVFormatContext *s);
|
||||
|
||||
/**
|
||||
* Get the index for a specific timestamp.
|
||||
*
|
||||
* @param st stream that the timestamp belongs to
|
||||
* @param timestamp timestamp to retrieve the index for
|
||||
* @param flags if AVSEEK_FLAG_BACKWARD then the returned index will correspond
|
||||
* to the timestamp which is <= the requested one, if backward
|
||||
* is 0, then it will be >=
|
||||
* if AVSEEK_FLAG_ANY seek to any frame, only keyframes otherwise
|
||||
* @return < 0 if no such timestamp could be found
|
||||
*/
|
||||
int av_index_search_timestamp(AVStream *st, int64_t timestamp, int flags);
|
||||
|
||||
/**
|
||||
* Add an index entry into a sorted list. Update the entry if the list
|
||||
* already contains it.
|
||||
*
|
||||
* @param timestamp timestamp in the time base of the given stream
|
||||
*/
|
||||
int av_add_index_entry(AVStream *st, int64_t pos, int64_t timestamp,
|
||||
int size, int distance, int flags);
|
||||
|
||||
|
||||
/**
|
||||
* Split a URL string into components.
|
||||
*
|
||||
* The pointers to buffers for storing individual components may be null,
|
||||
* in order to ignore that component. Buffers for components not found are
|
||||
* set to empty strings. If the port is not found, it is set to a negative
|
||||
* value.
|
||||
*
|
||||
* @param proto the buffer for the protocol
|
||||
* @param proto_size the size of the proto buffer
|
||||
* @param authorization the buffer for the authorization
|
||||
* @param authorization_size the size of the authorization buffer
|
||||
* @param hostname the buffer for the host name
|
||||
* @param hostname_size the size of the hostname buffer
|
||||
* @param port_ptr a pointer to store the port number in
|
||||
* @param path the buffer for the path
|
||||
* @param path_size the size of the path buffer
|
||||
* @param url the URL to split
|
||||
*/
|
||||
void av_url_split(char *proto, int proto_size,
|
||||
char *authorization, int authorization_size,
|
||||
char *hostname, int hostname_size,
|
||||
int *port_ptr,
|
||||
char *path, int path_size,
|
||||
const char *url);
|
||||
|
||||
|
||||
/**
|
||||
* Print detailed information about the input or output format, such as
|
||||
* duration, bitrate, streams, container, programs, metadata, side data,
|
||||
* codec and time base.
|
||||
*
|
||||
* @param ic the context to analyze
|
||||
* @param index index of the stream to dump information about
|
||||
* @param url the URL to print, such as source or destination file
|
||||
* @param is_output Select whether the specified context is an input(0) or output(1)
|
||||
*/
|
||||
void av_dump_format(AVFormatContext *ic,
|
||||
int index,
|
||||
const char *url,
|
||||
int is_output);
|
||||
|
||||
|
||||
#define AV_FRAME_FILENAME_FLAGS_MULTIPLE 1 ///< Allow multiple %d
|
||||
|
||||
/**
|
||||
* Return in 'buf' the path with '%d' replaced by a number.
|
||||
*
|
||||
* Also handles the '%0nd' format where 'n' is the total number
|
||||
* of digits and '%%'.
|
||||
*
|
||||
* @param buf destination buffer
|
||||
* @param buf_size destination buffer size
|
||||
* @param path numbered sequence string
|
||||
* @param number frame number
|
||||
* @param flags AV_FRAME_FILENAME_FLAGS_*
|
||||
* @return 0 if OK, -1 on format error
|
||||
*/
|
||||
int av_get_frame_filename2(char *buf, int buf_size,
|
||||
const char *path, int number, int flags);
|
||||
|
||||
int av_get_frame_filename(char *buf, int buf_size,
|
||||
const char *path, int number);
|
||||
|
||||
/**
|
||||
* Check whether filename actually is a numbered sequence generator.
|
||||
*
|
||||
* @param filename possible numbered sequence string
|
||||
* @return 1 if a valid numbered sequence string, 0 otherwise
|
||||
*/
|
||||
int av_filename_number_test(const char *filename);
|
||||
|
||||
/**
|
||||
* Generate an SDP for an RTP session.
|
||||
*
|
||||
* Note, this overwrites the id values of AVStreams in the muxer contexts
|
||||
* for getting unique dynamic payload types.
|
||||
*
|
||||
* @param ac array of AVFormatContexts describing the RTP streams. If the
|
||||
* array is composed by only one context, such context can contain
|
||||
* multiple AVStreams (one AVStream per RTP stream). Otherwise,
|
||||
* all the contexts in the array (an AVCodecContext per RTP stream)
|
||||
* must contain only one AVStream.
|
||||
* @param n_files number of AVCodecContexts contained in ac
|
||||
* @param buf buffer where the SDP will be stored (must be allocated by
|
||||
* the caller)
|
||||
* @param size the size of the buffer
|
||||
* @return 0 if OK, AVERROR_xxx on error
|
||||
*/
|
||||
int av_sdp_create(AVFormatContext *ac[], int n_files, char *buf, int size);
|
||||
|
||||
/**
|
||||
* Return a positive value if the given filename has one of the given
|
||||
* extensions, 0 otherwise.
|
||||
*
|
||||
* @param filename file name to check against the given extensions
|
||||
* @param extensions a comma-separated list of filename extensions
|
||||
*/
|
||||
int av_match_ext(const char *filename, const char *extensions);
|
||||
|
||||
/**
|
||||
* Test if the given container can store a codec.
|
||||
*
|
||||
* @param ofmt container to check for compatibility
|
||||
* @param codec_id codec to potentially store in container
|
||||
* @param std_compliance standards compliance level, one of FF_COMPLIANCE_*
|
||||
*
|
||||
* @return 1 if codec with ID codec_id can be stored in ofmt, 0 if it cannot.
|
||||
* A negative number if this information is not available.
|
||||
*/
|
||||
int avformat_query_codec(const AVOutputFormat *ofmt, enum AVCodecID codec_id,
|
||||
int std_compliance);
|
||||
|
||||
/**
|
||||
* @defgroup riff_fourcc RIFF FourCCs
|
||||
* @{
|
||||
* Get the tables mapping RIFF FourCCs to libavcodec AVCodecIDs. The tables are
|
||||
* meant to be passed to av_codec_get_id()/av_codec_get_tag() as in the
|
||||
* following code:
|
||||
* @code
|
||||
* uint32_t tag = MKTAG('H', '2', '6', '4');
|
||||
* const struct AVCodecTag *table[] = { avformat_get_riff_video_tags(), 0 };
|
||||
* enum AVCodecID id = av_codec_get_id(table, tag);
|
||||
* @endcode
|
||||
*/
|
||||
/**
|
||||
* @return the table mapping RIFF FourCCs for video to libavcodec AVCodecID.
|
||||
*/
|
||||
const struct AVCodecTag *avformat_get_riff_video_tags(void);
|
||||
/**
|
||||
* @return the table mapping RIFF FourCCs for audio to AVCodecID.
|
||||
*/
|
||||
const struct AVCodecTag *avformat_get_riff_audio_tags(void);
|
||||
/**
|
||||
* @return the table mapping MOV FourCCs for video to libavcodec AVCodecID.
|
||||
*/
|
||||
const struct AVCodecTag *avformat_get_mov_video_tags(void);
|
||||
/**
|
||||
* @return the table mapping MOV FourCCs for audio to AVCodecID.
|
||||
*/
|
||||
const struct AVCodecTag *avformat_get_mov_audio_tags(void);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Guess the sample aspect ratio of a frame, based on both the stream and the
|
||||
* frame aspect ratio.
|
||||
*
|
||||
* Since the frame aspect ratio is set by the codec but the stream aspect ratio
|
||||
* is set by the demuxer, these two may not be equal. This function tries to
|
||||
* return the value that you should use if you would like to display the frame.
|
||||
*
|
||||
* Basic logic is to use the stream aspect ratio if it is set to something sane
|
||||
* otherwise use the frame aspect ratio. This way a container setting, which is
|
||||
* usually easy to modify can override the coded value in the frames.
|
||||
*
|
||||
* @param format the format context which the stream is part of
|
||||
* @param stream the stream which the frame is part of
|
||||
* @param frame the frame with the aspect ratio to be determined
|
||||
* @return the guessed (valid) sample_aspect_ratio, 0/1 if no idea
|
||||
*/
|
||||
AVRational av_guess_sample_aspect_ratio(AVFormatContext *format, AVStream *stream, AVFrame *frame);
|
||||
|
||||
/**
|
||||
* Guess the frame rate, based on both the container and codec information.
|
||||
*
|
||||
* @param ctx the format context which the stream is part of
|
||||
* @param stream the stream which the frame is part of
|
||||
* @param frame the frame for which the frame rate should be determined, may be NULL
|
||||
* @return the guessed (valid) frame rate, 0/1 if no idea
|
||||
*/
|
||||
AVRational av_guess_frame_rate(AVFormatContext *ctx, AVStream *stream, AVFrame *frame);
|
||||
|
||||
/**
|
||||
* Check if the stream st contained in s is matched by the stream specifier
|
||||
* spec.
|
||||
*
|
||||
* See the "stream specifiers" chapter in the documentation for the syntax
|
||||
* of spec.
|
||||
*
|
||||
* @return >0 if st is matched by spec;
|
||||
* 0 if st is not matched by spec;
|
||||
* AVERROR code if spec is invalid
|
||||
*
|
||||
* @note A stream specifier can match several streams in the format.
|
||||
*/
|
||||
int avformat_match_stream_specifier(AVFormatContext *s, AVStream *st,
|
||||
const char *spec);
|
||||
|
||||
int avformat_queue_attached_pictures(AVFormatContext *s);
|
||||
|
||||
#if FF_API_OLD_BSF
|
||||
/**
|
||||
* Apply a list of bitstream filters to a packet.
|
||||
*
|
||||
* @param codec AVCodecContext, usually from an AVStream
|
||||
* @param pkt the packet to apply filters to. If, on success, the returned
|
||||
* packet has size == 0 and side_data_elems == 0, it indicates that
|
||||
* the packet should be dropped
|
||||
* @param bsfc a NULL-terminated list of filters to apply
|
||||
* @return >=0 on success;
|
||||
* AVERROR code on failure
|
||||
*/
|
||||
attribute_deprecated
|
||||
int av_apply_bitstream_filters(AVCodecContext *codec, AVPacket *pkt,
|
||||
AVBitStreamFilterContext *bsfc);
|
||||
#endif
|
||||
|
||||
enum AVTimebaseSource {
|
||||
AVFMT_TBCF_AUTO = -1,
|
||||
AVFMT_TBCF_DECODER,
|
||||
AVFMT_TBCF_DEMUXER,
|
||||
#if FF_API_R_FRAME_RATE
|
||||
AVFMT_TBCF_R_FRAMERATE,
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
* Transfer internal timing information from one stream to another.
|
||||
*
|
||||
* This function is useful when doing stream copy.
|
||||
*
|
||||
* @param ofmt target output format for ost
|
||||
* @param ost output stream which needs timings copy and adjustments
|
||||
* @param ist reference input stream to copy timings from
|
||||
* @param copy_tb define from where the stream codec timebase needs to be imported
|
||||
*/
|
||||
int avformat_transfer_internal_stream_timing_info(const AVOutputFormat *ofmt,
|
||||
AVStream *ost, const AVStream *ist,
|
||||
enum AVTimebaseSource copy_tb);
|
||||
|
||||
/**
|
||||
* Get the internal codec timebase from a stream.
|
||||
*
|
||||
* @param st input stream to extract the timebase from
|
||||
*/
|
||||
AVRational av_stream_get_codec_timebase(const AVStream *st);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* AVFORMAT_AVFORMAT_H */
|
||||
@@ -0,0 +1,861 @@
|
||||
/*
|
||||
* copyright (c) 2001 Fabrice Bellard
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#ifndef AVFORMAT_AVIO_H
|
||||
#define AVFORMAT_AVIO_H
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @ingroup lavf_io
|
||||
* Buffered I/O operations
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "libavutil/common.h"
|
||||
#include "libavutil/dict.h"
|
||||
#include "libavutil/log.h"
|
||||
|
||||
#include "libavformat/version.h"
|
||||
|
||||
/**
|
||||
* Seeking works like for a local file.
|
||||
*/
|
||||
#define AVIO_SEEKABLE_NORMAL (1 << 0)
|
||||
|
||||
/**
|
||||
* Seeking by timestamp with avio_seek_time() is possible.
|
||||
*/
|
||||
#define AVIO_SEEKABLE_TIME (1 << 1)
|
||||
|
||||
/**
|
||||
* Callback for checking whether to abort blocking functions.
|
||||
* AVERROR_EXIT is returned in this case by the interrupted
|
||||
* function. During blocking operations, callback is called with
|
||||
* opaque as parameter. If the callback returns 1, the
|
||||
* blocking operation will be aborted.
|
||||
*
|
||||
* No members can be added to this struct without a major bump, if
|
||||
* new elements have been added after this struct in AVFormatContext
|
||||
* or AVIOContext.
|
||||
*/
|
||||
typedef struct AVIOInterruptCB {
|
||||
int (*callback)(void*);
|
||||
void *opaque;
|
||||
} AVIOInterruptCB;
|
||||
|
||||
/**
|
||||
* Directory entry types.
|
||||
*/
|
||||
enum AVIODirEntryType {
|
||||
AVIO_ENTRY_UNKNOWN,
|
||||
AVIO_ENTRY_BLOCK_DEVICE,
|
||||
AVIO_ENTRY_CHARACTER_DEVICE,
|
||||
AVIO_ENTRY_DIRECTORY,
|
||||
AVIO_ENTRY_NAMED_PIPE,
|
||||
AVIO_ENTRY_SYMBOLIC_LINK,
|
||||
AVIO_ENTRY_SOCKET,
|
||||
AVIO_ENTRY_FILE,
|
||||
AVIO_ENTRY_SERVER,
|
||||
AVIO_ENTRY_SHARE,
|
||||
AVIO_ENTRY_WORKGROUP,
|
||||
};
|
||||
|
||||
/**
|
||||
* Describes single entry of the directory.
|
||||
*
|
||||
* Only name and type fields are guaranteed be set.
|
||||
* Rest of fields are protocol or/and platform dependent and might be unknown.
|
||||
*/
|
||||
typedef struct AVIODirEntry {
|
||||
char *name; /**< Filename */
|
||||
int type; /**< Type of the entry */
|
||||
int utf8; /**< Set to 1 when name is encoded with UTF-8, 0 otherwise.
|
||||
Name can be encoded with UTF-8 even though 0 is set. */
|
||||
int64_t size; /**< File size in bytes, -1 if unknown. */
|
||||
int64_t modification_timestamp; /**< Time of last modification in microseconds since unix
|
||||
epoch, -1 if unknown. */
|
||||
int64_t access_timestamp; /**< Time of last access in microseconds since unix epoch,
|
||||
-1 if unknown. */
|
||||
int64_t status_change_timestamp; /**< Time of last status change in microseconds since unix
|
||||
epoch, -1 if unknown. */
|
||||
int64_t user_id; /**< User ID of owner, -1 if unknown. */
|
||||
int64_t group_id; /**< Group ID of owner, -1 if unknown. */
|
||||
int64_t filemode; /**< Unix file mode, -1 if unknown. */
|
||||
} AVIODirEntry;
|
||||
|
||||
typedef struct AVIODirContext {
|
||||
struct URLContext *url_context;
|
||||
} AVIODirContext;
|
||||
|
||||
/**
|
||||
* Different data types that can be returned via the AVIO
|
||||
* write_data_type callback.
|
||||
*/
|
||||
enum AVIODataMarkerType {
|
||||
/**
|
||||
* Header data; this needs to be present for the stream to be decodeable.
|
||||
*/
|
||||
AVIO_DATA_MARKER_HEADER,
|
||||
/**
|
||||
* A point in the output bytestream where a decoder can start decoding
|
||||
* (i.e. a keyframe). A demuxer/decoder given the data flagged with
|
||||
* AVIO_DATA_MARKER_HEADER, followed by any AVIO_DATA_MARKER_SYNC_POINT,
|
||||
* should give decodeable results.
|
||||
*/
|
||||
AVIO_DATA_MARKER_SYNC_POINT,
|
||||
/**
|
||||
* A point in the output bytestream where a demuxer can start parsing
|
||||
* (for non self synchronizing bytestream formats). That is, any
|
||||
* non-keyframe packet start point.
|
||||
*/
|
||||
AVIO_DATA_MARKER_BOUNDARY_POINT,
|
||||
/**
|
||||
* This is any, unlabelled data. It can either be a muxer not marking
|
||||
* any positions at all, it can be an actual boundary/sync point
|
||||
* that the muxer chooses not to mark, or a later part of a packet/fragment
|
||||
* that is cut into multiple write callbacks due to limited IO buffer size.
|
||||
*/
|
||||
AVIO_DATA_MARKER_UNKNOWN,
|
||||
/**
|
||||
* Trailer data, which doesn't contain actual content, but only for
|
||||
* finalizing the output file.
|
||||
*/
|
||||
AVIO_DATA_MARKER_TRAILER,
|
||||
/**
|
||||
* A point in the output bytestream where the underlying AVIOContext might
|
||||
* flush the buffer depending on latency or buffering requirements. Typically
|
||||
* means the end of a packet.
|
||||
*/
|
||||
AVIO_DATA_MARKER_FLUSH_POINT,
|
||||
};
|
||||
|
||||
/**
|
||||
* Bytestream IO Context.
|
||||
* New fields can be added to the end with minor version bumps.
|
||||
* Removal, reordering and changes to existing fields require a major
|
||||
* version bump.
|
||||
* sizeof(AVIOContext) must not be used outside libav*.
|
||||
*
|
||||
* @note None of the function pointers in AVIOContext should be called
|
||||
* directly, they should only be set by the client application
|
||||
* when implementing custom I/O. Normally these are set to the
|
||||
* function pointers specified in avio_alloc_context()
|
||||
*/
|
||||
typedef struct AVIOContext {
|
||||
/**
|
||||
* A class for private options.
|
||||
*
|
||||
* If this AVIOContext is created by avio_open2(), av_class is set and
|
||||
* passes the options down to protocols.
|
||||
*
|
||||
* If this AVIOContext is manually allocated, then av_class may be set by
|
||||
* the caller.
|
||||
*
|
||||
* warning -- this field can be NULL, be sure to not pass this AVIOContext
|
||||
* to any av_opt_* functions in that case.
|
||||
*/
|
||||
const AVClass *av_class;
|
||||
|
||||
/*
|
||||
* The following shows the relationship between buffer, buf_ptr,
|
||||
* buf_ptr_max, buf_end, buf_size, and pos, when reading and when writing
|
||||
* (since AVIOContext is used for both):
|
||||
*
|
||||
**********************************************************************************
|
||||
* READING
|
||||
**********************************************************************************
|
||||
*
|
||||
* | buffer_size |
|
||||
* |---------------------------------------|
|
||||
* | |
|
||||
*
|
||||
* buffer buf_ptr buf_end
|
||||
* +---------------+-----------------------+
|
||||
* |/ / / / / / / /|/ / / / / / /| |
|
||||
* read buffer: |/ / consumed / | to be read /| |
|
||||
* |/ / / / / / / /|/ / / / / / /| |
|
||||
* +---------------+-----------------------+
|
||||
*
|
||||
* pos
|
||||
* +-------------------------------------------+-----------------+
|
||||
* input file: | | |
|
||||
* +-------------------------------------------+-----------------+
|
||||
*
|
||||
*
|
||||
**********************************************************************************
|
||||
* WRITING
|
||||
**********************************************************************************
|
||||
*
|
||||
* | buffer_size |
|
||||
* |--------------------------------------|
|
||||
* | |
|
||||
*
|
||||
* buf_ptr_max
|
||||
* buffer (buf_ptr) buf_end
|
||||
* +-----------------------+--------------+
|
||||
* |/ / / / / / / / / / / /| |
|
||||
* write buffer: | / / to be flushed / / | |
|
||||
* |/ / / / / / / / / / / /| |
|
||||
* +-----------------------+--------------+
|
||||
* buf_ptr can be in this
|
||||
* due to a backward seek
|
||||
*
|
||||
* pos
|
||||
* +-------------+----------------------------------------------+
|
||||
* output file: | | |
|
||||
* +-------------+----------------------------------------------+
|
||||
*
|
||||
*/
|
||||
unsigned char *buffer; /**< Start of the buffer. */
|
||||
int buffer_size; /**< Maximum buffer size */
|
||||
unsigned char *buf_ptr; /**< Current position in the buffer */
|
||||
unsigned char *buf_end; /**< End of the data, may be less than
|
||||
buffer+buffer_size if the read function returned
|
||||
less data than requested, e.g. for streams where
|
||||
no more data has been received yet. */
|
||||
void *opaque; /**< A private pointer, passed to the read/write/seek/...
|
||||
functions. */
|
||||
int (*read_packet)(void *opaque, uint8_t *buf, int buf_size);
|
||||
int (*write_packet)(void *opaque, uint8_t *buf, int buf_size);
|
||||
int64_t (*seek)(void *opaque, int64_t offset, int whence);
|
||||
int64_t pos; /**< position in the file of the current buffer */
|
||||
int eof_reached; /**< true if eof reached */
|
||||
int write_flag; /**< true if open for writing */
|
||||
int max_packet_size;
|
||||
unsigned long checksum;
|
||||
unsigned char *checksum_ptr;
|
||||
unsigned long (*update_checksum)(unsigned long checksum, const uint8_t *buf, unsigned int size);
|
||||
int error; /**< contains the error code or 0 if no error happened */
|
||||
/**
|
||||
* Pause or resume playback for network streaming protocols - e.g. MMS.
|
||||
*/
|
||||
int (*read_pause)(void *opaque, int pause);
|
||||
/**
|
||||
* Seek to a given timestamp in stream with the specified stream_index.
|
||||
* Needed for some network streaming protocols which don't support seeking
|
||||
* to byte position.
|
||||
*/
|
||||
int64_t (*read_seek)(void *opaque, int stream_index,
|
||||
int64_t timestamp, int flags);
|
||||
/**
|
||||
* A combination of AVIO_SEEKABLE_ flags or 0 when the stream is not seekable.
|
||||
*/
|
||||
int seekable;
|
||||
|
||||
/**
|
||||
* max filesize, used to limit allocations
|
||||
* This field is internal to libavformat and access from outside is not allowed.
|
||||
*/
|
||||
int64_t maxsize;
|
||||
|
||||
/**
|
||||
* avio_read and avio_write should if possible be satisfied directly
|
||||
* instead of going through a buffer, and avio_seek will always
|
||||
* call the underlying seek function directly.
|
||||
*/
|
||||
int direct;
|
||||
|
||||
/**
|
||||
* Bytes read statistic
|
||||
* This field is internal to libavformat and access from outside is not allowed.
|
||||
*/
|
||||
int64_t bytes_read;
|
||||
|
||||
/**
|
||||
* seek statistic
|
||||
* This field is internal to libavformat and access from outside is not allowed.
|
||||
*/
|
||||
int seek_count;
|
||||
|
||||
/**
|
||||
* writeout statistic
|
||||
* This field is internal to libavformat and access from outside is not allowed.
|
||||
*/
|
||||
int writeout_count;
|
||||
|
||||
/**
|
||||
* Original buffer size
|
||||
* used internally after probing and ensure seekback to reset the buffer size
|
||||
* This field is internal to libavformat and access from outside is not allowed.
|
||||
*/
|
||||
int orig_buffer_size;
|
||||
|
||||
/**
|
||||
* Threshold to favor readahead over seek.
|
||||
* This is current internal only, do not use from outside.
|
||||
*/
|
||||
int short_seek_threshold;
|
||||
|
||||
/**
|
||||
* ',' separated list of allowed protocols.
|
||||
*/
|
||||
const char *protocol_whitelist;
|
||||
|
||||
/**
|
||||
* ',' separated list of disallowed protocols.
|
||||
*/
|
||||
const char *protocol_blacklist;
|
||||
|
||||
/**
|
||||
* A callback that is used instead of write_packet.
|
||||
*/
|
||||
int (*write_data_type)(void *opaque, uint8_t *buf, int buf_size,
|
||||
enum AVIODataMarkerType type, int64_t time);
|
||||
/**
|
||||
* If set, don't call write_data_type separately for AVIO_DATA_MARKER_BOUNDARY_POINT,
|
||||
* but ignore them and treat them as AVIO_DATA_MARKER_UNKNOWN (to avoid needlessly
|
||||
* small chunks of data returned from the callback).
|
||||
*/
|
||||
int ignore_boundary_point;
|
||||
|
||||
/**
|
||||
* Internal, not meant to be used from outside of AVIOContext.
|
||||
*/
|
||||
enum AVIODataMarkerType current_type;
|
||||
int64_t last_time;
|
||||
|
||||
/**
|
||||
* A callback that is used instead of short_seek_threshold.
|
||||
* This is current internal only, do not use from outside.
|
||||
*/
|
||||
int (*short_seek_get)(void *opaque);
|
||||
|
||||
int64_t written;
|
||||
|
||||
/**
|
||||
* Maximum reached position before a backward seek in the write buffer,
|
||||
* used keeping track of already written data for a later flush.
|
||||
*/
|
||||
unsigned char *buf_ptr_max;
|
||||
|
||||
/**
|
||||
* Try to buffer at least this amount of data before flushing it
|
||||
*/
|
||||
int min_packet_size;
|
||||
} AVIOContext;
|
||||
|
||||
/**
|
||||
* Return the name of the protocol that will handle the passed URL.
|
||||
*
|
||||
* NULL is returned if no protocol could be found for the given URL.
|
||||
*
|
||||
* @return Name of the protocol or NULL.
|
||||
*/
|
||||
const char *avio_find_protocol_name(const char *url);
|
||||
|
||||
/**
|
||||
* Return AVIO_FLAG_* access flags corresponding to the access permissions
|
||||
* of the resource in url, or a negative value corresponding to an
|
||||
* AVERROR code in case of failure. The returned access flags are
|
||||
* masked by the value in flags.
|
||||
*
|
||||
* @note This function is intrinsically unsafe, in the sense that the
|
||||
* checked resource may change its existence or permission status from
|
||||
* one call to another. Thus you should not trust the returned value,
|
||||
* unless you are sure that no other processes are accessing the
|
||||
* checked resource.
|
||||
*/
|
||||
int avio_check(const char *url, int flags);
|
||||
|
||||
/**
|
||||
* Move or rename a resource.
|
||||
*
|
||||
* @note url_src and url_dst should share the same protocol and authority.
|
||||
*
|
||||
* @param url_src url to resource to be moved
|
||||
* @param url_dst new url to resource if the operation succeeded
|
||||
* @return >=0 on success or negative on error.
|
||||
*/
|
||||
int avpriv_io_move(const char *url_src, const char *url_dst);
|
||||
|
||||
/**
|
||||
* Delete a resource.
|
||||
*
|
||||
* @param url resource to be deleted.
|
||||
* @return >=0 on success or negative on error.
|
||||
*/
|
||||
int avpriv_io_delete(const char *url);
|
||||
|
||||
/**
|
||||
* Open directory for reading.
|
||||
*
|
||||
* @param s directory read context. Pointer to a NULL pointer must be passed.
|
||||
* @param url directory to be listed.
|
||||
* @param options A dictionary filled with protocol-private options. On return
|
||||
* this parameter will be destroyed and replaced with a dictionary
|
||||
* containing options that were not found. May be NULL.
|
||||
* @return >=0 on success or negative on error.
|
||||
*/
|
||||
int avio_open_dir(AVIODirContext **s, const char *url, AVDictionary **options);
|
||||
|
||||
/**
|
||||
* Get next directory entry.
|
||||
*
|
||||
* Returned entry must be freed with avio_free_directory_entry(). In particular
|
||||
* it may outlive AVIODirContext.
|
||||
*
|
||||
* @param s directory read context.
|
||||
* @param[out] next next entry or NULL when no more entries.
|
||||
* @return >=0 on success or negative on error. End of list is not considered an
|
||||
* error.
|
||||
*/
|
||||
int avio_read_dir(AVIODirContext *s, AVIODirEntry **next);
|
||||
|
||||
/**
|
||||
* Close directory.
|
||||
*
|
||||
* @note Entries created using avio_read_dir() are not deleted and must be
|
||||
* freeded with avio_free_directory_entry().
|
||||
*
|
||||
* @param s directory read context.
|
||||
* @return >=0 on success or negative on error.
|
||||
*/
|
||||
int avio_close_dir(AVIODirContext **s);
|
||||
|
||||
/**
|
||||
* Free entry allocated by avio_read_dir().
|
||||
*
|
||||
* @param entry entry to be freed.
|
||||
*/
|
||||
void avio_free_directory_entry(AVIODirEntry **entry);
|
||||
|
||||
/**
|
||||
* Allocate and initialize an AVIOContext for buffered I/O. It must be later
|
||||
* freed with avio_context_free().
|
||||
*
|
||||
* @param buffer Memory block for input/output operations via AVIOContext.
|
||||
* The buffer must be allocated with av_malloc() and friends.
|
||||
* It may be freed and replaced with a new buffer by libavformat.
|
||||
* AVIOContext.buffer holds the buffer currently in use,
|
||||
* which must be later freed with av_free().
|
||||
* @param buffer_size The buffer size is very important for performance.
|
||||
* For protocols with fixed blocksize it should be set to this blocksize.
|
||||
* For others a typical size is a cache page, e.g. 4kb.
|
||||
* @param write_flag Set to 1 if the buffer should be writable, 0 otherwise.
|
||||
* @param opaque An opaque pointer to user-specific data.
|
||||
* @param read_packet A function for refilling the buffer, may be NULL.
|
||||
* For stream protocols, must never return 0 but rather
|
||||
* a proper AVERROR code.
|
||||
* @param write_packet A function for writing the buffer contents, may be NULL.
|
||||
* The function may not change the input buffers content.
|
||||
* @param seek A function for seeking to specified byte position, may be NULL.
|
||||
*
|
||||
* @return Allocated AVIOContext or NULL on failure.
|
||||
*/
|
||||
AVIOContext *avio_alloc_context(
|
||||
unsigned char *buffer,
|
||||
int buffer_size,
|
||||
int write_flag,
|
||||
void *opaque,
|
||||
int (*read_packet)(void *opaque, uint8_t *buf, int buf_size),
|
||||
int (*write_packet)(void *opaque, uint8_t *buf, int buf_size),
|
||||
int64_t (*seek)(void *opaque, int64_t offset, int whence));
|
||||
|
||||
/**
|
||||
* Free the supplied IO context and everything associated with it.
|
||||
*
|
||||
* @param s Double pointer to the IO context. This function will write NULL
|
||||
* into s.
|
||||
*/
|
||||
void avio_context_free(AVIOContext **s);
|
||||
|
||||
void avio_w8(AVIOContext *s, int b);
|
||||
void avio_write(AVIOContext *s, const unsigned char *buf, int size);
|
||||
void avio_wl64(AVIOContext *s, uint64_t val);
|
||||
void avio_wb64(AVIOContext *s, uint64_t val);
|
||||
void avio_wl32(AVIOContext *s, unsigned int val);
|
||||
void avio_wb32(AVIOContext *s, unsigned int val);
|
||||
void avio_wl24(AVIOContext *s, unsigned int val);
|
||||
void avio_wb24(AVIOContext *s, unsigned int val);
|
||||
void avio_wl16(AVIOContext *s, unsigned int val);
|
||||
void avio_wb16(AVIOContext *s, unsigned int val);
|
||||
|
||||
/**
|
||||
* Write a NULL-terminated string.
|
||||
* @return number of bytes written.
|
||||
*/
|
||||
int avio_put_str(AVIOContext *s, const char *str);
|
||||
|
||||
/**
|
||||
* Convert an UTF-8 string to UTF-16LE and write it.
|
||||
* @param s the AVIOContext
|
||||
* @param str NULL-terminated UTF-8 string
|
||||
*
|
||||
* @return number of bytes written.
|
||||
*/
|
||||
int avio_put_str16le(AVIOContext *s, const char *str);
|
||||
|
||||
/**
|
||||
* Convert an UTF-8 string to UTF-16BE and write it.
|
||||
* @param s the AVIOContext
|
||||
* @param str NULL-terminated UTF-8 string
|
||||
*
|
||||
* @return number of bytes written.
|
||||
*/
|
||||
int avio_put_str16be(AVIOContext *s, const char *str);
|
||||
|
||||
/**
|
||||
* Mark the written bytestream as a specific type.
|
||||
*
|
||||
* Zero-length ranges are omitted from the output.
|
||||
*
|
||||
* @param time the stream time the current bytestream pos corresponds to
|
||||
* (in AV_TIME_BASE units), or AV_NOPTS_VALUE if unknown or not
|
||||
* applicable
|
||||
* @param type the kind of data written starting at the current pos
|
||||
*/
|
||||
void avio_write_marker(AVIOContext *s, int64_t time, enum AVIODataMarkerType type);
|
||||
|
||||
/**
|
||||
* ORing this as the "whence" parameter to a seek function causes it to
|
||||
* return the filesize without seeking anywhere. Supporting this is optional.
|
||||
* If it is not supported then the seek function will return <0.
|
||||
*/
|
||||
#define AVSEEK_SIZE 0x10000
|
||||
|
||||
/**
|
||||
* Passing this flag as the "whence" parameter to a seek function causes it to
|
||||
* seek by any means (like reopening and linear reading) or other normally unreasonable
|
||||
* means that can be extremely slow.
|
||||
* This may be ignored by the seek code.
|
||||
*/
|
||||
#define AVSEEK_FORCE 0x20000
|
||||
|
||||
/**
|
||||
* fseek() equivalent for AVIOContext.
|
||||
* @return new position or AVERROR.
|
||||
*/
|
||||
int64_t avio_seek(AVIOContext *s, int64_t offset, int whence);
|
||||
|
||||
/**
|
||||
* Skip given number of bytes forward
|
||||
* @return new position or AVERROR.
|
||||
*/
|
||||
int64_t avio_skip(AVIOContext *s, int64_t offset);
|
||||
|
||||
/**
|
||||
* ftell() equivalent for AVIOContext.
|
||||
* @return position or AVERROR.
|
||||
*/
|
||||
static av_always_inline int64_t avio_tell(AVIOContext *s)
|
||||
{
|
||||
return avio_seek(s, 0, SEEK_CUR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the filesize.
|
||||
* @return filesize or AVERROR
|
||||
*/
|
||||
int64_t avio_size(AVIOContext *s);
|
||||
|
||||
/**
|
||||
* feof() equivalent for AVIOContext.
|
||||
* @return non zero if and only if end of file
|
||||
*/
|
||||
int avio_feof(AVIOContext *s);
|
||||
|
||||
/** @warning Writes up to 4 KiB per call */
|
||||
int avio_printf(AVIOContext *s, const char *fmt, ...) av_printf_format(2, 3);
|
||||
|
||||
/**
|
||||
* Force flushing of buffered data.
|
||||
*
|
||||
* For write streams, force the buffered data to be immediately written to the output,
|
||||
* without to wait to fill the internal buffer.
|
||||
*
|
||||
* For read streams, discard all currently buffered data, and advance the
|
||||
* reported file position to that of the underlying stream. This does not
|
||||
* read new data, and does not perform any seeks.
|
||||
*/
|
||||
void avio_flush(AVIOContext *s);
|
||||
|
||||
/**
|
||||
* Read size bytes from AVIOContext into buf.
|
||||
* @return number of bytes read or AVERROR
|
||||
*/
|
||||
int avio_read(AVIOContext *s, unsigned char *buf, int size);
|
||||
|
||||
/**
|
||||
* Read size bytes from AVIOContext into buf. Unlike avio_read(), this is allowed
|
||||
* to read fewer bytes than requested. The missing bytes can be read in the next
|
||||
* call. This always tries to read at least 1 byte.
|
||||
* Useful to reduce latency in certain cases.
|
||||
* @return number of bytes read or AVERROR
|
||||
*/
|
||||
int avio_read_partial(AVIOContext *s, unsigned char *buf, int size);
|
||||
|
||||
/**
|
||||
* @name Functions for reading from AVIOContext
|
||||
* @{
|
||||
*
|
||||
* @note return 0 if EOF, so you cannot use it if EOF handling is
|
||||
* necessary
|
||||
*/
|
||||
int avio_r8 (AVIOContext *s);
|
||||
unsigned int avio_rl16(AVIOContext *s);
|
||||
unsigned int avio_rl24(AVIOContext *s);
|
||||
unsigned int avio_rl32(AVIOContext *s);
|
||||
uint64_t avio_rl64(AVIOContext *s);
|
||||
unsigned int avio_rb16(AVIOContext *s);
|
||||
unsigned int avio_rb24(AVIOContext *s);
|
||||
unsigned int avio_rb32(AVIOContext *s);
|
||||
uint64_t avio_rb64(AVIOContext *s);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Read a string from pb into buf. The reading will terminate when either
|
||||
* a NULL character was encountered, maxlen bytes have been read, or nothing
|
||||
* more can be read from pb. The result is guaranteed to be NULL-terminated, it
|
||||
* will be truncated if buf is too small.
|
||||
* Note that the string is not interpreted or validated in any way, it
|
||||
* might get truncated in the middle of a sequence for multi-byte encodings.
|
||||
*
|
||||
* @return number of bytes read (is always <= maxlen).
|
||||
* If reading ends on EOF or error, the return value will be one more than
|
||||
* bytes actually read.
|
||||
*/
|
||||
int avio_get_str(AVIOContext *pb, int maxlen, char *buf, int buflen);
|
||||
|
||||
/**
|
||||
* Read a UTF-16 string from pb and convert it to UTF-8.
|
||||
* The reading will terminate when either a null or invalid character was
|
||||
* encountered or maxlen bytes have been read.
|
||||
* @return number of bytes read (is always <= maxlen)
|
||||
*/
|
||||
int avio_get_str16le(AVIOContext *pb, int maxlen, char *buf, int buflen);
|
||||
int avio_get_str16be(AVIOContext *pb, int maxlen, char *buf, int buflen);
|
||||
|
||||
|
||||
/**
|
||||
* @name URL open modes
|
||||
* The flags argument to avio_open must be one of the following
|
||||
* constants, optionally ORed with other flags.
|
||||
* @{
|
||||
*/
|
||||
#define AVIO_FLAG_READ 1 /**< read-only */
|
||||
#define AVIO_FLAG_WRITE 2 /**< write-only */
|
||||
#define AVIO_FLAG_READ_WRITE (AVIO_FLAG_READ|AVIO_FLAG_WRITE) /**< read-write pseudo flag */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Use non-blocking mode.
|
||||
* If this flag is set, operations on the context will return
|
||||
* AVERROR(EAGAIN) if they can not be performed immediately.
|
||||
* If this flag is not set, operations on the context will never return
|
||||
* AVERROR(EAGAIN).
|
||||
* Note that this flag does not affect the opening/connecting of the
|
||||
* context. Connecting a protocol will always block if necessary (e.g. on
|
||||
* network protocols) but never hang (e.g. on busy devices).
|
||||
* Warning: non-blocking protocols is work-in-progress; this flag may be
|
||||
* silently ignored.
|
||||
*/
|
||||
#define AVIO_FLAG_NONBLOCK 8
|
||||
|
||||
/**
|
||||
* Use direct mode.
|
||||
* avio_read and avio_write should if possible be satisfied directly
|
||||
* instead of going through a buffer, and avio_seek will always
|
||||
* call the underlying seek function directly.
|
||||
*/
|
||||
#define AVIO_FLAG_DIRECT 0x8000
|
||||
|
||||
/**
|
||||
* Create and initialize a AVIOContext for accessing the
|
||||
* resource indicated by url.
|
||||
* @note When the resource indicated by url has been opened in
|
||||
* read+write mode, the AVIOContext can be used only for writing.
|
||||
*
|
||||
* @param s Used to return the pointer to the created AVIOContext.
|
||||
* In case of failure the pointed to value is set to NULL.
|
||||
* @param url resource to access
|
||||
* @param flags flags which control how the resource indicated by url
|
||||
* is to be opened
|
||||
* @return >= 0 in case of success, a negative value corresponding to an
|
||||
* AVERROR code in case of failure
|
||||
*/
|
||||
int avio_open(AVIOContext **s, const char *url, int flags);
|
||||
|
||||
/**
|
||||
* Create and initialize a AVIOContext for accessing the
|
||||
* resource indicated by url.
|
||||
* @note When the resource indicated by url has been opened in
|
||||
* read+write mode, the AVIOContext can be used only for writing.
|
||||
*
|
||||
* @param s Used to return the pointer to the created AVIOContext.
|
||||
* In case of failure the pointed to value is set to NULL.
|
||||
* @param url resource to access
|
||||
* @param flags flags which control how the resource indicated by url
|
||||
* is to be opened
|
||||
* @param int_cb an interrupt callback to be used at the protocols level
|
||||
* @param options A dictionary filled with protocol-private options. On return
|
||||
* this parameter will be destroyed and replaced with a dict containing options
|
||||
* that were not found. May be NULL.
|
||||
* @return >= 0 in case of success, a negative value corresponding to an
|
||||
* AVERROR code in case of failure
|
||||
*/
|
||||
int avio_open2(AVIOContext **s, const char *url, int flags,
|
||||
const AVIOInterruptCB *int_cb, AVDictionary **options);
|
||||
|
||||
/**
|
||||
* Close the resource accessed by the AVIOContext s and free it.
|
||||
* This function can only be used if s was opened by avio_open().
|
||||
*
|
||||
* The internal buffer is automatically flushed before closing the
|
||||
* resource.
|
||||
*
|
||||
* @return 0 on success, an AVERROR < 0 on error.
|
||||
* @see avio_closep
|
||||
*/
|
||||
int avio_close(AVIOContext *s);
|
||||
|
||||
/**
|
||||
* Close the resource accessed by the AVIOContext *s, free it
|
||||
* and set the pointer pointing to it to NULL.
|
||||
* This function can only be used if s was opened by avio_open().
|
||||
*
|
||||
* The internal buffer is automatically flushed before closing the
|
||||
* resource.
|
||||
*
|
||||
* @return 0 on success, an AVERROR < 0 on error.
|
||||
* @see avio_close
|
||||
*/
|
||||
int avio_closep(AVIOContext **s);
|
||||
|
||||
|
||||
/**
|
||||
* Open a write only memory stream.
|
||||
*
|
||||
* @param s new IO context
|
||||
* @return zero if no error.
|
||||
*/
|
||||
int avio_open_dyn_buf(AVIOContext **s);
|
||||
|
||||
/**
|
||||
* Return the written size and a pointer to the buffer.
|
||||
* The AVIOContext stream is left intact.
|
||||
* The buffer must NOT be freed.
|
||||
* No padding is added to the buffer.
|
||||
*
|
||||
* @param s IO context
|
||||
* @param pbuffer pointer to a byte buffer
|
||||
* @return the length of the byte buffer
|
||||
*/
|
||||
int avio_get_dyn_buf(AVIOContext *s, uint8_t **pbuffer);
|
||||
|
||||
/**
|
||||
* Return the written size and a pointer to the buffer. The buffer
|
||||
* must be freed with av_free().
|
||||
* Padding of AV_INPUT_BUFFER_PADDING_SIZE is added to the buffer.
|
||||
*
|
||||
* @param s IO context
|
||||
* @param pbuffer pointer to a byte buffer
|
||||
* @return the length of the byte buffer
|
||||
*/
|
||||
int avio_close_dyn_buf(AVIOContext *s, uint8_t **pbuffer);
|
||||
|
||||
/**
|
||||
* Iterate through names of available protocols.
|
||||
*
|
||||
* @param opaque A private pointer representing current protocol.
|
||||
* It must be a pointer to NULL on first iteration and will
|
||||
* be updated by successive calls to avio_enum_protocols.
|
||||
* @param output If set to 1, iterate over output protocols,
|
||||
* otherwise over input protocols.
|
||||
*
|
||||
* @return A static string containing the name of current protocol or NULL
|
||||
*/
|
||||
const char *avio_enum_protocols(void **opaque, int output);
|
||||
|
||||
/**
|
||||
* Pause and resume playing - only meaningful if using a network streaming
|
||||
* protocol (e.g. MMS).
|
||||
*
|
||||
* @param h IO context from which to call the read_pause function pointer
|
||||
* @param pause 1 for pause, 0 for resume
|
||||
*/
|
||||
int avio_pause(AVIOContext *h, int pause);
|
||||
|
||||
/**
|
||||
* Seek to a given timestamp relative to some component stream.
|
||||
* Only meaningful if using a network streaming protocol (e.g. MMS.).
|
||||
*
|
||||
* @param h IO context from which to call the seek function pointers
|
||||
* @param stream_index The stream index that the timestamp is relative to.
|
||||
* If stream_index is (-1) the timestamp should be in AV_TIME_BASE
|
||||
* units from the beginning of the presentation.
|
||||
* If a stream_index >= 0 is used and the protocol does not support
|
||||
* seeking based on component streams, the call will fail.
|
||||
* @param timestamp timestamp in AVStream.time_base units
|
||||
* or if there is no stream specified then in AV_TIME_BASE units.
|
||||
* @param flags Optional combination of AVSEEK_FLAG_BACKWARD, AVSEEK_FLAG_BYTE
|
||||
* and AVSEEK_FLAG_ANY. The protocol may silently ignore
|
||||
* AVSEEK_FLAG_BACKWARD and AVSEEK_FLAG_ANY, but AVSEEK_FLAG_BYTE will
|
||||
* fail if used and not supported.
|
||||
* @return >= 0 on success
|
||||
* @see AVInputFormat::read_seek
|
||||
*/
|
||||
int64_t avio_seek_time(AVIOContext *h, int stream_index,
|
||||
int64_t timestamp, int flags);
|
||||
|
||||
/* Avoid a warning. The header can not be included because it breaks c++. */
|
||||
struct AVBPrint;
|
||||
|
||||
/**
|
||||
* Read contents of h into print buffer, up to max_size bytes, or up to EOF.
|
||||
*
|
||||
* @return 0 for success (max_size bytes read or EOF reached), negative error
|
||||
* code otherwise
|
||||
*/
|
||||
int avio_read_to_bprint(AVIOContext *h, struct AVBPrint *pb, size_t max_size);
|
||||
|
||||
/**
|
||||
* Accept and allocate a client context on a server context.
|
||||
* @param s the server context
|
||||
* @param c the client context, must be unallocated
|
||||
* @return >= 0 on success or a negative value corresponding
|
||||
* to an AVERROR on failure
|
||||
*/
|
||||
int avio_accept(AVIOContext *s, AVIOContext **c);
|
||||
|
||||
/**
|
||||
* Perform one step of the protocol handshake to accept a new client.
|
||||
* This function must be called on a client returned by avio_accept() before
|
||||
* using it as a read/write context.
|
||||
* It is separate from avio_accept() because it may block.
|
||||
* A step of the handshake is defined by places where the application may
|
||||
* decide to change the proceedings.
|
||||
* For example, on a protocol with a request header and a reply header, each
|
||||
* one can constitute a step because the application may use the parameters
|
||||
* from the request to change parameters in the reply; or each individual
|
||||
* chunk of the request can constitute a step.
|
||||
* If the handshake is already finished, avio_handshake() does nothing and
|
||||
* returns 0 immediately.
|
||||
*
|
||||
* @param c the client context to perform the handshake on
|
||||
* @return 0 on a complete and successful handshake
|
||||
* > 0 if the handshake progressed, but is not complete
|
||||
* < 0 for an AVERROR code
|
||||
*/
|
||||
int avio_handshake(AVIOContext *c);
|
||||
#endif /* AVFORMAT_AVIO_H */
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Version macros.
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef AVFORMAT_VERSION_H
|
||||
#define AVFORMAT_VERSION_H
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @ingroup libavf
|
||||
* Libavformat version macros
|
||||
*/
|
||||
|
||||
#include "libavutil/version.h"
|
||||
|
||||
// Major bumping may affect Ticket5467, 5421, 5451(compatibility with Chromium)
|
||||
// Also please add any ticket numbers that you believe might be affected here
|
||||
#define LIBAVFORMAT_VERSION_MAJOR 58
|
||||
#define LIBAVFORMAT_VERSION_MINOR 17
|
||||
#define LIBAVFORMAT_VERSION_MICRO 101
|
||||
|
||||
#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
|
||||
LIBAVFORMAT_VERSION_MINOR, \
|
||||
LIBAVFORMAT_VERSION_MICRO)
|
||||
#define LIBAVFORMAT_VERSION AV_VERSION(LIBAVFORMAT_VERSION_MAJOR, \
|
||||
LIBAVFORMAT_VERSION_MINOR, \
|
||||
LIBAVFORMAT_VERSION_MICRO)
|
||||
#define LIBAVFORMAT_BUILD LIBAVFORMAT_VERSION_INT
|
||||
|
||||
#define LIBAVFORMAT_IDENT "Lavf" AV_STRINGIFY(LIBAVFORMAT_VERSION)
|
||||
|
||||
/**
|
||||
* FF_API_* defines may be placed below to indicate public API that will be
|
||||
* dropped at a future version bump. The defines themselves are not part of
|
||||
* the public API and may change, break or disappear at any time.
|
||||
*
|
||||
* @note, when bumping the major version it is recommended to manually
|
||||
* disable each FF_API_* in its own commit instead of disabling them all
|
||||
* at once through the bump. This improves the git bisect-ability of the change.
|
||||
*
|
||||
*/
|
||||
#ifndef FF_API_COMPUTE_PKT_FIELDS2
|
||||
#define FF_API_COMPUTE_PKT_FIELDS2 (LIBAVFORMAT_VERSION_MAJOR < 59)
|
||||
#endif
|
||||
#ifndef FF_API_OLD_OPEN_CALLBACKS
|
||||
#define FF_API_OLD_OPEN_CALLBACKS (LIBAVFORMAT_VERSION_MAJOR < 59)
|
||||
#endif
|
||||
#ifndef FF_API_LAVF_AVCTX
|
||||
#define FF_API_LAVF_AVCTX (LIBAVFORMAT_VERSION_MAJOR < 59)
|
||||
#endif
|
||||
#ifndef FF_API_HTTP_USER_AGENT
|
||||
#define FF_API_HTTP_USER_AGENT (LIBAVFORMAT_VERSION_MAJOR < 59)
|
||||
#endif
|
||||
#ifndef FF_API_HLS_WRAP
|
||||
#define FF_API_HLS_WRAP (LIBAVFORMAT_VERSION_MAJOR < 59)
|
||||
#endif
|
||||
#ifndef FF_API_LAVF_KEEPSIDE_FLAG
|
||||
#define FF_API_LAVF_KEEPSIDE_FLAG (LIBAVFORMAT_VERSION_MAJOR < 59)
|
||||
#endif
|
||||
#ifndef FF_API_OLD_ROTATE_API
|
||||
#define FF_API_OLD_ROTATE_API (LIBAVFORMAT_VERSION_MAJOR < 59)
|
||||
#endif
|
||||
#ifndef FF_API_FORMAT_GET_SET
|
||||
#define FF_API_FORMAT_GET_SET (LIBAVFORMAT_VERSION_MAJOR < 59)
|
||||
#endif
|
||||
#ifndef FF_API_OLD_AVIO_EOF_0
|
||||
#define FF_API_OLD_AVIO_EOF_0 (LIBAVFORMAT_VERSION_MAJOR < 59)
|
||||
#endif
|
||||
#ifndef FF_API_LAVF_FFSERVER
|
||||
#define FF_API_LAVF_FFSERVER (LIBAVFORMAT_VERSION_MAJOR < 59)
|
||||
#endif
|
||||
#ifndef FF_API_FORMAT_FILENAME
|
||||
#define FF_API_FORMAT_FILENAME (LIBAVFORMAT_VERSION_MAJOR < 59)
|
||||
#endif
|
||||
#ifndef FF_API_OLD_RTSP_OPTIONS
|
||||
#define FF_API_OLD_RTSP_OPTIONS (LIBAVFORMAT_VERSION_MAJOR < 59)
|
||||
#endif
|
||||
#ifndef FF_API_NEXT
|
||||
#define FF_API_NEXT (LIBAVFORMAT_VERSION_MAJOR < 59)
|
||||
#endif
|
||||
#ifndef FF_API_DASH_MIN_SEG_DURATION
|
||||
#define FF_API_DASH_MIN_SEG_DURATION (LIBAVFORMAT_VERSION_MAJOR < 59)
|
||||
#endif
|
||||
#ifndef FF_API_LAVF_MP4A_LATM
|
||||
#define FF_API_LAVF_MP4A_LATM (LIBAVFORMAT_VERSION_MAJOR < 59)
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef FF_API_R_FRAME_RATE
|
||||
#define FF_API_R_FRAME_RATE 1
|
||||
#endif
|
||||
#endif /* AVFORMAT_VERSION_H */
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2003 Michael Niedermayer ([email protected])
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* FFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef POSTPROC_POSTPROCESS_H
|
||||
#define POSTPROC_POSTPROCESS_H
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @ingroup lpp
|
||||
* external API header
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup lpp libpostproc
|
||||
* Video postprocessing library.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "libpostproc/version.h"
|
||||
|
||||
/**
|
||||
* Return the LIBPOSTPROC_VERSION_INT constant.
|
||||
*/
|
||||
unsigned postproc_version(void);
|
||||
|
||||
/**
|
||||
* Return the libpostproc build-time configuration.
|
||||
*/
|
||||
const char *postproc_configuration(void);
|
||||
|
||||
/**
|
||||
* Return the libpostproc license.
|
||||
*/
|
||||
const char *postproc_license(void);
|
||||
|
||||
#define PP_QUALITY_MAX 6
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
typedef void pp_context;
|
||||
typedef void pp_mode;
|
||||
|
||||
#if LIBPOSTPROC_VERSION_INT < (52<<16)
|
||||
typedef pp_context pp_context_t;
|
||||
typedef pp_mode pp_mode_t;
|
||||
extern const char *const pp_help; ///< a simple help text
|
||||
#else
|
||||
extern const char pp_help[]; ///< a simple help text
|
||||
#endif
|
||||
|
||||
void pp_postprocess(const uint8_t * src[3], const int srcStride[3],
|
||||
uint8_t * dst[3], const int dstStride[3],
|
||||
int horizontalSize, int verticalSize,
|
||||
const int8_t *QP_store, int QP_stride,
|
||||
pp_mode *mode, pp_context *ppContext, int pict_type);
|
||||
|
||||
|
||||
/**
|
||||
* Return a pp_mode or NULL if an error occurred.
|
||||
*
|
||||
* @param name the string after "-pp" on the command line
|
||||
* @param quality a number from 0 to PP_QUALITY_MAX
|
||||
*/
|
||||
pp_mode *pp_get_mode_by_name_and_quality(const char *name, int quality);
|
||||
void pp_free_mode(pp_mode *mode);
|
||||
|
||||
pp_context *pp_get_context(int width, int height, int flags);
|
||||
void pp_free_context(pp_context *ppContext);
|
||||
|
||||
#define PP_CPU_CAPS_MMX 0x80000000
|
||||
#define PP_CPU_CAPS_MMX2 0x20000000
|
||||
#define PP_CPU_CAPS_3DNOW 0x40000000
|
||||
#define PP_CPU_CAPS_ALTIVEC 0x10000000
|
||||
#define PP_CPU_CAPS_AUTO 0x00080000
|
||||
|
||||
#define PP_FORMAT 0x00000008
|
||||
#define PP_FORMAT_420 (0x00000011|PP_FORMAT)
|
||||
#define PP_FORMAT_422 (0x00000001|PP_FORMAT)
|
||||
#define PP_FORMAT_411 (0x00000002|PP_FORMAT)
|
||||
#define PP_FORMAT_444 (0x00000000|PP_FORMAT)
|
||||
#define PP_FORMAT_440 (0x00000010|PP_FORMAT)
|
||||
|
||||
#define PP_PICT_TYPE_QP2 0x00000010 ///< MPEG2 style QScale
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* POSTPROC_POSTPROCESS_H */
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Version macros.
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef POSTPROC_VERSION_H
|
||||
#define POSTPROC_VERSION_H
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Libpostproc version macros
|
||||
*/
|
||||
|
||||
#include "libavutil/avutil.h"
|
||||
|
||||
#define LIBPOSTPROC_VERSION_MAJOR 55
|
||||
#define LIBPOSTPROC_VERSION_MINOR 2
|
||||
#define LIBPOSTPROC_VERSION_MICRO 100
|
||||
|
||||
#define LIBPOSTPROC_VERSION_INT AV_VERSION_INT(LIBPOSTPROC_VERSION_MAJOR, \
|
||||
LIBPOSTPROC_VERSION_MINOR, \
|
||||
LIBPOSTPROC_VERSION_MICRO)
|
||||
#define LIBPOSTPROC_VERSION AV_VERSION(LIBPOSTPROC_VERSION_MAJOR, \
|
||||
LIBPOSTPROC_VERSION_MINOR, \
|
||||
LIBPOSTPROC_VERSION_MICRO)
|
||||
#define LIBPOSTPROC_BUILD LIBPOSTPROC_VERSION_INT
|
||||
|
||||
#define LIBPOSTPROC_IDENT "postproc" AV_STRINGIFY(LIBPOSTPROC_VERSION)
|
||||
|
||||
#endif /* POSTPROC_VERSION_H */
|
||||
@@ -0,0 +1,579 @@
|
||||
/*
|
||||
* Copyright (C) 2011-2013 Michael Niedermayer ([email protected])
|
||||
*
|
||||
* This file is part of libswresample
|
||||
*
|
||||
* libswresample is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* libswresample is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with libswresample; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef SWRESAMPLE_SWRESAMPLE_H
|
||||
#define SWRESAMPLE_SWRESAMPLE_H
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @ingroup lswr
|
||||
* libswresample public header
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup lswr libswresample
|
||||
* @{
|
||||
*
|
||||
* Audio resampling, sample format conversion and mixing library.
|
||||
*
|
||||
* Interaction with lswr is done through SwrContext, which is
|
||||
* allocated with swr_alloc() or swr_alloc_set_opts(). It is opaque, so all parameters
|
||||
* must be set with the @ref avoptions API.
|
||||
*
|
||||
* The first thing you will need to do in order to use lswr is to allocate
|
||||
* SwrContext. This can be done with swr_alloc() or swr_alloc_set_opts(). If you
|
||||
* are using the former, you must set options through the @ref avoptions API.
|
||||
* The latter function provides the same feature, but it allows you to set some
|
||||
* common options in the same statement.
|
||||
*
|
||||
* For example the following code will setup conversion from planar float sample
|
||||
* format to interleaved signed 16-bit integer, downsampling from 48kHz to
|
||||
* 44.1kHz and downmixing from 5.1 channels to stereo (using the default mixing
|
||||
* matrix). This is using the swr_alloc() function.
|
||||
* @code
|
||||
* SwrContext *swr = swr_alloc();
|
||||
* av_opt_set_channel_layout(swr, "in_channel_layout", AV_CH_LAYOUT_5POINT1, 0);
|
||||
* av_opt_set_channel_layout(swr, "out_channel_layout", AV_CH_LAYOUT_STEREO, 0);
|
||||
* av_opt_set_int(swr, "in_sample_rate", 48000, 0);
|
||||
* av_opt_set_int(swr, "out_sample_rate", 44100, 0);
|
||||
* av_opt_set_sample_fmt(swr, "in_sample_fmt", AV_SAMPLE_FMT_FLTP, 0);
|
||||
* av_opt_set_sample_fmt(swr, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0);
|
||||
* @endcode
|
||||
*
|
||||
* The same job can be done using swr_alloc_set_opts() as well:
|
||||
* @code
|
||||
* SwrContext *swr = swr_alloc_set_opts(NULL, // we're allocating a new context
|
||||
* AV_CH_LAYOUT_STEREO, // out_ch_layout
|
||||
* AV_SAMPLE_FMT_S16, // out_sample_fmt
|
||||
* 44100, // out_sample_rate
|
||||
* AV_CH_LAYOUT_5POINT1, // in_ch_layout
|
||||
* AV_SAMPLE_FMT_FLTP, // in_sample_fmt
|
||||
* 48000, // in_sample_rate
|
||||
* 0, // log_offset
|
||||
* NULL); // log_ctx
|
||||
* @endcode
|
||||
*
|
||||
* Once all values have been set, it must be initialized with swr_init(). If
|
||||
* you need to change the conversion parameters, you can change the parameters
|
||||
* using @ref AVOptions, as described above in the first example; or by using
|
||||
* swr_alloc_set_opts(), but with the first argument the allocated context.
|
||||
* You must then call swr_init() again.
|
||||
*
|
||||
* The conversion itself is done by repeatedly calling swr_convert().
|
||||
* Note that the samples may get buffered in swr if you provide insufficient
|
||||
* output space or if sample rate conversion is done, which requires "future"
|
||||
* samples. Samples that do not require future input can be retrieved at any
|
||||
* time by using swr_convert() (in_count can be set to 0).
|
||||
* At the end of conversion the resampling buffer can be flushed by calling
|
||||
* swr_convert() with NULL in and 0 in_count.
|
||||
*
|
||||
* The samples used in the conversion process can be managed with the libavutil
|
||||
* @ref lavu_sampmanip "samples manipulation" API, including av_samples_alloc()
|
||||
* function used in the following example.
|
||||
*
|
||||
* The delay between input and output, can at any time be found by using
|
||||
* swr_get_delay().
|
||||
*
|
||||
* The following code demonstrates the conversion loop assuming the parameters
|
||||
* from above and caller-defined functions get_input() and handle_output():
|
||||
* @code
|
||||
* uint8_t **input;
|
||||
* int in_samples;
|
||||
*
|
||||
* while (get_input(&input, &in_samples)) {
|
||||
* uint8_t *output;
|
||||
* int out_samples = av_rescale_rnd(swr_get_delay(swr, 48000) +
|
||||
* in_samples, 44100, 48000, AV_ROUND_UP);
|
||||
* av_samples_alloc(&output, NULL, 2, out_samples,
|
||||
* AV_SAMPLE_FMT_S16, 0);
|
||||
* out_samples = swr_convert(swr, &output, out_samples,
|
||||
* input, in_samples);
|
||||
* handle_output(output, out_samples);
|
||||
* av_freep(&output);
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
* When the conversion is finished, the conversion
|
||||
* context and everything associated with it must be freed with swr_free().
|
||||
* A swr_close() function is also available, but it exists mainly for
|
||||
* compatibility with libavresample, and is not required to be called.
|
||||
*
|
||||
* There will be no memory leak if the data is not completely flushed before
|
||||
* swr_free().
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "libavutil/channel_layout.h"
|
||||
#include "libavutil/frame.h"
|
||||
#include "libavutil/samplefmt.h"
|
||||
|
||||
#include "libswresample/version.h"
|
||||
|
||||
/**
|
||||
* @name Option constants
|
||||
* These constants are used for the @ref avoptions interface for lswr.
|
||||
* @{
|
||||
*
|
||||
*/
|
||||
|
||||
#define SWR_FLAG_RESAMPLE 1 ///< Force resampling even if equal sample rate
|
||||
//TODO use int resample ?
|
||||
//long term TODO can we enable this dynamically?
|
||||
|
||||
/** Dithering algorithms */
|
||||
enum SwrDitherType {
|
||||
SWR_DITHER_NONE = 0,
|
||||
SWR_DITHER_RECTANGULAR,
|
||||
SWR_DITHER_TRIANGULAR,
|
||||
SWR_DITHER_TRIANGULAR_HIGHPASS,
|
||||
|
||||
SWR_DITHER_NS = 64, ///< not part of API/ABI
|
||||
SWR_DITHER_NS_LIPSHITZ,
|
||||
SWR_DITHER_NS_F_WEIGHTED,
|
||||
SWR_DITHER_NS_MODIFIED_E_WEIGHTED,
|
||||
SWR_DITHER_NS_IMPROVED_E_WEIGHTED,
|
||||
SWR_DITHER_NS_SHIBATA,
|
||||
SWR_DITHER_NS_LOW_SHIBATA,
|
||||
SWR_DITHER_NS_HIGH_SHIBATA,
|
||||
SWR_DITHER_NB, ///< not part of API/ABI
|
||||
};
|
||||
|
||||
/** Resampling Engines */
|
||||
enum SwrEngine {
|
||||
SWR_ENGINE_SWR, /**< SW Resampler */
|
||||
SWR_ENGINE_SOXR, /**< SoX Resampler */
|
||||
SWR_ENGINE_NB, ///< not part of API/ABI
|
||||
};
|
||||
|
||||
/** Resampling Filter Types */
|
||||
enum SwrFilterType {
|
||||
SWR_FILTER_TYPE_CUBIC, /**< Cubic */
|
||||
SWR_FILTER_TYPE_BLACKMAN_NUTTALL, /**< Blackman Nuttall windowed sinc */
|
||||
SWR_FILTER_TYPE_KAISER, /**< Kaiser windowed sinc */
|
||||
};
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* The libswresample context. Unlike libavcodec and libavformat, this structure
|
||||
* is opaque. This means that if you would like to set options, you must use
|
||||
* the @ref avoptions API and cannot directly set values to members of the
|
||||
* structure.
|
||||
*/
|
||||
typedef struct SwrContext SwrContext;
|
||||
|
||||
/**
|
||||
* Get the AVClass for SwrContext. It can be used in combination with
|
||||
* AV_OPT_SEARCH_FAKE_OBJ for examining options.
|
||||
*
|
||||
* @see av_opt_find().
|
||||
* @return the AVClass of SwrContext
|
||||
*/
|
||||
const AVClass *swr_get_class(void);
|
||||
|
||||
/**
|
||||
* @name SwrContext constructor functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Allocate SwrContext.
|
||||
*
|
||||
* If you use this function you will need to set the parameters (manually or
|
||||
* with swr_alloc_set_opts()) before calling swr_init().
|
||||
*
|
||||
* @see swr_alloc_set_opts(), swr_init(), swr_free()
|
||||
* @return NULL on error, allocated context otherwise
|
||||
*/
|
||||
struct SwrContext *swr_alloc(void);
|
||||
|
||||
/**
|
||||
* Initialize context after user parameters have been set.
|
||||
* @note The context must be configured using the AVOption API.
|
||||
*
|
||||
* @see av_opt_set_int()
|
||||
* @see av_opt_set_dict()
|
||||
*
|
||||
* @param[in,out] s Swr context to initialize
|
||||
* @return AVERROR error code in case of failure.
|
||||
*/
|
||||
int swr_init(struct SwrContext *s);
|
||||
|
||||
/**
|
||||
* Check whether an swr context has been initialized or not.
|
||||
*
|
||||
* @param[in] s Swr context to check
|
||||
* @see swr_init()
|
||||
* @return positive if it has been initialized, 0 if not initialized
|
||||
*/
|
||||
int swr_is_initialized(struct SwrContext *s);
|
||||
|
||||
/**
|
||||
* Allocate SwrContext if needed and set/reset common parameters.
|
||||
*
|
||||
* This function does not require s to be allocated with swr_alloc(). On the
|
||||
* other hand, swr_alloc() can use swr_alloc_set_opts() to set the parameters
|
||||
* on the allocated context.
|
||||
*
|
||||
* @param s existing Swr context if available, or NULL if not
|
||||
* @param out_ch_layout output channel layout (AV_CH_LAYOUT_*)
|
||||
* @param out_sample_fmt output sample format (AV_SAMPLE_FMT_*).
|
||||
* @param out_sample_rate output sample rate (frequency in Hz)
|
||||
* @param in_ch_layout input channel layout (AV_CH_LAYOUT_*)
|
||||
* @param in_sample_fmt input sample format (AV_SAMPLE_FMT_*).
|
||||
* @param in_sample_rate input sample rate (frequency in Hz)
|
||||
* @param log_offset logging level offset
|
||||
* @param log_ctx parent logging context, can be NULL
|
||||
*
|
||||
* @see swr_init(), swr_free()
|
||||
* @return NULL on error, allocated context otherwise
|
||||
*/
|
||||
struct SwrContext *swr_alloc_set_opts(struct SwrContext *s,
|
||||
int64_t out_ch_layout, enum AVSampleFormat out_sample_fmt, int out_sample_rate,
|
||||
int64_t in_ch_layout, enum AVSampleFormat in_sample_fmt, int in_sample_rate,
|
||||
int log_offset, void *log_ctx);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
* @name SwrContext destructor functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Free the given SwrContext and set the pointer to NULL.
|
||||
*
|
||||
* @param[in] s a pointer to a pointer to Swr context
|
||||
*/
|
||||
void swr_free(struct SwrContext **s);
|
||||
|
||||
/**
|
||||
* Closes the context so that swr_is_initialized() returns 0.
|
||||
*
|
||||
* The context can be brought back to life by running swr_init(),
|
||||
* swr_init() can also be used without swr_close().
|
||||
* This function is mainly provided for simplifying the usecase
|
||||
* where one tries to support libavresample and libswresample.
|
||||
*
|
||||
* @param[in,out] s Swr context to be closed
|
||||
*/
|
||||
void swr_close(struct SwrContext *s);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
* @name Core conversion functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** Convert audio.
|
||||
*
|
||||
* in and in_count can be set to 0 to flush the last few samples out at the
|
||||
* end.
|
||||
*
|
||||
* If more input is provided than output space, then the input will be buffered.
|
||||
* You can avoid this buffering by using swr_get_out_samples() to retrieve an
|
||||
* upper bound on the required number of output samples for the given number of
|
||||
* input samples. Conversion will run directly without copying whenever possible.
|
||||
*
|
||||
* @param s allocated Swr context, with parameters set
|
||||
* @param out output buffers, only the first one need be set in case of packed audio
|
||||
* @param out_count amount of space available for output in samples per channel
|
||||
* @param in input buffers, only the first one need to be set in case of packed audio
|
||||
* @param in_count number of input samples available in one channel
|
||||
*
|
||||
* @return number of samples output per channel, negative value on error
|
||||
*/
|
||||
int swr_convert(struct SwrContext *s, uint8_t **out, int out_count,
|
||||
const uint8_t **in , int in_count);
|
||||
|
||||
/**
|
||||
* Convert the next timestamp from input to output
|
||||
* timestamps are in 1/(in_sample_rate * out_sample_rate) units.
|
||||
*
|
||||
* @note There are 2 slightly differently behaving modes.
|
||||
* @li When automatic timestamp compensation is not used, (min_compensation >= FLT_MAX)
|
||||
* in this case timestamps will be passed through with delays compensated
|
||||
* @li When automatic timestamp compensation is used, (min_compensation < FLT_MAX)
|
||||
* in this case the output timestamps will match output sample numbers.
|
||||
* See ffmpeg-resampler(1) for the two modes of compensation.
|
||||
*
|
||||
* @param s[in] initialized Swr context
|
||||
* @param pts[in] timestamp for the next input sample, INT64_MIN if unknown
|
||||
* @see swr_set_compensation(), swr_drop_output(), and swr_inject_silence() are
|
||||
* function used internally for timestamp compensation.
|
||||
* @return the output timestamp for the next output sample
|
||||
*/
|
||||
int64_t swr_next_pts(struct SwrContext *s, int64_t pts);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
* @name Low-level option setting functions
|
||||
* These functons provide a means to set low-level options that is not possible
|
||||
* with the AVOption API.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Activate resampling compensation ("soft" compensation). This function is
|
||||
* internally called when needed in swr_next_pts().
|
||||
*
|
||||
* @param[in,out] s allocated Swr context. If it is not initialized,
|
||||
* or SWR_FLAG_RESAMPLE is not set, swr_init() is
|
||||
* called with the flag set.
|
||||
* @param[in] sample_delta delta in PTS per sample
|
||||
* @param[in] compensation_distance number of samples to compensate for
|
||||
* @return >= 0 on success, AVERROR error codes if:
|
||||
* @li @c s is NULL,
|
||||
* @li @c compensation_distance is less than 0,
|
||||
* @li @c compensation_distance is 0 but sample_delta is not,
|
||||
* @li compensation unsupported by resampler, or
|
||||
* @li swr_init() fails when called.
|
||||
*/
|
||||
int swr_set_compensation(struct SwrContext *s, int sample_delta, int compensation_distance);
|
||||
|
||||
/**
|
||||
* Set a customized input channel mapping.
|
||||
*
|
||||
* @param[in,out] s allocated Swr context, not yet initialized
|
||||
* @param[in] channel_map customized input channel mapping (array of channel
|
||||
* indexes, -1 for a muted channel)
|
||||
* @return >= 0 on success, or AVERROR error code in case of failure.
|
||||
*/
|
||||
int swr_set_channel_mapping(struct SwrContext *s, const int *channel_map);
|
||||
|
||||
/**
|
||||
* Generate a channel mixing matrix.
|
||||
*
|
||||
* This function is the one used internally by libswresample for building the
|
||||
* default mixing matrix. It is made public just as a utility function for
|
||||
* building custom matrices.
|
||||
*
|
||||
* @param in_layout input channel layout
|
||||
* @param out_layout output channel layout
|
||||
* @param center_mix_level mix level for the center channel
|
||||
* @param surround_mix_level mix level for the surround channel(s)
|
||||
* @param lfe_mix_level mix level for the low-frequency effects channel
|
||||
* @param rematrix_maxval if 1.0, coefficients will be normalized to prevent
|
||||
* overflow. if INT_MAX, coefficients will not be
|
||||
* normalized.
|
||||
* @param[out] matrix mixing coefficients; matrix[i + stride * o] is
|
||||
* the weight of input channel i in output channel o.
|
||||
* @param stride distance between adjacent input channels in the
|
||||
* matrix array
|
||||
* @param matrix_encoding matrixed stereo downmix mode (e.g. dplii)
|
||||
* @param log_ctx parent logging context, can be NULL
|
||||
* @return 0 on success, negative AVERROR code on failure
|
||||
*/
|
||||
int swr_build_matrix(uint64_t in_layout, uint64_t out_layout,
|
||||
double center_mix_level, double surround_mix_level,
|
||||
double lfe_mix_level, double rematrix_maxval,
|
||||
double rematrix_volume, double *matrix,
|
||||
int stride, enum AVMatrixEncoding matrix_encoding,
|
||||
void *log_ctx);
|
||||
|
||||
/**
|
||||
* Set a customized remix matrix.
|
||||
*
|
||||
* @param s allocated Swr context, not yet initialized
|
||||
* @param matrix remix coefficients; matrix[i + stride * o] is
|
||||
* the weight of input channel i in output channel o
|
||||
* @param stride offset between lines of the matrix
|
||||
* @return >= 0 on success, or AVERROR error code in case of failure.
|
||||
*/
|
||||
int swr_set_matrix(struct SwrContext *s, const double *matrix, int stride);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
* @name Sample handling functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Drops the specified number of output samples.
|
||||
*
|
||||
* This function, along with swr_inject_silence(), is called by swr_next_pts()
|
||||
* if needed for "hard" compensation.
|
||||
*
|
||||
* @param s allocated Swr context
|
||||
* @param count number of samples to be dropped
|
||||
*
|
||||
* @return >= 0 on success, or a negative AVERROR code on failure
|
||||
*/
|
||||
int swr_drop_output(struct SwrContext *s, int count);
|
||||
|
||||
/**
|
||||
* Injects the specified number of silence samples.
|
||||
*
|
||||
* This function, along with swr_drop_output(), is called by swr_next_pts()
|
||||
* if needed for "hard" compensation.
|
||||
*
|
||||
* @param s allocated Swr context
|
||||
* @param count number of samples to be dropped
|
||||
*
|
||||
* @return >= 0 on success, or a negative AVERROR code on failure
|
||||
*/
|
||||
int swr_inject_silence(struct SwrContext *s, int count);
|
||||
|
||||
/**
|
||||
* Gets the delay the next input sample will experience relative to the next output sample.
|
||||
*
|
||||
* Swresample can buffer data if more input has been provided than available
|
||||
* output space, also converting between sample rates needs a delay.
|
||||
* This function returns the sum of all such delays.
|
||||
* The exact delay is not necessarily an integer value in either input or
|
||||
* output sample rate. Especially when downsampling by a large value, the
|
||||
* output sample rate may be a poor choice to represent the delay, similarly
|
||||
* for upsampling and the input sample rate.
|
||||
*
|
||||
* @param s swr context
|
||||
* @param base timebase in which the returned delay will be:
|
||||
* @li if it's set to 1 the returned delay is in seconds
|
||||
* @li if it's set to 1000 the returned delay is in milliseconds
|
||||
* @li if it's set to the input sample rate then the returned
|
||||
* delay is in input samples
|
||||
* @li if it's set to the output sample rate then the returned
|
||||
* delay is in output samples
|
||||
* @li if it's the least common multiple of in_sample_rate and
|
||||
* out_sample_rate then an exact rounding-free delay will be
|
||||
* returned
|
||||
* @returns the delay in 1 / @c base units.
|
||||
*/
|
||||
int64_t swr_get_delay(struct SwrContext *s, int64_t base);
|
||||
|
||||
/**
|
||||
* Find an upper bound on the number of samples that the next swr_convert
|
||||
* call will output, if called with in_samples of input samples. This
|
||||
* depends on the internal state, and anything changing the internal state
|
||||
* (like further swr_convert() calls) will may change the number of samples
|
||||
* swr_get_out_samples() returns for the same number of input samples.
|
||||
*
|
||||
* @param in_samples number of input samples.
|
||||
* @note any call to swr_inject_silence(), swr_convert(), swr_next_pts()
|
||||
* or swr_set_compensation() invalidates this limit
|
||||
* @note it is recommended to pass the correct available buffer size
|
||||
* to all functions like swr_convert() even if swr_get_out_samples()
|
||||
* indicates that less would be used.
|
||||
* @returns an upper bound on the number of samples that the next swr_convert
|
||||
* will output or a negative value to indicate an error
|
||||
*/
|
||||
int swr_get_out_samples(struct SwrContext *s, int in_samples);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
* @name Configuration accessors
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Return the @ref LIBSWRESAMPLE_VERSION_INT constant.
|
||||
*
|
||||
* This is useful to check if the build-time libswresample has the same version
|
||||
* as the run-time one.
|
||||
*
|
||||
* @returns the unsigned int-typed version
|
||||
*/
|
||||
unsigned swresample_version(void);
|
||||
|
||||
/**
|
||||
* Return the swr build-time configuration.
|
||||
*
|
||||
* @returns the build-time @c ./configure flags
|
||||
*/
|
||||
const char *swresample_configuration(void);
|
||||
|
||||
/**
|
||||
* Return the swr license.
|
||||
*
|
||||
* @returns the license of libswresample, determined at build-time
|
||||
*/
|
||||
const char *swresample_license(void);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
* @name AVFrame based API
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Convert the samples in the input AVFrame and write them to the output AVFrame.
|
||||
*
|
||||
* Input and output AVFrames must have channel_layout, sample_rate and format set.
|
||||
*
|
||||
* If the output AVFrame does not have the data pointers allocated the nb_samples
|
||||
* field will be set using av_frame_get_buffer()
|
||||
* is called to allocate the frame.
|
||||
*
|
||||
* The output AVFrame can be NULL or have fewer allocated samples than required.
|
||||
* In this case, any remaining samples not written to the output will be added
|
||||
* to an internal FIFO buffer, to be returned at the next call to this function
|
||||
* or to swr_convert().
|
||||
*
|
||||
* If converting sample rate, there may be data remaining in the internal
|
||||
* resampling delay buffer. swr_get_delay() tells the number of
|
||||
* remaining samples. To get this data as output, call this function or
|
||||
* swr_convert() with NULL input.
|
||||
*
|
||||
* If the SwrContext configuration does not match the output and
|
||||
* input AVFrame settings the conversion does not take place and depending on
|
||||
* which AVFrame is not matching AVERROR_OUTPUT_CHANGED, AVERROR_INPUT_CHANGED
|
||||
* or the result of a bitwise-OR of them is returned.
|
||||
*
|
||||
* @see swr_delay()
|
||||
* @see swr_convert()
|
||||
* @see swr_get_delay()
|
||||
*
|
||||
* @param swr audio resample context
|
||||
* @param output output AVFrame
|
||||
* @param input input AVFrame
|
||||
* @return 0 on success, AVERROR on failure or nonmatching
|
||||
* configuration.
|
||||
*/
|
||||
int swr_convert_frame(SwrContext *swr,
|
||||
AVFrame *output, const AVFrame *input);
|
||||
|
||||
/**
|
||||
* Configure or reconfigure the SwrContext using the information
|
||||
* provided by the AVFrames.
|
||||
*
|
||||
* The original resampling context is reset even on failure.
|
||||
* The function calls swr_close() internally if the context is open.
|
||||
*
|
||||
* @see swr_close();
|
||||
*
|
||||
* @param swr audio resample context
|
||||
* @param output output AVFrame
|
||||
* @param input input AVFrame
|
||||
* @return 0 on success, AVERROR on failure.
|
||||
*/
|
||||
int swr_config_frame(SwrContext *swr, const AVFrame *out, const AVFrame *in);
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* SWRESAMPLE_SWRESAMPLE_H */
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Version macros.
|
||||
*
|
||||
* This file is part of libswresample
|
||||
*
|
||||
* libswresample is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* libswresample is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with libswresample; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef SWRESAMPLE_VERSION_H
|
||||
#define SWRESAMPLE_VERSION_H
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Libswresample version macros
|
||||
*/
|
||||
|
||||
#include "libavutil/avutil.h"
|
||||
|
||||
#define LIBSWRESAMPLE_VERSION_MAJOR 3
|
||||
#define LIBSWRESAMPLE_VERSION_MINOR 2
|
||||
#define LIBSWRESAMPLE_VERSION_MICRO 100
|
||||
|
||||
#define LIBSWRESAMPLE_VERSION_INT AV_VERSION_INT(LIBSWRESAMPLE_VERSION_MAJOR, \
|
||||
LIBSWRESAMPLE_VERSION_MINOR, \
|
||||
LIBSWRESAMPLE_VERSION_MICRO)
|
||||
#define LIBSWRESAMPLE_VERSION AV_VERSION(LIBSWRESAMPLE_VERSION_MAJOR, \
|
||||
LIBSWRESAMPLE_VERSION_MINOR, \
|
||||
LIBSWRESAMPLE_VERSION_MICRO)
|
||||
#define LIBSWRESAMPLE_BUILD LIBSWRESAMPLE_VERSION_INT
|
||||
|
||||
#define LIBSWRESAMPLE_IDENT "SwR" AV_STRINGIFY(LIBSWRESAMPLE_VERSION)
|
||||
|
||||
#endif /* SWRESAMPLE_VERSION_H */
|
||||
@@ -0,0 +1,336 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2011 Michael Niedermayer <[email protected]>
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef SWSCALE_SWSCALE_H
|
||||
#define SWSCALE_SWSCALE_H
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @ingroup libsws
|
||||
* external API header
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "libavutil/avutil.h"
|
||||
#include "libavutil/log.h"
|
||||
#include "libavutil/pixfmt.h"
|
||||
#include "version.h"
|
||||
|
||||
/**
|
||||
* @defgroup libsws libswscale
|
||||
* Color conversion and scaling library.
|
||||
*
|
||||
* @{
|
||||
*
|
||||
* Return the LIBSWSCALE_VERSION_INT constant.
|
||||
*/
|
||||
unsigned swscale_version(void);
|
||||
|
||||
/**
|
||||
* Return the libswscale build-time configuration.
|
||||
*/
|
||||
const char *swscale_configuration(void);
|
||||
|
||||
/**
|
||||
* Return the libswscale license.
|
||||
*/
|
||||
const char *swscale_license(void);
|
||||
|
||||
/* values for the flags, the stuff on the command line is different */
|
||||
#define SWS_FAST_BILINEAR 1
|
||||
#define SWS_BILINEAR 2
|
||||
#define SWS_BICUBIC 4
|
||||
#define SWS_X 8
|
||||
#define SWS_POINT 0x10
|
||||
#define SWS_AREA 0x20
|
||||
#define SWS_BICUBLIN 0x40
|
||||
#define SWS_GAUSS 0x80
|
||||
#define SWS_SINC 0x100
|
||||
#define SWS_LANCZOS 0x200
|
||||
#define SWS_SPLINE 0x400
|
||||
|
||||
#define SWS_SRC_V_CHR_DROP_MASK 0x30000
|
||||
#define SWS_SRC_V_CHR_DROP_SHIFT 16
|
||||
|
||||
#define SWS_PARAM_DEFAULT 123456
|
||||
|
||||
#define SWS_PRINT_INFO 0x1000
|
||||
|
||||
//the following 3 flags are not completely implemented
|
||||
//internal chrominance subsampling info
|
||||
#define SWS_FULL_CHR_H_INT 0x2000
|
||||
//input subsampling info
|
||||
#define SWS_FULL_CHR_H_INP 0x4000
|
||||
#define SWS_DIRECT_BGR 0x8000
|
||||
#define SWS_ACCURATE_RND 0x40000
|
||||
#define SWS_BITEXACT 0x80000
|
||||
#define SWS_ERROR_DIFFUSION 0x800000
|
||||
|
||||
#define SWS_MAX_REDUCE_CUTOFF 0.002
|
||||
|
||||
#define SWS_CS_ITU709 1
|
||||
#define SWS_CS_FCC 4
|
||||
#define SWS_CS_ITU601 5
|
||||
#define SWS_CS_ITU624 5
|
||||
#define SWS_CS_SMPTE170M 5
|
||||
#define SWS_CS_SMPTE240M 7
|
||||
#define SWS_CS_DEFAULT 5
|
||||
#define SWS_CS_BT2020 9
|
||||
|
||||
/**
|
||||
* Return a pointer to yuv<->rgb coefficients for the given colorspace
|
||||
* suitable for sws_setColorspaceDetails().
|
||||
*
|
||||
* @param colorspace One of the SWS_CS_* macros. If invalid,
|
||||
* SWS_CS_DEFAULT is used.
|
||||
*/
|
||||
const int *sws_getCoefficients(int colorspace);
|
||||
|
||||
// when used for filters they must have an odd number of elements
|
||||
// coeffs cannot be shared between vectors
|
||||
typedef struct SwsVector {
|
||||
double *coeff; ///< pointer to the list of coefficients
|
||||
int length; ///< number of coefficients in the vector
|
||||
} SwsVector;
|
||||
|
||||
// vectors can be shared
|
||||
typedef struct SwsFilter {
|
||||
SwsVector *lumH;
|
||||
SwsVector *lumV;
|
||||
SwsVector *chrH;
|
||||
SwsVector *chrV;
|
||||
} SwsFilter;
|
||||
|
||||
struct SwsContext;
|
||||
|
||||
/**
|
||||
* Return a positive value if pix_fmt is a supported input format, 0
|
||||
* otherwise.
|
||||
*/
|
||||
int sws_isSupportedInput(enum AVPixelFormat pix_fmt);
|
||||
|
||||
/**
|
||||
* Return a positive value if pix_fmt is a supported output format, 0
|
||||
* otherwise.
|
||||
*/
|
||||
int sws_isSupportedOutput(enum AVPixelFormat pix_fmt);
|
||||
|
||||
/**
|
||||
* @param[in] pix_fmt the pixel format
|
||||
* @return a positive value if an endianness conversion for pix_fmt is
|
||||
* supported, 0 otherwise.
|
||||
*/
|
||||
int sws_isSupportedEndiannessConversion(enum AVPixelFormat pix_fmt);
|
||||
|
||||
/**
|
||||
* Allocate an empty SwsContext. This must be filled and passed to
|
||||
* sws_init_context(). For filling see AVOptions, options.c and
|
||||
* sws_setColorspaceDetails().
|
||||
*/
|
||||
struct SwsContext *sws_alloc_context(void);
|
||||
|
||||
/**
|
||||
* Initialize the swscaler context sws_context.
|
||||
*
|
||||
* @return zero or positive value on success, a negative value on
|
||||
* error
|
||||
*/
|
||||
av_warn_unused_result
|
||||
int sws_init_context(struct SwsContext *sws_context, SwsFilter *srcFilter, SwsFilter *dstFilter);
|
||||
|
||||
/**
|
||||
* Free the swscaler context swsContext.
|
||||
* If swsContext is NULL, then does nothing.
|
||||
*/
|
||||
void sws_freeContext(struct SwsContext *swsContext);
|
||||
|
||||
/**
|
||||
* Allocate and return an SwsContext. You need it to perform
|
||||
* scaling/conversion operations using sws_scale().
|
||||
*
|
||||
* @param srcW the width of the source image
|
||||
* @param srcH the height of the source image
|
||||
* @param srcFormat the source image format
|
||||
* @param dstW the width of the destination image
|
||||
* @param dstH the height of the destination image
|
||||
* @param dstFormat the destination image format
|
||||
* @param flags specify which algorithm and options to use for rescaling
|
||||
* @param param extra parameters to tune the used scaler
|
||||
* For SWS_BICUBIC param[0] and [1] tune the shape of the basis
|
||||
* function, param[0] tunes f(1) and param[1] f´(1)
|
||||
* For SWS_GAUSS param[0] tunes the exponent and thus cutoff
|
||||
* frequency
|
||||
* For SWS_LANCZOS param[0] tunes the width of the window function
|
||||
* @return a pointer to an allocated context, or NULL in case of error
|
||||
* @note this function is to be removed after a saner alternative is
|
||||
* written
|
||||
*/
|
||||
struct SwsContext *sws_getContext(int srcW, int srcH, enum AVPixelFormat srcFormat,
|
||||
int dstW, int dstH, enum AVPixelFormat dstFormat,
|
||||
int flags, SwsFilter *srcFilter,
|
||||
SwsFilter *dstFilter, const double *param);
|
||||
|
||||
/**
|
||||
* Scale the image slice in srcSlice and put the resulting scaled
|
||||
* slice in the image in dst. A slice is a sequence of consecutive
|
||||
* rows in an image.
|
||||
*
|
||||
* Slices have to be provided in sequential order, either in
|
||||
* top-bottom or bottom-top order. If slices are provided in
|
||||
* non-sequential order the behavior of the function is undefined.
|
||||
*
|
||||
* @param c the scaling context previously created with
|
||||
* sws_getContext()
|
||||
* @param srcSlice the array containing the pointers to the planes of
|
||||
* the source slice
|
||||
* @param srcStride the array containing the strides for each plane of
|
||||
* the source image
|
||||
* @param srcSliceY the position in the source image of the slice to
|
||||
* process, that is the number (counted starting from
|
||||
* zero) in the image of the first row of the slice
|
||||
* @param srcSliceH the height of the source slice, that is the number
|
||||
* of rows in the slice
|
||||
* @param dst the array containing the pointers to the planes of
|
||||
* the destination image
|
||||
* @param dstStride the array containing the strides for each plane of
|
||||
* the destination image
|
||||
* @return the height of the output slice
|
||||
*/
|
||||
int sws_scale(struct SwsContext *c, const uint8_t *const srcSlice[],
|
||||
const int srcStride[], int srcSliceY, int srcSliceH,
|
||||
uint8_t *const dst[], const int dstStride[]);
|
||||
|
||||
/**
|
||||
* @param dstRange flag indicating the while-black range of the output (1=jpeg / 0=mpeg)
|
||||
* @param srcRange flag indicating the while-black range of the input (1=jpeg / 0=mpeg)
|
||||
* @param table the yuv2rgb coefficients describing the output yuv space, normally ff_yuv2rgb_coeffs[x]
|
||||
* @param inv_table the yuv2rgb coefficients describing the input yuv space, normally ff_yuv2rgb_coeffs[x]
|
||||
* @param brightness 16.16 fixed point brightness correction
|
||||
* @param contrast 16.16 fixed point contrast correction
|
||||
* @param saturation 16.16 fixed point saturation correction
|
||||
* @return -1 if not supported
|
||||
*/
|
||||
int sws_setColorspaceDetails(struct SwsContext *c, const int inv_table[4],
|
||||
int srcRange, const int table[4], int dstRange,
|
||||
int brightness, int contrast, int saturation);
|
||||
|
||||
/**
|
||||
* @return -1 if not supported
|
||||
*/
|
||||
int sws_getColorspaceDetails(struct SwsContext *c, int **inv_table,
|
||||
int *srcRange, int **table, int *dstRange,
|
||||
int *brightness, int *contrast, int *saturation);
|
||||
|
||||
/**
|
||||
* Allocate and return an uninitialized vector with length coefficients.
|
||||
*/
|
||||
SwsVector *sws_allocVec(int length);
|
||||
|
||||
/**
|
||||
* Return a normalized Gaussian curve used to filter stuff
|
||||
* quality = 3 is high quality, lower is lower quality.
|
||||
*/
|
||||
SwsVector *sws_getGaussianVec(double variance, double quality);
|
||||
|
||||
/**
|
||||
* Scale all the coefficients of a by the scalar value.
|
||||
*/
|
||||
void sws_scaleVec(SwsVector *a, double scalar);
|
||||
|
||||
/**
|
||||
* Scale all the coefficients of a so that their sum equals height.
|
||||
*/
|
||||
void sws_normalizeVec(SwsVector *a, double height);
|
||||
|
||||
#if FF_API_SWS_VECTOR
|
||||
attribute_deprecated SwsVector *sws_getConstVec(double c, int length);
|
||||
attribute_deprecated SwsVector *sws_getIdentityVec(void);
|
||||
attribute_deprecated void sws_convVec(SwsVector *a, SwsVector *b);
|
||||
attribute_deprecated void sws_addVec(SwsVector *a, SwsVector *b);
|
||||
attribute_deprecated void sws_subVec(SwsVector *a, SwsVector *b);
|
||||
attribute_deprecated void sws_shiftVec(SwsVector *a, int shift);
|
||||
attribute_deprecated SwsVector *sws_cloneVec(SwsVector *a);
|
||||
attribute_deprecated void sws_printVec2(SwsVector *a, AVClass *log_ctx, int log_level);
|
||||
#endif
|
||||
|
||||
void sws_freeVec(SwsVector *a);
|
||||
|
||||
SwsFilter *sws_getDefaultFilter(float lumaGBlur, float chromaGBlur,
|
||||
float lumaSharpen, float chromaSharpen,
|
||||
float chromaHShift, float chromaVShift,
|
||||
int verbose);
|
||||
void sws_freeFilter(SwsFilter *filter);
|
||||
|
||||
/**
|
||||
* Check if context can be reused, otherwise reallocate a new one.
|
||||
*
|
||||
* If context is NULL, just calls sws_getContext() to get a new
|
||||
* context. Otherwise, checks if the parameters are the ones already
|
||||
* saved in context. If that is the case, returns the current
|
||||
* context. Otherwise, frees context and gets a new context with
|
||||
* the new parameters.
|
||||
*
|
||||
* Be warned that srcFilter and dstFilter are not checked, they
|
||||
* are assumed to remain the same.
|
||||
*/
|
||||
struct SwsContext *sws_getCachedContext(struct SwsContext *context,
|
||||
int srcW, int srcH, enum AVPixelFormat srcFormat,
|
||||
int dstW, int dstH, enum AVPixelFormat dstFormat,
|
||||
int flags, SwsFilter *srcFilter,
|
||||
SwsFilter *dstFilter, const double *param);
|
||||
|
||||
/**
|
||||
* Convert an 8-bit paletted frame into a frame with a color depth of 32 bits.
|
||||
*
|
||||
* The output frame will have the same packed format as the palette.
|
||||
*
|
||||
* @param src source frame buffer
|
||||
* @param dst destination frame buffer
|
||||
* @param num_pixels number of pixels to convert
|
||||
* @param palette array with [256] entries, which must match color arrangement (RGB or BGR) of src
|
||||
*/
|
||||
void sws_convertPalette8ToPacked32(const uint8_t *src, uint8_t *dst, int num_pixels, const uint8_t *palette);
|
||||
|
||||
/**
|
||||
* Convert an 8-bit paletted frame into a frame with a color depth of 24 bits.
|
||||
*
|
||||
* With the palette format "ABCD", the destination frame ends up with the format "ABC".
|
||||
*
|
||||
* @param src source frame buffer
|
||||
* @param dst destination frame buffer
|
||||
* @param num_pixels number of pixels to convert
|
||||
* @param palette array with [256] entries, which must match color arrangement (RGB or BGR) of src
|
||||
*/
|
||||
void sws_convertPalette8ToPacked24(const uint8_t *src, uint8_t *dst, int num_pixels, const uint8_t *palette);
|
||||
|
||||
/**
|
||||
* Get the AVClass for swsContext. It can be used in combination with
|
||||
* AV_OPT_SEARCH_FAKE_OBJ for examining options.
|
||||
*
|
||||
* @see av_opt_find().
|
||||
*/
|
||||
const AVClass *sws_get_class(void);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* SWSCALE_SWSCALE_H */
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef SWSCALE_VERSION_H
|
||||
#define SWSCALE_VERSION_H
|
||||
|
||||
/**
|
||||
* @file
|
||||
* swscale version macros
|
||||
*/
|
||||
|
||||
#include "libavutil/version.h"
|
||||
|
||||
#define LIBSWSCALE_VERSION_MAJOR 5
|
||||
#define LIBSWSCALE_VERSION_MINOR 2
|
||||
#define LIBSWSCALE_VERSION_MICRO 100
|
||||
|
||||
#define LIBSWSCALE_VERSION_INT AV_VERSION_INT(LIBSWSCALE_VERSION_MAJOR, \
|
||||
LIBSWSCALE_VERSION_MINOR, \
|
||||
LIBSWSCALE_VERSION_MICRO)
|
||||
#define LIBSWSCALE_VERSION AV_VERSION(LIBSWSCALE_VERSION_MAJOR, \
|
||||
LIBSWSCALE_VERSION_MINOR, \
|
||||
LIBSWSCALE_VERSION_MICRO)
|
||||
#define LIBSWSCALE_BUILD LIBSWSCALE_VERSION_INT
|
||||
|
||||
#define LIBSWSCALE_IDENT "SwS" AV_STRINGIFY(LIBSWSCALE_VERSION)
|
||||
|
||||
/**
|
||||
* FF_API_* defines may be placed below to indicate public API that will be
|
||||
* dropped at a future version bump. The defines themselves are not part of
|
||||
* the public API and may change, break or disappear at any time.
|
||||
*/
|
||||
|
||||
#ifndef FF_API_SWS_VECTOR
|
||||
#define FF_API_SWS_VECTOR (LIBSWSCALE_VERSION_MAJOR < 6)
|
||||
#endif
|
||||
|
||||
#endif /* SWSCALE_VERSION_H */
|
||||
@@ -1,981 +0,0 @@
|
||||
/* 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(4);
|
||||
|
||||
/** 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 */
|
||||
@@ -1,342 +0,0 @@
|
||||
/* 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 */
|
||||
@@ -1,785 +0,0 @@
|
||||
/* 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
|
||||
|
||||
/* 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)
|
||||
|
||||
/**@}*/
|
||||
|
||||
/** @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 */
|
||||
@@ -1,660 +0,0 @@
|
||||
/* 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 */
|
||||
@@ -1,159 +0,0 @@
|
||||
/* (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
|
||||
|
||||
/* 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>
|
||||
|
||||
typedef int16_t opus_int16;
|
||||
typedef uint16_t opus_uint16;
|
||||
typedef int32_t opus_int32;
|
||||
typedef uint32_t opus_uint32;
|
||||
#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
|
||||
|
||||
#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
|
||||
|
||||
#endif /* OPUS_TYPES_H */
|
||||
@@ -0,0 +1,514 @@
|
||||
/*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef AVDEVICE_AVDEVICE_H
|
||||
#define AVDEVICE_AVDEVICE_H
|
||||
|
||||
#include "version.h"
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @ingroup lavd
|
||||
* Main libavdevice API header
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup lavd libavdevice
|
||||
* Special devices muxing/demuxing library.
|
||||
*
|
||||
* Libavdevice is a complementary library to @ref libavf "libavformat". It
|
||||
* provides various "special" platform-specific muxers and demuxers, e.g. for
|
||||
* grabbing devices, audio capture and playback etc. As a consequence, the
|
||||
* (de)muxers in libavdevice are of the AVFMT_NOFILE type (they use their own
|
||||
* I/O functions). The filename passed to avformat_open_input() often does not
|
||||
* refer to an actually existing file, but has some special device-specific
|
||||
* meaning - e.g. for xcbgrab it is the display name.
|
||||
*
|
||||
* To use libavdevice, simply call avdevice_register_all() to register all
|
||||
* compiled muxers and demuxers. They all use standard libavformat API.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "libavutil/log.h"
|
||||
#include "libavutil/opt.h"
|
||||
#include "libavutil/dict.h"
|
||||
#include "libavformat/avformat.h"
|
||||
|
||||
/**
|
||||
* Return the LIBAVDEVICE_VERSION_INT constant.
|
||||
*/
|
||||
unsigned avdevice_version(void);
|
||||
|
||||
/**
|
||||
* Return the libavdevice build-time configuration.
|
||||
*/
|
||||
const char *avdevice_configuration(void);
|
||||
|
||||
/**
|
||||
* Return the libavdevice license.
|
||||
*/
|
||||
const char *avdevice_license(void);
|
||||
|
||||
/**
|
||||
* Initialize libavdevice and register all the input and output devices.
|
||||
*/
|
||||
void avdevice_register_all(void);
|
||||
|
||||
/**
|
||||
* Audio input devices iterator.
|
||||
*
|
||||
* If d is NULL, returns the first registered input audio/video device,
|
||||
* if d is non-NULL, returns the next registered input audio/video device after d
|
||||
* or NULL if d is the last one.
|
||||
*/
|
||||
AVInputFormat *av_input_audio_device_next(AVInputFormat *d);
|
||||
|
||||
/**
|
||||
* Video input devices iterator.
|
||||
*
|
||||
* If d is NULL, returns the first registered input audio/video device,
|
||||
* if d is non-NULL, returns the next registered input audio/video device after d
|
||||
* or NULL if d is the last one.
|
||||
*/
|
||||
AVInputFormat *av_input_video_device_next(AVInputFormat *d);
|
||||
|
||||
/**
|
||||
* Audio output devices iterator.
|
||||
*
|
||||
* If d is NULL, returns the first registered output audio/video device,
|
||||
* if d is non-NULL, returns the next registered output audio/video device after d
|
||||
* or NULL if d is the last one.
|
||||
*/
|
||||
AVOutputFormat *av_output_audio_device_next(AVOutputFormat *d);
|
||||
|
||||
/**
|
||||
* Video output devices iterator.
|
||||
*
|
||||
* If d is NULL, returns the first registered output audio/video device,
|
||||
* if d is non-NULL, returns the next registered output audio/video device after d
|
||||
* or NULL if d is the last one.
|
||||
*/
|
||||
AVOutputFormat *av_output_video_device_next(AVOutputFormat *d);
|
||||
|
||||
typedef struct AVDeviceRect {
|
||||
int x; /**< x coordinate of top left corner */
|
||||
int y; /**< y coordinate of top left corner */
|
||||
int width; /**< width */
|
||||
int height; /**< height */
|
||||
} AVDeviceRect;
|
||||
|
||||
/**
|
||||
* Message types used by avdevice_app_to_dev_control_message().
|
||||
*/
|
||||
enum AVAppToDevMessageType {
|
||||
/**
|
||||
* Dummy message.
|
||||
*/
|
||||
AV_APP_TO_DEV_NONE = MKBETAG('N','O','N','E'),
|
||||
|
||||
/**
|
||||
* Window size change message.
|
||||
*
|
||||
* Message is sent to the device every time the application changes the size
|
||||
* of the window device renders to.
|
||||
* Message should also be sent right after window is created.
|
||||
*
|
||||
* data: AVDeviceRect: new window size.
|
||||
*/
|
||||
AV_APP_TO_DEV_WINDOW_SIZE = MKBETAG('G','E','O','M'),
|
||||
|
||||
/**
|
||||
* Repaint request message.
|
||||
*
|
||||
* Message is sent to the device when window has to be repainted.
|
||||
*
|
||||
* data: AVDeviceRect: area required to be repainted.
|
||||
* NULL: whole area is required to be repainted.
|
||||
*/
|
||||
AV_APP_TO_DEV_WINDOW_REPAINT = MKBETAG('R','E','P','A'),
|
||||
|
||||
/**
|
||||
* Request pause/play.
|
||||
*
|
||||
* Application requests pause/unpause playback.
|
||||
* Mostly usable with devices that have internal buffer.
|
||||
* By default devices are not paused.
|
||||
*
|
||||
* data: NULL
|
||||
*/
|
||||
AV_APP_TO_DEV_PAUSE = MKBETAG('P', 'A', 'U', ' '),
|
||||
AV_APP_TO_DEV_PLAY = MKBETAG('P', 'L', 'A', 'Y'),
|
||||
AV_APP_TO_DEV_TOGGLE_PAUSE = MKBETAG('P', 'A', 'U', 'T'),
|
||||
|
||||
/**
|
||||
* Volume control message.
|
||||
*
|
||||
* Set volume level. It may be device-dependent if volume
|
||||
* is changed per stream or system wide. Per stream volume
|
||||
* change is expected when possible.
|
||||
*
|
||||
* data: double: new volume with range of 0.0 - 1.0.
|
||||
*/
|
||||
AV_APP_TO_DEV_SET_VOLUME = MKBETAG('S', 'V', 'O', 'L'),
|
||||
|
||||
/**
|
||||
* Mute control messages.
|
||||
*
|
||||
* Change mute state. It may be device-dependent if mute status
|
||||
* is changed per stream or system wide. Per stream mute status
|
||||
* change is expected when possible.
|
||||
*
|
||||
* data: NULL.
|
||||
*/
|
||||
AV_APP_TO_DEV_MUTE = MKBETAG(' ', 'M', 'U', 'T'),
|
||||
AV_APP_TO_DEV_UNMUTE = MKBETAG('U', 'M', 'U', 'T'),
|
||||
AV_APP_TO_DEV_TOGGLE_MUTE = MKBETAG('T', 'M', 'U', 'T'),
|
||||
|
||||
/**
|
||||
* Get volume/mute messages.
|
||||
*
|
||||
* Force the device to send AV_DEV_TO_APP_VOLUME_LEVEL_CHANGED or
|
||||
* AV_DEV_TO_APP_MUTE_STATE_CHANGED command respectively.
|
||||
*
|
||||
* data: NULL.
|
||||
*/
|
||||
AV_APP_TO_DEV_GET_VOLUME = MKBETAG('G', 'V', 'O', 'L'),
|
||||
AV_APP_TO_DEV_GET_MUTE = MKBETAG('G', 'M', 'U', 'T'),
|
||||
};
|
||||
|
||||
/**
|
||||
* Message types used by avdevice_dev_to_app_control_message().
|
||||
*/
|
||||
enum AVDevToAppMessageType {
|
||||
/**
|
||||
* Dummy message.
|
||||
*/
|
||||
AV_DEV_TO_APP_NONE = MKBETAG('N','O','N','E'),
|
||||
|
||||
/**
|
||||
* Create window buffer message.
|
||||
*
|
||||
* Device requests to create a window buffer. Exact meaning is device-
|
||||
* and application-dependent. Message is sent before rendering first
|
||||
* frame and all one-shot initializations should be done here.
|
||||
* Application is allowed to ignore preferred window buffer size.
|
||||
*
|
||||
* @note: Application is obligated to inform about window buffer size
|
||||
* with AV_APP_TO_DEV_WINDOW_SIZE message.
|
||||
*
|
||||
* data: AVDeviceRect: preferred size of the window buffer.
|
||||
* NULL: no preferred size of the window buffer.
|
||||
*/
|
||||
AV_DEV_TO_APP_CREATE_WINDOW_BUFFER = MKBETAG('B','C','R','E'),
|
||||
|
||||
/**
|
||||
* Prepare window buffer message.
|
||||
*
|
||||
* Device requests to prepare a window buffer for rendering.
|
||||
* Exact meaning is device- and application-dependent.
|
||||
* Message is sent before rendering of each frame.
|
||||
*
|
||||
* data: NULL.
|
||||
*/
|
||||
AV_DEV_TO_APP_PREPARE_WINDOW_BUFFER = MKBETAG('B','P','R','E'),
|
||||
|
||||
/**
|
||||
* Display window buffer message.
|
||||
*
|
||||
* Device requests to display a window buffer.
|
||||
* Message is sent when new frame is ready to be displayed.
|
||||
* Usually buffers need to be swapped in handler of this message.
|
||||
*
|
||||
* data: NULL.
|
||||
*/
|
||||
AV_DEV_TO_APP_DISPLAY_WINDOW_BUFFER = MKBETAG('B','D','I','S'),
|
||||
|
||||
/**
|
||||
* Destroy window buffer message.
|
||||
*
|
||||
* Device requests to destroy a window buffer.
|
||||
* Message is sent when device is about to be destroyed and window
|
||||
* buffer is not required anymore.
|
||||
*
|
||||
* data: NULL.
|
||||
*/
|
||||
AV_DEV_TO_APP_DESTROY_WINDOW_BUFFER = MKBETAG('B','D','E','S'),
|
||||
|
||||
/**
|
||||
* Buffer fullness status messages.
|
||||
*
|
||||
* Device signals buffer overflow/underflow.
|
||||
*
|
||||
* data: NULL.
|
||||
*/
|
||||
AV_DEV_TO_APP_BUFFER_OVERFLOW = MKBETAG('B','O','F','L'),
|
||||
AV_DEV_TO_APP_BUFFER_UNDERFLOW = MKBETAG('B','U','F','L'),
|
||||
|
||||
/**
|
||||
* Buffer readable/writable.
|
||||
*
|
||||
* Device informs that buffer is readable/writable.
|
||||
* When possible, device informs how many bytes can be read/write.
|
||||
*
|
||||
* @warning Device may not inform when number of bytes than can be read/write changes.
|
||||
*
|
||||
* data: int64_t: amount of bytes available to read/write.
|
||||
* NULL: amount of bytes available to read/write is not known.
|
||||
*/
|
||||
AV_DEV_TO_APP_BUFFER_READABLE = MKBETAG('B','R','D',' '),
|
||||
AV_DEV_TO_APP_BUFFER_WRITABLE = MKBETAG('B','W','R',' '),
|
||||
|
||||
/**
|
||||
* Mute state change message.
|
||||
*
|
||||
* Device informs that mute state has changed.
|
||||
*
|
||||
* data: int: 0 for not muted state, non-zero for muted state.
|
||||
*/
|
||||
AV_DEV_TO_APP_MUTE_STATE_CHANGED = MKBETAG('C','M','U','T'),
|
||||
|
||||
/**
|
||||
* Volume level change message.
|
||||
*
|
||||
* Device informs that volume level has changed.
|
||||
*
|
||||
* data: double: new volume with range of 0.0 - 1.0.
|
||||
*/
|
||||
AV_DEV_TO_APP_VOLUME_LEVEL_CHANGED = MKBETAG('C','V','O','L'),
|
||||
};
|
||||
|
||||
/**
|
||||
* Send control message from application to device.
|
||||
*
|
||||
* @param s device context.
|
||||
* @param type message type.
|
||||
* @param data message data. Exact type depends on message type.
|
||||
* @param data_size size of message data.
|
||||
* @return >= 0 on success, negative on error.
|
||||
* AVERROR(ENOSYS) when device doesn't implement handler of the message.
|
||||
*/
|
||||
int avdevice_app_to_dev_control_message(struct AVFormatContext *s,
|
||||
enum AVAppToDevMessageType type,
|
||||
void *data, size_t data_size);
|
||||
|
||||
/**
|
||||
* Send control message from device to application.
|
||||
*
|
||||
* @param s device context.
|
||||
* @param type message type.
|
||||
* @param data message data. Can be NULL.
|
||||
* @param data_size size of message data.
|
||||
* @return >= 0 on success, negative on error.
|
||||
* AVERROR(ENOSYS) when application doesn't implement handler of the message.
|
||||
*/
|
||||
int avdevice_dev_to_app_control_message(struct AVFormatContext *s,
|
||||
enum AVDevToAppMessageType type,
|
||||
void *data, size_t data_size);
|
||||
|
||||
/**
|
||||
* Following API allows user to probe device capabilities (supported codecs,
|
||||
* pixel formats, sample formats, resolutions, channel counts, etc).
|
||||
* It is build on top op AVOption API.
|
||||
* Queried capabilities make it possible to set up converters of video or audio
|
||||
* parameters that fit to the device.
|
||||
*
|
||||
* List of capabilities that can be queried:
|
||||
* - Capabilities valid for both audio and video devices:
|
||||
* - codec: supported audio/video codecs.
|
||||
* type: AV_OPT_TYPE_INT (AVCodecID value)
|
||||
* - Capabilities valid for audio devices:
|
||||
* - sample_format: supported sample formats.
|
||||
* type: AV_OPT_TYPE_INT (AVSampleFormat value)
|
||||
* - sample_rate: supported sample rates.
|
||||
* type: AV_OPT_TYPE_INT
|
||||
* - channels: supported number of channels.
|
||||
* type: AV_OPT_TYPE_INT
|
||||
* - channel_layout: supported channel layouts.
|
||||
* type: AV_OPT_TYPE_INT64
|
||||
* - Capabilities valid for video devices:
|
||||
* - pixel_format: supported pixel formats.
|
||||
* type: AV_OPT_TYPE_INT (AVPixelFormat value)
|
||||
* - window_size: supported window sizes (describes size of the window size presented to the user).
|
||||
* type: AV_OPT_TYPE_IMAGE_SIZE
|
||||
* - frame_size: supported frame sizes (describes size of provided video frames).
|
||||
* type: AV_OPT_TYPE_IMAGE_SIZE
|
||||
* - fps: supported fps values
|
||||
* type: AV_OPT_TYPE_RATIONAL
|
||||
*
|
||||
* Value of the capability may be set by user using av_opt_set() function
|
||||
* and AVDeviceCapabilitiesQuery object. Following queries will
|
||||
* limit results to the values matching already set capabilities.
|
||||
* For example, setting a codec may impact number of formats or fps values
|
||||
* returned during next query. Setting invalid value may limit results to zero.
|
||||
*
|
||||
* Example of the usage basing on opengl output device:
|
||||
*
|
||||
* @code
|
||||
* AVFormatContext *oc = NULL;
|
||||
* AVDeviceCapabilitiesQuery *caps = NULL;
|
||||
* AVOptionRanges *ranges;
|
||||
* int ret;
|
||||
*
|
||||
* if ((ret = avformat_alloc_output_context2(&oc, NULL, "opengl", NULL)) < 0)
|
||||
* goto fail;
|
||||
* if (avdevice_capabilities_create(&caps, oc, NULL) < 0)
|
||||
* goto fail;
|
||||
*
|
||||
* //query codecs
|
||||
* if (av_opt_query_ranges(&ranges, caps, "codec", AV_OPT_MULTI_COMPONENT_RANGE)) < 0)
|
||||
* goto fail;
|
||||
* //pick codec here and set it
|
||||
* av_opt_set(caps, "codec", AV_CODEC_ID_RAWVIDEO, 0);
|
||||
*
|
||||
* //query format
|
||||
* if (av_opt_query_ranges(&ranges, caps, "pixel_format", AV_OPT_MULTI_COMPONENT_RANGE)) < 0)
|
||||
* goto fail;
|
||||
* //pick format here and set it
|
||||
* av_opt_set(caps, "pixel_format", AV_PIX_FMT_YUV420P, 0);
|
||||
*
|
||||
* //query and set more capabilities
|
||||
*
|
||||
* fail:
|
||||
* //clean up code
|
||||
* avdevice_capabilities_free(&query, oc);
|
||||
* avformat_free_context(oc);
|
||||
* @endcode
|
||||
*/
|
||||
|
||||
/**
|
||||
* Structure describes device capabilities.
|
||||
*
|
||||
* It is used by devices in conjunction with av_device_capabilities AVOption table
|
||||
* to implement capabilities probing API based on AVOption API. Should not be used directly.
|
||||
*/
|
||||
typedef struct AVDeviceCapabilitiesQuery {
|
||||
const AVClass *av_class;
|
||||
AVFormatContext *device_context;
|
||||
enum AVCodecID codec;
|
||||
enum AVSampleFormat sample_format;
|
||||
enum AVPixelFormat pixel_format;
|
||||
int sample_rate;
|
||||
int channels;
|
||||
int64_t channel_layout;
|
||||
int window_width;
|
||||
int window_height;
|
||||
int frame_width;
|
||||
int frame_height;
|
||||
AVRational fps;
|
||||
} AVDeviceCapabilitiesQuery;
|
||||
|
||||
/**
|
||||
* AVOption table used by devices to implement device capabilities API. Should not be used by a user.
|
||||
*/
|
||||
extern const AVOption av_device_capabilities[];
|
||||
|
||||
/**
|
||||
* Initialize capabilities probing API based on AVOption API.
|
||||
*
|
||||
* avdevice_capabilities_free() must be called when query capabilities API is
|
||||
* not used anymore.
|
||||
*
|
||||
* @param[out] caps Device capabilities data. Pointer to a NULL pointer must be passed.
|
||||
* @param s Context of the device.
|
||||
* @param device_options An AVDictionary filled with device-private options.
|
||||
* On return this parameter will be destroyed and replaced with a dict
|
||||
* containing options that were not found. May be NULL.
|
||||
* The same options must be passed later to avformat_write_header() for output
|
||||
* devices or avformat_open_input() for input devices, or at any other place
|
||||
* that affects device-private options.
|
||||
*
|
||||
* @return >= 0 on success, negative otherwise.
|
||||
*/
|
||||
int avdevice_capabilities_create(AVDeviceCapabilitiesQuery **caps, AVFormatContext *s,
|
||||
AVDictionary **device_options);
|
||||
|
||||
/**
|
||||
* Free resources created by avdevice_capabilities_create()
|
||||
*
|
||||
* @param caps Device capabilities data to be freed.
|
||||
* @param s Context of the device.
|
||||
*/
|
||||
void avdevice_capabilities_free(AVDeviceCapabilitiesQuery **caps, AVFormatContext *s);
|
||||
|
||||
/**
|
||||
* Structure describes basic parameters of the device.
|
||||
*/
|
||||
typedef struct AVDeviceInfo {
|
||||
char *device_name; /**< device name, format depends on device */
|
||||
char *device_description; /**< human friendly name */
|
||||
} AVDeviceInfo;
|
||||
|
||||
/**
|
||||
* List of devices.
|
||||
*/
|
||||
typedef struct AVDeviceInfoList {
|
||||
AVDeviceInfo **devices; /**< list of autodetected devices */
|
||||
int nb_devices; /**< number of autodetected devices */
|
||||
int default_device; /**< index of default device or -1 if no default */
|
||||
} AVDeviceInfoList;
|
||||
|
||||
/**
|
||||
* List devices.
|
||||
*
|
||||
* Returns available device names and their parameters.
|
||||
*
|
||||
* @note: Some devices may accept system-dependent device names that cannot be
|
||||
* autodetected. The list returned by this function cannot be assumed to
|
||||
* be always completed.
|
||||
*
|
||||
* @param s device context.
|
||||
* @param[out] device_list list of autodetected devices.
|
||||
* @return count of autodetected devices, negative on error.
|
||||
*/
|
||||
int avdevice_list_devices(struct AVFormatContext *s, AVDeviceInfoList **device_list);
|
||||
|
||||
/**
|
||||
* Convenient function to free result of avdevice_list_devices().
|
||||
*
|
||||
* @param devices device list to be freed.
|
||||
*/
|
||||
void avdevice_free_list_devices(AVDeviceInfoList **device_list);
|
||||
|
||||
/**
|
||||
* List devices.
|
||||
*
|
||||
* Returns available device names and their parameters.
|
||||
* These are convinient wrappers for avdevice_list_devices().
|
||||
* Device context is allocated and deallocated internally.
|
||||
*
|
||||
* @param device device format. May be NULL if device name is set.
|
||||
* @param device_name device name. May be NULL if device format is set.
|
||||
* @param device_options An AVDictionary filled with device-private options. May be NULL.
|
||||
* The same options must be passed later to avformat_write_header() for output
|
||||
* devices or avformat_open_input() for input devices, or at any other place
|
||||
* that affects device-private options.
|
||||
* @param[out] device_list list of autodetected devices
|
||||
* @return count of autodetected devices, negative on error.
|
||||
* @note device argument takes precedence over device_name when both are set.
|
||||
*/
|
||||
int avdevice_list_input_sources(struct AVInputFormat *device, const char *device_name,
|
||||
AVDictionary *device_options, AVDeviceInfoList **device_list);
|
||||
int avdevice_list_output_sinks(struct AVOutputFormat *device, const char *device_name,
|
||||
AVDictionary *device_options, AVDeviceInfoList **device_list);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* AVDEVICE_AVDEVICE_H */
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef AVDEVICE_VERSION_H
|
||||
#define AVDEVICE_VERSION_H
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @ingroup lavd
|
||||
* Libavdevice version macros
|
||||
*/
|
||||
|
||||
#include "libavutil/version.h"
|
||||
|
||||
#define LIBAVDEVICE_VERSION_MAJOR 58
|
||||
#define LIBAVDEVICE_VERSION_MINOR 4
|
||||
#define LIBAVDEVICE_VERSION_MICRO 101
|
||||
|
||||
#define LIBAVDEVICE_VERSION_INT AV_VERSION_INT(LIBAVDEVICE_VERSION_MAJOR, \
|
||||
LIBAVDEVICE_VERSION_MINOR, \
|
||||
LIBAVDEVICE_VERSION_MICRO)
|
||||
#define LIBAVDEVICE_VERSION AV_VERSION(LIBAVDEVICE_VERSION_MAJOR, \
|
||||
LIBAVDEVICE_VERSION_MINOR, \
|
||||
LIBAVDEVICE_VERSION_MICRO)
|
||||
#define LIBAVDEVICE_BUILD LIBAVDEVICE_VERSION_INT
|
||||
|
||||
#define LIBAVDEVICE_IDENT "Lavd" AV_STRINGIFY(LIBAVDEVICE_VERSION)
|
||||
|
||||
/**
|
||||
* FF_API_* defines may be placed below to indicate public API that will be
|
||||
* dropped at a future version bump. The defines themselves are not part of
|
||||
* the public API and may change, break or disappear at any time.
|
||||
*/
|
||||
|
||||
#endif /* AVDEVICE_VERSION_H */
|
||||
@@ -0,0 +1,1168 @@
|
||||
/*
|
||||
* filter layer
|
||||
* Copyright (c) 2007 Bobby Bingham
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef AVFILTER_AVFILTER_H
|
||||
#define AVFILTER_AVFILTER_H
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @ingroup lavfi
|
||||
* Main libavfilter public API header
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup lavfi libavfilter
|
||||
* Graph-based frame editing library.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "libavutil/attributes.h"
|
||||
#include "libavutil/avutil.h"
|
||||
#include "libavutil/buffer.h"
|
||||
#include "libavutil/dict.h"
|
||||
#include "libavutil/frame.h"
|
||||
#include "libavutil/log.h"
|
||||
#include "libavutil/samplefmt.h"
|
||||
#include "libavutil/pixfmt.h"
|
||||
#include "libavutil/rational.h"
|
||||
|
||||
#include "libavfilter/version.h"
|
||||
|
||||
/**
|
||||
* Return the LIBAVFILTER_VERSION_INT constant.
|
||||
*/
|
||||
unsigned avfilter_version(void);
|
||||
|
||||
/**
|
||||
* Return the libavfilter build-time configuration.
|
||||
*/
|
||||
const char *avfilter_configuration(void);
|
||||
|
||||
/**
|
||||
* Return the libavfilter license.
|
||||
*/
|
||||
const char *avfilter_license(void);
|
||||
|
||||
typedef struct AVFilterContext AVFilterContext;
|
||||
typedef struct AVFilterLink AVFilterLink;
|
||||
typedef struct AVFilterPad AVFilterPad;
|
||||
typedef struct AVFilterFormats AVFilterFormats;
|
||||
|
||||
/**
|
||||
* Get the number of elements in a NULL-terminated array of AVFilterPads (e.g.
|
||||
* AVFilter.inputs/outputs).
|
||||
*/
|
||||
int avfilter_pad_count(const AVFilterPad *pads);
|
||||
|
||||
/**
|
||||
* Get the name of an AVFilterPad.
|
||||
*
|
||||
* @param pads an array of AVFilterPads
|
||||
* @param pad_idx index of the pad in the array it; is the caller's
|
||||
* responsibility to ensure the index is valid
|
||||
*
|
||||
* @return name of the pad_idx'th pad in pads
|
||||
*/
|
||||
const char *avfilter_pad_get_name(const AVFilterPad *pads, int pad_idx);
|
||||
|
||||
/**
|
||||
* Get the type of an AVFilterPad.
|
||||
*
|
||||
* @param pads an array of AVFilterPads
|
||||
* @param pad_idx index of the pad in the array; it is the caller's
|
||||
* responsibility to ensure the index is valid
|
||||
*
|
||||
* @return type of the pad_idx'th pad in pads
|
||||
*/
|
||||
enum AVMediaType avfilter_pad_get_type(const AVFilterPad *pads, int pad_idx);
|
||||
|
||||
/**
|
||||
* The number of the filter inputs is not determined just by AVFilter.inputs.
|
||||
* The filter might add additional inputs during initialization depending on the
|
||||
* options supplied to it.
|
||||
*/
|
||||
#define AVFILTER_FLAG_DYNAMIC_INPUTS (1 << 0)
|
||||
/**
|
||||
* The number of the filter outputs is not determined just by AVFilter.outputs.
|
||||
* The filter might add additional outputs during initialization depending on
|
||||
* the options supplied to it.
|
||||
*/
|
||||
#define AVFILTER_FLAG_DYNAMIC_OUTPUTS (1 << 1)
|
||||
/**
|
||||
* The filter supports multithreading by splitting frames into multiple parts
|
||||
* and processing them concurrently.
|
||||
*/
|
||||
#define AVFILTER_FLAG_SLICE_THREADS (1 << 2)
|
||||
/**
|
||||
* Some filters support a generic "enable" expression option that can be used
|
||||
* to enable or disable a filter in the timeline. Filters supporting this
|
||||
* option have this flag set. When the enable expression is false, the default
|
||||
* no-op filter_frame() function is called in place of the filter_frame()
|
||||
* callback defined on each input pad, thus the frame is passed unchanged to
|
||||
* the next filters.
|
||||
*/
|
||||
#define AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC (1 << 16)
|
||||
/**
|
||||
* Same as AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, except that the filter will
|
||||
* have its filter_frame() callback(s) called as usual even when the enable
|
||||
* expression is false. The filter will disable filtering within the
|
||||
* filter_frame() callback(s) itself, for example executing code depending on
|
||||
* the AVFilterContext->is_disabled value.
|
||||
*/
|
||||
#define AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL (1 << 17)
|
||||
/**
|
||||
* Handy mask to test whether the filter supports or no the timeline feature
|
||||
* (internally or generically).
|
||||
*/
|
||||
#define AVFILTER_FLAG_SUPPORT_TIMELINE (AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL)
|
||||
|
||||
/**
|
||||
* Filter definition. This defines the pads a filter contains, and all the
|
||||
* callback functions used to interact with the filter.
|
||||
*/
|
||||
typedef struct AVFilter {
|
||||
/**
|
||||
* Filter name. Must be non-NULL and unique among filters.
|
||||
*/
|
||||
const char *name;
|
||||
|
||||
/**
|
||||
* A description of the filter. May be NULL.
|
||||
*
|
||||
* You should use the NULL_IF_CONFIG_SMALL() macro to define it.
|
||||
*/
|
||||
const char *description;
|
||||
|
||||
/**
|
||||
* List of inputs, terminated by a zeroed element.
|
||||
*
|
||||
* NULL if there are no (static) inputs. Instances of filters with
|
||||
* AVFILTER_FLAG_DYNAMIC_INPUTS set may have more inputs than present in
|
||||
* this list.
|
||||
*/
|
||||
const AVFilterPad *inputs;
|
||||
/**
|
||||
* List of outputs, terminated by a zeroed element.
|
||||
*
|
||||
* NULL if there are no (static) outputs. Instances of filters with
|
||||
* AVFILTER_FLAG_DYNAMIC_OUTPUTS set may have more outputs than present in
|
||||
* this list.
|
||||
*/
|
||||
const AVFilterPad *outputs;
|
||||
|
||||
/**
|
||||
* A class for the private data, used to declare filter private AVOptions.
|
||||
* This field is NULL for filters that do not declare any options.
|
||||
*
|
||||
* If this field is non-NULL, the first member of the filter private data
|
||||
* must be a pointer to AVClass, which will be set by libavfilter generic
|
||||
* code to this class.
|
||||
*/
|
||||
const AVClass *priv_class;
|
||||
|
||||
/**
|
||||
* A combination of AVFILTER_FLAG_*
|
||||
*/
|
||||
int flags;
|
||||
|
||||
/*****************************************************************
|
||||
* All fields below this line are not part of the public API. They
|
||||
* may not be used outside of libavfilter and can be changed and
|
||||
* removed at will.
|
||||
* New public fields should be added right above.
|
||||
*****************************************************************
|
||||
*/
|
||||
|
||||
/**
|
||||
* Filter pre-initialization function
|
||||
*
|
||||
* This callback will be called immediately after the filter context is
|
||||
* allocated, to allow allocating and initing sub-objects.
|
||||
*
|
||||
* If this callback is not NULL, the uninit callback will be called on
|
||||
* allocation failure.
|
||||
*
|
||||
* @return 0 on success,
|
||||
* AVERROR code on failure (but the code will be
|
||||
* dropped and treated as ENOMEM by the calling code)
|
||||
*/
|
||||
int (*preinit)(AVFilterContext *ctx);
|
||||
|
||||
/**
|
||||
* Filter initialization function.
|
||||
*
|
||||
* This callback will be called only once during the filter lifetime, after
|
||||
* all the options have been set, but before links between filters are
|
||||
* established and format negotiation is done.
|
||||
*
|
||||
* Basic filter initialization should be done here. Filters with dynamic
|
||||
* inputs and/or outputs should create those inputs/outputs here based on
|
||||
* provided options. No more changes to this filter's inputs/outputs can be
|
||||
* done after this callback.
|
||||
*
|
||||
* This callback must not assume that the filter links exist or frame
|
||||
* parameters are known.
|
||||
*
|
||||
* @ref AVFilter.uninit "uninit" is guaranteed to be called even if
|
||||
* initialization fails, so this callback does not have to clean up on
|
||||
* failure.
|
||||
*
|
||||
* @return 0 on success, a negative AVERROR on failure
|
||||
*/
|
||||
int (*init)(AVFilterContext *ctx);
|
||||
|
||||
/**
|
||||
* Should be set instead of @ref AVFilter.init "init" by the filters that
|
||||
* want to pass a dictionary of AVOptions to nested contexts that are
|
||||
* allocated during init.
|
||||
*
|
||||
* On return, the options dict should be freed and replaced with one that
|
||||
* contains all the options which could not be processed by this filter (or
|
||||
* with NULL if all the options were processed).
|
||||
*
|
||||
* Otherwise the semantics is the same as for @ref AVFilter.init "init".
|
||||
*/
|
||||
int (*init_dict)(AVFilterContext *ctx, AVDictionary **options);
|
||||
|
||||
/**
|
||||
* Filter uninitialization function.
|
||||
*
|
||||
* Called only once right before the filter is freed. Should deallocate any
|
||||
* memory held by the filter, release any buffer references, etc. It does
|
||||
* not need to deallocate the AVFilterContext.priv memory itself.
|
||||
*
|
||||
* This callback may be called even if @ref AVFilter.init "init" was not
|
||||
* called or failed, so it must be prepared to handle such a situation.
|
||||
*/
|
||||
void (*uninit)(AVFilterContext *ctx);
|
||||
|
||||
/**
|
||||
* Query formats supported by the filter on its inputs and outputs.
|
||||
*
|
||||
* This callback is called after the filter is initialized (so the inputs
|
||||
* and outputs are fixed), shortly before the format negotiation. This
|
||||
* callback may be called more than once.
|
||||
*
|
||||
* This callback must set AVFilterLink.out_formats on every input link and
|
||||
* AVFilterLink.in_formats on every output link to a list of pixel/sample
|
||||
* formats that the filter supports on that link. For audio links, this
|
||||
* filter must also set @ref AVFilterLink.in_samplerates "in_samplerates" /
|
||||
* @ref AVFilterLink.out_samplerates "out_samplerates" and
|
||||
* @ref AVFilterLink.in_channel_layouts "in_channel_layouts" /
|
||||
* @ref AVFilterLink.out_channel_layouts "out_channel_layouts" analogously.
|
||||
*
|
||||
* This callback may be NULL for filters with one input, in which case
|
||||
* libavfilter assumes that it supports all input formats and preserves
|
||||
* them on output.
|
||||
*
|
||||
* @return zero on success, a negative value corresponding to an
|
||||
* AVERROR code otherwise
|
||||
*/
|
||||
int (*query_formats)(AVFilterContext *);
|
||||
|
||||
int priv_size; ///< size of private data to allocate for the filter
|
||||
|
||||
int flags_internal; ///< Additional flags for avfilter internal use only.
|
||||
|
||||
/**
|
||||
* Used by the filter registration system. Must not be touched by any other
|
||||
* code.
|
||||
*/
|
||||
struct AVFilter *next;
|
||||
|
||||
/**
|
||||
* Make the filter instance process a command.
|
||||
*
|
||||
* @param cmd the command to process, for handling simplicity all commands must be alphanumeric only
|
||||
* @param arg the argument for the command
|
||||
* @param res a buffer with size res_size where the filter(s) can return a response. This must not change when the command is not supported.
|
||||
* @param flags if AVFILTER_CMD_FLAG_FAST is set and the command would be
|
||||
* time consuming then a filter should treat it like an unsupported command
|
||||
*
|
||||
* @returns >=0 on success otherwise an error code.
|
||||
* AVERROR(ENOSYS) on unsupported commands
|
||||
*/
|
||||
int (*process_command)(AVFilterContext *, const char *cmd, const char *arg, char *res, int res_len, int flags);
|
||||
|
||||
/**
|
||||
* Filter initialization function, alternative to the init()
|
||||
* callback. Args contains the user-supplied parameters, opaque is
|
||||
* used for providing binary data.
|
||||
*/
|
||||
int (*init_opaque)(AVFilterContext *ctx, void *opaque);
|
||||
|
||||
/**
|
||||
* Filter activation function.
|
||||
*
|
||||
* Called when any processing is needed from the filter, instead of any
|
||||
* filter_frame and request_frame on pads.
|
||||
*
|
||||
* The function must examine inlinks and outlinks and perform a single
|
||||
* step of processing. If there is nothing to do, the function must do
|
||||
* nothing and not return an error. If more steps are or may be
|
||||
* possible, it must use ff_filter_set_ready() to schedule another
|
||||
* activation.
|
||||
*/
|
||||
int (*activate)(AVFilterContext *ctx);
|
||||
} AVFilter;
|
||||
|
||||
/**
|
||||
* Process multiple parts of the frame concurrently.
|
||||
*/
|
||||
#define AVFILTER_THREAD_SLICE (1 << 0)
|
||||
|
||||
typedef struct AVFilterInternal AVFilterInternal;
|
||||
|
||||
/** An instance of a filter */
|
||||
struct AVFilterContext {
|
||||
const AVClass *av_class; ///< needed for av_log() and filters common options
|
||||
|
||||
const AVFilter *filter; ///< the AVFilter of which this is an instance
|
||||
|
||||
char *name; ///< name of this filter instance
|
||||
|
||||
AVFilterPad *input_pads; ///< array of input pads
|
||||
AVFilterLink **inputs; ///< array of pointers to input links
|
||||
unsigned nb_inputs; ///< number of input pads
|
||||
|
||||
AVFilterPad *output_pads; ///< array of output pads
|
||||
AVFilterLink **outputs; ///< array of pointers to output links
|
||||
unsigned nb_outputs; ///< number of output pads
|
||||
|
||||
void *priv; ///< private data for use by the filter
|
||||
|
||||
struct AVFilterGraph *graph; ///< filtergraph this filter belongs to
|
||||
|
||||
/**
|
||||
* Type of multithreading being allowed/used. A combination of
|
||||
* AVFILTER_THREAD_* flags.
|
||||
*
|
||||
* May be set by the caller before initializing the filter to forbid some
|
||||
* or all kinds of multithreading for this filter. The default is allowing
|
||||
* everything.
|
||||
*
|
||||
* When the filter is initialized, this field is combined using bit AND with
|
||||
* AVFilterGraph.thread_type to get the final mask used for determining
|
||||
* allowed threading types. I.e. a threading type needs to be set in both
|
||||
* to be allowed.
|
||||
*
|
||||
* After the filter is initialized, libavfilter sets this field to the
|
||||
* threading type that is actually used (0 for no multithreading).
|
||||
*/
|
||||
int thread_type;
|
||||
|
||||
/**
|
||||
* An opaque struct for libavfilter internal use.
|
||||
*/
|
||||
AVFilterInternal *internal;
|
||||
|
||||
struct AVFilterCommand *command_queue;
|
||||
|
||||
char *enable_str; ///< enable expression string
|
||||
void *enable; ///< parsed expression (AVExpr*)
|
||||
double *var_values; ///< variable values for the enable expression
|
||||
int is_disabled; ///< the enabled state from the last expression evaluation
|
||||
|
||||
/**
|
||||
* For filters which will create hardware frames, sets the device the
|
||||
* filter should create them in. All other filters will ignore this field:
|
||||
* in particular, a filter which consumes or processes hardware frames will
|
||||
* instead use the hw_frames_ctx field in AVFilterLink to carry the
|
||||
* hardware context information.
|
||||
*/
|
||||
AVBufferRef *hw_device_ctx;
|
||||
|
||||
/**
|
||||
* Max number of threads allowed in this filter instance.
|
||||
* If <= 0, its value is ignored.
|
||||
* Overrides global number of threads set per filter graph.
|
||||
*/
|
||||
int nb_threads;
|
||||
|
||||
/**
|
||||
* Ready status of the filter.
|
||||
* A non-0 value means that the filter needs activating;
|
||||
* a higher value suggests a more urgent activation.
|
||||
*/
|
||||
unsigned ready;
|
||||
|
||||
/**
|
||||
* Sets the number of extra hardware frames which the filter will
|
||||
* allocate on its output links for use in following filters or by
|
||||
* the caller.
|
||||
*
|
||||
* Some hardware filters require all frames that they will use for
|
||||
* output to be defined in advance before filtering starts. For such
|
||||
* filters, any hardware frame pools used for output must therefore be
|
||||
* of fixed size. The extra frames set here are on top of any number
|
||||
* that the filter needs internally in order to operate normally.
|
||||
*
|
||||
* This field must be set before the graph containing this filter is
|
||||
* configured.
|
||||
*/
|
||||
int extra_hw_frames;
|
||||
};
|
||||
|
||||
/**
|
||||
* A link between two filters. This contains pointers to the source and
|
||||
* destination filters between which this link exists, and the indexes of
|
||||
* the pads involved. In addition, this link also contains the parameters
|
||||
* which have been negotiated and agreed upon between the filter, such as
|
||||
* image dimensions, format, etc.
|
||||
*
|
||||
* Applications must not normally access the link structure directly.
|
||||
* Use the buffersrc and buffersink API instead.
|
||||
* In the future, access to the header may be reserved for filters
|
||||
* implementation.
|
||||
*/
|
||||
struct AVFilterLink {
|
||||
AVFilterContext *src; ///< source filter
|
||||
AVFilterPad *srcpad; ///< output pad on the source filter
|
||||
|
||||
AVFilterContext *dst; ///< dest filter
|
||||
AVFilterPad *dstpad; ///< input pad on the dest filter
|
||||
|
||||
enum AVMediaType type; ///< filter media type
|
||||
|
||||
/* These parameters apply only to video */
|
||||
int w; ///< agreed upon image width
|
||||
int h; ///< agreed upon image height
|
||||
AVRational sample_aspect_ratio; ///< agreed upon sample aspect ratio
|
||||
/* These parameters apply only to audio */
|
||||
uint64_t channel_layout; ///< channel layout of current buffer (see libavutil/channel_layout.h)
|
||||
int sample_rate; ///< samples per second
|
||||
|
||||
int format; ///< agreed upon media format
|
||||
|
||||
/**
|
||||
* Define the time base used by the PTS of the frames/samples
|
||||
* which will pass through this link.
|
||||
* During the configuration stage, each filter is supposed to
|
||||
* change only the output timebase, while the timebase of the
|
||||
* input link is assumed to be an unchangeable property.
|
||||
*/
|
||||
AVRational time_base;
|
||||
|
||||
/*****************************************************************
|
||||
* All fields below this line are not part of the public API. They
|
||||
* may not be used outside of libavfilter and can be changed and
|
||||
* removed at will.
|
||||
* New public fields should be added right above.
|
||||
*****************************************************************
|
||||
*/
|
||||
/**
|
||||
* Lists of formats and channel layouts supported by the input and output
|
||||
* filters respectively. These lists are used for negotiating the format
|
||||
* to actually be used, which will be loaded into the format and
|
||||
* channel_layout members, above, when chosen.
|
||||
*
|
||||
*/
|
||||
AVFilterFormats *in_formats;
|
||||
AVFilterFormats *out_formats;
|
||||
|
||||
/**
|
||||
* Lists of channel layouts and sample rates used for automatic
|
||||
* negotiation.
|
||||
*/
|
||||
AVFilterFormats *in_samplerates;
|
||||
AVFilterFormats *out_samplerates;
|
||||
struct AVFilterChannelLayouts *in_channel_layouts;
|
||||
struct AVFilterChannelLayouts *out_channel_layouts;
|
||||
|
||||
/**
|
||||
* Audio only, the destination filter sets this to a non-zero value to
|
||||
* request that buffers with the given number of samples should be sent to
|
||||
* it. AVFilterPad.needs_fifo must also be set on the corresponding input
|
||||
* pad.
|
||||
* Last buffer before EOF will be padded with silence.
|
||||
*/
|
||||
int request_samples;
|
||||
|
||||
/** stage of the initialization of the link properties (dimensions, etc) */
|
||||
enum {
|
||||
AVLINK_UNINIT = 0, ///< not started
|
||||
AVLINK_STARTINIT, ///< started, but incomplete
|
||||
AVLINK_INIT ///< complete
|
||||
} init_state;
|
||||
|
||||
/**
|
||||
* Graph the filter belongs to.
|
||||
*/
|
||||
struct AVFilterGraph *graph;
|
||||
|
||||
/**
|
||||
* Current timestamp of the link, as defined by the most recent
|
||||
* frame(s), in link time_base units.
|
||||
*/
|
||||
int64_t current_pts;
|
||||
|
||||
/**
|
||||
* Current timestamp of the link, as defined by the most recent
|
||||
* frame(s), in AV_TIME_BASE units.
|
||||
*/
|
||||
int64_t current_pts_us;
|
||||
|
||||
/**
|
||||
* Index in the age array.
|
||||
*/
|
||||
int age_index;
|
||||
|
||||
/**
|
||||
* Frame rate of the stream on the link, or 1/0 if unknown or variable;
|
||||
* if left to 0/0, will be automatically copied from the first input
|
||||
* of the source filter if it exists.
|
||||
*
|
||||
* Sources should set it to the best estimation of the real frame rate.
|
||||
* If the source frame rate is unknown or variable, set this to 1/0.
|
||||
* Filters should update it if necessary depending on their function.
|
||||
* Sinks can use it to set a default output frame rate.
|
||||
* It is similar to the r_frame_rate field in AVStream.
|
||||
*/
|
||||
AVRational frame_rate;
|
||||
|
||||
/**
|
||||
* Buffer partially filled with samples to achieve a fixed/minimum size.
|
||||
*/
|
||||
AVFrame *partial_buf;
|
||||
|
||||
/**
|
||||
* Size of the partial buffer to allocate.
|
||||
* Must be between min_samples and max_samples.
|
||||
*/
|
||||
int partial_buf_size;
|
||||
|
||||
/**
|
||||
* Minimum number of samples to filter at once. If filter_frame() is
|
||||
* called with fewer samples, it will accumulate them in partial_buf.
|
||||
* This field and the related ones must not be changed after filtering
|
||||
* has started.
|
||||
* If 0, all related fields are ignored.
|
||||
*/
|
||||
int min_samples;
|
||||
|
||||
/**
|
||||
* Maximum number of samples to filter at once. If filter_frame() is
|
||||
* called with more samples, it will split them.
|
||||
*/
|
||||
int max_samples;
|
||||
|
||||
/**
|
||||
* Number of channels.
|
||||
*/
|
||||
int channels;
|
||||
|
||||
/**
|
||||
* Link processing flags.
|
||||
*/
|
||||
unsigned flags;
|
||||
|
||||
/**
|
||||
* Number of past frames sent through the link.
|
||||
*/
|
||||
int64_t frame_count_in, frame_count_out;
|
||||
|
||||
/**
|
||||
* A pointer to a FFFramePool struct.
|
||||
*/
|
||||
void *frame_pool;
|
||||
|
||||
/**
|
||||
* True if a frame is currently wanted on the output of this filter.
|
||||
* Set when ff_request_frame() is called by the output,
|
||||
* cleared when a frame is filtered.
|
||||
*/
|
||||
int frame_wanted_out;
|
||||
|
||||
/**
|
||||
* For hwaccel pixel formats, this should be a reference to the
|
||||
* AVHWFramesContext describing the frames.
|
||||
*/
|
||||
AVBufferRef *hw_frames_ctx;
|
||||
|
||||
#ifndef FF_INTERNAL_FIELDS
|
||||
|
||||
/**
|
||||
* Internal structure members.
|
||||
* The fields below this limit are internal for libavfilter's use
|
||||
* and must in no way be accessed by applications.
|
||||
*/
|
||||
char reserved[0xF000];
|
||||
|
||||
#else /* FF_INTERNAL_FIELDS */
|
||||
|
||||
/**
|
||||
* Queue of frames waiting to be filtered.
|
||||
*/
|
||||
FFFrameQueue fifo;
|
||||
|
||||
/**
|
||||
* If set, the source filter can not generate a frame as is.
|
||||
* The goal is to avoid repeatedly calling the request_frame() method on
|
||||
* the same link.
|
||||
*/
|
||||
int frame_blocked_in;
|
||||
|
||||
/**
|
||||
* Link input status.
|
||||
* If not zero, all attempts of filter_frame will fail with the
|
||||
* corresponding code.
|
||||
*/
|
||||
int status_in;
|
||||
|
||||
/**
|
||||
* Timestamp of the input status change.
|
||||
*/
|
||||
int64_t status_in_pts;
|
||||
|
||||
/**
|
||||
* Link output status.
|
||||
* If not zero, all attempts of request_frame will fail with the
|
||||
* corresponding code.
|
||||
*/
|
||||
int status_out;
|
||||
|
||||
#endif /* FF_INTERNAL_FIELDS */
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Link two filters together.
|
||||
*
|
||||
* @param src the source filter
|
||||
* @param srcpad index of the output pad on the source filter
|
||||
* @param dst the destination filter
|
||||
* @param dstpad index of the input pad on the destination filter
|
||||
* @return zero on success
|
||||
*/
|
||||
int avfilter_link(AVFilterContext *src, unsigned srcpad,
|
||||
AVFilterContext *dst, unsigned dstpad);
|
||||
|
||||
/**
|
||||
* Free the link in *link, and set its pointer to NULL.
|
||||
*/
|
||||
void avfilter_link_free(AVFilterLink **link);
|
||||
|
||||
#if FF_API_FILTER_GET_SET
|
||||
/**
|
||||
* Get the number of channels of a link.
|
||||
* @deprecated Use av_buffersink_get_channels()
|
||||
*/
|
||||
attribute_deprecated
|
||||
int avfilter_link_get_channels(AVFilterLink *link);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Set the closed field of a link.
|
||||
* @deprecated applications are not supposed to mess with links, they should
|
||||
* close the sinks.
|
||||
*/
|
||||
attribute_deprecated
|
||||
void avfilter_link_set_closed(AVFilterLink *link, int closed);
|
||||
|
||||
/**
|
||||
* Negotiate the media format, dimensions, etc of all inputs to a filter.
|
||||
*
|
||||
* @param filter the filter to negotiate the properties for its inputs
|
||||
* @return zero on successful negotiation
|
||||
*/
|
||||
int avfilter_config_links(AVFilterContext *filter);
|
||||
|
||||
#define AVFILTER_CMD_FLAG_ONE 1 ///< Stop once a filter understood the command (for target=all for example), fast filters are favored automatically
|
||||
#define AVFILTER_CMD_FLAG_FAST 2 ///< Only execute command when its fast (like a video out that supports contrast adjustment in hw)
|
||||
|
||||
/**
|
||||
* Make the filter instance process a command.
|
||||
* It is recommended to use avfilter_graph_send_command().
|
||||
*/
|
||||
int avfilter_process_command(AVFilterContext *filter, const char *cmd, const char *arg, char *res, int res_len, int flags);
|
||||
|
||||
/**
|
||||
* Iterate over all registered filters.
|
||||
*
|
||||
* @param opaque a pointer where libavfilter will store the iteration state. Must
|
||||
* point to NULL to start the iteration.
|
||||
*
|
||||
* @return the next registered filter or NULL when the iteration is
|
||||
* finished
|
||||
*/
|
||||
const AVFilter *av_filter_iterate(void **opaque);
|
||||
|
||||
#if FF_API_NEXT
|
||||
/** Initialize the filter system. Register all builtin filters. */
|
||||
attribute_deprecated
|
||||
void avfilter_register_all(void);
|
||||
|
||||
/**
|
||||
* Register a filter. This is only needed if you plan to use
|
||||
* avfilter_get_by_name later to lookup the AVFilter structure by name. A
|
||||
* filter can still by instantiated with avfilter_graph_alloc_filter even if it
|
||||
* is not registered.
|
||||
*
|
||||
* @param filter the filter to register
|
||||
* @return 0 if the registration was successful, a negative value
|
||||
* otherwise
|
||||
*/
|
||||
attribute_deprecated
|
||||
int avfilter_register(AVFilter *filter);
|
||||
|
||||
/**
|
||||
* Iterate over all registered filters.
|
||||
* @return If prev is non-NULL, next registered filter after prev or NULL if
|
||||
* prev is the last filter. If prev is NULL, return the first registered filter.
|
||||
*/
|
||||
attribute_deprecated
|
||||
const AVFilter *avfilter_next(const AVFilter *prev);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Get a filter definition matching the given name.
|
||||
*
|
||||
* @param name the filter name to find
|
||||
* @return the filter definition, if any matching one is registered.
|
||||
* NULL if none found.
|
||||
*/
|
||||
const AVFilter *avfilter_get_by_name(const char *name);
|
||||
|
||||
|
||||
/**
|
||||
* Initialize a filter with the supplied parameters.
|
||||
*
|
||||
* @param ctx uninitialized filter context to initialize
|
||||
* @param args Options to initialize the filter with. This must be a
|
||||
* ':'-separated list of options in the 'key=value' form.
|
||||
* May be NULL if the options have been set directly using the
|
||||
* AVOptions API or there are no options that need to be set.
|
||||
* @return 0 on success, a negative AVERROR on failure
|
||||
*/
|
||||
int avfilter_init_str(AVFilterContext *ctx, const char *args);
|
||||
|
||||
/**
|
||||
* Initialize a filter with the supplied dictionary of options.
|
||||
*
|
||||
* @param ctx uninitialized filter context to initialize
|
||||
* @param options An AVDictionary filled with options for this filter. On
|
||||
* return this parameter will be destroyed and replaced with
|
||||
* a dict containing options that were not found. This dictionary
|
||||
* must be freed by the caller.
|
||||
* May be NULL, then this function is equivalent to
|
||||
* avfilter_init_str() with the second parameter set to NULL.
|
||||
* @return 0 on success, a negative AVERROR on failure
|
||||
*
|
||||
* @note This function and avfilter_init_str() do essentially the same thing,
|
||||
* the difference is in manner in which the options are passed. It is up to the
|
||||
* calling code to choose whichever is more preferable. The two functions also
|
||||
* behave differently when some of the provided options are not declared as
|
||||
* supported by the filter. In such a case, avfilter_init_str() will fail, but
|
||||
* this function will leave those extra options in the options AVDictionary and
|
||||
* continue as usual.
|
||||
*/
|
||||
int avfilter_init_dict(AVFilterContext *ctx, AVDictionary **options);
|
||||
|
||||
/**
|
||||
* Free a filter context. This will also remove the filter from its
|
||||
* filtergraph's list of filters.
|
||||
*
|
||||
* @param filter the filter to free
|
||||
*/
|
||||
void avfilter_free(AVFilterContext *filter);
|
||||
|
||||
/**
|
||||
* Insert a filter in the middle of an existing link.
|
||||
*
|
||||
* @param link the link into which the filter should be inserted
|
||||
* @param filt the filter to be inserted
|
||||
* @param filt_srcpad_idx the input pad on the filter to connect
|
||||
* @param filt_dstpad_idx the output pad on the filter to connect
|
||||
* @return zero on success
|
||||
*/
|
||||
int avfilter_insert_filter(AVFilterLink *link, AVFilterContext *filt,
|
||||
unsigned filt_srcpad_idx, unsigned filt_dstpad_idx);
|
||||
|
||||
/**
|
||||
* @return AVClass for AVFilterContext.
|
||||
*
|
||||
* @see av_opt_find().
|
||||
*/
|
||||
const AVClass *avfilter_get_class(void);
|
||||
|
||||
typedef struct AVFilterGraphInternal AVFilterGraphInternal;
|
||||
|
||||
/**
|
||||
* A function pointer passed to the @ref AVFilterGraph.execute callback to be
|
||||
* executed multiple times, possibly in parallel.
|
||||
*
|
||||
* @param ctx the filter context the job belongs to
|
||||
* @param arg an opaque parameter passed through from @ref
|
||||
* AVFilterGraph.execute
|
||||
* @param jobnr the index of the job being executed
|
||||
* @param nb_jobs the total number of jobs
|
||||
*
|
||||
* @return 0 on success, a negative AVERROR on error
|
||||
*/
|
||||
typedef int (avfilter_action_func)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs);
|
||||
|
||||
/**
|
||||
* A function executing multiple jobs, possibly in parallel.
|
||||
*
|
||||
* @param ctx the filter context to which the jobs belong
|
||||
* @param func the function to be called multiple times
|
||||
* @param arg the argument to be passed to func
|
||||
* @param ret a nb_jobs-sized array to be filled with return values from each
|
||||
* invocation of func
|
||||
* @param nb_jobs the number of jobs to execute
|
||||
*
|
||||
* @return 0 on success, a negative AVERROR on error
|
||||
*/
|
||||
typedef int (avfilter_execute_func)(AVFilterContext *ctx, avfilter_action_func *func,
|
||||
void *arg, int *ret, int nb_jobs);
|
||||
|
||||
typedef struct AVFilterGraph {
|
||||
const AVClass *av_class;
|
||||
AVFilterContext **filters;
|
||||
unsigned nb_filters;
|
||||
|
||||
char *scale_sws_opts; ///< sws options to use for the auto-inserted scale filters
|
||||
#if FF_API_LAVR_OPTS
|
||||
attribute_deprecated char *resample_lavr_opts; ///< libavresample options to use for the auto-inserted resample filters
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Type of multithreading allowed for filters in this graph. A combination
|
||||
* of AVFILTER_THREAD_* flags.
|
||||
*
|
||||
* May be set by the caller at any point, the setting will apply to all
|
||||
* filters initialized after that. The default is allowing everything.
|
||||
*
|
||||
* When a filter in this graph is initialized, this field is combined using
|
||||
* bit AND with AVFilterContext.thread_type to get the final mask used for
|
||||
* determining allowed threading types. I.e. a threading type needs to be
|
||||
* set in both to be allowed.
|
||||
*/
|
||||
int thread_type;
|
||||
|
||||
/**
|
||||
* Maximum number of threads used by filters in this graph. May be set by
|
||||
* the caller before adding any filters to the filtergraph. Zero (the
|
||||
* default) means that the number of threads is determined automatically.
|
||||
*/
|
||||
int nb_threads;
|
||||
|
||||
/**
|
||||
* Opaque object for libavfilter internal use.
|
||||
*/
|
||||
AVFilterGraphInternal *internal;
|
||||
|
||||
/**
|
||||
* Opaque user data. May be set by the caller to an arbitrary value, e.g. to
|
||||
* be used from callbacks like @ref AVFilterGraph.execute.
|
||||
* Libavfilter will not touch this field in any way.
|
||||
*/
|
||||
void *opaque;
|
||||
|
||||
/**
|
||||
* This callback may be set by the caller immediately after allocating the
|
||||
* graph and before adding any filters to it, to provide a custom
|
||||
* multithreading implementation.
|
||||
*
|
||||
* If set, filters with slice threading capability will call this callback
|
||||
* to execute multiple jobs in parallel.
|
||||
*
|
||||
* If this field is left unset, libavfilter will use its internal
|
||||
* implementation, which may or may not be multithreaded depending on the
|
||||
* platform and build options.
|
||||
*/
|
||||
avfilter_execute_func *execute;
|
||||
|
||||
char *aresample_swr_opts; ///< swr options to use for the auto-inserted aresample filters, Access ONLY through AVOptions
|
||||
|
||||
/**
|
||||
* Private fields
|
||||
*
|
||||
* The following fields are for internal use only.
|
||||
* Their type, offset, number and semantic can change without notice.
|
||||
*/
|
||||
|
||||
AVFilterLink **sink_links;
|
||||
int sink_links_count;
|
||||
|
||||
unsigned disable_auto_convert;
|
||||
} AVFilterGraph;
|
||||
|
||||
/**
|
||||
* Allocate a filter graph.
|
||||
*
|
||||
* @return the allocated filter graph on success or NULL.
|
||||
*/
|
||||
AVFilterGraph *avfilter_graph_alloc(void);
|
||||
|
||||
/**
|
||||
* Create a new filter instance in a filter graph.
|
||||
*
|
||||
* @param graph graph in which the new filter will be used
|
||||
* @param filter the filter to create an instance of
|
||||
* @param name Name to give to the new instance (will be copied to
|
||||
* AVFilterContext.name). This may be used by the caller to identify
|
||||
* different filters, libavfilter itself assigns no semantics to
|
||||
* this parameter. May be NULL.
|
||||
*
|
||||
* @return the context of the newly created filter instance (note that it is
|
||||
* also retrievable directly through AVFilterGraph.filters or with
|
||||
* avfilter_graph_get_filter()) on success or NULL on failure.
|
||||
*/
|
||||
AVFilterContext *avfilter_graph_alloc_filter(AVFilterGraph *graph,
|
||||
const AVFilter *filter,
|
||||
const char *name);
|
||||
|
||||
/**
|
||||
* Get a filter instance identified by instance name from graph.
|
||||
*
|
||||
* @param graph filter graph to search through.
|
||||
* @param name filter instance name (should be unique in the graph).
|
||||
* @return the pointer to the found filter instance or NULL if it
|
||||
* cannot be found.
|
||||
*/
|
||||
AVFilterContext *avfilter_graph_get_filter(AVFilterGraph *graph, const char *name);
|
||||
|
||||
/**
|
||||
* Create and add a filter instance into an existing graph.
|
||||
* The filter instance is created from the filter filt and inited
|
||||
* with the parameters args and opaque.
|
||||
*
|
||||
* In case of success put in *filt_ctx the pointer to the created
|
||||
* filter instance, otherwise set *filt_ctx to NULL.
|
||||
*
|
||||
* @param name the instance name to give to the created filter instance
|
||||
* @param graph_ctx the filter graph
|
||||
* @return a negative AVERROR error code in case of failure, a non
|
||||
* negative value otherwise
|
||||
*/
|
||||
int avfilter_graph_create_filter(AVFilterContext **filt_ctx, const AVFilter *filt,
|
||||
const char *name, const char *args, void *opaque,
|
||||
AVFilterGraph *graph_ctx);
|
||||
|
||||
/**
|
||||
* Enable or disable automatic format conversion inside the graph.
|
||||
*
|
||||
* Note that format conversion can still happen inside explicitly inserted
|
||||
* scale and aresample filters.
|
||||
*
|
||||
* @param flags any of the AVFILTER_AUTO_CONVERT_* constants
|
||||
*/
|
||||
void avfilter_graph_set_auto_convert(AVFilterGraph *graph, unsigned flags);
|
||||
|
||||
enum {
|
||||
AVFILTER_AUTO_CONVERT_ALL = 0, /**< all automatic conversions enabled */
|
||||
AVFILTER_AUTO_CONVERT_NONE = -1, /**< all automatic conversions disabled */
|
||||
};
|
||||
|
||||
/**
|
||||
* Check validity and configure all the links and formats in the graph.
|
||||
*
|
||||
* @param graphctx the filter graph
|
||||
* @param log_ctx context used for logging
|
||||
* @return >= 0 in case of success, a negative AVERROR code otherwise
|
||||
*/
|
||||
int avfilter_graph_config(AVFilterGraph *graphctx, void *log_ctx);
|
||||
|
||||
/**
|
||||
* Free a graph, destroy its links, and set *graph to NULL.
|
||||
* If *graph is NULL, do nothing.
|
||||
*/
|
||||
void avfilter_graph_free(AVFilterGraph **graph);
|
||||
|
||||
/**
|
||||
* A linked-list of the inputs/outputs of the filter chain.
|
||||
*
|
||||
* This is mainly useful for avfilter_graph_parse() / avfilter_graph_parse2(),
|
||||
* where it is used to communicate open (unlinked) inputs and outputs from and
|
||||
* to the caller.
|
||||
* This struct specifies, per each not connected pad contained in the graph, the
|
||||
* filter context and the pad index required for establishing a link.
|
||||
*/
|
||||
typedef struct AVFilterInOut {
|
||||
/** unique name for this input/output in the list */
|
||||
char *name;
|
||||
|
||||
/** filter context associated to this input/output */
|
||||
AVFilterContext *filter_ctx;
|
||||
|
||||
/** index of the filt_ctx pad to use for linking */
|
||||
int pad_idx;
|
||||
|
||||
/** next input/input in the list, NULL if this is the last */
|
||||
struct AVFilterInOut *next;
|
||||
} AVFilterInOut;
|
||||
|
||||
/**
|
||||
* Allocate a single AVFilterInOut entry.
|
||||
* Must be freed with avfilter_inout_free().
|
||||
* @return allocated AVFilterInOut on success, NULL on failure.
|
||||
*/
|
||||
AVFilterInOut *avfilter_inout_alloc(void);
|
||||
|
||||
/**
|
||||
* Free the supplied list of AVFilterInOut and set *inout to NULL.
|
||||
* If *inout is NULL, do nothing.
|
||||
*/
|
||||
void avfilter_inout_free(AVFilterInOut **inout);
|
||||
|
||||
/**
|
||||
* Add a graph described by a string to a graph.
|
||||
*
|
||||
* @note The caller must provide the lists of inputs and outputs,
|
||||
* which therefore must be known before calling the function.
|
||||
*
|
||||
* @note The inputs parameter describes inputs of the already existing
|
||||
* part of the graph; i.e. from the point of view of the newly created
|
||||
* part, they are outputs. Similarly the outputs parameter describes
|
||||
* outputs of the already existing filters, which are provided as
|
||||
* inputs to the parsed filters.
|
||||
*
|
||||
* @param graph the filter graph where to link the parsed graph context
|
||||
* @param filters string to be parsed
|
||||
* @param inputs linked list to the inputs of the graph
|
||||
* @param outputs linked list to the outputs of the graph
|
||||
* @return zero on success, a negative AVERROR code on error
|
||||
*/
|
||||
int avfilter_graph_parse(AVFilterGraph *graph, const char *filters,
|
||||
AVFilterInOut *inputs, AVFilterInOut *outputs,
|
||||
void *log_ctx);
|
||||
|
||||
/**
|
||||
* Add a graph described by a string to a graph.
|
||||
*
|
||||
* In the graph filters description, if the input label of the first
|
||||
* filter is not specified, "in" is assumed; if the output label of
|
||||
* the last filter is not specified, "out" is assumed.
|
||||
*
|
||||
* @param graph the filter graph where to link the parsed graph context
|
||||
* @param filters string to be parsed
|
||||
* @param inputs pointer to a linked list to the inputs of the graph, may be NULL.
|
||||
* If non-NULL, *inputs is updated to contain the list of open inputs
|
||||
* after the parsing, should be freed with avfilter_inout_free().
|
||||
* @param outputs pointer to a linked list to the outputs of the graph, may be NULL.
|
||||
* If non-NULL, *outputs is updated to contain the list of open outputs
|
||||
* after the parsing, should be freed with avfilter_inout_free().
|
||||
* @return non negative on success, a negative AVERROR code on error
|
||||
*/
|
||||
int avfilter_graph_parse_ptr(AVFilterGraph *graph, const char *filters,
|
||||
AVFilterInOut **inputs, AVFilterInOut **outputs,
|
||||
void *log_ctx);
|
||||
|
||||
/**
|
||||
* Add a graph described by a string to a graph.
|
||||
*
|
||||
* @param[in] graph the filter graph where to link the parsed graph context
|
||||
* @param[in] filters string to be parsed
|
||||
* @param[out] inputs a linked list of all free (unlinked) inputs of the
|
||||
* parsed graph will be returned here. It is to be freed
|
||||
* by the caller using avfilter_inout_free().
|
||||
* @param[out] outputs a linked list of all free (unlinked) outputs of the
|
||||
* parsed graph will be returned here. It is to be freed by the
|
||||
* caller using avfilter_inout_free().
|
||||
* @return zero on success, a negative AVERROR code on error
|
||||
*
|
||||
* @note This function returns the inputs and outputs that are left
|
||||
* unlinked after parsing the graph and the caller then deals with
|
||||
* them.
|
||||
* @note This function makes no reference whatsoever to already
|
||||
* existing parts of the graph and the inputs parameter will on return
|
||||
* contain inputs of the newly parsed part of the graph. Analogously
|
||||
* the outputs parameter will contain outputs of the newly created
|
||||
* filters.
|
||||
*/
|
||||
int avfilter_graph_parse2(AVFilterGraph *graph, const char *filters,
|
||||
AVFilterInOut **inputs,
|
||||
AVFilterInOut **outputs);
|
||||
|
||||
/**
|
||||
* Send a command to one or more filter instances.
|
||||
*
|
||||
* @param graph the filter graph
|
||||
* @param target the filter(s) to which the command should be sent
|
||||
* "all" sends to all filters
|
||||
* otherwise it can be a filter or filter instance name
|
||||
* which will send the command to all matching filters.
|
||||
* @param cmd the command to send, for handling simplicity all commands must be alphanumeric only
|
||||
* @param arg the argument for the command
|
||||
* @param res a buffer with size res_size where the filter(s) can return a response.
|
||||
*
|
||||
* @returns >=0 on success otherwise an error code.
|
||||
* AVERROR(ENOSYS) on unsupported commands
|
||||
*/
|
||||
int avfilter_graph_send_command(AVFilterGraph *graph, const char *target, const char *cmd, const char *arg, char *res, int res_len, int flags);
|
||||
|
||||
/**
|
||||
* Queue a command for one or more filter instances.
|
||||
*
|
||||
* @param graph the filter graph
|
||||
* @param target the filter(s) to which the command should be sent
|
||||
* "all" sends to all filters
|
||||
* otherwise it can be a filter or filter instance name
|
||||
* which will send the command to all matching filters.
|
||||
* @param cmd the command to sent, for handling simplicity all commands must be alphanumeric only
|
||||
* @param arg the argument for the command
|
||||
* @param ts time at which the command should be sent to the filter
|
||||
*
|
||||
* @note As this executes commands after this function returns, no return code
|
||||
* from the filter is provided, also AVFILTER_CMD_FLAG_ONE is not supported.
|
||||
*/
|
||||
int avfilter_graph_queue_command(AVFilterGraph *graph, const char *target, const char *cmd, const char *arg, int flags, double ts);
|
||||
|
||||
|
||||
/**
|
||||
* Dump a graph into a human-readable string representation.
|
||||
*
|
||||
* @param graph the graph to dump
|
||||
* @param options formatting options; currently ignored
|
||||
* @return a string, or NULL in case of memory allocation failure;
|
||||
* the string must be freed using av_free
|
||||
*/
|
||||
char *avfilter_graph_dump(AVFilterGraph *graph, const char *options);
|
||||
|
||||
/**
|
||||
* Request a frame on the oldest sink link.
|
||||
*
|
||||
* If the request returns AVERROR_EOF, try the next.
|
||||
*
|
||||
* Note that this function is not meant to be the sole scheduling mechanism
|
||||
* of a filtergraph, only a convenience function to help drain a filtergraph
|
||||
* in a balanced way under normal circumstances.
|
||||
*
|
||||
* Also note that AVERROR_EOF does not mean that frames did not arrive on
|
||||
* some of the sinks during the process.
|
||||
* When there are multiple sink links, in case the requested link
|
||||
* returns an EOF, this may cause a filter to flush pending frames
|
||||
* which are sent to another sink link, although unrequested.
|
||||
*
|
||||
* @return the return value of ff_request_frame(),
|
||||
* or AVERROR_EOF if all links returned AVERROR_EOF
|
||||
*/
|
||||
int avfilter_graph_request_oldest(AVFilterGraph *graph);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* AVFILTER_AVFILTER_H */
|
||||
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef AVFILTER_BUFFERSINK_H
|
||||
#define AVFILTER_BUFFERSINK_H
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @ingroup lavfi_buffersink
|
||||
* memory buffer sink API for audio and video
|
||||
*/
|
||||
|
||||
#include "avfilter.h"
|
||||
|
||||
/**
|
||||
* @defgroup lavfi_buffersink Buffer sink API
|
||||
* @ingroup lavfi
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Get a frame with filtered data from sink and put it in frame.
|
||||
*
|
||||
* @param ctx pointer to a buffersink or abuffersink filter context.
|
||||
* @param frame pointer to an allocated frame that will be filled with data.
|
||||
* The data must be freed using av_frame_unref() / av_frame_free()
|
||||
* @param flags a combination of AV_BUFFERSINK_FLAG_* flags
|
||||
*
|
||||
* @return >= 0 in for success, a negative AVERROR code for failure.
|
||||
*/
|
||||
int av_buffersink_get_frame_flags(AVFilterContext *ctx, AVFrame *frame, int flags);
|
||||
|
||||
/**
|
||||
* Tell av_buffersink_get_buffer_ref() to read video/samples buffer
|
||||
* reference, but not remove it from the buffer. This is useful if you
|
||||
* need only to read a video/samples buffer, without to fetch it.
|
||||
*/
|
||||
#define AV_BUFFERSINK_FLAG_PEEK 1
|
||||
|
||||
/**
|
||||
* Tell av_buffersink_get_buffer_ref() not to request a frame from its input.
|
||||
* If a frame is already buffered, it is read (and removed from the buffer),
|
||||
* but if no frame is present, return AVERROR(EAGAIN).
|
||||
*/
|
||||
#define AV_BUFFERSINK_FLAG_NO_REQUEST 2
|
||||
|
||||
/**
|
||||
* Struct to use for initializing a buffersink context.
|
||||
*/
|
||||
typedef struct AVBufferSinkParams {
|
||||
const enum AVPixelFormat *pixel_fmts; ///< list of allowed pixel formats, terminated by AV_PIX_FMT_NONE
|
||||
} AVBufferSinkParams;
|
||||
|
||||
/**
|
||||
* Create an AVBufferSinkParams structure.
|
||||
*
|
||||
* Must be freed with av_free().
|
||||
*/
|
||||
AVBufferSinkParams *av_buffersink_params_alloc(void);
|
||||
|
||||
/**
|
||||
* Struct to use for initializing an abuffersink context.
|
||||
*/
|
||||
typedef struct AVABufferSinkParams {
|
||||
const enum AVSampleFormat *sample_fmts; ///< list of allowed sample formats, terminated by AV_SAMPLE_FMT_NONE
|
||||
const int64_t *channel_layouts; ///< list of allowed channel layouts, terminated by -1
|
||||
const int *channel_counts; ///< list of allowed channel counts, terminated by -1
|
||||
int all_channel_counts; ///< if not 0, accept any channel count or layout
|
||||
int *sample_rates; ///< list of allowed sample rates, terminated by -1
|
||||
} AVABufferSinkParams;
|
||||
|
||||
/**
|
||||
* Create an AVABufferSinkParams structure.
|
||||
*
|
||||
* Must be freed with av_free().
|
||||
*/
|
||||
AVABufferSinkParams *av_abuffersink_params_alloc(void);
|
||||
|
||||
/**
|
||||
* Set the frame size for an audio buffer sink.
|
||||
*
|
||||
* All calls to av_buffersink_get_buffer_ref will return a buffer with
|
||||
* exactly the specified number of samples, or AVERROR(EAGAIN) if there is
|
||||
* not enough. The last buffer at EOF will be padded with 0.
|
||||
*/
|
||||
void av_buffersink_set_frame_size(AVFilterContext *ctx, unsigned frame_size);
|
||||
|
||||
/**
|
||||
* @defgroup lavfi_buffersink_accessors Buffer sink accessors
|
||||
* Get the properties of the stream
|
||||
* @{
|
||||
*/
|
||||
|
||||
enum AVMediaType av_buffersink_get_type (const AVFilterContext *ctx);
|
||||
AVRational av_buffersink_get_time_base (const AVFilterContext *ctx);
|
||||
int av_buffersink_get_format (const AVFilterContext *ctx);
|
||||
|
||||
AVRational av_buffersink_get_frame_rate (const AVFilterContext *ctx);
|
||||
int av_buffersink_get_w (const AVFilterContext *ctx);
|
||||
int av_buffersink_get_h (const AVFilterContext *ctx);
|
||||
AVRational av_buffersink_get_sample_aspect_ratio (const AVFilterContext *ctx);
|
||||
|
||||
int av_buffersink_get_channels (const AVFilterContext *ctx);
|
||||
uint64_t av_buffersink_get_channel_layout (const AVFilterContext *ctx);
|
||||
int av_buffersink_get_sample_rate (const AVFilterContext *ctx);
|
||||
|
||||
AVBufferRef * av_buffersink_get_hw_frames_ctx (const AVFilterContext *ctx);
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* Get a frame with filtered data from sink and put it in frame.
|
||||
*
|
||||
* @param ctx pointer to a context of a buffersink or abuffersink AVFilter.
|
||||
* @param frame pointer to an allocated frame that will be filled with data.
|
||||
* The data must be freed using av_frame_unref() / av_frame_free()
|
||||
*
|
||||
* @return
|
||||
* - >= 0 if a frame was successfully returned.
|
||||
* - AVERROR(EAGAIN) if no frames are available at this point; more
|
||||
* input frames must be added to the filtergraph to get more output.
|
||||
* - AVERROR_EOF if there will be no more output frames on this sink.
|
||||
* - A different negative AVERROR code in other failure cases.
|
||||
*/
|
||||
int av_buffersink_get_frame(AVFilterContext *ctx, AVFrame *frame);
|
||||
|
||||
/**
|
||||
* Same as av_buffersink_get_frame(), but with the ability to specify the number
|
||||
* of samples read. This function is less efficient than
|
||||
* av_buffersink_get_frame(), because it copies the data around.
|
||||
*
|
||||
* @param ctx pointer to a context of the abuffersink AVFilter.
|
||||
* @param frame pointer to an allocated frame that will be filled with data.
|
||||
* The data must be freed using av_frame_unref() / av_frame_free()
|
||||
* frame will contain exactly nb_samples audio samples, except at
|
||||
* the end of stream, when it can contain less than nb_samples.
|
||||
*
|
||||
* @return The return codes have the same meaning as for
|
||||
* av_buffersink_get_samples().
|
||||
*
|
||||
* @warning do not mix this function with av_buffersink_get_frame(). Use only one or
|
||||
* the other with a single sink, not both.
|
||||
*/
|
||||
int av_buffersink_get_samples(AVFilterContext *ctx, AVFrame *frame, int nb_samples);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* AVFILTER_BUFFERSINK_H */
|
||||
@@ -0,0 +1,209 @@
|
||||
/*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef AVFILTER_BUFFERSRC_H
|
||||
#define AVFILTER_BUFFERSRC_H
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @ingroup lavfi_buffersrc
|
||||
* Memory buffer source API.
|
||||
*/
|
||||
|
||||
#include "avfilter.h"
|
||||
|
||||
/**
|
||||
* @defgroup lavfi_buffersrc Buffer source API
|
||||
* @ingroup lavfi
|
||||
* @{
|
||||
*/
|
||||
|
||||
enum {
|
||||
|
||||
/**
|
||||
* Do not check for format changes.
|
||||
*/
|
||||
AV_BUFFERSRC_FLAG_NO_CHECK_FORMAT = 1,
|
||||
|
||||
/**
|
||||
* Immediately push the frame to the output.
|
||||
*/
|
||||
AV_BUFFERSRC_FLAG_PUSH = 4,
|
||||
|
||||
/**
|
||||
* Keep a reference to the frame.
|
||||
* If the frame if reference-counted, create a new reference; otherwise
|
||||
* copy the frame data.
|
||||
*/
|
||||
AV_BUFFERSRC_FLAG_KEEP_REF = 8,
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the number of failed requests.
|
||||
*
|
||||
* A failed request is when the request_frame method is called while no
|
||||
* frame is present in the buffer.
|
||||
* The number is reset when a frame is added.
|
||||
*/
|
||||
unsigned av_buffersrc_get_nb_failed_requests(AVFilterContext *buffer_src);
|
||||
|
||||
/**
|
||||
* This structure contains the parameters describing the frames that will be
|
||||
* passed to this filter.
|
||||
*
|
||||
* It should be allocated with av_buffersrc_parameters_alloc() and freed with
|
||||
* av_free(). All the allocated fields in it remain owned by the caller.
|
||||
*/
|
||||
typedef struct AVBufferSrcParameters {
|
||||
/**
|
||||
* video: the pixel format, value corresponds to enum AVPixelFormat
|
||||
* audio: the sample format, value corresponds to enum AVSampleFormat
|
||||
*/
|
||||
int format;
|
||||
/**
|
||||
* The timebase to be used for the timestamps on the input frames.
|
||||
*/
|
||||
AVRational time_base;
|
||||
|
||||
/**
|
||||
* Video only, the display dimensions of the input frames.
|
||||
*/
|
||||
int width, height;
|
||||
|
||||
/**
|
||||
* Video only, the sample (pixel) aspect ratio.
|
||||
*/
|
||||
AVRational sample_aspect_ratio;
|
||||
|
||||
/**
|
||||
* Video only, the frame rate of the input video. This field must only be
|
||||
* set to a non-zero value if input stream has a known constant framerate
|
||||
* and should be left at its initial value if the framerate is variable or
|
||||
* unknown.
|
||||
*/
|
||||
AVRational frame_rate;
|
||||
|
||||
/**
|
||||
* Video with a hwaccel pixel format only. This should be a reference to an
|
||||
* AVHWFramesContext instance describing the input frames.
|
||||
*/
|
||||
AVBufferRef *hw_frames_ctx;
|
||||
|
||||
/**
|
||||
* Audio only, the audio sampling rate in samples per secon.
|
||||
*/
|
||||
int sample_rate;
|
||||
|
||||
/**
|
||||
* Audio only, the audio channel layout
|
||||
*/
|
||||
uint64_t channel_layout;
|
||||
} AVBufferSrcParameters;
|
||||
|
||||
/**
|
||||
* Allocate a new AVBufferSrcParameters instance. It should be freed by the
|
||||
* caller with av_free().
|
||||
*/
|
||||
AVBufferSrcParameters *av_buffersrc_parameters_alloc(void);
|
||||
|
||||
/**
|
||||
* Initialize the buffersrc or abuffersrc filter with the provided parameters.
|
||||
* This function may be called multiple times, the later calls override the
|
||||
* previous ones. Some of the parameters may also be set through AVOptions, then
|
||||
* whatever method is used last takes precedence.
|
||||
*
|
||||
* @param ctx an instance of the buffersrc or abuffersrc filter
|
||||
* @param param the stream parameters. The frames later passed to this filter
|
||||
* must conform to those parameters. All the allocated fields in
|
||||
* param remain owned by the caller, libavfilter will make internal
|
||||
* copies or references when necessary.
|
||||
* @return 0 on success, a negative AVERROR code on failure.
|
||||
*/
|
||||
int av_buffersrc_parameters_set(AVFilterContext *ctx, AVBufferSrcParameters *param);
|
||||
|
||||
/**
|
||||
* Add a frame to the buffer source.
|
||||
*
|
||||
* @param ctx an instance of the buffersrc filter
|
||||
* @param frame frame to be added. If the frame is reference counted, this
|
||||
* function will make a new reference to it. Otherwise the frame data will be
|
||||
* copied.
|
||||
*
|
||||
* @return 0 on success, a negative AVERROR on error
|
||||
*
|
||||
* This function is equivalent to av_buffersrc_add_frame_flags() with the
|
||||
* AV_BUFFERSRC_FLAG_KEEP_REF flag.
|
||||
*/
|
||||
av_warn_unused_result
|
||||
int av_buffersrc_write_frame(AVFilterContext *ctx, const AVFrame *frame);
|
||||
|
||||
/**
|
||||
* Add a frame to the buffer source.
|
||||
*
|
||||
* @param ctx an instance of the buffersrc filter
|
||||
* @param frame frame to be added. If the frame is reference counted, this
|
||||
* function will take ownership of the reference(s) and reset the frame.
|
||||
* Otherwise the frame data will be copied. If this function returns an error,
|
||||
* the input frame is not touched.
|
||||
*
|
||||
* @return 0 on success, a negative AVERROR on error.
|
||||
*
|
||||
* @note the difference between this function and av_buffersrc_write_frame() is
|
||||
* that av_buffersrc_write_frame() creates a new reference to the input frame,
|
||||
* while this function takes ownership of the reference passed to it.
|
||||
*
|
||||
* This function is equivalent to av_buffersrc_add_frame_flags() without the
|
||||
* AV_BUFFERSRC_FLAG_KEEP_REF flag.
|
||||
*/
|
||||
av_warn_unused_result
|
||||
int av_buffersrc_add_frame(AVFilterContext *ctx, AVFrame *frame);
|
||||
|
||||
/**
|
||||
* Add a frame to the buffer source.
|
||||
*
|
||||
* By default, if the frame is reference-counted, this function will take
|
||||
* ownership of the reference(s) and reset the frame. This can be controlled
|
||||
* using the flags.
|
||||
*
|
||||
* If this function returns an error, the input frame is not touched.
|
||||
*
|
||||
* @param buffer_src pointer to a buffer source context
|
||||
* @param frame a frame, or NULL to mark EOF
|
||||
* @param flags a combination of AV_BUFFERSRC_FLAG_*
|
||||
* @return >= 0 in case of success, a negative AVERROR code
|
||||
* in case of failure
|
||||
*/
|
||||
av_warn_unused_result
|
||||
int av_buffersrc_add_frame_flags(AVFilterContext *buffer_src,
|
||||
AVFrame *frame, int flags);
|
||||
|
||||
/**
|
||||
* Close the buffer source after EOF.
|
||||
*
|
||||
* This is similar to passing NULL to av_buffersrc_add_frame_flags()
|
||||
* except it takes the timestamp of the EOF, i.e. the timestamp of the end
|
||||
* of the last frame.
|
||||
*/
|
||||
int av_buffersrc_close(AVFilterContext *ctx, int64_t pts, unsigned flags);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* AVFILTER_BUFFERSRC_H */
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Version macros.
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef AVFILTER_VERSION_H
|
||||
#define AVFILTER_VERSION_H
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @ingroup lavfi
|
||||
* Libavfilter version macros
|
||||
*/
|
||||
|
||||
#include "libavutil/version.h"
|
||||
|
||||
#define LIBAVFILTER_VERSION_MAJOR 7
|
||||
#define LIBAVFILTER_VERSION_MINOR 25
|
||||
#define LIBAVFILTER_VERSION_MICRO 100
|
||||
|
||||
#define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
|
||||
LIBAVFILTER_VERSION_MINOR, \
|
||||
LIBAVFILTER_VERSION_MICRO)
|
||||
#define LIBAVFILTER_VERSION AV_VERSION(LIBAVFILTER_VERSION_MAJOR, \
|
||||
LIBAVFILTER_VERSION_MINOR, \
|
||||
LIBAVFILTER_VERSION_MICRO)
|
||||
#define LIBAVFILTER_BUILD LIBAVFILTER_VERSION_INT
|
||||
|
||||
#define LIBAVFILTER_IDENT "Lavfi" AV_STRINGIFY(LIBAVFILTER_VERSION)
|
||||
|
||||
/**
|
||||
* FF_API_* defines may be placed below to indicate public API that will be
|
||||
* dropped at a future version bump. The defines themselves are not part of
|
||||
* the public API and may change, break or disappear at any time.
|
||||
*/
|
||||
|
||||
#ifndef FF_API_OLD_FILTER_OPTS_ERROR
|
||||
#define FF_API_OLD_FILTER_OPTS_ERROR (LIBAVFILTER_VERSION_MAJOR < 8)
|
||||
#endif
|
||||
#ifndef FF_API_LAVR_OPTS
|
||||
#define FF_API_LAVR_OPTS (LIBAVFILTER_VERSION_MAJOR < 8)
|
||||
#endif
|
||||
#ifndef FF_API_FILTER_GET_SET
|
||||
#define FF_API_FILTER_GET_SET (LIBAVFILTER_VERSION_MAJOR < 8)
|
||||
#endif
|
||||
#ifndef FF_API_NEXT
|
||||
#define FF_API_NEXT (LIBAVFILTER_VERSION_MAJOR < 8)
|
||||
#endif
|
||||
|
||||
#endif /* AVFILTER_VERSION_H */
|
||||
@@ -0,0 +1,3085 @@
|
||||
/*
|
||||
* copyright (c) 2001 Fabrice Bellard
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef AVFORMAT_AVFORMAT_H
|
||||
#define AVFORMAT_AVFORMAT_H
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @ingroup libavf
|
||||
* Main libavformat public API header
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup libavf libavformat
|
||||
* I/O and Muxing/Demuxing Library
|
||||
*
|
||||
* Libavformat (lavf) is a library for dealing with various media container
|
||||
* formats. Its main two purposes are demuxing - i.e. splitting a media file
|
||||
* into component streams, and the reverse process of muxing - writing supplied
|
||||
* data in a specified container format. It also has an @ref lavf_io
|
||||
* "I/O module" which supports a number of protocols for accessing the data (e.g.
|
||||
* file, tcp, http and others). Before using lavf, you need to call
|
||||
* av_register_all() to register all compiled muxers, demuxers and protocols.
|
||||
* Unless you are absolutely sure you won't use libavformat's network
|
||||
* capabilities, you should also call avformat_network_init().
|
||||
*
|
||||
* A supported input format is described by an AVInputFormat struct, conversely
|
||||
* an output format is described by AVOutputFormat. You can iterate over all
|
||||
* registered input/output formats using the av_iformat_next() /
|
||||
* av_oformat_next() functions. The protocols layer is not part of the public
|
||||
* API, so you can only get the names of supported protocols with the
|
||||
* avio_enum_protocols() function.
|
||||
*
|
||||
* Main lavf structure used for both muxing and demuxing is AVFormatContext,
|
||||
* which exports all information about the file being read or written. As with
|
||||
* most Libavformat structures, its size is not part of public ABI, so it cannot be
|
||||
* allocated on stack or directly with av_malloc(). To create an
|
||||
* AVFormatContext, use avformat_alloc_context() (some functions, like
|
||||
* avformat_open_input() might do that for you).
|
||||
*
|
||||
* Most importantly an AVFormatContext contains:
|
||||
* @li the @ref AVFormatContext.iformat "input" or @ref AVFormatContext.oformat
|
||||
* "output" format. It is either autodetected or set by user for input;
|
||||
* always set by user for output.
|
||||
* @li an @ref AVFormatContext.streams "array" of AVStreams, which describe all
|
||||
* elementary streams stored in the file. AVStreams are typically referred to
|
||||
* using their index in this array.
|
||||
* @li an @ref AVFormatContext.pb "I/O context". It is either opened by lavf or
|
||||
* set by user for input, always set by user for output (unless you are dealing
|
||||
* with an AVFMT_NOFILE format).
|
||||
*
|
||||
* @section lavf_options Passing options to (de)muxers
|
||||
* It is possible to configure lavf muxers and demuxers using the @ref avoptions
|
||||
* mechanism. Generic (format-independent) libavformat options are provided by
|
||||
* AVFormatContext, they can be examined from a user program by calling
|
||||
* av_opt_next() / av_opt_find() on an allocated AVFormatContext (or its AVClass
|
||||
* from avformat_get_class()). Private (format-specific) options are provided by
|
||||
* AVFormatContext.priv_data if and only if AVInputFormat.priv_class /
|
||||
* AVOutputFormat.priv_class of the corresponding format struct is non-NULL.
|
||||
* Further options may be provided by the @ref AVFormatContext.pb "I/O context",
|
||||
* if its AVClass is non-NULL, and the protocols layer. See the discussion on
|
||||
* nesting in @ref avoptions documentation to learn how to access those.
|
||||
*
|
||||
* @section urls
|
||||
* URL strings in libavformat are made of a scheme/protocol, a ':', and a
|
||||
* scheme specific string. URLs without a scheme and ':' used for local files
|
||||
* are supported but deprecated. "file:" should be used for local files.
|
||||
*
|
||||
* It is important that the scheme string is not taken from untrusted
|
||||
* sources without checks.
|
||||
*
|
||||
* Note that some schemes/protocols are quite powerful, allowing access to
|
||||
* both local and remote files, parts of them, concatenations of them, local
|
||||
* audio and video devices and so on.
|
||||
*
|
||||
* @{
|
||||
*
|
||||
* @defgroup lavf_decoding Demuxing
|
||||
* @{
|
||||
* Demuxers read a media file and split it into chunks of data (@em packets). A
|
||||
* @ref AVPacket "packet" contains one or more encoded frames which belongs to a
|
||||
* single elementary stream. In the lavf API this process is represented by the
|
||||
* avformat_open_input() function for opening a file, av_read_frame() for
|
||||
* reading a single packet and finally avformat_close_input(), which does the
|
||||
* cleanup.
|
||||
*
|
||||
* @section lavf_decoding_open Opening a media file
|
||||
* The minimum information required to open a file is its URL, which
|
||||
* is passed to avformat_open_input(), as in the following code:
|
||||
* @code
|
||||
* const char *url = "file:in.mp3";
|
||||
* AVFormatContext *s = NULL;
|
||||
* int ret = avformat_open_input(&s, url, NULL, NULL);
|
||||
* if (ret < 0)
|
||||
* abort();
|
||||
* @endcode
|
||||
* The above code attempts to allocate an AVFormatContext, open the
|
||||
* specified file (autodetecting the format) and read the header, exporting the
|
||||
* information stored there into s. Some formats do not have a header or do not
|
||||
* store enough information there, so it is recommended that you call the
|
||||
* avformat_find_stream_info() function which tries to read and decode a few
|
||||
* frames to find missing information.
|
||||
*
|
||||
* In some cases you might want to preallocate an AVFormatContext yourself with
|
||||
* avformat_alloc_context() and do some tweaking on it before passing it to
|
||||
* avformat_open_input(). One such case is when you want to use custom functions
|
||||
* for reading input data instead of lavf internal I/O layer.
|
||||
* To do that, create your own AVIOContext with avio_alloc_context(), passing
|
||||
* your reading callbacks to it. Then set the @em pb field of your
|
||||
* AVFormatContext to newly created AVIOContext.
|
||||
*
|
||||
* Since the format of the opened file is in general not known until after
|
||||
* avformat_open_input() has returned, it is not possible to set demuxer private
|
||||
* options on a preallocated context. Instead, the options should be passed to
|
||||
* avformat_open_input() wrapped in an AVDictionary:
|
||||
* @code
|
||||
* AVDictionary *options = NULL;
|
||||
* av_dict_set(&options, "video_size", "640x480", 0);
|
||||
* av_dict_set(&options, "pixel_format", "rgb24", 0);
|
||||
*
|
||||
* if (avformat_open_input(&s, url, NULL, &options) < 0)
|
||||
* abort();
|
||||
* av_dict_free(&options);
|
||||
* @endcode
|
||||
* This code passes the private options 'video_size' and 'pixel_format' to the
|
||||
* demuxer. They would be necessary for e.g. the rawvideo demuxer, since it
|
||||
* cannot know how to interpret raw video data otherwise. If the format turns
|
||||
* out to be something different than raw video, those options will not be
|
||||
* recognized by the demuxer and therefore will not be applied. Such unrecognized
|
||||
* options are then returned in the options dictionary (recognized options are
|
||||
* consumed). The calling program can handle such unrecognized options as it
|
||||
* wishes, e.g.
|
||||
* @code
|
||||
* AVDictionaryEntry *e;
|
||||
* if (e = av_dict_get(options, "", NULL, AV_DICT_IGNORE_SUFFIX)) {
|
||||
* fprintf(stderr, "Option %s not recognized by the demuxer.\n", e->key);
|
||||
* abort();
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
* After you have finished reading the file, you must close it with
|
||||
* avformat_close_input(). It will free everything associated with the file.
|
||||
*
|
||||
* @section lavf_decoding_read Reading from an opened file
|
||||
* Reading data from an opened AVFormatContext is done by repeatedly calling
|
||||
* av_read_frame() on it. Each call, if successful, will return an AVPacket
|
||||
* containing encoded data for one AVStream, identified by
|
||||
* AVPacket.stream_index. This packet may be passed straight into the libavcodec
|
||||
* decoding functions avcodec_send_packet() or avcodec_decode_subtitle2() if the
|
||||
* caller wishes to decode the data.
|
||||
*
|
||||
* AVPacket.pts, AVPacket.dts and AVPacket.duration timing information will be
|
||||
* set if known. They may also be unset (i.e. AV_NOPTS_VALUE for
|
||||
* pts/dts, 0 for duration) if the stream does not provide them. The timing
|
||||
* information will be in AVStream.time_base units, i.e. it has to be
|
||||
* multiplied by the timebase to convert them to seconds.
|
||||
*
|
||||
* If AVPacket.buf is set on the returned packet, then the packet is
|
||||
* allocated dynamically and the user may keep it indefinitely.
|
||||
* Otherwise, if AVPacket.buf is NULL, the packet data is backed by a
|
||||
* static storage somewhere inside the demuxer and the packet is only valid
|
||||
* until the next av_read_frame() call or closing the file. If the caller
|
||||
* requires a longer lifetime, av_dup_packet() will make an av_malloc()ed copy
|
||||
* of it.
|
||||
* In both cases, the packet must be freed with av_packet_unref() when it is no
|
||||
* longer needed.
|
||||
*
|
||||
* @section lavf_decoding_seek Seeking
|
||||
* @}
|
||||
*
|
||||
* @defgroup lavf_encoding Muxing
|
||||
* @{
|
||||
* Muxers take encoded data in the form of @ref AVPacket "AVPackets" and write
|
||||
* it into files or other output bytestreams in the specified container format.
|
||||
*
|
||||
* The main API functions for muxing are avformat_write_header() for writing the
|
||||
* file header, av_write_frame() / av_interleaved_write_frame() for writing the
|
||||
* packets and av_write_trailer() for finalizing the file.
|
||||
*
|
||||
* At the beginning of the muxing process, the caller must first call
|
||||
* avformat_alloc_context() to create a muxing context. The caller then sets up
|
||||
* the muxer by filling the various fields in this context:
|
||||
*
|
||||
* - The @ref AVFormatContext.oformat "oformat" field must be set to select the
|
||||
* muxer that will be used.
|
||||
* - Unless the format is of the AVFMT_NOFILE type, the @ref AVFormatContext.pb
|
||||
* "pb" field must be set to an opened IO context, either returned from
|
||||
* avio_open2() or a custom one.
|
||||
* - Unless the format is of the AVFMT_NOSTREAMS type, at least one stream must
|
||||
* be created with the avformat_new_stream() function. The caller should fill
|
||||
* the @ref AVStream.codecpar "stream codec parameters" information, such as the
|
||||
* codec @ref AVCodecParameters.codec_type "type", @ref AVCodecParameters.codec_id
|
||||
* "id" and other parameters (e.g. width / height, the pixel or sample format,
|
||||
* etc.) as known. The @ref AVStream.time_base "stream timebase" should
|
||||
* be set to the timebase that the caller desires to use for this stream (note
|
||||
* that the timebase actually used by the muxer can be different, as will be
|
||||
* described later).
|
||||
* - It is advised to manually initialize only the relevant fields in
|
||||
* AVCodecParameters, rather than using @ref avcodec_parameters_copy() during
|
||||
* remuxing: there is no guarantee that the codec context values remain valid
|
||||
* for both input and output format contexts.
|
||||
* - The caller may fill in additional information, such as @ref
|
||||
* AVFormatContext.metadata "global" or @ref AVStream.metadata "per-stream"
|
||||
* metadata, @ref AVFormatContext.chapters "chapters", @ref
|
||||
* AVFormatContext.programs "programs", etc. as described in the
|
||||
* AVFormatContext documentation. Whether such information will actually be
|
||||
* stored in the output depends on what the container format and the muxer
|
||||
* support.
|
||||
*
|
||||
* When the muxing context is fully set up, the caller must call
|
||||
* avformat_write_header() to initialize the muxer internals and write the file
|
||||
* header. Whether anything actually is written to the IO context at this step
|
||||
* depends on the muxer, but this function must always be called. Any muxer
|
||||
* private options must be passed in the options parameter to this function.
|
||||
*
|
||||
* The data is then sent to the muxer by repeatedly calling av_write_frame() or
|
||||
* av_interleaved_write_frame() (consult those functions' documentation for
|
||||
* discussion on the difference between them; only one of them may be used with
|
||||
* a single muxing context, they should not be mixed). Do note that the timing
|
||||
* information on the packets sent to the muxer must be in the corresponding
|
||||
* AVStream's timebase. That timebase is set by the muxer (in the
|
||||
* avformat_write_header() step) and may be different from the timebase
|
||||
* requested by the caller.
|
||||
*
|
||||
* Once all the data has been written, the caller must call av_write_trailer()
|
||||
* to flush any buffered packets and finalize the output file, then close the IO
|
||||
* context (if any) and finally free the muxing context with
|
||||
* avformat_free_context().
|
||||
* @}
|
||||
*
|
||||
* @defgroup lavf_io I/O Read/Write
|
||||
* @{
|
||||
* @section lavf_io_dirlist Directory listing
|
||||
* The directory listing API makes it possible to list files on remote servers.
|
||||
*
|
||||
* Some of possible use cases:
|
||||
* - an "open file" dialog to choose files from a remote location,
|
||||
* - a recursive media finder providing a player with an ability to play all
|
||||
* files from a given directory.
|
||||
*
|
||||
* @subsection lavf_io_dirlist_open Opening a directory
|
||||
* At first, a directory needs to be opened by calling avio_open_dir()
|
||||
* supplied with a URL and, optionally, ::AVDictionary containing
|
||||
* protocol-specific parameters. The function returns zero or positive
|
||||
* integer and allocates AVIODirContext on success.
|
||||
*
|
||||
* @code
|
||||
* AVIODirContext *ctx = NULL;
|
||||
* if (avio_open_dir(&ctx, "smb://example.com/some_dir", NULL) < 0) {
|
||||
* fprintf(stderr, "Cannot open directory.\n");
|
||||
* abort();
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
* This code tries to open a sample directory using smb protocol without
|
||||
* any additional parameters.
|
||||
*
|
||||
* @subsection lavf_io_dirlist_read Reading entries
|
||||
* Each directory's entry (i.e. file, another directory, anything else
|
||||
* within ::AVIODirEntryType) is represented by AVIODirEntry.
|
||||
* Reading consecutive entries from an opened AVIODirContext is done by
|
||||
* repeatedly calling avio_read_dir() on it. Each call returns zero or
|
||||
* positive integer if successful. Reading can be stopped right after the
|
||||
* NULL entry has been read -- it means there are no entries left to be
|
||||
* read. The following code reads all entries from a directory associated
|
||||
* with ctx and prints their names to standard output.
|
||||
* @code
|
||||
* AVIODirEntry *entry = NULL;
|
||||
* for (;;) {
|
||||
* if (avio_read_dir(ctx, &entry) < 0) {
|
||||
* fprintf(stderr, "Cannot list directory.\n");
|
||||
* abort();
|
||||
* }
|
||||
* if (!entry)
|
||||
* break;
|
||||
* printf("%s\n", entry->name);
|
||||
* avio_free_directory_entry(&entry);
|
||||
* }
|
||||
* @endcode
|
||||
* @}
|
||||
*
|
||||
* @defgroup lavf_codec Demuxers
|
||||
* @{
|
||||
* @defgroup lavf_codec_native Native Demuxers
|
||||
* @{
|
||||
* @}
|
||||
* @defgroup lavf_codec_wrappers External library wrappers
|
||||
* @{
|
||||
* @}
|
||||
* @}
|
||||
* @defgroup lavf_protos I/O Protocols
|
||||
* @{
|
||||
* @}
|
||||
* @defgroup lavf_internal Internal
|
||||
* @{
|
||||
* @}
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <time.h>
|
||||
#include <stdio.h> /* FILE */
|
||||
#include "libavcodec/avcodec.h"
|
||||
#include "libavutil/dict.h"
|
||||
#include "libavutil/log.h"
|
||||
|
||||
#include "avio.h"
|
||||
#include "libavformat/version.h"
|
||||
|
||||
struct AVFormatContext;
|
||||
|
||||
struct AVDeviceInfoList;
|
||||
struct AVDeviceCapabilitiesQuery;
|
||||
|
||||
/**
|
||||
* @defgroup metadata_api Public Metadata API
|
||||
* @{
|
||||
* @ingroup libavf
|
||||
* The metadata API allows libavformat to export metadata tags to a client
|
||||
* application when demuxing. Conversely it allows a client application to
|
||||
* set metadata when muxing.
|
||||
*
|
||||
* Metadata is exported or set as pairs of key/value strings in the 'metadata'
|
||||
* fields of the AVFormatContext, AVStream, AVChapter and AVProgram structs
|
||||
* using the @ref lavu_dict "AVDictionary" API. Like all strings in FFmpeg,
|
||||
* metadata is assumed to be UTF-8 encoded Unicode. Note that metadata
|
||||
* exported by demuxers isn't checked to be valid UTF-8 in most cases.
|
||||
*
|
||||
* Important concepts to keep in mind:
|
||||
* - Keys are unique; there can never be 2 tags with the same key. This is
|
||||
* also meant semantically, i.e., a demuxer should not knowingly produce
|
||||
* several keys that are literally different but semantically identical.
|
||||
* E.g., key=Author5, key=Author6. In this example, all authors must be
|
||||
* placed in the same tag.
|
||||
* - Metadata is flat, not hierarchical; there are no subtags. If you
|
||||
* want to store, e.g., the email address of the child of producer Alice
|
||||
* and actor Bob, that could have key=alice_and_bobs_childs_email_address.
|
||||
* - Several modifiers can be applied to the tag name. This is done by
|
||||
* appending a dash character ('-') and the modifier name in the order
|
||||
* they appear in the list below -- e.g. foo-eng-sort, not foo-sort-eng.
|
||||
* - language -- a tag whose value is localized for a particular language
|
||||
* is appended with the ISO 639-2/B 3-letter language code.
|
||||
* For example: Author-ger=Michael, Author-eng=Mike
|
||||
* The original/default language is in the unqualified "Author" tag.
|
||||
* A demuxer should set a default if it sets any translated tag.
|
||||
* - sorting -- a modified version of a tag that should be used for
|
||||
* sorting will have '-sort' appended. E.g. artist="The Beatles",
|
||||
* artist-sort="Beatles, The".
|
||||
* - Some protocols and demuxers support metadata updates. After a successful
|
||||
* call to av_read_packet(), AVFormatContext.event_flags or AVStream.event_flags
|
||||
* will be updated to indicate if metadata changed. In order to detect metadata
|
||||
* changes on a stream, you need to loop through all streams in the AVFormatContext
|
||||
* and check their individual event_flags.
|
||||
*
|
||||
* - Demuxers attempt to export metadata in a generic format, however tags
|
||||
* with no generic equivalents are left as they are stored in the container.
|
||||
* Follows a list of generic tag names:
|
||||
*
|
||||
@verbatim
|
||||
album -- name of the set this work belongs to
|
||||
album_artist -- main creator of the set/album, if different from artist.
|
||||
e.g. "Various Artists" for compilation albums.
|
||||
artist -- main creator of the work
|
||||
comment -- any additional description of the file.
|
||||
composer -- who composed the work, if different from artist.
|
||||
copyright -- name of copyright holder.
|
||||
creation_time-- date when the file was created, preferably in ISO 8601.
|
||||
date -- date when the work was created, preferably in ISO 8601.
|
||||
disc -- number of a subset, e.g. disc in a multi-disc collection.
|
||||
encoder -- name/settings of the software/hardware that produced the file.
|
||||
encoded_by -- person/group who created the file.
|
||||
filename -- original name of the file.
|
||||
genre -- <self-evident>.
|
||||
language -- main language in which the work is performed, preferably
|
||||
in ISO 639-2 format. Multiple languages can be specified by
|
||||
separating them with commas.
|
||||
performer -- artist who performed the work, if different from artist.
|
||||
E.g for "Also sprach Zarathustra", artist would be "Richard
|
||||
Strauss" and performer "London Philharmonic Orchestra".
|
||||
publisher -- name of the label/publisher.
|
||||
service_name -- name of the service in broadcasting (channel name).
|
||||
service_provider -- name of the service provider in broadcasting.
|
||||
title -- name of the work.
|
||||
track -- number of this work in the set, can be in form current/total.
|
||||
variant_bitrate -- the total bitrate of the bitrate variant that the current stream is part of
|
||||
@endverbatim
|
||||
*
|
||||
* Look in the examples section for an application example how to use the Metadata API.
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* packet functions */
|
||||
|
||||
|
||||
/**
|
||||
* Allocate and read the payload of a packet and initialize its
|
||||
* fields with default values.
|
||||
*
|
||||
* @param s associated IO context
|
||||
* @param pkt packet
|
||||
* @param size desired payload size
|
||||
* @return >0 (read size) if OK, AVERROR_xxx otherwise
|
||||
*/
|
||||
int av_get_packet(AVIOContext *s, AVPacket *pkt, int size);
|
||||
|
||||
|
||||
/**
|
||||
* Read data and append it to the current content of the AVPacket.
|
||||
* If pkt->size is 0 this is identical to av_get_packet.
|
||||
* Note that this uses av_grow_packet and thus involves a realloc
|
||||
* which is inefficient. Thus this function should only be used
|
||||
* when there is no reasonable way to know (an upper bound of)
|
||||
* the final size.
|
||||
*
|
||||
* @param s associated IO context
|
||||
* @param pkt packet
|
||||
* @param size amount of data to read
|
||||
* @return >0 (read size) if OK, AVERROR_xxx otherwise, previous data
|
||||
* will not be lost even if an error occurs.
|
||||
*/
|
||||
int av_append_packet(AVIOContext *s, AVPacket *pkt, int size);
|
||||
|
||||
/*************************************************/
|
||||
/* input/output formats */
|
||||
|
||||
struct AVCodecTag;
|
||||
|
||||
/**
|
||||
* This structure contains the data a format has to probe a file.
|
||||
*/
|
||||
typedef struct AVProbeData {
|
||||
const char *filename;
|
||||
unsigned char *buf; /**< Buffer must have AVPROBE_PADDING_SIZE of extra allocated bytes filled with zero. */
|
||||
int buf_size; /**< Size of buf except extra allocated bytes */
|
||||
const char *mime_type; /**< mime_type, when known. */
|
||||
} AVProbeData;
|
||||
|
||||
#define AVPROBE_SCORE_RETRY (AVPROBE_SCORE_MAX/4)
|
||||
#define AVPROBE_SCORE_STREAM_RETRY (AVPROBE_SCORE_MAX/4-1)
|
||||
|
||||
#define AVPROBE_SCORE_EXTENSION 50 ///< score for file extension
|
||||
#define AVPROBE_SCORE_MIME 75 ///< score for file mime type
|
||||
#define AVPROBE_SCORE_MAX 100 ///< maximum score
|
||||
|
||||
#define AVPROBE_PADDING_SIZE 32 ///< extra allocated bytes at the end of the probe buffer
|
||||
|
||||
/// Demuxer will use avio_open, no opened file should be provided by the caller.
|
||||
#define AVFMT_NOFILE 0x0001
|
||||
#define AVFMT_NEEDNUMBER 0x0002 /**< Needs '%d' in filename. */
|
||||
#define AVFMT_SHOW_IDS 0x0008 /**< Show format stream IDs numbers. */
|
||||
#define AVFMT_GLOBALHEADER 0x0040 /**< Format wants global header. */
|
||||
#define AVFMT_NOTIMESTAMPS 0x0080 /**< Format does not need / have any timestamps. */
|
||||
#define AVFMT_GENERIC_INDEX 0x0100 /**< Use generic index building code. */
|
||||
#define AVFMT_TS_DISCONT 0x0200 /**< Format allows timestamp discontinuities. Note, muxers always require valid (monotone) timestamps */
|
||||
#define AVFMT_VARIABLE_FPS 0x0400 /**< Format allows variable fps. */
|
||||
#define AVFMT_NODIMENSIONS 0x0800 /**< Format does not need width/height */
|
||||
#define AVFMT_NOSTREAMS 0x1000 /**< Format does not require any streams */
|
||||
#define AVFMT_NOBINSEARCH 0x2000 /**< Format does not allow to fall back on binary search via read_timestamp */
|
||||
#define AVFMT_NOGENSEARCH 0x4000 /**< Format does not allow to fall back on generic search */
|
||||
#define AVFMT_NO_BYTE_SEEK 0x8000 /**< Format does not allow seeking by bytes */
|
||||
#define AVFMT_ALLOW_FLUSH 0x10000 /**< Format allows flushing. If not set, the muxer will not receive a NULL packet in the write_packet function. */
|
||||
#define AVFMT_TS_NONSTRICT 0x20000 /**< Format does not require strictly
|
||||
increasing timestamps, but they must
|
||||
still be monotonic */
|
||||
#define AVFMT_TS_NEGATIVE 0x40000 /**< Format allows muxing negative
|
||||
timestamps. If not set the timestamp
|
||||
will be shifted in av_write_frame and
|
||||
av_interleaved_write_frame so they
|
||||
start from 0.
|
||||
The user or muxer can override this through
|
||||
AVFormatContext.avoid_negative_ts
|
||||
*/
|
||||
|
||||
#define AVFMT_SEEK_TO_PTS 0x4000000 /**< Seeking is based on PTS */
|
||||
|
||||
/**
|
||||
* @addtogroup lavf_encoding
|
||||
* @{
|
||||
*/
|
||||
typedef struct AVOutputFormat {
|
||||
const char *name;
|
||||
/**
|
||||
* Descriptive name for the format, meant to be more human-readable
|
||||
* than name. You should use the NULL_IF_CONFIG_SMALL() macro
|
||||
* to define it.
|
||||
*/
|
||||
const char *long_name;
|
||||
const char *mime_type;
|
||||
const char *extensions; /**< comma-separated filename extensions */
|
||||
/* output support */
|
||||
enum AVCodecID audio_codec; /**< default audio codec */
|
||||
enum AVCodecID video_codec; /**< default video codec */
|
||||
enum AVCodecID subtitle_codec; /**< default subtitle codec */
|
||||
/**
|
||||
* can use flags: AVFMT_NOFILE, AVFMT_NEEDNUMBER,
|
||||
* AVFMT_GLOBALHEADER, AVFMT_NOTIMESTAMPS, AVFMT_VARIABLE_FPS,
|
||||
* AVFMT_NODIMENSIONS, AVFMT_NOSTREAMS, AVFMT_ALLOW_FLUSH,
|
||||
* AVFMT_TS_NONSTRICT, AVFMT_TS_NEGATIVE
|
||||
*/
|
||||
int flags;
|
||||
|
||||
/**
|
||||
* List of supported codec_id-codec_tag pairs, ordered by "better
|
||||
* choice first". The arrays are all terminated by AV_CODEC_ID_NONE.
|
||||
*/
|
||||
const struct AVCodecTag * const *codec_tag;
|
||||
|
||||
|
||||
const AVClass *priv_class; ///< AVClass for the private context
|
||||
|
||||
/*****************************************************************
|
||||
* No fields below this line are part of the public API. They
|
||||
* may not be used outside of libavformat and can be changed and
|
||||
* removed at will.
|
||||
* New public fields should be added right above.
|
||||
*****************************************************************
|
||||
*/
|
||||
struct AVOutputFormat *next;
|
||||
/**
|
||||
* size of private data so that it can be allocated in the wrapper
|
||||
*/
|
||||
int priv_data_size;
|
||||
|
||||
int (*write_header)(struct AVFormatContext *);
|
||||
/**
|
||||
* Write a packet. If AVFMT_ALLOW_FLUSH is set in flags,
|
||||
* pkt can be NULL in order to flush data buffered in the muxer.
|
||||
* When flushing, return 0 if there still is more data to flush,
|
||||
* or 1 if everything was flushed and there is no more buffered
|
||||
* data.
|
||||
*/
|
||||
int (*write_packet)(struct AVFormatContext *, AVPacket *pkt);
|
||||
int (*write_trailer)(struct AVFormatContext *);
|
||||
/**
|
||||
* Currently only used to set pixel format if not YUV420P.
|
||||
*/
|
||||
int (*interleave_packet)(struct AVFormatContext *, AVPacket *out,
|
||||
AVPacket *in, int flush);
|
||||
/**
|
||||
* Test if the given codec can be stored in this container.
|
||||
*
|
||||
* @return 1 if the codec is supported, 0 if it is not.
|
||||
* A negative number if unknown.
|
||||
* MKTAG('A', 'P', 'I', 'C') if the codec is only supported as AV_DISPOSITION_ATTACHED_PIC
|
||||
*/
|
||||
int (*query_codec)(enum AVCodecID id, int std_compliance);
|
||||
|
||||
void (*get_output_timestamp)(struct AVFormatContext *s, int stream,
|
||||
int64_t *dts, int64_t *wall);
|
||||
/**
|
||||
* Allows sending messages from application to device.
|
||||
*/
|
||||
int (*control_message)(struct AVFormatContext *s, int type,
|
||||
void *data, size_t data_size);
|
||||
|
||||
/**
|
||||
* Write an uncoded AVFrame.
|
||||
*
|
||||
* See av_write_uncoded_frame() for details.
|
||||
*
|
||||
* The library will free *frame afterwards, but the muxer can prevent it
|
||||
* by setting the pointer to NULL.
|
||||
*/
|
||||
int (*write_uncoded_frame)(struct AVFormatContext *, int stream_index,
|
||||
AVFrame **frame, unsigned flags);
|
||||
/**
|
||||
* Returns device list with it properties.
|
||||
* @see avdevice_list_devices() for more details.
|
||||
*/
|
||||
int (*get_device_list)(struct AVFormatContext *s, struct AVDeviceInfoList *device_list);
|
||||
/**
|
||||
* Initialize device capabilities submodule.
|
||||
* @see avdevice_capabilities_create() for more details.
|
||||
*/
|
||||
int (*create_device_capabilities)(struct AVFormatContext *s, struct AVDeviceCapabilitiesQuery *caps);
|
||||
/**
|
||||
* Free device capabilities submodule.
|
||||
* @see avdevice_capabilities_free() for more details.
|
||||
*/
|
||||
int (*free_device_capabilities)(struct AVFormatContext *s, struct AVDeviceCapabilitiesQuery *caps);
|
||||
enum AVCodecID data_codec; /**< default data codec */
|
||||
/**
|
||||
* Initialize format. May allocate data here, and set any AVFormatContext or
|
||||
* AVStream parameters that need to be set before packets are sent.
|
||||
* This method must not write output.
|
||||
*
|
||||
* Return 0 if streams were fully configured, 1 if not, negative AVERROR on failure
|
||||
*
|
||||
* Any allocations made here must be freed in deinit().
|
||||
*/
|
||||
int (*init)(struct AVFormatContext *);
|
||||
/**
|
||||
* Deinitialize format. If present, this is called whenever the muxer is being
|
||||
* destroyed, regardless of whether or not the header has been written.
|
||||
*
|
||||
* If a trailer is being written, this is called after write_trailer().
|
||||
*
|
||||
* This is called if init() fails as well.
|
||||
*/
|
||||
void (*deinit)(struct AVFormatContext *);
|
||||
/**
|
||||
* Set up any necessary bitstream filtering and extract any extra data needed
|
||||
* for the global header.
|
||||
* Return 0 if more packets from this stream must be checked; 1 if not.
|
||||
*/
|
||||
int (*check_bitstream)(struct AVFormatContext *, const AVPacket *pkt);
|
||||
} AVOutputFormat;
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup lavf_decoding
|
||||
* @{
|
||||
*/
|
||||
typedef struct AVInputFormat {
|
||||
/**
|
||||
* A comma separated list of short names for the format. New names
|
||||
* may be appended with a minor bump.
|
||||
*/
|
||||
const char *name;
|
||||
|
||||
/**
|
||||
* Descriptive name for the format, meant to be more human-readable
|
||||
* than name. You should use the NULL_IF_CONFIG_SMALL() macro
|
||||
* to define it.
|
||||
*/
|
||||
const char *long_name;
|
||||
|
||||
/**
|
||||
* Can use flags: AVFMT_NOFILE, AVFMT_NEEDNUMBER, AVFMT_SHOW_IDS,
|
||||
* AVFMT_GENERIC_INDEX, AVFMT_TS_DISCONT, AVFMT_NOBINSEARCH,
|
||||
* AVFMT_NOGENSEARCH, AVFMT_NO_BYTE_SEEK, AVFMT_SEEK_TO_PTS.
|
||||
*/
|
||||
int flags;
|
||||
|
||||
/**
|
||||
* If extensions are defined, then no probe is done. You should
|
||||
* usually not use extension format guessing because it is not
|
||||
* reliable enough
|
||||
*/
|
||||
const char *extensions;
|
||||
|
||||
const struct AVCodecTag * const *codec_tag;
|
||||
|
||||
const AVClass *priv_class; ///< AVClass for the private context
|
||||
|
||||
/**
|
||||
* Comma-separated list of mime types.
|
||||
* It is used check for matching mime types while probing.
|
||||
* @see av_probe_input_format2
|
||||
*/
|
||||
const char *mime_type;
|
||||
|
||||
/*****************************************************************
|
||||
* No fields below this line are part of the public API. They
|
||||
* may not be used outside of libavformat and can be changed and
|
||||
* removed at will.
|
||||
* New public fields should be added right above.
|
||||
*****************************************************************
|
||||
*/
|
||||
struct AVInputFormat *next;
|
||||
|
||||
/**
|
||||
* Raw demuxers store their codec ID here.
|
||||
*/
|
||||
int raw_codec_id;
|
||||
|
||||
/**
|
||||
* Size of private data so that it can be allocated in the wrapper.
|
||||
*/
|
||||
int priv_data_size;
|
||||
|
||||
/**
|
||||
* Tell if a given file has a chance of being parsed as this format.
|
||||
* The buffer provided is guaranteed to be AVPROBE_PADDING_SIZE bytes
|
||||
* big so you do not have to check for that unless you need more.
|
||||
*/
|
||||
int (*read_probe)(AVProbeData *);
|
||||
|
||||
/**
|
||||
* Read the format header and initialize the AVFormatContext
|
||||
* structure. Return 0 if OK. 'avformat_new_stream' should be
|
||||
* called to create new streams.
|
||||
*/
|
||||
int (*read_header)(struct AVFormatContext *);
|
||||
|
||||
/**
|
||||
* Read one packet and put it in 'pkt'. pts and flags are also
|
||||
* set. 'avformat_new_stream' can be called only if the flag
|
||||
* AVFMTCTX_NOHEADER is used and only in the calling thread (not in a
|
||||
* background thread).
|
||||
* @return 0 on success, < 0 on error.
|
||||
* When returning an error, pkt must not have been allocated
|
||||
* or must be freed before returning
|
||||
*/
|
||||
int (*read_packet)(struct AVFormatContext *, AVPacket *pkt);
|
||||
|
||||
/**
|
||||
* Close the stream. The AVFormatContext and AVStreams are not
|
||||
* freed by this function
|
||||
*/
|
||||
int (*read_close)(struct AVFormatContext *);
|
||||
|
||||
/**
|
||||
* Seek to a given timestamp relative to the frames in
|
||||
* stream component stream_index.
|
||||
* @param stream_index Must not be -1.
|
||||
* @param flags Selects which direction should be preferred if no exact
|
||||
* match is available.
|
||||
* @return >= 0 on success (but not necessarily the new offset)
|
||||
*/
|
||||
int (*read_seek)(struct AVFormatContext *,
|
||||
int stream_index, int64_t timestamp, int flags);
|
||||
|
||||
/**
|
||||
* Get the next timestamp in stream[stream_index].time_base units.
|
||||
* @return the timestamp or AV_NOPTS_VALUE if an error occurred
|
||||
*/
|
||||
int64_t (*read_timestamp)(struct AVFormatContext *s, int stream_index,
|
||||
int64_t *pos, int64_t pos_limit);
|
||||
|
||||
/**
|
||||
* Start/resume playing - only meaningful if using a network-based format
|
||||
* (RTSP).
|
||||
*/
|
||||
int (*read_play)(struct AVFormatContext *);
|
||||
|
||||
/**
|
||||
* Pause playing - only meaningful if using a network-based format
|
||||
* (RTSP).
|
||||
*/
|
||||
int (*read_pause)(struct AVFormatContext *);
|
||||
|
||||
/**
|
||||
* Seek to timestamp ts.
|
||||
* Seeking will be done so that the point from which all active streams
|
||||
* can be presented successfully will be closest to ts and within min/max_ts.
|
||||
* Active streams are all streams that have AVStream.discard < AVDISCARD_ALL.
|
||||
*/
|
||||
int (*read_seek2)(struct AVFormatContext *s, int stream_index, int64_t min_ts, int64_t ts, int64_t max_ts, int flags);
|
||||
|
||||
/**
|
||||
* Returns device list with it properties.
|
||||
* @see avdevice_list_devices() for more details.
|
||||
*/
|
||||
int (*get_device_list)(struct AVFormatContext *s, struct AVDeviceInfoList *device_list);
|
||||
|
||||
/**
|
||||
* Initialize device capabilities submodule.
|
||||
* @see avdevice_capabilities_create() for more details.
|
||||
*/
|
||||
int (*create_device_capabilities)(struct AVFormatContext *s, struct AVDeviceCapabilitiesQuery *caps);
|
||||
|
||||
/**
|
||||
* Free device capabilities submodule.
|
||||
* @see avdevice_capabilities_free() for more details.
|
||||
*/
|
||||
int (*free_device_capabilities)(struct AVFormatContext *s, struct AVDeviceCapabilitiesQuery *caps);
|
||||
} AVInputFormat;
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
enum AVStreamParseType {
|
||||
AVSTREAM_PARSE_NONE,
|
||||
AVSTREAM_PARSE_FULL, /**< full parsing and repack */
|
||||
AVSTREAM_PARSE_HEADERS, /**< Only parse headers, do not repack. */
|
||||
AVSTREAM_PARSE_TIMESTAMPS, /**< full parsing and interpolation of timestamps for frames not starting on a packet boundary */
|
||||
AVSTREAM_PARSE_FULL_ONCE, /**< full parsing and repack of the first frame only, only implemented for H.264 currently */
|
||||
AVSTREAM_PARSE_FULL_RAW, /**< full parsing and repack with timestamp and position generation by parser for raw
|
||||
this assumes that each packet in the file contains no demuxer level headers and
|
||||
just codec level data, otherwise position generation would fail */
|
||||
};
|
||||
|
||||
typedef struct AVIndexEntry {
|
||||
int64_t pos;
|
||||
int64_t timestamp; /**<
|
||||
* Timestamp in AVStream.time_base units, preferably the time from which on correctly decoded frames are available
|
||||
* when seeking to this entry. That means preferable PTS on keyframe based formats.
|
||||
* But demuxers can choose to store a different timestamp, if it is more convenient for the implementation or nothing better
|
||||
* is known
|
||||
*/
|
||||
#define AVINDEX_KEYFRAME 0x0001
|
||||
#define AVINDEX_DISCARD_FRAME 0x0002 /**
|
||||
* Flag is used to indicate which frame should be discarded after decoding.
|
||||
*/
|
||||
int flags:2;
|
||||
int size:30; //Yeah, trying to keep the size of this small to reduce memory requirements (it is 24 vs. 32 bytes due to possible 8-byte alignment).
|
||||
int min_distance; /**< Minimum distance between this and the previous keyframe, used to avoid unneeded searching. */
|
||||
} AVIndexEntry;
|
||||
|
||||
#define AV_DISPOSITION_DEFAULT 0x0001
|
||||
#define AV_DISPOSITION_DUB 0x0002
|
||||
#define AV_DISPOSITION_ORIGINAL 0x0004
|
||||
#define AV_DISPOSITION_COMMENT 0x0008
|
||||
#define AV_DISPOSITION_LYRICS 0x0010
|
||||
#define AV_DISPOSITION_KARAOKE 0x0020
|
||||
|
||||
/**
|
||||
* Track should be used during playback by default.
|
||||
* Useful for subtitle track that should be displayed
|
||||
* even when user did not explicitly ask for subtitles.
|
||||
*/
|
||||
#define AV_DISPOSITION_FORCED 0x0040
|
||||
#define AV_DISPOSITION_HEARING_IMPAIRED 0x0080 /**< stream for hearing impaired audiences */
|
||||
#define AV_DISPOSITION_VISUAL_IMPAIRED 0x0100 /**< stream for visual impaired audiences */
|
||||
#define AV_DISPOSITION_CLEAN_EFFECTS 0x0200 /**< stream without voice */
|
||||
/**
|
||||
* The stream is stored in the file as an attached picture/"cover art" (e.g.
|
||||
* APIC frame in ID3v2). The first (usually only) packet associated with it
|
||||
* will be returned among the first few packets read from the file unless
|
||||
* seeking takes place. It can also be accessed at any time in
|
||||
* AVStream.attached_pic.
|
||||
*/
|
||||
#define AV_DISPOSITION_ATTACHED_PIC 0x0400
|
||||
/**
|
||||
* The stream is sparse, and contains thumbnail images, often corresponding
|
||||
* to chapter markers. Only ever used with AV_DISPOSITION_ATTACHED_PIC.
|
||||
*/
|
||||
#define AV_DISPOSITION_TIMED_THUMBNAILS 0x0800
|
||||
|
||||
typedef struct AVStreamInternal AVStreamInternal;
|
||||
|
||||
/**
|
||||
* To specify text track kind (different from subtitles default).
|
||||
*/
|
||||
#define AV_DISPOSITION_CAPTIONS 0x10000
|
||||
#define AV_DISPOSITION_DESCRIPTIONS 0x20000
|
||||
#define AV_DISPOSITION_METADATA 0x40000
|
||||
#define AV_DISPOSITION_DEPENDENT 0x80000 ///< dependent audio stream (mix_type=0 in mpegts)
|
||||
#define AV_DISPOSITION_STILL_IMAGE 0x100000 ///< still images in video stream (still_picture_flag=1 in mpegts)
|
||||
|
||||
/**
|
||||
* Options for behavior on timestamp wrap detection.
|
||||
*/
|
||||
#define AV_PTS_WRAP_IGNORE 0 ///< ignore the wrap
|
||||
#define AV_PTS_WRAP_ADD_OFFSET 1 ///< add the format specific offset on wrap detection
|
||||
#define AV_PTS_WRAP_SUB_OFFSET -1 ///< subtract the format specific offset on wrap detection
|
||||
|
||||
/**
|
||||
* Stream structure.
|
||||
* New fields can be added to the end with minor version bumps.
|
||||
* Removal, reordering and changes to existing fields require a major
|
||||
* version bump.
|
||||
* sizeof(AVStream) must not be used outside libav*.
|
||||
*/
|
||||
typedef struct AVStream {
|
||||
int index; /**< stream index in AVFormatContext */
|
||||
/**
|
||||
* Format-specific stream ID.
|
||||
* decoding: set by libavformat
|
||||
* encoding: set by the user, replaced by libavformat if left unset
|
||||
*/
|
||||
int id;
|
||||
#if FF_API_LAVF_AVCTX
|
||||
/**
|
||||
* @deprecated use the codecpar struct instead
|
||||
*/
|
||||
attribute_deprecated
|
||||
AVCodecContext *codec;
|
||||
#endif
|
||||
void *priv_data;
|
||||
|
||||
/**
|
||||
* This is the fundamental unit of time (in seconds) in terms
|
||||
* of which frame timestamps are represented.
|
||||
*
|
||||
* decoding: set by libavformat
|
||||
* encoding: May be set by the caller before avformat_write_header() to
|
||||
* provide a hint to the muxer about the desired timebase. In
|
||||
* avformat_write_header(), the muxer will overwrite this field
|
||||
* with the timebase that will actually be used for the timestamps
|
||||
* written into the file (which may or may not be related to the
|
||||
* user-provided one, depending on the format).
|
||||
*/
|
||||
AVRational time_base;
|
||||
|
||||
/**
|
||||
* Decoding: pts of the first frame of the stream in presentation order, in stream time base.
|
||||
* Only set this if you are absolutely 100% sure that the value you set
|
||||
* it to really is the pts of the first frame.
|
||||
* This may be undefined (AV_NOPTS_VALUE).
|
||||
* @note The ASF header does NOT contain a correct start_time the ASF
|
||||
* demuxer must NOT set this.
|
||||
*/
|
||||
int64_t start_time;
|
||||
|
||||
/**
|
||||
* Decoding: duration of the stream, in stream time base.
|
||||
* If a source file does not specify a duration, but does specify
|
||||
* a bitrate, this value will be estimated from bitrate and file size.
|
||||
*
|
||||
* Encoding: May be set by the caller before avformat_write_header() to
|
||||
* provide a hint to the muxer about the estimated duration.
|
||||
*/
|
||||
int64_t duration;
|
||||
|
||||
int64_t nb_frames; ///< number of frames in this stream if known or 0
|
||||
|
||||
int disposition; /**< AV_DISPOSITION_* bit field */
|
||||
|
||||
enum AVDiscard discard; ///< Selects which packets can be discarded at will and do not need to be demuxed.
|
||||
|
||||
/**
|
||||
* sample aspect ratio (0 if unknown)
|
||||
* - encoding: Set by user.
|
||||
* - decoding: Set by libavformat.
|
||||
*/
|
||||
AVRational sample_aspect_ratio;
|
||||
|
||||
AVDictionary *metadata;
|
||||
|
||||
/**
|
||||
* Average framerate
|
||||
*
|
||||
* - demuxing: May be set by libavformat when creating the stream or in
|
||||
* avformat_find_stream_info().
|
||||
* - muxing: May be set by the caller before avformat_write_header().
|
||||
*/
|
||||
AVRational avg_frame_rate;
|
||||
|
||||
/**
|
||||
* For streams with AV_DISPOSITION_ATTACHED_PIC disposition, this packet
|
||||
* will contain the attached picture.
|
||||
*
|
||||
* decoding: set by libavformat, must not be modified by the caller.
|
||||
* encoding: unused
|
||||
*/
|
||||
AVPacket attached_pic;
|
||||
|
||||
/**
|
||||
* An array of side data that applies to the whole stream (i.e. the
|
||||
* container does not allow it to change between packets).
|
||||
*
|
||||
* There may be no overlap between the side data in this array and side data
|
||||
* in the packets. I.e. a given side data is either exported by the muxer
|
||||
* (demuxing) / set by the caller (muxing) in this array, then it never
|
||||
* appears in the packets, or the side data is exported / sent through
|
||||
* the packets (always in the first packet where the value becomes known or
|
||||
* changes), then it does not appear in this array.
|
||||
*
|
||||
* - demuxing: Set by libavformat when the stream is created.
|
||||
* - muxing: May be set by the caller before avformat_write_header().
|
||||
*
|
||||
* Freed by libavformat in avformat_free_context().
|
||||
*
|
||||
* @see av_format_inject_global_side_data()
|
||||
*/
|
||||
AVPacketSideData *side_data;
|
||||
/**
|
||||
* The number of elements in the AVStream.side_data array.
|
||||
*/
|
||||
int nb_side_data;
|
||||
|
||||
/**
|
||||
* Flags for the user to detect events happening on the stream. Flags must
|
||||
* be cleared by the user once the event has been handled.
|
||||
* A combination of AVSTREAM_EVENT_FLAG_*.
|
||||
*/
|
||||
int event_flags;
|
||||
#define AVSTREAM_EVENT_FLAG_METADATA_UPDATED 0x0001 ///< The call resulted in updated metadata.
|
||||
|
||||
/**
|
||||
* Real base framerate of the stream.
|
||||
* This is the lowest framerate with which all timestamps can be
|
||||
* represented accurately (it is the least common multiple of all
|
||||
* framerates in the stream). Note, this value is just a guess!
|
||||
* For example, if the time base is 1/90000 and all frames have either
|
||||
* approximately 3600 or 1800 timer ticks, then r_frame_rate will be 50/1.
|
||||
*/
|
||||
AVRational r_frame_rate;
|
||||
|
||||
#if FF_API_LAVF_FFSERVER
|
||||
/**
|
||||
* String containing pairs of key and values describing recommended encoder configuration.
|
||||
* Pairs are separated by ','.
|
||||
* Keys are separated from values by '='.
|
||||
*
|
||||
* @deprecated unused
|
||||
*/
|
||||
attribute_deprecated
|
||||
char *recommended_encoder_configuration;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Codec parameters associated with this stream. Allocated and freed by
|
||||
* libavformat in avformat_new_stream() and avformat_free_context()
|
||||
* respectively.
|
||||
*
|
||||
* - demuxing: filled by libavformat on stream creation or in
|
||||
* avformat_find_stream_info()
|
||||
* - muxing: filled by the caller before avformat_write_header()
|
||||
*/
|
||||
AVCodecParameters *codecpar;
|
||||
|
||||
/*****************************************************************
|
||||
* All fields below this line are not part of the public API. They
|
||||
* may not be used outside of libavformat and can be changed and
|
||||
* removed at will.
|
||||
* Internal note: be aware that physically removing these fields
|
||||
* will break ABI. Replace removed fields with dummy fields, and
|
||||
* add new fields to AVStreamInternal.
|
||||
*****************************************************************
|
||||
*/
|
||||
|
||||
#define MAX_STD_TIMEBASES (30*12+30+3+6)
|
||||
/**
|
||||
* Stream information used internally by avformat_find_stream_info()
|
||||
*/
|
||||
struct {
|
||||
int64_t last_dts;
|
||||
int64_t duration_gcd;
|
||||
int duration_count;
|
||||
int64_t rfps_duration_sum;
|
||||
double (*duration_error)[2][MAX_STD_TIMEBASES];
|
||||
int64_t codec_info_duration;
|
||||
int64_t codec_info_duration_fields;
|
||||
int frame_delay_evidence;
|
||||
|
||||
/**
|
||||
* 0 -> decoder has not been searched for yet.
|
||||
* >0 -> decoder found
|
||||
* <0 -> decoder with codec_id == -found_decoder has not been found
|
||||
*/
|
||||
int found_decoder;
|
||||
|
||||
int64_t last_duration;
|
||||
|
||||
/**
|
||||
* Those are used for average framerate estimation.
|
||||
*/
|
||||
int64_t fps_first_dts;
|
||||
int fps_first_dts_idx;
|
||||
int64_t fps_last_dts;
|
||||
int fps_last_dts_idx;
|
||||
|
||||
} *info;
|
||||
|
||||
int pts_wrap_bits; /**< number of bits in pts (used for wrapping control) */
|
||||
|
||||
// Timestamp generation support:
|
||||
/**
|
||||
* Timestamp corresponding to the last dts sync point.
|
||||
*
|
||||
* Initialized when AVCodecParserContext.dts_sync_point >= 0 and
|
||||
* a DTS is received from the underlying container. Otherwise set to
|
||||
* AV_NOPTS_VALUE by default.
|
||||
*/
|
||||
int64_t first_dts;
|
||||
int64_t cur_dts;
|
||||
int64_t last_IP_pts;
|
||||
int last_IP_duration;
|
||||
|
||||
/**
|
||||
* Number of packets to buffer for codec probing
|
||||
*/
|
||||
int probe_packets;
|
||||
|
||||
/**
|
||||
* Number of frames that have been demuxed during avformat_find_stream_info()
|
||||
*/
|
||||
int codec_info_nb_frames;
|
||||
|
||||
/* av_read_frame() support */
|
||||
enum AVStreamParseType need_parsing;
|
||||
struct AVCodecParserContext *parser;
|
||||
|
||||
/**
|
||||
* last packet in packet_buffer for this stream when muxing.
|
||||
*/
|
||||
struct AVPacketList *last_in_packet_buffer;
|
||||
AVProbeData probe_data;
|
||||
#define MAX_REORDER_DELAY 16
|
||||
int64_t pts_buffer[MAX_REORDER_DELAY+1];
|
||||
|
||||
AVIndexEntry *index_entries; /**< Only used if the format does not
|
||||
support seeking natively. */
|
||||
int nb_index_entries;
|
||||
unsigned int index_entries_allocated_size;
|
||||
|
||||
/**
|
||||
* Stream Identifier
|
||||
* This is the MPEG-TS stream identifier +1
|
||||
* 0 means unknown
|
||||
*/
|
||||
int stream_identifier;
|
||||
|
||||
/**
|
||||
* Details of the MPEG-TS program which created this stream.
|
||||
*/
|
||||
int program_num;
|
||||
int pmt_version;
|
||||
int pmt_stream_idx;
|
||||
|
||||
int64_t interleaver_chunk_size;
|
||||
int64_t interleaver_chunk_duration;
|
||||
|
||||
/**
|
||||
* stream probing state
|
||||
* -1 -> probing finished
|
||||
* 0 -> no probing requested
|
||||
* rest -> perform probing with request_probe being the minimum score to accept.
|
||||
* NOT PART OF PUBLIC API
|
||||
*/
|
||||
int request_probe;
|
||||
/**
|
||||
* Indicates that everything up to the next keyframe
|
||||
* should be discarded.
|
||||
*/
|
||||
int skip_to_keyframe;
|
||||
|
||||
/**
|
||||
* Number of samples to skip at the start of the frame decoded from the next packet.
|
||||
*/
|
||||
int skip_samples;
|
||||
|
||||
/**
|
||||
* If not 0, the number of samples that should be skipped from the start of
|
||||
* the stream (the samples are removed from packets with pts==0, which also
|
||||
* assumes negative timestamps do not happen).
|
||||
* Intended for use with formats such as mp3 with ad-hoc gapless audio
|
||||
* support.
|
||||
*/
|
||||
int64_t start_skip_samples;
|
||||
|
||||
/**
|
||||
* If not 0, the first audio sample that should be discarded from the stream.
|
||||
* This is broken by design (needs global sample count), but can't be
|
||||
* avoided for broken by design formats such as mp3 with ad-hoc gapless
|
||||
* audio support.
|
||||
*/
|
||||
int64_t first_discard_sample;
|
||||
|
||||
/**
|
||||
* The sample after last sample that is intended to be discarded after
|
||||
* first_discard_sample. Works on frame boundaries only. Used to prevent
|
||||
* early EOF if the gapless info is broken (considered concatenated mp3s).
|
||||
*/
|
||||
int64_t last_discard_sample;
|
||||
|
||||
/**
|
||||
* Number of internally decoded frames, used internally in libavformat, do not access
|
||||
* its lifetime differs from info which is why it is not in that structure.
|
||||
*/
|
||||
int nb_decoded_frames;
|
||||
|
||||
/**
|
||||
* Timestamp offset added to timestamps before muxing
|
||||
* NOT PART OF PUBLIC API
|
||||
*/
|
||||
int64_t mux_ts_offset;
|
||||
|
||||
/**
|
||||
* Internal data to check for wrapping of the time stamp
|
||||
*/
|
||||
int64_t pts_wrap_reference;
|
||||
|
||||
/**
|
||||
* Options for behavior, when a wrap is detected.
|
||||
*
|
||||
* Defined by AV_PTS_WRAP_ values.
|
||||
*
|
||||
* If correction is enabled, there are two possibilities:
|
||||
* If the first time stamp is near the wrap point, the wrap offset
|
||||
* will be subtracted, which will create negative time stamps.
|
||||
* Otherwise the offset will be added.
|
||||
*/
|
||||
int pts_wrap_behavior;
|
||||
|
||||
/**
|
||||
* Internal data to prevent doing update_initial_durations() twice
|
||||
*/
|
||||
int update_initial_durations_done;
|
||||
|
||||
/**
|
||||
* Internal data to generate dts from pts
|
||||
*/
|
||||
int64_t pts_reorder_error[MAX_REORDER_DELAY+1];
|
||||
uint8_t pts_reorder_error_count[MAX_REORDER_DELAY+1];
|
||||
|
||||
/**
|
||||
* Internal data to analyze DTS and detect faulty mpeg streams
|
||||
*/
|
||||
int64_t last_dts_for_order_check;
|
||||
uint8_t dts_ordered;
|
||||
uint8_t dts_misordered;
|
||||
|
||||
/**
|
||||
* Internal data to inject global side data
|
||||
*/
|
||||
int inject_global_side_data;
|
||||
|
||||
/**
|
||||
* display aspect ratio (0 if unknown)
|
||||
* - encoding: unused
|
||||
* - decoding: Set by libavformat to calculate sample_aspect_ratio internally
|
||||
*/
|
||||
AVRational display_aspect_ratio;
|
||||
|
||||
/**
|
||||
* An opaque field for libavformat internal usage.
|
||||
* Must not be accessed in any way by callers.
|
||||
*/
|
||||
AVStreamInternal *internal;
|
||||
} AVStream;
|
||||
|
||||
#if FF_API_FORMAT_GET_SET
|
||||
/**
|
||||
* Accessors for some AVStream fields. These used to be provided for ABI
|
||||
* compatibility, and do not need to be used anymore.
|
||||
*/
|
||||
attribute_deprecated
|
||||
AVRational av_stream_get_r_frame_rate(const AVStream *s);
|
||||
attribute_deprecated
|
||||
void av_stream_set_r_frame_rate(AVStream *s, AVRational r);
|
||||
#if FF_API_LAVF_FFSERVER
|
||||
attribute_deprecated
|
||||
char* av_stream_get_recommended_encoder_configuration(const AVStream *s);
|
||||
attribute_deprecated
|
||||
void av_stream_set_recommended_encoder_configuration(AVStream *s, char *configuration);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
struct AVCodecParserContext *av_stream_get_parser(const AVStream *s);
|
||||
|
||||
/**
|
||||
* Returns the pts of the last muxed packet + its duration
|
||||
*
|
||||
* the retuned value is undefined when used with a demuxer.
|
||||
*/
|
||||
int64_t av_stream_get_end_pts(const AVStream *st);
|
||||
|
||||
#define AV_PROGRAM_RUNNING 1
|
||||
|
||||
/**
|
||||
* New fields can be added to the end with minor version bumps.
|
||||
* Removal, reordering and changes to existing fields require a major
|
||||
* version bump.
|
||||
* sizeof(AVProgram) must not be used outside libav*.
|
||||
*/
|
||||
typedef struct AVProgram {
|
||||
int id;
|
||||
int flags;
|
||||
enum AVDiscard discard; ///< selects which program to discard and which to feed to the caller
|
||||
unsigned int *stream_index;
|
||||
unsigned int nb_stream_indexes;
|
||||
AVDictionary *metadata;
|
||||
|
||||
int program_num;
|
||||
int pmt_pid;
|
||||
int pcr_pid;
|
||||
int pmt_version;
|
||||
|
||||
/*****************************************************************
|
||||
* All fields below this line are not part of the public API. They
|
||||
* may not be used outside of libavformat and can be changed and
|
||||
* removed at will.
|
||||
* New public fields should be added right above.
|
||||
*****************************************************************
|
||||
*/
|
||||
int64_t start_time;
|
||||
int64_t end_time;
|
||||
|
||||
int64_t pts_wrap_reference; ///< reference dts for wrap detection
|
||||
int pts_wrap_behavior; ///< behavior on wrap detection
|
||||
} AVProgram;
|
||||
|
||||
#define AVFMTCTX_NOHEADER 0x0001 /**< signal that no header is present
|
||||
(streams are added dynamically) */
|
||||
#define AVFMTCTX_UNSEEKABLE 0x0002 /**< signal that the stream is definitely
|
||||
not seekable, and attempts to call the
|
||||
seek function will fail. For some
|
||||
network protocols (e.g. HLS), this can
|
||||
change dynamically at runtime. */
|
||||
|
||||
typedef struct AVChapter {
|
||||
int id; ///< unique ID to identify the chapter
|
||||
AVRational time_base; ///< time base in which the start/end timestamps are specified
|
||||
int64_t start, end; ///< chapter start/end time in time_base units
|
||||
AVDictionary *metadata;
|
||||
} AVChapter;
|
||||
|
||||
|
||||
/**
|
||||
* Callback used by devices to communicate with application.
|
||||
*/
|
||||
typedef int (*av_format_control_message)(struct AVFormatContext *s, int type,
|
||||
void *data, size_t data_size);
|
||||
|
||||
typedef int (*AVOpenCallback)(struct AVFormatContext *s, AVIOContext **pb, const char *url, int flags,
|
||||
const AVIOInterruptCB *int_cb, AVDictionary **options);
|
||||
|
||||
/**
|
||||
* The duration of a video can be estimated through various ways, and this enum can be used
|
||||
* to know how the duration was estimated.
|
||||
*/
|
||||
enum AVDurationEstimationMethod {
|
||||
AVFMT_DURATION_FROM_PTS, ///< Duration accurately estimated from PTSes
|
||||
AVFMT_DURATION_FROM_STREAM, ///< Duration estimated from a stream with a known duration
|
||||
AVFMT_DURATION_FROM_BITRATE ///< Duration estimated from bitrate (less accurate)
|
||||
};
|
||||
|
||||
typedef struct AVFormatInternal AVFormatInternal;
|
||||
|
||||
/**
|
||||
* Format I/O context.
|
||||
* New fields can be added to the end with minor version bumps.
|
||||
* Removal, reordering and changes to existing fields require a major
|
||||
* version bump.
|
||||
* sizeof(AVFormatContext) must not be used outside libav*, use
|
||||
* avformat_alloc_context() to create an AVFormatContext.
|
||||
*
|
||||
* Fields can be accessed through AVOptions (av_opt*),
|
||||
* the name string used matches the associated command line parameter name and
|
||||
* can be found in libavformat/options_table.h.
|
||||
* The AVOption/command line parameter names differ in some cases from the C
|
||||
* structure field names for historic reasons or brevity.
|
||||
*/
|
||||
typedef struct AVFormatContext {
|
||||
/**
|
||||
* A class for logging and @ref avoptions. Set by avformat_alloc_context().
|
||||
* Exports (de)muxer private options if they exist.
|
||||
*/
|
||||
const AVClass *av_class;
|
||||
|
||||
/**
|
||||
* The input container format.
|
||||
*
|
||||
* Demuxing only, set by avformat_open_input().
|
||||
*/
|
||||
struct AVInputFormat *iformat;
|
||||
|
||||
/**
|
||||
* The output container format.
|
||||
*
|
||||
* Muxing only, must be set by the caller before avformat_write_header().
|
||||
*/
|
||||
struct AVOutputFormat *oformat;
|
||||
|
||||
/**
|
||||
* Format private data. This is an AVOptions-enabled struct
|
||||
* if and only if iformat/oformat.priv_class is not NULL.
|
||||
*
|
||||
* - muxing: set by avformat_write_header()
|
||||
* - demuxing: set by avformat_open_input()
|
||||
*/
|
||||
void *priv_data;
|
||||
|
||||
/**
|
||||
* I/O context.
|
||||
*
|
||||
* - demuxing: either set by the user before avformat_open_input() (then
|
||||
* the user must close it manually) or set by avformat_open_input().
|
||||
* - muxing: set by the user before avformat_write_header(). The caller must
|
||||
* take care of closing / freeing the IO context.
|
||||
*
|
||||
* Do NOT set this field if AVFMT_NOFILE flag is set in
|
||||
* iformat/oformat.flags. In such a case, the (de)muxer will handle
|
||||
* I/O in some other way and this field will be NULL.
|
||||
*/
|
||||
AVIOContext *pb;
|
||||
|
||||
/* stream info */
|
||||
/**
|
||||
* Flags signalling stream properties. A combination of AVFMTCTX_*.
|
||||
* Set by libavformat.
|
||||
*/
|
||||
int ctx_flags;
|
||||
|
||||
/**
|
||||
* Number of elements in AVFormatContext.streams.
|
||||
*
|
||||
* Set by avformat_new_stream(), must not be modified by any other code.
|
||||
*/
|
||||
unsigned int nb_streams;
|
||||
/**
|
||||
* A list of all streams in the file. New streams are created with
|
||||
* avformat_new_stream().
|
||||
*
|
||||
* - demuxing: streams are created by libavformat in avformat_open_input().
|
||||
* If AVFMTCTX_NOHEADER is set in ctx_flags, then new streams may also
|
||||
* appear in av_read_frame().
|
||||
* - muxing: streams are created by the user before avformat_write_header().
|
||||
*
|
||||
* Freed by libavformat in avformat_free_context().
|
||||
*/
|
||||
AVStream **streams;
|
||||
|
||||
#if FF_API_FORMAT_FILENAME
|
||||
/**
|
||||
* input or output filename
|
||||
*
|
||||
* - demuxing: set by avformat_open_input()
|
||||
* - muxing: may be set by the caller before avformat_write_header()
|
||||
*
|
||||
* @deprecated Use url instead.
|
||||
*/
|
||||
attribute_deprecated
|
||||
char filename[1024];
|
||||
#endif
|
||||
|
||||
/**
|
||||
* input or output URL. Unlike the old filename field, this field has no
|
||||
* length restriction.
|
||||
*
|
||||
* - demuxing: set by avformat_open_input(), initialized to an empty
|
||||
* string if url parameter was NULL in avformat_open_input().
|
||||
* - muxing: may be set by the caller before calling avformat_write_header()
|
||||
* (or avformat_init_output() if that is called first) to a string
|
||||
* which is freeable by av_free(). Set to an empty string if it
|
||||
* was NULL in avformat_init_output().
|
||||
*
|
||||
* Freed by libavformat in avformat_free_context().
|
||||
*/
|
||||
char *url;
|
||||
|
||||
/**
|
||||
* Position of the first frame of the component, in
|
||||
* AV_TIME_BASE fractional seconds. NEVER set this value directly:
|
||||
* It is deduced from the AVStream values.
|
||||
*
|
||||
* Demuxing only, set by libavformat.
|
||||
*/
|
||||
int64_t start_time;
|
||||
|
||||
/**
|
||||
* Duration of the stream, in AV_TIME_BASE fractional
|
||||
* seconds. Only set this value if you know none of the individual stream
|
||||
* durations and also do not set any of them. This is deduced from the
|
||||
* AVStream values if not set.
|
||||
*
|
||||
* Demuxing only, set by libavformat.
|
||||
*/
|
||||
int64_t duration;
|
||||
|
||||
/**
|
||||
* Total stream bitrate in bit/s, 0 if not
|
||||
* available. Never set it directly if the file_size and the
|
||||
* duration are known as FFmpeg can compute it automatically.
|
||||
*/
|
||||
int64_t bit_rate;
|
||||
|
||||
unsigned int packet_size;
|
||||
int max_delay;
|
||||
|
||||
/**
|
||||
* Flags modifying the (de)muxer behaviour. A combination of AVFMT_FLAG_*.
|
||||
* Set by the user before avformat_open_input() / avformat_write_header().
|
||||
*/
|
||||
int flags;
|
||||
#define AVFMT_FLAG_GENPTS 0x0001 ///< Generate missing pts even if it requires parsing future frames.
|
||||
#define AVFMT_FLAG_IGNIDX 0x0002 ///< Ignore index.
|
||||
#define AVFMT_FLAG_NONBLOCK 0x0004 ///< Do not block when reading packets from input.
|
||||
#define AVFMT_FLAG_IGNDTS 0x0008 ///< Ignore DTS on frames that contain both DTS & PTS
|
||||
#define AVFMT_FLAG_NOFILLIN 0x0010 ///< Do not infer any values from other values, just return what is stored in the container
|
||||
#define AVFMT_FLAG_NOPARSE 0x0020 ///< Do not use AVParsers, you also must set AVFMT_FLAG_NOFILLIN as the fillin code works on frames and no parsing -> no frames. Also seeking to frames can not work if parsing to find frame boundaries has been disabled
|
||||
#define AVFMT_FLAG_NOBUFFER 0x0040 ///< Do not buffer frames when possible
|
||||
#define AVFMT_FLAG_CUSTOM_IO 0x0080 ///< The caller has supplied a custom AVIOContext, don't avio_close() it.
|
||||
#define AVFMT_FLAG_DISCARD_CORRUPT 0x0100 ///< Discard frames marked corrupted
|
||||
#define AVFMT_FLAG_FLUSH_PACKETS 0x0200 ///< Flush the AVIOContext every packet.
|
||||
/**
|
||||
* When muxing, try to avoid writing any random/volatile data to the output.
|
||||
* This includes any random IDs, real-time timestamps/dates, muxer version, etc.
|
||||
*
|
||||
* This flag is mainly intended for testing.
|
||||
*/
|
||||
#define AVFMT_FLAG_BITEXACT 0x0400
|
||||
#if FF_API_LAVF_MP4A_LATM
|
||||
#define AVFMT_FLAG_MP4A_LATM 0x8000 ///< Deprecated, does nothing.
|
||||
#endif
|
||||
#define AVFMT_FLAG_SORT_DTS 0x10000 ///< try to interleave outputted packets by dts (using this flag can slow demuxing down)
|
||||
#define AVFMT_FLAG_PRIV_OPT 0x20000 ///< Enable use of private options by delaying codec open (this could be made default once all code is converted)
|
||||
#if FF_API_LAVF_KEEPSIDE_FLAG
|
||||
#define AVFMT_FLAG_KEEP_SIDE_DATA 0x40000 ///< Deprecated, does nothing.
|
||||
#endif
|
||||
#define AVFMT_FLAG_FAST_SEEK 0x80000 ///< Enable fast, but inaccurate seeks for some formats
|
||||
#define AVFMT_FLAG_SHORTEST 0x100000 ///< Stop muxing when the shortest stream stops.
|
||||
#define AVFMT_FLAG_AUTO_BSF 0x200000 ///< Add bitstream filters as requested by the muxer
|
||||
|
||||
/**
|
||||
* Maximum size of the data read from input for determining
|
||||
* the input container format.
|
||||
* Demuxing only, set by the caller before avformat_open_input().
|
||||
*/
|
||||
int64_t probesize;
|
||||
|
||||
/**
|
||||
* Maximum duration (in AV_TIME_BASE units) of the data read
|
||||
* from input in avformat_find_stream_info().
|
||||
* Demuxing only, set by the caller before avformat_find_stream_info().
|
||||
* Can be set to 0 to let avformat choose using a heuristic.
|
||||
*/
|
||||
int64_t max_analyze_duration;
|
||||
|
||||
const uint8_t *key;
|
||||
int keylen;
|
||||
|
||||
unsigned int nb_programs;
|
||||
AVProgram **programs;
|
||||
|
||||
/**
|
||||
* Forced video codec_id.
|
||||
* Demuxing: Set by user.
|
||||
*/
|
||||
enum AVCodecID video_codec_id;
|
||||
|
||||
/**
|
||||
* Forced audio codec_id.
|
||||
* Demuxing: Set by user.
|
||||
*/
|
||||
enum AVCodecID audio_codec_id;
|
||||
|
||||
/**
|
||||
* Forced subtitle codec_id.
|
||||
* Demuxing: Set by user.
|
||||
*/
|
||||
enum AVCodecID subtitle_codec_id;
|
||||
|
||||
/**
|
||||
* Maximum amount of memory in bytes to use for the index of each stream.
|
||||
* If the index exceeds this size, entries will be discarded as
|
||||
* needed to maintain a smaller size. This can lead to slower or less
|
||||
* accurate seeking (depends on demuxer).
|
||||
* Demuxers for which a full in-memory index is mandatory will ignore
|
||||
* this.
|
||||
* - muxing: unused
|
||||
* - demuxing: set by user
|
||||
*/
|
||||
unsigned int max_index_size;
|
||||
|
||||
/**
|
||||
* Maximum amount of memory in bytes to use for buffering frames
|
||||
* obtained from realtime capture devices.
|
||||
*/
|
||||
unsigned int max_picture_buffer;
|
||||
|
||||
/**
|
||||
* Number of chapters in AVChapter array.
|
||||
* When muxing, chapters are normally written in the file header,
|
||||
* so nb_chapters should normally be initialized before write_header
|
||||
* is called. Some muxers (e.g. mov and mkv) can also write chapters
|
||||
* in the trailer. To write chapters in the trailer, nb_chapters
|
||||
* must be zero when write_header is called and non-zero when
|
||||
* write_trailer is called.
|
||||
* - muxing: set by user
|
||||
* - demuxing: set by libavformat
|
||||
*/
|
||||
unsigned int nb_chapters;
|
||||
AVChapter **chapters;
|
||||
|
||||
/**
|
||||
* Metadata that applies to the whole file.
|
||||
*
|
||||
* - demuxing: set by libavformat in avformat_open_input()
|
||||
* - muxing: may be set by the caller before avformat_write_header()
|
||||
*
|
||||
* Freed by libavformat in avformat_free_context().
|
||||
*/
|
||||
AVDictionary *metadata;
|
||||
|
||||
/**
|
||||
* Start time of the stream in real world time, in microseconds
|
||||
* since the Unix epoch (00:00 1st January 1970). That is, pts=0 in the
|
||||
* stream was captured at this real world time.
|
||||
* - muxing: Set by the caller before avformat_write_header(). If set to
|
||||
* either 0 or AV_NOPTS_VALUE, then the current wall-time will
|
||||
* be used.
|
||||
* - demuxing: Set by libavformat. AV_NOPTS_VALUE if unknown. Note that
|
||||
* the value may become known after some number of frames
|
||||
* have been received.
|
||||
*/
|
||||
int64_t start_time_realtime;
|
||||
|
||||
/**
|
||||
* The number of frames used for determining the framerate in
|
||||
* avformat_find_stream_info().
|
||||
* Demuxing only, set by the caller before avformat_find_stream_info().
|
||||
*/
|
||||
int fps_probe_size;
|
||||
|
||||
/**
|
||||
* Error recognition; higher values will detect more errors but may
|
||||
* misdetect some more or less valid parts as errors.
|
||||
* Demuxing only, set by the caller before avformat_open_input().
|
||||
*/
|
||||
int error_recognition;
|
||||
|
||||
/**
|
||||
* Custom interrupt callbacks for the I/O layer.
|
||||
*
|
||||
* demuxing: set by the user before avformat_open_input().
|
||||
* muxing: set by the user before avformat_write_header()
|
||||
* (mainly useful for AVFMT_NOFILE formats). The callback
|
||||
* should also be passed to avio_open2() if it's used to
|
||||
* open the file.
|
||||
*/
|
||||
AVIOInterruptCB interrupt_callback;
|
||||
|
||||
/**
|
||||
* Flags to enable debugging.
|
||||
*/
|
||||
int debug;
|
||||
#define FF_FDEBUG_TS 0x0001
|
||||
|
||||
/**
|
||||
* Maximum buffering duration for interleaving.
|
||||
*
|
||||
* To ensure all the streams are interleaved correctly,
|
||||
* av_interleaved_write_frame() will wait until it has at least one packet
|
||||
* for each stream before actually writing any packets to the output file.
|
||||
* When some streams are "sparse" (i.e. there are large gaps between
|
||||
* successive packets), this can result in excessive buffering.
|
||||
*
|
||||
* This field specifies the maximum difference between the timestamps of the
|
||||
* first and the last packet in the muxing queue, above which libavformat
|
||||
* will output a packet regardless of whether it has queued a packet for all
|
||||
* the streams.
|
||||
*
|
||||
* Muxing only, set by the caller before avformat_write_header().
|
||||
*/
|
||||
int64_t max_interleave_delta;
|
||||
|
||||
/**
|
||||
* Allow non-standard and experimental extension
|
||||
* @see AVCodecContext.strict_std_compliance
|
||||
*/
|
||||
int strict_std_compliance;
|
||||
|
||||
/**
|
||||
* Flags for the user to detect events happening on the file. Flags must
|
||||
* be cleared by the user once the event has been handled.
|
||||
* A combination of AVFMT_EVENT_FLAG_*.
|
||||
*/
|
||||
int event_flags;
|
||||
#define AVFMT_EVENT_FLAG_METADATA_UPDATED 0x0001 ///< The call resulted in updated metadata.
|
||||
|
||||
/**
|
||||
* Maximum number of packets to read while waiting for the first timestamp.
|
||||
* Decoding only.
|
||||
*/
|
||||
int max_ts_probe;
|
||||
|
||||
/**
|
||||
* Avoid negative timestamps during muxing.
|
||||
* Any value of the AVFMT_AVOID_NEG_TS_* constants.
|
||||
* Note, this only works when using av_interleaved_write_frame. (interleave_packet_per_dts is in use)
|
||||
* - muxing: Set by user
|
||||
* - demuxing: unused
|
||||
*/
|
||||
int avoid_negative_ts;
|
||||
#define AVFMT_AVOID_NEG_TS_AUTO -1 ///< Enabled when required by target format
|
||||
#define AVFMT_AVOID_NEG_TS_MAKE_NON_NEGATIVE 1 ///< Shift timestamps so they are non negative
|
||||
#define AVFMT_AVOID_NEG_TS_MAKE_ZERO 2 ///< Shift timestamps so that they start at 0
|
||||
|
||||
/**
|
||||
* Transport stream id.
|
||||
* This will be moved into demuxer private options. Thus no API/ABI compatibility
|
||||
*/
|
||||
int ts_id;
|
||||
|
||||
/**
|
||||
* Audio preload in microseconds.
|
||||
* Note, not all formats support this and unpredictable things may happen if it is used when not supported.
|
||||
* - encoding: Set by user
|
||||
* - decoding: unused
|
||||
*/
|
||||
int audio_preload;
|
||||
|
||||
/**
|
||||
* Max chunk time in microseconds.
|
||||
* Note, not all formats support this and unpredictable things may happen if it is used when not supported.
|
||||
* - encoding: Set by user
|
||||
* - decoding: unused
|
||||
*/
|
||||
int max_chunk_duration;
|
||||
|
||||
/**
|
||||
* Max chunk size in bytes
|
||||
* Note, not all formats support this and unpredictable things may happen if it is used when not supported.
|
||||
* - encoding: Set by user
|
||||
* - decoding: unused
|
||||
*/
|
||||
int max_chunk_size;
|
||||
|
||||
/**
|
||||
* forces the use of wallclock timestamps as pts/dts of packets
|
||||
* This has undefined results in the presence of B frames.
|
||||
* - encoding: unused
|
||||
* - decoding: Set by user
|
||||
*/
|
||||
int use_wallclock_as_timestamps;
|
||||
|
||||
/**
|
||||
* avio flags, used to force AVIO_FLAG_DIRECT.
|
||||
* - encoding: unused
|
||||
* - decoding: Set by user
|
||||
*/
|
||||
int avio_flags;
|
||||
|
||||
/**
|
||||
* The duration field can be estimated through various ways, and this field can be used
|
||||
* to know how the duration was estimated.
|
||||
* - encoding: unused
|
||||
* - decoding: Read by user
|
||||
*/
|
||||
enum AVDurationEstimationMethod duration_estimation_method;
|
||||
|
||||
/**
|
||||
* Skip initial bytes when opening stream
|
||||
* - encoding: unused
|
||||
* - decoding: Set by user
|
||||
*/
|
||||
int64_t skip_initial_bytes;
|
||||
|
||||
/**
|
||||
* Correct single timestamp overflows
|
||||
* - encoding: unused
|
||||
* - decoding: Set by user
|
||||
*/
|
||||
unsigned int correct_ts_overflow;
|
||||
|
||||
/**
|
||||
* Force seeking to any (also non key) frames.
|
||||
* - encoding: unused
|
||||
* - decoding: Set by user
|
||||
*/
|
||||
int seek2any;
|
||||
|
||||
/**
|
||||
* Flush the I/O context after each packet.
|
||||
* - encoding: Set by user
|
||||
* - decoding: unused
|
||||
*/
|
||||
int flush_packets;
|
||||
|
||||
/**
|
||||
* format probing score.
|
||||
* The maximal score is AVPROBE_SCORE_MAX, its set when the demuxer probes
|
||||
* the format.
|
||||
* - encoding: unused
|
||||
* - decoding: set by avformat, read by user
|
||||
*/
|
||||
int probe_score;
|
||||
|
||||
/**
|
||||
* number of bytes to read maximally to identify format.
|
||||
* - encoding: unused
|
||||
* - decoding: set by user
|
||||
*/
|
||||
int format_probesize;
|
||||
|
||||
/**
|
||||
* ',' separated list of allowed decoders.
|
||||
* If NULL then all are allowed
|
||||
* - encoding: unused
|
||||
* - decoding: set by user
|
||||
*/
|
||||
char *codec_whitelist;
|
||||
|
||||
/**
|
||||
* ',' separated list of allowed demuxers.
|
||||
* If NULL then all are allowed
|
||||
* - encoding: unused
|
||||
* - decoding: set by user
|
||||
*/
|
||||
char *format_whitelist;
|
||||
|
||||
/**
|
||||
* An opaque field for libavformat internal usage.
|
||||
* Must not be accessed in any way by callers.
|
||||
*/
|
||||
AVFormatInternal *internal;
|
||||
|
||||
/**
|
||||
* IO repositioned flag.
|
||||
* This is set by avformat when the underlaying IO context read pointer
|
||||
* is repositioned, for example when doing byte based seeking.
|
||||
* Demuxers can use the flag to detect such changes.
|
||||
*/
|
||||
int io_repositioned;
|
||||
|
||||
/**
|
||||
* Forced video codec.
|
||||
* This allows forcing a specific decoder, even when there are multiple with
|
||||
* the same codec_id.
|
||||
* Demuxing: Set by user
|
||||
*/
|
||||
AVCodec *video_codec;
|
||||
|
||||
/**
|
||||
* Forced audio codec.
|
||||
* This allows forcing a specific decoder, even when there are multiple with
|
||||
* the same codec_id.
|
||||
* Demuxing: Set by user
|
||||
*/
|
||||
AVCodec *audio_codec;
|
||||
|
||||
/**
|
||||
* Forced subtitle codec.
|
||||
* This allows forcing a specific decoder, even when there are multiple with
|
||||
* the same codec_id.
|
||||
* Demuxing: Set by user
|
||||
*/
|
||||
AVCodec *subtitle_codec;
|
||||
|
||||
/**
|
||||
* Forced data codec.
|
||||
* This allows forcing a specific decoder, even when there are multiple with
|
||||
* the same codec_id.
|
||||
* Demuxing: Set by user
|
||||
*/
|
||||
AVCodec *data_codec;
|
||||
|
||||
/**
|
||||
* Number of bytes to be written as padding in a metadata header.
|
||||
* Demuxing: Unused.
|
||||
* Muxing: Set by user via av_format_set_metadata_header_padding.
|
||||
*/
|
||||
int metadata_header_padding;
|
||||
|
||||
/**
|
||||
* User data.
|
||||
* This is a place for some private data of the user.
|
||||
*/
|
||||
void *opaque;
|
||||
|
||||
/**
|
||||
* Callback used by devices to communicate with application.
|
||||
*/
|
||||
av_format_control_message control_message_cb;
|
||||
|
||||
/**
|
||||
* Output timestamp offset, in microseconds.
|
||||
* Muxing: set by user
|
||||
*/
|
||||
int64_t output_ts_offset;
|
||||
|
||||
/**
|
||||
* dump format separator.
|
||||
* can be ", " or "\n " or anything else
|
||||
* - muxing: Set by user.
|
||||
* - demuxing: Set by user.
|
||||
*/
|
||||
uint8_t *dump_separator;
|
||||
|
||||
/**
|
||||
* Forced Data codec_id.
|
||||
* Demuxing: Set by user.
|
||||
*/
|
||||
enum AVCodecID data_codec_id;
|
||||
|
||||
#if FF_API_OLD_OPEN_CALLBACKS
|
||||
/**
|
||||
* Called to open further IO contexts when needed for demuxing.
|
||||
*
|
||||
* This can be set by the user application to perform security checks on
|
||||
* the URLs before opening them.
|
||||
* The function should behave like avio_open2(), AVFormatContext is provided
|
||||
* as contextual information and to reach AVFormatContext.opaque.
|
||||
*
|
||||
* If NULL then some simple checks are used together with avio_open2().
|
||||
*
|
||||
* Must not be accessed directly from outside avformat.
|
||||
* @See av_format_set_open_cb()
|
||||
*
|
||||
* Demuxing: Set by user.
|
||||
*
|
||||
* @deprecated Use io_open and io_close.
|
||||
*/
|
||||
attribute_deprecated
|
||||
int (*open_cb)(struct AVFormatContext *s, AVIOContext **p, const char *url, int flags, const AVIOInterruptCB *int_cb, AVDictionary **options);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* ',' separated list of allowed protocols.
|
||||
* - encoding: unused
|
||||
* - decoding: set by user
|
||||
*/
|
||||
char *protocol_whitelist;
|
||||
|
||||
/**
|
||||
* A callback for opening new IO streams.
|
||||
*
|
||||
* Whenever a muxer or a demuxer needs to open an IO stream (typically from
|
||||
* avformat_open_input() for demuxers, but for certain formats can happen at
|
||||
* other times as well), it will call this callback to obtain an IO context.
|
||||
*
|
||||
* @param s the format context
|
||||
* @param pb on success, the newly opened IO context should be returned here
|
||||
* @param url the url to open
|
||||
* @param flags a combination of AVIO_FLAG_*
|
||||
* @param options a dictionary of additional options, with the same
|
||||
* semantics as in avio_open2()
|
||||
* @return 0 on success, a negative AVERROR code on failure
|
||||
*
|
||||
* @note Certain muxers and demuxers do nesting, i.e. they open one or more
|
||||
* additional internal format contexts. Thus the AVFormatContext pointer
|
||||
* passed to this callback may be different from the one facing the caller.
|
||||
* It will, however, have the same 'opaque' field.
|
||||
*/
|
||||
int (*io_open)(struct AVFormatContext *s, AVIOContext **pb, const char *url,
|
||||
int flags, AVDictionary **options);
|
||||
|
||||
/**
|
||||
* A callback for closing the streams opened with AVFormatContext.io_open().
|
||||
*/
|
||||
void (*io_close)(struct AVFormatContext *s, AVIOContext *pb);
|
||||
|
||||
/**
|
||||
* ',' separated list of disallowed protocols.
|
||||
* - encoding: unused
|
||||
* - decoding: set by user
|
||||
*/
|
||||
char *protocol_blacklist;
|
||||
|
||||
/**
|
||||
* The maximum number of streams.
|
||||
* - encoding: unused
|
||||
* - decoding: set by user
|
||||
*/
|
||||
int max_streams;
|
||||
|
||||
/**
|
||||
* Skip duration calcuation in estimate_timings_from_pts.
|
||||
* - encoding: unused
|
||||
* - decoding: set by user
|
||||
*/
|
||||
int skip_estimate_duration_from_pts;
|
||||
} AVFormatContext;
|
||||
|
||||
#if FF_API_FORMAT_GET_SET
|
||||
/**
|
||||
* Accessors for some AVFormatContext fields. These used to be provided for ABI
|
||||
* compatibility, and do not need to be used anymore.
|
||||
*/
|
||||
attribute_deprecated
|
||||
int av_format_get_probe_score(const AVFormatContext *s);
|
||||
attribute_deprecated
|
||||
AVCodec * av_format_get_video_codec(const AVFormatContext *s);
|
||||
attribute_deprecated
|
||||
void av_format_set_video_codec(AVFormatContext *s, AVCodec *c);
|
||||
attribute_deprecated
|
||||
AVCodec * av_format_get_audio_codec(const AVFormatContext *s);
|
||||
attribute_deprecated
|
||||
void av_format_set_audio_codec(AVFormatContext *s, AVCodec *c);
|
||||
attribute_deprecated
|
||||
AVCodec * av_format_get_subtitle_codec(const AVFormatContext *s);
|
||||
attribute_deprecated
|
||||
void av_format_set_subtitle_codec(AVFormatContext *s, AVCodec *c);
|
||||
attribute_deprecated
|
||||
AVCodec * av_format_get_data_codec(const AVFormatContext *s);
|
||||
attribute_deprecated
|
||||
void av_format_set_data_codec(AVFormatContext *s, AVCodec *c);
|
||||
attribute_deprecated
|
||||
int av_format_get_metadata_header_padding(const AVFormatContext *s);
|
||||
attribute_deprecated
|
||||
void av_format_set_metadata_header_padding(AVFormatContext *s, int c);
|
||||
attribute_deprecated
|
||||
void * av_format_get_opaque(const AVFormatContext *s);
|
||||
attribute_deprecated
|
||||
void av_format_set_opaque(AVFormatContext *s, void *opaque);
|
||||
attribute_deprecated
|
||||
av_format_control_message av_format_get_control_message_cb(const AVFormatContext *s);
|
||||
attribute_deprecated
|
||||
void av_format_set_control_message_cb(AVFormatContext *s, av_format_control_message callback);
|
||||
#if FF_API_OLD_OPEN_CALLBACKS
|
||||
attribute_deprecated AVOpenCallback av_format_get_open_cb(const AVFormatContext *s);
|
||||
attribute_deprecated void av_format_set_open_cb(AVFormatContext *s, AVOpenCallback callback);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This function will cause global side data to be injected in the next packet
|
||||
* of each stream as well as after any subsequent seek.
|
||||
*/
|
||||
void av_format_inject_global_side_data(AVFormatContext *s);
|
||||
|
||||
/**
|
||||
* Returns the method used to set ctx->duration.
|
||||
*
|
||||
* @return AVFMT_DURATION_FROM_PTS, AVFMT_DURATION_FROM_STREAM, or AVFMT_DURATION_FROM_BITRATE.
|
||||
*/
|
||||
enum AVDurationEstimationMethod av_fmt_ctx_get_duration_estimation_method(const AVFormatContext* ctx);
|
||||
|
||||
typedef struct AVPacketList {
|
||||
AVPacket pkt;
|
||||
struct AVPacketList *next;
|
||||
} AVPacketList;
|
||||
|
||||
|
||||
/**
|
||||
* @defgroup lavf_core Core functions
|
||||
* @ingroup libavf
|
||||
*
|
||||
* Functions for querying libavformat capabilities, allocating core structures,
|
||||
* etc.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Return the LIBAVFORMAT_VERSION_INT constant.
|
||||
*/
|
||||
unsigned avformat_version(void);
|
||||
|
||||
/**
|
||||
* Return the libavformat build-time configuration.
|
||||
*/
|
||||
const char *avformat_configuration(void);
|
||||
|
||||
/**
|
||||
* Return the libavformat license.
|
||||
*/
|
||||
const char *avformat_license(void);
|
||||
|
||||
#if FF_API_NEXT
|
||||
/**
|
||||
* Initialize libavformat and register all the muxers, demuxers and
|
||||
* protocols. If you do not call this function, then you can select
|
||||
* exactly which formats you want to support.
|
||||
*
|
||||
* @see av_register_input_format()
|
||||
* @see av_register_output_format()
|
||||
*/
|
||||
attribute_deprecated
|
||||
void av_register_all(void);
|
||||
|
||||
attribute_deprecated
|
||||
void av_register_input_format(AVInputFormat *format);
|
||||
attribute_deprecated
|
||||
void av_register_output_format(AVOutputFormat *format);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Do global initialization of network libraries. This is optional,
|
||||
* and not recommended anymore.
|
||||
*
|
||||
* This functions only exists to work around thread-safety issues
|
||||
* with older GnuTLS or OpenSSL libraries. If libavformat is linked
|
||||
* to newer versions of those libraries, or if you do not use them,
|
||||
* calling this function is unnecessary. Otherwise, you need to call
|
||||
* this function before any other threads using them are started.
|
||||
*
|
||||
* This function will be deprecated once support for older GnuTLS and
|
||||
* OpenSSL libraries is removed, and this function has no purpose
|
||||
* anymore.
|
||||
*/
|
||||
int avformat_network_init(void);
|
||||
|
||||
/**
|
||||
* Undo the initialization done by avformat_network_init. Call it only
|
||||
* once for each time you called avformat_network_init.
|
||||
*/
|
||||
int avformat_network_deinit(void);
|
||||
|
||||
#if FF_API_NEXT
|
||||
/**
|
||||
* If f is NULL, returns the first registered input format,
|
||||
* if f is non-NULL, returns the next registered input format after f
|
||||
* or NULL if f is the last one.
|
||||
*/
|
||||
attribute_deprecated
|
||||
AVInputFormat *av_iformat_next(const AVInputFormat *f);
|
||||
|
||||
/**
|
||||
* If f is NULL, returns the first registered output format,
|
||||
* if f is non-NULL, returns the next registered output format after f
|
||||
* or NULL if f is the last one.
|
||||
*/
|
||||
attribute_deprecated
|
||||
AVOutputFormat *av_oformat_next(const AVOutputFormat *f);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Iterate over all registered muxers.
|
||||
*
|
||||
* @param opaque a pointer where libavformat will store the iteration state. Must
|
||||
* point to NULL to start the iteration.
|
||||
*
|
||||
* @return the next registered muxer or NULL when the iteration is
|
||||
* finished
|
||||
*/
|
||||
const AVOutputFormat *av_muxer_iterate(void **opaque);
|
||||
|
||||
/**
|
||||
* Iterate over all registered demuxers.
|
||||
*
|
||||
* @param opaque a pointer where libavformat will store the iteration state. Must
|
||||
* point to NULL to start the iteration.
|
||||
*
|
||||
* @return the next registered demuxer or NULL when the iteration is
|
||||
* finished
|
||||
*/
|
||||
const AVInputFormat *av_demuxer_iterate(void **opaque);
|
||||
|
||||
/**
|
||||
* Allocate an AVFormatContext.
|
||||
* avformat_free_context() can be used to free the context and everything
|
||||
* allocated by the framework within it.
|
||||
*/
|
||||
AVFormatContext *avformat_alloc_context(void);
|
||||
|
||||
/**
|
||||
* Free an AVFormatContext and all its streams.
|
||||
* @param s context to free
|
||||
*/
|
||||
void avformat_free_context(AVFormatContext *s);
|
||||
|
||||
/**
|
||||
* Get the AVClass for AVFormatContext. It can be used in combination with
|
||||
* AV_OPT_SEARCH_FAKE_OBJ for examining options.
|
||||
*
|
||||
* @see av_opt_find().
|
||||
*/
|
||||
const AVClass *avformat_get_class(void);
|
||||
|
||||
/**
|
||||
* Add a new stream to a media file.
|
||||
*
|
||||
* When demuxing, it is called by the demuxer in read_header(). If the
|
||||
* flag AVFMTCTX_NOHEADER is set in s.ctx_flags, then it may also
|
||||
* be called in read_packet().
|
||||
*
|
||||
* When muxing, should be called by the user before avformat_write_header().
|
||||
*
|
||||
* User is required to call avcodec_close() and avformat_free_context() to
|
||||
* clean up the allocation by avformat_new_stream().
|
||||
*
|
||||
* @param s media file handle
|
||||
* @param c If non-NULL, the AVCodecContext corresponding to the new stream
|
||||
* will be initialized to use this codec. This is needed for e.g. codec-specific
|
||||
* defaults to be set, so codec should be provided if it is known.
|
||||
*
|
||||
* @return newly created stream or NULL on error.
|
||||
*/
|
||||
AVStream *avformat_new_stream(AVFormatContext *s, const AVCodec *c);
|
||||
|
||||
/**
|
||||
* Wrap an existing array as stream side data.
|
||||
*
|
||||
* @param st stream
|
||||
* @param type side information type
|
||||
* @param data the side data array. It must be allocated with the av_malloc()
|
||||
* family of functions. The ownership of the data is transferred to
|
||||
* st.
|
||||
* @param size side information size
|
||||
* @return zero on success, a negative AVERROR code on failure. On failure,
|
||||
* the stream is unchanged and the data remains owned by the caller.
|
||||
*/
|
||||
int av_stream_add_side_data(AVStream *st, enum AVPacketSideDataType type,
|
||||
uint8_t *data, size_t size);
|
||||
|
||||
/**
|
||||
* Allocate new information from stream.
|
||||
*
|
||||
* @param stream stream
|
||||
* @param type desired side information type
|
||||
* @param size side information size
|
||||
* @return pointer to fresh allocated data or NULL otherwise
|
||||
*/
|
||||
uint8_t *av_stream_new_side_data(AVStream *stream,
|
||||
enum AVPacketSideDataType type, int size);
|
||||
/**
|
||||
* Get side information from stream.
|
||||
*
|
||||
* @param stream stream
|
||||
* @param type desired side information type
|
||||
* @param size pointer for side information size to store (optional)
|
||||
* @return pointer to data if present or NULL otherwise
|
||||
*/
|
||||
uint8_t *av_stream_get_side_data(const AVStream *stream,
|
||||
enum AVPacketSideDataType type, int *size);
|
||||
|
||||
AVProgram *av_new_program(AVFormatContext *s, int id);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Allocate an AVFormatContext for an output format.
|
||||
* avformat_free_context() can be used to free the context and
|
||||
* everything allocated by the framework within it.
|
||||
*
|
||||
* @param *ctx is set to the created format context, or to NULL in
|
||||
* case of failure
|
||||
* @param oformat format to use for allocating the context, if NULL
|
||||
* format_name and filename are used instead
|
||||
* @param format_name the name of output format to use for allocating the
|
||||
* context, if NULL filename is used instead
|
||||
* @param filename the name of the filename to use for allocating the
|
||||
* context, may be NULL
|
||||
* @return >= 0 in case of success, a negative AVERROR code in case of
|
||||
* failure
|
||||
*/
|
||||
int avformat_alloc_output_context2(AVFormatContext **ctx, AVOutputFormat *oformat,
|
||||
const char *format_name, const char *filename);
|
||||
|
||||
/**
|
||||
* @addtogroup lavf_decoding
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Find AVInputFormat based on the short name of the input format.
|
||||
*/
|
||||
AVInputFormat *av_find_input_format(const char *short_name);
|
||||
|
||||
/**
|
||||
* Guess the file format.
|
||||
*
|
||||
* @param pd data to be probed
|
||||
* @param is_opened Whether the file is already opened; determines whether
|
||||
* demuxers with or without AVFMT_NOFILE are probed.
|
||||
*/
|
||||
AVInputFormat *av_probe_input_format(AVProbeData *pd, int is_opened);
|
||||
|
||||
/**
|
||||
* Guess the file format.
|
||||
*
|
||||
* @param pd data to be probed
|
||||
* @param is_opened Whether the file is already opened; determines whether
|
||||
* demuxers with or without AVFMT_NOFILE are probed.
|
||||
* @param score_max A probe score larger that this is required to accept a
|
||||
* detection, the variable is set to the actual detection
|
||||
* score afterwards.
|
||||
* If the score is <= AVPROBE_SCORE_MAX / 4 it is recommended
|
||||
* to retry with a larger probe buffer.
|
||||
*/
|
||||
AVInputFormat *av_probe_input_format2(AVProbeData *pd, int is_opened, int *score_max);
|
||||
|
||||
/**
|
||||
* Guess the file format.
|
||||
*
|
||||
* @param is_opened Whether the file is already opened; determines whether
|
||||
* demuxers with or without AVFMT_NOFILE are probed.
|
||||
* @param score_ret The score of the best detection.
|
||||
*/
|
||||
AVInputFormat *av_probe_input_format3(AVProbeData *pd, int is_opened, int *score_ret);
|
||||
|
||||
/**
|
||||
* Probe a bytestream to determine the input format. Each time a probe returns
|
||||
* with a score that is too low, the probe buffer size is increased and another
|
||||
* attempt is made. When the maximum probe size is reached, the input format
|
||||
* with the highest score is returned.
|
||||
*
|
||||
* @param pb the bytestream to probe
|
||||
* @param fmt the input format is put here
|
||||
* @param url the url of the stream
|
||||
* @param logctx the log context
|
||||
* @param offset the offset within the bytestream to probe from
|
||||
* @param max_probe_size the maximum probe buffer size (zero for default)
|
||||
* @return the score in case of success, a negative value corresponding to an
|
||||
* the maximal score is AVPROBE_SCORE_MAX
|
||||
* AVERROR code otherwise
|
||||
*/
|
||||
int av_probe_input_buffer2(AVIOContext *pb, AVInputFormat **fmt,
|
||||
const char *url, void *logctx,
|
||||
unsigned int offset, unsigned int max_probe_size);
|
||||
|
||||
/**
|
||||
* Like av_probe_input_buffer2() but returns 0 on success
|
||||
*/
|
||||
int av_probe_input_buffer(AVIOContext *pb, AVInputFormat **fmt,
|
||||
const char *url, void *logctx,
|
||||
unsigned int offset, unsigned int max_probe_size);
|
||||
|
||||
/**
|
||||
* Open an input stream and read the header. The codecs are not opened.
|
||||
* The stream must be closed with avformat_close_input().
|
||||
*
|
||||
* @param ps Pointer to user-supplied AVFormatContext (allocated by avformat_alloc_context).
|
||||
* May be a pointer to NULL, in which case an AVFormatContext is allocated by this
|
||||
* function and written into ps.
|
||||
* Note that a user-supplied AVFormatContext will be freed on failure.
|
||||
* @param url URL of the stream to open.
|
||||
* @param fmt If non-NULL, this parameter forces a specific input format.
|
||||
* Otherwise the format is autodetected.
|
||||
* @param options A dictionary filled with AVFormatContext and demuxer-private options.
|
||||
* On return this parameter will be destroyed and replaced with a dict containing
|
||||
* options that were not found. May be NULL.
|
||||
*
|
||||
* @return 0 on success, a negative AVERROR on failure.
|
||||
*
|
||||
* @note If you want to use custom IO, preallocate the format context and set its pb field.
|
||||
*/
|
||||
int avformat_open_input(AVFormatContext **ps, const char *url, AVInputFormat *fmt, AVDictionary **options);
|
||||
|
||||
attribute_deprecated
|
||||
int av_demuxer_open(AVFormatContext *ic);
|
||||
|
||||
/**
|
||||
* Read packets of a media file to get stream information. This
|
||||
* is useful for file formats with no headers such as MPEG. This
|
||||
* function also computes the real framerate in case of MPEG-2 repeat
|
||||
* frame mode.
|
||||
* The logical file position is not changed by this function;
|
||||
* examined packets may be buffered for later processing.
|
||||
*
|
||||
* @param ic media file handle
|
||||
* @param options If non-NULL, an ic.nb_streams long array of pointers to
|
||||
* dictionaries, where i-th member contains options for
|
||||
* codec corresponding to i-th stream.
|
||||
* On return each dictionary will be filled with options that were not found.
|
||||
* @return >=0 if OK, AVERROR_xxx on error
|
||||
*
|
||||
* @note this function isn't guaranteed to open all the codecs, so
|
||||
* options being non-empty at return is a perfectly normal behavior.
|
||||
*
|
||||
* @todo Let the user decide somehow what information is needed so that
|
||||
* we do not waste time getting stuff the user does not need.
|
||||
*/
|
||||
int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options);
|
||||
|
||||
/**
|
||||
* Find the programs which belong to a given stream.
|
||||
*
|
||||
* @param ic media file handle
|
||||
* @param last the last found program, the search will start after this
|
||||
* program, or from the beginning if it is NULL
|
||||
* @param s stream index
|
||||
* @return the next program which belongs to s, NULL if no program is found or
|
||||
* the last program is not among the programs of ic.
|
||||
*/
|
||||
AVProgram *av_find_program_from_stream(AVFormatContext *ic, AVProgram *last, int s);
|
||||
|
||||
void av_program_add_stream_index(AVFormatContext *ac, int progid, unsigned int idx);
|
||||
|
||||
/**
|
||||
* Find the "best" stream in the file.
|
||||
* The best stream is determined according to various heuristics as the most
|
||||
* likely to be what the user expects.
|
||||
* If the decoder parameter is non-NULL, av_find_best_stream will find the
|
||||
* default decoder for the stream's codec; streams for which no decoder can
|
||||
* be found are ignored.
|
||||
*
|
||||
* @param ic media file handle
|
||||
* @param type stream type: video, audio, subtitles, etc.
|
||||
* @param wanted_stream_nb user-requested stream number,
|
||||
* or -1 for automatic selection
|
||||
* @param related_stream try to find a stream related (eg. in the same
|
||||
* program) to this one, or -1 if none
|
||||
* @param decoder_ret if non-NULL, returns the decoder for the
|
||||
* selected stream
|
||||
* @param flags flags; none are currently defined
|
||||
* @return the non-negative stream number in case of success,
|
||||
* AVERROR_STREAM_NOT_FOUND if no stream with the requested type
|
||||
* could be found,
|
||||
* AVERROR_DECODER_NOT_FOUND if streams were found but no decoder
|
||||
* @note If av_find_best_stream returns successfully and decoder_ret is not
|
||||
* NULL, then *decoder_ret is guaranteed to be set to a valid AVCodec.
|
||||
*/
|
||||
int av_find_best_stream(AVFormatContext *ic,
|
||||
enum AVMediaType type,
|
||||
int wanted_stream_nb,
|
||||
int related_stream,
|
||||
AVCodec **decoder_ret,
|
||||
int flags);
|
||||
|
||||
/**
|
||||
* Return the next frame of a stream.
|
||||
* This function returns what is stored in the file, and does not validate
|
||||
* that what is there are valid frames for the decoder. It will split what is
|
||||
* stored in the file into frames and return one for each call. It will not
|
||||
* omit invalid data between valid frames so as to give the decoder the maximum
|
||||
* information possible for decoding.
|
||||
*
|
||||
* If pkt->buf is NULL, then the packet is valid until the next
|
||||
* av_read_frame() or until avformat_close_input(). Otherwise the packet
|
||||
* is valid indefinitely. In both cases the packet must be freed with
|
||||
* av_packet_unref when it is no longer needed. For video, the packet contains
|
||||
* exactly one frame. For audio, it contains an integer number of frames if each
|
||||
* frame has a known fixed size (e.g. PCM or ADPCM data). If the audio frames
|
||||
* have a variable size (e.g. MPEG audio), then it contains one frame.
|
||||
*
|
||||
* pkt->pts, pkt->dts and pkt->duration are always set to correct
|
||||
* values in AVStream.time_base units (and guessed if the format cannot
|
||||
* provide them). pkt->pts can be AV_NOPTS_VALUE if the video format
|
||||
* has B-frames, so it is better to rely on pkt->dts if you do not
|
||||
* decompress the payload.
|
||||
*
|
||||
* @return 0 if OK, < 0 on error or end of file
|
||||
*/
|
||||
int av_read_frame(AVFormatContext *s, AVPacket *pkt);
|
||||
|
||||
/**
|
||||
* Seek to the keyframe at timestamp.
|
||||
* 'timestamp' in 'stream_index'.
|
||||
*
|
||||
* @param s media file handle
|
||||
* @param stream_index If stream_index is (-1), a default
|
||||
* stream is selected, and timestamp is automatically converted
|
||||
* from AV_TIME_BASE units to the stream specific time_base.
|
||||
* @param timestamp Timestamp in AVStream.time_base units
|
||||
* or, if no stream is specified, in AV_TIME_BASE units.
|
||||
* @param flags flags which select direction and seeking mode
|
||||
* @return >= 0 on success
|
||||
*/
|
||||
int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp,
|
||||
int flags);
|
||||
|
||||
/**
|
||||
* Seek to timestamp ts.
|
||||
* Seeking will be done so that the point from which all active streams
|
||||
* can be presented successfully will be closest to ts and within min/max_ts.
|
||||
* Active streams are all streams that have AVStream.discard < AVDISCARD_ALL.
|
||||
*
|
||||
* If flags contain AVSEEK_FLAG_BYTE, then all timestamps are in bytes and
|
||||
* are the file position (this may not be supported by all demuxers).
|
||||
* If flags contain AVSEEK_FLAG_FRAME, then all timestamps are in frames
|
||||
* in the stream with stream_index (this may not be supported by all demuxers).
|
||||
* Otherwise all timestamps are in units of the stream selected by stream_index
|
||||
* or if stream_index is -1, in AV_TIME_BASE units.
|
||||
* If flags contain AVSEEK_FLAG_ANY, then non-keyframes are treated as
|
||||
* keyframes (this may not be supported by all demuxers).
|
||||
* If flags contain AVSEEK_FLAG_BACKWARD, it is ignored.
|
||||
*
|
||||
* @param s media file handle
|
||||
* @param stream_index index of the stream which is used as time base reference
|
||||
* @param min_ts smallest acceptable timestamp
|
||||
* @param ts target timestamp
|
||||
* @param max_ts largest acceptable timestamp
|
||||
* @param flags flags
|
||||
* @return >=0 on success, error code otherwise
|
||||
*
|
||||
* @note This is part of the new seek API which is still under construction.
|
||||
* Thus do not use this yet. It may change at any time, do not expect
|
||||
* ABI compatibility yet!
|
||||
*/
|
||||
int avformat_seek_file(AVFormatContext *s, int stream_index, int64_t min_ts, int64_t ts, int64_t max_ts, int flags);
|
||||
|
||||
/**
|
||||
* Discard all internally buffered data. This can be useful when dealing with
|
||||
* discontinuities in the byte stream. Generally works only with formats that
|
||||
* can resync. This includes headerless formats like MPEG-TS/TS but should also
|
||||
* work with NUT, Ogg and in a limited way AVI for example.
|
||||
*
|
||||
* The set of streams, the detected duration, stream parameters and codecs do
|
||||
* not change when calling this function. If you want a complete reset, it's
|
||||
* better to open a new AVFormatContext.
|
||||
*
|
||||
* This does not flush the AVIOContext (s->pb). If necessary, call
|
||||
* avio_flush(s->pb) before calling this function.
|
||||
*
|
||||
* @param s media file handle
|
||||
* @return >=0 on success, error code otherwise
|
||||
*/
|
||||
int avformat_flush(AVFormatContext *s);
|
||||
|
||||
/**
|
||||
* Start playing a network-based stream (e.g. RTSP stream) at the
|
||||
* current position.
|
||||
*/
|
||||
int av_read_play(AVFormatContext *s);
|
||||
|
||||
/**
|
||||
* Pause a network-based stream (e.g. RTSP stream).
|
||||
*
|
||||
* Use av_read_play() to resume it.
|
||||
*/
|
||||
int av_read_pause(AVFormatContext *s);
|
||||
|
||||
/**
|
||||
* Close an opened input AVFormatContext. Free it and all its contents
|
||||
* and set *s to NULL.
|
||||
*/
|
||||
void avformat_close_input(AVFormatContext **s);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#define AVSEEK_FLAG_BACKWARD 1 ///< seek backward
|
||||
#define AVSEEK_FLAG_BYTE 2 ///< seeking based on position in bytes
|
||||
#define AVSEEK_FLAG_ANY 4 ///< seek to any frame, even non-keyframes
|
||||
#define AVSEEK_FLAG_FRAME 8 ///< seeking based on frame number
|
||||
|
||||
/**
|
||||
* @addtogroup lavf_encoding
|
||||
* @{
|
||||
*/
|
||||
|
||||
#define AVSTREAM_INIT_IN_WRITE_HEADER 0 ///< stream parameters initialized in avformat_write_header
|
||||
#define AVSTREAM_INIT_IN_INIT_OUTPUT 1 ///< stream parameters initialized in avformat_init_output
|
||||
|
||||
/**
|
||||
* Allocate the stream private data and write the stream header to
|
||||
* an output media file.
|
||||
*
|
||||
* @param s Media file handle, must be allocated with avformat_alloc_context().
|
||||
* Its oformat field must be set to the desired output format;
|
||||
* Its pb field must be set to an already opened AVIOContext.
|
||||
* @param options An AVDictionary filled with AVFormatContext and muxer-private options.
|
||||
* On return this parameter will be destroyed and replaced with a dict containing
|
||||
* options that were not found. May be NULL.
|
||||
*
|
||||
* @return AVSTREAM_INIT_IN_WRITE_HEADER on success if the codec had not already been fully initialized in avformat_init,
|
||||
* AVSTREAM_INIT_IN_INIT_OUTPUT on success if the codec had already been fully initialized in avformat_init,
|
||||
* negative AVERROR on failure.
|
||||
*
|
||||
* @see av_opt_find, av_dict_set, avio_open, av_oformat_next, avformat_init_output.
|
||||
*/
|
||||
av_warn_unused_result
|
||||
int avformat_write_header(AVFormatContext *s, AVDictionary **options);
|
||||
|
||||
/**
|
||||
* Allocate the stream private data and initialize the codec, but do not write the header.
|
||||
* May optionally be used before avformat_write_header to initialize stream parameters
|
||||
* before actually writing the header.
|
||||
* If using this function, do not pass the same options to avformat_write_header.
|
||||
*
|
||||
* @param s Media file handle, must be allocated with avformat_alloc_context().
|
||||
* Its oformat field must be set to the desired output format;
|
||||
* Its pb field must be set to an already opened AVIOContext.
|
||||
* @param options An AVDictionary filled with AVFormatContext and muxer-private options.
|
||||
* On return this parameter will be destroyed and replaced with a dict containing
|
||||
* options that were not found. May be NULL.
|
||||
*
|
||||
* @return AVSTREAM_INIT_IN_WRITE_HEADER on success if the codec requires avformat_write_header to fully initialize,
|
||||
* AVSTREAM_INIT_IN_INIT_OUTPUT on success if the codec has been fully initialized,
|
||||
* negative AVERROR on failure.
|
||||
*
|
||||
* @see av_opt_find, av_dict_set, avio_open, av_oformat_next, avformat_write_header.
|
||||
*/
|
||||
av_warn_unused_result
|
||||
int avformat_init_output(AVFormatContext *s, AVDictionary **options);
|
||||
|
||||
/**
|
||||
* Write a packet to an output media file.
|
||||
*
|
||||
* This function passes the packet directly to the muxer, without any buffering
|
||||
* or reordering. The caller is responsible for correctly interleaving the
|
||||
* packets if the format requires it. Callers that want libavformat to handle
|
||||
* the interleaving should call av_interleaved_write_frame() instead of this
|
||||
* function.
|
||||
*
|
||||
* @param s media file handle
|
||||
* @param pkt The packet containing the data to be written. Note that unlike
|
||||
* av_interleaved_write_frame(), this function does not take
|
||||
* ownership of the packet passed to it (though some muxers may make
|
||||
* an internal reference to the input packet).
|
||||
* <br>
|
||||
* This parameter can be NULL (at any time, not just at the end), in
|
||||
* order to immediately flush data buffered within the muxer, for
|
||||
* muxers that buffer up data internally before writing it to the
|
||||
* output.
|
||||
* <br>
|
||||
* Packet's @ref AVPacket.stream_index "stream_index" field must be
|
||||
* set to the index of the corresponding stream in @ref
|
||||
* AVFormatContext.streams "s->streams".
|
||||
* <br>
|
||||
* The timestamps (@ref AVPacket.pts "pts", @ref AVPacket.dts "dts")
|
||||
* must be set to correct values in the stream's timebase (unless the
|
||||
* output format is flagged with the AVFMT_NOTIMESTAMPS flag, then
|
||||
* they can be set to AV_NOPTS_VALUE).
|
||||
* The dts for subsequent packets passed to this function must be strictly
|
||||
* increasing when compared in their respective timebases (unless the
|
||||
* output format is flagged with the AVFMT_TS_NONSTRICT, then they
|
||||
* merely have to be nondecreasing). @ref AVPacket.duration
|
||||
* "duration") should also be set if known.
|
||||
* @return < 0 on error, = 0 if OK, 1 if flushed and there is no more data to flush
|
||||
*
|
||||
* @see av_interleaved_write_frame()
|
||||
*/
|
||||
int av_write_frame(AVFormatContext *s, AVPacket *pkt);
|
||||
|
||||
/**
|
||||
* Write a packet to an output media file ensuring correct interleaving.
|
||||
*
|
||||
* This function will buffer the packets internally as needed to make sure the
|
||||
* packets in the output file are properly interleaved in the order of
|
||||
* increasing dts. Callers doing their own interleaving should call
|
||||
* av_write_frame() instead of this function.
|
||||
*
|
||||
* Using this function instead of av_write_frame() can give muxers advance
|
||||
* knowledge of future packets, improving e.g. the behaviour of the mp4
|
||||
* muxer for VFR content in fragmenting mode.
|
||||
*
|
||||
* @param s media file handle
|
||||
* @param pkt The packet containing the data to be written.
|
||||
* <br>
|
||||
* If the packet is reference-counted, this function will take
|
||||
* ownership of this reference and unreference it later when it sees
|
||||
* fit.
|
||||
* The caller must not access the data through this reference after
|
||||
* this function returns. If the packet is not reference-counted,
|
||||
* libavformat will make a copy.
|
||||
* <br>
|
||||
* This parameter can be NULL (at any time, not just at the end), to
|
||||
* flush the interleaving queues.
|
||||
* <br>
|
||||
* Packet's @ref AVPacket.stream_index "stream_index" field must be
|
||||
* set to the index of the corresponding stream in @ref
|
||||
* AVFormatContext.streams "s->streams".
|
||||
* <br>
|
||||
* The timestamps (@ref AVPacket.pts "pts", @ref AVPacket.dts "dts")
|
||||
* must be set to correct values in the stream's timebase (unless the
|
||||
* output format is flagged with the AVFMT_NOTIMESTAMPS flag, then
|
||||
* they can be set to AV_NOPTS_VALUE).
|
||||
* The dts for subsequent packets in one stream must be strictly
|
||||
* increasing (unless the output format is flagged with the
|
||||
* AVFMT_TS_NONSTRICT, then they merely have to be nondecreasing).
|
||||
* @ref AVPacket.duration "duration") should also be set if known.
|
||||
*
|
||||
* @return 0 on success, a negative AVERROR on error. Libavformat will always
|
||||
* take care of freeing the packet, even if this function fails.
|
||||
*
|
||||
* @see av_write_frame(), AVFormatContext.max_interleave_delta
|
||||
*/
|
||||
int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt);
|
||||
|
||||
/**
|
||||
* Write an uncoded frame to an output media file.
|
||||
*
|
||||
* The frame must be correctly interleaved according to the container
|
||||
* specification; if not, then av_interleaved_write_frame() must be used.
|
||||
*
|
||||
* See av_interleaved_write_frame() for details.
|
||||
*/
|
||||
int av_write_uncoded_frame(AVFormatContext *s, int stream_index,
|
||||
AVFrame *frame);
|
||||
|
||||
/**
|
||||
* Write an uncoded frame to an output media file.
|
||||
*
|
||||
* If the muxer supports it, this function makes it possible to write an AVFrame
|
||||
* structure directly, without encoding it into a packet.
|
||||
* It is mostly useful for devices and similar special muxers that use raw
|
||||
* video or PCM data and will not serialize it into a byte stream.
|
||||
*
|
||||
* To test whether it is possible to use it with a given muxer and stream,
|
||||
* use av_write_uncoded_frame_query().
|
||||
*
|
||||
* The caller gives up ownership of the frame and must not access it
|
||||
* afterwards.
|
||||
*
|
||||
* @return >=0 for success, a negative code on error
|
||||
*/
|
||||
int av_interleaved_write_uncoded_frame(AVFormatContext *s, int stream_index,
|
||||
AVFrame *frame);
|
||||
|
||||
/**
|
||||
* Test whether a muxer supports uncoded frame.
|
||||
*
|
||||
* @return >=0 if an uncoded frame can be written to that muxer and stream,
|
||||
* <0 if not
|
||||
*/
|
||||
int av_write_uncoded_frame_query(AVFormatContext *s, int stream_index);
|
||||
|
||||
/**
|
||||
* Write the stream trailer to an output media file and free the
|
||||
* file private data.
|
||||
*
|
||||
* May only be called after a successful call to avformat_write_header.
|
||||
*
|
||||
* @param s media file handle
|
||||
* @return 0 if OK, AVERROR_xxx on error
|
||||
*/
|
||||
int av_write_trailer(AVFormatContext *s);
|
||||
|
||||
/**
|
||||
* Return the output format in the list of registered output formats
|
||||
* which best matches the provided parameters, or return NULL if
|
||||
* there is no match.
|
||||
*
|
||||
* @param short_name if non-NULL checks if short_name matches with the
|
||||
* names of the registered formats
|
||||
* @param filename if non-NULL checks if filename terminates with the
|
||||
* extensions of the registered formats
|
||||
* @param mime_type if non-NULL checks if mime_type matches with the
|
||||
* MIME type of the registered formats
|
||||
*/
|
||||
AVOutputFormat *av_guess_format(const char *short_name,
|
||||
const char *filename,
|
||||
const char *mime_type);
|
||||
|
||||
/**
|
||||
* Guess the codec ID based upon muxer and filename.
|
||||
*/
|
||||
enum AVCodecID av_guess_codec(AVOutputFormat *fmt, const char *short_name,
|
||||
const char *filename, const char *mime_type,
|
||||
enum AVMediaType type);
|
||||
|
||||
/**
|
||||
* Get timing information for the data currently output.
|
||||
* The exact meaning of "currently output" depends on the format.
|
||||
* It is mostly relevant for devices that have an internal buffer and/or
|
||||
* work in real time.
|
||||
* @param s media file handle
|
||||
* @param stream stream in the media file
|
||||
* @param[out] dts DTS of the last packet output for the stream, in stream
|
||||
* time_base units
|
||||
* @param[out] wall absolute time when that packet whas output,
|
||||
* in microsecond
|
||||
* @return 0 if OK, AVERROR(ENOSYS) if the format does not support it
|
||||
* Note: some formats or devices may not allow to measure dts and wall
|
||||
* atomically.
|
||||
*/
|
||||
int av_get_output_timestamp(struct AVFormatContext *s, int stream,
|
||||
int64_t *dts, int64_t *wall);
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @defgroup lavf_misc Utility functions
|
||||
* @ingroup libavf
|
||||
* @{
|
||||
*
|
||||
* Miscellaneous utility functions related to both muxing and demuxing
|
||||
* (or neither).
|
||||
*/
|
||||
|
||||
/**
|
||||
* Send a nice hexadecimal dump of a buffer to the specified file stream.
|
||||
*
|
||||
* @param f The file stream pointer where the dump should be sent to.
|
||||
* @param buf buffer
|
||||
* @param size buffer size
|
||||
*
|
||||
* @see av_hex_dump_log, av_pkt_dump2, av_pkt_dump_log2
|
||||
*/
|
||||
void av_hex_dump(FILE *f, const uint8_t *buf, int size);
|
||||
|
||||
/**
|
||||
* Send a nice hexadecimal dump of a buffer to the log.
|
||||
*
|
||||
* @param avcl A pointer to an arbitrary struct of which the first field is a
|
||||
* pointer to an AVClass struct.
|
||||
* @param level The importance level of the message, lower values signifying
|
||||
* higher importance.
|
||||
* @param buf buffer
|
||||
* @param size buffer size
|
||||
*
|
||||
* @see av_hex_dump, av_pkt_dump2, av_pkt_dump_log2
|
||||
*/
|
||||
void av_hex_dump_log(void *avcl, int level, const uint8_t *buf, int size);
|
||||
|
||||
/**
|
||||
* Send a nice dump of a packet to the specified file stream.
|
||||
*
|
||||
* @param f The file stream pointer where the dump should be sent to.
|
||||
* @param pkt packet to dump
|
||||
* @param dump_payload True if the payload must be displayed, too.
|
||||
* @param st AVStream that the packet belongs to
|
||||
*/
|
||||
void av_pkt_dump2(FILE *f, const AVPacket *pkt, int dump_payload, const AVStream *st);
|
||||
|
||||
|
||||
/**
|
||||
* Send a nice dump of a packet to the log.
|
||||
*
|
||||
* @param avcl A pointer to an arbitrary struct of which the first field is a
|
||||
* pointer to an AVClass struct.
|
||||
* @param level The importance level of the message, lower values signifying
|
||||
* higher importance.
|
||||
* @param pkt packet to dump
|
||||
* @param dump_payload True if the payload must be displayed, too.
|
||||
* @param st AVStream that the packet belongs to
|
||||
*/
|
||||
void av_pkt_dump_log2(void *avcl, int level, const AVPacket *pkt, int dump_payload,
|
||||
const AVStream *st);
|
||||
|
||||
/**
|
||||
* Get the AVCodecID for the given codec tag tag.
|
||||
* If no codec id is found returns AV_CODEC_ID_NONE.
|
||||
*
|
||||
* @param tags list of supported codec_id-codec_tag pairs, as stored
|
||||
* in AVInputFormat.codec_tag and AVOutputFormat.codec_tag
|
||||
* @param tag codec tag to match to a codec ID
|
||||
*/
|
||||
enum AVCodecID av_codec_get_id(const struct AVCodecTag * const *tags, unsigned int tag);
|
||||
|
||||
/**
|
||||
* Get the codec tag for the given codec id id.
|
||||
* If no codec tag is found returns 0.
|
||||
*
|
||||
* @param tags list of supported codec_id-codec_tag pairs, as stored
|
||||
* in AVInputFormat.codec_tag and AVOutputFormat.codec_tag
|
||||
* @param id codec ID to match to a codec tag
|
||||
*/
|
||||
unsigned int av_codec_get_tag(const struct AVCodecTag * const *tags, enum AVCodecID id);
|
||||
|
||||
/**
|
||||
* Get the codec tag for the given codec id.
|
||||
*
|
||||
* @param tags list of supported codec_id - codec_tag pairs, as stored
|
||||
* in AVInputFormat.codec_tag and AVOutputFormat.codec_tag
|
||||
* @param id codec id that should be searched for in the list
|
||||
* @param tag A pointer to the found tag
|
||||
* @return 0 if id was not found in tags, > 0 if it was found
|
||||
*/
|
||||
int av_codec_get_tag2(const struct AVCodecTag * const *tags, enum AVCodecID id,
|
||||
unsigned int *tag);
|
||||
|
||||
int av_find_default_stream_index(AVFormatContext *s);
|
||||
|
||||
/**
|
||||
* Get the index for a specific timestamp.
|
||||
*
|
||||
* @param st stream that the timestamp belongs to
|
||||
* @param timestamp timestamp to retrieve the index for
|
||||
* @param flags if AVSEEK_FLAG_BACKWARD then the returned index will correspond
|
||||
* to the timestamp which is <= the requested one, if backward
|
||||
* is 0, then it will be >=
|
||||
* if AVSEEK_FLAG_ANY seek to any frame, only keyframes otherwise
|
||||
* @return < 0 if no such timestamp could be found
|
||||
*/
|
||||
int av_index_search_timestamp(AVStream *st, int64_t timestamp, int flags);
|
||||
|
||||
/**
|
||||
* Add an index entry into a sorted list. Update the entry if the list
|
||||
* already contains it.
|
||||
*
|
||||
* @param timestamp timestamp in the time base of the given stream
|
||||
*/
|
||||
int av_add_index_entry(AVStream *st, int64_t pos, int64_t timestamp,
|
||||
int size, int distance, int flags);
|
||||
|
||||
|
||||
/**
|
||||
* Split a URL string into components.
|
||||
*
|
||||
* The pointers to buffers for storing individual components may be null,
|
||||
* in order to ignore that component. Buffers for components not found are
|
||||
* set to empty strings. If the port is not found, it is set to a negative
|
||||
* value.
|
||||
*
|
||||
* @param proto the buffer for the protocol
|
||||
* @param proto_size the size of the proto buffer
|
||||
* @param authorization the buffer for the authorization
|
||||
* @param authorization_size the size of the authorization buffer
|
||||
* @param hostname the buffer for the host name
|
||||
* @param hostname_size the size of the hostname buffer
|
||||
* @param port_ptr a pointer to store the port number in
|
||||
* @param path the buffer for the path
|
||||
* @param path_size the size of the path buffer
|
||||
* @param url the URL to split
|
||||
*/
|
||||
void av_url_split(char *proto, int proto_size,
|
||||
char *authorization, int authorization_size,
|
||||
char *hostname, int hostname_size,
|
||||
int *port_ptr,
|
||||
char *path, int path_size,
|
||||
const char *url);
|
||||
|
||||
|
||||
/**
|
||||
* Print detailed information about the input or output format, such as
|
||||
* duration, bitrate, streams, container, programs, metadata, side data,
|
||||
* codec and time base.
|
||||
*
|
||||
* @param ic the context to analyze
|
||||
* @param index index of the stream to dump information about
|
||||
* @param url the URL to print, such as source or destination file
|
||||
* @param is_output Select whether the specified context is an input(0) or output(1)
|
||||
*/
|
||||
void av_dump_format(AVFormatContext *ic,
|
||||
int index,
|
||||
const char *url,
|
||||
int is_output);
|
||||
|
||||
|
||||
#define AV_FRAME_FILENAME_FLAGS_MULTIPLE 1 ///< Allow multiple %d
|
||||
|
||||
/**
|
||||
* Return in 'buf' the path with '%d' replaced by a number.
|
||||
*
|
||||
* Also handles the '%0nd' format where 'n' is the total number
|
||||
* of digits and '%%'.
|
||||
*
|
||||
* @param buf destination buffer
|
||||
* @param buf_size destination buffer size
|
||||
* @param path numbered sequence string
|
||||
* @param number frame number
|
||||
* @param flags AV_FRAME_FILENAME_FLAGS_*
|
||||
* @return 0 if OK, -1 on format error
|
||||
*/
|
||||
int av_get_frame_filename2(char *buf, int buf_size,
|
||||
const char *path, int number, int flags);
|
||||
|
||||
int av_get_frame_filename(char *buf, int buf_size,
|
||||
const char *path, int number);
|
||||
|
||||
/**
|
||||
* Check whether filename actually is a numbered sequence generator.
|
||||
*
|
||||
* @param filename possible numbered sequence string
|
||||
* @return 1 if a valid numbered sequence string, 0 otherwise
|
||||
*/
|
||||
int av_filename_number_test(const char *filename);
|
||||
|
||||
/**
|
||||
* Generate an SDP for an RTP session.
|
||||
*
|
||||
* Note, this overwrites the id values of AVStreams in the muxer contexts
|
||||
* for getting unique dynamic payload types.
|
||||
*
|
||||
* @param ac array of AVFormatContexts describing the RTP streams. If the
|
||||
* array is composed by only one context, such context can contain
|
||||
* multiple AVStreams (one AVStream per RTP stream). Otherwise,
|
||||
* all the contexts in the array (an AVCodecContext per RTP stream)
|
||||
* must contain only one AVStream.
|
||||
* @param n_files number of AVCodecContexts contained in ac
|
||||
* @param buf buffer where the SDP will be stored (must be allocated by
|
||||
* the caller)
|
||||
* @param size the size of the buffer
|
||||
* @return 0 if OK, AVERROR_xxx on error
|
||||
*/
|
||||
int av_sdp_create(AVFormatContext *ac[], int n_files, char *buf, int size);
|
||||
|
||||
/**
|
||||
* Return a positive value if the given filename has one of the given
|
||||
* extensions, 0 otherwise.
|
||||
*
|
||||
* @param filename file name to check against the given extensions
|
||||
* @param extensions a comma-separated list of filename extensions
|
||||
*/
|
||||
int av_match_ext(const char *filename, const char *extensions);
|
||||
|
||||
/**
|
||||
* Test if the given container can store a codec.
|
||||
*
|
||||
* @param ofmt container to check for compatibility
|
||||
* @param codec_id codec to potentially store in container
|
||||
* @param std_compliance standards compliance level, one of FF_COMPLIANCE_*
|
||||
*
|
||||
* @return 1 if codec with ID codec_id can be stored in ofmt, 0 if it cannot.
|
||||
* A negative number if this information is not available.
|
||||
*/
|
||||
int avformat_query_codec(const AVOutputFormat *ofmt, enum AVCodecID codec_id,
|
||||
int std_compliance);
|
||||
|
||||
/**
|
||||
* @defgroup riff_fourcc RIFF FourCCs
|
||||
* @{
|
||||
* Get the tables mapping RIFF FourCCs to libavcodec AVCodecIDs. The tables are
|
||||
* meant to be passed to av_codec_get_id()/av_codec_get_tag() as in the
|
||||
* following code:
|
||||
* @code
|
||||
* uint32_t tag = MKTAG('H', '2', '6', '4');
|
||||
* const struct AVCodecTag *table[] = { avformat_get_riff_video_tags(), 0 };
|
||||
* enum AVCodecID id = av_codec_get_id(table, tag);
|
||||
* @endcode
|
||||
*/
|
||||
/**
|
||||
* @return the table mapping RIFF FourCCs for video to libavcodec AVCodecID.
|
||||
*/
|
||||
const struct AVCodecTag *avformat_get_riff_video_tags(void);
|
||||
/**
|
||||
* @return the table mapping RIFF FourCCs for audio to AVCodecID.
|
||||
*/
|
||||
const struct AVCodecTag *avformat_get_riff_audio_tags(void);
|
||||
/**
|
||||
* @return the table mapping MOV FourCCs for video to libavcodec AVCodecID.
|
||||
*/
|
||||
const struct AVCodecTag *avformat_get_mov_video_tags(void);
|
||||
/**
|
||||
* @return the table mapping MOV FourCCs for audio to AVCodecID.
|
||||
*/
|
||||
const struct AVCodecTag *avformat_get_mov_audio_tags(void);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Guess the sample aspect ratio of a frame, based on both the stream and the
|
||||
* frame aspect ratio.
|
||||
*
|
||||
* Since the frame aspect ratio is set by the codec but the stream aspect ratio
|
||||
* is set by the demuxer, these two may not be equal. This function tries to
|
||||
* return the value that you should use if you would like to display the frame.
|
||||
*
|
||||
* Basic logic is to use the stream aspect ratio if it is set to something sane
|
||||
* otherwise use the frame aspect ratio. This way a container setting, which is
|
||||
* usually easy to modify can override the coded value in the frames.
|
||||
*
|
||||
* @param format the format context which the stream is part of
|
||||
* @param stream the stream which the frame is part of
|
||||
* @param frame the frame with the aspect ratio to be determined
|
||||
* @return the guessed (valid) sample_aspect_ratio, 0/1 if no idea
|
||||
*/
|
||||
AVRational av_guess_sample_aspect_ratio(AVFormatContext *format, AVStream *stream, AVFrame *frame);
|
||||
|
||||
/**
|
||||
* Guess the frame rate, based on both the container and codec information.
|
||||
*
|
||||
* @param ctx the format context which the stream is part of
|
||||
* @param stream the stream which the frame is part of
|
||||
* @param frame the frame for which the frame rate should be determined, may be NULL
|
||||
* @return the guessed (valid) frame rate, 0/1 if no idea
|
||||
*/
|
||||
AVRational av_guess_frame_rate(AVFormatContext *ctx, AVStream *stream, AVFrame *frame);
|
||||
|
||||
/**
|
||||
* Check if the stream st contained in s is matched by the stream specifier
|
||||
* spec.
|
||||
*
|
||||
* See the "stream specifiers" chapter in the documentation for the syntax
|
||||
* of spec.
|
||||
*
|
||||
* @return >0 if st is matched by spec;
|
||||
* 0 if st is not matched by spec;
|
||||
* AVERROR code if spec is invalid
|
||||
*
|
||||
* @note A stream specifier can match several streams in the format.
|
||||
*/
|
||||
int avformat_match_stream_specifier(AVFormatContext *s, AVStream *st,
|
||||
const char *spec);
|
||||
|
||||
int avformat_queue_attached_pictures(AVFormatContext *s);
|
||||
|
||||
#if FF_API_OLD_BSF
|
||||
/**
|
||||
* Apply a list of bitstream filters to a packet.
|
||||
*
|
||||
* @param codec AVCodecContext, usually from an AVStream
|
||||
* @param pkt the packet to apply filters to. If, on success, the returned
|
||||
* packet has size == 0 and side_data_elems == 0, it indicates that
|
||||
* the packet should be dropped
|
||||
* @param bsfc a NULL-terminated list of filters to apply
|
||||
* @return >=0 on success;
|
||||
* AVERROR code on failure
|
||||
*/
|
||||
attribute_deprecated
|
||||
int av_apply_bitstream_filters(AVCodecContext *codec, AVPacket *pkt,
|
||||
AVBitStreamFilterContext *bsfc);
|
||||
#endif
|
||||
|
||||
enum AVTimebaseSource {
|
||||
AVFMT_TBCF_AUTO = -1,
|
||||
AVFMT_TBCF_DECODER,
|
||||
AVFMT_TBCF_DEMUXER,
|
||||
#if FF_API_R_FRAME_RATE
|
||||
AVFMT_TBCF_R_FRAMERATE,
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
* Transfer internal timing information from one stream to another.
|
||||
*
|
||||
* This function is useful when doing stream copy.
|
||||
*
|
||||
* @param ofmt target output format for ost
|
||||
* @param ost output stream which needs timings copy and adjustments
|
||||
* @param ist reference input stream to copy timings from
|
||||
* @param copy_tb define from where the stream codec timebase needs to be imported
|
||||
*/
|
||||
int avformat_transfer_internal_stream_timing_info(const AVOutputFormat *ofmt,
|
||||
AVStream *ost, const AVStream *ist,
|
||||
enum AVTimebaseSource copy_tb);
|
||||
|
||||
/**
|
||||
* Get the internal codec timebase from a stream.
|
||||
*
|
||||
* @param st input stream to extract the timebase from
|
||||
*/
|
||||
AVRational av_stream_get_codec_timebase(const AVStream *st);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* AVFORMAT_AVFORMAT_H */
|
||||
@@ -0,0 +1,861 @@
|
||||
/*
|
||||
* copyright (c) 2001 Fabrice Bellard
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#ifndef AVFORMAT_AVIO_H
|
||||
#define AVFORMAT_AVIO_H
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @ingroup lavf_io
|
||||
* Buffered I/O operations
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "libavutil/common.h"
|
||||
#include "libavutil/dict.h"
|
||||
#include "libavutil/log.h"
|
||||
|
||||
#include "libavformat/version.h"
|
||||
|
||||
/**
|
||||
* Seeking works like for a local file.
|
||||
*/
|
||||
#define AVIO_SEEKABLE_NORMAL (1 << 0)
|
||||
|
||||
/**
|
||||
* Seeking by timestamp with avio_seek_time() is possible.
|
||||
*/
|
||||
#define AVIO_SEEKABLE_TIME (1 << 1)
|
||||
|
||||
/**
|
||||
* Callback for checking whether to abort blocking functions.
|
||||
* AVERROR_EXIT is returned in this case by the interrupted
|
||||
* function. During blocking operations, callback is called with
|
||||
* opaque as parameter. If the callback returns 1, the
|
||||
* blocking operation will be aborted.
|
||||
*
|
||||
* No members can be added to this struct without a major bump, if
|
||||
* new elements have been added after this struct in AVFormatContext
|
||||
* or AVIOContext.
|
||||
*/
|
||||
typedef struct AVIOInterruptCB {
|
||||
int (*callback)(void*);
|
||||
void *opaque;
|
||||
} AVIOInterruptCB;
|
||||
|
||||
/**
|
||||
* Directory entry types.
|
||||
*/
|
||||
enum AVIODirEntryType {
|
||||
AVIO_ENTRY_UNKNOWN,
|
||||
AVIO_ENTRY_BLOCK_DEVICE,
|
||||
AVIO_ENTRY_CHARACTER_DEVICE,
|
||||
AVIO_ENTRY_DIRECTORY,
|
||||
AVIO_ENTRY_NAMED_PIPE,
|
||||
AVIO_ENTRY_SYMBOLIC_LINK,
|
||||
AVIO_ENTRY_SOCKET,
|
||||
AVIO_ENTRY_FILE,
|
||||
AVIO_ENTRY_SERVER,
|
||||
AVIO_ENTRY_SHARE,
|
||||
AVIO_ENTRY_WORKGROUP,
|
||||
};
|
||||
|
||||
/**
|
||||
* Describes single entry of the directory.
|
||||
*
|
||||
* Only name and type fields are guaranteed be set.
|
||||
* Rest of fields are protocol or/and platform dependent and might be unknown.
|
||||
*/
|
||||
typedef struct AVIODirEntry {
|
||||
char *name; /**< Filename */
|
||||
int type; /**< Type of the entry */
|
||||
int utf8; /**< Set to 1 when name is encoded with UTF-8, 0 otherwise.
|
||||
Name can be encoded with UTF-8 even though 0 is set. */
|
||||
int64_t size; /**< File size in bytes, -1 if unknown. */
|
||||
int64_t modification_timestamp; /**< Time of last modification in microseconds since unix
|
||||
epoch, -1 if unknown. */
|
||||
int64_t access_timestamp; /**< Time of last access in microseconds since unix epoch,
|
||||
-1 if unknown. */
|
||||
int64_t status_change_timestamp; /**< Time of last status change in microseconds since unix
|
||||
epoch, -1 if unknown. */
|
||||
int64_t user_id; /**< User ID of owner, -1 if unknown. */
|
||||
int64_t group_id; /**< Group ID of owner, -1 if unknown. */
|
||||
int64_t filemode; /**< Unix file mode, -1 if unknown. */
|
||||
} AVIODirEntry;
|
||||
|
||||
typedef struct AVIODirContext {
|
||||
struct URLContext *url_context;
|
||||
} AVIODirContext;
|
||||
|
||||
/**
|
||||
* Different data types that can be returned via the AVIO
|
||||
* write_data_type callback.
|
||||
*/
|
||||
enum AVIODataMarkerType {
|
||||
/**
|
||||
* Header data; this needs to be present for the stream to be decodeable.
|
||||
*/
|
||||
AVIO_DATA_MARKER_HEADER,
|
||||
/**
|
||||
* A point in the output bytestream where a decoder can start decoding
|
||||
* (i.e. a keyframe). A demuxer/decoder given the data flagged with
|
||||
* AVIO_DATA_MARKER_HEADER, followed by any AVIO_DATA_MARKER_SYNC_POINT,
|
||||
* should give decodeable results.
|
||||
*/
|
||||
AVIO_DATA_MARKER_SYNC_POINT,
|
||||
/**
|
||||
* A point in the output bytestream where a demuxer can start parsing
|
||||
* (for non self synchronizing bytestream formats). That is, any
|
||||
* non-keyframe packet start point.
|
||||
*/
|
||||
AVIO_DATA_MARKER_BOUNDARY_POINT,
|
||||
/**
|
||||
* This is any, unlabelled data. It can either be a muxer not marking
|
||||
* any positions at all, it can be an actual boundary/sync point
|
||||
* that the muxer chooses not to mark, or a later part of a packet/fragment
|
||||
* that is cut into multiple write callbacks due to limited IO buffer size.
|
||||
*/
|
||||
AVIO_DATA_MARKER_UNKNOWN,
|
||||
/**
|
||||
* Trailer data, which doesn't contain actual content, but only for
|
||||
* finalizing the output file.
|
||||
*/
|
||||
AVIO_DATA_MARKER_TRAILER,
|
||||
/**
|
||||
* A point in the output bytestream where the underlying AVIOContext might
|
||||
* flush the buffer depending on latency or buffering requirements. Typically
|
||||
* means the end of a packet.
|
||||
*/
|
||||
AVIO_DATA_MARKER_FLUSH_POINT,
|
||||
};
|
||||
|
||||
/**
|
||||
* Bytestream IO Context.
|
||||
* New fields can be added to the end with minor version bumps.
|
||||
* Removal, reordering and changes to existing fields require a major
|
||||
* version bump.
|
||||
* sizeof(AVIOContext) must not be used outside libav*.
|
||||
*
|
||||
* @note None of the function pointers in AVIOContext should be called
|
||||
* directly, they should only be set by the client application
|
||||
* when implementing custom I/O. Normally these are set to the
|
||||
* function pointers specified in avio_alloc_context()
|
||||
*/
|
||||
typedef struct AVIOContext {
|
||||
/**
|
||||
* A class for private options.
|
||||
*
|
||||
* If this AVIOContext is created by avio_open2(), av_class is set and
|
||||
* passes the options down to protocols.
|
||||
*
|
||||
* If this AVIOContext is manually allocated, then av_class may be set by
|
||||
* the caller.
|
||||
*
|
||||
* warning -- this field can be NULL, be sure to not pass this AVIOContext
|
||||
* to any av_opt_* functions in that case.
|
||||
*/
|
||||
const AVClass *av_class;
|
||||
|
||||
/*
|
||||
* The following shows the relationship between buffer, buf_ptr,
|
||||
* buf_ptr_max, buf_end, buf_size, and pos, when reading and when writing
|
||||
* (since AVIOContext is used for both):
|
||||
*
|
||||
**********************************************************************************
|
||||
* READING
|
||||
**********************************************************************************
|
||||
*
|
||||
* | buffer_size |
|
||||
* |---------------------------------------|
|
||||
* | |
|
||||
*
|
||||
* buffer buf_ptr buf_end
|
||||
* +---------------+-----------------------+
|
||||
* |/ / / / / / / /|/ / / / / / /| |
|
||||
* read buffer: |/ / consumed / | to be read /| |
|
||||
* |/ / / / / / / /|/ / / / / / /| |
|
||||
* +---------------+-----------------------+
|
||||
*
|
||||
* pos
|
||||
* +-------------------------------------------+-----------------+
|
||||
* input file: | | |
|
||||
* +-------------------------------------------+-----------------+
|
||||
*
|
||||
*
|
||||
**********************************************************************************
|
||||
* WRITING
|
||||
**********************************************************************************
|
||||
*
|
||||
* | buffer_size |
|
||||
* |--------------------------------------|
|
||||
* | |
|
||||
*
|
||||
* buf_ptr_max
|
||||
* buffer (buf_ptr) buf_end
|
||||
* +-----------------------+--------------+
|
||||
* |/ / / / / / / / / / / /| |
|
||||
* write buffer: | / / to be flushed / / | |
|
||||
* |/ / / / / / / / / / / /| |
|
||||
* +-----------------------+--------------+
|
||||
* buf_ptr can be in this
|
||||
* due to a backward seek
|
||||
*
|
||||
* pos
|
||||
* +-------------+----------------------------------------------+
|
||||
* output file: | | |
|
||||
* +-------------+----------------------------------------------+
|
||||
*
|
||||
*/
|
||||
unsigned char *buffer; /**< Start of the buffer. */
|
||||
int buffer_size; /**< Maximum buffer size */
|
||||
unsigned char *buf_ptr; /**< Current position in the buffer */
|
||||
unsigned char *buf_end; /**< End of the data, may be less than
|
||||
buffer+buffer_size if the read function returned
|
||||
less data than requested, e.g. for streams where
|
||||
no more data has been received yet. */
|
||||
void *opaque; /**< A private pointer, passed to the read/write/seek/...
|
||||
functions. */
|
||||
int (*read_packet)(void *opaque, uint8_t *buf, int buf_size);
|
||||
int (*write_packet)(void *opaque, uint8_t *buf, int buf_size);
|
||||
int64_t (*seek)(void *opaque, int64_t offset, int whence);
|
||||
int64_t pos; /**< position in the file of the current buffer */
|
||||
int eof_reached; /**< true if eof reached */
|
||||
int write_flag; /**< true if open for writing */
|
||||
int max_packet_size;
|
||||
unsigned long checksum;
|
||||
unsigned char *checksum_ptr;
|
||||
unsigned long (*update_checksum)(unsigned long checksum, const uint8_t *buf, unsigned int size);
|
||||
int error; /**< contains the error code or 0 if no error happened */
|
||||
/**
|
||||
* Pause or resume playback for network streaming protocols - e.g. MMS.
|
||||
*/
|
||||
int (*read_pause)(void *opaque, int pause);
|
||||
/**
|
||||
* Seek to a given timestamp in stream with the specified stream_index.
|
||||
* Needed for some network streaming protocols which don't support seeking
|
||||
* to byte position.
|
||||
*/
|
||||
int64_t (*read_seek)(void *opaque, int stream_index,
|
||||
int64_t timestamp, int flags);
|
||||
/**
|
||||
* A combination of AVIO_SEEKABLE_ flags or 0 when the stream is not seekable.
|
||||
*/
|
||||
int seekable;
|
||||
|
||||
/**
|
||||
* max filesize, used to limit allocations
|
||||
* This field is internal to libavformat and access from outside is not allowed.
|
||||
*/
|
||||
int64_t maxsize;
|
||||
|
||||
/**
|
||||
* avio_read and avio_write should if possible be satisfied directly
|
||||
* instead of going through a buffer, and avio_seek will always
|
||||
* call the underlying seek function directly.
|
||||
*/
|
||||
int direct;
|
||||
|
||||
/**
|
||||
* Bytes read statistic
|
||||
* This field is internal to libavformat and access from outside is not allowed.
|
||||
*/
|
||||
int64_t bytes_read;
|
||||
|
||||
/**
|
||||
* seek statistic
|
||||
* This field is internal to libavformat and access from outside is not allowed.
|
||||
*/
|
||||
int seek_count;
|
||||
|
||||
/**
|
||||
* writeout statistic
|
||||
* This field is internal to libavformat and access from outside is not allowed.
|
||||
*/
|
||||
int writeout_count;
|
||||
|
||||
/**
|
||||
* Original buffer size
|
||||
* used internally after probing and ensure seekback to reset the buffer size
|
||||
* This field is internal to libavformat and access from outside is not allowed.
|
||||
*/
|
||||
int orig_buffer_size;
|
||||
|
||||
/**
|
||||
* Threshold to favor readahead over seek.
|
||||
* This is current internal only, do not use from outside.
|
||||
*/
|
||||
int short_seek_threshold;
|
||||
|
||||
/**
|
||||
* ',' separated list of allowed protocols.
|
||||
*/
|
||||
const char *protocol_whitelist;
|
||||
|
||||
/**
|
||||
* ',' separated list of disallowed protocols.
|
||||
*/
|
||||
const char *protocol_blacklist;
|
||||
|
||||
/**
|
||||
* A callback that is used instead of write_packet.
|
||||
*/
|
||||
int (*write_data_type)(void *opaque, uint8_t *buf, int buf_size,
|
||||
enum AVIODataMarkerType type, int64_t time);
|
||||
/**
|
||||
* If set, don't call write_data_type separately for AVIO_DATA_MARKER_BOUNDARY_POINT,
|
||||
* but ignore them and treat them as AVIO_DATA_MARKER_UNKNOWN (to avoid needlessly
|
||||
* small chunks of data returned from the callback).
|
||||
*/
|
||||
int ignore_boundary_point;
|
||||
|
||||
/**
|
||||
* Internal, not meant to be used from outside of AVIOContext.
|
||||
*/
|
||||
enum AVIODataMarkerType current_type;
|
||||
int64_t last_time;
|
||||
|
||||
/**
|
||||
* A callback that is used instead of short_seek_threshold.
|
||||
* This is current internal only, do not use from outside.
|
||||
*/
|
||||
int (*short_seek_get)(void *opaque);
|
||||
|
||||
int64_t written;
|
||||
|
||||
/**
|
||||
* Maximum reached position before a backward seek in the write buffer,
|
||||
* used keeping track of already written data for a later flush.
|
||||
*/
|
||||
unsigned char *buf_ptr_max;
|
||||
|
||||
/**
|
||||
* Try to buffer at least this amount of data before flushing it
|
||||
*/
|
||||
int min_packet_size;
|
||||
} AVIOContext;
|
||||
|
||||
/**
|
||||
* Return the name of the protocol that will handle the passed URL.
|
||||
*
|
||||
* NULL is returned if no protocol could be found for the given URL.
|
||||
*
|
||||
* @return Name of the protocol or NULL.
|
||||
*/
|
||||
const char *avio_find_protocol_name(const char *url);
|
||||
|
||||
/**
|
||||
* Return AVIO_FLAG_* access flags corresponding to the access permissions
|
||||
* of the resource in url, or a negative value corresponding to an
|
||||
* AVERROR code in case of failure. The returned access flags are
|
||||
* masked by the value in flags.
|
||||
*
|
||||
* @note This function is intrinsically unsafe, in the sense that the
|
||||
* checked resource may change its existence or permission status from
|
||||
* one call to another. Thus you should not trust the returned value,
|
||||
* unless you are sure that no other processes are accessing the
|
||||
* checked resource.
|
||||
*/
|
||||
int avio_check(const char *url, int flags);
|
||||
|
||||
/**
|
||||
* Move or rename a resource.
|
||||
*
|
||||
* @note url_src and url_dst should share the same protocol and authority.
|
||||
*
|
||||
* @param url_src url to resource to be moved
|
||||
* @param url_dst new url to resource if the operation succeeded
|
||||
* @return >=0 on success or negative on error.
|
||||
*/
|
||||
int avpriv_io_move(const char *url_src, const char *url_dst);
|
||||
|
||||
/**
|
||||
* Delete a resource.
|
||||
*
|
||||
* @param url resource to be deleted.
|
||||
* @return >=0 on success or negative on error.
|
||||
*/
|
||||
int avpriv_io_delete(const char *url);
|
||||
|
||||
/**
|
||||
* Open directory for reading.
|
||||
*
|
||||
* @param s directory read context. Pointer to a NULL pointer must be passed.
|
||||
* @param url directory to be listed.
|
||||
* @param options A dictionary filled with protocol-private options. On return
|
||||
* this parameter will be destroyed and replaced with a dictionary
|
||||
* containing options that were not found. May be NULL.
|
||||
* @return >=0 on success or negative on error.
|
||||
*/
|
||||
int avio_open_dir(AVIODirContext **s, const char *url, AVDictionary **options);
|
||||
|
||||
/**
|
||||
* Get next directory entry.
|
||||
*
|
||||
* Returned entry must be freed with avio_free_directory_entry(). In particular
|
||||
* it may outlive AVIODirContext.
|
||||
*
|
||||
* @param s directory read context.
|
||||
* @param[out] next next entry or NULL when no more entries.
|
||||
* @return >=0 on success or negative on error. End of list is not considered an
|
||||
* error.
|
||||
*/
|
||||
int avio_read_dir(AVIODirContext *s, AVIODirEntry **next);
|
||||
|
||||
/**
|
||||
* Close directory.
|
||||
*
|
||||
* @note Entries created using avio_read_dir() are not deleted and must be
|
||||
* freeded with avio_free_directory_entry().
|
||||
*
|
||||
* @param s directory read context.
|
||||
* @return >=0 on success or negative on error.
|
||||
*/
|
||||
int avio_close_dir(AVIODirContext **s);
|
||||
|
||||
/**
|
||||
* Free entry allocated by avio_read_dir().
|
||||
*
|
||||
* @param entry entry to be freed.
|
||||
*/
|
||||
void avio_free_directory_entry(AVIODirEntry **entry);
|
||||
|
||||
/**
|
||||
* Allocate and initialize an AVIOContext for buffered I/O. It must be later
|
||||
* freed with avio_context_free().
|
||||
*
|
||||
* @param buffer Memory block for input/output operations via AVIOContext.
|
||||
* The buffer must be allocated with av_malloc() and friends.
|
||||
* It may be freed and replaced with a new buffer by libavformat.
|
||||
* AVIOContext.buffer holds the buffer currently in use,
|
||||
* which must be later freed with av_free().
|
||||
* @param buffer_size The buffer size is very important for performance.
|
||||
* For protocols with fixed blocksize it should be set to this blocksize.
|
||||
* For others a typical size is a cache page, e.g. 4kb.
|
||||
* @param write_flag Set to 1 if the buffer should be writable, 0 otherwise.
|
||||
* @param opaque An opaque pointer to user-specific data.
|
||||
* @param read_packet A function for refilling the buffer, may be NULL.
|
||||
* For stream protocols, must never return 0 but rather
|
||||
* a proper AVERROR code.
|
||||
* @param write_packet A function for writing the buffer contents, may be NULL.
|
||||
* The function may not change the input buffers content.
|
||||
* @param seek A function for seeking to specified byte position, may be NULL.
|
||||
*
|
||||
* @return Allocated AVIOContext or NULL on failure.
|
||||
*/
|
||||
AVIOContext *avio_alloc_context(
|
||||
unsigned char *buffer,
|
||||
int buffer_size,
|
||||
int write_flag,
|
||||
void *opaque,
|
||||
int (*read_packet)(void *opaque, uint8_t *buf, int buf_size),
|
||||
int (*write_packet)(void *opaque, uint8_t *buf, int buf_size),
|
||||
int64_t (*seek)(void *opaque, int64_t offset, int whence));
|
||||
|
||||
/**
|
||||
* Free the supplied IO context and everything associated with it.
|
||||
*
|
||||
* @param s Double pointer to the IO context. This function will write NULL
|
||||
* into s.
|
||||
*/
|
||||
void avio_context_free(AVIOContext **s);
|
||||
|
||||
void avio_w8(AVIOContext *s, int b);
|
||||
void avio_write(AVIOContext *s, const unsigned char *buf, int size);
|
||||
void avio_wl64(AVIOContext *s, uint64_t val);
|
||||
void avio_wb64(AVIOContext *s, uint64_t val);
|
||||
void avio_wl32(AVIOContext *s, unsigned int val);
|
||||
void avio_wb32(AVIOContext *s, unsigned int val);
|
||||
void avio_wl24(AVIOContext *s, unsigned int val);
|
||||
void avio_wb24(AVIOContext *s, unsigned int val);
|
||||
void avio_wl16(AVIOContext *s, unsigned int val);
|
||||
void avio_wb16(AVIOContext *s, unsigned int val);
|
||||
|
||||
/**
|
||||
* Write a NULL-terminated string.
|
||||
* @return number of bytes written.
|
||||
*/
|
||||
int avio_put_str(AVIOContext *s, const char *str);
|
||||
|
||||
/**
|
||||
* Convert an UTF-8 string to UTF-16LE and write it.
|
||||
* @param s the AVIOContext
|
||||
* @param str NULL-terminated UTF-8 string
|
||||
*
|
||||
* @return number of bytes written.
|
||||
*/
|
||||
int avio_put_str16le(AVIOContext *s, const char *str);
|
||||
|
||||
/**
|
||||
* Convert an UTF-8 string to UTF-16BE and write it.
|
||||
* @param s the AVIOContext
|
||||
* @param str NULL-terminated UTF-8 string
|
||||
*
|
||||
* @return number of bytes written.
|
||||
*/
|
||||
int avio_put_str16be(AVIOContext *s, const char *str);
|
||||
|
||||
/**
|
||||
* Mark the written bytestream as a specific type.
|
||||
*
|
||||
* Zero-length ranges are omitted from the output.
|
||||
*
|
||||
* @param time the stream time the current bytestream pos corresponds to
|
||||
* (in AV_TIME_BASE units), or AV_NOPTS_VALUE if unknown or not
|
||||
* applicable
|
||||
* @param type the kind of data written starting at the current pos
|
||||
*/
|
||||
void avio_write_marker(AVIOContext *s, int64_t time, enum AVIODataMarkerType type);
|
||||
|
||||
/**
|
||||
* ORing this as the "whence" parameter to a seek function causes it to
|
||||
* return the filesize without seeking anywhere. Supporting this is optional.
|
||||
* If it is not supported then the seek function will return <0.
|
||||
*/
|
||||
#define AVSEEK_SIZE 0x10000
|
||||
|
||||
/**
|
||||
* Passing this flag as the "whence" parameter to a seek function causes it to
|
||||
* seek by any means (like reopening and linear reading) or other normally unreasonable
|
||||
* means that can be extremely slow.
|
||||
* This may be ignored by the seek code.
|
||||
*/
|
||||
#define AVSEEK_FORCE 0x20000
|
||||
|
||||
/**
|
||||
* fseek() equivalent for AVIOContext.
|
||||
* @return new position or AVERROR.
|
||||
*/
|
||||
int64_t avio_seek(AVIOContext *s, int64_t offset, int whence);
|
||||
|
||||
/**
|
||||
* Skip given number of bytes forward
|
||||
* @return new position or AVERROR.
|
||||
*/
|
||||
int64_t avio_skip(AVIOContext *s, int64_t offset);
|
||||
|
||||
/**
|
||||
* ftell() equivalent for AVIOContext.
|
||||
* @return position or AVERROR.
|
||||
*/
|
||||
static av_always_inline int64_t avio_tell(AVIOContext *s)
|
||||
{
|
||||
return avio_seek(s, 0, SEEK_CUR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the filesize.
|
||||
* @return filesize or AVERROR
|
||||
*/
|
||||
int64_t avio_size(AVIOContext *s);
|
||||
|
||||
/**
|
||||
* feof() equivalent for AVIOContext.
|
||||
* @return non zero if and only if end of file
|
||||
*/
|
||||
int avio_feof(AVIOContext *s);
|
||||
|
||||
/** @warning Writes up to 4 KiB per call */
|
||||
int avio_printf(AVIOContext *s, const char *fmt, ...) av_printf_format(2, 3);
|
||||
|
||||
/**
|
||||
* Force flushing of buffered data.
|
||||
*
|
||||
* For write streams, force the buffered data to be immediately written to the output,
|
||||
* without to wait to fill the internal buffer.
|
||||
*
|
||||
* For read streams, discard all currently buffered data, and advance the
|
||||
* reported file position to that of the underlying stream. This does not
|
||||
* read new data, and does not perform any seeks.
|
||||
*/
|
||||
void avio_flush(AVIOContext *s);
|
||||
|
||||
/**
|
||||
* Read size bytes from AVIOContext into buf.
|
||||
* @return number of bytes read or AVERROR
|
||||
*/
|
||||
int avio_read(AVIOContext *s, unsigned char *buf, int size);
|
||||
|
||||
/**
|
||||
* Read size bytes from AVIOContext into buf. Unlike avio_read(), this is allowed
|
||||
* to read fewer bytes than requested. The missing bytes can be read in the next
|
||||
* call. This always tries to read at least 1 byte.
|
||||
* Useful to reduce latency in certain cases.
|
||||
* @return number of bytes read or AVERROR
|
||||
*/
|
||||
int avio_read_partial(AVIOContext *s, unsigned char *buf, int size);
|
||||
|
||||
/**
|
||||
* @name Functions for reading from AVIOContext
|
||||
* @{
|
||||
*
|
||||
* @note return 0 if EOF, so you cannot use it if EOF handling is
|
||||
* necessary
|
||||
*/
|
||||
int avio_r8 (AVIOContext *s);
|
||||
unsigned int avio_rl16(AVIOContext *s);
|
||||
unsigned int avio_rl24(AVIOContext *s);
|
||||
unsigned int avio_rl32(AVIOContext *s);
|
||||
uint64_t avio_rl64(AVIOContext *s);
|
||||
unsigned int avio_rb16(AVIOContext *s);
|
||||
unsigned int avio_rb24(AVIOContext *s);
|
||||
unsigned int avio_rb32(AVIOContext *s);
|
||||
uint64_t avio_rb64(AVIOContext *s);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Read a string from pb into buf. The reading will terminate when either
|
||||
* a NULL character was encountered, maxlen bytes have been read, or nothing
|
||||
* more can be read from pb. The result is guaranteed to be NULL-terminated, it
|
||||
* will be truncated if buf is too small.
|
||||
* Note that the string is not interpreted or validated in any way, it
|
||||
* might get truncated in the middle of a sequence for multi-byte encodings.
|
||||
*
|
||||
* @return number of bytes read (is always <= maxlen).
|
||||
* If reading ends on EOF or error, the return value will be one more than
|
||||
* bytes actually read.
|
||||
*/
|
||||
int avio_get_str(AVIOContext *pb, int maxlen, char *buf, int buflen);
|
||||
|
||||
/**
|
||||
* Read a UTF-16 string from pb and convert it to UTF-8.
|
||||
* The reading will terminate when either a null or invalid character was
|
||||
* encountered or maxlen bytes have been read.
|
||||
* @return number of bytes read (is always <= maxlen)
|
||||
*/
|
||||
int avio_get_str16le(AVIOContext *pb, int maxlen, char *buf, int buflen);
|
||||
int avio_get_str16be(AVIOContext *pb, int maxlen, char *buf, int buflen);
|
||||
|
||||
|
||||
/**
|
||||
* @name URL open modes
|
||||
* The flags argument to avio_open must be one of the following
|
||||
* constants, optionally ORed with other flags.
|
||||
* @{
|
||||
*/
|
||||
#define AVIO_FLAG_READ 1 /**< read-only */
|
||||
#define AVIO_FLAG_WRITE 2 /**< write-only */
|
||||
#define AVIO_FLAG_READ_WRITE (AVIO_FLAG_READ|AVIO_FLAG_WRITE) /**< read-write pseudo flag */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Use non-blocking mode.
|
||||
* If this flag is set, operations on the context will return
|
||||
* AVERROR(EAGAIN) if they can not be performed immediately.
|
||||
* If this flag is not set, operations on the context will never return
|
||||
* AVERROR(EAGAIN).
|
||||
* Note that this flag does not affect the opening/connecting of the
|
||||
* context. Connecting a protocol will always block if necessary (e.g. on
|
||||
* network protocols) but never hang (e.g. on busy devices).
|
||||
* Warning: non-blocking protocols is work-in-progress; this flag may be
|
||||
* silently ignored.
|
||||
*/
|
||||
#define AVIO_FLAG_NONBLOCK 8
|
||||
|
||||
/**
|
||||
* Use direct mode.
|
||||
* avio_read and avio_write should if possible be satisfied directly
|
||||
* instead of going through a buffer, and avio_seek will always
|
||||
* call the underlying seek function directly.
|
||||
*/
|
||||
#define AVIO_FLAG_DIRECT 0x8000
|
||||
|
||||
/**
|
||||
* Create and initialize a AVIOContext for accessing the
|
||||
* resource indicated by url.
|
||||
* @note When the resource indicated by url has been opened in
|
||||
* read+write mode, the AVIOContext can be used only for writing.
|
||||
*
|
||||
* @param s Used to return the pointer to the created AVIOContext.
|
||||
* In case of failure the pointed to value is set to NULL.
|
||||
* @param url resource to access
|
||||
* @param flags flags which control how the resource indicated by url
|
||||
* is to be opened
|
||||
* @return >= 0 in case of success, a negative value corresponding to an
|
||||
* AVERROR code in case of failure
|
||||
*/
|
||||
int avio_open(AVIOContext **s, const char *url, int flags);
|
||||
|
||||
/**
|
||||
* Create and initialize a AVIOContext for accessing the
|
||||
* resource indicated by url.
|
||||
* @note When the resource indicated by url has been opened in
|
||||
* read+write mode, the AVIOContext can be used only for writing.
|
||||
*
|
||||
* @param s Used to return the pointer to the created AVIOContext.
|
||||
* In case of failure the pointed to value is set to NULL.
|
||||
* @param url resource to access
|
||||
* @param flags flags which control how the resource indicated by url
|
||||
* is to be opened
|
||||
* @param int_cb an interrupt callback to be used at the protocols level
|
||||
* @param options A dictionary filled with protocol-private options. On return
|
||||
* this parameter will be destroyed and replaced with a dict containing options
|
||||
* that were not found. May be NULL.
|
||||
* @return >= 0 in case of success, a negative value corresponding to an
|
||||
* AVERROR code in case of failure
|
||||
*/
|
||||
int avio_open2(AVIOContext **s, const char *url, int flags,
|
||||
const AVIOInterruptCB *int_cb, AVDictionary **options);
|
||||
|
||||
/**
|
||||
* Close the resource accessed by the AVIOContext s and free it.
|
||||
* This function can only be used if s was opened by avio_open().
|
||||
*
|
||||
* The internal buffer is automatically flushed before closing the
|
||||
* resource.
|
||||
*
|
||||
* @return 0 on success, an AVERROR < 0 on error.
|
||||
* @see avio_closep
|
||||
*/
|
||||
int avio_close(AVIOContext *s);
|
||||
|
||||
/**
|
||||
* Close the resource accessed by the AVIOContext *s, free it
|
||||
* and set the pointer pointing to it to NULL.
|
||||
* This function can only be used if s was opened by avio_open().
|
||||
*
|
||||
* The internal buffer is automatically flushed before closing the
|
||||
* resource.
|
||||
*
|
||||
* @return 0 on success, an AVERROR < 0 on error.
|
||||
* @see avio_close
|
||||
*/
|
||||
int avio_closep(AVIOContext **s);
|
||||
|
||||
|
||||
/**
|
||||
* Open a write only memory stream.
|
||||
*
|
||||
* @param s new IO context
|
||||
* @return zero if no error.
|
||||
*/
|
||||
int avio_open_dyn_buf(AVIOContext **s);
|
||||
|
||||
/**
|
||||
* Return the written size and a pointer to the buffer.
|
||||
* The AVIOContext stream is left intact.
|
||||
* The buffer must NOT be freed.
|
||||
* No padding is added to the buffer.
|
||||
*
|
||||
* @param s IO context
|
||||
* @param pbuffer pointer to a byte buffer
|
||||
* @return the length of the byte buffer
|
||||
*/
|
||||
int avio_get_dyn_buf(AVIOContext *s, uint8_t **pbuffer);
|
||||
|
||||
/**
|
||||
* Return the written size and a pointer to the buffer. The buffer
|
||||
* must be freed with av_free().
|
||||
* Padding of AV_INPUT_BUFFER_PADDING_SIZE is added to the buffer.
|
||||
*
|
||||
* @param s IO context
|
||||
* @param pbuffer pointer to a byte buffer
|
||||
* @return the length of the byte buffer
|
||||
*/
|
||||
int avio_close_dyn_buf(AVIOContext *s, uint8_t **pbuffer);
|
||||
|
||||
/**
|
||||
* Iterate through names of available protocols.
|
||||
*
|
||||
* @param opaque A private pointer representing current protocol.
|
||||
* It must be a pointer to NULL on first iteration and will
|
||||
* be updated by successive calls to avio_enum_protocols.
|
||||
* @param output If set to 1, iterate over output protocols,
|
||||
* otherwise over input protocols.
|
||||
*
|
||||
* @return A static string containing the name of current protocol or NULL
|
||||
*/
|
||||
const char *avio_enum_protocols(void **opaque, int output);
|
||||
|
||||
/**
|
||||
* Pause and resume playing - only meaningful if using a network streaming
|
||||
* protocol (e.g. MMS).
|
||||
*
|
||||
* @param h IO context from which to call the read_pause function pointer
|
||||
* @param pause 1 for pause, 0 for resume
|
||||
*/
|
||||
int avio_pause(AVIOContext *h, int pause);
|
||||
|
||||
/**
|
||||
* Seek to a given timestamp relative to some component stream.
|
||||
* Only meaningful if using a network streaming protocol (e.g. MMS.).
|
||||
*
|
||||
* @param h IO context from which to call the seek function pointers
|
||||
* @param stream_index The stream index that the timestamp is relative to.
|
||||
* If stream_index is (-1) the timestamp should be in AV_TIME_BASE
|
||||
* units from the beginning of the presentation.
|
||||
* If a stream_index >= 0 is used and the protocol does not support
|
||||
* seeking based on component streams, the call will fail.
|
||||
* @param timestamp timestamp in AVStream.time_base units
|
||||
* or if there is no stream specified then in AV_TIME_BASE units.
|
||||
* @param flags Optional combination of AVSEEK_FLAG_BACKWARD, AVSEEK_FLAG_BYTE
|
||||
* and AVSEEK_FLAG_ANY. The protocol may silently ignore
|
||||
* AVSEEK_FLAG_BACKWARD and AVSEEK_FLAG_ANY, but AVSEEK_FLAG_BYTE will
|
||||
* fail if used and not supported.
|
||||
* @return >= 0 on success
|
||||
* @see AVInputFormat::read_seek
|
||||
*/
|
||||
int64_t avio_seek_time(AVIOContext *h, int stream_index,
|
||||
int64_t timestamp, int flags);
|
||||
|
||||
/* Avoid a warning. The header can not be included because it breaks c++. */
|
||||
struct AVBPrint;
|
||||
|
||||
/**
|
||||
* Read contents of h into print buffer, up to max_size bytes, or up to EOF.
|
||||
*
|
||||
* @return 0 for success (max_size bytes read or EOF reached), negative error
|
||||
* code otherwise
|
||||
*/
|
||||
int avio_read_to_bprint(AVIOContext *h, struct AVBPrint *pb, size_t max_size);
|
||||
|
||||
/**
|
||||
* Accept and allocate a client context on a server context.
|
||||
* @param s the server context
|
||||
* @param c the client context, must be unallocated
|
||||
* @return >= 0 on success or a negative value corresponding
|
||||
* to an AVERROR on failure
|
||||
*/
|
||||
int avio_accept(AVIOContext *s, AVIOContext **c);
|
||||
|
||||
/**
|
||||
* Perform one step of the protocol handshake to accept a new client.
|
||||
* This function must be called on a client returned by avio_accept() before
|
||||
* using it as a read/write context.
|
||||
* It is separate from avio_accept() because it may block.
|
||||
* A step of the handshake is defined by places where the application may
|
||||
* decide to change the proceedings.
|
||||
* For example, on a protocol with a request header and a reply header, each
|
||||
* one can constitute a step because the application may use the parameters
|
||||
* from the request to change parameters in the reply; or each individual
|
||||
* chunk of the request can constitute a step.
|
||||
* If the handshake is already finished, avio_handshake() does nothing and
|
||||
* returns 0 immediately.
|
||||
*
|
||||
* @param c the client context to perform the handshake on
|
||||
* @return 0 on a complete and successful handshake
|
||||
* > 0 if the handshake progressed, but is not complete
|
||||
* < 0 for an AVERROR code
|
||||
*/
|
||||
int avio_handshake(AVIOContext *c);
|
||||
#endif /* AVFORMAT_AVIO_H */
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Version macros.
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef AVFORMAT_VERSION_H
|
||||
#define AVFORMAT_VERSION_H
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @ingroup libavf
|
||||
* Libavformat version macros
|
||||
*/
|
||||
|
||||
#include "libavutil/version.h"
|
||||
|
||||
// Major bumping may affect Ticket5467, 5421, 5451(compatibility with Chromium)
|
||||
// Also please add any ticket numbers that you believe might be affected here
|
||||
#define LIBAVFORMAT_VERSION_MAJOR 58
|
||||
#define LIBAVFORMAT_VERSION_MINOR 17
|
||||
#define LIBAVFORMAT_VERSION_MICRO 101
|
||||
|
||||
#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
|
||||
LIBAVFORMAT_VERSION_MINOR, \
|
||||
LIBAVFORMAT_VERSION_MICRO)
|
||||
#define LIBAVFORMAT_VERSION AV_VERSION(LIBAVFORMAT_VERSION_MAJOR, \
|
||||
LIBAVFORMAT_VERSION_MINOR, \
|
||||
LIBAVFORMAT_VERSION_MICRO)
|
||||
#define LIBAVFORMAT_BUILD LIBAVFORMAT_VERSION_INT
|
||||
|
||||
#define LIBAVFORMAT_IDENT "Lavf" AV_STRINGIFY(LIBAVFORMAT_VERSION)
|
||||
|
||||
/**
|
||||
* FF_API_* defines may be placed below to indicate public API that will be
|
||||
* dropped at a future version bump. The defines themselves are not part of
|
||||
* the public API and may change, break or disappear at any time.
|
||||
*
|
||||
* @note, when bumping the major version it is recommended to manually
|
||||
* disable each FF_API_* in its own commit instead of disabling them all
|
||||
* at once through the bump. This improves the git bisect-ability of the change.
|
||||
*
|
||||
*/
|
||||
#ifndef FF_API_COMPUTE_PKT_FIELDS2
|
||||
#define FF_API_COMPUTE_PKT_FIELDS2 (LIBAVFORMAT_VERSION_MAJOR < 59)
|
||||
#endif
|
||||
#ifndef FF_API_OLD_OPEN_CALLBACKS
|
||||
#define FF_API_OLD_OPEN_CALLBACKS (LIBAVFORMAT_VERSION_MAJOR < 59)
|
||||
#endif
|
||||
#ifndef FF_API_LAVF_AVCTX
|
||||
#define FF_API_LAVF_AVCTX (LIBAVFORMAT_VERSION_MAJOR < 59)
|
||||
#endif
|
||||
#ifndef FF_API_HTTP_USER_AGENT
|
||||
#define FF_API_HTTP_USER_AGENT (LIBAVFORMAT_VERSION_MAJOR < 59)
|
||||
#endif
|
||||
#ifndef FF_API_HLS_WRAP
|
||||
#define FF_API_HLS_WRAP (LIBAVFORMAT_VERSION_MAJOR < 59)
|
||||
#endif
|
||||
#ifndef FF_API_LAVF_KEEPSIDE_FLAG
|
||||
#define FF_API_LAVF_KEEPSIDE_FLAG (LIBAVFORMAT_VERSION_MAJOR < 59)
|
||||
#endif
|
||||
#ifndef FF_API_OLD_ROTATE_API
|
||||
#define FF_API_OLD_ROTATE_API (LIBAVFORMAT_VERSION_MAJOR < 59)
|
||||
#endif
|
||||
#ifndef FF_API_FORMAT_GET_SET
|
||||
#define FF_API_FORMAT_GET_SET (LIBAVFORMAT_VERSION_MAJOR < 59)
|
||||
#endif
|
||||
#ifndef FF_API_OLD_AVIO_EOF_0
|
||||
#define FF_API_OLD_AVIO_EOF_0 (LIBAVFORMAT_VERSION_MAJOR < 59)
|
||||
#endif
|
||||
#ifndef FF_API_LAVF_FFSERVER
|
||||
#define FF_API_LAVF_FFSERVER (LIBAVFORMAT_VERSION_MAJOR < 59)
|
||||
#endif
|
||||
#ifndef FF_API_FORMAT_FILENAME
|
||||
#define FF_API_FORMAT_FILENAME (LIBAVFORMAT_VERSION_MAJOR < 59)
|
||||
#endif
|
||||
#ifndef FF_API_OLD_RTSP_OPTIONS
|
||||
#define FF_API_OLD_RTSP_OPTIONS (LIBAVFORMAT_VERSION_MAJOR < 59)
|
||||
#endif
|
||||
#ifndef FF_API_NEXT
|
||||
#define FF_API_NEXT (LIBAVFORMAT_VERSION_MAJOR < 59)
|
||||
#endif
|
||||
#ifndef FF_API_DASH_MIN_SEG_DURATION
|
||||
#define FF_API_DASH_MIN_SEG_DURATION (LIBAVFORMAT_VERSION_MAJOR < 59)
|
||||
#endif
|
||||
#ifndef FF_API_LAVF_MP4A_LATM
|
||||
#define FF_API_LAVF_MP4A_LATM (LIBAVFORMAT_VERSION_MAJOR < 59)
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef FF_API_R_FRAME_RATE
|
||||
#define FF_API_R_FRAME_RATE 1
|
||||
#endif
|
||||
#endif /* AVFORMAT_VERSION_H */
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2003 Michael Niedermayer ([email protected])
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* FFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef POSTPROC_POSTPROCESS_H
|
||||
#define POSTPROC_POSTPROCESS_H
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @ingroup lpp
|
||||
* external API header
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup lpp libpostproc
|
||||
* Video postprocessing library.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "libpostproc/version.h"
|
||||
|
||||
/**
|
||||
* Return the LIBPOSTPROC_VERSION_INT constant.
|
||||
*/
|
||||
unsigned postproc_version(void);
|
||||
|
||||
/**
|
||||
* Return the libpostproc build-time configuration.
|
||||
*/
|
||||
const char *postproc_configuration(void);
|
||||
|
||||
/**
|
||||
* Return the libpostproc license.
|
||||
*/
|
||||
const char *postproc_license(void);
|
||||
|
||||
#define PP_QUALITY_MAX 6
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
typedef void pp_context;
|
||||
typedef void pp_mode;
|
||||
|
||||
#if LIBPOSTPROC_VERSION_INT < (52<<16)
|
||||
typedef pp_context pp_context_t;
|
||||
typedef pp_mode pp_mode_t;
|
||||
extern const char *const pp_help; ///< a simple help text
|
||||
#else
|
||||
extern const char pp_help[]; ///< a simple help text
|
||||
#endif
|
||||
|
||||
void pp_postprocess(const uint8_t * src[3], const int srcStride[3],
|
||||
uint8_t * dst[3], const int dstStride[3],
|
||||
int horizontalSize, int verticalSize,
|
||||
const int8_t *QP_store, int QP_stride,
|
||||
pp_mode *mode, pp_context *ppContext, int pict_type);
|
||||
|
||||
|
||||
/**
|
||||
* Return a pp_mode or NULL if an error occurred.
|
||||
*
|
||||
* @param name the string after "-pp" on the command line
|
||||
* @param quality a number from 0 to PP_QUALITY_MAX
|
||||
*/
|
||||
pp_mode *pp_get_mode_by_name_and_quality(const char *name, int quality);
|
||||
void pp_free_mode(pp_mode *mode);
|
||||
|
||||
pp_context *pp_get_context(int width, int height, int flags);
|
||||
void pp_free_context(pp_context *ppContext);
|
||||
|
||||
#define PP_CPU_CAPS_MMX 0x80000000
|
||||
#define PP_CPU_CAPS_MMX2 0x20000000
|
||||
#define PP_CPU_CAPS_3DNOW 0x40000000
|
||||
#define PP_CPU_CAPS_ALTIVEC 0x10000000
|
||||
#define PP_CPU_CAPS_AUTO 0x00080000
|
||||
|
||||
#define PP_FORMAT 0x00000008
|
||||
#define PP_FORMAT_420 (0x00000011|PP_FORMAT)
|
||||
#define PP_FORMAT_422 (0x00000001|PP_FORMAT)
|
||||
#define PP_FORMAT_411 (0x00000002|PP_FORMAT)
|
||||
#define PP_FORMAT_444 (0x00000000|PP_FORMAT)
|
||||
#define PP_FORMAT_440 (0x00000010|PP_FORMAT)
|
||||
|
||||
#define PP_PICT_TYPE_QP2 0x00000010 ///< MPEG2 style QScale
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* POSTPROC_POSTPROCESS_H */
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Version macros.
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef POSTPROC_VERSION_H
|
||||
#define POSTPROC_VERSION_H
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Libpostproc version macros
|
||||
*/
|
||||
|
||||
#include "libavutil/avutil.h"
|
||||
|
||||
#define LIBPOSTPROC_VERSION_MAJOR 55
|
||||
#define LIBPOSTPROC_VERSION_MINOR 2
|
||||
#define LIBPOSTPROC_VERSION_MICRO 100
|
||||
|
||||
#define LIBPOSTPROC_VERSION_INT AV_VERSION_INT(LIBPOSTPROC_VERSION_MAJOR, \
|
||||
LIBPOSTPROC_VERSION_MINOR, \
|
||||
LIBPOSTPROC_VERSION_MICRO)
|
||||
#define LIBPOSTPROC_VERSION AV_VERSION(LIBPOSTPROC_VERSION_MAJOR, \
|
||||
LIBPOSTPROC_VERSION_MINOR, \
|
||||
LIBPOSTPROC_VERSION_MICRO)
|
||||
#define LIBPOSTPROC_BUILD LIBPOSTPROC_VERSION_INT
|
||||
|
||||
#define LIBPOSTPROC_IDENT "postproc" AV_STRINGIFY(LIBPOSTPROC_VERSION)
|
||||
|
||||
#endif /* POSTPROC_VERSION_H */
|
||||
@@ -0,0 +1,579 @@
|
||||
/*
|
||||
* Copyright (C) 2011-2013 Michael Niedermayer ([email protected])
|
||||
*
|
||||
* This file is part of libswresample
|
||||
*
|
||||
* libswresample is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* libswresample is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with libswresample; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef SWRESAMPLE_SWRESAMPLE_H
|
||||
#define SWRESAMPLE_SWRESAMPLE_H
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @ingroup lswr
|
||||
* libswresample public header
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup lswr libswresample
|
||||
* @{
|
||||
*
|
||||
* Audio resampling, sample format conversion and mixing library.
|
||||
*
|
||||
* Interaction with lswr is done through SwrContext, which is
|
||||
* allocated with swr_alloc() or swr_alloc_set_opts(). It is opaque, so all parameters
|
||||
* must be set with the @ref avoptions API.
|
||||
*
|
||||
* The first thing you will need to do in order to use lswr is to allocate
|
||||
* SwrContext. This can be done with swr_alloc() or swr_alloc_set_opts(). If you
|
||||
* are using the former, you must set options through the @ref avoptions API.
|
||||
* The latter function provides the same feature, but it allows you to set some
|
||||
* common options in the same statement.
|
||||
*
|
||||
* For example the following code will setup conversion from planar float sample
|
||||
* format to interleaved signed 16-bit integer, downsampling from 48kHz to
|
||||
* 44.1kHz and downmixing from 5.1 channels to stereo (using the default mixing
|
||||
* matrix). This is using the swr_alloc() function.
|
||||
* @code
|
||||
* SwrContext *swr = swr_alloc();
|
||||
* av_opt_set_channel_layout(swr, "in_channel_layout", AV_CH_LAYOUT_5POINT1, 0);
|
||||
* av_opt_set_channel_layout(swr, "out_channel_layout", AV_CH_LAYOUT_STEREO, 0);
|
||||
* av_opt_set_int(swr, "in_sample_rate", 48000, 0);
|
||||
* av_opt_set_int(swr, "out_sample_rate", 44100, 0);
|
||||
* av_opt_set_sample_fmt(swr, "in_sample_fmt", AV_SAMPLE_FMT_FLTP, 0);
|
||||
* av_opt_set_sample_fmt(swr, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0);
|
||||
* @endcode
|
||||
*
|
||||
* The same job can be done using swr_alloc_set_opts() as well:
|
||||
* @code
|
||||
* SwrContext *swr = swr_alloc_set_opts(NULL, // we're allocating a new context
|
||||
* AV_CH_LAYOUT_STEREO, // out_ch_layout
|
||||
* AV_SAMPLE_FMT_S16, // out_sample_fmt
|
||||
* 44100, // out_sample_rate
|
||||
* AV_CH_LAYOUT_5POINT1, // in_ch_layout
|
||||
* AV_SAMPLE_FMT_FLTP, // in_sample_fmt
|
||||
* 48000, // in_sample_rate
|
||||
* 0, // log_offset
|
||||
* NULL); // log_ctx
|
||||
* @endcode
|
||||
*
|
||||
* Once all values have been set, it must be initialized with swr_init(). If
|
||||
* you need to change the conversion parameters, you can change the parameters
|
||||
* using @ref AVOptions, as described above in the first example; or by using
|
||||
* swr_alloc_set_opts(), but with the first argument the allocated context.
|
||||
* You must then call swr_init() again.
|
||||
*
|
||||
* The conversion itself is done by repeatedly calling swr_convert().
|
||||
* Note that the samples may get buffered in swr if you provide insufficient
|
||||
* output space or if sample rate conversion is done, which requires "future"
|
||||
* samples. Samples that do not require future input can be retrieved at any
|
||||
* time by using swr_convert() (in_count can be set to 0).
|
||||
* At the end of conversion the resampling buffer can be flushed by calling
|
||||
* swr_convert() with NULL in and 0 in_count.
|
||||
*
|
||||
* The samples used in the conversion process can be managed with the libavutil
|
||||
* @ref lavu_sampmanip "samples manipulation" API, including av_samples_alloc()
|
||||
* function used in the following example.
|
||||
*
|
||||
* The delay between input and output, can at any time be found by using
|
||||
* swr_get_delay().
|
||||
*
|
||||
* The following code demonstrates the conversion loop assuming the parameters
|
||||
* from above and caller-defined functions get_input() and handle_output():
|
||||
* @code
|
||||
* uint8_t **input;
|
||||
* int in_samples;
|
||||
*
|
||||
* while (get_input(&input, &in_samples)) {
|
||||
* uint8_t *output;
|
||||
* int out_samples = av_rescale_rnd(swr_get_delay(swr, 48000) +
|
||||
* in_samples, 44100, 48000, AV_ROUND_UP);
|
||||
* av_samples_alloc(&output, NULL, 2, out_samples,
|
||||
* AV_SAMPLE_FMT_S16, 0);
|
||||
* out_samples = swr_convert(swr, &output, out_samples,
|
||||
* input, in_samples);
|
||||
* handle_output(output, out_samples);
|
||||
* av_freep(&output);
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
* When the conversion is finished, the conversion
|
||||
* context and everything associated with it must be freed with swr_free().
|
||||
* A swr_close() function is also available, but it exists mainly for
|
||||
* compatibility with libavresample, and is not required to be called.
|
||||
*
|
||||
* There will be no memory leak if the data is not completely flushed before
|
||||
* swr_free().
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "libavutil/channel_layout.h"
|
||||
#include "libavutil/frame.h"
|
||||
#include "libavutil/samplefmt.h"
|
||||
|
||||
#include "libswresample/version.h"
|
||||
|
||||
/**
|
||||
* @name Option constants
|
||||
* These constants are used for the @ref avoptions interface for lswr.
|
||||
* @{
|
||||
*
|
||||
*/
|
||||
|
||||
#define SWR_FLAG_RESAMPLE 1 ///< Force resampling even if equal sample rate
|
||||
//TODO use int resample ?
|
||||
//long term TODO can we enable this dynamically?
|
||||
|
||||
/** Dithering algorithms */
|
||||
enum SwrDitherType {
|
||||
SWR_DITHER_NONE = 0,
|
||||
SWR_DITHER_RECTANGULAR,
|
||||
SWR_DITHER_TRIANGULAR,
|
||||
SWR_DITHER_TRIANGULAR_HIGHPASS,
|
||||
|
||||
SWR_DITHER_NS = 64, ///< not part of API/ABI
|
||||
SWR_DITHER_NS_LIPSHITZ,
|
||||
SWR_DITHER_NS_F_WEIGHTED,
|
||||
SWR_DITHER_NS_MODIFIED_E_WEIGHTED,
|
||||
SWR_DITHER_NS_IMPROVED_E_WEIGHTED,
|
||||
SWR_DITHER_NS_SHIBATA,
|
||||
SWR_DITHER_NS_LOW_SHIBATA,
|
||||
SWR_DITHER_NS_HIGH_SHIBATA,
|
||||
SWR_DITHER_NB, ///< not part of API/ABI
|
||||
};
|
||||
|
||||
/** Resampling Engines */
|
||||
enum SwrEngine {
|
||||
SWR_ENGINE_SWR, /**< SW Resampler */
|
||||
SWR_ENGINE_SOXR, /**< SoX Resampler */
|
||||
SWR_ENGINE_NB, ///< not part of API/ABI
|
||||
};
|
||||
|
||||
/** Resampling Filter Types */
|
||||
enum SwrFilterType {
|
||||
SWR_FILTER_TYPE_CUBIC, /**< Cubic */
|
||||
SWR_FILTER_TYPE_BLACKMAN_NUTTALL, /**< Blackman Nuttall windowed sinc */
|
||||
SWR_FILTER_TYPE_KAISER, /**< Kaiser windowed sinc */
|
||||
};
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* The libswresample context. Unlike libavcodec and libavformat, this structure
|
||||
* is opaque. This means that if you would like to set options, you must use
|
||||
* the @ref avoptions API and cannot directly set values to members of the
|
||||
* structure.
|
||||
*/
|
||||
typedef struct SwrContext SwrContext;
|
||||
|
||||
/**
|
||||
* Get the AVClass for SwrContext. It can be used in combination with
|
||||
* AV_OPT_SEARCH_FAKE_OBJ for examining options.
|
||||
*
|
||||
* @see av_opt_find().
|
||||
* @return the AVClass of SwrContext
|
||||
*/
|
||||
const AVClass *swr_get_class(void);
|
||||
|
||||
/**
|
||||
* @name SwrContext constructor functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Allocate SwrContext.
|
||||
*
|
||||
* If you use this function you will need to set the parameters (manually or
|
||||
* with swr_alloc_set_opts()) before calling swr_init().
|
||||
*
|
||||
* @see swr_alloc_set_opts(), swr_init(), swr_free()
|
||||
* @return NULL on error, allocated context otherwise
|
||||
*/
|
||||
struct SwrContext *swr_alloc(void);
|
||||
|
||||
/**
|
||||
* Initialize context after user parameters have been set.
|
||||
* @note The context must be configured using the AVOption API.
|
||||
*
|
||||
* @see av_opt_set_int()
|
||||
* @see av_opt_set_dict()
|
||||
*
|
||||
* @param[in,out] s Swr context to initialize
|
||||
* @return AVERROR error code in case of failure.
|
||||
*/
|
||||
int swr_init(struct SwrContext *s);
|
||||
|
||||
/**
|
||||
* Check whether an swr context has been initialized or not.
|
||||
*
|
||||
* @param[in] s Swr context to check
|
||||
* @see swr_init()
|
||||
* @return positive if it has been initialized, 0 if not initialized
|
||||
*/
|
||||
int swr_is_initialized(struct SwrContext *s);
|
||||
|
||||
/**
|
||||
* Allocate SwrContext if needed and set/reset common parameters.
|
||||
*
|
||||
* This function does not require s to be allocated with swr_alloc(). On the
|
||||
* other hand, swr_alloc() can use swr_alloc_set_opts() to set the parameters
|
||||
* on the allocated context.
|
||||
*
|
||||
* @param s existing Swr context if available, or NULL if not
|
||||
* @param out_ch_layout output channel layout (AV_CH_LAYOUT_*)
|
||||
* @param out_sample_fmt output sample format (AV_SAMPLE_FMT_*).
|
||||
* @param out_sample_rate output sample rate (frequency in Hz)
|
||||
* @param in_ch_layout input channel layout (AV_CH_LAYOUT_*)
|
||||
* @param in_sample_fmt input sample format (AV_SAMPLE_FMT_*).
|
||||
* @param in_sample_rate input sample rate (frequency in Hz)
|
||||
* @param log_offset logging level offset
|
||||
* @param log_ctx parent logging context, can be NULL
|
||||
*
|
||||
* @see swr_init(), swr_free()
|
||||
* @return NULL on error, allocated context otherwise
|
||||
*/
|
||||
struct SwrContext *swr_alloc_set_opts(struct SwrContext *s,
|
||||
int64_t out_ch_layout, enum AVSampleFormat out_sample_fmt, int out_sample_rate,
|
||||
int64_t in_ch_layout, enum AVSampleFormat in_sample_fmt, int in_sample_rate,
|
||||
int log_offset, void *log_ctx);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
* @name SwrContext destructor functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Free the given SwrContext and set the pointer to NULL.
|
||||
*
|
||||
* @param[in] s a pointer to a pointer to Swr context
|
||||
*/
|
||||
void swr_free(struct SwrContext **s);
|
||||
|
||||
/**
|
||||
* Closes the context so that swr_is_initialized() returns 0.
|
||||
*
|
||||
* The context can be brought back to life by running swr_init(),
|
||||
* swr_init() can also be used without swr_close().
|
||||
* This function is mainly provided for simplifying the usecase
|
||||
* where one tries to support libavresample and libswresample.
|
||||
*
|
||||
* @param[in,out] s Swr context to be closed
|
||||
*/
|
||||
void swr_close(struct SwrContext *s);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
* @name Core conversion functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** Convert audio.
|
||||
*
|
||||
* in and in_count can be set to 0 to flush the last few samples out at the
|
||||
* end.
|
||||
*
|
||||
* If more input is provided than output space, then the input will be buffered.
|
||||
* You can avoid this buffering by using swr_get_out_samples() to retrieve an
|
||||
* upper bound on the required number of output samples for the given number of
|
||||
* input samples. Conversion will run directly without copying whenever possible.
|
||||
*
|
||||
* @param s allocated Swr context, with parameters set
|
||||
* @param out output buffers, only the first one need be set in case of packed audio
|
||||
* @param out_count amount of space available for output in samples per channel
|
||||
* @param in input buffers, only the first one need to be set in case of packed audio
|
||||
* @param in_count number of input samples available in one channel
|
||||
*
|
||||
* @return number of samples output per channel, negative value on error
|
||||
*/
|
||||
int swr_convert(struct SwrContext *s, uint8_t **out, int out_count,
|
||||
const uint8_t **in , int in_count);
|
||||
|
||||
/**
|
||||
* Convert the next timestamp from input to output
|
||||
* timestamps are in 1/(in_sample_rate * out_sample_rate) units.
|
||||
*
|
||||
* @note There are 2 slightly differently behaving modes.
|
||||
* @li When automatic timestamp compensation is not used, (min_compensation >= FLT_MAX)
|
||||
* in this case timestamps will be passed through with delays compensated
|
||||
* @li When automatic timestamp compensation is used, (min_compensation < FLT_MAX)
|
||||
* in this case the output timestamps will match output sample numbers.
|
||||
* See ffmpeg-resampler(1) for the two modes of compensation.
|
||||
*
|
||||
* @param s[in] initialized Swr context
|
||||
* @param pts[in] timestamp for the next input sample, INT64_MIN if unknown
|
||||
* @see swr_set_compensation(), swr_drop_output(), and swr_inject_silence() are
|
||||
* function used internally for timestamp compensation.
|
||||
* @return the output timestamp for the next output sample
|
||||
*/
|
||||
int64_t swr_next_pts(struct SwrContext *s, int64_t pts);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
* @name Low-level option setting functions
|
||||
* These functons provide a means to set low-level options that is not possible
|
||||
* with the AVOption API.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Activate resampling compensation ("soft" compensation). This function is
|
||||
* internally called when needed in swr_next_pts().
|
||||
*
|
||||
* @param[in,out] s allocated Swr context. If it is not initialized,
|
||||
* or SWR_FLAG_RESAMPLE is not set, swr_init() is
|
||||
* called with the flag set.
|
||||
* @param[in] sample_delta delta in PTS per sample
|
||||
* @param[in] compensation_distance number of samples to compensate for
|
||||
* @return >= 0 on success, AVERROR error codes if:
|
||||
* @li @c s is NULL,
|
||||
* @li @c compensation_distance is less than 0,
|
||||
* @li @c compensation_distance is 0 but sample_delta is not,
|
||||
* @li compensation unsupported by resampler, or
|
||||
* @li swr_init() fails when called.
|
||||
*/
|
||||
int swr_set_compensation(struct SwrContext *s, int sample_delta, int compensation_distance);
|
||||
|
||||
/**
|
||||
* Set a customized input channel mapping.
|
||||
*
|
||||
* @param[in,out] s allocated Swr context, not yet initialized
|
||||
* @param[in] channel_map customized input channel mapping (array of channel
|
||||
* indexes, -1 for a muted channel)
|
||||
* @return >= 0 on success, or AVERROR error code in case of failure.
|
||||
*/
|
||||
int swr_set_channel_mapping(struct SwrContext *s, const int *channel_map);
|
||||
|
||||
/**
|
||||
* Generate a channel mixing matrix.
|
||||
*
|
||||
* This function is the one used internally by libswresample for building the
|
||||
* default mixing matrix. It is made public just as a utility function for
|
||||
* building custom matrices.
|
||||
*
|
||||
* @param in_layout input channel layout
|
||||
* @param out_layout output channel layout
|
||||
* @param center_mix_level mix level for the center channel
|
||||
* @param surround_mix_level mix level for the surround channel(s)
|
||||
* @param lfe_mix_level mix level for the low-frequency effects channel
|
||||
* @param rematrix_maxval if 1.0, coefficients will be normalized to prevent
|
||||
* overflow. if INT_MAX, coefficients will not be
|
||||
* normalized.
|
||||
* @param[out] matrix mixing coefficients; matrix[i + stride * o] is
|
||||
* the weight of input channel i in output channel o.
|
||||
* @param stride distance between adjacent input channels in the
|
||||
* matrix array
|
||||
* @param matrix_encoding matrixed stereo downmix mode (e.g. dplii)
|
||||
* @param log_ctx parent logging context, can be NULL
|
||||
* @return 0 on success, negative AVERROR code on failure
|
||||
*/
|
||||
int swr_build_matrix(uint64_t in_layout, uint64_t out_layout,
|
||||
double center_mix_level, double surround_mix_level,
|
||||
double lfe_mix_level, double rematrix_maxval,
|
||||
double rematrix_volume, double *matrix,
|
||||
int stride, enum AVMatrixEncoding matrix_encoding,
|
||||
void *log_ctx);
|
||||
|
||||
/**
|
||||
* Set a customized remix matrix.
|
||||
*
|
||||
* @param s allocated Swr context, not yet initialized
|
||||
* @param matrix remix coefficients; matrix[i + stride * o] is
|
||||
* the weight of input channel i in output channel o
|
||||
* @param stride offset between lines of the matrix
|
||||
* @return >= 0 on success, or AVERROR error code in case of failure.
|
||||
*/
|
||||
int swr_set_matrix(struct SwrContext *s, const double *matrix, int stride);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
* @name Sample handling functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Drops the specified number of output samples.
|
||||
*
|
||||
* This function, along with swr_inject_silence(), is called by swr_next_pts()
|
||||
* if needed for "hard" compensation.
|
||||
*
|
||||
* @param s allocated Swr context
|
||||
* @param count number of samples to be dropped
|
||||
*
|
||||
* @return >= 0 on success, or a negative AVERROR code on failure
|
||||
*/
|
||||
int swr_drop_output(struct SwrContext *s, int count);
|
||||
|
||||
/**
|
||||
* Injects the specified number of silence samples.
|
||||
*
|
||||
* This function, along with swr_drop_output(), is called by swr_next_pts()
|
||||
* if needed for "hard" compensation.
|
||||
*
|
||||
* @param s allocated Swr context
|
||||
* @param count number of samples to be dropped
|
||||
*
|
||||
* @return >= 0 on success, or a negative AVERROR code on failure
|
||||
*/
|
||||
int swr_inject_silence(struct SwrContext *s, int count);
|
||||
|
||||
/**
|
||||
* Gets the delay the next input sample will experience relative to the next output sample.
|
||||
*
|
||||
* Swresample can buffer data if more input has been provided than available
|
||||
* output space, also converting between sample rates needs a delay.
|
||||
* This function returns the sum of all such delays.
|
||||
* The exact delay is not necessarily an integer value in either input or
|
||||
* output sample rate. Especially when downsampling by a large value, the
|
||||
* output sample rate may be a poor choice to represent the delay, similarly
|
||||
* for upsampling and the input sample rate.
|
||||
*
|
||||
* @param s swr context
|
||||
* @param base timebase in which the returned delay will be:
|
||||
* @li if it's set to 1 the returned delay is in seconds
|
||||
* @li if it's set to 1000 the returned delay is in milliseconds
|
||||
* @li if it's set to the input sample rate then the returned
|
||||
* delay is in input samples
|
||||
* @li if it's set to the output sample rate then the returned
|
||||
* delay is in output samples
|
||||
* @li if it's the least common multiple of in_sample_rate and
|
||||
* out_sample_rate then an exact rounding-free delay will be
|
||||
* returned
|
||||
* @returns the delay in 1 / @c base units.
|
||||
*/
|
||||
int64_t swr_get_delay(struct SwrContext *s, int64_t base);
|
||||
|
||||
/**
|
||||
* Find an upper bound on the number of samples that the next swr_convert
|
||||
* call will output, if called with in_samples of input samples. This
|
||||
* depends on the internal state, and anything changing the internal state
|
||||
* (like further swr_convert() calls) will may change the number of samples
|
||||
* swr_get_out_samples() returns for the same number of input samples.
|
||||
*
|
||||
* @param in_samples number of input samples.
|
||||
* @note any call to swr_inject_silence(), swr_convert(), swr_next_pts()
|
||||
* or swr_set_compensation() invalidates this limit
|
||||
* @note it is recommended to pass the correct available buffer size
|
||||
* to all functions like swr_convert() even if swr_get_out_samples()
|
||||
* indicates that less would be used.
|
||||
* @returns an upper bound on the number of samples that the next swr_convert
|
||||
* will output or a negative value to indicate an error
|
||||
*/
|
||||
int swr_get_out_samples(struct SwrContext *s, int in_samples);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
* @name Configuration accessors
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Return the @ref LIBSWRESAMPLE_VERSION_INT constant.
|
||||
*
|
||||
* This is useful to check if the build-time libswresample has the same version
|
||||
* as the run-time one.
|
||||
*
|
||||
* @returns the unsigned int-typed version
|
||||
*/
|
||||
unsigned swresample_version(void);
|
||||
|
||||
/**
|
||||
* Return the swr build-time configuration.
|
||||
*
|
||||
* @returns the build-time @c ./configure flags
|
||||
*/
|
||||
const char *swresample_configuration(void);
|
||||
|
||||
/**
|
||||
* Return the swr license.
|
||||
*
|
||||
* @returns the license of libswresample, determined at build-time
|
||||
*/
|
||||
const char *swresample_license(void);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
* @name AVFrame based API
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Convert the samples in the input AVFrame and write them to the output AVFrame.
|
||||
*
|
||||
* Input and output AVFrames must have channel_layout, sample_rate and format set.
|
||||
*
|
||||
* If the output AVFrame does not have the data pointers allocated the nb_samples
|
||||
* field will be set using av_frame_get_buffer()
|
||||
* is called to allocate the frame.
|
||||
*
|
||||
* The output AVFrame can be NULL or have fewer allocated samples than required.
|
||||
* In this case, any remaining samples not written to the output will be added
|
||||
* to an internal FIFO buffer, to be returned at the next call to this function
|
||||
* or to swr_convert().
|
||||
*
|
||||
* If converting sample rate, there may be data remaining in the internal
|
||||
* resampling delay buffer. swr_get_delay() tells the number of
|
||||
* remaining samples. To get this data as output, call this function or
|
||||
* swr_convert() with NULL input.
|
||||
*
|
||||
* If the SwrContext configuration does not match the output and
|
||||
* input AVFrame settings the conversion does not take place and depending on
|
||||
* which AVFrame is not matching AVERROR_OUTPUT_CHANGED, AVERROR_INPUT_CHANGED
|
||||
* or the result of a bitwise-OR of them is returned.
|
||||
*
|
||||
* @see swr_delay()
|
||||
* @see swr_convert()
|
||||
* @see swr_get_delay()
|
||||
*
|
||||
* @param swr audio resample context
|
||||
* @param output output AVFrame
|
||||
* @param input input AVFrame
|
||||
* @return 0 on success, AVERROR on failure or nonmatching
|
||||
* configuration.
|
||||
*/
|
||||
int swr_convert_frame(SwrContext *swr,
|
||||
AVFrame *output, const AVFrame *input);
|
||||
|
||||
/**
|
||||
* Configure or reconfigure the SwrContext using the information
|
||||
* provided by the AVFrames.
|
||||
*
|
||||
* The original resampling context is reset even on failure.
|
||||
* The function calls swr_close() internally if the context is open.
|
||||
*
|
||||
* @see swr_close();
|
||||
*
|
||||
* @param swr audio resample context
|
||||
* @param output output AVFrame
|
||||
* @param input input AVFrame
|
||||
* @return 0 on success, AVERROR on failure.
|
||||
*/
|
||||
int swr_config_frame(SwrContext *swr, const AVFrame *out, const AVFrame *in);
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* SWRESAMPLE_SWRESAMPLE_H */
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Version macros.
|
||||
*
|
||||
* This file is part of libswresample
|
||||
*
|
||||
* libswresample is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* libswresample is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with libswresample; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef SWRESAMPLE_VERSION_H
|
||||
#define SWRESAMPLE_VERSION_H
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Libswresample version macros
|
||||
*/
|
||||
|
||||
#include "libavutil/avutil.h"
|
||||
|
||||
#define LIBSWRESAMPLE_VERSION_MAJOR 3
|
||||
#define LIBSWRESAMPLE_VERSION_MINOR 2
|
||||
#define LIBSWRESAMPLE_VERSION_MICRO 100
|
||||
|
||||
#define LIBSWRESAMPLE_VERSION_INT AV_VERSION_INT(LIBSWRESAMPLE_VERSION_MAJOR, \
|
||||
LIBSWRESAMPLE_VERSION_MINOR, \
|
||||
LIBSWRESAMPLE_VERSION_MICRO)
|
||||
#define LIBSWRESAMPLE_VERSION AV_VERSION(LIBSWRESAMPLE_VERSION_MAJOR, \
|
||||
LIBSWRESAMPLE_VERSION_MINOR, \
|
||||
LIBSWRESAMPLE_VERSION_MICRO)
|
||||
#define LIBSWRESAMPLE_BUILD LIBSWRESAMPLE_VERSION_INT
|
||||
|
||||
#define LIBSWRESAMPLE_IDENT "SwR" AV_STRINGIFY(LIBSWRESAMPLE_VERSION)
|
||||
|
||||
#endif /* SWRESAMPLE_VERSION_H */
|
||||
@@ -0,0 +1,336 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2011 Michael Niedermayer <[email protected]>
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef SWSCALE_SWSCALE_H
|
||||
#define SWSCALE_SWSCALE_H
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @ingroup libsws
|
||||
* external API header
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "libavutil/avutil.h"
|
||||
#include "libavutil/log.h"
|
||||
#include "libavutil/pixfmt.h"
|
||||
#include "version.h"
|
||||
|
||||
/**
|
||||
* @defgroup libsws libswscale
|
||||
* Color conversion and scaling library.
|
||||
*
|
||||
* @{
|
||||
*
|
||||
* Return the LIBSWSCALE_VERSION_INT constant.
|
||||
*/
|
||||
unsigned swscale_version(void);
|
||||
|
||||
/**
|
||||
* Return the libswscale build-time configuration.
|
||||
*/
|
||||
const char *swscale_configuration(void);
|
||||
|
||||
/**
|
||||
* Return the libswscale license.
|
||||
*/
|
||||
const char *swscale_license(void);
|
||||
|
||||
/* values for the flags, the stuff on the command line is different */
|
||||
#define SWS_FAST_BILINEAR 1
|
||||
#define SWS_BILINEAR 2
|
||||
#define SWS_BICUBIC 4
|
||||
#define SWS_X 8
|
||||
#define SWS_POINT 0x10
|
||||
#define SWS_AREA 0x20
|
||||
#define SWS_BICUBLIN 0x40
|
||||
#define SWS_GAUSS 0x80
|
||||
#define SWS_SINC 0x100
|
||||
#define SWS_LANCZOS 0x200
|
||||
#define SWS_SPLINE 0x400
|
||||
|
||||
#define SWS_SRC_V_CHR_DROP_MASK 0x30000
|
||||
#define SWS_SRC_V_CHR_DROP_SHIFT 16
|
||||
|
||||
#define SWS_PARAM_DEFAULT 123456
|
||||
|
||||
#define SWS_PRINT_INFO 0x1000
|
||||
|
||||
//the following 3 flags are not completely implemented
|
||||
//internal chrominance subsampling info
|
||||
#define SWS_FULL_CHR_H_INT 0x2000
|
||||
//input subsampling info
|
||||
#define SWS_FULL_CHR_H_INP 0x4000
|
||||
#define SWS_DIRECT_BGR 0x8000
|
||||
#define SWS_ACCURATE_RND 0x40000
|
||||
#define SWS_BITEXACT 0x80000
|
||||
#define SWS_ERROR_DIFFUSION 0x800000
|
||||
|
||||
#define SWS_MAX_REDUCE_CUTOFF 0.002
|
||||
|
||||
#define SWS_CS_ITU709 1
|
||||
#define SWS_CS_FCC 4
|
||||
#define SWS_CS_ITU601 5
|
||||
#define SWS_CS_ITU624 5
|
||||
#define SWS_CS_SMPTE170M 5
|
||||
#define SWS_CS_SMPTE240M 7
|
||||
#define SWS_CS_DEFAULT 5
|
||||
#define SWS_CS_BT2020 9
|
||||
|
||||
/**
|
||||
* Return a pointer to yuv<->rgb coefficients for the given colorspace
|
||||
* suitable for sws_setColorspaceDetails().
|
||||
*
|
||||
* @param colorspace One of the SWS_CS_* macros. If invalid,
|
||||
* SWS_CS_DEFAULT is used.
|
||||
*/
|
||||
const int *sws_getCoefficients(int colorspace);
|
||||
|
||||
// when used for filters they must have an odd number of elements
|
||||
// coeffs cannot be shared between vectors
|
||||
typedef struct SwsVector {
|
||||
double *coeff; ///< pointer to the list of coefficients
|
||||
int length; ///< number of coefficients in the vector
|
||||
} SwsVector;
|
||||
|
||||
// vectors can be shared
|
||||
typedef struct SwsFilter {
|
||||
SwsVector *lumH;
|
||||
SwsVector *lumV;
|
||||
SwsVector *chrH;
|
||||
SwsVector *chrV;
|
||||
} SwsFilter;
|
||||
|
||||
struct SwsContext;
|
||||
|
||||
/**
|
||||
* Return a positive value if pix_fmt is a supported input format, 0
|
||||
* otherwise.
|
||||
*/
|
||||
int sws_isSupportedInput(enum AVPixelFormat pix_fmt);
|
||||
|
||||
/**
|
||||
* Return a positive value if pix_fmt is a supported output format, 0
|
||||
* otherwise.
|
||||
*/
|
||||
int sws_isSupportedOutput(enum AVPixelFormat pix_fmt);
|
||||
|
||||
/**
|
||||
* @param[in] pix_fmt the pixel format
|
||||
* @return a positive value if an endianness conversion for pix_fmt is
|
||||
* supported, 0 otherwise.
|
||||
*/
|
||||
int sws_isSupportedEndiannessConversion(enum AVPixelFormat pix_fmt);
|
||||
|
||||
/**
|
||||
* Allocate an empty SwsContext. This must be filled and passed to
|
||||
* sws_init_context(). For filling see AVOptions, options.c and
|
||||
* sws_setColorspaceDetails().
|
||||
*/
|
||||
struct SwsContext *sws_alloc_context(void);
|
||||
|
||||
/**
|
||||
* Initialize the swscaler context sws_context.
|
||||
*
|
||||
* @return zero or positive value on success, a negative value on
|
||||
* error
|
||||
*/
|
||||
av_warn_unused_result
|
||||
int sws_init_context(struct SwsContext *sws_context, SwsFilter *srcFilter, SwsFilter *dstFilter);
|
||||
|
||||
/**
|
||||
* Free the swscaler context swsContext.
|
||||
* If swsContext is NULL, then does nothing.
|
||||
*/
|
||||
void sws_freeContext(struct SwsContext *swsContext);
|
||||
|
||||
/**
|
||||
* Allocate and return an SwsContext. You need it to perform
|
||||
* scaling/conversion operations using sws_scale().
|
||||
*
|
||||
* @param srcW the width of the source image
|
||||
* @param srcH the height of the source image
|
||||
* @param srcFormat the source image format
|
||||
* @param dstW the width of the destination image
|
||||
* @param dstH the height of the destination image
|
||||
* @param dstFormat the destination image format
|
||||
* @param flags specify which algorithm and options to use for rescaling
|
||||
* @param param extra parameters to tune the used scaler
|
||||
* For SWS_BICUBIC param[0] and [1] tune the shape of the basis
|
||||
* function, param[0] tunes f(1) and param[1] f´(1)
|
||||
* For SWS_GAUSS param[0] tunes the exponent and thus cutoff
|
||||
* frequency
|
||||
* For SWS_LANCZOS param[0] tunes the width of the window function
|
||||
* @return a pointer to an allocated context, or NULL in case of error
|
||||
* @note this function is to be removed after a saner alternative is
|
||||
* written
|
||||
*/
|
||||
struct SwsContext *sws_getContext(int srcW, int srcH, enum AVPixelFormat srcFormat,
|
||||
int dstW, int dstH, enum AVPixelFormat dstFormat,
|
||||
int flags, SwsFilter *srcFilter,
|
||||
SwsFilter *dstFilter, const double *param);
|
||||
|
||||
/**
|
||||
* Scale the image slice in srcSlice and put the resulting scaled
|
||||
* slice in the image in dst. A slice is a sequence of consecutive
|
||||
* rows in an image.
|
||||
*
|
||||
* Slices have to be provided in sequential order, either in
|
||||
* top-bottom or bottom-top order. If slices are provided in
|
||||
* non-sequential order the behavior of the function is undefined.
|
||||
*
|
||||
* @param c the scaling context previously created with
|
||||
* sws_getContext()
|
||||
* @param srcSlice the array containing the pointers to the planes of
|
||||
* the source slice
|
||||
* @param srcStride the array containing the strides for each plane of
|
||||
* the source image
|
||||
* @param srcSliceY the position in the source image of the slice to
|
||||
* process, that is the number (counted starting from
|
||||
* zero) in the image of the first row of the slice
|
||||
* @param srcSliceH the height of the source slice, that is the number
|
||||
* of rows in the slice
|
||||
* @param dst the array containing the pointers to the planes of
|
||||
* the destination image
|
||||
* @param dstStride the array containing the strides for each plane of
|
||||
* the destination image
|
||||
* @return the height of the output slice
|
||||
*/
|
||||
int sws_scale(struct SwsContext *c, const uint8_t *const srcSlice[],
|
||||
const int srcStride[], int srcSliceY, int srcSliceH,
|
||||
uint8_t *const dst[], const int dstStride[]);
|
||||
|
||||
/**
|
||||
* @param dstRange flag indicating the while-black range of the output (1=jpeg / 0=mpeg)
|
||||
* @param srcRange flag indicating the while-black range of the input (1=jpeg / 0=mpeg)
|
||||
* @param table the yuv2rgb coefficients describing the output yuv space, normally ff_yuv2rgb_coeffs[x]
|
||||
* @param inv_table the yuv2rgb coefficients describing the input yuv space, normally ff_yuv2rgb_coeffs[x]
|
||||
* @param brightness 16.16 fixed point brightness correction
|
||||
* @param contrast 16.16 fixed point contrast correction
|
||||
* @param saturation 16.16 fixed point saturation correction
|
||||
* @return -1 if not supported
|
||||
*/
|
||||
int sws_setColorspaceDetails(struct SwsContext *c, const int inv_table[4],
|
||||
int srcRange, const int table[4], int dstRange,
|
||||
int brightness, int contrast, int saturation);
|
||||
|
||||
/**
|
||||
* @return -1 if not supported
|
||||
*/
|
||||
int sws_getColorspaceDetails(struct SwsContext *c, int **inv_table,
|
||||
int *srcRange, int **table, int *dstRange,
|
||||
int *brightness, int *contrast, int *saturation);
|
||||
|
||||
/**
|
||||
* Allocate and return an uninitialized vector with length coefficients.
|
||||
*/
|
||||
SwsVector *sws_allocVec(int length);
|
||||
|
||||
/**
|
||||
* Return a normalized Gaussian curve used to filter stuff
|
||||
* quality = 3 is high quality, lower is lower quality.
|
||||
*/
|
||||
SwsVector *sws_getGaussianVec(double variance, double quality);
|
||||
|
||||
/**
|
||||
* Scale all the coefficients of a by the scalar value.
|
||||
*/
|
||||
void sws_scaleVec(SwsVector *a, double scalar);
|
||||
|
||||
/**
|
||||
* Scale all the coefficients of a so that their sum equals height.
|
||||
*/
|
||||
void sws_normalizeVec(SwsVector *a, double height);
|
||||
|
||||
#if FF_API_SWS_VECTOR
|
||||
attribute_deprecated SwsVector *sws_getConstVec(double c, int length);
|
||||
attribute_deprecated SwsVector *sws_getIdentityVec(void);
|
||||
attribute_deprecated void sws_convVec(SwsVector *a, SwsVector *b);
|
||||
attribute_deprecated void sws_addVec(SwsVector *a, SwsVector *b);
|
||||
attribute_deprecated void sws_subVec(SwsVector *a, SwsVector *b);
|
||||
attribute_deprecated void sws_shiftVec(SwsVector *a, int shift);
|
||||
attribute_deprecated SwsVector *sws_cloneVec(SwsVector *a);
|
||||
attribute_deprecated void sws_printVec2(SwsVector *a, AVClass *log_ctx, int log_level);
|
||||
#endif
|
||||
|
||||
void sws_freeVec(SwsVector *a);
|
||||
|
||||
SwsFilter *sws_getDefaultFilter(float lumaGBlur, float chromaGBlur,
|
||||
float lumaSharpen, float chromaSharpen,
|
||||
float chromaHShift, float chromaVShift,
|
||||
int verbose);
|
||||
void sws_freeFilter(SwsFilter *filter);
|
||||
|
||||
/**
|
||||
* Check if context can be reused, otherwise reallocate a new one.
|
||||
*
|
||||
* If context is NULL, just calls sws_getContext() to get a new
|
||||
* context. Otherwise, checks if the parameters are the ones already
|
||||
* saved in context. If that is the case, returns the current
|
||||
* context. Otherwise, frees context and gets a new context with
|
||||
* the new parameters.
|
||||
*
|
||||
* Be warned that srcFilter and dstFilter are not checked, they
|
||||
* are assumed to remain the same.
|
||||
*/
|
||||
struct SwsContext *sws_getCachedContext(struct SwsContext *context,
|
||||
int srcW, int srcH, enum AVPixelFormat srcFormat,
|
||||
int dstW, int dstH, enum AVPixelFormat dstFormat,
|
||||
int flags, SwsFilter *srcFilter,
|
||||
SwsFilter *dstFilter, const double *param);
|
||||
|
||||
/**
|
||||
* Convert an 8-bit paletted frame into a frame with a color depth of 32 bits.
|
||||
*
|
||||
* The output frame will have the same packed format as the palette.
|
||||
*
|
||||
* @param src source frame buffer
|
||||
* @param dst destination frame buffer
|
||||
* @param num_pixels number of pixels to convert
|
||||
* @param palette array with [256] entries, which must match color arrangement (RGB or BGR) of src
|
||||
*/
|
||||
void sws_convertPalette8ToPacked32(const uint8_t *src, uint8_t *dst, int num_pixels, const uint8_t *palette);
|
||||
|
||||
/**
|
||||
* Convert an 8-bit paletted frame into a frame with a color depth of 24 bits.
|
||||
*
|
||||
* With the palette format "ABCD", the destination frame ends up with the format "ABC".
|
||||
*
|
||||
* @param src source frame buffer
|
||||
* @param dst destination frame buffer
|
||||
* @param num_pixels number of pixels to convert
|
||||
* @param palette array with [256] entries, which must match color arrangement (RGB or BGR) of src
|
||||
*/
|
||||
void sws_convertPalette8ToPacked24(const uint8_t *src, uint8_t *dst, int num_pixels, const uint8_t *palette);
|
||||
|
||||
/**
|
||||
* Get the AVClass for swsContext. It can be used in combination with
|
||||
* AV_OPT_SEARCH_FAKE_OBJ for examining options.
|
||||
*
|
||||
* @see av_opt_find().
|
||||
*/
|
||||
const AVClass *sws_get_class(void);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* SWSCALE_SWSCALE_H */
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef SWSCALE_VERSION_H
|
||||
#define SWSCALE_VERSION_H
|
||||
|
||||
/**
|
||||
* @file
|
||||
* swscale version macros
|
||||
*/
|
||||
|
||||
#include "libavutil/version.h"
|
||||
|
||||
#define LIBSWSCALE_VERSION_MAJOR 5
|
||||
#define LIBSWSCALE_VERSION_MINOR 2
|
||||
#define LIBSWSCALE_VERSION_MICRO 100
|
||||
|
||||
#define LIBSWSCALE_VERSION_INT AV_VERSION_INT(LIBSWSCALE_VERSION_MAJOR, \
|
||||
LIBSWSCALE_VERSION_MINOR, \
|
||||
LIBSWSCALE_VERSION_MICRO)
|
||||
#define LIBSWSCALE_VERSION AV_VERSION(LIBSWSCALE_VERSION_MAJOR, \
|
||||
LIBSWSCALE_VERSION_MINOR, \
|
||||
LIBSWSCALE_VERSION_MICRO)
|
||||
#define LIBSWSCALE_BUILD LIBSWSCALE_VERSION_INT
|
||||
|
||||
#define LIBSWSCALE_IDENT "SwS" AV_STRINGIFY(LIBSWSCALE_VERSION)
|
||||
|
||||
/**
|
||||
* FF_API_* defines may be placed below to indicate public API that will be
|
||||
* dropped at a future version bump. The defines themselves are not part of
|
||||
* the public API and may change, break or disappear at any time.
|
||||
*/
|
||||
|
||||
#ifndef FF_API_SWS_VECTOR
|
||||
#define FF_API_SWS_VECTOR (LIBSWSCALE_VERSION_MAJOR < 6)
|
||||
#endif
|
||||
|
||||
#endif /* SWSCALE_VERSION_H */
|
||||
@@ -1,981 +0,0 @@
|
||||
/* 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(4);
|
||||
|
||||
/** 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 */
|
||||
@@ -1,342 +0,0 @@
|
||||
/* 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 */
|
||||
@@ -1,785 +0,0 @@
|
||||
/* 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
|
||||
|
||||
/* 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)
|
||||
|
||||
/**@}*/
|
||||
|
||||
/** @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 */
|
||||
@@ -1,660 +0,0 @@
|
||||
/* 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 */
|
||||
@@ -1,159 +0,0 @@
|
||||
/* (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
|
||||
|
||||
/* 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>
|
||||
|
||||
typedef int16_t opus_int16;
|
||||
typedef uint16_t opus_uint16;
|
||||
typedef int32_t opus_int32;
|
||||
typedef uint32_t opus_uint32;
|
||||
#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
|
||||
|
||||
#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
|
||||
|
||||
#endif /* OPUS_TYPES_H */
|
||||
@@ -9,9 +9,6 @@ QT -= core gui
|
||||
TARGET = moonlight-common-c
|
||||
TEMPLATE = lib
|
||||
|
||||
# Support debug and release builds from command line for CI
|
||||
CONFIG += debug_and_release
|
||||
|
||||
win32 {
|
||||
INCLUDEPATH += $$PWD/../libs/windows/include
|
||||
}
|
||||
@@ -62,13 +59,3 @@ INCLUDEPATH += \
|
||||
$$COMMON_C_DIR/src
|
||||
CONFIG += warn_off staticlib
|
||||
DEFINES += HAS_SOCKLEN_T
|
||||
|
||||
debug {
|
||||
# Enable asserts on debug builds
|
||||
DEFINES += LC_DEBUG
|
||||
}
|
||||
|
||||
# Older GCC versions defaulted to GNU89
|
||||
*-g++ {
|
||||
QMAKE_CFLAGS += -std=gnu99
|
||||
}
|
||||
|
||||
@@ -1,14 +1,8 @@
|
||||
TEMPLATE = subdirs
|
||||
SUBDIRS = \
|
||||
moonlight-common-c \
|
||||
opus \
|
||||
qmdnsengine \
|
||||
app
|
||||
|
||||
CONFIG += ordered
|
||||
|
||||
# Support debug and release builds from command line for CI
|
||||
CONFIG += debug_and_release
|
||||
|
||||
# Run our compile tests
|
||||
load(configure)
|
||||
qtCompileTest(SLVideo)
|
||||
|
||||
@@ -0,0 +1,230 @@
|
||||
QT -= core gui
|
||||
|
||||
TARGET = opus
|
||||
TEMPLATE = lib
|
||||
|
||||
OPUS_DIR = $$PWD/opus
|
||||
DEFINES += \
|
||||
USE_ALLOCA=1 \
|
||||
HAVE_LRINT=1 \
|
||||
HAVE_LRINTF=1 \
|
||||
OPUS_HAVE_RTCD=1 \
|
||||
OPUS_BUILD=1
|
||||
|
||||
contains(QT_ARCH, i386) {
|
||||
DEFINES += \
|
||||
OPUS_X86_MAY_HAVE_SSE=1 \
|
||||
OPUS_X86_MAY_HAVE_SSE2=1 \
|
||||
OPUS_X86_MAY_HAVE_SSE4_1=1 \
|
||||
OPUS_X86_MAY_HAVE_AVX=1
|
||||
}
|
||||
|
||||
# AMD64 implies SSE2 support
|
||||
contains(QT_ARCH, x86_64) {
|
||||
DEFINES += \
|
||||
OPUS_X86_MAY_HAVE_SSE=1 \
|
||||
OPUS_X86_MAY_HAVE_SSE2=1 \
|
||||
OPUS_X86_MAY_HAVE_SSE4_1=1 \
|
||||
OPUS_X86_MAY_HAVE_AVX=1 \
|
||||
OPUS_X86_PRESUME_SSE=1 \
|
||||
OPUS_X86_PRESUME_SSE2=1
|
||||
}
|
||||
|
||||
QMAKE_CFLAGS += -O2
|
||||
|
||||
SOURCES_SSE = \
|
||||
$$OPUS_DIR/celt/x86/pitch_sse.c
|
||||
|
||||
SOURCES_SSE2 = \
|
||||
$$OPUS_DIR/celt/x86/pitch_sse2.c \
|
||||
$$OPUS_DIR/celt/x86/vq_sse2.c
|
||||
|
||||
SOURCES_SSE41 = \
|
||||
$$OPUS_DIR/celt/x86/pitch_sse4_1.c \
|
||||
$$OPUS_DIR/celt/x86/celt_lpc_sse4_1.c \
|
||||
$$OPUS_DIR/silk/x86/NSQ_sse4_1.c \
|
||||
$$OPUS_DIR/silk/x86/VAD_sse4_1.c \
|
||||
$$OPUS_DIR/silk/x86/NSQ_del_dec_sse4_1.c \
|
||||
$$OPUS_DIR/silk/x86/VQ_WMat_EC_sse4_1.c
|
||||
|
||||
SOURCES += \
|
||||
$$OPUS_DIR/celt/quant_bands.c \
|
||||
$$OPUS_DIR/celt/laplace.c \
|
||||
$$OPUS_DIR/celt/rate.c \
|
||||
$$OPUS_DIR/celt/celt_decoder.c \
|
||||
$$OPUS_DIR/celt/celt_encoder.c \
|
||||
$$OPUS_DIR/celt/modes.c \
|
||||
$$OPUS_DIR/celt/entenc.c \
|
||||
$$OPUS_DIR/celt/entcode.c \
|
||||
$$OPUS_DIR/celt/cwrs.c \
|
||||
$$OPUS_DIR/celt/pitch.c \
|
||||
$$OPUS_DIR/celt/entdec.c \
|
||||
$$OPUS_DIR/celt/x86/x86_celt_map.c \
|
||||
$$OPUS_DIR/celt/x86/x86cpu.c \
|
||||
$$OPUS_DIR/celt/mathops.c \
|
||||
$$OPUS_DIR/celt/vq.c \
|
||||
$$OPUS_DIR/celt/bands.c \
|
||||
$$OPUS_DIR/celt/celt.c \
|
||||
$$OPUS_DIR/celt/celt_lpc.c \
|
||||
$$OPUS_DIR/celt/kiss_fft.c \
|
||||
$$OPUS_DIR/celt/mdct.c \
|
||||
$$OPUS_DIR/src/opus_decoder.c \
|
||||
$$OPUS_DIR/src/opus_compare.c \
|
||||
$$OPUS_DIR/src/opus_multistream_encoder.c \
|
||||
$$OPUS_DIR/src/opus.c \
|
||||
$$OPUS_DIR/src/mapping_matrix.c \
|
||||
$$OPUS_DIR/src/mlp.c \
|
||||
$$OPUS_DIR/src/opus_multistream_decoder.c \
|
||||
$$OPUS_DIR/src/analysis.c \
|
||||
$$OPUS_DIR/src/opus_projection_encoder.c \
|
||||
$$OPUS_DIR/src/repacketizer.c \
|
||||
$$OPUS_DIR/src/mlp_data.c \
|
||||
$$OPUS_DIR/src/opus_projection_decoder.c \
|
||||
$$OPUS_DIR/src/opus_multistream.c \
|
||||
$$OPUS_DIR/src/opus_encoder.c \
|
||||
$$OPUS_DIR/silk/x86/x86_silk_map.c \
|
||||
$$OPUS_DIR/silk/NSQ_del_dec.c \
|
||||
$$OPUS_DIR/silk/ana_filt_bank_1.c \
|
||||
$$OPUS_DIR/silk/stereo_find_predictor.c \
|
||||
$$OPUS_DIR/silk/resampler.c \
|
||||
$$OPUS_DIR/silk/HP_variable_cutoff.c \
|
||||
$$OPUS_DIR/silk/shell_coder.c \
|
||||
$$OPUS_DIR/silk/inner_prod_aligned.c \
|
||||
$$OPUS_DIR/silk/tables_gain.c \
|
||||
$$OPUS_DIR/silk/bwexpander_32.c \
|
||||
$$OPUS_DIR/silk/stereo_quant_pred.c \
|
||||
$$OPUS_DIR/silk/gain_quant.c \
|
||||
$$OPUS_DIR/silk/debug.c \
|
||||
$$OPUS_DIR/silk/decoder_set_fs.c \
|
||||
$$OPUS_DIR/silk/LPC_inv_pred_gain.c \
|
||||
$$OPUS_DIR/silk/tables_pulses_per_block.c \
|
||||
$$OPUS_DIR/silk/NLSF_VQ.c \
|
||||
$$OPUS_DIR/silk/control_audio_bandwidth.c \
|
||||
$$OPUS_DIR/silk/tables_LTP.c \
|
||||
$$OPUS_DIR/silk/dec_API.c \
|
||||
$$OPUS_DIR/silk/tables_NLSF_CB_WB.c \
|
||||
$$OPUS_DIR/silk/bwexpander.c \
|
||||
$$OPUS_DIR/silk/tables_NLSF_CB_NB_MB.c \
|
||||
$$OPUS_DIR/silk/LP_variable_cutoff.c \
|
||||
$$OPUS_DIR/silk/float/LPC_inv_pred_gain_FLP.c \
|
||||
$$OPUS_DIR/silk/float/schur_FLP.c \
|
||||
$$OPUS_DIR/silk/float/wrappers_FLP.c \
|
||||
$$OPUS_DIR/silk/float/autocorrelation_FLP.c \
|
||||
$$OPUS_DIR/silk/float/regularize_correlations_FLP.c \
|
||||
$$OPUS_DIR/silk/float/warped_autocorrelation_FLP.c \
|
||||
$$OPUS_DIR/silk/float/k2a_FLP.c \
|
||||
$$OPUS_DIR/silk/float/find_LPC_FLP.c \
|
||||
$$OPUS_DIR/silk/float/noise_shape_analysis_FLP.c \
|
||||
$$OPUS_DIR/silk/float/scale_vector_FLP.c \
|
||||
$$OPUS_DIR/silk/float/apply_sine_window_FLP.c \
|
||||
$$OPUS_DIR/silk/float/bwexpander_FLP.c \
|
||||
$$OPUS_DIR/silk/float/inner_product_FLP.c \
|
||||
$$OPUS_DIR/silk/float/scale_copy_vector_FLP.c \
|
||||
$$OPUS_DIR/silk/float/energy_FLP.c \
|
||||
$$OPUS_DIR/silk/float/pitch_analysis_core_FLP.c \
|
||||
$$OPUS_DIR/silk/float/process_gains_FLP.c \
|
||||
$$OPUS_DIR/silk/float/residual_energy_FLP.c \
|
||||
$$OPUS_DIR/silk/float/find_pred_coefs_FLP.c \
|
||||
$$OPUS_DIR/silk/float/encode_frame_FLP.c \
|
||||
$$OPUS_DIR/silk/float/find_LTP_FLP.c \
|
||||
$$OPUS_DIR/silk/float/find_pitch_lags_FLP.c \
|
||||
$$OPUS_DIR/silk/float/burg_modified_FLP.c \
|
||||
$$OPUS_DIR/silk/float/corrMatrix_FLP.c \
|
||||
$$OPUS_DIR/silk/float/LTP_scale_ctrl_FLP.c \
|
||||
$$OPUS_DIR/silk/float/sort_FLP.c \
|
||||
$$OPUS_DIR/silk/float/LPC_analysis_filter_FLP.c \
|
||||
$$OPUS_DIR/silk/float/LTP_analysis_filter_FLP.c \
|
||||
$$OPUS_DIR/silk/stereo_MS_to_LR.c \
|
||||
$$OPUS_DIR/silk/log2lin.c \
|
||||
$$OPUS_DIR/silk/resampler_private_up2_HQ.c \
|
||||
$$OPUS_DIR/silk/resampler_rom.c \
|
||||
$$OPUS_DIR/silk/A2NLSF.c \
|
||||
$$OPUS_DIR/silk/NLSF_decode.c \
|
||||
$$OPUS_DIR/silk/resampler_down2.c \
|
||||
$$OPUS_DIR/silk/NLSF2A.c \
|
||||
$$OPUS_DIR/silk/table_LSF_cos.c \
|
||||
$$OPUS_DIR/silk/control_codec.c \
|
||||
$$OPUS_DIR/silk/pitch_est_tables.c \
|
||||
$$OPUS_DIR/silk/NLSF_unpack.c \
|
||||
$$OPUS_DIR/silk/resampler_private_down_FIR.c \
|
||||
$$OPUS_DIR/silk/decode_frame.c \
|
||||
$$OPUS_DIR/silk/PLC.c \
|
||||
$$OPUS_DIR/silk/check_control_input.c \
|
||||
$$OPUS_DIR/silk/decode_indices.c \
|
||||
$$OPUS_DIR/silk/encode_pulses.c \
|
||||
$$OPUS_DIR/silk/LPC_fit.c \
|
||||
$$OPUS_DIR/silk/enc_API.c \
|
||||
$$OPUS_DIR/silk/init_decoder.c \
|
||||
$$OPUS_DIR/silk/biquad_alt.c \
|
||||
$$OPUS_DIR/silk/resampler_private_IIR_FIR.c \
|
||||
$$OPUS_DIR/silk/resampler_private_AR2.c \
|
||||
$$OPUS_DIR/silk/interpolate.c \
|
||||
$$OPUS_DIR/silk/stereo_encode_pred.c \
|
||||
$$OPUS_DIR/silk/sort.c \
|
||||
$$OPUS_DIR/silk/process_NLSFs.c \
|
||||
$$OPUS_DIR/silk/tables_other.c \
|
||||
$$OPUS_DIR/silk/encode_indices.c \
|
||||
$$OPUS_DIR/silk/NLSF_encode.c \
|
||||
$$OPUS_DIR/silk/VQ_WMat_EC.c \
|
||||
$$OPUS_DIR/silk/NSQ.c \
|
||||
$$OPUS_DIR/silk/NLSF_stabilize.c \
|
||||
$$OPUS_DIR/silk/CNG.c \
|
||||
$$OPUS_DIR/silk/sum_sqr_shift.c \
|
||||
$$OPUS_DIR/silk/tables_pitch_lag.c \
|
||||
$$OPUS_DIR/silk/NLSF_del_dec_quant.c \
|
||||
$$OPUS_DIR/silk/init_encoder.c \
|
||||
$$OPUS_DIR/silk/decode_core.c \
|
||||
$$OPUS_DIR/silk/decode_pulses.c \
|
||||
$$OPUS_DIR/silk/stereo_decode_pred.c \
|
||||
$$OPUS_DIR/silk/VAD.c \
|
||||
$$OPUS_DIR/silk/decode_pitch.c \
|
||||
$$OPUS_DIR/silk/NLSF_VQ_weights_laroia.c \
|
||||
$$OPUS_DIR/silk/control_SNR.c \
|
||||
$$OPUS_DIR/silk/code_signs.c \
|
||||
$$OPUS_DIR/silk/quant_LTP_gains.c \
|
||||
$$OPUS_DIR/silk/sigm_Q15.c \
|
||||
$$OPUS_DIR/silk/lin2log.c \
|
||||
$$OPUS_DIR/silk/decode_parameters.c \
|
||||
$$OPUS_DIR/silk/resampler_down2_3.c \
|
||||
$$OPUS_DIR/silk/stereo_LR_to_MS.c \
|
||||
$$OPUS_DIR/silk/LPC_analysis_filter.c
|
||||
|
||||
INCLUDEPATH += \
|
||||
$$OPUS_DIR \
|
||||
$$OPUS_DIR/include \
|
||||
$$OPUS_DIR/src \
|
||||
$$OPUS_DIR/silk \
|
||||
$$OPUS_DIR/celt \
|
||||
$$OPUS_DIR/silk/fixed \
|
||||
$$OPUS_DIR/silk/float
|
||||
|
||||
CONFIG += warn_off staticlib
|
||||
|
||||
win32-msvc* {
|
||||
# No flags required to build with SSE on MSVC
|
||||
SOURCES += $$SOURCES_SSE $$SOURCES_SSE2 $$SOURCES_SSE41
|
||||
}
|
||||
else {
|
||||
sse.name = sse
|
||||
sse.input = SOURCES_SSE
|
||||
sse.dependency_type = TYPE_C
|
||||
sse.variable_out = OBJECTS
|
||||
sse.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_IN_BASE}$${first(QMAKE_EXT_OBJ)}
|
||||
sse.commands = $${QMAKE_CC} -c $(CFLAGS) -msse $(INCPATH) -o ${QMAKE_FILE_OUT} ${QMAKE_FILE_IN}
|
||||
|
||||
sse2.name = sse2
|
||||
sse2.input = SOURCES_SSE2
|
||||
sse2.dependency_type = TYPE_C
|
||||
sse2.variable_out = OBJECTS
|
||||
sse2.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_IN_BASE}$${first(QMAKE_EXT_OBJ)}
|
||||
sse2.commands = $${QMAKE_CC} -c $(CFLAGS) -msse2 $(INCPATH) -o ${QMAKE_FILE_OUT} ${QMAKE_FILE_IN}
|
||||
|
||||
sse41.name = sse41
|
||||
sse41.input = SOURCES_SSE41
|
||||
sse41.dependency_type = TYPE_C
|
||||
sse41.variable_out = OBJECTS
|
||||
sse41.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_IN_BASE}$${first(QMAKE_EXT_OBJ)}
|
||||
sse41.commands = $${QMAKE_CC} -c $(CFLAGS) -msse4.1 $(INCPATH) -o ${QMAKE_FILE_OUT} ${QMAKE_FILE_IN}
|
||||
|
||||
QMAKE_EXTRA_COMPILERS += sse sse2 sse41
|
||||
}
|
||||
@@ -4,9 +4,6 @@ QT += network
|
||||
TARGET = qmdnsengine
|
||||
TEMPLATE = lib
|
||||
|
||||
# Support debug and release builds from command line for CI
|
||||
CONFIG += debug_and_release
|
||||
|
||||
QMDNSE_DIR = $$PWD/qmdnsengine/src
|
||||
DEFINES += \
|
||||
QT_NO_SIGNALS_SLOTS_KEYWORDS
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
./configure --extra-cflags="-mmacosx-version-min=10.10" --enable-pic --enable-shared --disable-static --disable-all --enable-avcodec --enable-decoder=h264 --enable-decoder=hevc --enable-hwaccel=h264_videotoolbox --enable-hwaccel=hevc_videotoolbox
|
||||
make clean
|
||||
make -j4
|
||||
@@ -1,3 +0,0 @@
|
||||
./configure --toolchain=msvc --enable-cross-compile --enable-pic --enable-shared --disable-static --disable-all --enable-avcodec --enable-decoder=h264 --enable-decoder=hevc --enable-hwaccel=h264_dxva2 --enable-hwaccel=hevc_dxva2
|
||||
make clean
|
||||
make -j4
|
||||
@@ -1,3 +0,0 @@
|
||||
./configure --toolchain=msvc --enable-pic --enable-shared --disable-static --disable-all --enable-avcodec --enable-decoder=h264 --enable-decoder=hevc --enable-hwaccel=h264_dxva2 --enable-hwaccel=hevc_dxva2
|
||||
make clean
|
||||
make -j4
|
||||
@@ -1,51 +0,0 @@
|
||||
BUILD_CONFIG=$1
|
||||
|
||||
fail()
|
||||
{
|
||||
echo "$1" 1>&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
if [ "$BUILD_CONFIG" != "Debug" ] && [ "$BUILD_CONFIG" != "Release" ]; then
|
||||
fail "Invalid build configuration"
|
||||
fi
|
||||
|
||||
BUILD_ROOT=$PWD/build
|
||||
SOURCE_ROOT=$PWD
|
||||
BUILD_FOLDER=$BUILD_ROOT/build-$BUILD_CONFIG
|
||||
INSTALLER_FOLDER=$BUILD_ROOT/installer-$BUILD_CONFIG
|
||||
|
||||
echo Cleaning output directories
|
||||
rm -rf $BUILD_FOLDER
|
||||
rm -rf $INSTALLER_FOLDER
|
||||
mkdir $BUILD_ROOT
|
||||
mkdir $BUILD_FOLDER
|
||||
mkdir $INSTALLER_FOLDER
|
||||
|
||||
echo Configuring the project
|
||||
pushd $BUILD_FOLDER
|
||||
qmake $SOURCE_ROOT/moonlight-qt.pro || fail "Qmake failed!"
|
||||
popd
|
||||
|
||||
echo Compiling Moonlight in $BUILD_CONFIG configuration
|
||||
pushd $BUILD_FOLDER
|
||||
make $(echo "$BUILD_CONFIG" | tr '[:upper:]' '[:lower:]') || fail "Make failed!"
|
||||
popd
|
||||
|
||||
echo Copying dylib dependencies
|
||||
mkdir $BUILD_FOLDER/app/Moonlight.app/Contents/lib
|
||||
cp $SOURCE_ROOT/libs/mac/lib/*.dylib $BUILD_FOLDER/app/Moonlight.app/Contents/lib/ || fail "Dylib copy failed!"
|
||||
|
||||
echo Copying frameworks dependencies
|
||||
mkdir $BUILD_FOLDER/app/Moonlight.app/Contents/Frameworks
|
||||
cp -R $SOURCE_ROOT/libs/mac/Frameworks/ $BUILD_FOLDER/app/Moonlight.app/Contents/Frameworks/ || fail "Framework copy failed!"
|
||||
|
||||
echo Creating DMG
|
||||
EXTRA_ARGS=
|
||||
if [ "$BUILD_CONFIG" == "Debug" ]; then EXTRA_ARGS="$EXTRA_ARGS -use-debug-libs"; fi
|
||||
if [ "$SIGNING_KEY" != "" ]; then EXTRA_ARGS="$EXTRA_ARGS -codesign=$SIGNING_KEY"; fi
|
||||
echo Extra deployment arguments: $EXTRA_ARGS
|
||||
macdeployqt $BUILD_FOLDER/app/Moonlight.app -dmg $EXTRA_ARGS -qmldir=$SOURCE_ROOT/app/gui -appstore-compliant || fail "macdeployqt failed!"
|
||||
|
||||
echo Deploying DMG
|
||||
mv $BUILD_FOLDER/app/Moonlight.dmg $INSTALLER_FOLDER/
|
||||
@@ -1,10 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# The ImageMagick conversion tool doesn't seem to always generate
|
||||
# ICO files with background transparency properly. Please validate
|
||||
# that the output has a transparent background.
|
||||
|
||||
convert -density 256 -background none -define icon:auto-resize ../app/res/moonlight.svg ../app/moonlight.ico
|
||||
convert -density 256 -background none -size 64x64 ../app/res/moonlight.svg ../app/moonlight_wix.png
|
||||
|
||||
echo IMPORTANT: Validate the icon has a transparent background before committing!
|
||||
@@ -1,118 +0,0 @@
|
||||
rem Run from Qt command prompt with working directory set to root of repo
|
||||
|
||||
setlocal enableDelayedExpansion
|
||||
@echo off
|
||||
|
||||
set BUILD_CONFIG=%1
|
||||
set ARCH=%2
|
||||
|
||||
rem Convert to lower case for windeployqt
|
||||
if /I "%BUILD_CONFIG%"=="debug" (
|
||||
set BUILD_CONFIG=debug
|
||||
) else (
|
||||
if /I "%BUILD_CONFIG%"=="release" (
|
||||
set BUILD_CONFIG=release
|
||||
) else (
|
||||
if /I "%BUILD_CONFIG%"=="signed-release" (
|
||||
set BUILD_CONFIG=release
|
||||
set SIGN=1
|
||||
) else (
|
||||
echo Invalid build configuration
|
||||
exit /b 1
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
if /I "%ARCH%" NEQ "x86" (
|
||||
if /I "%ARCH%" NEQ "x64" (
|
||||
echo Invalid build architecture
|
||||
exit /b 1
|
||||
)
|
||||
)
|
||||
|
||||
set VS_PATH=%ProgramFiles(x86)%\Microsoft Visual Studio\2017\Community
|
||||
set SIGNTOOL_PARAMS=sign /tr http://timestamp.digicert.com /td sha256 /fd sha256 /sha1 1B3C676E831A94EC0327C3347EB32C68C26B3A67 /v
|
||||
|
||||
call "%VS_PATH%\VC\Auxiliary\Build\vcvarsall.bat" %ARCH%
|
||||
if !ERRORLEVEL! NEQ 0 goto Error
|
||||
|
||||
set BUILD_ROOT=%cd%\build
|
||||
set SOURCE_ROOT=%cd%
|
||||
set BUILD_FOLDER=%BUILD_ROOT%\build-%ARCH%-%BUILD_CONFIG%
|
||||
set DEPLOY_FOLDER=%BUILD_ROOT%\deploy-%ARCH%-%BUILD_CONFIG%
|
||||
set INSTALLER_FOLDER=%BUILD_ROOT%\installer-%ARCH%-%BUILD_CONFIG%
|
||||
|
||||
echo Cleaning output directories
|
||||
rmdir /s /q %DEPLOY_FOLDER%
|
||||
rmdir /s /q %BUILD_FOLDER%
|
||||
rmdir /s /q %INSTALLER_FOLDER%
|
||||
mkdir %BUILD_ROOT%
|
||||
mkdir %DEPLOY_FOLDER%
|
||||
mkdir %BUILD_FOLDER%
|
||||
mkdir %INSTALLER_FOLDER%
|
||||
|
||||
echo Configuring the project
|
||||
pushd %BUILD_FOLDER%
|
||||
qmake %SOURCE_ROOT%\moonlight-qt.pro
|
||||
if !ERRORLEVEL! NEQ 0 goto Error
|
||||
popd
|
||||
|
||||
echo Compiling Moonlight in %BUILD_CONFIG% configuration
|
||||
pushd %BUILD_FOLDER%
|
||||
nmake %BUILD_CONFIG%
|
||||
if !ERRORLEVEL! NEQ 0 goto Error
|
||||
popd
|
||||
|
||||
echo Copying DLL dependencies
|
||||
copy %SOURCE_ROOT%\libs\windows\lib\%ARCH%\*.dll %DEPLOY_FOLDER%
|
||||
if !ERRORLEVEL! NEQ 0 goto Error
|
||||
|
||||
echo Deploying Qt dependencies
|
||||
windeployqt.exe --dir %DEPLOY_FOLDER% --%BUILD_CONFIG% --qmldir %SOURCE_ROOT%\app\gui --no-opengl-sw --no-compiler-runtime %BUILD_FOLDER%\app\%BUILD_CONFIG%\Moonlight.exe
|
||||
if !ERRORLEVEL! NEQ 0 goto Error
|
||||
|
||||
echo Harvesting files for WiX
|
||||
"%WIX%\bin\heat" dir %DEPLOY_FOLDER% -srd -sfrag -ag -sw5150 -cg MoonlightDependencies -var var.SourceDir -dr INSTALLFOLDER -out %BUILD_FOLDER%\Dependencies.wxs
|
||||
if !ERRORLEVEL! NEQ 0 goto Error
|
||||
|
||||
echo Copying application binary to deployment directory
|
||||
copy %BUILD_FOLDER%\app\%BUILD_CONFIG%\Moonlight.exe %DEPLOY_FOLDER%
|
||||
if !ERRORLEVEL! NEQ 0 goto Error
|
||||
|
||||
if "%SIGN%"=="1" (
|
||||
echo Signing deployed binaries
|
||||
for /r "%DEPLOY_FOLDER%" %%f in (*.dll *.exe) do (
|
||||
signtool %SIGNTOOL_PARAMS% %%f
|
||||
if !ERRORLEVEL! NEQ 0 goto Error
|
||||
)
|
||||
)
|
||||
|
||||
echo Building installer
|
||||
set VCREDIST_INSTALLER=%VS_PATH%\VC\Redist\MSVC\14.14.26405\vcredist_%ARCH%.exe
|
||||
msbuild %SOURCE_ROOT%\wix\Moonlight.sln /p:Configuration=%BUILD_CONFIG% /p:Platform=%ARCH%
|
||||
if !ERRORLEVEL! NEQ 0 goto Error
|
||||
|
||||
if "%SIGN%"=="1" (
|
||||
echo Signing installer binary
|
||||
"%WIX%\bin\insignia" -ib %INSTALLER_FOLDER%\MoonlightSetup.exe -o %BUILD_FOLDER%\engine.exe
|
||||
if !ERRORLEVEL! NEQ 0 goto Error
|
||||
signtool %SIGNTOOL_PARAMS% %BUILD_FOLDER%\engine.exe
|
||||
if !ERRORLEVEL! NEQ 0 goto Error
|
||||
"%WIX%\bin\insignia" -ab %BUILD_FOLDER%\engine.exe %INSTALLER_FOLDER%\MoonlightSetup.exe -o %INSTALLER_FOLDER%\MoonlightSetup.exe
|
||||
if !ERRORLEVEL! NEQ 0 goto Error
|
||||
signtool %SIGNTOOL_PARAMS% %INSTALLER_FOLDER%\MoonlightSetup.exe
|
||||
if !ERRORLEVEL! NEQ 0 goto Error
|
||||
)
|
||||
|
||||
if /i "%APPVEYOR%"=="true" (
|
||||
echo Pushing artifacts
|
||||
appveyor PushArtifact %INSTALLER_FOLDER%\MoonlightSetup.exe -FileName MoonlightSetup-%ARCH%-%BUILD_CONFIG%.exe
|
||||
if !ERRORLEVEL! NEQ 0 goto Error
|
||||
)
|
||||
|
||||
echo Build successful!
|
||||
exit /b 0
|
||||
|
||||
:Error
|
||||
echo Build failed!
|
||||
exit /b !ERRORLEVEL!
|
||||
@@ -1,27 +0,0 @@
|
||||
#!/bin/bash
|
||||
# https://gist.github.com/zlbruce/883605a635df8d5964bab11ed75e46ad
|
||||
echo "*** SVG 2 ICNS ***"
|
||||
if [ $# -ne 1 ]; then
|
||||
echo "Usage: svg2icns filename.svg"
|
||||
exit 100
|
||||
fi
|
||||
filename="$1"
|
||||
name=${filename%.*}
|
||||
ext=${filename##*.}
|
||||
echo "processing: $name"
|
||||
dest="$name".iconset
|
||||
mkdir "$dest"
|
||||
|
||||
convert -background none -resize '!16x16' "$1" "$dest/icon_16x16.png"
|
||||
convert -background none -resize '!32x32' "$1" "$dest/[email protected]"
|
||||
cp "$dest/[email protected]" "$dest/icon_32x32.png"
|
||||
convert -background none -resize '!64x64' "$1" "$dest/[email protected]"
|
||||
convert -background none -resize '!128x128' "$1" "$dest/icon_128x128.png"
|
||||
convert -background none -resize '!256x256' "$1" "$dest/[email protected]"
|
||||
cp "$dest/[email protected]" "$dest/icon_256x256.png"
|
||||
convert -background none -resize '!512x512' "$1" "$dest/[email protected]"
|
||||
cp "$dest/[email protected]" "$dest/icon_512x512.png"
|
||||
convert -background none -resize '!1024x1024' "$1" "$dest/[email protected]"
|
||||
|
||||
iconutil -c icns "$dest"
|
||||
rm -R "$dest"
|
||||
@@ -1,41 +0,0 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.27703.2035
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "MoonlightSetup", "MoonlightSetup\MoonlightSetup.wixproj", "{466FA35D-4BE4-40EF-9CE5-AFADC3B63BC5}"
|
||||
EndProject
|
||||
Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "Moonlight", "Moonlight\Moonlight.wixproj", "{8468EF94-3BB8-47A5-AF15-0E314AFE664D}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{466FA35D-4BE4-40EF-9CE5-AFADC3B63BC5}.Debug|x64.ActiveCfg = Debug|x86
|
||||
{466FA35D-4BE4-40EF-9CE5-AFADC3B63BC5}.Debug|x64.Build.0 = Debug|x86
|
||||
{466FA35D-4BE4-40EF-9CE5-AFADC3B63BC5}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{466FA35D-4BE4-40EF-9CE5-AFADC3B63BC5}.Debug|x86.Build.0 = Debug|x86
|
||||
{466FA35D-4BE4-40EF-9CE5-AFADC3B63BC5}.Release|x64.ActiveCfg = Release|x86
|
||||
{466FA35D-4BE4-40EF-9CE5-AFADC3B63BC5}.Release|x64.Build.0 = Release|x86
|
||||
{466FA35D-4BE4-40EF-9CE5-AFADC3B63BC5}.Release|x86.ActiveCfg = Release|x86
|
||||
{466FA35D-4BE4-40EF-9CE5-AFADC3B63BC5}.Release|x86.Build.0 = Release|x86
|
||||
{8468EF94-3BB8-47A5-AF15-0E314AFE664D}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{8468EF94-3BB8-47A5-AF15-0E314AFE664D}.Debug|x64.Build.0 = Debug|x64
|
||||
{8468EF94-3BB8-47A5-AF15-0E314AFE664D}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{8468EF94-3BB8-47A5-AF15-0E314AFE664D}.Debug|x86.Build.0 = Debug|x86
|
||||
{8468EF94-3BB8-47A5-AF15-0E314AFE664D}.Release|x64.ActiveCfg = Release|x64
|
||||
{8468EF94-3BB8-47A5-AF15-0E314AFE664D}.Release|x64.Build.0 = Release|x64
|
||||
{8468EF94-3BB8-47A5-AF15-0E314AFE664D}.Release|x86.ActiveCfg = Release|x86
|
||||
{8468EF94-3BB8-47A5-AF15-0E314AFE664D}.Release|x86.Build.0 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {7EEF5F41-49B8-4803-9608-6EA127BE9AE1}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -1,43 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" InitialTargets="EnsureWixToolsetInstalled" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<ProductVersion>3.10</ProductVersion>
|
||||
<ProjectGuid>8468ef94-3bb8-47a5-af15-0e314afe664d</ProjectGuid>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<OutputName>Moonlight</OutputName>
|
||||
<OutputType>Package</OutputType>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
|
||||
<DefineConstants>Debug</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<OutputPath>$(BUILD_FOLDER)\</OutputPath>
|
||||
<IntermediateOutputPath>$(BUILD_FOLDER)\</IntermediateOutputPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<DefineConstants>SourceDir=$(DEPLOY_FOLDER)</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Product.wxs" />
|
||||
<Compile Include="$(BUILD_FOLDER)\Dependencies.wxs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<WixExtension Include="WixFirewallExtension">
|
||||
<HintPath>$(WixExtDir)\WixFirewallExtension.dll</HintPath>
|
||||
<Name>WixFirewallExtension</Name>
|
||||
</WixExtension>
|
||||
</ItemGroup>
|
||||
<Import Project="$(WixTargetsPath)" Condition=" '$(WixTargetsPath)' != '' " />
|
||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets" Condition=" '$(WixTargetsPath)' == '' AND Exists('$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets') " />
|
||||
<Target Name="EnsureWixToolsetInstalled" Condition=" '$(WixTargetsImported)' != 'true' ">
|
||||
<Error Text="The WiX Toolset v3.11 (or newer) build tools must be installed to build this project. To download the WiX Toolset, see http://wixtoolset.org/releases/" />
|
||||
</Target>
|
||||
<!--
|
||||
To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Wix.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
@@ -1,87 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?define ShortName = "Moonlight" ?>
|
||||
<?define FullName = "Moonlight Game Streaming Client" ?>
|
||||
|
||||
<?define ShortcutName = "$(var.ShortName)" ?>
|
||||
<?define ShortcutDesc = "Stream games from a NVIDIA GameStream-compatible PC" ?>
|
||||
<?define InstallFolder = "Moonlight Game Streaming" ?>
|
||||
|
||||
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
|
||||
xmlns:fire="http://schemas.microsoft.com/wix/FirewallExtension">
|
||||
|
||||
<Product Id="*"
|
||||
Name="$(var.FullName)"
|
||||
Language="1033"
|
||||
Version="!(bind.fileVersion.MoonlightExe)"
|
||||
Manufacturer="Moonlight Game Streaming Team"
|
||||
UpgradeCode="5c09f94e-f809-4c6a-9b7b-597c99f041fe">
|
||||
|
||||
<Package InstallerVersion="500" Compressed="yes" InstallScope="perMachine" />
|
||||
|
||||
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
|
||||
<MediaTemplate CompressionLevel="high" />
|
||||
|
||||
<?if $(var.Platform) = x64 ?>
|
||||
<?define PlatformProgramFilesFolder = "ProgramFiles64Folder" ?>
|
||||
<?else ?>
|
||||
<?define PlatformProgramFilesFolder = "ProgramFilesFolder" ?>
|
||||
<?endif ?>
|
||||
|
||||
<Directory Id="TARGETDIR" Name="SourceDir">
|
||||
<Directory Id="DesktopFolder" />
|
||||
<Directory Id="$(var.PlatformProgramFilesFolder)">
|
||||
<Directory Id="INSTALLFOLDER" Name="$(var.InstallFolder)" />
|
||||
</Directory>
|
||||
<Directory Id="ProgramMenuFolder">
|
||||
<Directory Id="ApplicationProgramsFolder" Name="$(var.InstallFolder)" />
|
||||
</Directory>
|
||||
</Directory>
|
||||
|
||||
<!-- There's no way to delete a registry key on uninstall but not major upgrade, so
|
||||
we have to roll our own deletion via custom action -->
|
||||
<CustomAction Id="DeleteRegistryKey"
|
||||
Directory="$(var.PlatformProgramFilesFolder)"
|
||||
ExeCommand="reg.exe delete "HKCU\Software\Moonlight Game Streaming Project" /f"
|
||||
Execute="deferred"
|
||||
Return="ignore"
|
||||
Impersonate="yes"/>
|
||||
<InstallExecuteSequence>
|
||||
<Custom Action="DeleteRegistryKey" Before="InstallFinalize">Installed AND REMOVE~="ALL" AND NOT UPGRADINGPRODUCTCODE</Custom>
|
||||
</InstallExecuteSequence>
|
||||
|
||||
<Component Id="MoonlightShortcuts" Guid="*" Directory="INSTALLFOLDER">
|
||||
<Shortcut Id="StartMenuShortcut"
|
||||
Name="$(var.ShortcutName)"
|
||||
Description="$(var.ShortcutDesc)"
|
||||
Target="[#MoonlightExe]"
|
||||
Directory="ApplicationProgramsFolder"
|
||||
WorkingDirectory="INSTALLFOLDER" />
|
||||
<Shortcut Id="DesktopShortcut"
|
||||
Name="$(var.ShortcutName)"
|
||||
Description="$(var.ShortcutDesc)"
|
||||
Target="[#MoonlightExe]"
|
||||
Directory="DesktopFolder"
|
||||
WorkingDirectory="INSTALLFOLDER" />
|
||||
<RemoveFolder Id="CleanupStartMenuShortcut" Directory="ApplicationProgramsFolder" On="uninstall" />
|
||||
<RemoveFolder Id="CleanupDesktopShortcut" Directory="DesktopFolder" On="uninstall" />
|
||||
<RegistryValue Root="HKCU" Key="Software\Moonlight Game Streaming Project" Name="Installed" Type="integer" Value="1" KeyPath="yes" />
|
||||
</Component>
|
||||
|
||||
<DirectoryRef Id="INSTALLFOLDER">
|
||||
<Component Id="Moonlight" Guid="*">
|
||||
<File Id="MoonlightExe" KeyPath="yes" Checksum="yes" Source="$(var.SourceDir)\Moonlight.exe">
|
||||
<fire:FirewallException Id="MoonlightFirewallException"
|
||||
Scope="any"
|
||||
Name="$(var.FullName)" />
|
||||
</File>
|
||||
</Component>
|
||||
</DirectoryRef>
|
||||
|
||||
<Feature Id="ProductFeature" Title="Moonlight" Level="1" ConfigurableDirectory="INSTALLFOLDER">
|
||||
<ComponentRef Id="Moonlight" />
|
||||
<ComponentRef Id="MoonlightShortcuts" />
|
||||
<ComponentGroupRef Id="MoonlightDependencies" />
|
||||
</Feature>
|
||||
</Product>
|
||||
</Wix>
|
||||
@@ -1,78 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
|
||||
xmlns:bal="http://schemas.microsoft.com/wix/BalExtension"
|
||||
xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
|
||||
|
||||
<Bundle Name="Moonlight Game Streaming Client"
|
||||
Version="!(bind.PackageVersion.Moonlight)"
|
||||
Manufacturer="Moonlight Game Streaming Team"
|
||||
UpgradeCode="466fa35d-4be4-40ef-9ce5-afadc3b63bc5"
|
||||
HelpUrl="https://github.com/moonlight-stream/moonlight-docs/wiki/Setup-Guide"
|
||||
UpdateUrl="https://github.com/moonlight-stream/moonlight-qt/releases"
|
||||
DisableModify="yes"
|
||||
IconSourceFile="..\..\app\moonlight.ico">
|
||||
|
||||
<bal:Condition Message="Moonlight requires Windows 7 or later.">
|
||||
<![CDATA[VersionNT >= v6.1]]>
|
||||
</bal:Condition>
|
||||
|
||||
<!-- https://stackoverflow.com/questions/46637094/how-can-i-find-the-upgrade-code-for-an-installed-msi-file -->
|
||||
<?if $(env.ARCH) ~= x86 ?>
|
||||
<util:ProductSearch Id="Find_VCRedist_x86"
|
||||
UpgradeCode="{C78B8E51-0C65-377E-85D1-282F689FE505}"
|
||||
Result="state"
|
||||
Variable="VCRedist_Present" />
|
||||
<?elseif $(env.ARCH) ~= x64 ?>
|
||||
<util:ProductSearch Id="Find_VCRedist_x64"
|
||||
UpgradeCode="{9B0BAA88-E15F-3A1F-ACC0-B206E9DDF71C}"
|
||||
Result="state"
|
||||
Variable="VCRedist_Present" />
|
||||
<?else ?>
|
||||
<?error Bad ARCH value ?>
|
||||
<?endif ?>
|
||||
|
||||
<?if $(env.ARCH) ~= x64 ?>
|
||||
<bal:Condition Message="This Moonlight installer requires a 64-bit (x64) OS. Please download the 32-bit (x86) installer.">
|
||||
VersionNT64
|
||||
</bal:Condition>
|
||||
<?elseif $(env.ARCH) ~= x86 ?>
|
||||
<bal:Condition Message="This Moonlight installer requires a 32-bit (x86) OS. Please download the 64-bit (x64) installer.">
|
||||
NOT VersionNT64
|
||||
</bal:Condition>
|
||||
<?endif ?>
|
||||
|
||||
<?if $(env.ARCH) ~= x64 ?>
|
||||
<Variable Name="InstallFolder" Type="string" Value="[ProgramFiles64Folder]Moonlight Game Streaming" />
|
||||
<?elseif $(env.ARCH) ~= x86 ?>
|
||||
<Variable Name="InstallFolder" Type="string" Value="[ProgramFilesFolder]Moonlight Game Streaming" />
|
||||
<?endif ?>
|
||||
|
||||
<BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.RtfLicense">
|
||||
<bal:WixStandardBootstrapperApplication
|
||||
ShowVersion="yes"
|
||||
LicenseFile="license.rtf"
|
||||
LogoFile="..\..\app\moonlight_wix.png"
|
||||
ShowFilesInUse="yes"
|
||||
LaunchTarget="[InstallFolder]\Moonlight.exe" />
|
||||
</BootstrapperApplicationRef>
|
||||
|
||||
<Chain>
|
||||
<ExePackage Cache="no"
|
||||
PerMachine="yes"
|
||||
Permanent="yes"
|
||||
InstallCondition="VCRedist_Present = 2"
|
||||
Vital="yes"
|
||||
Compressed="yes"
|
||||
SourceFile="$(env.VCREDIST_INSTALLER)"
|
||||
InstallCommand="/install /quiet /norestart">
|
||||
<!-- Newer version installed is fine -->
|
||||
<ExitCode Value="1638" Behavior="success" />
|
||||
</ExePackage>
|
||||
<MsiPackage Id="Moonlight" SourceFile="$(var.Moonlight.TargetPath)" Vital="yes">
|
||||
<MsiProperty Name="INSTALLFOLDER" Value="[InstallFolder]" />
|
||||
</MsiPackage>
|
||||
</Chain>
|
||||
|
||||
</Bundle>
|
||||
</Wix>
|
||||
@@ -1,53 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" InitialTargets="EnsureWixToolsetInstalled" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<ProductVersion>3.10</ProductVersion>
|
||||
<ProjectGuid>466fa35d-4be4-40ef-9ce5-afadc3b63bc5</ProjectGuid>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<OutputName>MoonlightSetup</OutputName>
|
||||
<OutputType>Bundle</OutputType>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
|
||||
<DefineConstants>Debug</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<OutputPath>$(INSTALLER_FOLDER)\</OutputPath>
|
||||
<IntermediateOutputPath>$(BUILD_FOLDER)\</IntermediateOutputPath>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Bundle.wxs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<WixExtension Include="WixBalExtension">
|
||||
<HintPath>$(WixExtDir)\WixBalExtension.dll</HintPath>
|
||||
<Name>WixBalExtension</Name>
|
||||
</WixExtension>
|
||||
<WixExtension Include="WixUtilExtension">
|
||||
<HintPath>$(WixExtDir)\WixUtilExtension.dll</HintPath>
|
||||
<Name>WixUtilExtension</Name>
|
||||
</WixExtension>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Moonlight\Moonlight.wixproj">
|
||||
<Name>Moonlight</Name>
|
||||
<Project>{8468ef94-3bb8-47a5-af15-0e314afe664d}</Project>
|
||||
<Private>True</Private>
|
||||
<DoNotHarvest>True</DoNotHarvest>
|
||||
<RefProjectOutputGroups>Binaries;Content;Satellites</RefProjectOutputGroups>
|
||||
<RefTargetDir>INSTALLFOLDER</RefTargetDir>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(WixTargetsPath)" Condition=" '$(WixTargetsPath)' != '' " />
|
||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets" Condition=" '$(WixTargetsPath)' == '' AND Exists('$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets') " />
|
||||
<Target Name="EnsureWixToolsetInstalled" Condition=" '$(WixTargetsImported)' != 'true' ">
|
||||
<Error Text="The WiX Toolset v3.11 (or newer) build tools must be installed to build this project. To download the WiX Toolset, see http://wixtoolset.org/releases/" />
|
||||
</Target>
|
||||
<!--
|
||||
To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Wix.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
@@ -1,124 +0,0 @@
|
||||
{\rtf1\ansi\deff0\nouicompat{\fonttbl{\f0\fswiss Helvetica;}{\f1\fswiss\fcharset0 Helvetica;}}
|
||||
{\colortbl ;\red0\green0\blue255;}
|
||||
{\*\generator Riched20 10.0.17713}\viewkind4\uc1
|
||||
\pard\sa180\b\f0\fs28\lang9 GNU GENERAL PUBLIC LICENSE\par
|
||||
\b0\fs24 Version 3, 29 June 2007\par
|
||||
Copyright \f1\'a9 2007 Free Software Foundation, Inc. <{{\field{\*\fldinst{HYPERLINK "https://fsf.org/"}}{\fldrslt{https://fsf.org/\ul0\cf0}}}}\f1\fs24 >\par
|
||||
\f0 Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.\par
|
||||
\b\fs28 Preamble\par
|
||||
\b0\fs24 The GNU General Public License is a free, copyleft license for software and other kinds of works.\par
|
||||
The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too.\par
|
||||
When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things.\par
|
||||
To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others.\par
|
||||
For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.\par
|
||||
Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it.\par
|
||||
For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions.\par
|
||||
Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users.\par
|
||||
Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free.\par
|
||||
The precise terms and conditions for copying, distribution and modification follow.\par
|
||||
\b\fs28 TERMS AND CONDITIONS\par
|
||||
\fs24 0. Definitions.\par
|
||||
\b0\ldblquote This License\rdblquote refers to version 3 of the GNU General Public License.\par
|
||||
\ldblquote Copyright\rdblquote also means copyright-like laws that apply to other kinds of works, such as semiconductor masks.\par
|
||||
\ldblquote The Program\rdblquote refers to any copyrightable work licensed under this License. Each licensee is addressed as \ldblquote you\rdblquote . \ldblquote Licensees\rdblquote and \ldblquote recipients\rdblquote may be individuals or organizations.\par
|
||||
To \ldblquote modify\rdblquote a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a \ldblquote modified version\rdblquote of the earlier work or a work \ldblquote based on\rdblquote the earlier work.\par
|
||||
A \ldblquote covered work\rdblquote means either the unmodified Program or a work based on the Program.\par
|
||||
To \ldblquote propagate\rdblquote a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well.\par
|
||||
To \ldblquote convey\rdblquote a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying.\par
|
||||
An interactive user interface displays \ldblquote Appropriate Legal Notices\rdblquote to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion.\par
|
||||
\b 1. Source Code.\par
|
||||
\b0 The \ldblquote source code\rdblquote for a work means the preferred form of the work for making modifications to it. \ldblquote Object code\rdblquote means any non-source form of a work.\par
|
||||
A \ldblquote Standard Interface\rdblquote means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language.\par
|
||||
The \ldblquote System Libraries\rdblquote of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A \ldblquote Major Component\rdblquote , in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it.\par
|
||||
The \ldblquote Corresponding Source\rdblquote for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work.\par
|
||||
The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source.\par
|
||||
The Corresponding Source for a work in source code form is that same work.\par
|
||||
\b 2. Basic Permissions.\par
|
||||
\b0 All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law.\par
|
||||
You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you.\par
|
||||
Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary.\par
|
||||
\b 3. Protecting Users' Legal Rights From Anti-Circumvention Law.\par
|
||||
\b0 No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures.\par
|
||||
When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures.\par
|
||||
\b 4. Conveying Verbatim Copies.\par
|
||||
\b0 You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program.\par
|
||||
You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee.\par
|
||||
\b 5. Conveying Modified Source Versions.\par
|
||||
\b0 You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions:\par
|
||||
|
||||
\pard\fi-360\li360\tx360\bullet\tab a) The work must carry prominent notices stating that you modified it, and giving a relevant date.\par
|
||||
\bullet\tab b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to \ldblquote keep intact all notices\rdblquote .\par
|
||||
\bullet\tab c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it.\par
|
||||
|
||||
\pard\fi-360\li360\sa180\tx360\bullet\tab d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so.\par
|
||||
|
||||
\pard\sa180 A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an \ldblquote aggregate\rdblquote if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate.\par
|
||||
\b 6. Conveying Non-Source Forms.\par
|
||||
\b0 You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways:\par
|
||||
|
||||
\pard\fi-360\li360\tx360\bullet\tab a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange.\par
|
||||
\bullet\tab b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge.\par
|
||||
\bullet\tab c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b.\par
|
||||
\bullet\tab d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements.\par
|
||||
|
||||
\pard\fi-360\li360\sa180\tx360\bullet\tab e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d.\par
|
||||
|
||||
\pard\sa180 A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work.\par
|
||||
A \ldblquote User Product\rdblquote is either (1) a \ldblquote consumer product\rdblquote , which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, \ldblquote normally used\rdblquote refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product.\par
|
||||
\ldblquote Installation Information\rdblquote for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made.\par
|
||||
If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM).\par
|
||||
The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network.\par
|
||||
Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying.\par
|
||||
\b 7. Additional Terms.\par
|
||||
\b0\ldblquote Additional permissions\rdblquote are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions.\par
|
||||
When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission.\par
|
||||
Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms:\par
|
||||
|
||||
\pard\fi-360\li360\tx360\bullet\tab a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or\par
|
||||
\bullet\tab b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or\par
|
||||
\bullet\tab c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or\par
|
||||
\bullet\tab d) Limiting the use for publicity purposes of names of licensors or authors of the material; or\par
|
||||
\bullet\tab e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or\par
|
||||
|
||||
\pard\fi-360\li360\sa180\tx360\bullet\tab f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors.\par
|
||||
|
||||
\pard\sa180 All other non-permissive additional terms are considered \ldblquote further restrictions\rdblquote within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying.\par
|
||||
If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms.\par
|
||||
Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way.\par
|
||||
\b 8. Termination.\par
|
||||
\b0 You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11).\par
|
||||
However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation.\par
|
||||
Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice.\par
|
||||
Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10.\par
|
||||
\b 9. Acceptance Not Required for Having Copies.\par
|
||||
\b0 You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so.\par
|
||||
\b 10. Automatic Licensing of Downstream Recipients.\par
|
||||
\b0 Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License.\par
|
||||
An \ldblquote entity transaction\rdblquote is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts.\par
|
||||
You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it.\par
|
||||
\b 11. Patents.\par
|
||||
\b0 A \ldblquote contributor\rdblquote is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's \ldblquote contributor version\rdblquote .\par
|
||||
A contributor's \ldblquote essential patent claims\rdblquote are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, \ldblquote control\rdblquote includes the right to grant patent sublicenses in a manner consistent with the requirements of this License.\par
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version.\par
|
||||
In the following three paragraphs, a \ldblquote patent license\rdblquote is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To \ldblquote grant\rdblquote such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party.\par
|
||||
If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. \ldblquote Knowingly relying\rdblquote means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid.\par
|
||||
If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it.\par
|
||||
A patent license is \ldblquote discriminatory\rdblquote if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007.\par
|
||||
Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law.\par
|
||||
\b 12. No Surrender of Others' Freedom.\par
|
||||
\b0 If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program.\par
|
||||
\b 13. Use with the GNU Affero General Public License.\par
|
||||
\b0 Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such.\par
|
||||
\b 14. Revised Versions of this License.\par
|
||||
\b0 The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.\par
|
||||
Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License \ldblquote or any later version\rdblquote applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation.\par
|
||||
If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program.\par
|
||||
Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version.\par
|
||||
\b 15. Disclaimer of Warranty.\par
|
||||
\b0 THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \ldblquote AS IS\rdblquote WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.\par
|
||||
\b 16. Limitation of Liability.\par
|
||||
\b0 IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.\par
|
||||
\b 17. Interpretation of Sections 15 and 16.\par
|
||||
\b0 If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee.\b\fs28\par
|
||||
}
|
||||
| ||||