Compare commits

...
Author SHA1 Message Date
Cameron Gutman 42ed39a67f Version 0.0.3 2018-07-28 03:13:39 -07:00
Cameron Gutman 68612db86d Fix audio glitching on GFE 3.14.1 at low bitrates 2018-07-28 03:13:05 -07:00
Cameron Gutman 3ad5f1478c Comment out HDR option since it's non-working and tweak the remaining option text 2018-07-28 03:06:11 -07:00
Cameron Gutman a81b501d7d Hide the gamepad mapping button since it's unimplemented 2018-07-28 01:27:42 -07:00
Cameron Gutman 871988b2cb Add 1440p and up to 90 FPS streaming options for > 60 Hz monitors 2018-07-28 01:22:31 -07:00
Cameron Gutman 59d087adf5 Add function for querying maximum supported streaming frame rate 2018-07-28 00:25:52 -07:00
Cameron Gutman d9ed3f9694 Fix incorrect key mappings with non-QWERTY keyboards on both host and client 2018-07-27 02:08:54 -07:00
Cameron Gutman e652dbcc79 Version 0.0.2 2018-07-27 00:14:29 -07:00
Cameron Gutman b5965d763c Create desktop shortcut, detect various error conditions to fail installation, and only install VCRedist if it's not already present 2018-07-27 00:13:02 -07:00
Cameron Gutman 717c3903d1 Fix top padding for grid views 2018-07-26 22:47:48 -07:00
Cameron Gutman 5854ce2000 Fix handling of long app names 2018-07-26 22:39:45 -07:00
Cameron Gutman eb1316ce32 Avoid asserting if we get a box art load completion callback for an app that's gone 2018-07-26 22:16:27 -07:00
Cameron Gutman c31e7262b2 Fix decoding of non-ASCII characters 2018-07-26 22:15:52 -07:00
Cameron Gutman 9e6aadffa1 Populate the DXVA2_VideoDesc with format details from the AVFrame 2018-07-26 21:04:05 -07:00
Cameron Gutman 0bde932550 Prevent HEVC streaming with the software decoder for performance reasons 2018-07-26 19:26:22 -07:00
Cameron Gutman f5499be215 Warn when no hardware decoding is available 2018-07-26 12:13:38 -07:00
Cameron Gutman 42988e0dbf Limit log file sizes to 10k lines 2018-07-26 00:21:26 -07:00
Cameron Gutman b16aac0c06 Fix priority and formatting on many debug messages 2018-07-25 23:47:32 -07:00
Cameron Gutman 7c74cdc50b Add enhanced logging support, including log to file for release builds 2018-07-25 23:25:17 -07:00
Cameron Gutman 26ee8564f8 Include VC redistributable in the bundle 2018-07-25 19:52:58 -07:00
Cameron Gutman 718a575478 Reorganize WiX sources 2018-07-25 19:33:09 -07:00
Cameron Gutman 1f314b839e Various installer fixes 2018-07-25 19:16:06 -07:00
Cameron Gutman 34494e4c89 Add initial WiX installer for Windows 2018-07-25 02:53:51 -07:00
Cameron Gutman 03dc563b32 Create Moonlight png for WiX bootstrapper 2018-07-24 21:11:48 -07:00
Cameron Gutman 5e4182f0a0 Add Moonlight.ico for Windows and script to generate it 2018-07-24 20:07:10 -07:00
Cameron Gutman 010475e8a2 Use per-display undefined window positions 2018-07-22 18:40:15 -07:00
Cameron Gutman bd170c4bd6 Always use the current display mode and just let the renderers scale the output 2018-07-22 18:28:17 -07:00
Cameron Gutman 386e463942 Also use the SDL icon for Linux 2018-07-22 17:42:31 -07:00
Cameron Gutman 9d840afdfb Add an SDL window icon for Windows 2018-07-22 17:07:45 -07:00
Cameron Gutman 83b81aad4b Don't capture the mouse initially on debug builds 2018-07-22 16:21:15 -07:00
Cameron Gutman 4caa7ec749 Enable LC_DEBUG for debug builds 2018-07-22 16:05:42 -07:00
Cameron Gutman cf3cbd627d Use full-screen windowed mode to avoid having to enable V-Sync on DXVA2 2018-07-22 15:42:17 -07:00
Cameron Gutman 3bb62a82e1 Avoid doing a display mode change on Linux when entering full-screen 2018-07-22 14:03:47 -07:00
Cameron Gutman a06a625d48 Rework the logo SVG to look better as an app icon, by Jorys Paulin 2018-07-22 03:21:19 -07:00
Cameron Gutman 13d686b6f8 Rename output binary to moonlight 2018-07-22 03:16:53 -07:00
Cameron Gutman 75c7b2828f Remove unneccessary FFmpeg files 2018-07-22 02:47:59 -07:00
Cameron Gutman 18c5e19ac9 Add files for Flatpak deployment 2018-07-22 01:51:05 -07:00
Cameron Gutman 06635d9f9a Update common-c submodule 2018-07-21 20:30:53 -07:00
Cameron Gutman ad57a55d12 Add (untested) Steam Link video decoding/rendering 2018-07-21 20:29:05 -07:00
Cameron Gutman a97e4babf9 Fix build on GCC 4.x and lower 2018-07-21 19:34:13 -07:00
Cameron Gutman 1117c49867 Fix another brown-paper-bag bug in the build system 2018-07-21 19:26:24 -07:00
Cameron Gutman dc723a8da1 Fix strict aliasing violation 2018-07-21 19:16:08 -07:00
Cameron Gutman 27239ff320 Fix typo in ARM configuration 2018-07-21 19:15:16 -07:00
Cameron Gutman b073c90f0f Fix build on OpenSSL 1.0.1 2018-07-21 19:02:12 -07:00
Cameron Gutman 519626a6d5 Fix compilation with Qt 5.9 2018-07-21 18:47:41 -07:00
Cameron Gutman 71c11cacd9 Update opus project for ARM 2018-07-21 18:30:12 -07:00
Cameron Gutman b7b452875d Add a missing HAVE_FFMPEG guard 2018-07-21 17:32:00 -07:00
Cameron Gutman eb536c2273 Overhaul platform and decoder/renderer detection 2018-07-21 17:00:09 -07:00
R. Aidan Campbell c816a6198c fix macos build: for macos, Q_OS_UNIX is also defined 2018-07-21 14:31:37 -07:00
Cameron Gutman 399154f5f5 Implement VAAPI rendering for X11 2018-07-21 00:16:03 -07:00
Cameron Gutman 64a839c2f9 Create the window after starting streaming to avoid a mouse capture bug in SDL on Windows 2018-07-20 19:55:07 -07:00
Cameron Gutman 20288210be Fix VT video centering after transition from windowed to full screen 2018-07-20 19:37:54 -07:00
Cameron Gutman 7b235743cb Count the window chrome size in our placement decision and fix sizing after full-screen toggle 2018-07-20 19:18:55 -07:00
Cameron Gutman 4c507f1179 Move SDL subsystem init into appropriate components to fix gamepad detection issue 2018-07-20 18:15:46 -07:00
Cameron Gutman e516861366 Set window dimensions properly when toggling full-screen 2018-07-20 16:01:22 -07:00
R. Aidan Campbell 48c2a8c5b0 Merge branch 'master' of github.com:cgutman/moonlight-qt 2018-07-20 15:47:57 -07:00
R. Aidan Campbell b41e8c07d2 Switched settings page to two-pane layout 2018-07-20 15:47:50 -07:00
Cameron Gutman 10b5245919 Reset the decoder when D3D state is lost 2018-07-20 15:31:57 -07:00
R. Aidan Campbell 86874a2e1c minor wording change in settings 2018-07-20 14:36:39 -07:00
R. Aidan Campbell f951a01a68 changed audio configuration to a dropdown, allowing auto/stereo/surround 2018-07-20 14:35:47 -07:00
R. Aidan Campbell d12fed3e7f remove unused settings 2018-07-20 14:24:27 -07:00
R. Aidan Campbell 4566139c75 now with video codec selection 2018-07-20 14:22:22 -07:00
R. Aidan Campbell 38df63b962 now with video decoder selection 2018-07-20 14:14:38 -07:00
Cameron Gutman faaf9dfa07 Fix crashes when restarting streaming with DXVA2 renderer due to leaked surface references 2018-07-20 13:10:54 -07:00
Cameron Gutman 9c2befc386 Only require OpenSSL 1.1 on Apple platforms where SecureTransport requires keys from PEM_write_bio_PrivateKey_traditional() 2018-07-19 23:19:00 -07:00
Cameron Gutman e85ca2a6c9 Reduce VideoToolbox renderer video latency 2018-07-18 22:25:46 -07:00
Cameron Gutman e32aace443 Draw a black background behind the rendering 2018-07-18 22:07:43 -07:00
Cameron Gutman bd8e4a4bce Fix DXVA video centering 2018-07-18 21:48:46 -07:00
Cameron Gutman 5ee1358712 Implement a proper destructor for ComputerManager to prevent polling threads from living beyond QGuiApplication 2018-07-18 21:27:43 -07:00
Cameron Gutman 06501bd4b7 Fix video scaling on DXVA2 2018-07-18 19:10:14 -07:00
Cameron Gutman a4ad58d9ec Fix some Clang static analysis warnings 2018-07-18 18:39:33 -07:00
Cameron Gutman 76d99cd60e Raise combo keys for all special combos, not just quit 2018-07-18 00:14:12 -07:00
Cameron Gutman 1b85dcc829 Improve frame pacing on VideoToolbox renderer 2018-07-18 00:11:17 -07:00
Cameron Gutman c97e298b80 Use the queueFrame() helper 2018-07-17 20:05:59 -07:00
108 changed files with 2560 additions and 15343 deletions
+4
View File
@@ -1 +1,5 @@
*pro.user
**/.vs/
build/
+3 -8
View File
@@ -4,17 +4,12 @@
Moonlight also has mobile versions for [Android](https://github.com/moonlight-stream/moonlight-android) and [iOS](https://github.com/moonlight-stream/moonlight-ios).
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
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
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
## 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
+1 -1
View File
@@ -3,7 +3,7 @@
<plist version="1.0">
<dict>
<key>CFBundleExecutable</key>
<string>moonlight-qt</string>
<string>Moonlight</string>
<key>CFBundleGetInfoString</key>
<string>Created by Qt/QMake</string>
<key>CFBundleIconFile</key>
+86 -23
View File
@@ -1,7 +1,13 @@
QT += core quick network quickcontrols2
QT += core quick network quickcontrols2 svg
CONFIG += c++11
TARGET = moonlight-qt
unix:!macx {
TARGET = moonlight
} else {
# On macOS, this is the name displayed in the global menu bar
TARGET = Moonlight
}
TEMPLATE = app
# The following define makes your compiler emit warnings if you use
@@ -34,14 +40,26 @@ macx {
unix:!macx {
CONFIG += link_pkgconfig
PKGCONFIG += openssl sdl2 libavcodec libavdevice libavformat libavutil
PKGCONFIG += openssl sdl2
LIBS += -ldl
packagesExist(libavcodec) {
PKGCONFIG += libavcodec libavutil
CONFIG += ffmpeg
packagesExist(libva) {
CONFIG += libva
}
}
}
win32 {
LIBS += -llibssl -llibcrypto -lSDL2 -lavcodec -lavdevice -lavformat -lavutil
LIBS += -llibssl -llibcrypto -lSDL2 -lavcodec -lavutil
CONFIG += ffmpeg
}
macx {
LIBS += -lssl -lcrypto -lSDL2 -lavcodec.58 -lavdevice.58 -lavformat.58 -lavutil.56
LIBS += -lobjc -framework VideoToolbox -framework AVFoundation -framework CoreGraphics -framework CoreMedia -framework AppKit
LIBS += -lssl -lcrypto -lSDL2 -lavcodec.58 -lavutil.56
LIBS += -lobjc -framework VideoToolbox -framework AVFoundation -framework CoreVideo -framework CoreGraphics -framework CoreMedia -framework AppKit
CONFIG += ffmpeg
}
SOURCES += \
@@ -55,17 +73,8 @@ SOURCES += \
streaming/input.cpp \
streaming/session.cpp \
streaming/audio.cpp \
streaming/video/ffmpeg.cpp \
gui/computermodel.cpp \
gui/appmodel.cpp \
streaming/video/ffmpeg-renderers/sdl.cpp
win32 {
SOURCES += streaming/video/ffmpeg-renderers/dxva2.cpp
}
macx {
SOURCES += streaming/video/ffmpeg-renderers/vt.mm
}
gui/appmodel.cpp
HEADERS += \
utils.h \
@@ -79,14 +88,45 @@ HEADERS += \
streaming/session.hpp \
gui/computermodel.h \
gui/appmodel.h \
streaming/video/decoder.h \
streaming/video/ffmpeg.h \
streaming/video/ffmpeg-renderers/renderer.h
streaming/video/decoder.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
}
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
}
@@ -121,10 +161,31 @@ else:unix: LIBS += -L$$OUT_PWD/../qmdnsengine/ -lqmdnsengine
INCLUDEPATH += $$PWD/../qmdnsengine/qmdnsengine/src/include $$PWD/../qmdnsengine
DEPENDPATH += $$PWD/../qmdnsengine/qmdnsengine/src/include $$PWD/../qmdnsengine
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
unix:!macx: {
isEmpty(PREFIX) {
PREFIX = /usr/local
}
isEmpty(BINDIR) {
BINDIR = bin
}
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
@@ -132,3 +193,5 @@ macx {
APP_QML_FILES.path = Contents/Resources
QMAKE_BUNDLE_DATA += APP_QML_FILES
}
VERSION = 0.0.3
+55 -5
View File
@@ -140,12 +140,12 @@ NvComputer::NvComputer(QString address, QString serverInfo)
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;
}
@@ -184,7 +184,7 @@ bool NvComputer::wake()
// Send to all ports
for (quint16 port : WOL_PORTS) {
if (sock.writeDatagram(wolPayload, address, port)) {
qDebug() << "Send WoL packet to " << name << " via " << address.toString() << ":" << port;
qInfo().nospace().noquote() << "Send WoL packet to " << name << " via " << address.toString() << ":" << port;
success = true;
}
}
@@ -286,6 +286,56 @@ 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;
@@ -312,7 +362,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) {
qDebug() << "Discovered mDNS host: " << service.hostname();
qInfo() << "Discovered mDNS host:" << service.hostname();
MdnsPendingComputer* pendingComputer = new MdnsPendingComputer(&m_MdnsServer, &m_MdnsCache, service);
connect(pendingComputer, SIGNAL(resolvedv4(MdnsPendingComputer*,QHostAddress)),
@@ -331,7 +381,7 @@ void ComputerManager::startPolling()
void ComputerManager::handleMdnsServiceResolved(MdnsPendingComputer* computer,
const QHostAddress& address)
{
qDebug() << "Resolved " << computer->hostname() << " to " << address.toString();
qInfo() << "Resolved" << computer->hostname() << "to" << address.toString();
addNewHost(address.toString(), true);
+2
View File
@@ -249,6 +249,8 @@ class ComputerManager : public QObject
public:
explicit ComputerManager(QObject *parent = nullptr);
virtual ~ComputerManager();
Q_INVOKABLE void startPolling();
Q_INVOKABLE void stopPollingAsync();
+14 -9
View File
@@ -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);
qDebug() << "Wrote new identity credentials to settings";
qInfo() << "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()) {
qDebug() << "No existing credentials found";
qInfo() << "No existing credentials found";
createCredentials(settings);
}
else if (getSslCertificate().isNull()) {
@@ -157,10 +157,14 @@ 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);
@@ -187,14 +191,15 @@ IdentityManager::getUniqueId()
// Load the unique ID from settings
m_CachedUniqueId = settings.value(SER_UNIQUEID).toString();
if (!m_CachedUniqueId.isEmpty() && !m_CachedUniqueId.isNull()) {
qDebug() << "Loaded unique ID from settings: " << m_CachedUniqueId;
qInfo() << "Loaded unique ID from settings:" << m_CachedUniqueId;
}
else {
// Generate a new unique ID in base 16
m_CachedUniqueId = QString::number(
QRandomGenerator64::securelySeeded().generate64(), 16);
uint64_t uid;
RAND_bytes(reinterpret_cast<unsigned char*>(&uid), sizeof(uid));
m_CachedUniqueId = QString::number(uid, 16);
qDebug() << "Generated new unique ID: " << m_CachedUniqueId;
qInfo() << "Generated new unique ID:" << m_CachedUniqueId;
settings.setValue(SER_UNIQUEID, m_CachedUniqueId);
}
+22 -7
View File
@@ -123,6 +123,11 @@ 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",
@@ -132,7 +137,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(qFromBigEndian(*(int*)streamConfig->remoteInputAesIv))+
"&rikeyid="+QString::number(riKeyId)+
(streamConfig->enableHdr ?
"&hdrMode=1&clientHdrCapVersion=0&clientHdrCapSupportedFlagsInUint32=0&clientHdrCapMetaDataId=NV_STATIC_METADATA_TYPE_1&clientHdrCapDisplayData=0x0x0x0x0x0x0x0x0x0x0" :
"")+
@@ -149,11 +154,16 @@ 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(qFromBigEndian(*(int*)streamConfig->remoteInputAesIv))+
"&rikeyid="+QString::number(riKeyId)+
"&surroundAudioInfo="+getSurroundAudioInfoString(streamConfig->audioConfiguration),
false);
@@ -265,7 +275,10 @@ NvHTTP::verifyResponseStatus(QString xml)
else
{
QString statusMessage = xmlReader.attributes().value("status_message").toString();
qDebug() << "Request failed: " << statusCode << " " << statusMessage;
if (statusCode != 401) {
// 401 is expected for unpaired PCs when we fetch serverinfo over HTTPS
qWarning() << "Request failed:" << statusCode << statusMessage;
}
throw GfeHttpResponseException(statusCode, statusMessage);
}
}
@@ -330,7 +343,9 @@ NvHTTP::openConnectionToString(QUrl baseUrl,
QNetworkReply* reply = openConnection(baseUrl, command, arguments, enableTimeout);
QString ret;
ret = QTextStream(reply).readAll();
QTextStream stream(reply);
stream.setCodec("UTF-8");
ret = stream.readAll();
delete reply;
return ret;
@@ -366,13 +381,13 @@ NvHTTP::openConnection(QUrl baseUrl,
{
QTimer::singleShot(REQUEST_TIMEOUT_MS, &loop, SLOT(quit()));
}
qDebug() << "Executing request: " << url.toString();
qInfo() << "Executing request:" << url.toString();
loop.exec(QEventLoop::ExcludeUserInputEvents);
// Abort the request if it timed out
if (!reply->isFinished())
{
qDebug() << "Aborting timed out request for " << url.toString();
qWarning() << "Aborting timed out request for" << url.toString();
reply->abort();
}
@@ -383,7 +398,7 @@ NvHTTP::openConnection(QUrl baseUrl,
// Handle error
if (reply->error() != QNetworkReply::NoError)
{
qDebug() << command << " request failed with error " << reply->error();
qWarning() << command << " request failed with error " << reply->error();
GfeHttpResponseException exception(reply->error(), reply->errorString());
delete reply;
throw exception;
+26 -24
View File
@@ -1,8 +1,6 @@
#include "nvpairingmanager.h"
#include "utils.h"
#include <QRandomGenerator>
#include <openssl/bio.h>
#include <openssl/aes.h>
#include <openssl/rand.h>
@@ -21,7 +19,7 @@ NvPairingManager::NvPairingManager(QString address) :
BIO_free_all(bio);
if (m_Cert == nullptr)
{
throw new std::runtime_error("Unable to load certificate");
throw std::runtime_error("Unable to load certificate");
}
QByteArray pk = IdentityManager::get()->getPrivateKey();
@@ -32,7 +30,7 @@ NvPairingManager::NvPairingManager(QString address) :
BIO_free_all(bio);
if (m_PrivateKey == nullptr)
{
throw new std::runtime_error("Unable to load private key");
throw std::runtime_error("Unable to load private key");
}
}
@@ -89,13 +87,15 @@ NvPairingManager::getSignatureFromPemCert(QByteArray certificate)
X509* cert = PEM_read_bio_X509(bio, nullptr, nullptr, nullptr);
BIO_free_all(bio);
#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
ASN1_BIT_STRING *asnSignature;
#else
const ASN1_BIT_STRING *asnSignature;
#endif
#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);
#else
const ASN1_BIT_STRING *asnSignature;
X509_get0_signature(&asnSignature, NULL, cert);
#endif
QByteArray signature(reinterpret_cast<char*>(asnSignature->data), asnSignature->length);
@@ -164,7 +164,7 @@ NvPairingManager::PairState
NvPairingManager::pair(QString appVersion, QString pin)
{
int serverMajorVersion = NvHTTP::parseQuad(appVersion).at(0);
qDebug() << "Pairing with server generation: " << serverMajorVersion;
qInfo() << "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")
{
qDebug() << "Failed pairing at stage #1";
qCritical() << "Failed pairing at stage #1";
return PairState::FAILED;
}
QByteArray serverCert = NvHTTP::getXmlStringFromHex(getCert, "plaincert");
if (serverCert == nullptr)
{
qDebug() << "Server likely already pairing";
qCritical() << "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")
{
qDebug() << "Failed pairing at stage #2";
qCritical() << "Failed pairing at stage #2";
m_Http.openConnectionToString(m_Http.m_BaseUrlHttp, "unpair", nullptr, true);
return PairState::FAILED;
}
@@ -228,13 +228,15 @@ NvPairingManager::pair(QString appVersion, QString pin)
QByteArray challengeResponse;
QByteArray serverResponse(challengeResponseData.data(), hashLength);
#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
#if (OPENSSL_VERSION_NUMBER < 0x10002000L)
ASN1_BIT_STRING *asnSignature = m_Cert->signature;
#elif (OPENSSL_VERSION_NUMBER < 0x10100000L)
ASN1_BIT_STRING *asnSignature;
#else
const ASN1_BIT_STRING *asnSignature;
#endif
X509_get0_signature(&asnSignature, NULL, m_Cert);
#else
const ASN1_BIT_STRING *asnSignature;
X509_get0_signature(&asnSignature, NULL, m_Cert);
#endif
challengeResponse.append(challengeResponseData.data() + hashLength, 16);
challengeResponse.append(reinterpret_cast<char*>(asnSignature->data), asnSignature->length);
@@ -249,7 +251,7 @@ NvPairingManager::pair(QString appVersion, QString pin)
NvHTTP::verifyResponseStatus(respXml);
if (NvHTTP::getXmlString(respXml, "paired") != "1")
{
qDebug() << "Failed pairing at stage #3";
qCritical() << "Failed pairing at stage #3";
m_Http.openConnectionToString(m_Http.m_BaseUrlHttp, "unpair", nullptr, true);
return PairState::FAILED;
}
@@ -262,7 +264,7 @@ NvPairingManager::pair(QString appVersion, QString pin)
serverSignature,
serverCert))
{
qDebug() << "MITM detected";
qCritical() << "MITM detected";
m_Http.openConnectionToString(m_Http.m_BaseUrlHttp, "unpair", nullptr, true);
return PairState::FAILED;
}
@@ -273,7 +275,7 @@ NvPairingManager::pair(QString appVersion, QString pin)
expectedResponseData.append(serverSecret);
if (QCryptographicHash::hash(expectedResponseData, hashAlgo) != serverResponse)
{
qDebug() << "Incorrect PIN";
qCritical() << "Incorrect PIN";
m_Http.openConnectionToString(m_Http.m_BaseUrlHttp, "unpair", nullptr, true);
return PairState::PIN_WRONG;
}
@@ -290,7 +292,7 @@ NvPairingManager::pair(QString appVersion, QString pin)
NvHTTP::verifyResponseStatus(secretRespXml);
if (NvHTTP::getXmlString(secretRespXml, "paired") != "1")
{
qDebug() << "Failed pairing at stage #4";
qCritical() << "Failed pairing at stage #4";
m_Http.openConnectionToString(m_Http.m_BaseUrlHttp, "unpair", nullptr, true);
return PairState::FAILED;
}
@@ -302,7 +304,7 @@ NvPairingManager::pair(QString appVersion, QString pin)
NvHTTP::verifyResponseStatus(pairChallengeXml);
if (NvHTTP::getXmlString(pairChallengeXml, "paired") != "1")
{
qDebug() << "Failed pairing at stage #5";
qCritical() << "Failed pairing at stage #5";
m_Http.openConnectionToString(m_Http.m_BaseUrlHttp, "unpair", nullptr, true);
return PairState::FAILED;
}
@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8"?>
<component type="desktop">
<id>com.moonlight_stream.Moonlight.desktop</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 or other applications from a PC with an NVIDIA GeForce GTX 600-series or higher GPU and GeForce Experience installed.</p>
<p>GameStream utilizes the NVENC hardware encoder present on NVIDIA GPUs for low-latency streaming at up 4K 60 FPS. Moonlight can utilize VAAPI hardware acceleration for high-performance H.264 and HEVC video decoding with low CPU usage.</p>
</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>
<categories>
<category>Game</category>
<category>Qt</category>
</categories>
<developer_name>Moonlight Game Streaming Team</developer_name>
<update_contact>cameron@moonlight-stream.com</update_contact>
<launchable type="desktop-id">com.moonlight_stream.Moonlight.desktop</launchable>
<provides>
<binary>moonlight</binary>
</provides>
<content_rating type="oars-1.1">
<content_attribute id="violence-cartoon">none</content_attribute>
<content_attribute id="violence-fantasy">none</content_attribute>
<content_attribute id="violence-realistic">none</content_attribute>
<content_attribute id="violence-bloodshed">none</content_attribute>
<content_attribute id="violence-sexual">none</content_attribute>
<content_attribute id="violence-desecration">none</content_attribute>
<content_attribute id="violence-slavery">none</content_attribute>
<content_attribute id="violence-worship">none</content_attribute>
<content_attribute id="drugs-alcohol">none</content_attribute>
<content_attribute id="drugs-narcotics">none</content_attribute>
<content_attribute id="drugs-tobacco">none</content_attribute>
<content_attribute id="sex-nudity">none</content_attribute>
<content_attribute id="sex-themes">none</content_attribute>
<content_attribute id="sex-homosexuality">none</content_attribute>
<content_attribute id="sex-prostitution">none</content_attribute>
<content_attribute id="sex-adultery">none</content_attribute>
<content_attribute id="sex-appearance">none</content_attribute>
<content_attribute id="language-profanity">none</content_attribute>
<content_attribute id="language-humor">none</content_attribute>
<content_attribute id="language-discrimination">none</content_attribute>
<content_attribute id="social-chat">none</content_attribute>
<content_attribute id="social-info">moderate</content_attribute>
<content_attribute id="social-audio">none</content_attribute>
<content_attribute id="social-location">none</content_attribute>
<content_attribute id="social-contacts">none</content_attribute>
<content_attribute id="money-purchasing">none</content_attribute>
<content_attribute id="money-gambling">none</content_attribute>
</content_rating>
</component>
@@ -0,0 +1,9 @@
[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;
+4 -3
View File
@@ -12,7 +12,7 @@ GridView {
id: appGrid
anchors.fill: parent
anchors.leftMargin: (parent.width % (cellWidth + anchors.rightMargin)) / 2
anchors.topMargin: 5
anchors.topMargin: 20
anchors.rightMargin: 5
anchors.bottomMargin: 5
cellWidth: 225; cellHeight: 350;
@@ -72,11 +72,12 @@ GridView {
color: "white"
width: parent.width
height: 100
height: 125
anchors.top: appIcon.bottom
font.pointSize: 26
font.pointSize: 22
horizontalAlignment: Text.AlignHCenter
wrapMode: Text.Wrap
elide: Text.ElideRight
}
MouseArea {
+23 -1
View File
@@ -6,6 +6,7 @@ import QtQuick.Layouts 1.3
import ComputerModel 1.0
import ComputerManager 1.0
import StreamingPreferences 1.0
GridView {
property ComputerModel computerModel : createModel()
@@ -13,7 +14,7 @@ GridView {
id: pcGrid
anchors.fill: parent
anchors.leftMargin: (parent.width % (cellWidth + anchors.rightMargin)) / 2
anchors.topMargin: 5
anchors.topMargin: 20
anchors.rightMargin: 5
anchors.bottomMargin: 5
cellWidth: 350; cellHeight: 350;
@@ -25,9 +26,17 @@ 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: {
@@ -184,6 +193,19 @@ 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
+258 -118
View File
@@ -16,14 +16,13 @@ ScrollView {
}
Column {
x: 10
y: 10
width: settingsPage.width
height: 400
padding: 10
id: settingsColumn1
width: settingsPage.width / 2 - padding
GroupBox {
id: basicSettingsGroupBox
width: (parent.width - 20)
width: (parent.width - 2 * parent.padding)
padding: 12
title: "<font color=\"skyblue\">Basic Settings</font>"
font.pointSize: 12
@@ -35,7 +34,7 @@ ScrollView {
Label {
width: parent.width
id: resFPStitle
text: qsTr("Resolution and FPS target")
text: qsTr("Resolution and FPS")
font.pointSize: 12
wrapMode: Text.Wrap
color: "white"
@@ -44,84 +43,113 @@ ScrollView {
Label {
width: parent.width
id: resFPSdesc
text: qsTr("Setting values too high for your device may cause lag or crashes")
text: qsTr("Setting values too high for your PC may cause lag, stuttering, or errors")
font.pointSize: 9
wrapMode: Text.Wrap
color: "white"
}
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
}
Row {
spacing: 5
ComboBox {
// ignore setting the index at first, and actually set it when the component is loaded
Component.onCompleted: {
// 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);
if (saved_width === el_width && saved_height === el_height) {
currentIndex = i
}
}
}
id: resolutionComboBox
font.pointSize: 9
textRole: "text"
model: ListModel {
id: resolutionListModel
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
}
}
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"
}
ListElement {
text: "720p 60 FPS"
video_width: "1280"
video_height: "720"
video_fps: "60"
}
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)
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();
prefs.bitrateKbps = prefs.getDefaultBitrate(prefs.width, prefs.height, prefs.fps);
slider.value = prefs.bitrateKbps
// 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);
if (el_fps === saved_fps) {
currentIndex = i
}
}
}
id: fpsComboBox
font.pointSize: 9
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
}
// ::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
}
}
}
@@ -151,7 +179,7 @@ ScrollView {
stepSize: 500
from : 500
to: 100000
to: 150000
snapMode: "SnapOnRelease"
width: Math.min(bitrateDesc.implicitWidth, parent.width)
@@ -177,7 +205,7 @@ ScrollView {
GroupBox {
id: audioSettingsGroupBox
width: (parent.width - 20)
width: (parent.width - 2 * parent.padding)
padding: 12
title: "<font color=\"skyblue\">Audio Settings</font>"
font.pointSize: 12
@@ -186,24 +214,66 @@ ScrollView {
anchors.fill: parent
spacing: 5
CheckBox {
id: surroundSoundCheck
text: "<font color=\"white\">Enable 5.1 surround sound</font>"
font.pointSize: 12
Label {
width: parent.width
id: resAudioTitle
text: qsTr("Audio configuration")
font.pointSize: 12
wrapMode: Text.Wrap
color: "white"
}
// the backend actually supports auto/stereo/5.1. We'll expose stereo/5.1
checked: prefs.audioConfig === StreamingPreferences.AC_FORCE_SURROUND
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
}
}
}
onCheckedChanged: {
prefs.audioConfig = checked ? StreamingPreferences.AC_FORCE_SURROUND : StreamingPreferences.AC_FORCE_STEREO
id: audioComboBox
width: Math.min(bitrateDesc.implicitWidth, parent.width)
font.pointSize: 9
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
}
}
}
}
}
Column {
padding: 10
anchors.left: settingsColumn1.right
id: settingsColumn2
width: settingsPage.width / 2 - padding
GroupBox {
id: gamepadSettingsGroupBox
width: (parent.width - 20)
width: (parent.width - parent.padding)
padding: 12
title: "<font color=\"skyblue\">Gamepad Settings</font>"
font.pointSize: 12
@@ -221,38 +291,12 @@ 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 - 20)
width: (parent.width - parent.padding)
padding: 12
title: "<font color=\"skyblue\">Host Settings</font>"
font.pointSize: 12
@@ -285,7 +329,7 @@ ScrollView {
GroupBox {
id: advancedSettingsGroupBox
width: (parent.width - 20)
width: (parent.width - parent.padding)
padding: 12
title: "<font color=\"skyblue\">Advanced Settings</font>"
font.pointSize: 12
@@ -294,11 +338,107 @@ ScrollView {
anchors.fill: parent
spacing: 5
CheckBox {
id: neverDropFramesCheck
text: "<font color=\"white\">Never drop frames</font>"
font.pointSize: 12
Label {
width: parent.width
id: resVDSTitle
text: qsTr("Video decoder")
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_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)
font.pointSize: 9
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)
font.pointSize: 9
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
}
}
}
}
}
+10 -5
View File
@@ -123,10 +123,15 @@ void AppModel::handleBoxArtLoaded(NvComputer* computer, NvApp app, QUrl /* image
Q_ASSERT(computer == m_Computer);
int index = m_Apps.indexOf(app);
Q_ASSERT(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);
// 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;
}
}
+3
View File
@@ -80,6 +80,9 @@ 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")
+129 -5
View File
@@ -2,6 +2,8 @@
#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
@@ -14,8 +16,134 @@
#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
@@ -53,12 +181,8 @@ 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(SDL_INIT_VIDEO |
SDL_INIT_AUDIO |
SDL_INIT_GAMECONTROLLER) != 0) {
if (SDL_Init(0) != 0) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"SDL_Init() failed: %s",
SDL_GetError());
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 345 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

+68 -22
View File
@@ -1,23 +1,69 @@
<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"/>
<?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" />
</g>
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

+44 -14
View File
@@ -1,4 +1,5 @@
#include "streamingpreferences.h"
#include "streaming/session.hpp"
#include <QSettings>
@@ -57,24 +58,53 @@ 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 90 FPS, since I can't seem to get
// much more out of GFE even with the game rendering at > 300 FPS.
maxFrameRate = qMax(maxFrameRate, qMin(90, mode.refresh_rate));
}
}
SDL_QuitSubSystem(SDL_INIT_VIDEO);
return maxFrameRate;
}
int StreamingPreferences::getDefaultBitrate(int width, int height, int fps)
{
if (width * height * fps <= 1280 * 720 * 30) {
return 5000;
if (width * height <= 1280 * 720) {
return static_cast<int>(5000 * (fps / 30.0));
}
else if (width * height * fps <= 1280 * 720 * 60) {
return 10000;
else if (width * height <= 1920 * 1080) {
return static_cast<int>(10000 * (fps / 30.0));
}
else if (width * height * fps <= 1920 * 1080 * 30) {
return 10000;
else if (width * height <= 2560 * 1440) {
return static_cast<int>(20000 * (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;
else /* if (width * height <= 3840 * 2160) */ {
return static_cast<int>(40000 * (fps / 30.0));
}
}
+4
View File
@@ -14,6 +14,10 @@ public:
Q_INVOKABLE void save();
Q_INVOKABLE static bool hasAnyHardwareAcceleration();
Q_INVOKABLE static int getMaximumStreamingFrameRate();
void reload();
enum AudioConfig
+31 -5
View File
@@ -23,6 +23,14 @@ 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;
@@ -38,7 +46,8 @@ int Session::sdlDetermineAudioConfiguration()
"Failed to open audio device");
// We'll probably have issues during audio stream init, but we'll
// try anyway
return AUDIO_CONFIGURATION_STEREO;
ret = AUDIO_CONFIGURATION_STEREO;
goto Exit;
}
SDL_CloseAudioDevice(dev);
@@ -50,11 +59,15 @@ 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.
return AUDIO_CONFIGURATION_51_SURROUND;
ret = AUDIO_CONFIGURATION_51_SURROUND;
}
else {
return AUDIO_CONFIGURATION_STEREO;
ret = AUDIO_CONFIGURATION_STEREO;
}
Exit:
SDL_QuitSubSystem(SDL_INIT_AUDIO);
return ret;
}
int Session::sdlAudioInit(int /* audioConfiguration */,
@@ -64,6 +77,14 @@ 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;
@@ -80,6 +101,7 @@ 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;
}
@@ -95,6 +117,7 @@ int Session::sdlAudioInit(int /* audioConfiguration */,
error);
SDL_CloseAudioDevice(s_AudioDevice);
s_AudioDevice = 0;
SDL_QuitSubSystem(SDL_INIT_AUDIO);
return -2;
}
@@ -104,7 +127,7 @@ int Session::sdlAudioInit(int /* audioConfiguration */,
// pending data count. Get a baseline so we
// can exclude that data.
s_BaselinePendingData = 0;
#ifdef _WIN32
#ifdef Q_OS_WIN32
for (int i = 0; i < 100; i++) {
s_BaselinePendingData = qMax(s_BaselinePendingData, SDL_GetQueuedAudioSize(s_AudioDevice));
SDL_Delay(10);
@@ -140,7 +163,10 @@ void Session::sdlAudioCleanup()
s_AudioDevice = 0;
opus_multistream_decoder_destroy(s_OpusDecoder);
s_OpusDecoder = NULL;
s_OpusDecoder = nullptr;
SDL_QuitSubSystem(SDL_INIT_AUDIO);
SDL_assert(!SDL_WasInit(SDL_INIT_AUDIO));
}
void Session::sdlAudioDecodeAndPlaySample(char* sampleData, int sampleLength)
+103 -92
View File
@@ -9,7 +9,7 @@
#ifndef VK_F1
#define VK_F1 0x70
#define VK_F13 0x7C
#define VK_NUMPAD1 0x61
#define VK_NUMPAD0 0x60
#endif
const int SdlInputHandler::k_ButtonMap[] = {
@@ -23,6 +23,15 @@ const int SdlInputHandler::k_ButtonMap[] = {
SdlInputHandler::SdlInputHandler(bool multiController)
: m_MultiController(multiController)
{
// 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;
@@ -38,6 +47,9 @@ 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)
@@ -51,26 +63,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");
// 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);
// Uncapture the mouse to avoid processing any
// further keyboard input
SDL_SetRelativeMouseMode(SDL_FALSE);
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();
@@ -88,12 +100,7 @@ void SdlInputHandler::handleKeyEvent(SDL_KeyboardEvent* event)
else if (event->keysym.sym == SDLK_x) {
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
"Detected full-screen toggle combo");
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);
}
Session::s_ActiveSession->toggleFullscreen();
return;
}
}
@@ -115,195 +122,199 @@ void SdlInputHandler::handleKeyEvent(SDL_KeyboardEvent* event)
modifiers |= MODIFIER_SHIFT;
}
// Set keycode
if (event->keysym.sym >= SDLK_0 && event->keysym.sym <= SDLK_9) {
keyCode = (event->keysym.sym - SDLK_0) + VK_0;
// 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;
}
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_A && event->keysym.scancode <= SDL_SCANCODE_Z) {
keyCode = (event->keysym.scancode - SDL_SCANCODE_A) + VK_A;
}
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_F1 && event->keysym.scancode <= SDL_SCANCODE_F12) {
keyCode = (event->keysym.scancode - SDL_SCANCODE_F1) + VK_F1;
}
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_F13 && event->keysym.scancode <= SDL_SCANCODE_F24) {
keyCode = (event->keysym.scancode - SDL_SCANCODE_F13) + VK_F13;
}
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 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 {
switch (event->keysym.sym) {
case SDLK_BACKSPACE:
switch (event->keysym.scancode) {
case SDL_SCANCODE_BACKSPACE:
keyCode = 0x08;
break;
case SDLK_TAB:
case SDL_SCANCODE_TAB:
keyCode = 0x09;
break;
case SDLK_CLEAR:
case SDL_SCANCODE_CLEAR:
keyCode = 0x0C;
break;
case SDLK_RETURN:
case SDL_SCANCODE_RETURN:
keyCode = 0x0D;
break;
case SDLK_PAUSE:
case SDL_SCANCODE_PAUSE:
keyCode = 0x13;
break;
case SDLK_CAPSLOCK:
case SDL_SCANCODE_CAPSLOCK:
keyCode = 0x14;
break;
case SDLK_ESCAPE:
case SDL_SCANCODE_ESCAPE:
keyCode = 0x1B;
break;
case SDLK_SPACE:
case SDL_SCANCODE_SPACE:
keyCode = 0x20;
break;
case SDLK_PAGEUP:
case SDL_SCANCODE_PAGEUP:
keyCode = 0x21;
break;
case SDLK_PAGEDOWN:
case SDL_SCANCODE_PAGEDOWN:
keyCode = 0x22;
break;
case SDLK_END:
case SDL_SCANCODE_END:
keyCode = 0x23;
break;
case SDLK_HOME:
case SDL_SCANCODE_HOME:
keyCode = 0x24;
break;
case SDLK_LEFT:
case SDL_SCANCODE_LEFT:
keyCode = 0x25;
break;
case SDLK_UP:
case SDL_SCANCODE_UP:
keyCode = 0x26;
break;
case SDLK_RIGHT:
case SDL_SCANCODE_RIGHT:
keyCode = 0x27;
break;
case SDLK_DOWN:
case SDL_SCANCODE_DOWN:
keyCode = 0x28;
break;
case SDLK_SELECT:
case SDL_SCANCODE_SELECT:
keyCode = 0x29;
break;
case SDLK_EXECUTE:
case SDL_SCANCODE_EXECUTE:
keyCode = 0x2B;
break;
case SDLK_PRINTSCREEN:
case SDL_SCANCODE_PRINTSCREEN:
keyCode = 0x2C;
break;
case SDLK_INSERT:
case SDL_SCANCODE_INSERT:
keyCode = 0x2D;
break;
case SDLK_DELETE:
case SDL_SCANCODE_DELETE:
keyCode = 0x2E;
break;
case SDLK_HELP:
case SDL_SCANCODE_HELP:
keyCode = 0x2F;
break;
case SDLK_KP_0:
// See comment above about why we only handle KP_0 here
keyCode = 0x60;
case SDL_SCANCODE_KP_0:
// See comment above about why we only handle SDL_SCANCODE_KP_0 here
keyCode = VK_NUMPAD0;
break;
case SDLK_KP_MULTIPLY:
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:
keyCode = 0x6A;
break;
case SDLK_KP_PLUS:
case SDL_SCANCODE_KP_PLUS:
keyCode = 0x6B;
break;
case SDLK_KP_COMMA:
case SDL_SCANCODE_KP_COMMA:
keyCode = 0x6C;
break;
case SDLK_KP_MINUS:
case SDL_SCANCODE_KP_MINUS:
keyCode = 0x6D;
break;
case SDLK_KP_DECIMAL:
case SDL_SCANCODE_KP_DECIMAL:
keyCode = 0x6E;
break;
case SDLK_KP_DIVIDE:
case SDL_SCANCODE_KP_DIVIDE:
keyCode = 0x6F;
break;
case SDLK_NUMLOCKCLEAR:
case SDL_SCANCODE_NUMLOCKCLEAR:
keyCode = 0x90;
break;
case SDLK_SCROLLLOCK:
case SDL_SCANCODE_SCROLLLOCK:
keyCode = 0x91;
break;
case SDLK_LSHIFT:
case SDL_SCANCODE_LSHIFT:
keyCode = 0xA0;
break;
case SDLK_RSHIFT:
case SDL_SCANCODE_RSHIFT:
keyCode = 0xA1;
break;
case SDLK_LCTRL:
case SDL_SCANCODE_LCTRL:
keyCode = 0xA2;
break;
case SDLK_RCTRL:
case SDL_SCANCODE_RCTRL:
keyCode = 0xA3;
break;
case SDLK_LALT:
case SDL_SCANCODE_LALT:
keyCode = 0xA4;
break;
case SDLK_RALT:
case SDL_SCANCODE_RALT:
keyCode = 0xA5;
break;
case SDLK_AC_BACK:
case SDL_SCANCODE_AC_BACK:
keyCode = 0xA6;
break;
case SDLK_AC_FORWARD:
case SDL_SCANCODE_AC_FORWARD:
keyCode = 0xA7;
break;
case SDLK_AC_REFRESH:
case SDL_SCANCODE_AC_REFRESH:
keyCode = 0xA8;
break;
case SDLK_AC_STOP:
case SDL_SCANCODE_AC_STOP:
keyCode = 0xA9;
break;
case SDLK_AC_SEARCH:
case SDL_SCANCODE_AC_SEARCH:
keyCode = 0xAA;
break;
case SDLK_AC_BOOKMARKS:
case SDL_SCANCODE_AC_BOOKMARKS:
keyCode = 0xAB;
break;
case SDLK_AC_HOME:
case SDL_SCANCODE_AC_HOME:
keyCode = 0xAC;
break;
case SDLK_SEMICOLON:
case SDL_SCANCODE_SEMICOLON:
keyCode = 0xBA;
break;
case SDLK_PLUS:
keyCode = 0xBB;
break;
case SDLK_COMMA:
case SDL_SCANCODE_COMMA:
keyCode = 0xBC;
break;
case SDLK_MINUS:
case SDL_SCANCODE_MINUS:
keyCode = 0xBD;
break;
case SDLK_PERIOD:
case SDL_SCANCODE_PERIOD:
keyCode = 0xBE;
break;
case SDLK_SLASH:
case SDL_SCANCODE_SLASH:
keyCode = 0xBF;
break;
case SDLK_BACKQUOTE:
case SDL_SCANCODE_GRAVE:
keyCode = 0xC0;
break;
case SDLK_LEFTBRACKET:
case SDL_SCANCODE_LEFTBRACKET:
keyCode = 0xDB;
break;
case SDLK_BACKSLASH:
case SDL_SCANCODE_BACKSLASH:
keyCode = 0xDC;
break;
case SDLK_RIGHTBRACKET:
case SDL_SCANCODE_RIGHTBRACKET:
keyCode = 0xDD;
break;
case SDLK_QUOTE:
case SDL_SCANCODE_APOSTROPHE:
keyCode = 0xDE;
break;
default:
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
"Unhandled button event: %d",
event->keysym.sym);
event->keysym.scancode);
return;
}
}
+298 -91
View File
@@ -5,12 +5,38 @@
#include <SDL.h>
#include "utils.h"
#ifdef HAVE_FFMPEG
#include "video/ffmpeg.h"
#endif
#ifdef HAVE_SLVIDEO
#include "video/sl.h"
#endif
#ifdef Q_OS_WIN32
// Using full-screen desktop allows us to avoid needing to enable V-sync
// and it also avoids some strange flickering issues on my Win7 test machine
// with Intel HD 5500 graphics.
#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,
@@ -82,6 +108,22 @@ 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();
if (chosenDecoder->initialize(vds, window, videoFormat, width, height, frameRate)) {
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
"SLVideo video decoder chosen");
return true;
}
else {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Unable to load SLVideo 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,
@@ -94,6 +136,7 @@ bool Session::chooseDecoder(StreamingPreferences::VideoDecoderSelection vds,
delete chosenDecoder;
chosenDecoder = nullptr;
}
#endif
// If we reach this, we didn't initialize any decoders successfully
return false;
@@ -101,12 +144,14 @@ bool Session::chooseDecoder(StreamingPreferences::VideoDecoderSelection vds,
int Session::drSetup(int videoFormat, int width, int height, int frameRate, void *, int)
{
if (!chooseDecoder(s_ActiveSession->m_Preferences.videoDecoderSelection,
s_ActiveSession->m_Window,
videoFormat, width, height, frameRate,
s_ActiveSession->m_VideoDecoder)) {
return -1;
}
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).
return 0;
}
@@ -117,7 +162,16 @@ 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);
@@ -135,23 +189,35 @@ 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;
}
@@ -160,7 +226,8 @@ Session::Session(NvComputer* computer, NvApp& app)
m_App(app),
m_Window(nullptr),
m_VideoDecoder(nullptr),
m_DecoderLock(0)
m_DecoderLock(0),
m_NeedsIdr(false)
{
LiInitializeVideoCallbacks(&m_VideoCallbacks);
m_VideoCallbacks.setup = drSetup;
@@ -178,11 +245,12 @@ Session::Session(NvComputer* computer, NvApp& app)
m_StreamConfig.fps = m_Preferences.fps;
m_StreamConfig.bitrate = m_Preferences.bitrateKbps;
m_StreamConfig.hevcBitratePercentageMultiplier = 75;
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());
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);
switch (m_Preferences.audioConfig)
{
case StreamingPreferences::AC_AUTO:
@@ -242,23 +310,30 @@ bool Session::validateLaunch()
QStringList warningList;
if (m_StreamConfig.supportsHevc) {
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.");
}
}
else if (!isHardwareDecodeAvailable(m_Preferences.videoDecoderSelection,
VIDEO_FORMAT_H265,
m_StreamConfig.width,
m_StreamConfig.height,
m_StreamConfig.fps)) {
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)) {
// 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;
if (hevcForced) {
emit displayLaunchWarning("This PC's GPU doesn't support HEVC decoding.");
}
}
if (hevcForced) {
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.");
}
}
}
@@ -280,7 +355,7 @@ bool Session::validateLaunch()
m_StreamConfig.width,
m_StreamConfig.height,
m_StreamConfig.fps)) {
emit displayLaunchWarning("Your client PC GPU doesn't support HEVC Main10 decoding for HDR streaming.");
emit displayLaunchWarning("This PC's GPU doesn't support HEVC Main10 decoding for HDR streaming.");
}
else {
// TODO: Also validate display capabilites
@@ -320,9 +395,6 @@ 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;
@@ -330,6 +402,103 @@ class DeferredSessionCleanupTask : public QRunnable
}
};
void Session::getWindowDimensions(bool fullScreen,
int& x, int& y,
int& width, int& height)
{
int displayIndex = 0;
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, &currentMode) == 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;
}
}
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);
}
getWindowDimensions(fullScreen, x, y, width, height);
SDL_SetWindowPosition(m_Window, x, y);
SDL_SetWindowSize(m_Window, width, height);
if (fullScreen) {
SDL_SetWindowFullscreen(m_Window, SDL_OS_FULLSCREEN_FLAG);
}
}
void Session::exec()
{
// Check for validation errors/warnings and emit
@@ -373,64 +542,12 @@ void Session::exec()
return;
}
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, &current) == 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_assert(!SDL_WasInit(SDL_INIT_VIDEO));
if (SDL_InitSubSystem(SDL_INIT_VIDEO) != 0) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"SDL_CreateWindow() failed: %s",
"SDL_InitSubSystem(SDL_INIT_VIDEO) failed: %s",
SDL_GetError());
emit displayLaunchError(QString::fromLocal8Bit(SDL_GetError()));
s_ActiveSessionSemaphore.release();
return;
}
@@ -458,6 +575,7 @@ void Session::exec()
// We already displayed an error dialog in the stage failure
// listener.
s_ActiveSessionSemaphore.release();
SDL_QuitSubSystem(SDL_INIT_VIDEO);
return;
}
@@ -465,11 +583,61 @@ void Session::exec()
emit connectionStarted();
QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
// Show the streaming window
SDL_ShowWindow(m_Window);
int x, y, width, height;
getWindowDimensions(m_Preferences.fullScreen,
x, y, width, height);
// Capture the mouse
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);
}
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.
SDL_SetRelativeMouseMode(SDL_TRUE);
#endif
// Disable the screen saver
SDL_DisableScreenSaver();
@@ -510,6 +678,41 @@ 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);
@@ -547,9 +750,6 @@ 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);
@@ -557,6 +757,13 @@ 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.
+15 -3
View File
@@ -21,6 +21,10 @@ 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,9 +43,11 @@ private:
int sdlDetermineAudioConfiguration();
static
bool isHardwareDecodeAvailable(StreamingPreferences::VideoDecoderSelection vds,
int videoFormat, int width, int height, int frameRate);
void getWindowDimensions(bool fullScreen,
int& x, int& y,
int& width, int& height);
void toggleFullscreen();
static
bool chooseDecoder(StreamingPreferences::VideoDecoderSelection vds,
@@ -94,6 +100,12 @@ 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;
+165 -47
View File
@@ -1,4 +1,4 @@
#include <Initguid.h>
#include <initguid.h>
#include "dxva2.h"
#include <Limelight.h>
@@ -8,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_Processor(nullptr),
m_FrameIndex(0)
{
RtlZeroMemory(m_DecSurfaces, sizeof(m_DecSurfaces));
RtlZeroMemory(&m_DXVAContext, sizeof(m_DXVAContext));
@@ -101,8 +101,8 @@ 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_Width;
frame->height = me->m_Height;
frame->width = me->m_VideoWidth;
frame->height = me->m_VideoHeight;
return 0;
}
@@ -218,8 +218,8 @@ bool DXVA2Renderer::initializeDecoder()
alignment = 16;
}
hr = m_DecService->CreateSurface(FFALIGN(m_Width, alignment),
FFALIGN(m_Height, alignment),
hr = m_DecService->CreateSurface(FFALIGN(m_VideoWidth, alignment),
FFALIGN(m_VideoHeight, alignment),
ARRAYSIZE(m_DecSurfaces) - 1,
m_Desc.Format,
D3DPOOL_DEFAULT,
@@ -262,6 +262,9 @@ 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));
@@ -302,6 +305,14 @@ 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);
@@ -341,21 +352,17 @@ bool DXVA2Renderer::initializeRenderer()
bool DXVA2Renderer::initialize(SDL_Window* window, int videoFormat, int width, int height)
{
m_VideoFormat = videoFormat;
m_Width = width;
m_Height = height;
m_VideoWidth = width;
m_VideoHeight = 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 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));
// 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);
if (!m_SdlRenderer) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"SDL_CreateRenderer() failed: %s",
@@ -365,15 +372,20 @@ 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));
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.SampleWidth = m_VideoWidth;
m_Desc.SampleHeight = m_VideoHeight;
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.SampleFormat.SampleFormat = DXVA2_SampleProgressiveFrame;
m_Desc.Format = (D3DFORMAT)MAKEFOURCC('N','V','1','2');
@@ -393,23 +405,95 @@ void DXVA2Renderer::renderFrame(AVFrame* frame)
IDirect3DSurface9* surface = reinterpret_cast<IDirect3DSurface9*>(frame->data[3]);
HRESULT hr;
hr = m_Device->TestCooperativeLevel();
switch (hr) {
case D3D_OK:
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;
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:
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Unknown D3D error: %x",
hr);
return;
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;
}
DXVA2_VideoSample sample = {};
@@ -418,18 +502,31 @@ void DXVA2Renderer::renderFrame(AVFrame* frame)
sample.SrcSurface = surface;
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
double srcAspectRatio = (double)m_Desc.SampleWidth / (double)m_Desc.SampleHeight;
double dstAspectRatio = (double)m_DisplayWidth / (double)m_DisplayHeight;
if (dstAspectRatio < srcAspectRatio) {
// Greater height per width
int drawHeight = (int)(m_DisplayWidth / srcAspectRatio);
sample.DstRect.top = (m_DisplayHeight - drawHeight) / 2;
sample.DstRect.bottom = sample.DstRect.bottom + drawHeight;
sample.DstRect.right = m_DisplayWidth;
}
else {
// Greater width per height
int drawWidth = (int)(m_DisplayHeight * srcAspectRatio);
sample.DstRect.bottom = m_DisplayHeight;
sample.DstRect.left = (m_DisplayWidth - drawWidth) / 2;
sample.DstRect.right = sample.DstRect.left + drawWidth;
}
DXVA2_VideoProcessBltParams bltParams = {};
bltParams.TargetFrame = m_FrameIndex++;
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.TargetRect = sample.DstRect;
bltParams.BackgroundColor.Alpha = 0xFFFF;
bltParams.DestFormat.SampleFormat = DXVA2_SampleProgressiveFrame;
@@ -441,12 +538,33 @@ 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);
}
m_Device->Present(nullptr, nullptr, nullptr, nullptr);
// We must try to present to trigger SDL's logic to recover the render target,
// even if VideoProcessBlt() fails.
SDL_RenderPresent(m_SdlRenderer);
}
+5 -2
View File
@@ -39,8 +39,11 @@ private:
const enum AVPixelFormat* pixFmts);
int m_VideoFormat;
int m_Width;
int m_Height;
int m_VideoWidth;
int m_VideoHeight;
int m_DisplayWidth;
int m_DisplayHeight;
SDL_Renderer* m_SdlRenderer;
+20 -1
View File
@@ -1,5 +1,7 @@
#include "renderer.h"
#include <Limelight.h>
SdlRenderer::SdlRenderer()
: m_Renderer(nullptr),
m_Texture(nullptr)
@@ -25,10 +27,18 @@ bool SdlRenderer::prepareDecoderContext(AVCodecContext*)
}
bool SdlRenderer::initialize(SDL_Window* window,
int,
int videoFormat,
int width,
int height)
{
// 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).
if (videoFormat != VIDEO_FORMAT_H264) {
return false;
}
m_Renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
if (!m_Renderer) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
@@ -41,6 +51,11 @@ 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,
@@ -65,6 +80,10 @@ 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);
@@ -0,0 +1,132 @@
#include "vaapi.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;
}
return true;
}
bool
VAAPIRenderer::prepareDecoderContext(AVCodecContext* context)
{
context->hw_device_ctx = av_buffer_ref(m_HwContext);
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;
// Center in frame and preserve aspect ratio
int x, y, width, height;
double srcAspectRatio = (double)m_VideoWidth / (double)m_VideoHeight;
double dstAspectRatio = (double)m_DisplayWidth / (double)m_DisplayHeight;
if (dstAspectRatio < srcAspectRatio) {
// Greater height per width
int drawHeight = (int)(m_DisplayWidth / srcAspectRatio);
y = (m_DisplayHeight - drawHeight) / 2;
height = drawHeight;
x = 0;
width = m_DisplayWidth;
}
else {
// Greater width per height
int drawWidth = (int)(m_DisplayHeight * srcAspectRatio);
y = 0;
height = m_DisplayHeight;
x = (m_DisplayWidth - drawWidth) / 2;
width = drawWidth;
}
m_vaPutSurface(vaDeviceContext->display,
surface,
m_XWindow,
0, 0,
m_VideoWidth, m_VideoHeight,
x, y,
width, height,
NULL, 0, 0);
av_frame_free(&frame);
}
@@ -0,0 +1,50 @@
#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;
};
+143 -39
View File
@@ -7,9 +7,14 @@
#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
{
@@ -18,9 +23,10 @@ public:
: m_HwContext(nullptr),
m_DisplayLayer(nullptr),
m_FormatDesc(nullptr),
m_View(nullptr)
m_View(nullptr),
m_DisplayLink(nullptr),
m_FrameQueueLock(0)
{
}
virtual ~VTRenderer()
@@ -32,8 +38,132 @@ 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,
@@ -113,6 +243,10 @@ public:
return false;
}
CVDisplayLinkCreateWithActiveCGDisplays(&m_DisplayLink);
CVDisplayLinkSetOutputCallback(m_DisplayLink, displayLinkOutputCallback, this);
CVDisplayLinkStart(m_DisplayLink);
return true;
}
@@ -124,49 +258,15 @@ public:
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();
}
// 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);
SDL_AtomicLock(&m_FrameQueueLock);
m_FrameQueue.enqueue(frame);
SDL_AtomicUnlock(&m_FrameQueueLock);
}
private:
@@ -192,6 +292,10 @@ 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() {
+41 -18
View File
@@ -1,14 +1,18 @@
#include <Limelight.h>
#include "ffmpeg.h"
#ifdef _WIN32
#ifdef Q_OS_WIN32
#include "ffmpeg-renderers/dxva2.h"
#endif
#ifdef __APPLE__
#ifdef Q_OS_DARWIN
#include "ffmpeg-renderers/vt.h"
#endif
#ifdef HAVE_LIBVA
#include "ffmpeg-renderers/vaapi.h"
#endif
bool FFmpegVideoDecoder::chooseDecoder(
StreamingPreferences::VideoDecoderSelection vds,
SDL_Window* window,
@@ -60,15 +64,20 @@ bool FFmpegVideoDecoder::chooseDecoder(
// Look for acceleration types we support
switch (config->device_type) {
#ifdef _WIN32
#ifdef Q_OS_WIN32
case AV_HWDEVICE_TYPE_DXVA2:
newRenderer = new DXVA2Renderer();
break;
#endif
#ifdef __APPLE__
#ifdef Q_OS_DARWIN
case AV_HWDEVICE_TYPE_VIDEOTOOLBOX:
newRenderer = VTRendererFactory::createRenderer();
break;
#endif
#ifdef HAVE_LIBVA
case AV_HWDEVICE_TYPE_VAAPI:
newRenderer = new VAAPIRenderer();
break;
#endif
default:
continue;
@@ -98,6 +107,7 @@ 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");
@@ -105,14 +115,31 @@ FFmpegVideoDecoder::FFmpegVideoDecoder()
FFmpegVideoDecoder::~FFmpegVideoDecoder()
{
avcodec_close(m_VideoDecoderCtx);
av_free(m_VideoDecoderCtx);
m_VideoDecoderCtx = nullptr;
// Drop any frames still queued to ensure
// they are properly freed.
SDL_Event event;
m_HwDecodeCfg = nullptr;
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);
delete m_Renderer;
m_Renderer = nullptr;
}
bool FFmpegVideoDecoder::initialize(
@@ -217,14 +244,9 @@ int FFmpegVideoDecoder::submitDecodeUnit(PDECODE_UNIT du)
err = avcodec_receive_frame(m_VideoDecoderCtx, frame);
if (err == 0) {
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);
// Queue the frame for rendering from the main thread
SDL_AtomicIncRef(&m_QueuedFrames);
queueFrame(frame);
}
else {
av_frame_free(&frame);
@@ -238,7 +260,7 @@ void FFmpegVideoDecoder::renderFrame(SDL_UserEvent* event)
{
AVFrame* frame = reinterpret_cast<AVFrame*>(event->data1);
m_Renderer->renderFrame(frame);
av_frame_free(&frame);
SDL_AtomicDecRef(&m_QueuedFrames);
}
// Called on main thread
@@ -246,4 +268,5 @@ void FFmpegVideoDecoder::dropFrame(SDL_UserEvent* event)
{
AVFrame* frame = reinterpret_cast<AVFrame*>(event->data1);
av_frame_free(&frame);
SDL_AtomicDecRef(&m_QueuedFrames);
}
+1
View File
@@ -38,4 +38,5 @@ private:
QByteArray m_DecodeBuffer;
const AVCodecHWConfig* m_HwDecodeCfg;
IFFmpegRenderer* m_Renderer;
SDL_atomic_t m_QueuedFrames;
};
+106
View File
@@ -0,0 +1,106 @@
#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;
}
+28
View File
@@ -0,0 +1,28 @@
#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 -1
View File
@@ -1,5 +1,5 @@
#pragma once
#define THROW_BAD_ALLOC_IF_NULL(x) \
if ((x) == nullptr) throw new std::bad_alloc()
if ((x) == nullptr) throw std::bad_alloc()
+3
View File
@@ -0,0 +1,3 @@
SOURCES = main.cpp
LIBS += -lSLVideo
+7
View File
@@ -0,0 +1,7 @@
#include <SLVideo.h>
int main()
{
SLVideo_CreateContext();
return 0;
}
-514
View File
@@ -1,514 +0,0 @@
/*
* 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 */
-50
View File
@@ -1,50 +0,0 @@
/*
* 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 */
File diff suppressed because it is too large Load Diff
-165
View File
@@ -1,165 +0,0 @@
/*
* 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 */
-209
View File
@@ -1,209 +0,0 @@
/*
* 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 */
-65
View File
@@ -1,65 +0,0 @@
/*
* 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 */
File diff suppressed because it is too large Load Diff
-861
View File
@@ -1,861 +0,0 @@
/*
* 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 */
-108
View File
@@ -1,108 +0,0 @@
/*
* 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 */
-107
View File
@@ -1,107 +0,0 @@
/*
* Copyright (C) 2001-2003 Michael Niedermayer (michaelni@gmx.at)
*
* 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 */
-45
View File
@@ -1,45 +0,0 @@
/*
* 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 */
-579
View File
@@ -1,579 +0,0 @@
/*
* Copyright (C) 2011-2013 Michael Niedermayer (michaelni@gmx.at)
*
* 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 */
-45
View File
@@ -1,45 +0,0 @@
/*
* 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 */
-336
View File
@@ -1,336 +0,0 @@
/*
* Copyright (C) 2001-2011 Michael Niedermayer <michaelni@gmx.at>
*
* 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 */
-53
View File
@@ -1,53 +0,0 @@
/*
* 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 */
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
-514
View File
@@ -1,514 +0,0 @@
/*
* 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 */
@@ -1,50 +0,0 @@
/*
* 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 */
File diff suppressed because it is too large Load Diff
@@ -1,165 +0,0 @@
/*
* 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 */
@@ -1,209 +0,0 @@
/*
* 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 */
@@ -1,65 +0,0 @@
/*
* 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 */
File diff suppressed because it is too large Load Diff
-861
View File
@@ -1,861 +0,0 @@
/*
* 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 */
-108
View File
@@ -1,108 +0,0 @@
/*
* 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 */
@@ -1,107 +0,0 @@
/*
* Copyright (C) 2001-2003 Michael Niedermayer (michaelni@gmx.at)
*
* 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 */
@@ -1,45 +0,0 @@
/*
* 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 */
@@ -1,579 +0,0 @@
/*
* Copyright (C) 2011-2013 Michael Niedermayer (michaelni@gmx.at)
*
* 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 */
@@ -1,45 +0,0 @@
/*
* 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 */
-336
View File
@@ -1,336 +0,0 @@
/*
* Copyright (C) 2001-2011 Michael Niedermayer <michaelni@gmx.at>
*
* 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 */
-53
View File
@@ -1,53 +0,0 @@
/*
* 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 */
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+10
View File
@@ -59,3 +59,13 @@ 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
}
+4
View File
@@ -6,3 +6,7 @@ SUBDIRS = \
app
CONFIG += ordered
# Run our compile tests
load(configure)
qtCompileTest(SLVideo)
+57 -18
View File
@@ -12,6 +12,7 @@ DEFINES += \
OPUS_BUILD=1
contains(QT_ARCH, i386) {
CONFIG += x86
DEFINES += \
OPUS_X86_MAY_HAVE_SSE=1 \
OPUS_X86_MAY_HAVE_SSE2=1 \
@@ -21,6 +22,7 @@ contains(QT_ARCH, i386) {
# AMD64 implies SSE2 support
contains(QT_ARCH, x86_64) {
CONFIG += x86
DEFINES += \
OPUS_X86_MAY_HAVE_SSE=1 \
OPUS_X86_MAY_HAVE_SSE2=1 \
@@ -30,22 +32,50 @@ contains(QT_ARCH, x86_64) {
OPUS_X86_PRESUME_SSE2=1
}
contains(QT_ARCH, arm) {
CONFIG += arm
DEFINES += \
OPUS_ARM_MAY_HAVE_NEON_INTR=1
}
QMAKE_CFLAGS += -O2
SOURCES_SSE = \
$$OPUS_DIR/celt/x86/pitch_sse.c
x86 {
SOURCES += \
$$OPUS_DIR/celt/x86/x86_celt_map.c \
$$OPUS_DIR/silk/x86/x86_silk_map.c \
$$OPUS_DIR/celt/x86/x86cpu.c
SOURCES_SSE2 = \
$$OPUS_DIR/celt/x86/pitch_sse2.c \
$$OPUS_DIR/celt/x86/vq_sse2.c
SOURCES_SSE = \
$$OPUS_DIR/celt/x86/pitch_sse.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_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
}
arm {
SOURCES += \
$$OPUS_DIR/celt/arm/arm_celt_map.c \
$$OPUS_DIR/celt/arm/armcpu.c
SOURCES_NEON = \
$$OPUS_DIR/celt/arm/celt_neon_intr.c \
$$OPUS_DIR/celt/arm/pitch_neon_intr.c \
$$OPUS_DIR/silk/arm/arm_silk_map.c \
$$OPUS_DIR/silk/arm/biquad_alt_neon_intr.c \
$$OPUS_DIR/silk/arm/LPC_inv_pred_gain_neon_intr.c \
$$OPUS_DIR/silk/arm/NSQ_del_dec_neon_intr.c \
$$OPUS_DIR/silk/arm/NSQ_neon.c
}
SOURCES += \
$$OPUS_DIR/celt/quant_bands.c \
@@ -59,8 +89,6 @@ SOURCES += \
$$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 \
@@ -82,7 +110,6 @@ SOURCES += \
$$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 \
@@ -201,8 +228,13 @@ INCLUDEPATH += \
CONFIG += warn_off staticlib
win32-msvc* {
# No flags required to build with SSE on MSVC
SOURCES += $$SOURCES_SSE $$SOURCES_SSE2 $$SOURCES_SSE41
# No flags required to build with SSE or NEON on MSVC
x86 {
SOURCES += $$SOURCES_SSE $$SOURCES_SSE2 $$SOURCES_SSE41
}
arm {
SOURCES += $$SOURCES_NEON
}
}
else {
sse.name = sse
@@ -226,5 +258,12 @@ else {
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
neon.name = neon
neon.input = SOURCES_NEON
neon.dependency_type = TYPE_C
neon.variable_out = OBJECTS
neon.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_IN_BASE}$${first(QMAKE_EXT_OBJ)}
neon.commands = $${QMAKE_CC} -c $(CFLAGS) $(INCPATH) -o ${QMAKE_FILE_OUT} ${QMAKE_FILE_IN}
QMAKE_EXTRA_COMPILERS += sse sse2 sse41 neon
}

Some files were not shown because too many files have changed in this diff Show More