mirror of
https://github.com/jellyfin/jellyfin-ffmpeg.git
synced 2026-09-02 21:03:08 +03:00
New upstream version 3.5~git20180113
This commit is contained in:
+38
@@ -0,0 +1,38 @@
|
||||
*.a
|
||||
*.o
|
||||
*.o.*
|
||||
*.d
|
||||
*.def
|
||||
*.dll
|
||||
*.dylib
|
||||
*.exe
|
||||
*.exp
|
||||
*.gcda
|
||||
*.gcno
|
||||
*.h.c
|
||||
*.ilk
|
||||
*.lib
|
||||
*.pc
|
||||
*.pdb
|
||||
*.so
|
||||
*.so.*
|
||||
*.swp
|
||||
*.ver
|
||||
*.version
|
||||
*.ptx
|
||||
*.ptx.c
|
||||
*_g
|
||||
\#*
|
||||
.\#*
|
||||
/.config
|
||||
/.version
|
||||
/ffmpeg
|
||||
/ffplay
|
||||
/ffprobe
|
||||
/config.asm
|
||||
/config.h
|
||||
/coverage.info
|
||||
/avversion.h
|
||||
/lcov/
|
||||
/src
|
||||
/mapfile
|
||||
@@ -11,6 +11,10 @@ addons:
|
||||
compiler:
|
||||
- clang
|
||||
- gcc
|
||||
matrix:
|
||||
exclude:
|
||||
- os: osx
|
||||
compiler: gcc
|
||||
cache:
|
||||
directories:
|
||||
- ffmpeg-samples
|
||||
|
||||
@@ -1,6 +1,45 @@
|
||||
Entries are sorted chronologically from oldest to youngest within each release,
|
||||
releases are sorted from youngest to oldest.
|
||||
|
||||
version <next>:
|
||||
- Bitstream filters for editing metadata in H.264, HEVC and MPEG-2 streams
|
||||
- Dropped support for OpenJPEG versions 2.0 and below. Using OpenJPEG now
|
||||
requires 2.1 (or later) and pkg-config.
|
||||
- VDA dropped (use VideoToolbox instead)
|
||||
- MagicYUV encoder
|
||||
- Raw AMR-NB and AMR-WB demuxers
|
||||
- TiVo ty/ty+ demuxer
|
||||
- Intel QSV-accelerated MJPEG encoding
|
||||
- PCE support for extended channel layouts in the AAC encoder
|
||||
- native aptX encoder and decoder
|
||||
- Raw aptX muxer and demuxer
|
||||
- NVIDIA NVDEC-accelerated H.264, HEVC, MPEG-1/2/4, VC1, VP8/9 hwaccel decoding
|
||||
- Intel QSV-accelerated overlay filter
|
||||
- mcompand audio filter
|
||||
- acontrast audio filter
|
||||
- OpenCL overlay filter
|
||||
- video mix filter
|
||||
- video normalize filter
|
||||
- audio lv2 wrapper filter
|
||||
- VAAPI VP8 decoding
|
||||
- AMD AMF H.264 and HEVC encoders
|
||||
- video fillborders filter
|
||||
- video setrange filter
|
||||
- nsp demuxer
|
||||
- support LibreSSL (via libtls)
|
||||
- AVX-512/ZMM support added
|
||||
- Dropped support for building for Windows XP. The minimum supported Windows
|
||||
version is Windows Vista.
|
||||
- deconvolve video filter
|
||||
- entropy video filter
|
||||
- hilbert audio filter source
|
||||
- aiir audio filter
|
||||
- aiff: add support for CD-ROM XA ADPCM
|
||||
- Removed the ffserver program
|
||||
- Removed the ffmenc and ffmdec muxer and demuxer
|
||||
- VideoToolbox HEVC encoder and hwaccel
|
||||
|
||||
|
||||
version 3.4:
|
||||
- deflicker video filter
|
||||
- doubleweave video filter
|
||||
|
||||
+6
-8
@@ -29,9 +29,6 @@ ffplay:
|
||||
ffprobe:
|
||||
ffprobe.c Stefano Sabatini
|
||||
|
||||
ffserver:
|
||||
ffserver.c Reynaldo H. Verdejo Pinochet
|
||||
|
||||
Commandline utility code:
|
||||
cmdutils.c, cmdutils.h Michael Niedermayer
|
||||
|
||||
@@ -158,7 +155,7 @@ Codecs:
|
||||
cpia.c Stephan Hilb
|
||||
crystalhd.c Philip Langdale
|
||||
cscd.c Reimar Doeffinger
|
||||
cuvid.c Timo Rothenpieler
|
||||
cuviddec.c Timo Rothenpieler
|
||||
dca* foo86
|
||||
dirac* Rostislav Pehlivanov
|
||||
dnxhd* Baptiste Coudurier
|
||||
@@ -170,6 +167,7 @@ Codecs:
|
||||
eacmv*, eaidct*, eat* Peter Ross
|
||||
evrc* Paul B Mahol
|
||||
exif.c, exif.h Thilo Borgmann
|
||||
exr.c Martin Vignali
|
||||
ffv1* Michael Niedermayer
|
||||
ffwavesynth.c Nicolas George
|
||||
fifo.c Jan Sebechlebsky
|
||||
@@ -212,7 +210,7 @@ Codecs:
|
||||
msrle.c Mike Melanson
|
||||
msvideo1.c Mike Melanson
|
||||
nuv.c Reimar Doeffinger
|
||||
nvenc* Timo Rothenpieler
|
||||
nvdec*, nvenc* Timo Rothenpieler
|
||||
opus* Rostislav Pehlivanov
|
||||
paf.* Paul B Mahol
|
||||
pcx.c Ivo van Poorten
|
||||
@@ -244,8 +242,7 @@ Codecs:
|
||||
txd.c Ivo van Poorten
|
||||
vc2* Rostislav Pehlivanov
|
||||
vcr1.c Michael Niedermayer
|
||||
vda_h264_dec.c Xidorn Quan
|
||||
videotoolboxenc.c Rick Kern
|
||||
videotoolboxenc.c Rick Kern, Aman Gupta
|
||||
vima.c Paul B Mahol
|
||||
vorbisdec.c Denes Balatoni, David Conrad
|
||||
vorbisenc.c Oded Shimon
|
||||
@@ -272,7 +269,7 @@ Hardware acceleration:
|
||||
vaapi* Gwenole Beauchesne
|
||||
vaapi_encode* Mark Thompson
|
||||
vdpau* Philip Langdale, Carl Eugen Hoyos
|
||||
videotoolbox* Rick Kern
|
||||
videotoolbox* Rick Kern, Aman Gupta
|
||||
|
||||
|
||||
libavdevice
|
||||
@@ -587,6 +584,7 @@ FFmpeg release signing key FCF9 86EA 15E6 E293 A564 4F10 B432 2F04 D676 58D8
|
||||
Ganesh Ajjanagadde C96A 848E 97C3 CEA2 AB72 5CE4 45F9 6A2D 3C36 FB1B
|
||||
Gwenole Beauchesne 2E63 B3A6 3E44 37E2 017D 2704 53C7 6266 B153 99C4
|
||||
Jaikrishnan Menon 61A1 F09F 01C9 2D45 78E1 C862 25DC 8831 AF70 D368
|
||||
James Almer 7751 2E8C FD94 A169 57E6 9A7A 1463 01AD 7376 59E0
|
||||
Jean Delvare 7CA6 9F44 60F1 BDC4 1FD2 C858 A552 6B9B B3CD 4E6A
|
||||
Loren Merritt ABD9 08F4 C920 3F65 D8BE 35D7 1540 DAA7 060F 56DE
|
||||
Lou Logan 7D68 DC73 CBEF EABB 671A B6CF 621C 2E28 82F8 DC3A
|
||||
|
||||
@@ -45,12 +45,11 @@ FF_DEP_LIBS := $(DEP_LIBS)
|
||||
FF_STATIC_DEP_LIBS := $(STATIC_DEP_LIBS)
|
||||
|
||||
$(TOOLS): %$(EXESUF): %.o
|
||||
$(LD) $(LDFLAGS) $(LDEXEFLAGS) $(LD_O) $^ $(ELIBS)
|
||||
$(LD) $(LDFLAGS) $(LDEXEFLAGS) $(LD_O) $^ $(EXTRALIBS-$(*F)) $(EXTRALIBS) $(ELIBS)
|
||||
|
||||
target_dec_%_fuzzer$(EXESUF): target_dec_%_fuzzer.o $(FF_DEP_LIBS)
|
||||
$(LD) $(LDFLAGS) $(LDEXEFLAGS) $(LD_O) $^ $(ELIBS) $(FF_EXTRALIBS) $(LIBFUZZER_PATH)
|
||||
|
||||
tools/cws2fws$(EXESUF): ELIBS = $(ZLIB)
|
||||
tools/sofa2wavs$(EXESUF): ELIBS = $(FF_EXTRALIBS)
|
||||
tools/uncoded_frame$(EXESUF): $(FF_DEP_LIBS)
|
||||
tools/uncoded_frame$(EXESUF): ELIBS = $(FF_EXTRALIBS)
|
||||
@@ -128,21 +127,18 @@ install-data: $(DATA_FILES)
|
||||
$(Q)mkdir -p "$(DATADIR)"
|
||||
$(INSTALL) -m 644 $(DATA_FILES) "$(DATADIR)"
|
||||
|
||||
uninstall: uninstall-libs uninstall-headers uninstall-data
|
||||
uninstall: uninstall-data uninstall-headers uninstall-libs uninstall-pkgconfig
|
||||
|
||||
uninstall-data:
|
||||
$(RM) -r "$(DATADIR)"
|
||||
|
||||
clean::
|
||||
$(RM) $(CLEANSUFFIXES)
|
||||
$(RM) $(CLEANSUFFIXES:%=compat/msvcrt/%)
|
||||
$(RM) $(CLEANSUFFIXES:%=compat/atomics/pthread/%)
|
||||
$(RM) $(CLEANSUFFIXES:%=compat/%)
|
||||
$(RM) $(addprefix compat/,$(CLEANSUFFIXES)) $(addprefix compat/*/,$(CLEANSUFFIXES))
|
||||
$(RM) -r coverage-html
|
||||
$(RM) -rf coverage.info coverage.info.in lcov
|
||||
|
||||
distclean::
|
||||
$(RM) $(DISTCLEANSUFFIXES)
|
||||
distclean:: clean
|
||||
$(RM) .version avversion.h config.asm config.h mapfile \
|
||||
ffbuild/.config ffbuild/config.* libavutil/avconfig.h \
|
||||
version.h libavutil/ffversion.h libavcodec/codec_names.h \
|
||||
@@ -155,6 +151,7 @@ endif
|
||||
config:
|
||||
$(SRC_PATH)/configure $(value FFMPEG_CONFIGURATION)
|
||||
|
||||
build: all alltools examples testprogs
|
||||
check: all alltools examples testprogs fate
|
||||
|
||||
include $(SRC_PATH)/tests/Makefile
|
||||
@@ -170,4 +167,5 @@ $(sort $(OBJDIRS)):
|
||||
# so this saves some time on slow systems.
|
||||
.SUFFIXES:
|
||||
|
||||
.PHONY: all all-yes alltools check *clean config install* testprogs uninstall*
|
||||
.PHONY: all all-yes alltools build check config testprogs
|
||||
.PHONY: *clean install* uninstall*
|
||||
|
||||
@@ -21,8 +21,6 @@ such as audio, video, subtitles and related metadata.
|
||||
* [ffplay](https://ffmpeg.org/ffplay.html) is a minimalistic multimedia player.
|
||||
* [ffprobe](https://ffmpeg.org/ffprobe.html) is a simple analysis tool to inspect
|
||||
multimedia content.
|
||||
* [ffserver](https://ffmpeg.org/ffserver.html) is a multimedia streaming server
|
||||
for live broadcasts.
|
||||
* Additional small tools such as `aviocat`, `ismindex` and `qt-faststart`.
|
||||
|
||||
## Documentation
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
|
||||
┌───────────────────────────────────────┐
|
||||
│ RELEASE NOTES for FFmpeg 3.4 "Cantor" │
|
||||
└───────────────────────────────────────┘
|
||||
|
||||
The FFmpeg Project proudly presents FFmpeg 3.4 "Cantor", about 6
|
||||
months after the release of FFmpeg 3.3.
|
||||
|
||||
A complete Changelog is available at the root of the project, and the
|
||||
complete Git history on http://source.ffmpeg.org.
|
||||
|
||||
We hope you will like this release as much as we enjoyed working on it, and
|
||||
as usual, if you have any questions about it, or any FFmpeg related topic,
|
||||
feel free to join us on the #ffmpeg IRC channel (on irc.freenode.net) or ask
|
||||
on the mailing-lists.
|
||||
@@ -59,29 +59,29 @@
|
||||
#define LOAD_LIBRARY(l, path) \
|
||||
do { \
|
||||
if (!((l) = dlopen(path, RTLD_LAZY))) { \
|
||||
av_log(NULL, AV_LOG_ERROR, "Cannot load %s\n", path); \
|
||||
av_log(logctx, AV_LOG_ERROR, "Cannot load %s\n", path); \
|
||||
ret = AVERROR_UNKNOWN; \
|
||||
goto error; \
|
||||
} \
|
||||
av_log(NULL, AV_LOG_TRACE, "Loaded lib: %s\n", path); \
|
||||
av_log(logctx, AV_LOG_TRACE, "Loaded lib: %s\n", path); \
|
||||
} while (0)
|
||||
|
||||
#define LOAD_SYMBOL(fun, tp, symbol) \
|
||||
do { \
|
||||
if (!((f->fun) = (tp*)dlsym(f->lib, symbol))) { \
|
||||
av_log(NULL, AV_LOG_ERROR, "Cannot load %s\n", symbol); \
|
||||
av_log(logctx, AV_LOG_ERROR, "Cannot load %s\n", symbol); \
|
||||
ret = AVERROR_UNKNOWN; \
|
||||
goto error; \
|
||||
} \
|
||||
av_log(NULL, AV_LOG_TRACE, "Loaded sym: %s\n", symbol); \
|
||||
av_log(logctx, AV_LOG_TRACE, "Loaded sym: %s\n", symbol); \
|
||||
} while (0)
|
||||
|
||||
#define LOAD_SYMBOL_OPT(fun, tp, symbol) \
|
||||
do { \
|
||||
if (!((f->fun) = (tp*)dlsym(f->lib, symbol))) { \
|
||||
av_log(NULL, AV_LOG_DEBUG, "Cannot load optional %s\n", symbol); \
|
||||
av_log(logctx, AV_LOG_DEBUG, "Cannot load optional %s\n", symbol); \
|
||||
} else { \
|
||||
av_log(NULL, AV_LOG_TRACE, "Loaded sym: %s\n", symbol); \
|
||||
av_log(logctx, AV_LOG_TRACE, "Loaded sym: %s\n", symbol); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
@@ -187,7 +187,7 @@ static inline void nvenc_free_functions(NvencFunctions **functions)
|
||||
}
|
||||
|
||||
#ifdef AV_COMPAT_DYNLINK_CUDA_H
|
||||
static inline int cuda_load_functions(CudaFunctions **functions)
|
||||
static inline int cuda_load_functions(CudaFunctions **functions, void *logctx)
|
||||
{
|
||||
GENERIC_LOAD_FUNC_PREAMBLE(CudaFunctions, cuda, CUDA_LIBNAME);
|
||||
|
||||
@@ -210,7 +210,7 @@ static inline int cuda_load_functions(CudaFunctions **functions)
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline int cuvid_load_functions(CuvidFunctions **functions)
|
||||
static inline int cuvid_load_functions(CuvidFunctions **functions, void *logctx)
|
||||
{
|
||||
GENERIC_LOAD_FUNC_PREAMBLE(CuvidFunctions, cuvid, NVCUVID_LIBNAME);
|
||||
|
||||
@@ -244,7 +244,7 @@ static inline int cuvid_load_functions(CuvidFunctions **functions)
|
||||
GENERIC_LOAD_FUNC_FINALE(cuvid);
|
||||
}
|
||||
|
||||
static inline int nvenc_load_functions(NvencFunctions **functions)
|
||||
static inline int nvenc_load_functions(NvencFunctions **functions, void *logctx)
|
||||
{
|
||||
GENERIC_LOAD_FUNC_PREAMBLE(NvencFunctions, nvenc, NVENC_LIBNAME);
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ extern "C" {
|
||||
typedef RECT NVENC_RECT;
|
||||
#else
|
||||
// =========================================================================================
|
||||
#ifndef GUID
|
||||
#if !defined(GUID) && !defined(GUID_DEFINED)
|
||||
/*!
|
||||
* \struct GUID
|
||||
* Abstracts the GUID structure for non-windows platforms.
|
||||
|
||||
+8
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011 KO Myung-Hun <komh@chollian.net>
|
||||
* Copyright (c) 2011-2017 KO Myung-Hun <komh@chollian.net>
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
@@ -46,9 +46,11 @@ typedef struct {
|
||||
|
||||
typedef void pthread_attr_t;
|
||||
|
||||
typedef HMTX pthread_mutex_t;
|
||||
typedef _fmutex pthread_mutex_t;
|
||||
typedef void pthread_mutexattr_t;
|
||||
|
||||
#define PTHREAD_MUTEX_INITIALIZER _FMUTEX_INITIALIZER
|
||||
|
||||
typedef struct {
|
||||
HEV event_sem;
|
||||
HEV ack_sem;
|
||||
@@ -98,28 +100,28 @@ static av_always_inline int pthread_join(pthread_t thread, void **value_ptr)
|
||||
static av_always_inline int pthread_mutex_init(pthread_mutex_t *mutex,
|
||||
const pthread_mutexattr_t *attr)
|
||||
{
|
||||
DosCreateMutexSem(NULL, (PHMTX)mutex, 0, FALSE);
|
||||
_fmutex_create(mutex, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static av_always_inline int pthread_mutex_destroy(pthread_mutex_t *mutex)
|
||||
{
|
||||
DosCloseMutexSem(*(PHMTX)mutex);
|
||||
_fmutex_close(mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static av_always_inline int pthread_mutex_lock(pthread_mutex_t *mutex)
|
||||
{
|
||||
DosRequestMutexSem(*(PHMTX)mutex, SEM_INDEFINITE_WAIT);
|
||||
_fmutex_request(mutex, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static av_always_inline int pthread_mutex_unlock(pthread_mutex_t *mutex)
|
||||
{
|
||||
DosReleaseMutexSem(*(PHMTX)mutex);
|
||||
_fmutex_release(mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include "config.h"
|
||||
#if (_WIN32_WINNT < 0x0602) || HAVE_WINRT
|
||||
#include "libavutil/wchar_filename.h"
|
||||
#endif
|
||||
|
||||
+10
-263
@@ -39,11 +39,6 @@
|
||||
#include <windows.h>
|
||||
#include <process.h>
|
||||
|
||||
#if _WIN32_WINNT < 0x0600 && defined(__MINGW32__)
|
||||
#undef MemoryBarrier
|
||||
#define MemoryBarrier __sync_synchronize
|
||||
#endif
|
||||
|
||||
#include "libavutil/attributes.h"
|
||||
#include "libavutil/common.h"
|
||||
#include "libavutil/internal.h"
|
||||
@@ -56,24 +51,15 @@ typedef struct pthread_t {
|
||||
void *ret;
|
||||
} pthread_t;
|
||||
|
||||
/* the conditional variable api for windows 6.0+ uses critical sections and
|
||||
* not mutexes */
|
||||
typedef CRITICAL_SECTION pthread_mutex_t;
|
||||
|
||||
/* This is the CONDITION_VARIABLE typedef for using Windows' native
|
||||
* conditional variables on kernels 6.0+. */
|
||||
#if HAVE_CONDITION_VARIABLE_PTR
|
||||
/* use light weight mutex/condition variable API for Windows Vista and later */
|
||||
typedef SRWLOCK pthread_mutex_t;
|
||||
typedef CONDITION_VARIABLE pthread_cond_t;
|
||||
#else
|
||||
typedef struct pthread_cond_t {
|
||||
void *Ptr;
|
||||
} pthread_cond_t;
|
||||
#endif
|
||||
|
||||
#if _WIN32_WINNT >= 0x0600
|
||||
#define PTHREAD_MUTEX_INITIALIZER SRWLOCK_INIT
|
||||
#define PTHREAD_COND_INITIALIZER CONDITION_VARIABLE_INIT
|
||||
|
||||
#define InitializeCriticalSection(x) InitializeCriticalSectionEx(x, 0, 0)
|
||||
#define WaitForSingleObject(a, b) WaitForSingleObjectEx(a, b, FALSE)
|
||||
#endif
|
||||
|
||||
static av_unused unsigned __stdcall attribute_align_arg win32thread_worker(void *arg)
|
||||
{
|
||||
@@ -114,26 +100,25 @@ static av_unused int pthread_join(pthread_t thread, void **value_ptr)
|
||||
|
||||
static inline int pthread_mutex_init(pthread_mutex_t *m, void* attr)
|
||||
{
|
||||
InitializeCriticalSection(m);
|
||||
InitializeSRWLock(m);
|
||||
return 0;
|
||||
}
|
||||
static inline int pthread_mutex_destroy(pthread_mutex_t *m)
|
||||
{
|
||||
DeleteCriticalSection(m);
|
||||
/* Unlocked SWR locks use no resources */
|
||||
return 0;
|
||||
}
|
||||
static inline int pthread_mutex_lock(pthread_mutex_t *m)
|
||||
{
|
||||
EnterCriticalSection(m);
|
||||
AcquireSRWLockExclusive(m);
|
||||
return 0;
|
||||
}
|
||||
static inline int pthread_mutex_unlock(pthread_mutex_t *m)
|
||||
{
|
||||
LeaveCriticalSection(m);
|
||||
ReleaseSRWLockExclusive(m);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if _WIN32_WINNT >= 0x0600
|
||||
typedef INIT_ONCE pthread_once_t;
|
||||
#define PTHREAD_ONCE_INIT INIT_ONCE_STATIC_INIT
|
||||
|
||||
@@ -167,7 +152,7 @@ static inline int pthread_cond_broadcast(pthread_cond_t *cond)
|
||||
|
||||
static inline int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
|
||||
{
|
||||
SleepConditionVariableCS(cond, mutex, INFINITE);
|
||||
SleepConditionVariableSRW(cond, mutex, INFINITE, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -177,242 +162,4 @@ static inline int pthread_cond_signal(pthread_cond_t *cond)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else // _WIN32_WINNT < 0x0600
|
||||
|
||||
/* atomic init state of dynamically loaded functions */
|
||||
static LONG w32thread_init_state = 0;
|
||||
static av_unused void w32thread_init(void);
|
||||
|
||||
/* for pre-Windows 6.0 platforms, define INIT_ONCE struct,
|
||||
* compatible to the one used in the native API */
|
||||
|
||||
typedef union pthread_once_t {
|
||||
void * Ptr; ///< For the Windows 6.0+ native functions
|
||||
LONG state; ///< For the pre-Windows 6.0 compat code
|
||||
} pthread_once_t;
|
||||
|
||||
#define PTHREAD_ONCE_INIT {0}
|
||||
|
||||
/* function pointers to init once API on windows 6.0+ kernels */
|
||||
static BOOL (WINAPI *initonce_begin)(pthread_once_t *lpInitOnce, DWORD dwFlags, BOOL *fPending, void **lpContext);
|
||||
static BOOL (WINAPI *initonce_complete)(pthread_once_t *lpInitOnce, DWORD dwFlags, void *lpContext);
|
||||
|
||||
/* pre-Windows 6.0 compat using a spin-lock */
|
||||
static inline void w32thread_once_fallback(LONG volatile *state, void (*init_routine)(void))
|
||||
{
|
||||
switch (InterlockedCompareExchange(state, 1, 0)) {
|
||||
/* Initial run */
|
||||
case 0:
|
||||
init_routine();
|
||||
InterlockedExchange(state, 2);
|
||||
break;
|
||||
/* Another thread is running init */
|
||||
case 1:
|
||||
while (1) {
|
||||
MemoryBarrier();
|
||||
if (*state == 2)
|
||||
break;
|
||||
Sleep(0);
|
||||
}
|
||||
break;
|
||||
/* Initialization complete */
|
||||
case 2:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static av_unused int pthread_once(pthread_once_t *once_control, void (*init_routine)(void))
|
||||
{
|
||||
w32thread_once_fallback(&w32thread_init_state, w32thread_init);
|
||||
|
||||
/* Use native functions on Windows 6.0+ */
|
||||
if (initonce_begin && initonce_complete) {
|
||||
BOOL pending = FALSE;
|
||||
initonce_begin(once_control, 0, &pending, NULL);
|
||||
if (pending)
|
||||
init_routine();
|
||||
initonce_complete(once_control, 0, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
w32thread_once_fallback(&once_control->state, init_routine);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* for pre-Windows 6.0 platforms we need to define and use our own condition
|
||||
* variable and api */
|
||||
|
||||
typedef struct win32_cond_t {
|
||||
pthread_mutex_t mtx_broadcast;
|
||||
pthread_mutex_t mtx_waiter_count;
|
||||
volatile int waiter_count;
|
||||
HANDLE semaphore;
|
||||
HANDLE waiters_done;
|
||||
volatile int is_broadcast;
|
||||
} win32_cond_t;
|
||||
|
||||
/* function pointers to conditional variable API on windows 6.0+ kernels */
|
||||
static void (WINAPI *cond_broadcast)(pthread_cond_t *cond);
|
||||
static void (WINAPI *cond_init)(pthread_cond_t *cond);
|
||||
static void (WINAPI *cond_signal)(pthread_cond_t *cond);
|
||||
static BOOL (WINAPI *cond_wait)(pthread_cond_t *cond, pthread_mutex_t *mutex,
|
||||
DWORD milliseconds);
|
||||
|
||||
static av_unused int pthread_cond_init(pthread_cond_t *cond, const void *unused_attr)
|
||||
{
|
||||
win32_cond_t *win32_cond = NULL;
|
||||
|
||||
w32thread_once_fallback(&w32thread_init_state, w32thread_init);
|
||||
|
||||
if (cond_init) {
|
||||
cond_init(cond);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* non native condition variables */
|
||||
win32_cond = (win32_cond_t*)av_mallocz(sizeof(win32_cond_t));
|
||||
if (!win32_cond)
|
||||
return ENOMEM;
|
||||
cond->Ptr = win32_cond;
|
||||
win32_cond->semaphore = CreateSemaphore(NULL, 0, 0x7fffffff, NULL);
|
||||
if (!win32_cond->semaphore)
|
||||
return ENOMEM;
|
||||
win32_cond->waiters_done = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
if (!win32_cond->waiters_done)
|
||||
return ENOMEM;
|
||||
|
||||
pthread_mutex_init(&win32_cond->mtx_waiter_count, NULL);
|
||||
pthread_mutex_init(&win32_cond->mtx_broadcast, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static av_unused int pthread_cond_destroy(pthread_cond_t *cond)
|
||||
{
|
||||
win32_cond_t *win32_cond = (win32_cond_t*)cond->Ptr;
|
||||
/* native condition variables do not destroy */
|
||||
if (cond_init)
|
||||
return 0;
|
||||
|
||||
/* non native condition variables */
|
||||
CloseHandle(win32_cond->semaphore);
|
||||
CloseHandle(win32_cond->waiters_done);
|
||||
pthread_mutex_destroy(&win32_cond->mtx_waiter_count);
|
||||
pthread_mutex_destroy(&win32_cond->mtx_broadcast);
|
||||
av_freep(&win32_cond);
|
||||
cond->Ptr = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static av_unused int pthread_cond_broadcast(pthread_cond_t *cond)
|
||||
{
|
||||
win32_cond_t *win32_cond = (win32_cond_t*)cond->Ptr;
|
||||
int have_waiter;
|
||||
|
||||
if (cond_broadcast) {
|
||||
cond_broadcast(cond);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* non native condition variables */
|
||||
pthread_mutex_lock(&win32_cond->mtx_broadcast);
|
||||
pthread_mutex_lock(&win32_cond->mtx_waiter_count);
|
||||
have_waiter = 0;
|
||||
|
||||
if (win32_cond->waiter_count) {
|
||||
win32_cond->is_broadcast = 1;
|
||||
have_waiter = 1;
|
||||
}
|
||||
|
||||
if (have_waiter) {
|
||||
ReleaseSemaphore(win32_cond->semaphore, win32_cond->waiter_count, NULL);
|
||||
pthread_mutex_unlock(&win32_cond->mtx_waiter_count);
|
||||
WaitForSingleObject(win32_cond->waiters_done, INFINITE);
|
||||
ResetEvent(win32_cond->waiters_done);
|
||||
win32_cond->is_broadcast = 0;
|
||||
} else
|
||||
pthread_mutex_unlock(&win32_cond->mtx_waiter_count);
|
||||
pthread_mutex_unlock(&win32_cond->mtx_broadcast);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static av_unused int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
|
||||
{
|
||||
win32_cond_t *win32_cond = (win32_cond_t*)cond->Ptr;
|
||||
int last_waiter;
|
||||
if (cond_wait) {
|
||||
cond_wait(cond, mutex, INFINITE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* non native condition variables */
|
||||
pthread_mutex_lock(&win32_cond->mtx_broadcast);
|
||||
pthread_mutex_lock(&win32_cond->mtx_waiter_count);
|
||||
win32_cond->waiter_count++;
|
||||
pthread_mutex_unlock(&win32_cond->mtx_waiter_count);
|
||||
pthread_mutex_unlock(&win32_cond->mtx_broadcast);
|
||||
|
||||
// unlock the external mutex
|
||||
pthread_mutex_unlock(mutex);
|
||||
WaitForSingleObject(win32_cond->semaphore, INFINITE);
|
||||
|
||||
pthread_mutex_lock(&win32_cond->mtx_waiter_count);
|
||||
win32_cond->waiter_count--;
|
||||
last_waiter = !win32_cond->waiter_count || !win32_cond->is_broadcast;
|
||||
pthread_mutex_unlock(&win32_cond->mtx_waiter_count);
|
||||
|
||||
if (last_waiter)
|
||||
SetEvent(win32_cond->waiters_done);
|
||||
|
||||
// lock the external mutex
|
||||
return pthread_mutex_lock(mutex);
|
||||
}
|
||||
|
||||
static av_unused int pthread_cond_signal(pthread_cond_t *cond)
|
||||
{
|
||||
win32_cond_t *win32_cond = (win32_cond_t*)cond->Ptr;
|
||||
int have_waiter;
|
||||
if (cond_signal) {
|
||||
cond_signal(cond);
|
||||
return 0;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&win32_cond->mtx_broadcast);
|
||||
|
||||
/* non-native condition variables */
|
||||
pthread_mutex_lock(&win32_cond->mtx_waiter_count);
|
||||
have_waiter = win32_cond->waiter_count;
|
||||
pthread_mutex_unlock(&win32_cond->mtx_waiter_count);
|
||||
|
||||
if (have_waiter) {
|
||||
ReleaseSemaphore(win32_cond->semaphore, 1, NULL);
|
||||
WaitForSingleObject(win32_cond->waiters_done, INFINITE);
|
||||
ResetEvent(win32_cond->waiters_done);
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&win32_cond->mtx_broadcast);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static av_unused void w32thread_init(void)
|
||||
{
|
||||
#if _WIN32_WINNT < 0x0600
|
||||
HMODULE kernel_dll = GetModuleHandle(TEXT("kernel32.dll"));
|
||||
/* if one is available, then they should all be available */
|
||||
cond_init = (void (WINAPI*)(pthread_cond_t *))
|
||||
GetProcAddress(kernel_dll, "InitializeConditionVariable");
|
||||
cond_broadcast = (void (WINAPI*)(pthread_cond_t *))
|
||||
GetProcAddress(kernel_dll, "WakeAllConditionVariable");
|
||||
cond_signal = (void (WINAPI*)(pthread_cond_t *))
|
||||
GetProcAddress(kernel_dll, "WakeConditionVariable");
|
||||
cond_wait = (BOOL (WINAPI*)(pthread_cond_t *, pthread_mutex_t *, DWORD))
|
||||
GetProcAddress(kernel_dll, "SleepConditionVariableCS");
|
||||
initonce_begin = (BOOL (WINAPI*)(pthread_once_t *, DWORD, BOOL *, void **))
|
||||
GetProcAddress(kernel_dll, "InitOnceBeginInitialize");
|
||||
initonce_complete = (BOOL (WINAPI*)(pthread_once_t *, DWORD, void *))
|
||||
GetProcAddress(kernel_dll, "InitOnceComplete");
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endif /* COMPAT_W32PTHREADS_H */
|
||||
|
||||
+18
-21
@@ -45,7 +45,11 @@ libname=$(mktemp -u "library").lib
|
||||
|
||||
trap 'rm -f -- $libname' EXIT
|
||||
|
||||
if [ -n "$AR" ]; then
|
||||
$AR rcs ${libname} $@ >/dev/null
|
||||
else
|
||||
lib -out:${libname} $@ >/dev/null
|
||||
fi
|
||||
if [ $? != 0 ]; then
|
||||
echo "Could not create temporary library." >&2
|
||||
exit 1
|
||||
@@ -54,23 +58,7 @@ fi
|
||||
IFS='
|
||||
'
|
||||
|
||||
# Determine if we're building for x86 or x86_64 and
|
||||
# set the symbol prefix accordingly.
|
||||
prefix=""
|
||||
arch=$(dumpbin -headers ${libname} |
|
||||
tr '\t' ' ' |
|
||||
grep '^ \+.\+machine \+(.\+)' |
|
||||
head -1 |
|
||||
sed -e 's/^ \{1,\}.\{1,\} \{1,\}machine \{1,\}(\(...\)).*/\1/')
|
||||
|
||||
if [ "${arch}" = "x86" ]; then
|
||||
prefix="_"
|
||||
else
|
||||
if [ "${arch}" != "ARM" ] && [ "${arch}" != "x64" ]; then
|
||||
echo "Unknown machine type." >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
prefix="$EXTERN_PREFIX"
|
||||
|
||||
started=0
|
||||
regex="none"
|
||||
@@ -112,7 +100,19 @@ for line in $(cat ${vscript} | tr '\t' ' '); do
|
||||
'
|
||||
done
|
||||
|
||||
dump=$(dumpbin -linkermember:1 ${libname})
|
||||
if [ -n "$NM" ]; then
|
||||
# Use eval, since NM="nm -g"
|
||||
dump=$(eval "$NM --defined-only -g ${libname}" |
|
||||
grep -v : |
|
||||
grep -v ^$ |
|
||||
cut -d' ' -f3 |
|
||||
sed -e "s/^${prefix}//")
|
||||
else
|
||||
dump=$(dumpbin -linkermember:1 ${libname} |
|
||||
sed -e '/public symbols/,$!d' -e '/^ \{1,\}Summary/,$d' -e "s/ \{1,\}${prefix}/ /" -e 's/ \{1,\}/ /g' |
|
||||
tail -n +2 |
|
||||
cut -d' ' -f3)
|
||||
fi
|
||||
|
||||
rm ${libname}
|
||||
|
||||
@@ -121,9 +121,6 @@ list=""
|
||||
for exp in ${regex}; do
|
||||
list="${list}"'
|
||||
'$(echo "${dump}" |
|
||||
sed -e '/public symbols/,$!d' -e '/^ \{1,\}Summary/,$d' -e "s/ \{1,\}${prefix}/ /" -e 's/ \{1,\}/ /g' |
|
||||
tail -n +2 |
|
||||
cut -d' ' -f3 |
|
||||
grep "^${exp}" |
|
||||
sed -e 's/^/ /')
|
||||
done
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
/*.1
|
||||
/*.3
|
||||
/*.html
|
||||
/*.pod
|
||||
/config.texi
|
||||
/avoptions_codec.texi
|
||||
/avoptions_format.texi
|
||||
/fate.txt
|
||||
/print_options
|
||||
+66
-9
@@ -2,19 +2,76 @@ Never assume the API of libav* to be stable unless at least 1 month has passed
|
||||
since the last major version increase or the API was added.
|
||||
|
||||
The last version increases were:
|
||||
libavcodec: 2015-08-28
|
||||
libavdevice: 2015-08-28
|
||||
libavfilter: 2015-08-28
|
||||
libavformat: 2015-08-28
|
||||
libavresample: 2015-08-28
|
||||
libpostproc: 2015-08-28
|
||||
libswresample: 2015-08-28
|
||||
libswscale: 2015-08-28
|
||||
libavutil: 2015-08-28
|
||||
libavcodec: 2017-10-21
|
||||
libavdevice: 2017-10-21
|
||||
libavfilter: 2017-10-21
|
||||
libavformat: 2017-10-21
|
||||
libavresample: 2017-10-21
|
||||
libpostproc: 2017-10-21
|
||||
libswresample: 2017-10-21
|
||||
libswscale: 2017-10-21
|
||||
libavutil: 2017-10-21
|
||||
|
||||
|
||||
API changes, most recent first:
|
||||
|
||||
2018-01-xx - xxxxxxx - lavfi 7.11.101 - avfilter.h
|
||||
Deprecate avfilter_link_get_channels(). Use av_buffersink_get_channels().
|
||||
|
||||
2017-xx-xx - xxxxxxx - lavr 4.0.0 - avresample.h
|
||||
Deprecate the entire library. Merged years ago to provide compatibility
|
||||
with Libav, it remained unmaintained by the FFmpeg project and duplicated
|
||||
functionality provided by libswresample.
|
||||
|
||||
In order to improve consistency and reduce attack surface, it has been deprecated.
|
||||
Users of this library are asked to migrate to libswresample, which, as well as
|
||||
providing more functionality, is faster and has higher accuracy.
|
||||
|
||||
2017-xx-xx - xxxxxxx - lavc 58.9.100 - avcodec.h
|
||||
Deprecate av_lockmgr_register(). You need to build FFmpeg with threading
|
||||
support enabled to get basic thread-safety (which is the default build
|
||||
configuration).
|
||||
|
||||
2017-12-xx - xxxxxxx - lavu 56.7.100 - cpu.h
|
||||
AVX-512 flags added.
|
||||
|
||||
2017-xx-xx - xxxxxxx - lavc 58.8.100 - avcodec.h
|
||||
The MediaCodec decoders now support AVCodecContext.hw_device_ctx.
|
||||
|
||||
2017-xx-xx - xxxxxxx - lavu 56.6.100 - hwcontext.h hwcontext_mediacodec.h
|
||||
Add AV_HWDEVICE_TYPE_MEDIACODEC and a new installed header with
|
||||
MediaCodec-specific hwcontext definitions.
|
||||
|
||||
2017-xx-xx - xxxxxxc - lavc 58.7.100 - avcodec.h
|
||||
Add AV_CODEC_CAP_HARDWARE, AV_CODEC_CAP_HYBRID, and AVCodec.wrapper_name,
|
||||
and mark all AVCodecs accordingly.
|
||||
|
||||
2017-xx-xx - xxxxxxx - lavu 56.4.100 / 56.7.0 - stereo3d.h
|
||||
Add view field to AVStereo3D structure and AVStereo3DView enum.
|
||||
|
||||
2017-xx-xx - xxxxxxx - lavc 58.6.100 - avcodec.h
|
||||
Add const to AVCodecContext.hwaccel.
|
||||
|
||||
2017-11-xx - xxxxxxx - lavc 58.5.100 - avcodec.h
|
||||
Deprecate user visibility of the AVHWAccel structure and the functions
|
||||
av_register_hwaccel() and av_hwaccel_next().
|
||||
|
||||
2017-11-xx - xxxxxxx - lavc 58.4.100 - avcodec.h
|
||||
Add AVCodecHWConfig and avcodec_get_hw_config().
|
||||
|
||||
2017-11-22 - 3650cb2dfa - lavu 55.3.100 - opencl.h
|
||||
Remove experimental OpenCL API (av_opencl_*).
|
||||
|
||||
2017-11-22 - b25d8ef0a7 - lavu 55.2.100 - hwcontext.h hwcontext_opencl.h
|
||||
Add AV_HWDEVICE_TYPE_OPENCL and a new installed header with
|
||||
OpenCL-specific hwcontext definitions.
|
||||
|
||||
2017-11-22 - a050f56c09 - lavu 55.1.100 - pixfmt.h
|
||||
Add AV_PIX_FMT_OPENCL.
|
||||
|
||||
2017-11-11 - 48e4eda11d - lavc 58.3.100 - avcodec.h
|
||||
Add avcodec_get_hw_frames_parameters().
|
||||
|
||||
-------- 8< --------- FFmpeg 3.4 was cut here -------- 8< ---------
|
||||
|
||||
2017-09-28 - b6cf66ae1c - lavc 57.106.104 - avcodec.h
|
||||
|
||||
+1
-1
@@ -38,7 +38,7 @@ PROJECT_NAME = FFmpeg
|
||||
# could be handy for archiving the generated documentation or if some version
|
||||
# control system is used.
|
||||
|
||||
PROJECT_NUMBER = 3.4
|
||||
PROJECT_NUMBER =
|
||||
|
||||
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
||||
# for a project that appears at the top of each page and should give viewer a
|
||||
|
||||
@@ -92,6 +92,69 @@ When this option is enabled, the long-term headers are removed from the
|
||||
bitstream after extraction.
|
||||
@end table
|
||||
|
||||
@section h264_metadata
|
||||
|
||||
Modify metadata embedded in an H.264 stream.
|
||||
|
||||
@table @option
|
||||
@item aud
|
||||
Insert or remove AUD NAL units in all access units of the stream.
|
||||
|
||||
@table @samp
|
||||
@item insert
|
||||
@item remove
|
||||
@end table
|
||||
|
||||
@item sample_aspect_ratio
|
||||
Set the sample aspect ratio of the stream in the VUI parameters.
|
||||
|
||||
@item video_format
|
||||
@item video_full_range_flag
|
||||
Set the video format in the stream (see H.264 section E.2.1 and
|
||||
table E-2).
|
||||
|
||||
@item colour_primaries
|
||||
@item transfer_characteristics
|
||||
@item matrix_coefficients
|
||||
Set the colour description in the stream (see H.264 section E.2.1
|
||||
and tables E-3, E-4 and E-5).
|
||||
|
||||
@item chroma_sample_loc_type
|
||||
Set the chroma sample location in the stream (see H.264 section
|
||||
E.2.1 and figure E-1).
|
||||
|
||||
@item tick_rate
|
||||
Set the tick rate (num_units_in_tick / time_scale) in the VUI
|
||||
parameters. This is the smallest time unit representable in the
|
||||
stream, and in many cases represents the field rate of the stream
|
||||
(double the frame rate).
|
||||
@item fixed_frame_rate_flag
|
||||
Set whether the stream has fixed framerate - typically this indicates
|
||||
that the framerate is exactly half the tick rate, but the exact
|
||||
meaning is dependent on interlacing and the picture structure (see
|
||||
H.264 section E.2.1 and table E-6).
|
||||
|
||||
@item crop_left
|
||||
@item crop_right
|
||||
@item crop_top
|
||||
@item crop_bottom
|
||||
Set the frame cropping offsets in the SPS. These values will replace
|
||||
the current ones if the stream is already cropped.
|
||||
|
||||
These fields are set in pixels. Note that some sizes may not be
|
||||
representable if the chroma is subsampled or the stream is interlaced
|
||||
(see H.264 section 7.4.2.1.1).
|
||||
|
||||
@item sei_user_data
|
||||
Insert a string as SEI unregistered user data. The argument must
|
||||
be of the form @emph{UUID+string}, where the UUID is as hex digits
|
||||
possibly separated by hyphens, and the string can be anything.
|
||||
|
||||
For example, @samp{086f3693-b7b3-4f2c-9653-21492feee5b8+hello} will
|
||||
insert the string ``hello'' associated with the given UUID.
|
||||
|
||||
@end table
|
||||
|
||||
@section h264_mp4toannexb
|
||||
|
||||
Convert an H.264 bitstream from length prefixed mode to start code
|
||||
@@ -111,6 +174,69 @@ ffmpeg -i INPUT.mp4 -codec copy -bsf:v h264_mp4toannexb OUTPUT.ts
|
||||
Please note that this filter is auto-inserted for MPEG-TS (muxer
|
||||
@code{mpegts}) and raw H.264 (muxer @code{h264}) output formats.
|
||||
|
||||
@section h264_redundant_pps
|
||||
|
||||
This applies a specific fixup to some Blu-ray streams which contain
|
||||
redundant PPSs modifying irrelevant parameters of the stream which
|
||||
confuse other transformations which require correct extradata.
|
||||
|
||||
A new single global PPS is created, and all of the redundant PPSs
|
||||
within the stream are removed.
|
||||
|
||||
@section hevc_metadata
|
||||
|
||||
Modify metadata embedded in an HEVC stream.
|
||||
|
||||
@table @option
|
||||
@item aud
|
||||
Insert or remove AUD NAL units in all access units of the stream.
|
||||
|
||||
@table @samp
|
||||
@item insert
|
||||
@item remove
|
||||
@end table
|
||||
|
||||
@item sample_aspect_ratio
|
||||
Set the sample aspect ratio in the stream in the VUI parameters.
|
||||
|
||||
@item video_format
|
||||
@item video_full_range_flag
|
||||
Set the video format in the stream (see H.265 section E.3.1 and
|
||||
table E.2).
|
||||
|
||||
@item colour_primaries
|
||||
@item transfer_characteristics
|
||||
@item matrix_coefficients
|
||||
Set the colour description in the stream (see H.265 section E.3.1
|
||||
and tables E.3, E.4 and E.5).
|
||||
|
||||
@item chroma_sample_loc_type
|
||||
Set the chroma sample location in the stream (see H.265 section
|
||||
E.3.1 and figure E.1).
|
||||
|
||||
@item tick_rate
|
||||
Set the tick rate in the VPS and VUI parameters (num_units_in_tick /
|
||||
time_scale). Combined with @option{num_ticks_poc_diff_one}, this can
|
||||
set a constant framerate in the stream. Note that it is likely to be
|
||||
overridden by container parameters when the stream is in a container.
|
||||
|
||||
@item num_ticks_poc_diff_one
|
||||
Set poc_proportional_to_timing_flag in VPS and VUI and use this value
|
||||
to set num_ticks_poc_diff_one_minus1 (see H.265 sections 7.4.3.1 and
|
||||
E.3.1). Ignored if @option{tick_rate} is not also set.
|
||||
|
||||
@item crop_left
|
||||
@item crop_right
|
||||
@item crop_top
|
||||
@item crop_bottom
|
||||
Set the conformance window cropping offsets in the SPS. These values
|
||||
will replace the current ones if the stream is already cropped.
|
||||
|
||||
These fields are set in pixels. Note that some sizes may not be
|
||||
representable if the chroma is subsampled (H.265 section 7.4.3.2.1).
|
||||
|
||||
@end table
|
||||
|
||||
@section hevc_mp4toannexb
|
||||
|
||||
Convert an HEVC/H.265 bitstream from length prefixed mode to start code
|
||||
@@ -198,6 +324,42 @@ See also the @ref{text2movsub} filter.
|
||||
|
||||
Decompress non-standard compressed MP3 audio headers.
|
||||
|
||||
@section mpeg2_metadata
|
||||
|
||||
Modify metadata embedded in an MPEG-2 stream.
|
||||
|
||||
@table @option
|
||||
@item display_aspect_ratio
|
||||
Set the display aspect ratio in the stream.
|
||||
|
||||
The following fixed values are supported:
|
||||
@table @option
|
||||
@item 4/3
|
||||
@item 16/9
|
||||
@item 221/100
|
||||
@end table
|
||||
Any other value will result in square pixels being signalled instead
|
||||
(see H.262 section 6.3.3 and table 6-3).
|
||||
|
||||
@item frame_rate
|
||||
Set the frame rate in the stream. This is constructed from a table
|
||||
of known values combined with a small multiplier and divisor - if
|
||||
the supplied value is not exactly representable, the nearest
|
||||
representable value will be used instead (see H.262 section 6.3.3
|
||||
and table 6-4).
|
||||
|
||||
@item video_format
|
||||
Set the video format in the stream (see H.262 section 6.3.6 and
|
||||
table 6-6).
|
||||
|
||||
@item colour_primaries
|
||||
@item transfer_characteristics
|
||||
@item matrix_coefficients
|
||||
Set the colour description in the stream (see H.262 section 6.3.6
|
||||
and tables 6-7, 6-8 and 6-9).
|
||||
|
||||
@end table
|
||||
|
||||
@section mpeg4_unpack_bframes
|
||||
|
||||
Unpack DivX-style packed B-frames.
|
||||
@@ -275,6 +437,14 @@ codec) with metadata headers.
|
||||
|
||||
See also the @ref{mov2textsub} filter.
|
||||
|
||||
@section trace_headers
|
||||
|
||||
Log trace output containing all syntax elements in the coded stream
|
||||
headers (everything above the level of individual coded blocks).
|
||||
This can be useful for debugging low-level stream issues.
|
||||
|
||||
Supports H.264, H.265 and MPEG-2.
|
||||
|
||||
@section vp9_superframe
|
||||
|
||||
Merge VP9 invisible (alt-ref) frames back into VP9 superframes. This
|
||||
|
||||
@@ -44,12 +44,6 @@ Use 1/4 pel motion compensation.
|
||||
Use loop filter.
|
||||
@item qscale
|
||||
Use fixed qscale.
|
||||
@item gmc
|
||||
Use gmc.
|
||||
@item mv0
|
||||
Always try a mb with mv=<0,0>.
|
||||
@item input_preserved
|
||||
|
||||
@item pass1
|
||||
Use internal 2pass ratecontrol in first pass mode.
|
||||
@item pass2
|
||||
@@ -62,8 +56,6 @@ Do not draw edges.
|
||||
Set error[?] variables during encoding.
|
||||
@item truncated
|
||||
|
||||
@item naq
|
||||
Normalize adaptive quantization.
|
||||
@item ildct
|
||||
Use interlaced DCT.
|
||||
@item low_delay
|
||||
@@ -506,21 +498,6 @@ threading operations
|
||||
skip motion compensation
|
||||
@end table
|
||||
|
||||
@item vismv @var{integer} (@emph{decoding,video})
|
||||
Visualize motion vectors (MVs).
|
||||
|
||||
This option is deprecated, see the codecview filter instead.
|
||||
|
||||
Possible values:
|
||||
@table @samp
|
||||
@item pf
|
||||
forward predicted MVs of P-frames
|
||||
@item bf
|
||||
forward predicted MVs of B-frames
|
||||
@item bb
|
||||
backward predicted MVs of B-frames
|
||||
@end table
|
||||
|
||||
@item cmp @var{integer} (@emph{encoding,video})
|
||||
Set full pel me compare function.
|
||||
|
||||
@@ -757,8 +734,6 @@ Set context model.
|
||||
|
||||
@item slice_flags @var{integer}
|
||||
|
||||
@item xvmc_acceleration @var{integer}
|
||||
|
||||
@item mbd @var{integer} (@emph{encoding,video})
|
||||
Set macroblock decision algorithm (high quality mode).
|
||||
|
||||
|
||||
@@ -25,13 +25,6 @@ enabled decoders.
|
||||
A description of some of the currently available video decoders
|
||||
follows.
|
||||
|
||||
@section hevc
|
||||
|
||||
HEVC / H.265 decoder.
|
||||
|
||||
Note: the @option{skip_loop_filter} option has effect only at level
|
||||
@code{all}.
|
||||
|
||||
@section rawvideo
|
||||
|
||||
Raw video decoder.
|
||||
|
||||
@@ -316,6 +316,14 @@ segment index to start live streams at (negative values are from the end).
|
||||
@item max_reload
|
||||
Maximum number of times a insufficient list is attempted to be reloaded.
|
||||
Default value is 1000.
|
||||
|
||||
@item http_persistent
|
||||
Use persistent HTTP connections. Applicable only for HTTP streams.
|
||||
Enabled by default.
|
||||
|
||||
@item http_multiple
|
||||
Use multiple HTTP connections for downloading HTTP segments.
|
||||
Enabled by default for HTTP/1.1 servers.
|
||||
@end table
|
||||
|
||||
@section image2
|
||||
|
||||
+47
-32
@@ -10,9 +10,7 @@
|
||||
|
||||
@contents
|
||||
|
||||
@chapter Developers Guide
|
||||
|
||||
@section Notes for external developers
|
||||
@chapter Notes for external developers
|
||||
|
||||
This document is mostly useful for internal FFmpeg developers.
|
||||
External developers who need to use the API in their application should
|
||||
@@ -30,7 +28,7 @@ For more detailed legal information about the use of FFmpeg in
|
||||
external programs read the @file{LICENSE} file in the source tree and
|
||||
consult @url{https://ffmpeg.org/legal.html}.
|
||||
|
||||
@section Contributing
|
||||
@chapter Contributing
|
||||
|
||||
There are 3 ways by which code gets into FFmpeg.
|
||||
@itemize @bullet
|
||||
@@ -47,9 +45,9 @@ The developer making the commit and the author are responsible for their changes
|
||||
and should try to fix issues their commit causes.
|
||||
|
||||
@anchor{Coding Rules}
|
||||
@section Coding Rules
|
||||
@chapter Coding Rules
|
||||
|
||||
@subsection Code formatting conventions
|
||||
@section Code formatting conventions
|
||||
|
||||
There are the following guidelines regarding the indentation in files:
|
||||
|
||||
@@ -74,7 +72,7 @@ The presentation is one inspired by 'indent -i4 -kr -nut'.
|
||||
The main priority in FFmpeg is simplicity and small code size in order to
|
||||
minimize the bug count.
|
||||
|
||||
@subsection Comments
|
||||
@section Comments
|
||||
Use the JavaDoc/Doxygen format (see examples below) so that code documentation
|
||||
can be generated automatically. All nontrivial functions should have a comment
|
||||
above them explaining what the function does, even if it is just one sentence.
|
||||
@@ -114,7 +112,7 @@ int myfunc(int my_parameter)
|
||||
...
|
||||
@end example
|
||||
|
||||
@subsection C language features
|
||||
@section C language features
|
||||
|
||||
FFmpeg is programmed in the ISO C90 language with a few additional
|
||||
features from ISO C99, namely:
|
||||
@@ -160,7 +158,7 @@ mixing statements and declarations;
|
||||
GCC statement expressions (@samp{(x = (@{ int y = 4; y; @})}).
|
||||
@end itemize
|
||||
|
||||
@subsection Naming conventions
|
||||
@section Naming conventions
|
||||
All names should be composed with underscores (_), not CamelCase. For example,
|
||||
@samp{avfilter_get_video_buffer} is an acceptable function name and
|
||||
@samp{AVFilterGetVideo} is not. The exception from this are type names, like
|
||||
@@ -184,7 +182,7 @@ e.g. @samp{ff_w64_demuxer}.
|
||||
@item
|
||||
For variables and functions visible outside of file scope, used internally
|
||||
across multiple libraries, use @code{avpriv_} as prefix, for example,
|
||||
@samp{avpriv_aac_parse_header}.
|
||||
@samp{avpriv_report_missing_feature}.
|
||||
|
||||
@item
|
||||
Each library has its own prefix for public symbols, in addition to the
|
||||
@@ -204,7 +202,7 @@ letter as they are reserved by the C standard. Names starting with @code{_}
|
||||
are reserved at the file level and may not be used for externally visible
|
||||
symbols. If in doubt, just avoid names starting with @code{_} altogether.
|
||||
|
||||
@subsection Miscellaneous conventions
|
||||
@section Miscellaneous conventions
|
||||
|
||||
@itemize @bullet
|
||||
@item
|
||||
@@ -216,7 +214,7 @@ Casts should be used only when necessary. Unneeded parentheses
|
||||
should also be avoided if they don't make the code easier to understand.
|
||||
@end itemize
|
||||
|
||||
@subsection Editor configuration
|
||||
@section Editor configuration
|
||||
In order to configure Vim to follow FFmpeg formatting conventions, paste
|
||||
the following snippet into your @file{.vimrc}:
|
||||
@example
|
||||
@@ -249,9 +247,9 @@ For Emacs, add these roughly equivalent lines to your @file{.emacs.d/init.el}:
|
||||
(setq c-default-style "ffmpeg")
|
||||
@end lisp
|
||||
|
||||
@section Development Policy
|
||||
@chapter Development Policy
|
||||
|
||||
@subsection Patches/Committing
|
||||
@section Patches/Committing
|
||||
@subheading Licenses for patches must be compatible with FFmpeg.
|
||||
Contributions should be licensed under the
|
||||
@uref{http://www.gnu.org/licenses/lgpl-2.1.html, LGPL 2.1},
|
||||
@@ -350,7 +348,7 @@ time-frame (12h for build failures and security fixes, 3 days small changes,
|
||||
1 week for big patches) then commit your patch if you think it is OK.
|
||||
Also note, the maintainer can simply ask for more time to review!
|
||||
|
||||
@subsection Code
|
||||
@section Code
|
||||
@subheading API/ABI changes should be discussed before they are made.
|
||||
Do not change behavior of the programs (renaming options etc) or public
|
||||
API or ABI without first discussing it on the ffmpeg-devel mailing list.
|
||||
@@ -381,12 +379,29 @@ Never write to unallocated memory, never write over the end of arrays,
|
||||
always check values read from some untrusted source before using them
|
||||
as array index or other risky things.
|
||||
|
||||
@subsection Documentation/Other
|
||||
@section Documentation/Other
|
||||
@subheading Subscribe to the ffmpeg-devel mailing list.
|
||||
It is important to be subscribed to the
|
||||
@uref{https://lists.ffmpeg.org/mailman/listinfo/ffmpeg-devel, ffmpeg-devel}
|
||||
mailing list. Almost any non-trivial patch is to be sent there for review.
|
||||
Other developers may have comments about your contribution. We expect you see
|
||||
those comments, and to improve it if requested. (N.B. Experienced committers
|
||||
have other channels, and may sometimes skip review for trivial fixes.) Also,
|
||||
discussion here about bug fixes and FFmpeg improvements by other developers may
|
||||
be helpful information for you. Finally, by being a list subscriber, your
|
||||
contribution will be posted immediately to the list, without the moderation
|
||||
hold which messages from non-subscribers experience.
|
||||
|
||||
However, it is more important to the project that we receive your patch than
|
||||
that you be subscribed to the ffmpeg-devel list. If you have a patch, and don't
|
||||
want to subscribe and discuss the patch, then please do send it to the list
|
||||
anyway.
|
||||
|
||||
@subheading Subscribe to the ffmpeg-cvslog mailing list.
|
||||
It is important to do this as the diffs of all commits are sent there and
|
||||
reviewed by all the other developers. Bugs and possible improvements or
|
||||
general questions regarding commits are discussed there. We expect you to
|
||||
react if problems with your code are uncovered.
|
||||
Diffs of all commits are sent to the
|
||||
@uref{https://lists.ffmpeg.org/mailman/listinfo/ffmpeg-cvslog, ffmpeg-cvslog}
|
||||
mailing list. Some developers read this list to review all code base changes
|
||||
from all sources. Subscribing to this list is not mandatory.
|
||||
|
||||
@subheading Keep the documentation up to date.
|
||||
Update the documentation if you change behavior or add features. If you are
|
||||
@@ -406,7 +421,7 @@ finding a new maintainer and also don't forget to update the @file{MAINTAINERS}
|
||||
|
||||
We think our rules are not too hard. If you have comments, contact us.
|
||||
|
||||
@section Code of conduct
|
||||
@chapter Code of conduct
|
||||
|
||||
Be friendly and respectful towards others and third parties.
|
||||
Treat others the way you yourself want to be treated.
|
||||
@@ -436,7 +451,7 @@ Finally, keep in mind the immortal words of Bill and Ted,
|
||||
"Be excellent to each other."
|
||||
|
||||
@anchor{Submitting patches}
|
||||
@section Submitting patches
|
||||
@chapter Submitting patches
|
||||
|
||||
First, read the @ref{Coding Rules} above if you did not yet, in particular
|
||||
the rules regarding patch submission.
|
||||
@@ -485,7 +500,7 @@ Give us a few days to react. But if some time passes without reaction,
|
||||
send a reminder by email. Your patch should eventually be dealt with.
|
||||
|
||||
|
||||
@section New codecs or formats checklist
|
||||
@chapter New codecs or formats checklist
|
||||
|
||||
@enumerate
|
||||
@item
|
||||
@@ -537,7 +552,7 @@ Did you make sure it compiles standalone, i.e. with
|
||||
@end enumerate
|
||||
|
||||
|
||||
@section patch submission checklist
|
||||
@chapter Patch submission checklist
|
||||
|
||||
@enumerate
|
||||
@item
|
||||
@@ -650,7 +665,7 @@ Test your code with valgrind and or Address Sanitizer to ensure it's free
|
||||
of leaks, out of array accesses, etc.
|
||||
@end enumerate
|
||||
|
||||
@section Patch review process
|
||||
@chapter Patch review process
|
||||
|
||||
All patches posted to ffmpeg-devel will be reviewed, unless they contain a
|
||||
clear note that the patch is not for the git master branch.
|
||||
@@ -681,7 +696,7 @@ to be reviewed, please consider helping to review other patches, that is a great
|
||||
way to get everyone's patches reviewed sooner.
|
||||
|
||||
@anchor{Regression tests}
|
||||
@section Regression tests
|
||||
@chapter Regression tests
|
||||
|
||||
Before submitting a patch (or committing to the repository), you should at least
|
||||
test that you did not break anything.
|
||||
@@ -692,7 +707,7 @@ Running 'make fate' accomplishes this, please see @url{fate.html} for details.
|
||||
this case, the reference results of the regression tests shall be modified
|
||||
accordingly].
|
||||
|
||||
@subsection Adding files to the fate-suite dataset
|
||||
@section Adding files to the fate-suite dataset
|
||||
|
||||
When there is no muxer or encoder available to generate test media for a
|
||||
specific test then the media has to be included in the fate-suite.
|
||||
@@ -703,7 +718,7 @@ Once you have a working fate test and fate sample, provide in the commit
|
||||
message or introductory message for the patch series that you post to
|
||||
the ffmpeg-devel mailing list, a direct link to download the sample media.
|
||||
|
||||
@subsection Visualizing Test Coverage
|
||||
@section Visualizing Test Coverage
|
||||
|
||||
The FFmpeg build system allows visualizing the test coverage in an easy
|
||||
manner with the coverage tools @code{gcov}/@code{lcov}. This involves
|
||||
@@ -730,7 +745,7 @@ You can use the command @code{make lcov-reset} to reset the coverage
|
||||
measurements. You will need to rerun @code{make lcov} after running a
|
||||
new test.
|
||||
|
||||
@subsection Using Valgrind
|
||||
@section Using Valgrind
|
||||
|
||||
The configure script provides a shortcut for using valgrind to spot bugs
|
||||
related to memory handling. Just add the option
|
||||
@@ -744,7 +759,7 @@ In case you need finer control over how valgrind is invoked, use the
|
||||
your configure line instead.
|
||||
|
||||
@anchor{Release process}
|
||||
@section Release process
|
||||
@chapter Release process
|
||||
|
||||
FFmpeg maintains a set of @strong{release branches}, which are the
|
||||
recommended deliverable for system integrators and distributors (such as
|
||||
@@ -776,7 +791,7 @@ adjustments to the symbol versioning file. Please discuss such changes
|
||||
on the @strong{ffmpeg-devel} mailing list in time to allow forward planning.
|
||||
|
||||
@anchor{Criteria for Point Releases}
|
||||
@subsection Criteria for Point Releases
|
||||
@section Criteria for Point Releases
|
||||
|
||||
Changes that match the following criteria are valid candidates for
|
||||
inclusion into a point release:
|
||||
@@ -800,7 +815,7 @@ point releases of the same release branch.
|
||||
The order for checking the rules is (1 OR 2 OR 3) AND 4.
|
||||
|
||||
|
||||
@subsection Release Checklist
|
||||
@section Release Checklist
|
||||
|
||||
The release process involves the following steps:
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
/html/
|
||||
+11
-5
@@ -64,7 +64,6 @@ to find an optimal combination by adding or subtracting a specific value from
|
||||
all quantizers and adjusting some individual quantizer a little. Will tune
|
||||
itself based on whether @option{aac_is}, @option{aac_ms} and @option{aac_pns}
|
||||
are enabled.
|
||||
This is the default choice for a coder.
|
||||
|
||||
@item anmr
|
||||
Average noise to mask ratio (ANMR) trellis-based solution.
|
||||
@@ -77,10 +76,10 @@ Not currently recommended.
|
||||
@item fast
|
||||
Constant quantizer method.
|
||||
|
||||
This method sets a constant quantizer for all bands. This is the fastest of all
|
||||
the methods and has no rate control or support for @option{aac_is} or
|
||||
@option{aac_pns}.
|
||||
Not recommended.
|
||||
Uses a cheaper version of twoloop algorithm that doesn't try to do as many
|
||||
clever adjustments. Worse with low bitrates (less than 64kbps), but is better
|
||||
and much faster at higher bitrates.
|
||||
This is the default choice for a coder
|
||||
|
||||
@end table
|
||||
|
||||
@@ -1681,6 +1680,13 @@ colorspaces:
|
||||
@end table
|
||||
@item row-mt @var{boolean}
|
||||
Enable row based multi-threading.
|
||||
@item tune-content
|
||||
Set content type: default (0), screen (1), film (2).
|
||||
@item corpus-complexity
|
||||
Corpus VBR mode is a variant of standard VBR where the complexity distribution
|
||||
midpoint is passed in rather than calculated for a specific clip or chunk.
|
||||
|
||||
The valid range is [0, 10000]. 0 (default) uses standard VBR.
|
||||
@end table
|
||||
|
||||
@end table
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
/avio_dir_cmd
|
||||
/avio_reading
|
||||
/decode_audio
|
||||
/decode_video
|
||||
/demuxing_decoding
|
||||
/encode_audio
|
||||
/encode_video
|
||||
/extract_mvs
|
||||
/filter_audio
|
||||
/filtering_audio
|
||||
/filtering_video
|
||||
/http_multiclient
|
||||
/hw_decode
|
||||
/metadata
|
||||
/muxing
|
||||
/pc-uninstalled
|
||||
/qsvdec
|
||||
/remuxing
|
||||
/resampling_audio
|
||||
/scaling_video
|
||||
/transcode_aac
|
||||
/transcoding
|
||||
@@ -19,6 +19,7 @@ EXAMPLES-$(CONFIG_RESAMPLING_AUDIO_EXAMPLE) += resampling_audio
|
||||
EXAMPLES-$(CONFIG_SCALING_VIDEO_EXAMPLE) += scaling_video
|
||||
EXAMPLES-$(CONFIG_TRANSCODE_AAC_EXAMPLE) += transcode_aac
|
||||
EXAMPLES-$(CONFIG_TRANSCODING_EXAMPLE) += transcoding
|
||||
EXAMPLES-$(CONFIG_VAAPI_ENCODE_EXAMPLE) += vaapi_encode
|
||||
|
||||
EXAMPLES := $(EXAMPLES-yes:%=doc/examples/%$(PROGSSUF)$(EXESUF))
|
||||
EXAMPLES_G := $(EXAMPLES-yes:%=doc/examples/%$(PROGSSUF)_g$(EXESUF))
|
||||
|
||||
@@ -44,6 +44,8 @@ static int read_packet(void *opaque, uint8_t *buf, int buf_size)
|
||||
struct buffer_data *bd = (struct buffer_data *)opaque;
|
||||
buf_size = FFMIN(buf_size, bd->size);
|
||||
|
||||
if (!buf_size)
|
||||
return AVERROR_EOF;
|
||||
printf("ptr:%p size:%zu\n", bd->ptr, bd->size);
|
||||
|
||||
/* copy internal buffer data to buf */
|
||||
|
||||
@@ -64,13 +64,13 @@ static int init_filter_graph(AVFilterGraph **graph, AVFilterContext **src,
|
||||
{
|
||||
AVFilterGraph *filter_graph;
|
||||
AVFilterContext *abuffer_ctx;
|
||||
AVFilter *abuffer;
|
||||
const AVFilter *abuffer;
|
||||
AVFilterContext *volume_ctx;
|
||||
AVFilter *volume;
|
||||
const AVFilter *volume;
|
||||
AVFilterContext *aformat_ctx;
|
||||
AVFilter *aformat;
|
||||
const AVFilter *aformat;
|
||||
AVFilterContext *abuffersink_ctx;
|
||||
AVFilter *abuffersink;
|
||||
const AVFilter *abuffersink;
|
||||
|
||||
AVDictionary *options_dict = NULL;
|
||||
uint8_t options_str[1024];
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libavfilter/avfiltergraph.h>
|
||||
#include <libavfilter/buffersink.h>
|
||||
#include <libavfilter/buffersrc.h>
|
||||
#include <libavutil/opt.h>
|
||||
@@ -90,8 +89,8 @@ static int init_filters(const char *filters_descr)
|
||||
{
|
||||
char args[512];
|
||||
int ret = 0;
|
||||
AVFilter *abuffersrc = avfilter_get_by_name("abuffer");
|
||||
AVFilter *abuffersink = avfilter_get_by_name("abuffersink");
|
||||
const AVFilter *abuffersrc = avfilter_get_by_name("abuffer");
|
||||
const AVFilter *abuffersink = avfilter_get_by_name("abuffersink");
|
||||
AVFilterInOut *outputs = avfilter_inout_alloc();
|
||||
AVFilterInOut *inputs = avfilter_inout_alloc();
|
||||
static const enum AVSampleFormat out_sample_fmts[] = { AV_SAMPLE_FMT_S16, -1 };
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libavfilter/avfiltergraph.h>
|
||||
#include <libavfilter/buffersink.h>
|
||||
#include <libavfilter/buffersrc.h>
|
||||
#include <libavutil/opt.h>
|
||||
@@ -93,8 +92,8 @@ static int init_filters(const char *filters_descr)
|
||||
{
|
||||
char args[512];
|
||||
int ret = 0;
|
||||
AVFilter *buffersrc = avfilter_get_by_name("buffer");
|
||||
AVFilter *buffersink = avfilter_get_by_name("buffersink");
|
||||
const AVFilter *buffersrc = avfilter_get_by_name("buffer");
|
||||
const AVFilter *buffersink = avfilter_get_by_name("buffersink");
|
||||
AVFilterInOut *outputs = avfilter_inout_alloc();
|
||||
AVFilterInOut *inputs = avfilter_inout_alloc();
|
||||
AVRational time_base = fmt_ctx->streams[video_stream_index]->time_base;
|
||||
|
||||
+22
-32
@@ -44,34 +44,6 @@ static AVBufferRef *hw_device_ctx = NULL;
|
||||
static enum AVPixelFormat hw_pix_fmt;
|
||||
static FILE *output_file = NULL;
|
||||
|
||||
static enum AVPixelFormat find_fmt_by_hw_type(const enum AVHWDeviceType type)
|
||||
{
|
||||
enum AVPixelFormat fmt;
|
||||
|
||||
switch (type) {
|
||||
case AV_HWDEVICE_TYPE_VAAPI:
|
||||
fmt = AV_PIX_FMT_VAAPI;
|
||||
break;
|
||||
case AV_HWDEVICE_TYPE_DXVA2:
|
||||
fmt = AV_PIX_FMT_DXVA2_VLD;
|
||||
break;
|
||||
case AV_HWDEVICE_TYPE_D3D11VA:
|
||||
fmt = AV_PIX_FMT_D3D11;
|
||||
break;
|
||||
case AV_HWDEVICE_TYPE_VDPAU:
|
||||
fmt = AV_PIX_FMT_VDPAU;
|
||||
break;
|
||||
case AV_HWDEVICE_TYPE_VIDEOTOOLBOX:
|
||||
fmt = AV_PIX_FMT_VIDEOTOOLBOX;
|
||||
break;
|
||||
default:
|
||||
fmt = AV_PIX_FMT_NONE;
|
||||
break;
|
||||
}
|
||||
|
||||
return fmt;
|
||||
}
|
||||
|
||||
static int hw_decoder_init(AVCodecContext *ctx, const enum AVHWDeviceType type)
|
||||
{
|
||||
int err = 0;
|
||||
@@ -184,18 +156,22 @@ int main(int argc, char *argv[])
|
||||
AVCodec *decoder = NULL;
|
||||
AVPacket packet;
|
||||
enum AVHWDeviceType type;
|
||||
int i;
|
||||
|
||||
if (argc < 4) {
|
||||
fprintf(stderr, "Usage: %s <vaapi|vdpau|dxva2|d3d11va> <input file> <output file>\n", argv[0]);
|
||||
fprintf(stderr, "Usage: %s <device type> <input file> <output file>\n", argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
av_register_all();
|
||||
|
||||
type = av_hwdevice_find_type_by_name(argv[1]);
|
||||
hw_pix_fmt = find_fmt_by_hw_type(type);
|
||||
if (hw_pix_fmt == -1) {
|
||||
fprintf(stderr, "Cannot support '%s' in this example.\n", argv[1]);
|
||||
if (type == AV_HWDEVICE_TYPE_NONE) {
|
||||
fprintf(stderr, "Device type %s is not supported.\n", argv[1]);
|
||||
fprintf(stderr, "Available device types:");
|
||||
while((type = av_hwdevice_iterate_types(type)) != AV_HWDEVICE_TYPE_NONE)
|
||||
fprintf(stderr, " %s", av_hwdevice_get_type_name(type));
|
||||
fprintf(stderr, "\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -218,6 +194,20 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
video_stream = ret;
|
||||
|
||||
for (i = 0;; i++) {
|
||||
const AVCodecHWConfig *config = avcodec_get_hw_config(decoder, i);
|
||||
if (!config) {
|
||||
fprintf(stderr, "Decoder %s does not support device type %s.\n",
|
||||
decoder->name, av_hwdevice_get_type_name(type));
|
||||
return -1;
|
||||
}
|
||||
if (config->methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX &&
|
||||
config->device_type == type) {
|
||||
hw_pix_fmt = config->pix_fmt;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(decoder_ctx = avcodec_alloc_context3(decoder)))
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
|
||||
@@ -488,9 +488,9 @@ static AVFrame *get_video_frame(OutputStream *ost)
|
||||
}
|
||||
}
|
||||
fill_yuv_image(ost->tmp_frame, ost->next_pts, c->width, c->height);
|
||||
sws_scale(ost->sws_ctx,
|
||||
(const uint8_t * const *)ost->tmp_frame->data, ost->tmp_frame->linesize,
|
||||
0, c->height, ost->frame->data, ost->frame->linesize);
|
||||
sws_scale(ost->sws_ctx, (const uint8_t * const *) ost->tmp_frame->data,
|
||||
ost->tmp_frame->linesize, 0, c->height, ost->frame->data,
|
||||
ost->frame->linesize);
|
||||
} else {
|
||||
fill_yuv_image(ost->frame, ost->next_pts, c->width, c->height);
|
||||
}
|
||||
|
||||
+208
-151
@@ -1,4 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2017 Andreas Unterweger
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
@@ -18,10 +20,11 @@
|
||||
|
||||
/**
|
||||
* @file
|
||||
* simple audio converter
|
||||
* Simple audio converter
|
||||
*
|
||||
* @example transcode_aac.c
|
||||
* Convert an input audio file to AAC in an MP4 container using FFmpeg.
|
||||
* Formats other than MP4 are supported based on the output file extension.
|
||||
* @author Andreas Unterweger (dustsigns@gmail.com)
|
||||
*/
|
||||
|
||||
@@ -40,12 +43,18 @@
|
||||
|
||||
#include "libswresample/swresample.h"
|
||||
|
||||
/** The output bit rate in kbit/s */
|
||||
/* The output bit rate in bit/s */
|
||||
#define OUTPUT_BIT_RATE 96000
|
||||
/** The number of output channels */
|
||||
/* The number of output channels */
|
||||
#define OUTPUT_CHANNELS 2
|
||||
|
||||
/** Open an input file and the required decoder. */
|
||||
/**
|
||||
* Open an input file and the required decoder.
|
||||
* @param filename File to be opened
|
||||
* @param[out] input_format_context Format context of opened file
|
||||
* @param[out] input_codec_context Codec context of opened file
|
||||
* @return Error code (0 if successful)
|
||||
*/
|
||||
static int open_input_file(const char *filename,
|
||||
AVFormatContext **input_format_context,
|
||||
AVCodecContext **input_codec_context)
|
||||
@@ -54,7 +63,7 @@ static int open_input_file(const char *filename,
|
||||
AVCodec *input_codec;
|
||||
int error;
|
||||
|
||||
/** Open the input file to read from it. */
|
||||
/* Open the input file to read from it. */
|
||||
if ((error = avformat_open_input(input_format_context, filename, NULL,
|
||||
NULL)) < 0) {
|
||||
fprintf(stderr, "Could not open input file '%s' (error '%s')\n",
|
||||
@@ -63,7 +72,7 @@ static int open_input_file(const char *filename,
|
||||
return error;
|
||||
}
|
||||
|
||||
/** Get information on the input file (number of streams etc.). */
|
||||
/* Get information on the input file (number of streams etc.). */
|
||||
if ((error = avformat_find_stream_info(*input_format_context, NULL)) < 0) {
|
||||
fprintf(stderr, "Could not open find stream info (error '%s')\n",
|
||||
av_err2str(error));
|
||||
@@ -71,7 +80,7 @@ static int open_input_file(const char *filename,
|
||||
return error;
|
||||
}
|
||||
|
||||
/** Make sure that there is only one stream in the input file. */
|
||||
/* Make sure that there is only one stream in the input file. */
|
||||
if ((*input_format_context)->nb_streams != 1) {
|
||||
fprintf(stderr, "Expected one audio input stream, but found %d\n",
|
||||
(*input_format_context)->nb_streams);
|
||||
@@ -79,14 +88,14 @@ static int open_input_file(const char *filename,
|
||||
return AVERROR_EXIT;
|
||||
}
|
||||
|
||||
/** Find a decoder for the audio stream. */
|
||||
/* Find a decoder for the audio stream. */
|
||||
if (!(input_codec = avcodec_find_decoder((*input_format_context)->streams[0]->codecpar->codec_id))) {
|
||||
fprintf(stderr, "Could not find input codec\n");
|
||||
avformat_close_input(input_format_context);
|
||||
return AVERROR_EXIT;
|
||||
}
|
||||
|
||||
/** allocate a new decoding context */
|
||||
/* Allocate a new decoding context. */
|
||||
avctx = avcodec_alloc_context3(input_codec);
|
||||
if (!avctx) {
|
||||
fprintf(stderr, "Could not allocate a decoding context\n");
|
||||
@@ -94,7 +103,7 @@ static int open_input_file(const char *filename,
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
|
||||
/** initialize the stream parameters with demuxer information */
|
||||
/* Initialize the stream parameters with demuxer information. */
|
||||
error = avcodec_parameters_to_context(avctx, (*input_format_context)->streams[0]->codecpar);
|
||||
if (error < 0) {
|
||||
avformat_close_input(input_format_context);
|
||||
@@ -102,7 +111,7 @@ static int open_input_file(const char *filename,
|
||||
return error;
|
||||
}
|
||||
|
||||
/** Open the decoder for the audio stream to use it later. */
|
||||
/* Open the decoder for the audio stream to use it later. */
|
||||
if ((error = avcodec_open2(avctx, input_codec, NULL)) < 0) {
|
||||
fprintf(stderr, "Could not open input codec (error '%s')\n",
|
||||
av_err2str(error));
|
||||
@@ -111,7 +120,7 @@ static int open_input_file(const char *filename,
|
||||
return error;
|
||||
}
|
||||
|
||||
/** Save the decoder context for easier access later. */
|
||||
/* Save the decoder context for easier access later. */
|
||||
*input_codec_context = avctx;
|
||||
|
||||
return 0;
|
||||
@@ -121,6 +130,11 @@ static int open_input_file(const char *filename,
|
||||
* Open an output file and the required encoder.
|
||||
* Also set some basic encoder parameters.
|
||||
* Some of these parameters are based on the input file's parameters.
|
||||
* @param filename File to be opened
|
||||
* @param input_codec_context Codec context of input file
|
||||
* @param[out] output_format_context Format context of output file
|
||||
* @param[out] output_codec_context Codec context of output file
|
||||
* @return Error code (0 if successful)
|
||||
*/
|
||||
static int open_output_file(const char *filename,
|
||||
AVCodecContext *input_codec_context,
|
||||
@@ -133,7 +147,7 @@ static int open_output_file(const char *filename,
|
||||
AVCodec *output_codec = NULL;
|
||||
int error;
|
||||
|
||||
/** Open the output file to write to it. */
|
||||
/* Open the output file to write to it. */
|
||||
if ((error = avio_open(&output_io_context, filename,
|
||||
AVIO_FLAG_WRITE)) < 0) {
|
||||
fprintf(stderr, "Could not open output file '%s' (error '%s')\n",
|
||||
@@ -141,16 +155,16 @@ static int open_output_file(const char *filename,
|
||||
return error;
|
||||
}
|
||||
|
||||
/** Create a new format context for the output container format. */
|
||||
/* Create a new format context for the output container format. */
|
||||
if (!(*output_format_context = avformat_alloc_context())) {
|
||||
fprintf(stderr, "Could not allocate output format context\n");
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
|
||||
/** Associate the output file (pointer) with the container format context. */
|
||||
/* Associate the output file (pointer) with the container format context. */
|
||||
(*output_format_context)->pb = output_io_context;
|
||||
|
||||
/** Guess the desired container format based on the file extension. */
|
||||
/* Guess the desired container format based on the file extension. */
|
||||
if (!((*output_format_context)->oformat = av_guess_format(NULL, filename,
|
||||
NULL))) {
|
||||
fprintf(stderr, "Could not find output file format\n");
|
||||
@@ -160,13 +174,13 @@ static int open_output_file(const char *filename,
|
||||
av_strlcpy((*output_format_context)->filename, filename,
|
||||
sizeof((*output_format_context)->filename));
|
||||
|
||||
/** Find the encoder to be used by its name. */
|
||||
/* Find the encoder to be used by its name. */
|
||||
if (!(output_codec = avcodec_find_encoder(AV_CODEC_ID_AAC))) {
|
||||
fprintf(stderr, "Could not find an AAC encoder.\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/** Create a new audio stream in the output file container. */
|
||||
/* Create a new audio stream in the output file container. */
|
||||
if (!(stream = avformat_new_stream(*output_format_context, NULL))) {
|
||||
fprintf(stderr, "Could not create new stream\n");
|
||||
error = AVERROR(ENOMEM);
|
||||
@@ -180,31 +194,27 @@ static int open_output_file(const char *filename,
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the basic encoder parameters.
|
||||
* The input file's sample rate is used to avoid a sample rate conversion.
|
||||
*/
|
||||
/* Set the basic encoder parameters.
|
||||
* The input file's sample rate is used to avoid a sample rate conversion. */
|
||||
avctx->channels = OUTPUT_CHANNELS;
|
||||
avctx->channel_layout = av_get_default_channel_layout(OUTPUT_CHANNELS);
|
||||
avctx->sample_rate = input_codec_context->sample_rate;
|
||||
avctx->sample_fmt = output_codec->sample_fmts[0];
|
||||
avctx->bit_rate = OUTPUT_BIT_RATE;
|
||||
|
||||
/** Allow the use of the experimental AAC encoder */
|
||||
/* Allow the use of the experimental AAC encoder. */
|
||||
avctx->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
|
||||
|
||||
/** Set the sample rate for the container. */
|
||||
/* Set the sample rate for the container. */
|
||||
stream->time_base.den = input_codec_context->sample_rate;
|
||||
stream->time_base.num = 1;
|
||||
|
||||
/**
|
||||
* Some container formats (like MP4) require global headers to be present
|
||||
* Mark the encoder so that it behaves accordingly.
|
||||
*/
|
||||
/* Some container formats (like MP4) require global headers to be present.
|
||||
* Mark the encoder so that it behaves accordingly. */
|
||||
if ((*output_format_context)->oformat->flags & AVFMT_GLOBALHEADER)
|
||||
avctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
|
||||
|
||||
/** Open the encoder for the audio stream to use it later. */
|
||||
/* Open the encoder for the audio stream to use it later. */
|
||||
if ((error = avcodec_open2(avctx, output_codec, NULL)) < 0) {
|
||||
fprintf(stderr, "Could not open output codec (error '%s')\n",
|
||||
av_err2str(error));
|
||||
@@ -217,7 +227,7 @@ static int open_output_file(const char *filename,
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/** Save the encoder context for easier access later. */
|
||||
/* Save the encoder context for easier access later. */
|
||||
*output_codec_context = avctx;
|
||||
|
||||
return 0;
|
||||
@@ -230,16 +240,23 @@ cleanup:
|
||||
return error < 0 ? error : AVERROR_EXIT;
|
||||
}
|
||||
|
||||
/** Initialize one data packet for reading or writing. */
|
||||
/**
|
||||
* Initialize one data packet for reading or writing.
|
||||
* @param packet Packet to be initialized
|
||||
*/
|
||||
static void init_packet(AVPacket *packet)
|
||||
{
|
||||
av_init_packet(packet);
|
||||
/** Set the packet data and size so that it is recognized as being empty. */
|
||||
/* Set the packet data and size so that it is recognized as being empty. */
|
||||
packet->data = NULL;
|
||||
packet->size = 0;
|
||||
}
|
||||
|
||||
/** Initialize one audio frame for reading from the input file */
|
||||
/**
|
||||
* Initialize one audio frame for reading from the input file.
|
||||
* @param[out] frame Frame to be initialized
|
||||
* @return Error code (0 if successful)
|
||||
*/
|
||||
static int init_input_frame(AVFrame **frame)
|
||||
{
|
||||
if (!(*frame = av_frame_alloc())) {
|
||||
@@ -253,6 +270,10 @@ static int init_input_frame(AVFrame **frame)
|
||||
* Initialize the audio resampler based on the input and output codec settings.
|
||||
* If the input and output sample formats differ, a conversion is required
|
||||
* libswresample takes care of this, but requires initialization.
|
||||
* @param input_codec_context Codec context of the input file
|
||||
* @param output_codec_context Codec context of the output file
|
||||
* @param[out] resample_context Resample context for the required conversion
|
||||
* @return Error code (0 if successful)
|
||||
*/
|
||||
static int init_resampler(AVCodecContext *input_codec_context,
|
||||
AVCodecContext *output_codec_context,
|
||||
@@ -260,7 +281,7 @@ static int init_resampler(AVCodecContext *input_codec_context,
|
||||
{
|
||||
int error;
|
||||
|
||||
/**
|
||||
/*
|
||||
* Create a resampler context for the conversion.
|
||||
* Set the conversion parameters.
|
||||
* Default channel layouts based on the number of channels
|
||||
@@ -279,14 +300,14 @@ static int init_resampler(AVCodecContext *input_codec_context,
|
||||
fprintf(stderr, "Could not allocate resample context\n");
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
/**
|
||||
/*
|
||||
* Perform a sanity check so that the number of converted samples is
|
||||
* not greater than the number of samples to be converted.
|
||||
* If the sample rates differ, this case has to be handled differently
|
||||
*/
|
||||
av_assert0(output_codec_context->sample_rate == input_codec_context->sample_rate);
|
||||
|
||||
/** Open the resampler with the specified parameters. */
|
||||
/* Open the resampler with the specified parameters. */
|
||||
if ((error = swr_init(*resample_context)) < 0) {
|
||||
fprintf(stderr, "Could not open resample context\n");
|
||||
swr_free(resample_context);
|
||||
@@ -295,10 +316,15 @@ static int init_resampler(AVCodecContext *input_codec_context,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Initialize a FIFO buffer for the audio samples to be encoded. */
|
||||
/**
|
||||
* Initialize a FIFO buffer for the audio samples to be encoded.
|
||||
* @param[out] fifo Sample buffer
|
||||
* @param output_codec_context Codec context of the output file
|
||||
* @return Error code (0 if successful)
|
||||
*/
|
||||
static int init_fifo(AVAudioFifo **fifo, AVCodecContext *output_codec_context)
|
||||
{
|
||||
/** Create the FIFO buffer based on the specified output sample format. */
|
||||
/* Create the FIFO buffer based on the specified output sample format. */
|
||||
if (!(*fifo = av_audio_fifo_alloc(output_codec_context->sample_fmt,
|
||||
output_codec_context->channels, 1))) {
|
||||
fprintf(stderr, "Could not allocate FIFO\n");
|
||||
@@ -307,7 +333,11 @@ static int init_fifo(AVAudioFifo **fifo, AVCodecContext *output_codec_context)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Write the header of the output file container. */
|
||||
/**
|
||||
* Write the header of the output file container.
|
||||
* @param output_format_context Format context of the output file
|
||||
* @return Error code (0 if successful)
|
||||
*/
|
||||
static int write_output_file_header(AVFormatContext *output_format_context)
|
||||
{
|
||||
int error;
|
||||
@@ -319,20 +349,32 @@ static int write_output_file_header(AVFormatContext *output_format_context)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Decode one audio frame from the input file. */
|
||||
/**
|
||||
* Decode one audio frame from the input file.
|
||||
* @param frame Audio frame to be decoded
|
||||
* @param input_format_context Format context of the input file
|
||||
* @param input_codec_context Codec context of the input file
|
||||
* @param[out] data_present Indicates whether data has been decoded
|
||||
* @param[out] finished Indicates whether the end of file has
|
||||
* been reached and all data has been
|
||||
* decoded. If this flag is false, there
|
||||
* is more data to be decoded, i.e., this
|
||||
* function has to be called again.
|
||||
* @return Error code (0 if successful)
|
||||
*/
|
||||
static int decode_audio_frame(AVFrame *frame,
|
||||
AVFormatContext *input_format_context,
|
||||
AVCodecContext *input_codec_context,
|
||||
int *data_present, int *finished)
|
||||
{
|
||||
/** Packet used for temporary storage. */
|
||||
/* Packet used for temporary storage. */
|
||||
AVPacket input_packet;
|
||||
int error;
|
||||
init_packet(&input_packet);
|
||||
|
||||
/** Read one audio frame from the input file into a temporary packet. */
|
||||
/* Read one audio frame from the input file into a temporary packet. */
|
||||
if ((error = av_read_frame(input_format_context, &input_packet)) < 0) {
|
||||
/** If we are at the end of the file, flush the decoder below. */
|
||||
/* If we are at the end of the file, flush the decoder below. */
|
||||
if (error == AVERROR_EOF)
|
||||
*finished = 1;
|
||||
else {
|
||||
@@ -342,12 +384,10 @@ static int decode_audio_frame(AVFrame *frame,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode the audio frame stored in the temporary packet.
|
||||
/* Decode the audio frame stored in the temporary packet.
|
||||
* The input audio stream decoder is used to do this.
|
||||
* If we are at the end of the file, pass an empty packet to the decoder
|
||||
* to flush it.
|
||||
*/
|
||||
* to flush it. */
|
||||
if ((error = avcodec_decode_audio4(input_codec_context, frame,
|
||||
data_present, &input_packet)) < 0) {
|
||||
fprintf(stderr, "Could not decode frame (error '%s')\n",
|
||||
@@ -356,10 +396,8 @@ static int decode_audio_frame(AVFrame *frame,
|
||||
return error;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the decoder has not been flushed completely, we are not finished,
|
||||
* so that this function has to be called again.
|
||||
*/
|
||||
/* If the decoder has not been flushed completely, we are not finished,
|
||||
* so that this function has to be called again. */
|
||||
if (*finished && *data_present)
|
||||
*finished = 0;
|
||||
av_packet_unref(&input_packet);
|
||||
@@ -370,6 +408,13 @@ static int decode_audio_frame(AVFrame *frame,
|
||||
* Initialize a temporary storage for the specified number of audio samples.
|
||||
* The conversion requires temporary storage due to the different format.
|
||||
* The number of audio samples to be allocated is specified in frame_size.
|
||||
* @param[out] converted_input_samples Array of converted samples. The
|
||||
* dimensions are reference, channel
|
||||
* (for multi-channel audio), sample.
|
||||
* @param output_codec_context Codec context of the output file
|
||||
* @param frame_size Number of samples to be converted in
|
||||
* each round
|
||||
* @return Error code (0 if successful)
|
||||
*/
|
||||
static int init_converted_samples(uint8_t ***converted_input_samples,
|
||||
AVCodecContext *output_codec_context,
|
||||
@@ -377,8 +422,7 @@ static int init_converted_samples(uint8_t ***converted_input_samples,
|
||||
{
|
||||
int error;
|
||||
|
||||
/**
|
||||
* Allocate as many pointers as there are audio channels.
|
||||
/* Allocate as many pointers as there are audio channels.
|
||||
* Each pointer will later point to the audio samples of the corresponding
|
||||
* channels (although it may be NULL for interleaved formats).
|
||||
*/
|
||||
@@ -388,10 +432,8 @@ static int init_converted_samples(uint8_t ***converted_input_samples,
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate memory for the samples of all channels in one consecutive
|
||||
* block for convenience.
|
||||
*/
|
||||
/* Allocate memory for the samples of all channels in one consecutive
|
||||
* block for convenience. */
|
||||
if ((error = av_samples_alloc(*converted_input_samples, NULL,
|
||||
output_codec_context->channels,
|
||||
frame_size,
|
||||
@@ -408,8 +450,15 @@ static int init_converted_samples(uint8_t ***converted_input_samples,
|
||||
|
||||
/**
|
||||
* Convert the input audio samples into the output sample format.
|
||||
* The conversion happens on a per-frame basis, the size of which is specified
|
||||
* by frame_size.
|
||||
* The conversion happens on a per-frame basis, the size of which is
|
||||
* specified by frame_size.
|
||||
* @param input_data Samples to be decoded. The dimensions are
|
||||
* channel (for multi-channel audio), sample.
|
||||
* @param[out] converted_data Converted samples. The dimensions are channel
|
||||
* (for multi-channel audio), sample.
|
||||
* @param frame_size Number of samples to be converted
|
||||
* @param resample_context Resample context for the conversion
|
||||
* @return Error code (0 if successful)
|
||||
*/
|
||||
static int convert_samples(const uint8_t **input_data,
|
||||
uint8_t **converted_data, const int frame_size,
|
||||
@@ -417,7 +466,7 @@ static int convert_samples(const uint8_t **input_data,
|
||||
{
|
||||
int error;
|
||||
|
||||
/** Convert the samples using the resampler. */
|
||||
/* Convert the samples using the resampler. */
|
||||
if ((error = swr_convert(resample_context,
|
||||
converted_data, frame_size,
|
||||
input_data , frame_size)) < 0) {
|
||||
@@ -429,23 +478,28 @@ static int convert_samples(const uint8_t **input_data,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Add converted input audio samples to the FIFO buffer for later processing. */
|
||||
/**
|
||||
* Add converted input audio samples to the FIFO buffer for later processing.
|
||||
* @param fifo Buffer to add the samples to
|
||||
* @param converted_input_samples Samples to be added. The dimensions are channel
|
||||
* (for multi-channel audio), sample.
|
||||
* @param frame_size Number of samples to be converted
|
||||
* @return Error code (0 if successful)
|
||||
*/
|
||||
static int add_samples_to_fifo(AVAudioFifo *fifo,
|
||||
uint8_t **converted_input_samples,
|
||||
const int frame_size)
|
||||
{
|
||||
int error;
|
||||
|
||||
/**
|
||||
* Make the FIFO as large as it needs to be to hold both,
|
||||
* the old and the new samples.
|
||||
*/
|
||||
/* Make the FIFO as large as it needs to be to hold both,
|
||||
* the old and the new samples. */
|
||||
if ((error = av_audio_fifo_realloc(fifo, av_audio_fifo_size(fifo) + frame_size)) < 0) {
|
||||
fprintf(stderr, "Could not reallocate FIFO\n");
|
||||
return error;
|
||||
}
|
||||
|
||||
/** Store the new samples in the FIFO buffer. */
|
||||
/* Store the new samples in the FIFO buffer. */
|
||||
if (av_audio_fifo_write(fifo, (void **)converted_input_samples,
|
||||
frame_size) < frame_size) {
|
||||
fprintf(stderr, "Could not write data to FIFO\n");
|
||||
@@ -455,8 +509,20 @@ static int add_samples_to_fifo(AVAudioFifo *fifo,
|
||||
}
|
||||
|
||||
/**
|
||||
* Read one audio frame from the input file, decodes, converts and stores
|
||||
* Read one audio frame from the input file, decode, convert and store
|
||||
* it in the FIFO buffer.
|
||||
* @param fifo Buffer used for temporary storage
|
||||
* @param input_format_context Format context of the input file
|
||||
* @param input_codec_context Codec context of the input file
|
||||
* @param output_codec_context Codec context of the output file
|
||||
* @param resampler_context Resample context for the conversion
|
||||
* @param[out] finished Indicates whether the end of file has
|
||||
* been reached and all data has been
|
||||
* decoded. If this flag is false,
|
||||
* there is more data to be decoded,
|
||||
* i.e., this function has to be called
|
||||
* again.
|
||||
* @return Error code (0 if successful)
|
||||
*/
|
||||
static int read_decode_convert_and_store(AVAudioFifo *fifo,
|
||||
AVFormatContext *input_format_context,
|
||||
@@ -465,45 +531,41 @@ static int read_decode_convert_and_store(AVAudioFifo *fifo,
|
||||
SwrContext *resampler_context,
|
||||
int *finished)
|
||||
{
|
||||
/** Temporary storage of the input samples of the frame read from the file. */
|
||||
/* Temporary storage of the input samples of the frame read from the file. */
|
||||
AVFrame *input_frame = NULL;
|
||||
/** Temporary storage for the converted input samples. */
|
||||
/* Temporary storage for the converted input samples. */
|
||||
uint8_t **converted_input_samples = NULL;
|
||||
int data_present;
|
||||
int ret = AVERROR_EXIT;
|
||||
|
||||
/** Initialize temporary storage for one input frame. */
|
||||
/* Initialize temporary storage for one input frame. */
|
||||
if (init_input_frame(&input_frame))
|
||||
goto cleanup;
|
||||
/** Decode one frame worth of audio samples. */
|
||||
/* Decode one frame worth of audio samples. */
|
||||
if (decode_audio_frame(input_frame, input_format_context,
|
||||
input_codec_context, &data_present, finished))
|
||||
goto cleanup;
|
||||
/**
|
||||
* If we are at the end of the file and there are no more samples
|
||||
/* If we are at the end of the file and there are no more samples
|
||||
* in the decoder which are delayed, we are actually finished.
|
||||
* This must not be treated as an error.
|
||||
*/
|
||||
* This must not be treated as an error. */
|
||||
if (*finished && !data_present) {
|
||||
ret = 0;
|
||||
goto cleanup;
|
||||
}
|
||||
/** If there is decoded data, convert and store it */
|
||||
/* If there is decoded data, convert and store it. */
|
||||
if (data_present) {
|
||||
/** Initialize the temporary storage for the converted input samples. */
|
||||
/* Initialize the temporary storage for the converted input samples. */
|
||||
if (init_converted_samples(&converted_input_samples, output_codec_context,
|
||||
input_frame->nb_samples))
|
||||
goto cleanup;
|
||||
|
||||
/**
|
||||
* Convert the input samples to the desired output sample format.
|
||||
* This requires a temporary storage provided by converted_input_samples.
|
||||
*/
|
||||
/* Convert the input samples to the desired output sample format.
|
||||
* This requires a temporary storage provided by converted_input_samples. */
|
||||
if (convert_samples((const uint8_t**)input_frame->extended_data, converted_input_samples,
|
||||
input_frame->nb_samples, resampler_context))
|
||||
goto cleanup;
|
||||
|
||||
/** Add the converted input samples to the FIFO buffer for later processing. */
|
||||
/* Add the converted input samples to the FIFO buffer for later processing. */
|
||||
if (add_samples_to_fifo(fifo, converted_input_samples,
|
||||
input_frame->nb_samples))
|
||||
goto cleanup;
|
||||
@@ -524,6 +586,10 @@ cleanup:
|
||||
/**
|
||||
* Initialize one input frame for writing to the output file.
|
||||
* The frame will be exactly frame_size samples large.
|
||||
* @param[out] frame Frame to be initialized
|
||||
* @param output_codec_context Codec context of the output file
|
||||
* @param frame_size Size of the frame
|
||||
* @return Error code (0 if successful)
|
||||
*/
|
||||
static int init_output_frame(AVFrame **frame,
|
||||
AVCodecContext *output_codec_context,
|
||||
@@ -531,28 +597,24 @@ static int init_output_frame(AVFrame **frame,
|
||||
{
|
||||
int error;
|
||||
|
||||
/** Create a new frame to store the audio samples. */
|
||||
/* Create a new frame to store the audio samples. */
|
||||
if (!(*frame = av_frame_alloc())) {
|
||||
fprintf(stderr, "Could not allocate output frame\n");
|
||||
return AVERROR_EXIT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the frame's parameters, especially its size and format.
|
||||
/* Set the frame's parameters, especially its size and format.
|
||||
* av_frame_get_buffer needs this to allocate memory for the
|
||||
* audio samples of the frame.
|
||||
* Default channel layouts based on the number of channels
|
||||
* are assumed for simplicity.
|
||||
*/
|
||||
* are assumed for simplicity. */
|
||||
(*frame)->nb_samples = frame_size;
|
||||
(*frame)->channel_layout = output_codec_context->channel_layout;
|
||||
(*frame)->format = output_codec_context->sample_fmt;
|
||||
(*frame)->sample_rate = output_codec_context->sample_rate;
|
||||
|
||||
/**
|
||||
* Allocate the samples of the created frame. This call will make
|
||||
* sure that the audio frame can hold as many samples as specified.
|
||||
*/
|
||||
/* Allocate the samples of the created frame. This call will make
|
||||
* sure that the audio frame can hold as many samples as specified. */
|
||||
if ((error = av_frame_get_buffer(*frame, 0)) < 0) {
|
||||
fprintf(stderr, "Could not allocate output frame samples (error '%s')\n",
|
||||
av_err2str(error));
|
||||
@@ -563,30 +625,36 @@ static int init_output_frame(AVFrame **frame,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Global timestamp for the audio frames */
|
||||
/* Global timestamp for the audio frames. */
|
||||
static int64_t pts = 0;
|
||||
|
||||
/** Encode one frame worth of audio to the output file. */
|
||||
/**
|
||||
* Encode one frame worth of audio to the output file.
|
||||
* @param frame Samples to be encoded
|
||||
* @param output_format_context Format context of the output file
|
||||
* @param output_codec_context Codec context of the output file
|
||||
* @param[out] data_present Indicates whether data has been
|
||||
* decoded
|
||||
* @return Error code (0 if successful)
|
||||
*/
|
||||
static int encode_audio_frame(AVFrame *frame,
|
||||
AVFormatContext *output_format_context,
|
||||
AVCodecContext *output_codec_context,
|
||||
int *data_present)
|
||||
{
|
||||
/** Packet used for temporary storage. */
|
||||
/* Packet used for temporary storage. */
|
||||
AVPacket output_packet;
|
||||
int error;
|
||||
init_packet(&output_packet);
|
||||
|
||||
/** Set a timestamp based on the sample rate for the container. */
|
||||
/* Set a timestamp based on the sample rate for the container. */
|
||||
if (frame) {
|
||||
frame->pts = pts;
|
||||
pts += frame->nb_samples;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode the audio frame and store it in the temporary packet.
|
||||
* The output audio stream encoder is used to do this.
|
||||
*/
|
||||
/* Encode the audio frame and store it in the temporary packet.
|
||||
* The output audio stream encoder is used to do this. */
|
||||
if ((error = avcodec_encode_audio2(output_codec_context, &output_packet,
|
||||
frame, data_present)) < 0) {
|
||||
fprintf(stderr, "Could not encode frame (error '%s')\n",
|
||||
@@ -595,7 +663,7 @@ static int encode_audio_frame(AVFrame *frame,
|
||||
return error;
|
||||
}
|
||||
|
||||
/** Write one audio frame from the temporary packet to the output file. */
|
||||
/* Write one audio frame from the temporary packet to the output file. */
|
||||
if (*data_present) {
|
||||
if ((error = av_write_frame(output_format_context, &output_packet)) < 0) {
|
||||
fprintf(stderr, "Could not write frame (error '%s')\n",
|
||||
@@ -613,37 +681,37 @@ static int encode_audio_frame(AVFrame *frame,
|
||||
/**
|
||||
* Load one audio frame from the FIFO buffer, encode and write it to the
|
||||
* output file.
|
||||
* @param fifo Buffer used for temporary storage
|
||||
* @param output_format_context Format context of the output file
|
||||
* @param output_codec_context Codec context of the output file
|
||||
* @return Error code (0 if successful)
|
||||
*/
|
||||
static int load_encode_and_write(AVAudioFifo *fifo,
|
||||
AVFormatContext *output_format_context,
|
||||
AVCodecContext *output_codec_context)
|
||||
{
|
||||
/** Temporary storage of the output samples of the frame written to the file. */
|
||||
/* Temporary storage of the output samples of the frame written to the file. */
|
||||
AVFrame *output_frame;
|
||||
/**
|
||||
* Use the maximum number of possible samples per frame.
|
||||
/* Use the maximum number of possible samples per frame.
|
||||
* If there is less than the maximum possible frame size in the FIFO
|
||||
* buffer use this number. Otherwise, use the maximum possible frame size
|
||||
*/
|
||||
* buffer use this number. Otherwise, use the maximum possible frame size. */
|
||||
const int frame_size = FFMIN(av_audio_fifo_size(fifo),
|
||||
output_codec_context->frame_size);
|
||||
int data_written;
|
||||
|
||||
/** Initialize temporary storage for one output frame. */
|
||||
/* Initialize temporary storage for one output frame. */
|
||||
if (init_output_frame(&output_frame, output_codec_context, frame_size))
|
||||
return AVERROR_EXIT;
|
||||
|
||||
/**
|
||||
* Read as many samples from the FIFO buffer as required to fill the frame.
|
||||
* The samples are stored in the frame temporarily.
|
||||
*/
|
||||
/* Read as many samples from the FIFO buffer as required to fill the frame.
|
||||
* The samples are stored in the frame temporarily. */
|
||||
if (av_audio_fifo_read(fifo, (void **)output_frame->data, frame_size) < frame_size) {
|
||||
fprintf(stderr, "Could not read data from FIFO\n");
|
||||
av_frame_free(&output_frame);
|
||||
return AVERROR_EXIT;
|
||||
}
|
||||
|
||||
/** Encode one frame worth of audio samples. */
|
||||
/* Encode one frame worth of audio samples. */
|
||||
if (encode_audio_frame(output_frame, output_format_context,
|
||||
output_codec_context, &data_written)) {
|
||||
av_frame_free(&output_frame);
|
||||
@@ -653,7 +721,11 @@ static int load_encode_and_write(AVAudioFifo *fifo,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Write the trailer of the output file container. */
|
||||
/**
|
||||
* Write the trailer of the output file container.
|
||||
* @param output_format_context Format context of the output file
|
||||
* @return Error code (0 if successful)
|
||||
*/
|
||||
static int write_output_file_trailer(AVFormatContext *output_format_context)
|
||||
{
|
||||
int error;
|
||||
@@ -665,7 +737,6 @@ static int write_output_file_trailer(AVFormatContext *output_format_context)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Convert an audio file to an AAC file in an MP4 container. */
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
AVFormatContext *input_format_context = NULL, *output_format_context = NULL;
|
||||
@@ -674,89 +745,75 @@ int main(int argc, char **argv)
|
||||
AVAudioFifo *fifo = NULL;
|
||||
int ret = AVERROR_EXIT;
|
||||
|
||||
if (argc < 3) {
|
||||
if (argc != 3) {
|
||||
fprintf(stderr, "Usage: %s <input file> <output file>\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/** Register all codecs and formats so that they can be used. */
|
||||
/* Register all codecs and formats so that they can be used. */
|
||||
av_register_all();
|
||||
/** Open the input file for reading. */
|
||||
/* Open the input file for reading. */
|
||||
if (open_input_file(argv[1], &input_format_context,
|
||||
&input_codec_context))
|
||||
goto cleanup;
|
||||
/** Open the output file for writing. */
|
||||
/* Open the output file for writing. */
|
||||
if (open_output_file(argv[2], input_codec_context,
|
||||
&output_format_context, &output_codec_context))
|
||||
goto cleanup;
|
||||
/** Initialize the resampler to be able to convert audio sample formats. */
|
||||
/* Initialize the resampler to be able to convert audio sample formats. */
|
||||
if (init_resampler(input_codec_context, output_codec_context,
|
||||
&resample_context))
|
||||
goto cleanup;
|
||||
/** Initialize the FIFO buffer to store audio samples to be encoded. */
|
||||
/* Initialize the FIFO buffer to store audio samples to be encoded. */
|
||||
if (init_fifo(&fifo, output_codec_context))
|
||||
goto cleanup;
|
||||
/** Write the header of the output file container. */
|
||||
/* Write the header of the output file container. */
|
||||
if (write_output_file_header(output_format_context))
|
||||
goto cleanup;
|
||||
|
||||
/**
|
||||
* Loop as long as we have input samples to read or output samples
|
||||
* to write; abort as soon as we have neither.
|
||||
*/
|
||||
/* Loop as long as we have input samples to read or output samples
|
||||
* to write; abort as soon as we have neither. */
|
||||
while (1) {
|
||||
/** Use the encoder's desired frame size for processing. */
|
||||
/* Use the encoder's desired frame size for processing. */
|
||||
const int output_frame_size = output_codec_context->frame_size;
|
||||
int finished = 0;
|
||||
|
||||
/**
|
||||
* Make sure that there is one frame worth of samples in the FIFO
|
||||
/* Make sure that there is one frame worth of samples in the FIFO
|
||||
* buffer so that the encoder can do its work.
|
||||
* Since the decoder's and the encoder's frame size may differ, we
|
||||
* need to FIFO buffer to store as many frames worth of input samples
|
||||
* that they make up at least one frame worth of output samples.
|
||||
*/
|
||||
* that they make up at least one frame worth of output samples. */
|
||||
while (av_audio_fifo_size(fifo) < output_frame_size) {
|
||||
/**
|
||||
* Decode one frame worth of audio samples, convert it to the
|
||||
* output sample format and put it into the FIFO buffer.
|
||||
*/
|
||||
/* Decode one frame worth of audio samples, convert it to the
|
||||
* output sample format and put it into the FIFO buffer. */
|
||||
if (read_decode_convert_and_store(fifo, input_format_context,
|
||||
input_codec_context,
|
||||
output_codec_context,
|
||||
resample_context, &finished))
|
||||
goto cleanup;
|
||||
|
||||
/**
|
||||
* If we are at the end of the input file, we continue
|
||||
* encoding the remaining audio samples to the output file.
|
||||
*/
|
||||
/* If we are at the end of the input file, we continue
|
||||
* encoding the remaining audio samples to the output file. */
|
||||
if (finished)
|
||||
break;
|
||||
}
|
||||
|
||||
/**
|
||||
* If we have enough samples for the encoder, we encode them.
|
||||
/* If we have enough samples for the encoder, we encode them.
|
||||
* At the end of the file, we pass the remaining samples to
|
||||
* the encoder.
|
||||
*/
|
||||
* the encoder. */
|
||||
while (av_audio_fifo_size(fifo) >= output_frame_size ||
|
||||
(finished && av_audio_fifo_size(fifo) > 0))
|
||||
/**
|
||||
* Take one frame worth of audio samples from the FIFO buffer,
|
||||
* encode it and write it to the output file.
|
||||
*/
|
||||
/* Take one frame worth of audio samples from the FIFO buffer,
|
||||
* encode it and write it to the output file. */
|
||||
if (load_encode_and_write(fifo, output_format_context,
|
||||
output_codec_context))
|
||||
goto cleanup;
|
||||
|
||||
/**
|
||||
* If we are at the end of the input file and have encoded
|
||||
* all remaining samples, we can exit this loop and finish.
|
||||
*/
|
||||
/* If we are at the end of the input file and have encoded
|
||||
* all remaining samples, we can exit this loop and finish. */
|
||||
if (finished) {
|
||||
int data_written;
|
||||
/** Flush the encoder as it may have delayed frames. */
|
||||
/* Flush the encoder as it may have delayed frames. */
|
||||
do {
|
||||
if (encode_audio_frame(NULL, output_format_context,
|
||||
output_codec_context, &data_written))
|
||||
@@ -766,7 +823,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
/** Write the trailer of the output file container. */
|
||||
/* Write the trailer of the output file container. */
|
||||
if (write_output_file_trailer(output_format_context))
|
||||
goto cleanup;
|
||||
ret = 0;
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libavfilter/avfiltergraph.h>
|
||||
#include <libavfilter/buffersink.h>
|
||||
#include <libavfilter/buffersrc.h>
|
||||
#include <libavutil/opt.h>
|
||||
@@ -228,8 +227,8 @@ static int init_filter(FilteringContext* fctx, AVCodecContext *dec_ctx,
|
||||
{
|
||||
char args[512];
|
||||
int ret = 0;
|
||||
AVFilter *buffersrc = NULL;
|
||||
AVFilter *buffersink = NULL;
|
||||
const AVFilter *buffersrc = NULL;
|
||||
const AVFilter *buffersink = NULL;
|
||||
AVFilterContext *buffersrc_ctx = NULL;
|
||||
AVFilterContext *buffersink_ctx = NULL;
|
||||
AVFilterInOut *outputs = avfilter_inout_alloc();
|
||||
|
||||
@@ -0,0 +1,224 @@
|
||||
/*
|
||||
* Video Acceleration API (video encoding) encode sample
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Intel VAAPI-accelerated encoding example.
|
||||
*
|
||||
* @example vaapi_encode.c
|
||||
* This example shows how to do VAAPI-accelerated encoding. now only support NV12
|
||||
* raw file, usage like: vaapi_encode 1920 1080 input.yuv output.h264
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libavutil/pixdesc.h>
|
||||
#include <libavutil/hwcontext.h>
|
||||
|
||||
static int width, height;
|
||||
static AVBufferRef *hw_device_ctx = NULL;
|
||||
|
||||
static int set_hwframe_ctx(AVCodecContext *ctx, AVBufferRef *hw_device_ctx)
|
||||
{
|
||||
AVBufferRef *hw_frames_ref;
|
||||
AVHWFramesContext *frames_ctx = NULL;
|
||||
int err = 0;
|
||||
|
||||
if (!(hw_frames_ref = av_hwframe_ctx_alloc(hw_device_ctx))) {
|
||||
fprintf(stderr, "Failed to create VAAPI frame context.\n");
|
||||
return -1;
|
||||
}
|
||||
frames_ctx = (AVHWFramesContext *)(hw_frames_ref->data);
|
||||
frames_ctx->format = AV_PIX_FMT_VAAPI;
|
||||
frames_ctx->sw_format = AV_PIX_FMT_NV12;
|
||||
frames_ctx->width = width;
|
||||
frames_ctx->height = height;
|
||||
frames_ctx->initial_pool_size = 20;
|
||||
if ((err = av_hwframe_ctx_init(hw_frames_ref)) < 0) {
|
||||
fprintf(stderr, "Failed to initialize VAAPI frame context."
|
||||
"Error code: %s\n",av_err2str(err));
|
||||
av_buffer_unref(&hw_frames_ref);
|
||||
return err;
|
||||
}
|
||||
ctx->hw_frames_ctx = av_buffer_ref(hw_frames_ref);
|
||||
if (!ctx->hw_frames_ctx)
|
||||
err = AVERROR(ENOMEM);
|
||||
|
||||
av_buffer_unref(&hw_frames_ref);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int encode_write(AVCodecContext *avctx, AVFrame *frame, FILE *fout)
|
||||
{
|
||||
int ret = 0;
|
||||
AVPacket enc_pkt;
|
||||
|
||||
av_init_packet(&enc_pkt);
|
||||
enc_pkt.data = NULL;
|
||||
enc_pkt.size = 0;
|
||||
|
||||
if ((ret = avcodec_send_frame(avctx, frame)) < 0) {
|
||||
fprintf(stderr, "Error code: %s\n", av_err2str(ret));
|
||||
goto end;
|
||||
}
|
||||
while (1) {
|
||||
ret = avcodec_receive_packet(avctx, &enc_pkt);
|
||||
if (ret)
|
||||
break;
|
||||
|
||||
enc_pkt.stream_index = 0;
|
||||
ret = fwrite(enc_pkt.data, enc_pkt.size, 1, fout);
|
||||
av_packet_unref(&enc_pkt);
|
||||
}
|
||||
|
||||
end:
|
||||
ret = ((ret == AVERROR(EAGAIN)) ? 0 : -1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int size, err;
|
||||
FILE *fin = NULL, *fout = NULL;
|
||||
AVFrame *sw_frame = NULL, *hw_frame = NULL;
|
||||
AVCodecContext *avctx = NULL;
|
||||
AVCodec *codec = NULL;
|
||||
const char *enc_name = "h264_vaapi";
|
||||
|
||||
if (argc < 5) {
|
||||
fprintf(stderr, "Usage: %s <width> <height> <input file> <output file>\n", argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
width = atoi(argv[1]);
|
||||
height = atoi(argv[2]);
|
||||
size = width * height;
|
||||
|
||||
if (!(fin = fopen(argv[3], "r"))) {
|
||||
fprintf(stderr, "Fail to open input file : %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
if (!(fout = fopen(argv[4], "w+b"))) {
|
||||
fprintf(stderr, "Fail to open output file : %s\n", strerror(errno));
|
||||
err = -1;
|
||||
goto close;
|
||||
}
|
||||
|
||||
avcodec_register_all();
|
||||
|
||||
err = av_hwdevice_ctx_create(&hw_device_ctx, AV_HWDEVICE_TYPE_VAAPI,
|
||||
NULL, NULL, 0);
|
||||
if (err < 0) {
|
||||
fprintf(stderr, "Failed to create a VAAPI device. Error code: %s\n", av_err2str(err));
|
||||
goto close;
|
||||
}
|
||||
|
||||
if (!(codec = avcodec_find_encoder_by_name(enc_name))) {
|
||||
fprintf(stderr, "Could not find encoder.\n");
|
||||
err = -1;
|
||||
goto close;
|
||||
}
|
||||
|
||||
if (!(avctx = avcodec_alloc_context3(codec))) {
|
||||
err = AVERROR(ENOMEM);
|
||||
goto close;
|
||||
}
|
||||
|
||||
avctx->width = width;
|
||||
avctx->height = height;
|
||||
avctx->time_base = (AVRational){1, 25};
|
||||
avctx->framerate = (AVRational){25, 1};
|
||||
avctx->sample_aspect_ratio = (AVRational){1, 1};
|
||||
avctx->pix_fmt = AV_PIX_FMT_VAAPI;
|
||||
|
||||
/* set hw_frames_ctx for encoder's AVCodecContext */
|
||||
if ((err = set_hwframe_ctx(avctx, hw_device_ctx)) < 0) {
|
||||
fprintf(stderr, "Failed to set hwframe context.\n");
|
||||
goto close;
|
||||
}
|
||||
|
||||
if ((err = avcodec_open2(avctx, codec, NULL)) < 0) {
|
||||
fprintf(stderr, "Cannot open video encoder codec. Error code: %s\n", av_err2str(err));
|
||||
goto close;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
if (!(sw_frame = av_frame_alloc())) {
|
||||
err = AVERROR(ENOMEM);
|
||||
goto close;
|
||||
}
|
||||
/* read data into software frame, and transfer them into hw frame */
|
||||
sw_frame->width = width;
|
||||
sw_frame->height = height;
|
||||
sw_frame->format = AV_PIX_FMT_NV12;
|
||||
if ((err = av_frame_get_buffer(sw_frame, 32)) < 0)
|
||||
goto close;
|
||||
if ((err = fread((uint8_t*)(sw_frame->data[0]), size, 1, fin)) <= 0)
|
||||
break;
|
||||
if ((err = fread((uint8_t*)(sw_frame->data[1]), size/2, 1, fin)) <= 0)
|
||||
break;
|
||||
|
||||
if (!(hw_frame = av_frame_alloc())) {
|
||||
err = AVERROR(ENOMEM);
|
||||
goto close;
|
||||
}
|
||||
if ((err = av_hwframe_get_buffer(avctx->hw_frames_ctx, hw_frame, 0)) < 0) {
|
||||
fprintf(stderr, "Error code: %s.\n", av_err2str(err));
|
||||
goto close;
|
||||
}
|
||||
if (!hw_frame->hw_frames_ctx) {
|
||||
err = AVERROR(ENOMEM);
|
||||
goto close;
|
||||
}
|
||||
if ((err = av_hwframe_transfer_data(hw_frame, sw_frame, 0)) < 0) {
|
||||
fprintf(stderr, "Error while transferring frame data to surface."
|
||||
"Error code: %s.\n", av_err2str(err));
|
||||
goto close;
|
||||
}
|
||||
|
||||
if ((err = (encode_write(avctx, hw_frame, fout))) < 0) {
|
||||
fprintf(stderr, "Failed to encode.\n");
|
||||
goto close;
|
||||
}
|
||||
av_frame_free(&hw_frame);
|
||||
av_frame_free(&sw_frame);
|
||||
}
|
||||
|
||||
/* flush encoder */
|
||||
err = encode_write(avctx, NULL, fout);
|
||||
if (err == AVERROR_EOF)
|
||||
err = 0;
|
||||
|
||||
close:
|
||||
if (fin)
|
||||
fclose(fin);
|
||||
if (fout)
|
||||
fclose(fout);
|
||||
av_frame_free(&sw_frame);
|
||||
av_frame_free(&hw_frame);
|
||||
avcodec_free_context(&avctx);
|
||||
av_buffer_unref(&hw_device_ctx);
|
||||
|
||||
return err;
|
||||
}
|
||||
@@ -501,6 +501,71 @@ ffmpeg -i ega_screen.nut -vf setdar=4/3 ega_screen_anamorphic.nut
|
||||
ffmpeg -i ega_screen.nut -aspect 4/3 -c copy ega_screen_overridden.nut
|
||||
@end example
|
||||
|
||||
@anchor{background task}
|
||||
@section How do I run ffmpeg as a background task?
|
||||
|
||||
ffmpeg normally checks the console input, for entries like "q" to stop
|
||||
and "?" to give help, while performing operations. ffmpeg does not have a way of
|
||||
detecting when it is running as a background task.
|
||||
When it checks the console input, that can cause the process running ffmpeg
|
||||
in the background to suspend.
|
||||
|
||||
To prevent those input checks, allowing ffmpeg to run as a background task,
|
||||
use the @url{ffmpeg.html#stdin-option, @code{-nostdin} option}
|
||||
in the ffmpeg invocation. This is effective whether you run ffmpeg in a shell
|
||||
or invoke ffmpeg in its own process via an operating system API.
|
||||
|
||||
As an alternative, when you are running ffmpeg in a shell, you can redirect
|
||||
standard input to @code{/dev/null} (on Linux and Mac OS)
|
||||
or @code{NUL} (on Windows). You can do this redirect either
|
||||
on the ffmpeg invocation, or from a shell script which calls ffmpeg.
|
||||
|
||||
For example:
|
||||
|
||||
@example
|
||||
ffmpeg -nostdin -i INPUT OUTPUT
|
||||
@end example
|
||||
|
||||
or (on Linux, Mac OS, and other UNIX-like shells):
|
||||
|
||||
@example
|
||||
ffmpeg -i INPUT OUTPUT </dev/null
|
||||
@end example
|
||||
|
||||
or (on Windows):
|
||||
|
||||
@example
|
||||
ffmpeg -i INPUT OUTPUT <NUL
|
||||
@end example
|
||||
|
||||
@section How do I prevent ffmpeg from suspending with a message like @emph{suspended (tty output)}?
|
||||
|
||||
If you run ffmpeg in the background, you may find that its process suspends.
|
||||
There may be a message like @emph{suspended (tty output)}. The question is how
|
||||
to prevent the process from being suspended.
|
||||
|
||||
For example:
|
||||
|
||||
@example
|
||||
% ffmpeg -i INPUT OUTPUT &> ~/tmp/log.txt &
|
||||
[1] 93352
|
||||
%
|
||||
[1] + suspended (tty output) ffmpeg -i INPUT OUTPUT &>
|
||||
@end example
|
||||
|
||||
The message "tty output" notwithstanding, the problem here is that
|
||||
ffmpeg normally checks the console input when it runs. The operating system
|
||||
detects this, and suspends the process until you can bring it to the
|
||||
foreground and attend to it.
|
||||
|
||||
The solution is to use the right techniques to tell ffmpeg not to consult
|
||||
console input. You can use the
|
||||
@url{ffmpeg.html#stdin-option, @code{-nostdin} option},
|
||||
or redirect standard input with @code{< /dev/null}.
|
||||
See FAQ
|
||||
@ref{background task, @emph{How do I run ffmpeg as a background task?}}
|
||||
for details.
|
||||
|
||||
@chapter Development
|
||||
|
||||
@section Are there examples illustrating how to use the FFmpeg libraries, particularly libavcodec and libavformat?
|
||||
|
||||
@@ -147,6 +147,26 @@ process.
|
||||
The only thing left is to automate the execution of the fate.sh script and
|
||||
the synchronisation of the samples directory.
|
||||
|
||||
@chapter Uploading new samples to the fate suite
|
||||
|
||||
This is for developers who have an account on the fate suite server.
|
||||
If you upload new samples, please make sure they are as small as possible,
|
||||
space on each client, network bandwidth and so on benefit from smaller test cases.
|
||||
Also keep in mind older checkouts use existing sample files, that means in
|
||||
practice generally do not replace, remove or overwrite files as it likely would
|
||||
break older checkouts or releases.
|
||||
|
||||
@example
|
||||
#First update your local samples copy:
|
||||
rsync -vauL --chmod=Dg+s,Duo+x,ug+rw,o+r,o-w,+X fate-suite.ffmpeg.org:/home/samples/fate-suite/ ~/fate-suite
|
||||
|
||||
#Then do a dry run checking what would be uploaded:
|
||||
rsync -vanL --no-g --chmod=Dg+s,Duo+x,ug+rw,o+r,o-w,+X ~/fate-suite/ fate-suite.ffmpeg.org:/home/samples/fate-suite
|
||||
|
||||
#Upload the files:
|
||||
rsync -vaL --no-g --chmod=Dg+s,Duo+x,ug+rw,o+r,o-w,+X ~/fate-suite/ fate-suite.ffmpeg.org:/home/samples/fate-suite
|
||||
@end example
|
||||
|
||||
|
||||
@chapter FATE makefile targets and variables
|
||||
|
||||
|
||||
@@ -26,12 +26,12 @@ bitstream level modifications without performing decoding.
|
||||
@chapter See Also
|
||||
|
||||
@ifhtml
|
||||
@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe}, @url{ffserver.html,ffserver},
|
||||
@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe},
|
||||
@url{libavcodec.html,libavcodec}
|
||||
@end ifhtml
|
||||
|
||||
@ifnothtml
|
||||
ffmpeg(1), ffplay(1), ffprobe(1), ffserver(1), libavcodec(3)
|
||||
ffmpeg(1), ffplay(1), ffprobe(1), libavcodec(3)
|
||||
@end ifnothtml
|
||||
|
||||
@include authors.texi
|
||||
|
||||
@@ -23,12 +23,12 @@ the libavcodec library.
|
||||
@chapter See Also
|
||||
|
||||
@ifhtml
|
||||
@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe}, @url{ffserver.html,ffserver},
|
||||
@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe},
|
||||
@url{libavcodec.html,libavcodec}
|
||||
@end ifhtml
|
||||
|
||||
@ifnothtml
|
||||
ffmpeg(1), ffplay(1), ffprobe(1), ffserver(1), libavcodec(3)
|
||||
ffmpeg(1), ffplay(1), ffprobe(1), libavcodec(3)
|
||||
@end ifnothtml
|
||||
|
||||
@include authors.texi
|
||||
|
||||
@@ -23,12 +23,12 @@ libavdevice library.
|
||||
@chapter See Also
|
||||
|
||||
@ifhtml
|
||||
@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe}, @url{ffserver.html,ffserver},
|
||||
@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe},
|
||||
@url{libavdevice.html,libavdevice}
|
||||
@end ifhtml
|
||||
|
||||
@ifnothtml
|
||||
ffmpeg(1), ffplay(1), ffprobe(1), ffserver(1), libavdevice(3)
|
||||
ffmpeg(1), ffplay(1), ffprobe(1), libavdevice(3)
|
||||
@end ifnothtml
|
||||
|
||||
@include authors.texi
|
||||
|
||||
@@ -23,12 +23,12 @@ libavfilter library.
|
||||
@chapter See Also
|
||||
|
||||
@ifhtml
|
||||
@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe}, @url{ffserver.html,ffserver},
|
||||
@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe},
|
||||
@url{libavfilter.html,libavfilter}
|
||||
@end ifhtml
|
||||
|
||||
@ifnothtml
|
||||
ffmpeg(1), ffplay(1), ffprobe(1), ffserver(1), libavfilter(3)
|
||||
ffmpeg(1), ffplay(1), ffprobe(1), libavfilter(3)
|
||||
@end ifnothtml
|
||||
|
||||
@include authors.texi
|
||||
|
||||
@@ -23,12 +23,12 @@ provided by the libavformat library.
|
||||
@chapter See Also
|
||||
|
||||
@ifhtml
|
||||
@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe}, @url{ffserver.html,ffserver},
|
||||
@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe},
|
||||
@url{libavformat.html,libavformat}
|
||||
@end ifhtml
|
||||
|
||||
@ifnothtml
|
||||
ffmpeg(1), ffplay(1), ffprobe(1), ffserver(1), libavformat(3)
|
||||
ffmpeg(1), ffplay(1), ffprobe(1), libavformat(3)
|
||||
@end ifnothtml
|
||||
|
||||
@include authors.texi
|
||||
|
||||
@@ -23,12 +23,12 @@ libavformat library.
|
||||
@chapter See Also
|
||||
|
||||
@ifhtml
|
||||
@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe}, @url{ffserver.html,ffserver},
|
||||
@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe},
|
||||
@url{libavformat.html,libavformat}
|
||||
@end ifhtml
|
||||
|
||||
@ifnothtml
|
||||
ffmpeg(1), ffplay(1), ffprobe(1), ffserver(1), libavformat(3)
|
||||
ffmpeg(1), ffplay(1), ffprobe(1), libavformat(3)
|
||||
@end ifnothtml
|
||||
|
||||
@include authors.texi
|
||||
|
||||
@@ -25,12 +25,12 @@ and convert audio format and packing layout.
|
||||
@chapter See Also
|
||||
|
||||
@ifhtml
|
||||
@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe}, @url{ffserver.html,ffserver},
|
||||
@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe},
|
||||
@url{libswresample.html,libswresample}
|
||||
@end ifhtml
|
||||
|
||||
@ifnothtml
|
||||
ffmpeg(1), ffplay(1), ffprobe(1), ffserver(1), libswresample(3)
|
||||
ffmpeg(1), ffplay(1), ffprobe(1), libswresample(3)
|
||||
@end ifnothtml
|
||||
|
||||
@include authors.texi
|
||||
|
||||
@@ -24,12 +24,12 @@ image rescaling and pixel format conversion.
|
||||
@chapter See Also
|
||||
|
||||
@ifhtml
|
||||
@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe}, @url{ffserver.html,ffserver},
|
||||
@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe},
|
||||
@url{libswscale.html,libswscale}
|
||||
@end ifhtml
|
||||
|
||||
@ifnothtml
|
||||
ffmpeg(1), ffplay(1), ffprobe(1), ffserver(1), libswscale(3)
|
||||
ffmpeg(1), ffplay(1), ffprobe(1), libswscale(3)
|
||||
@end ifnothtml
|
||||
|
||||
@include authors.texi
|
||||
|
||||
@@ -23,12 +23,12 @@ by the libavutil library.
|
||||
@chapter See Also
|
||||
|
||||
@ifhtml
|
||||
@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe}, @url{ffserver.html,ffserver},
|
||||
@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe},
|
||||
@url{libavutil.html,libavutil}
|
||||
@end ifhtml
|
||||
|
||||
@ifnothtml
|
||||
ffmpeg(1), ffplay(1), ffprobe(1), ffserver(1), libavutil(3)
|
||||
ffmpeg(1), ffplay(1), ffprobe(1), libavutil(3)
|
||||
@end ifnothtml
|
||||
|
||||
@include authors.texi
|
||||
|
||||
+44
-21
@@ -289,8 +289,8 @@ see @ref{time duration syntax,,the Time duration section in the ffmpeg-utils(1)
|
||||
|
||||
-to and -t are mutually exclusive and -t has priority.
|
||||
|
||||
@item -to @var{position} (@emph{output})
|
||||
Stop writing the output at @var{position}.
|
||||
@item -to @var{position} (@emph{input/output})
|
||||
Stop writing the output or reading the input at @var{position}.
|
||||
@var{position} must be a time duration specification,
|
||||
see @ref{time duration syntax,,the Time duration section in the ffmpeg-utils(1) manual,ffmpeg-utils}.
|
||||
|
||||
@@ -470,6 +470,7 @@ the encoding process. It is made of "@var{key}=@var{value}" lines. @var{key}
|
||||
consists of only alphanumeric characters. The last key of a sequence of
|
||||
progress information is always "progress".
|
||||
|
||||
@anchor{stdin option}
|
||||
@item -stdin
|
||||
Enable interaction on standard input. On by default unless standard input is
|
||||
used as an input. To explicitly disable interaction you need to specify
|
||||
@@ -756,6 +757,43 @@ If not specified, @samp{auto_any} is used.
|
||||
platform-appropriate subdevice (@samp{dxva2} or @samp{vaapi}) and then deriving a
|
||||
QSV device from that.)
|
||||
|
||||
@item opencl
|
||||
@var{device} selects the platform and device as @emph{platform_index.device_index}.
|
||||
|
||||
The set of devices can also be filtered using the key-value pairs to find only
|
||||
devices matching particular platform or device strings.
|
||||
|
||||
The strings usable as filters are:
|
||||
@table @option
|
||||
@item platform_profile
|
||||
@item platform_version
|
||||
@item platform_name
|
||||
@item platform_vendor
|
||||
@item platform_extensions
|
||||
@item device_name
|
||||
@item device_vendor
|
||||
@item driver_version
|
||||
@item device_version
|
||||
@item device_profile
|
||||
@item device_extensions
|
||||
@item device_type
|
||||
@end table
|
||||
|
||||
The indices and filters must together uniquely select a device.
|
||||
|
||||
Examples:
|
||||
@table @emph
|
||||
@item -init_hw_device opencl:0.1
|
||||
Choose the second device on the first platform.
|
||||
|
||||
@item -init_hw_device opencl:,device_name=Foo9000
|
||||
Choose the device with a name containing the string @emph{Foo9000}.
|
||||
|
||||
@item -init_hw_device opencl:1,device_type=gpu,device_extensions=cl_khr_fp16
|
||||
Choose the GPU device on the second platform supporting the @emph{cl_khr_fp16}
|
||||
extension.
|
||||
@end table
|
||||
|
||||
@end table
|
||||
|
||||
@item -init_hw_device @var{type}[=@var{name}]@@@var{source}
|
||||
@@ -786,9 +824,6 @@ Do not use any hardware acceleration (the default).
|
||||
@item auto
|
||||
Automatically select the hardware acceleration method.
|
||||
|
||||
@item vda
|
||||
Use Apple VDA hardware acceleration.
|
||||
|
||||
@item vdpau
|
||||
Use VDPAU (Video Decode and Presentation API for Unix) hardware acceleration.
|
||||
|
||||
@@ -1132,10 +1167,6 @@ loss).
|
||||
By default @command{ffmpeg} attempts to read the input(s) as fast as possible.
|
||||
This option will slow down the reading of the input(s) to the native frame rate
|
||||
of the input(s). It is useful for real-time output (e.g. live streaming).
|
||||
@item -loop_input
|
||||
Loop over the input stream. Currently it works only for image
|
||||
streams. This option is used for automatic FFserver testing.
|
||||
This option is deprecated, use -loop 1.
|
||||
@item -loop_output @var{number_of_times}
|
||||
Repeatedly loop output for formats that support looping such as animated GIF
|
||||
(0 will loop the output infinitely).
|
||||
@@ -1253,6 +1284,8 @@ or as a floating point number (e.g. 0.04166, 2.0833e-5)
|
||||
|
||||
Default value is 0.
|
||||
|
||||
@item -bitexact (@emph{input/output})
|
||||
Enable bitexact mode for (de)muxer and (de/en)coder
|
||||
@item -shortest (@emph{output})
|
||||
Finish encoding when the shortest input stream ends.
|
||||
@item -dts_delta_threshold
|
||||
@@ -1375,16 +1408,6 @@ file or device. With low latency / high rate live streams, packets may be
|
||||
discarded if they are not read in a timely manner; raising this value can
|
||||
avoid it.
|
||||
|
||||
@item -override_ffserver (@emph{global})
|
||||
Overrides the input specifications from @command{ffserver}. Using this
|
||||
option you can map any input stream to @command{ffserver} and control
|
||||
many aspects of the encoding from @command{ffmpeg}. Without this
|
||||
option @command{ffmpeg} will transmit to @command{ffserver} what is
|
||||
requested by @command{ffserver}.
|
||||
|
||||
The option is intended for cases where features are needed that cannot be
|
||||
specified to @command{ffserver} but can be to @command{ffmpeg}.
|
||||
|
||||
@item -sdp_file @var{file} (@emph{global})
|
||||
Print sdp information for an output stream to @var{file}.
|
||||
This allows dumping sdp information when at least one output isn't an
|
||||
@@ -1739,7 +1762,7 @@ ffmpeg -i src.ext -lmax 21*QP2LAMBDA dst.ext
|
||||
@ifset config-not-all
|
||||
@url{ffmpeg-all.html,ffmpeg-all},
|
||||
@end ifset
|
||||
@url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe}, @url{ffserver.html,ffserver},
|
||||
@url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe},
|
||||
@url{ffmpeg-utils.html,ffmpeg-utils},
|
||||
@url{ffmpeg-scaler.html,ffmpeg-scaler},
|
||||
@url{ffmpeg-resampler.html,ffmpeg-resampler},
|
||||
@@ -1758,7 +1781,7 @@ ffmpeg(1),
|
||||
@ifset config-not-all
|
||||
ffmpeg-all(1),
|
||||
@end ifset
|
||||
ffplay(1), ffprobe(1), ffserver(1),
|
||||
ffplay(1), ffprobe(1),
|
||||
ffmpeg-utils(1), ffmpeg-scaler(1), ffmpeg-resampler(1),
|
||||
ffmpeg-codecs(1), ffmpeg-bitstream-filters(1), ffmpeg-formats(1),
|
||||
ffmpeg-devices(1), ffmpeg-protocols(1), ffmpeg-filters(1)
|
||||
|
||||
+2
-2
@@ -291,7 +291,7 @@ Toggle full screen.
|
||||
@ifset config-not-all
|
||||
@url{ffplay-all.html,ffmpeg-all},
|
||||
@end ifset
|
||||
@url{ffmpeg.html,ffmpeg}, @url{ffprobe.html,ffprobe}, @url{ffserver.html,ffserver},
|
||||
@url{ffmpeg.html,ffmpeg}, @url{ffprobe.html,ffprobe},
|
||||
@url{ffmpeg-utils.html,ffmpeg-utils},
|
||||
@url{ffmpeg-scaler.html,ffmpeg-scaler},
|
||||
@url{ffmpeg-resampler.html,ffmpeg-resampler},
|
||||
@@ -310,7 +310,7 @@ ffplay(1),
|
||||
@ifset config-not-all
|
||||
ffplay-all(1),
|
||||
@end ifset
|
||||
ffmpeg(1), ffprobe(1), ffserver(1),
|
||||
ffmpeg(1), ffprobe(1),
|
||||
ffmpeg-utils(1), ffmpeg-scaler(1), ffmpeg-resampler(1),
|
||||
ffmpeg-codecs(1), ffmpeg-bitstream-filters(1), ffmpeg-formats(1),
|
||||
ffmpeg-devices(1), ffmpeg-protocols(1), ffmpeg-filters(1)
|
||||
|
||||
+2
-2
@@ -653,7 +653,7 @@ DV, GXF and AVI timecodes are available in format metadata
|
||||
@ifset config-not-all
|
||||
@url{ffprobe-all.html,ffprobe-all},
|
||||
@end ifset
|
||||
@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffserver.html,ffserver},
|
||||
@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay},
|
||||
@url{ffmpeg-utils.html,ffmpeg-utils},
|
||||
@url{ffmpeg-scaler.html,ffmpeg-scaler},
|
||||
@url{ffmpeg-resampler.html,ffmpeg-resampler},
|
||||
@@ -672,7 +672,7 @@ ffprobe(1),
|
||||
@ifset config-not-all
|
||||
ffprobe-all(1),
|
||||
@end ifset
|
||||
ffmpeg(1), ffplay(1), ffserver(1),
|
||||
ffmpeg(1), ffplay(1),
|
||||
ffmpeg-utils(1), ffmpeg-scaler(1), ffmpeg-resampler(1),
|
||||
ffmpeg-codecs(1), ffmpeg-bitstream-filters(1), ffmpeg-formats(1),
|
||||
ffmpeg-devices(1), ffmpeg-protocols(1), ffmpeg-filters(1)
|
||||
|
||||
@@ -1,372 +0,0 @@
|
||||
# Port on which the server is listening. You must select a different
|
||||
# port from your standard HTTP web server if it is running on the same
|
||||
# computer.
|
||||
HTTPPort 8090
|
||||
|
||||
# Address on which the server is bound. Only useful if you have
|
||||
# several network interfaces.
|
||||
HTTPBindAddress 0.0.0.0
|
||||
|
||||
# Number of simultaneous HTTP connections that can be handled. It has
|
||||
# to be defined *before* the MaxClients parameter, since it defines the
|
||||
# MaxClients maximum limit.
|
||||
MaxHTTPConnections 2000
|
||||
|
||||
# Number of simultaneous requests that can be handled. Since FFServer
|
||||
# is very fast, it is more likely that you will want to leave this high
|
||||
# and use MaxBandwidth, below.
|
||||
MaxClients 1000
|
||||
|
||||
# This the maximum amount of kbit/sec that you are prepared to
|
||||
# consume when streaming to clients.
|
||||
MaxBandwidth 1000
|
||||
|
||||
# Access log file (uses standard Apache log file format)
|
||||
# '-' is the standard output.
|
||||
CustomLog -
|
||||
|
||||
##################################################################
|
||||
# Definition of the live feeds. Each live feed contains one video
|
||||
# and/or audio sequence coming from an ffmpeg encoder or another
|
||||
# ffserver. This sequence may be encoded simultaneously with several
|
||||
# codecs at several resolutions.
|
||||
|
||||
<Feed feed1.ffm>
|
||||
|
||||
# You must use 'ffmpeg' to send a live feed to ffserver. In this
|
||||
# example, you can type:
|
||||
#
|
||||
# ffmpeg http://localhost:8090/feed1.ffm
|
||||
|
||||
# ffserver can also do time shifting. It means that it can stream any
|
||||
# previously recorded live stream. The request should contain:
|
||||
# "http://xxxx?date=[YYYY-MM-DDT][[HH:]MM:]SS[.m...]".You must specify
|
||||
# a path where the feed is stored on disk. You also specify the
|
||||
# maximum size of the feed, where zero means unlimited. Default:
|
||||
# File=/tmp/feed_name.ffm FileMaxSize=5M
|
||||
File /tmp/feed1.ffm
|
||||
FileMaxSize 200K
|
||||
|
||||
# You could specify
|
||||
# ReadOnlyFile /saved/specialvideo.ffm
|
||||
# This marks the file as readonly and it will not be deleted or updated.
|
||||
|
||||
# Specify launch in order to start ffmpeg automatically.
|
||||
# First ffmpeg must be defined with an appropriate path if needed,
|
||||
# after that options can follow, but avoid adding the http:// field
|
||||
#Launch ffmpeg
|
||||
|
||||
# Only allow connections from localhost to the feed.
|
||||
ACL allow 127.0.0.1
|
||||
|
||||
</Feed>
|
||||
|
||||
|
||||
##################################################################
|
||||
# Now you can define each stream which will be generated from the
|
||||
# original audio and video stream. Each format has a filename (here
|
||||
# 'test1.mpg'). FFServer will send this stream when answering a
|
||||
# request containing this filename.
|
||||
|
||||
<Stream test1.mpg>
|
||||
|
||||
# coming from live feed 'feed1'
|
||||
Feed feed1.ffm
|
||||
|
||||
# Format of the stream : you can choose among:
|
||||
# mpeg : MPEG-1 multiplexed video and audio
|
||||
# mpegvideo : only MPEG-1 video
|
||||
# mp2 : MPEG-2 audio (use AudioCodec to select layer 2 and 3 codec)
|
||||
# ogg : Ogg format (Vorbis audio codec)
|
||||
# rm : RealNetworks-compatible stream. Multiplexed audio and video.
|
||||
# ra : RealNetworks-compatible stream. Audio only.
|
||||
# mpjpeg : Multipart JPEG (works with Netscape without any plugin)
|
||||
# jpeg : Generate a single JPEG image.
|
||||
# mjpeg : Generate a M-JPEG stream.
|
||||
# asf : ASF compatible streaming (Windows Media Player format).
|
||||
# swf : Macromedia Flash compatible stream
|
||||
# avi : AVI format (MPEG-4 video, MPEG audio sound)
|
||||
Format mpeg
|
||||
|
||||
# Bitrate for the audio stream. Codecs usually support only a few
|
||||
# different bitrates.
|
||||
AudioBitRate 32
|
||||
|
||||
# Number of audio channels: 1 = mono, 2 = stereo
|
||||
AudioChannels 1
|
||||
|
||||
# Sampling frequency for audio. When using low bitrates, you should
|
||||
# lower this frequency to 22050 or 11025. The supported frequencies
|
||||
# depend on the selected audio codec.
|
||||
AudioSampleRate 44100
|
||||
|
||||
# Bitrate for the video stream
|
||||
VideoBitRate 64
|
||||
|
||||
# Ratecontrol buffer size
|
||||
VideoBufferSize 40
|
||||
|
||||
# Number of frames per second
|
||||
VideoFrameRate 3
|
||||
|
||||
# Size of the video frame: WxH (default: 160x128)
|
||||
# The following abbreviations are defined: sqcif, qcif, cif, 4cif, qqvga,
|
||||
# qvga, vga, svga, xga, uxga, qxga, sxga, qsxga, hsxga, wvga, wxga, wsxga,
|
||||
# wuxga, woxga, wqsxga, wquxga, whsxga, whuxga, cga, ega, hd480, hd720,
|
||||
# hd1080
|
||||
VideoSize 160x128
|
||||
|
||||
# Transmit only intra frames (useful for low bitrates, but kills frame rate).
|
||||
#VideoIntraOnly
|
||||
|
||||
# If non-intra only, an intra frame is transmitted every VideoGopSize
|
||||
# frames. Video synchronization can only begin at an intra frame.
|
||||
VideoGopSize 12
|
||||
|
||||
# More MPEG-4 parameters
|
||||
# VideoHighQuality
|
||||
# Video4MotionVector
|
||||
|
||||
# Choose your codecs:
|
||||
#AudioCodec mp2
|
||||
#VideoCodec mpeg1video
|
||||
|
||||
# Suppress audio
|
||||
#NoAudio
|
||||
|
||||
# Suppress video
|
||||
#NoVideo
|
||||
|
||||
#VideoQMin 3
|
||||
#VideoQMax 31
|
||||
|
||||
# Set this to the number of seconds backwards in time to start. Note that
|
||||
# most players will buffer 5-10 seconds of video, and also you need to allow
|
||||
# for a keyframe to appear in the data stream.
|
||||
#Preroll 15
|
||||
|
||||
# ACL:
|
||||
|
||||
# You can allow ranges of addresses (or single addresses)
|
||||
#ACL ALLOW <first address> <last address>
|
||||
|
||||
# You can deny ranges of addresses (or single addresses)
|
||||
#ACL DENY <first address> <last address>
|
||||
|
||||
# You can repeat the ACL allow/deny as often as you like. It is on a per
|
||||
# stream basis. The first match defines the action. If there are no matches,
|
||||
# then the default is the inverse of the last ACL statement.
|
||||
#
|
||||
# Thus 'ACL allow localhost' only allows access from localhost.
|
||||
# 'ACL deny 1.0.0.0 1.255.255.255' would deny the whole of network 1 and
|
||||
# allow everybody else.
|
||||
|
||||
</Stream>
|
||||
|
||||
|
||||
##################################################################
|
||||
# Example streams
|
||||
|
||||
|
||||
# Multipart JPEG
|
||||
|
||||
#<Stream test.mjpg>
|
||||
#Feed feed1.ffm
|
||||
#Format mpjpeg
|
||||
#VideoFrameRate 2
|
||||
#VideoIntraOnly
|
||||
#NoAudio
|
||||
#Strict -1
|
||||
#</Stream>
|
||||
|
||||
|
||||
# Single JPEG
|
||||
|
||||
#<Stream test.jpg>
|
||||
#Feed feed1.ffm
|
||||
#Format jpeg
|
||||
#VideoFrameRate 2
|
||||
#VideoIntraOnly
|
||||
##VideoSize 352x240
|
||||
#NoAudio
|
||||
#Strict -1
|
||||
#</Stream>
|
||||
|
||||
|
||||
# Flash
|
||||
|
||||
#<Stream test.swf>
|
||||
#Feed feed1.ffm
|
||||
#Format swf
|
||||
#VideoFrameRate 2
|
||||
#VideoIntraOnly
|
||||
#NoAudio
|
||||
#</Stream>
|
||||
|
||||
|
||||
# ASF compatible
|
||||
|
||||
<Stream test.asf>
|
||||
Feed feed1.ffm
|
||||
Format asf
|
||||
VideoFrameRate 15
|
||||
VideoSize 352x240
|
||||
VideoBitRate 256
|
||||
VideoBufferSize 40
|
||||
VideoGopSize 30
|
||||
AudioBitRate 64
|
||||
StartSendOnKey
|
||||
</Stream>
|
||||
|
||||
|
||||
# MP3 audio
|
||||
|
||||
#<Stream test.mp3>
|
||||
#Feed feed1.ffm
|
||||
#Format mp2
|
||||
#AudioCodec mp3
|
||||
#AudioBitRate 64
|
||||
#AudioChannels 1
|
||||
#AudioSampleRate 44100
|
||||
#NoVideo
|
||||
#</Stream>
|
||||
|
||||
|
||||
# Ogg Vorbis audio
|
||||
|
||||
#<Stream test.ogg>
|
||||
#Feed feed1.ffm
|
||||
#Metadata title "Stream title"
|
||||
#AudioBitRate 64
|
||||
#AudioChannels 2
|
||||
#AudioSampleRate 44100
|
||||
#NoVideo
|
||||
#</Stream>
|
||||
|
||||
|
||||
# Real with audio only at 32 kbits
|
||||
|
||||
#<Stream test.ra>
|
||||
#Feed feed1.ffm
|
||||
#Format rm
|
||||
#AudioBitRate 32
|
||||
#NoVideo
|
||||
#NoAudio
|
||||
#</Stream>
|
||||
|
||||
|
||||
# Real with audio and video at 64 kbits
|
||||
|
||||
#<Stream test.rm>
|
||||
#Feed feed1.ffm
|
||||
#Format rm
|
||||
#AudioBitRate 32
|
||||
#VideoBitRate 128
|
||||
#VideoFrameRate 25
|
||||
#VideoGopSize 25
|
||||
#NoAudio
|
||||
#</Stream>
|
||||
|
||||
|
||||
##################################################################
|
||||
# A stream coming from a file: you only need to set the input
|
||||
# filename and optionally a new format. Supported conversions:
|
||||
# AVI -> ASF
|
||||
|
||||
#<Stream file.rm>
|
||||
#File "/usr/local/httpd/htdocs/tlive.rm"
|
||||
#NoAudio
|
||||
#</Stream>
|
||||
|
||||
#<Stream file.asf>
|
||||
#File "/usr/local/httpd/htdocs/test.asf"
|
||||
#NoAudio
|
||||
#Metadata author "Me"
|
||||
#Metadata copyright "Super MegaCorp"
|
||||
#Metadata title "Test stream from disk"
|
||||
#Metadata comment "Test comment"
|
||||
#</Stream>
|
||||
|
||||
|
||||
##################################################################
|
||||
# RTSP examples
|
||||
#
|
||||
# You can access this stream with the RTSP URL:
|
||||
# rtsp://localhost:5454/test1-rtsp.mpg
|
||||
#
|
||||
# A non-standard RTSP redirector is also created. Its URL is:
|
||||
# http://localhost:8090/test1-rtsp.rtsp
|
||||
|
||||
#<Stream test1-rtsp.mpg>
|
||||
#Format rtp
|
||||
#File "/usr/local/httpd/htdocs/test1.mpg"
|
||||
#</Stream>
|
||||
|
||||
|
||||
# Transcode an incoming live feed to another live feed,
|
||||
# using libx264 and video presets
|
||||
|
||||
#<Stream live.h264>
|
||||
#Format rtp
|
||||
#Feed feed1.ffm
|
||||
#VideoCodec libx264
|
||||
#VideoFrameRate 24
|
||||
#VideoBitRate 100
|
||||
#VideoSize 480x272
|
||||
#AVPresetVideo default
|
||||
#AVPresetVideo baseline
|
||||
#AVOptionVideo flags +global_header
|
||||
#
|
||||
#AudioCodec aac
|
||||
#AudioBitRate 32
|
||||
#AudioChannels 2
|
||||
#AudioSampleRate 22050
|
||||
#AVOptionAudio flags +global_header
|
||||
#</Stream>
|
||||
|
||||
##################################################################
|
||||
# SDP/multicast examples
|
||||
#
|
||||
# If you want to send your stream in multicast, you must set the
|
||||
# multicast address with MulticastAddress. The port and the TTL can
|
||||
# also be set.
|
||||
#
|
||||
# An SDP file is automatically generated by ffserver by adding the
|
||||
# 'sdp' extension to the stream name (here
|
||||
# http://localhost:8090/test1-sdp.sdp). You should usually give this
|
||||
# file to your player to play the stream.
|
||||
#
|
||||
# The 'NoLoop' option can be used to avoid looping when the stream is
|
||||
# terminated.
|
||||
|
||||
#<Stream test1-sdp.mpg>
|
||||
#Format rtp
|
||||
#File "/usr/local/httpd/htdocs/test1.mpg"
|
||||
#MulticastAddress 224.124.0.1
|
||||
#MulticastPort 5000
|
||||
#MulticastTTL 16
|
||||
#NoLoop
|
||||
#</Stream>
|
||||
|
||||
|
||||
##################################################################
|
||||
# Special streams
|
||||
|
||||
# Server status
|
||||
|
||||
<Stream stat.html>
|
||||
Format status
|
||||
|
||||
# Only allow local people to get the status
|
||||
ACL allow localhost
|
||||
ACL allow 192.168.0.0 192.168.255.255
|
||||
|
||||
#FaviconURL http://pond1.gladstonefamily.net:8080/favicon.ico
|
||||
</Stream>
|
||||
|
||||
|
||||
# Redirect index.html to the appropriate site
|
||||
|
||||
<Redirect index.html>
|
||||
URL http://www.ffmpeg.org/
|
||||
</Redirect>
|
||||
@@ -1,923 +0,0 @@
|
||||
\input texinfo @c -*- texinfo -*-
|
||||
@documentencoding UTF-8
|
||||
|
||||
@settitle ffserver Documentation
|
||||
@titlepage
|
||||
@center @titlefont{ffserver Documentation}
|
||||
@end titlepage
|
||||
|
||||
@top
|
||||
|
||||
@contents
|
||||
|
||||
@chapter Synopsis
|
||||
|
||||
ffserver [@var{options}]
|
||||
|
||||
@chapter Description
|
||||
@c man begin DESCRIPTION
|
||||
|
||||
@command{ffserver} is a streaming server for both audio and video.
|
||||
It supports several live feeds, streaming from files and time shifting
|
||||
on live feeds. You can seek to positions in the past on each live
|
||||
feed, provided you specify a big enough feed storage.
|
||||
|
||||
@command{ffserver} is configured through a configuration file, which
|
||||
is read at startup. If not explicitly specified, it will read from
|
||||
@file{/etc/ffserver.conf}.
|
||||
|
||||
@command{ffserver} receives prerecorded files or FFM streams from some
|
||||
@command{ffmpeg} instance as input, then streams them over
|
||||
RTP/RTSP/HTTP.
|
||||
|
||||
An @command{ffserver} instance will listen on some port as specified
|
||||
in the configuration file. You can launch one or more instances of
|
||||
@command{ffmpeg} and send one or more FFM streams to the port where
|
||||
ffserver is expecting to receive them. Alternately, you can make
|
||||
@command{ffserver} launch such @command{ffmpeg} instances at startup.
|
||||
|
||||
Input streams are called feeds, and each one is specified by a
|
||||
@code{<Feed>} section in the configuration file.
|
||||
|
||||
For each feed you can have different output streams in various
|
||||
formats, each one specified by a @code{<Stream>} section in the
|
||||
configuration file.
|
||||
|
||||
@chapter Detailed description
|
||||
|
||||
@command{ffserver} works by forwarding streams encoded by
|
||||
@command{ffmpeg}, or pre-recorded streams which are read from disk.
|
||||
|
||||
Precisely, @command{ffserver} acts as an HTTP server, accepting POST
|
||||
requests from @command{ffmpeg} to acquire the stream to publish, and
|
||||
serving RTSP clients or HTTP clients GET requests with the stream
|
||||
media content.
|
||||
|
||||
A feed is an @ref{FFM} stream created by @command{ffmpeg}, and sent to
|
||||
a port where @command{ffserver} is listening.
|
||||
|
||||
Each feed is identified by a unique name, corresponding to the name
|
||||
of the resource published on @command{ffserver}, and is configured by
|
||||
a dedicated @code{Feed} section in the configuration file.
|
||||
|
||||
The feed publish URL is given by:
|
||||
@example
|
||||
http://@var{ffserver_ip_address}:@var{http_port}/@var{feed_name}
|
||||
@end example
|
||||
|
||||
where @var{ffserver_ip_address} is the IP address of the machine where
|
||||
@command{ffserver} is installed, @var{http_port} is the port number of
|
||||
the HTTP server (configured through the @option{HTTPPort} option), and
|
||||
@var{feed_name} is the name of the corresponding feed defined in the
|
||||
configuration file.
|
||||
|
||||
Each feed is associated to a file which is stored on disk. This stored
|
||||
file is used to send pre-recorded data to a player as fast as
|
||||
possible when new content is added in real-time to the stream.
|
||||
|
||||
A "live-stream" or "stream" is a resource published by
|
||||
@command{ffserver}, and made accessible through the HTTP protocol to
|
||||
clients.
|
||||
|
||||
A stream can be connected to a feed, or to a file. In the first case,
|
||||
the published stream is forwarded from the corresponding feed
|
||||
generated by a running instance of @command{ffmpeg}, in the second
|
||||
case the stream is read from a pre-recorded file.
|
||||
|
||||
Each stream is identified by a unique name, corresponding to the name
|
||||
of the resource served by @command{ffserver}, and is configured by
|
||||
a dedicated @code{Stream} section in the configuration file.
|
||||
|
||||
The stream access HTTP URL is given by:
|
||||
@example
|
||||
http://@var{ffserver_ip_address}:@var{http_port}/@var{stream_name}[@var{options}]
|
||||
@end example
|
||||
|
||||
The stream access RTSP URL is given by:
|
||||
@example
|
||||
http://@var{ffserver_ip_address}:@var{rtsp_port}/@var{stream_name}[@var{options}]
|
||||
@end example
|
||||
|
||||
@var{stream_name} is the name of the corresponding stream defined in
|
||||
the configuration file. @var{options} is a list of options specified
|
||||
after the URL which affects how the stream is served by
|
||||
@command{ffserver}. @var{http_port} and @var{rtsp_port} are the HTTP
|
||||
and RTSP ports configured with the options @var{HTTPPort} and
|
||||
@var{RTSPPort} respectively.
|
||||
|
||||
In case the stream is associated to a feed, the encoding parameters
|
||||
must be configured in the stream configuration. They are sent to
|
||||
@command{ffmpeg} when setting up the encoding. This allows
|
||||
@command{ffserver} to define the encoding parameters used by
|
||||
the @command{ffmpeg} encoders.
|
||||
|
||||
The @command{ffmpeg} @option{override_ffserver} commandline option
|
||||
allows one to override the encoding parameters set by the server.
|
||||
|
||||
Multiple streams can be connected to the same feed.
|
||||
|
||||
For example, you can have a situation described by the following
|
||||
graph:
|
||||
|
||||
@verbatim
|
||||
_________ __________
|
||||
| | | |
|
||||
ffmpeg 1 -----| feed 1 |-----| stream 1 |
|
||||
\ |_________|\ |__________|
|
||||
\ \
|
||||
\ \ __________
|
||||
\ \ | |
|
||||
\ \| stream 2 |
|
||||
\ |__________|
|
||||
\
|
||||
\ _________ __________
|
||||
\ | | | |
|
||||
\| feed 2 |-----| stream 3 |
|
||||
|_________| |__________|
|
||||
|
||||
_________ __________
|
||||
| | | |
|
||||
ffmpeg 2 -----| feed 3 |-----| stream 4 |
|
||||
|_________| |__________|
|
||||
|
||||
_________ __________
|
||||
| | | |
|
||||
| file 1 |-----| stream 5 |
|
||||
|_________| |__________|
|
||||
|
||||
@end verbatim
|
||||
|
||||
@anchor{FFM}
|
||||
@section FFM, FFM2 formats
|
||||
|
||||
FFM and FFM2 are formats used by ffserver. They allow storing a wide variety of
|
||||
video and audio streams and encoding options, and can store a moving time segment
|
||||
of an infinite movie or a whole movie.
|
||||
|
||||
FFM is version specific, and there is limited compatibility of FFM files
|
||||
generated by one version of ffmpeg/ffserver and another version of
|
||||
ffmpeg/ffserver. It may work but it is not guaranteed to work.
|
||||
|
||||
FFM2 is extensible while maintaining compatibility and should work between
|
||||
differing versions of tools. FFM2 is the default.
|
||||
|
||||
@section Status stream
|
||||
|
||||
@command{ffserver} supports an HTTP interface which exposes the
|
||||
current status of the server.
|
||||
|
||||
Simply point your browser to the address of the special status stream
|
||||
specified in the configuration file.
|
||||
|
||||
For example if you have:
|
||||
@example
|
||||
<Stream status.html>
|
||||
Format status
|
||||
|
||||
# Only allow local people to get the status
|
||||
ACL allow localhost
|
||||
ACL allow 192.168.0.0 192.168.255.255
|
||||
</Stream>
|
||||
@end example
|
||||
|
||||
then the server will post a page with the status information when
|
||||
the special stream @file{status.html} is requested.
|
||||
|
||||
@section How do I make it work?
|
||||
|
||||
As a simple test, just run the following two command lines where INPUTFILE
|
||||
is some file which you can decode with ffmpeg:
|
||||
|
||||
@example
|
||||
ffserver -f doc/ffserver.conf &
|
||||
ffmpeg -i INPUTFILE http://localhost:8090/feed1.ffm
|
||||
@end example
|
||||
|
||||
At this point you should be able to go to your Windows machine and fire up
|
||||
Windows Media Player (WMP). Go to Open URL and enter
|
||||
|
||||
@example
|
||||
http://<linuxbox>:8090/test.asf
|
||||
@end example
|
||||
|
||||
You should (after a short delay) see video and hear audio.
|
||||
|
||||
WARNING: trying to stream test1.mpg doesn't work with WMP as it tries to
|
||||
transfer the entire file before starting to play.
|
||||
The same is true of AVI files.
|
||||
|
||||
You should edit the @file{ffserver.conf} file to suit your needs (in
|
||||
terms of frame rates etc). Then install @command{ffserver} and
|
||||
@command{ffmpeg}, write a script to start them up, and off you go.
|
||||
|
||||
@section What else can it do?
|
||||
|
||||
You can replay video from .ffm files that was recorded earlier.
|
||||
However, there are a number of caveats, including the fact that the
|
||||
ffserver parameters must match the original parameters used to record the
|
||||
file. If they do not, then ffserver deletes the file before recording into it.
|
||||
(Now that I write this, it seems broken).
|
||||
|
||||
You can fiddle with many of the codec choices and encoding parameters, and
|
||||
there are a bunch more parameters that you cannot control. Post a message
|
||||
to the mailing list if there are some 'must have' parameters. Look in
|
||||
ffserver.conf for a list of the currently available controls.
|
||||
|
||||
It will automatically generate the ASX or RAM files that are often used
|
||||
in browsers. These files are actually redirections to the underlying ASF
|
||||
or RM file. The reason for this is that the browser often fetches the
|
||||
entire file before starting up the external viewer. The redirection files
|
||||
are very small and can be transferred quickly. [The stream itself is
|
||||
often 'infinite' and thus the browser tries to download it and never
|
||||
finishes.]
|
||||
|
||||
@section Tips
|
||||
|
||||
* When you connect to a live stream, most players (WMP, RA, etc) want to
|
||||
buffer a certain number of seconds of material so that they can display the
|
||||
signal continuously. However, ffserver (by default) starts sending data
|
||||
in realtime. This means that there is a pause of a few seconds while the
|
||||
buffering is being done by the player. The good news is that this can be
|
||||
cured by adding a '?buffer=5' to the end of the URL. This means that the
|
||||
stream should start 5 seconds in the past -- and so the first 5 seconds
|
||||
of the stream are sent as fast as the network will allow. It will then
|
||||
slow down to real time. This noticeably improves the startup experience.
|
||||
|
||||
You can also add a 'Preroll 15' statement into the ffserver.conf that will
|
||||
add the 15 second prebuffering on all requests that do not otherwise
|
||||
specify a time. In addition, ffserver will skip frames until a key_frame
|
||||
is found. This further reduces the startup delay by not transferring data
|
||||
that will be discarded.
|
||||
|
||||
@section Why does the ?buffer / Preroll stop working after a time?
|
||||
|
||||
It turns out that (on my machine at least) the number of frames successfully
|
||||
grabbed is marginally less than the number that ought to be grabbed. This
|
||||
means that the timestamp in the encoded data stream gets behind realtime.
|
||||
This means that if you say 'Preroll 10', then when the stream gets 10
|
||||
or more seconds behind, there is no Preroll left.
|
||||
|
||||
Fixing this requires a change in the internals of how timestamps are
|
||||
handled.
|
||||
|
||||
@section Does the @code{?date=} stuff work.
|
||||
|
||||
Yes (subject to the limitation outlined above). Also note that whenever you
|
||||
start ffserver, it deletes the ffm file (if any parameters have changed),
|
||||
thus wiping out what you had recorded before.
|
||||
|
||||
The format of the @code{?date=xxxxxx} is fairly flexible. You should use one
|
||||
of the following formats (the 'T' is literal):
|
||||
|
||||
@example
|
||||
* YYYY-MM-DDTHH:MM:SS (localtime)
|
||||
* YYYY-MM-DDTHH:MM:SSZ (UTC)
|
||||
@end example
|
||||
|
||||
You can omit the YYYY-MM-DD, and then it refers to the current day. However
|
||||
note that @samp{?date=16:00:00} refers to 16:00 on the current day -- this
|
||||
may be in the future and so is unlikely to be useful.
|
||||
|
||||
You use this by adding the ?date= to the end of the URL for the stream.
|
||||
For example: @samp{http://localhost:8080/test.asf?date=2002-07-26T23:05:00}.
|
||||
@c man end
|
||||
|
||||
@chapter Options
|
||||
@c man begin OPTIONS
|
||||
|
||||
@include fftools-common-opts.texi
|
||||
|
||||
@section Main options
|
||||
|
||||
@table @option
|
||||
@item -f @var{configfile}
|
||||
Read configuration file @file{configfile}. If not specified it will
|
||||
read by default from @file{/etc/ffserver.conf}.
|
||||
|
||||
@item -n
|
||||
Enable no-launch mode. This option disables all the @code{Launch}
|
||||
directives within the various @code{<Feed>} sections. Since
|
||||
@command{ffserver} will not launch any @command{ffmpeg} instances, you
|
||||
will have to launch them manually.
|
||||
|
||||
@item -d
|
||||
Enable debug mode. This option increases log verbosity, and directs
|
||||
log messages to stdout. When specified, the @option{CustomLog} option
|
||||
is ignored.
|
||||
@end table
|
||||
|
||||
@chapter Configuration file syntax
|
||||
|
||||
@command{ffserver} reads a configuration file containing global
|
||||
options and settings for each stream and feed.
|
||||
|
||||
The configuration file consists of global options and dedicated
|
||||
sections, which must be introduced by "<@var{SECTION_NAME}
|
||||
@var{ARGS}>" on a separate line and must be terminated by a line in
|
||||
the form "</@var{SECTION_NAME}>". @var{ARGS} is optional.
|
||||
|
||||
Currently the following sections are recognized: @samp{Feed},
|
||||
@samp{Stream}, @samp{Redirect}.
|
||||
|
||||
A line starting with @code{#} is ignored and treated as a comment.
|
||||
|
||||
Name of options and sections are case-insensitive.
|
||||
|
||||
@section ACL syntax
|
||||
An ACL (Access Control List) specifies the address which are allowed
|
||||
to access a given stream, or to write a given feed.
|
||||
|
||||
It accepts the following forms
|
||||
@itemize
|
||||
@item
|
||||
Allow/deny access to @var{address}.
|
||||
@example
|
||||
ACL ALLOW <address>
|
||||
ACL DENY <address>
|
||||
@end example
|
||||
|
||||
@item
|
||||
Allow/deny access to ranges of addresses from @var{first_address} to
|
||||
@var{last_address}.
|
||||
@example
|
||||
ACL ALLOW <first_address> <last_address>
|
||||
ACL DENY <first_address> <last_address>
|
||||
@end example
|
||||
@end itemize
|
||||
|
||||
You can repeat the ACL allow/deny as often as you like. It is on a per
|
||||
stream basis. The first match defines the action. If there are no matches,
|
||||
then the default is the inverse of the last ACL statement.
|
||||
|
||||
Thus 'ACL allow localhost' only allows access from localhost.
|
||||
'ACL deny 1.0.0.0 1.255.255.255' would deny the whole of network 1 and
|
||||
allow everybody else.
|
||||
|
||||
@section Global options
|
||||
@table @option
|
||||
@item HTTPPort @var{port_number}
|
||||
@item Port @var{port_number}
|
||||
@item RTSPPort @var{port_number}
|
||||
|
||||
@var{HTTPPort} sets the HTTP server listening TCP port number,
|
||||
@var{RTSPPort} sets the RTSP server listening TCP port number.
|
||||
|
||||
@var{Port} is the equivalent of @var{HTTPPort} and is deprecated.
|
||||
|
||||
You must select a different port from your standard HTTP web server if
|
||||
it is running on the same computer.
|
||||
|
||||
If not specified, no corresponding server will be created.
|
||||
|
||||
@item HTTPBindAddress @var{ip_address}
|
||||
@item BindAddress @var{ip_address}
|
||||
@item RTSPBindAddress @var{ip_address}
|
||||
Set address on which the HTTP/RTSP server is bound. Only useful if you
|
||||
have several network interfaces.
|
||||
|
||||
@var{BindAddress} is the equivalent of @var{HTTPBindAddress} and is
|
||||
deprecated.
|
||||
|
||||
@item MaxHTTPConnections @var{n}
|
||||
Set number of simultaneous HTTP connections that can be handled. It
|
||||
has to be defined @emph{before} the @option{MaxClients} parameter,
|
||||
since it defines the @option{MaxClients} maximum limit.
|
||||
|
||||
Default value is 2000.
|
||||
|
||||
@item MaxClients @var{n}
|
||||
Set number of simultaneous requests that can be handled. Since
|
||||
@command{ffserver} is very fast, it is more likely that you will want
|
||||
to leave this high and use @option{MaxBandwidth}.
|
||||
|
||||
Default value is 5.
|
||||
|
||||
@item MaxBandwidth @var{kbps}
|
||||
Set the maximum amount of kbit/sec that you are prepared to consume
|
||||
when streaming to clients.
|
||||
|
||||
Default value is 1000.
|
||||
|
||||
@item CustomLog @var{filename}
|
||||
Set access log file (uses standard Apache log file format). '-' is the
|
||||
standard output.
|
||||
|
||||
If not specified @command{ffserver} will produce no log.
|
||||
|
||||
In case the commandline option @option{-d} is specified this option is
|
||||
ignored, and the log is written to standard output.
|
||||
|
||||
@item NoDaemon
|
||||
Set no-daemon mode. This option is currently ignored since now
|
||||
@command{ffserver} will always work in no-daemon mode, and is
|
||||
deprecated.
|
||||
|
||||
@item UseDefaults
|
||||
@item NoDefaults
|
||||
Control whether default codec options are used for the all streams or not.
|
||||
Each stream may overwrite this setting for its own. Default is @var{UseDefaults}.
|
||||
The last occurrence overrides the previous if multiple definitions exist.
|
||||
@end table
|
||||
|
||||
@section Feed section
|
||||
|
||||
A Feed section defines a feed provided to @command{ffserver}.
|
||||
|
||||
Each live feed contains one video and/or audio sequence coming from an
|
||||
@command{ffmpeg} encoder or another @command{ffserver}. This sequence
|
||||
may be encoded simultaneously with several codecs at several
|
||||
resolutions.
|
||||
|
||||
A feed instance specification is introduced by a line in the form:
|
||||
@example
|
||||
<Feed FEED_FILENAME>
|
||||
@end example
|
||||
|
||||
where @var{FEED_FILENAME} specifies the unique name of the FFM stream.
|
||||
|
||||
The following options are recognized within a Feed section.
|
||||
|
||||
@table @option
|
||||
@item File @var{filename}
|
||||
@item ReadOnlyFile @var{filename}
|
||||
Set the path where the feed file is stored on disk.
|
||||
|
||||
If not specified, the @file{/tmp/FEED.ffm} is assumed, where
|
||||
@var{FEED} is the feed name.
|
||||
|
||||
If @option{ReadOnlyFile} is used the file is marked as read-only and
|
||||
it will not be deleted or updated.
|
||||
|
||||
@item Truncate
|
||||
Truncate the feed file, rather than appending to it. By default
|
||||
@command{ffserver} will append data to the file, until the maximum
|
||||
file size value is reached (see @option{FileMaxSize} option).
|
||||
|
||||
@item FileMaxSize @var{size}
|
||||
Set maximum size of the feed file in bytes. 0 means unlimited. The
|
||||
postfixes @code{K} (2^10), @code{M} (2^20), and @code{G} (2^30) are
|
||||
recognized.
|
||||
|
||||
Default value is 5M.
|
||||
|
||||
@item Launch @var{args}
|
||||
Launch an @command{ffmpeg} command when creating @command{ffserver}.
|
||||
|
||||
@var{args} must be a sequence of arguments to be provided to an
|
||||
@command{ffmpeg} instance. The first provided argument is ignored, and
|
||||
it is replaced by a path with the same dirname of the @command{ffserver}
|
||||
instance, followed by the remaining argument and terminated with a
|
||||
path corresponding to the feed.
|
||||
|
||||
When the launched process exits, @command{ffserver} will launch
|
||||
another program instance.
|
||||
|
||||
In case you need a more complex @command{ffmpeg} configuration,
|
||||
e.g. if you need to generate multiple FFM feeds with a single
|
||||
@command{ffmpeg} instance, you should launch @command{ffmpeg} by hand.
|
||||
|
||||
This option is ignored in case the commandline option @option{-n} is
|
||||
specified.
|
||||
|
||||
@item ACL @var{spec}
|
||||
Specify the list of IP address which are allowed or denied to write
|
||||
the feed. Multiple ACL options can be specified.
|
||||
@end table
|
||||
|
||||
@section Stream section
|
||||
|
||||
A Stream section defines a stream provided by @command{ffserver}, and
|
||||
identified by a single name.
|
||||
|
||||
The stream is sent when answering a request containing the stream
|
||||
name.
|
||||
|
||||
A stream section must be introduced by the line:
|
||||
@example
|
||||
<Stream STREAM_NAME>
|
||||
@end example
|
||||
|
||||
where @var{STREAM_NAME} specifies the unique name of the stream.
|
||||
|
||||
The following options are recognized within a Stream section.
|
||||
|
||||
Encoding options are marked with the @emph{encoding} tag, and they are
|
||||
used to set the encoding parameters, and are mapped to libavcodec
|
||||
encoding options. Not all encoding options are supported, in
|
||||
particular it is not possible to set encoder private options. In order
|
||||
to override the encoding options specified by @command{ffserver}, you
|
||||
can use the @command{ffmpeg} @option{override_ffserver} commandline
|
||||
option.
|
||||
|
||||
Only one of the @option{Feed} and @option{File} options should be set.
|
||||
|
||||
@table @option
|
||||
@item Feed @var{feed_name}
|
||||
Set the input feed. @var{feed_name} must correspond to an existing
|
||||
feed defined in a @code{Feed} section.
|
||||
|
||||
When this option is set, encoding options are used to setup the
|
||||
encoding operated by the remote @command{ffmpeg} process.
|
||||
|
||||
@item File @var{filename}
|
||||
Set the filename of the pre-recorded input file to stream.
|
||||
|
||||
When this option is set, encoding options are ignored and the input
|
||||
file content is re-streamed as is.
|
||||
|
||||
@item Format @var{format_name}
|
||||
Set the format of the output stream.
|
||||
|
||||
Must be the name of a format recognized by FFmpeg. If set to
|
||||
@samp{status}, it is treated as a status stream.
|
||||
|
||||
@item InputFormat @var{format_name}
|
||||
Set input format. If not specified, it is automatically guessed.
|
||||
|
||||
@item Preroll @var{n}
|
||||
Set this to the number of seconds backwards in time to start. Note that
|
||||
most players will buffer 5-10 seconds of video, and also you need to allow
|
||||
for a keyframe to appear in the data stream.
|
||||
|
||||
Default value is 0.
|
||||
|
||||
@item StartSendOnKey
|
||||
Do not send stream until it gets the first key frame. By default
|
||||
@command{ffserver} will send data immediately.
|
||||
|
||||
@item MaxTime @var{n}
|
||||
Set the number of seconds to run. This value set the maximum duration
|
||||
of the stream a client will be able to receive.
|
||||
|
||||
A value of 0 means that no limit is set on the stream duration.
|
||||
|
||||
@item ACL @var{spec}
|
||||
Set ACL for the stream.
|
||||
|
||||
@item DynamicACL @var{spec}
|
||||
|
||||
@item RTSPOption @var{option}
|
||||
|
||||
@item MulticastAddress @var{address}
|
||||
|
||||
@item MulticastPort @var{port}
|
||||
|
||||
@item MulticastTTL @var{integer}
|
||||
|
||||
@item NoLoop
|
||||
|
||||
@item FaviconURL @var{url}
|
||||
Set favicon (favourite icon) for the server status page. It is ignored
|
||||
for regular streams.
|
||||
|
||||
@item Author @var{value}
|
||||
@item Comment @var{value}
|
||||
@item Copyright @var{value}
|
||||
@item Title @var{value}
|
||||
Set metadata corresponding to the option. All these options are
|
||||
deprecated in favor of @option{Metadata}.
|
||||
|
||||
@item Metadata @var{key} @var{value}
|
||||
Set metadata value on the output stream.
|
||||
|
||||
@item UseDefaults
|
||||
@item NoDefaults
|
||||
Control whether default codec options are used for the stream or not.
|
||||
Default is @var{UseDefaults} unless disabled globally.
|
||||
|
||||
@item NoAudio
|
||||
@item NoVideo
|
||||
Suppress audio/video.
|
||||
|
||||
@item AudioCodec @var{codec_name} (@emph{encoding,audio})
|
||||
Set audio codec.
|
||||
|
||||
@item AudioBitRate @var{rate} (@emph{encoding,audio})
|
||||
Set bitrate for the audio stream in kbits per second.
|
||||
|
||||
@item AudioChannels @var{n} (@emph{encoding,audio})
|
||||
Set number of audio channels.
|
||||
|
||||
@item AudioSampleRate @var{n} (@emph{encoding,audio})
|
||||
Set sampling frequency for audio. When using low bitrates, you should
|
||||
lower this frequency to 22050 or 11025. The supported frequencies
|
||||
depend on the selected audio codec.
|
||||
|
||||
@item AVOptionAudio [@var{codec}:]@var{option} @var{value} (@emph{encoding,audio})
|
||||
Set generic or private option for audio stream.
|
||||
Private option must be prefixed with codec name or codec must be defined before.
|
||||
|
||||
@item AVPresetAudio @var{preset} (@emph{encoding,audio})
|
||||
Set preset for audio stream.
|
||||
|
||||
@item VideoCodec @var{codec_name} (@emph{encoding,video})
|
||||
Set video codec.
|
||||
|
||||
@item VideoBitRate @var{n} (@emph{encoding,video})
|
||||
Set bitrate for the video stream in kbits per second.
|
||||
|
||||
@item VideoBitRateRange @var{range} (@emph{encoding,video})
|
||||
Set video bitrate range.
|
||||
|
||||
A range must be specified in the form @var{minrate}-@var{maxrate}, and
|
||||
specifies the @option{minrate} and @option{maxrate} encoding options
|
||||
expressed in kbits per second.
|
||||
|
||||
@item VideoBitRateRangeTolerance @var{n} (@emph{encoding,video})
|
||||
Set video bitrate tolerance in kbits per second.
|
||||
|
||||
@item PixelFormat @var{pixel_format} (@emph{encoding,video})
|
||||
Set video pixel format.
|
||||
|
||||
@item Debug @var{integer} (@emph{encoding,video})
|
||||
Set video @option{debug} encoding option.
|
||||
|
||||
@item Strict @var{integer} (@emph{encoding,video})
|
||||
Set video @option{strict} encoding option.
|
||||
|
||||
@item VideoBufferSize @var{n} (@emph{encoding,video})
|
||||
Set ratecontrol buffer size, expressed in KB.
|
||||
|
||||
@item VideoFrameRate @var{n} (@emph{encoding,video})
|
||||
Set number of video frames per second.
|
||||
|
||||
@item VideoSize (@emph{encoding,video})
|
||||
Set size of the video frame, must be an abbreviation or in the form
|
||||
@var{W}x@var{H}. See @ref{video size syntax,,the Video size section
|
||||
in the ffmpeg-utils(1) manual,ffmpeg-utils}.
|
||||
|
||||
Default value is @code{160x128}.
|
||||
|
||||
@item VideoIntraOnly (@emph{encoding,video})
|
||||
Transmit only intra frames (useful for low bitrates, but kills frame rate).
|
||||
|
||||
@item VideoGopSize @var{n} (@emph{encoding,video})
|
||||
If non-intra only, an intra frame is transmitted every VideoGopSize
|
||||
frames. Video synchronization can only begin at an intra frame.
|
||||
|
||||
@item VideoTag @var{tag} (@emph{encoding,video})
|
||||
Set video tag.
|
||||
|
||||
@item VideoHighQuality (@emph{encoding,video})
|
||||
@item Video4MotionVector (@emph{encoding,video})
|
||||
|
||||
@item BitExact (@emph{encoding,video})
|
||||
Set bitexact encoding flag.
|
||||
|
||||
@item IdctSimple (@emph{encoding,video})
|
||||
Set simple IDCT algorithm.
|
||||
|
||||
@item Qscale @var{n} (@emph{encoding,video})
|
||||
Enable constant quality encoding, and set video qscale (quantization
|
||||
scale) value, expressed in @var{n} QP units.
|
||||
|
||||
@item VideoQMin @var{n} (@emph{encoding,video})
|
||||
@item VideoQMax @var{n} (@emph{encoding,video})
|
||||
Set video qmin/qmax.
|
||||
|
||||
@item VideoQDiff @var{integer} (@emph{encoding,video})
|
||||
Set video @option{qdiff} encoding option.
|
||||
|
||||
@item LumiMask @var{float} (@emph{encoding,video})
|
||||
@item DarkMask @var{float} (@emph{encoding,video})
|
||||
Set @option{lumi_mask}/@option{dark_mask} encoding options.
|
||||
|
||||
@item AVOptionVideo [@var{codec}:]@var{option} @var{value} (@emph{encoding,video})
|
||||
Set generic or private option for video stream.
|
||||
Private option must be prefixed with codec name or codec must be defined before.
|
||||
|
||||
@item AVPresetVideo @var{preset} (@emph{encoding,video})
|
||||
Set preset for video stream.
|
||||
|
||||
@var{preset} must be the path of a preset file.
|
||||
@end table
|
||||
|
||||
@subsection Server status stream
|
||||
|
||||
A server status stream is a special stream which is used to show
|
||||
statistics about the @command{ffserver} operations.
|
||||
|
||||
It must be specified setting the option @option{Format} to
|
||||
@samp{status}.
|
||||
|
||||
@section Redirect section
|
||||
|
||||
A redirect section specifies where to redirect the requested URL to
|
||||
another page.
|
||||
|
||||
A redirect section must be introduced by the line:
|
||||
@example
|
||||
<Redirect NAME>
|
||||
@end example
|
||||
|
||||
where @var{NAME} is the name of the page which should be redirected.
|
||||
|
||||
It only accepts the option @option{URL}, which specify the redirection
|
||||
URL.
|
||||
|
||||
@chapter Stream examples
|
||||
|
||||
@itemize
|
||||
@item
|
||||
Multipart JPEG
|
||||
@example
|
||||
<Stream test.mjpg>
|
||||
Feed feed1.ffm
|
||||
Format mpjpeg
|
||||
VideoFrameRate 2
|
||||
VideoIntraOnly
|
||||
NoAudio
|
||||
Strict -1
|
||||
</Stream>
|
||||
@end example
|
||||
|
||||
@item
|
||||
Single JPEG
|
||||
@example
|
||||
<Stream test.jpg>
|
||||
Feed feed1.ffm
|
||||
Format jpeg
|
||||
VideoFrameRate 2
|
||||
VideoIntraOnly
|
||||
VideoSize 352x240
|
||||
NoAudio
|
||||
Strict -1
|
||||
</Stream>
|
||||
@end example
|
||||
|
||||
@item
|
||||
Flash
|
||||
@example
|
||||
<Stream test.swf>
|
||||
Feed feed1.ffm
|
||||
Format swf
|
||||
VideoFrameRate 2
|
||||
VideoIntraOnly
|
||||
NoAudio
|
||||
</Stream>
|
||||
@end example
|
||||
|
||||
@item
|
||||
ASF compatible
|
||||
@example
|
||||
<Stream test.asf>
|
||||
Feed feed1.ffm
|
||||
Format asf
|
||||
VideoFrameRate 15
|
||||
VideoSize 352x240
|
||||
VideoBitRate 256
|
||||
VideoBufferSize 40
|
||||
VideoGopSize 30
|
||||
AudioBitRate 64
|
||||
StartSendOnKey
|
||||
</Stream>
|
||||
@end example
|
||||
|
||||
@item
|
||||
MP3 audio
|
||||
@example
|
||||
<Stream test.mp3>
|
||||
Feed feed1.ffm
|
||||
Format mp2
|
||||
AudioCodec mp3
|
||||
AudioBitRate 64
|
||||
AudioChannels 1
|
||||
AudioSampleRate 44100
|
||||
NoVideo
|
||||
</Stream>
|
||||
@end example
|
||||
|
||||
@item
|
||||
Ogg Vorbis audio
|
||||
@example
|
||||
<Stream test.ogg>
|
||||
Feed feed1.ffm
|
||||
Metadata title "Stream title"
|
||||
AudioBitRate 64
|
||||
AudioChannels 2
|
||||
AudioSampleRate 44100
|
||||
NoVideo
|
||||
</Stream>
|
||||
@end example
|
||||
|
||||
@item
|
||||
Real with audio only at 32 kbits
|
||||
@example
|
||||
<Stream test.ra>
|
||||
Feed feed1.ffm
|
||||
Format rm
|
||||
AudioBitRate 32
|
||||
NoVideo
|
||||
</Stream>
|
||||
@end example
|
||||
|
||||
@item
|
||||
Real with audio and video at 64 kbits
|
||||
@example
|
||||
<Stream test.rm>
|
||||
Feed feed1.ffm
|
||||
Format rm
|
||||
AudioBitRate 32
|
||||
VideoBitRate 128
|
||||
VideoFrameRate 25
|
||||
VideoGopSize 25
|
||||
</Stream>
|
||||
@end example
|
||||
|
||||
@item
|
||||
For stream coming from a file: you only need to set the input filename
|
||||
and optionally a new format.
|
||||
|
||||
@example
|
||||
<Stream file.rm>
|
||||
File "/usr/local/httpd/htdocs/tlive.rm"
|
||||
NoAudio
|
||||
</Stream>
|
||||
@end example
|
||||
|
||||
@example
|
||||
<Stream file.asf>
|
||||
File "/usr/local/httpd/htdocs/test.asf"
|
||||
NoAudio
|
||||
Metadata author "Me"
|
||||
Metadata copyright "Super MegaCorp"
|
||||
Metadata title "Test stream from disk"
|
||||
Metadata comment "Test comment"
|
||||
</Stream>
|
||||
@end example
|
||||
@end itemize
|
||||
|
||||
@c man end
|
||||
|
||||
@include config.texi
|
||||
@ifset config-all
|
||||
@ifset config-avutil
|
||||
@include utils.texi
|
||||
@end ifset
|
||||
@ifset config-avcodec
|
||||
@include codecs.texi
|
||||
@include bitstream_filters.texi
|
||||
@end ifset
|
||||
@ifset config-avformat
|
||||
@include formats.texi
|
||||
@include protocols.texi
|
||||
@end ifset
|
||||
@ifset config-avdevice
|
||||
@include devices.texi
|
||||
@end ifset
|
||||
@ifset config-swresample
|
||||
@include resampler.texi
|
||||
@end ifset
|
||||
@ifset config-swscale
|
||||
@include scaler.texi
|
||||
@end ifset
|
||||
@ifset config-avfilter
|
||||
@include filters.texi
|
||||
@end ifset
|
||||
@end ifset
|
||||
|
||||
@chapter See Also
|
||||
|
||||
@ifhtml
|
||||
@ifset config-all
|
||||
@url{ffserver.html,ffserver},
|
||||
@end ifset
|
||||
@ifset config-not-all
|
||||
@url{ffserver-all.html,ffserver-all},
|
||||
@end ifset
|
||||
the @file{doc/ffserver.conf} example,
|
||||
@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe},
|
||||
@url{ffmpeg-utils.html,ffmpeg-utils},
|
||||
@url{ffmpeg-scaler.html,ffmpeg-scaler},
|
||||
@url{ffmpeg-resampler.html,ffmpeg-resampler},
|
||||
@url{ffmpeg-codecs.html,ffmpeg-codecs},
|
||||
@url{ffmpeg-bitstream-filters.html,ffmpeg-bitstream-filters},
|
||||
@url{ffmpeg-formats.html,ffmpeg-formats},
|
||||
@url{ffmpeg-devices.html,ffmpeg-devices},
|
||||
@url{ffmpeg-protocols.html,ffmpeg-protocols},
|
||||
@url{ffmpeg-filters.html,ffmpeg-filters}
|
||||
@end ifhtml
|
||||
|
||||
@ifnothtml
|
||||
@ifset config-all
|
||||
ffserver(1),
|
||||
@end ifset
|
||||
@ifset config-not-all
|
||||
ffserver-all(1),
|
||||
@end ifset
|
||||
the @file{doc/ffserver.conf} example, ffmpeg(1), ffplay(1), ffprobe(1),
|
||||
ffmpeg-utils(1), ffmpeg-scaler(1), ffmpeg-resampler(1),
|
||||
ffmpeg-codecs(1), ffmpeg-bitstream-filters(1), ffmpeg-formats(1),
|
||||
ffmpeg-devices(1), ffmpeg-protocols(1), ffmpeg-filters(1)
|
||||
@end ifnothtml
|
||||
|
||||
@include authors.texi
|
||||
|
||||
@ignore
|
||||
|
||||
@setfilename ffserver
|
||||
@settitle ffserver video server
|
||||
|
||||
@end ignore
|
||||
|
||||
@bye
|
||||
@@ -315,51 +315,6 @@ Possible flags for this option are:
|
||||
@item k8
|
||||
@end table
|
||||
@end table
|
||||
|
||||
@item -opencl_bench
|
||||
This option is used to benchmark all available OpenCL devices and print the
|
||||
results. This option is only available when FFmpeg has been compiled with
|
||||
@code{--enable-opencl}.
|
||||
|
||||
When FFmpeg is configured with @code{--enable-opencl}, the options for the
|
||||
global OpenCL context are set via @option{-opencl_options}. See the
|
||||
"OpenCL Options" section in the ffmpeg-utils manual for the complete list of
|
||||
supported options. Amongst others, these options include the ability to select
|
||||
a specific platform and device to run the OpenCL code on. By default, FFmpeg
|
||||
will run on the first device of the first platform. While the options for the
|
||||
global OpenCL context provide flexibility to the user in selecting the OpenCL
|
||||
device of their choice, most users would probably want to select the fastest
|
||||
OpenCL device for their system.
|
||||
|
||||
This option assists the selection of the most efficient configuration by
|
||||
identifying the appropriate device for the user's system. The built-in
|
||||
benchmark is run on all the OpenCL devices and the performance is measured for
|
||||
each device. The devices in the results list are sorted based on their
|
||||
performance with the fastest device listed first. The user can subsequently
|
||||
invoke @command{ffmpeg} using the device deemed most appropriate via
|
||||
@option{-opencl_options} to obtain the best performance for the OpenCL
|
||||
accelerated code.
|
||||
|
||||
Typical usage to use the fastest OpenCL device involve the following steps.
|
||||
|
||||
Run the command:
|
||||
@example
|
||||
ffmpeg -opencl_bench
|
||||
@end example
|
||||
Note down the platform ID (@var{pidx}) and device ID (@var{didx}) of the first
|
||||
i.e. fastest device in the list.
|
||||
Select the platform and device using the command:
|
||||
@example
|
||||
ffmpeg -opencl_options platform_idx=@var{pidx}:device_idx=@var{didx} ...
|
||||
@end example
|
||||
|
||||
@item -opencl_options options (@emph{global})
|
||||
Set OpenCL environment options. This option is only available when
|
||||
FFmpeg has been compiled with @code{--enable-opencl}.
|
||||
|
||||
@var{options} must be a list of @var{key}=@var{value} option pairs
|
||||
separated by ':'. See the ``OpenCL Options'' section in the
|
||||
ffmpeg-utils manual for the list of supported options.
|
||||
@end table
|
||||
|
||||
@section AVOptions
|
||||
|
||||
+902
-59
File diff suppressed because it is too large
Load Diff
+8
-1
@@ -365,6 +365,7 @@ library:
|
||||
@item Interplay MVE @tab @tab X
|
||||
@tab Format used in various Interplay computer games.
|
||||
@item Iterated Systems ClearVideo @tab @tab X
|
||||
@tab I-frames only
|
||||
@item IV8 @tab @tab X
|
||||
@tab A format generated by IndigoVision 8000 video server.
|
||||
@item IVF (On2) @tab X @tab X
|
||||
@@ -424,6 +425,7 @@ library:
|
||||
@item NC camera feed @tab @tab X
|
||||
@tab NC (AVIP NC4600) camera streams
|
||||
@item NIST SPeech HEader REsources @tab @tab X
|
||||
@item Computerized Speech Lab NSP @tab @tab X
|
||||
@item NTT TwinVQ (VQF) @tab @tab X
|
||||
@tab Nippon Telegraph and Telephone Corporation TwinVQ.
|
||||
@item Nullsoft Streaming Video @tab @tab X
|
||||
@@ -438,6 +440,9 @@ library:
|
||||
@item QCP @tab @tab X
|
||||
@item raw ADTS (AAC) @tab X @tab X
|
||||
@item raw AC-3 @tab X @tab X
|
||||
@item raw AMR-NB @tab @tab X
|
||||
@item raw AMR-WB @tab @tab X
|
||||
@item raw aptX @tab X @tab X
|
||||
@item raw Chinese AVS video @tab X @tab X
|
||||
@item raw CRI ADX @tab X @tab X
|
||||
@item raw Dirac @tab X @tab X
|
||||
@@ -792,7 +797,7 @@ following image formats are supported:
|
||||
@item LucasArts SANM/Smush @tab @tab X
|
||||
@tab Used in LucasArts games / SMUSH animations.
|
||||
@item lossless MJPEG @tab X @tab X
|
||||
@item MagicYUV Video @tab @tab X
|
||||
@item MagicYUV Video @tab X @tab X
|
||||
@item Mandsoft Screen Capture Codec @tab @tab X
|
||||
@item Microsoft ATC Screen @tab @tab X
|
||||
@tab Also known as Microsoft Screen 3.
|
||||
@@ -990,6 +995,8 @@ following image formats are supported:
|
||||
@item Amazing Studio PAF Audio @tab @tab X
|
||||
@item Apple lossless audio @tab X @tab X
|
||||
@tab QuickTime fourcc 'alac'
|
||||
@item aptX @tab X @tab X
|
||||
@tab Used in Bluetooth A2DP
|
||||
@item ATRAC1 @tab @tab X
|
||||
@item ATRAC3 @tab @tab X
|
||||
@item ATRAC3+ @tab @tab X
|
||||
|
||||
@@ -238,6 +238,8 @@ This sets the input video format to the format given by the FourCC. To see
|
||||
the supported values of your device(s) use @option{list_formats}.
|
||||
Note that there is a FourCC @option{'pal '} that can also be used
|
||||
as @option{pal} (3 letters).
|
||||
Default behavior is autodetection of the input video format, if the hardware
|
||||
supports it.
|
||||
|
||||
@item bm_v210
|
||||
This is a deprecated option, you can use @option{raw_format} instead.
|
||||
@@ -311,6 +313,10 @@ Sets maximum input buffer size in bytes. If the buffering reaches this value,
|
||||
incoming frames will be dropped.
|
||||
Defaults to @samp{1073741824}.
|
||||
|
||||
@item audio_depth
|
||||
Sets the audio sample bit depth. Must be @samp{16} or @samp{32}.
|
||||
Defaults to @samp{16}.
|
||||
|
||||
@end table
|
||||
|
||||
@subsection Examples
|
||||
|
||||
@@ -193,9 +193,6 @@ ffplay
|
||||
ffprobe
|
||||
issues in or related to ffprobe.c
|
||||
|
||||
ffserver
|
||||
issues in or related to ffserver.c
|
||||
|
||||
postproc
|
||||
issues in libpostproc/*
|
||||
|
||||
|
||||
+3
-3
@@ -94,13 +94,13 @@ Stuff that didn't reach the codebase:
|
||||
- a853388d2 hevc: change the stride of the MC buffer to be in bytes instead of elements
|
||||
- 0cef06df0 checkasm: add HEVC MC tests
|
||||
- e7078e842 hevcdsp: add x86 SIMD for MC
|
||||
- VAAPI VP8 decode hwaccel (currently under review: http://ffmpeg.org/pipermail/ffmpeg-devel/2017-February/thread.html#207348)
|
||||
- Removal of the custom atomic API (5cc0057f49, see http://ffmpeg.org/pipermail/ffmpeg-devel/2017-March/209003.html)
|
||||
- 7993ec19a hevc: Add hevc_get_pixel_4/8/12/16/24/32/48/64
|
||||
- new bitstream reader (see http://ffmpeg.org/pipermail/ffmpeg-devel/2017-April/209609.html)
|
||||
- use of the bsf instead of our parser for vp9 superframes (see fa1749dd34)
|
||||
- use av_cpu_max_align() instead of hardcoding alignment requirements (see https://ffmpeg.org/pipermail/ffmpeg-devel/2017-September/215834.html)
|
||||
- f44ec22e0 lavc: use av_cpu_max_align() instead of hardcoding alignment requirements
|
||||
- 4de220d2e frame: allow align=0 (meaning automatic) for av_frame_get_buffer()
|
||||
- Support recovery from an already present HLS playlist (see 16cb06bb30)
|
||||
- Remove all output devices (see 8e7e042d41, 8d3db95f20, 6ce13070bd, d46cd24986 and https://ffmpeg.org/pipermail/ffmpeg-devel/2017-September/216904.html)
|
||||
|
||||
Collateral damage that needs work locally:
|
||||
------------------------------------------
|
||||
|
||||
+2
-2
@@ -26,13 +26,13 @@ implementing robust and fast codecs as well as for experimentation.
|
||||
@chapter See Also
|
||||
|
||||
@ifhtml
|
||||
@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe}, @url{ffserver.html,ffserver},
|
||||
@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe},
|
||||
@url{ffmpeg-codecs.html,ffmpeg-codecs}, @url{ffmpeg-bitstream-filters.html,bitstream-filters},
|
||||
@url{libavutil.html,libavutil}
|
||||
@end ifhtml
|
||||
|
||||
@ifnothtml
|
||||
ffmpeg(1), ffplay(1), ffprobe(1), ffserver(1),
|
||||
ffmpeg(1), ffplay(1), ffprobe(1),
|
||||
ffmpeg-codecs(1), ffmpeg-bitstream-filters(1),
|
||||
libavutil(3)
|
||||
@end ifnothtml
|
||||
|
||||
@@ -23,13 +23,13 @@ VfW, DShow, and ALSA.
|
||||
@chapter See Also
|
||||
|
||||
@ifhtml
|
||||
@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe}, @url{ffserver.html,ffserver},
|
||||
@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe},
|
||||
@url{ffmpeg-devices.html,ffmpeg-devices},
|
||||
@url{libavutil.html,libavutil}, @url{libavcodec.html,libavcodec}, @url{libavformat.html,libavformat}
|
||||
@end ifhtml
|
||||
|
||||
@ifnothtml
|
||||
ffmpeg(1), ffplay(1), ffprobe(1), ffserver(1),
|
||||
ffmpeg(1), ffplay(1), ffprobe(1),
|
||||
ffmpeg-devices(1),
|
||||
libavutil(3), libavcodec(3), libavformat(3)
|
||||
@end ifnothtml
|
||||
|
||||
@@ -21,14 +21,14 @@ framework containing several filters, sources and sinks.
|
||||
@chapter See Also
|
||||
|
||||
@ifhtml
|
||||
@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe}, @url{ffserver.html,ffserver},
|
||||
@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe},
|
||||
@url{ffmpeg-filters.html,ffmpeg-filters},
|
||||
@url{libavutil.html,libavutil}, @url{libswscale.html,libswscale}, @url{libswresample.html,libswresample},
|
||||
@url{libavcodec.html,libavcodec}, @url{libavformat.html,libavformat}, @url{libavdevice.html,libavdevice}
|
||||
@end ifhtml
|
||||
|
||||
@ifnothtml
|
||||
ffmpeg(1), ffplay(1), ffprobe(1), ffserver(1),
|
||||
ffmpeg(1), ffplay(1), ffprobe(1),
|
||||
ffmpeg-filters(1),
|
||||
libavutil(3), libswscale(3), libswresample(3), libavcodec(3), libavformat(3), libavdevice(3)
|
||||
@end ifnothtml
|
||||
|
||||
@@ -26,13 +26,13 @@ resource.
|
||||
@chapter See Also
|
||||
|
||||
@ifhtml
|
||||
@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe}, @url{ffserver.html,ffserver},
|
||||
@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe},
|
||||
@url{ffmpeg-formats.html,ffmpeg-formats}, @url{ffmpeg-protocols.html,ffmpeg-protocols},
|
||||
@url{libavutil.html,libavutil}, @url{libavcodec.html,libavcodec}
|
||||
@end ifhtml
|
||||
|
||||
@ifnothtml
|
||||
ffmpeg(1), ffplay(1), ffprobe(1), ffserver(1),
|
||||
ffmpeg(1), ffplay(1), ffprobe(1),
|
||||
ffmpeg-formats(1), ffmpeg-protocols(1),
|
||||
libavutil(3), libavcodec(3)
|
||||
@end ifnothtml
|
||||
|
||||
+2
-2
@@ -42,12 +42,12 @@ It should avoid useless features that almost no one needs.
|
||||
@chapter See Also
|
||||
|
||||
@ifhtml
|
||||
@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe}, @url{ffserver.html,ffserver},
|
||||
@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe},
|
||||
@url{ffmpeg-utils.html,ffmpeg-utils}
|
||||
@end ifhtml
|
||||
|
||||
@ifnothtml
|
||||
ffmpeg(1), ffplay(1), ffprobe(1), ffserver(1),
|
||||
ffmpeg(1), ffplay(1), ffprobe(1),
|
||||
ffmpeg-utils(1)
|
||||
@end ifnothtml
|
||||
|
||||
|
||||
@@ -48,13 +48,13 @@ enabled through dedicated options.
|
||||
@chapter See Also
|
||||
|
||||
@ifhtml
|
||||
@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe}, @url{ffserver.html,ffserver},
|
||||
@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe},
|
||||
@url{ffmpeg-resampler.html,ffmpeg-resampler},
|
||||
@url{libavutil.html,libavutil}
|
||||
@end ifhtml
|
||||
|
||||
@ifnothtml
|
||||
ffmpeg(1), ffplay(1), ffprobe(1), ffserver(1),
|
||||
ffmpeg(1), ffplay(1), ffprobe(1),
|
||||
ffmpeg-resampler(1),
|
||||
libavutil(3)
|
||||
@end ifnothtml
|
||||
|
||||
+2
-2
@@ -41,13 +41,13 @@ colorspaces differ.
|
||||
@chapter See Also
|
||||
|
||||
@ifhtml
|
||||
@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe}, @url{ffserver.html,ffserver},
|
||||
@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe},
|
||||
@url{ffmpeg-scaler.html,ffmpeg-scaler},
|
||||
@url{libavutil.html,libavutil}
|
||||
@end ifhtml
|
||||
|
||||
@ifnothtml
|
||||
ffmpeg(1), ffplay(1), ffprobe(1), ffserver(1),
|
||||
ffmpeg(1), ffplay(1), ffprobe(1),
|
||||
ffmpeg-scaler(1),
|
||||
libavutil(3)
|
||||
@end ifnothtml
|
||||
|
||||
@@ -27,8 +27,7 @@ for examples.
|
||||
@item
|
||||
@url{https://lists.ffmpeg.org/mailman/listinfo/ffmpeg-user/, ffmpeg-user}:
|
||||
For questions involving unscripted usage or compilation of the FFmpeg
|
||||
command-line tools (@command{ffmpeg}, @command{ffprobe}, @command{ffplay},
|
||||
@command{ffserver}).
|
||||
command-line tools (@command{ffmpeg}, @command{ffprobe}, @command{ffplay}).
|
||||
|
||||
@item
|
||||
@url{https://lists.ffmpeg.org/mailman/listinfo/libav-user/, libav-user}:
|
||||
|
||||
+144
-2
@@ -247,6 +247,13 @@ DASH-templated name to used for the initialization segment. Default is "init-str
|
||||
DASH-templated name to used for the media segments. Default is "chunk-stream$RepresentationID$-$Number%05d$.m4s"
|
||||
@item -utc_timing_url @var{utc_url}
|
||||
URL of the page that will return the UTC timestamp in ISO format. Example: "https://time.akamai.com/?iso"
|
||||
@item -http_user_agent @var{user_agent}
|
||||
Override User-Agent field in HTTP header. Applicable only for HTTP output.
|
||||
@item -http_persistent @var{http_persistent}
|
||||
Use persistent HTTP connections. Applicable only for HTTP output.
|
||||
@item -hls_playlist @var{hls_playlist}
|
||||
Generate HLS playlist files as well. The master playlist is generated with the filename master.m3u8.
|
||||
One media playlist file is generated for each stream with filenames media_0.m3u8, media_1.m3u8, etc.
|
||||
@item -adaptation_sets @var{adaptation_sets}
|
||||
Assign streams to AdaptationSets. Syntax is "id=x,streams=a,b,c id=y,streams=d,e" with x and y being the IDs
|
||||
of the adaptation sets and a,b,c,d and e are the indices of the mapped streams.
|
||||
@@ -468,9 +475,12 @@ By default, the muxer creates a file for each segment produced. These files
|
||||
have the same name as the playlist, followed by a sequential number and a
|
||||
.ts extension.
|
||||
|
||||
Make sure to require a closed GOP when encoding and to set the GOP
|
||||
size to fit your segment time constraint.
|
||||
|
||||
For example, to convert an input file with @command{ffmpeg}:
|
||||
@example
|
||||
ffmpeg -i in.nut out.m3u8
|
||||
ffmpeg -i in.mkv -c:v h264 -flags +cgop -g 30 -hls_time 1 out.m3u8
|
||||
@end example
|
||||
This example will produce the playlist, @file{out.m3u8}, and segment files:
|
||||
@file{out0.ts}, @file{out1.ts}, @file{out2.ts}, etc.
|
||||
@@ -567,6 +577,31 @@ Should a relative path be specified, the path of the created segment
|
||||
files will be relative to the current working directory.
|
||||
When use_localtime_mkdir is set, the whole expanded value of @var{filename} will be written into the m3u8 segment list.
|
||||
|
||||
When @code{var_stream_map} is set with two or more variant streams, the
|
||||
@var{filename} pattern must contain the string "%v", this string specifies
|
||||
the position of variant stream index in the generated segment file names.
|
||||
@example
|
||||
ffmpeg -i in.ts -b:v:0 1000k -b:v:1 256k -b:a:0 64k -b:a:1 32k \
|
||||
-map 0:v -map 0:a -map 0:v -map 0:a -f hls -var_stream_map "v:0,a:0 v:1,a:1" \
|
||||
-hls_segment_filename 'file_%v_%03d.ts' out_%v.m3u8
|
||||
@end example
|
||||
This example will produce the playlists segment file sets:
|
||||
@file{file_0_000.ts}, @file{file_0_001.ts}, @file{file_0_002.ts}, etc. and
|
||||
@file{file_1_000.ts}, @file{file_1_001.ts}, @file{file_1_002.ts}, etc.
|
||||
|
||||
The string "%v" may be present in the filename or in the last directory name
|
||||
containing the file. If the string is present in the directory name, then
|
||||
sub-directories are created after expanding the directory name pattern. This
|
||||
enables creation of segments corresponding to different variant streams in
|
||||
subdirectories.
|
||||
@example
|
||||
ffmpeg -i in.ts -b:v:0 1000k -b:v:1 256k -b:a:0 64k -b:a:1 32k \
|
||||
-map 0:v -map 0:a -map 0:v -map 0:a -f hls -var_stream_map "v:0,a:0 v:1,a:1" \
|
||||
-hls_segment_filename 'vs%v/file_%03d.ts' vs%v/out.m3u8
|
||||
@end example
|
||||
This example will produce the playlists segment file sets:
|
||||
@file{vs0/file_000.ts}, @file{vs0/file_001.ts}, @file{vs0/file_002.ts}, etc. and
|
||||
@file{vs1/file_000.ts}, @file{vs1/file_001.ts}, @file{vs1/file_002.ts}, etc.
|
||||
|
||||
@item use_localtime
|
||||
Use strftime() on @var{filename} to expand the segment filename with localtime.
|
||||
@@ -693,6 +728,15 @@ the fmp4 files is used in hls after version 7.
|
||||
@item hls_fmp4_init_filename @var{filename}
|
||||
set filename to the fragment files header file, default filename is @file{init.mp4}.
|
||||
|
||||
When @code{var_stream_map} is set with two or more variant streams, the
|
||||
@var{filename} pattern must contain the string "%v", this string specifies
|
||||
the position of variant stream index in the generated init file names.
|
||||
The string "%v" may be present in the filename or in the last directory name
|
||||
containing the file. If the string is present in the directory name, then
|
||||
sub-directories are created after expanding the directory name pattern. This
|
||||
enables creation of init files corresponding to different variant streams in
|
||||
subdirectories.
|
||||
|
||||
@item hls_flags @var{flags}
|
||||
Possible values:
|
||||
|
||||
@@ -732,6 +776,10 @@ The file specified by @code{hls_key_info_file} will be checked periodically and
|
||||
detect updates to the encryption info. Be sure to replace this file atomically,
|
||||
including the file containing the AES encryption key.
|
||||
|
||||
@item independent_segments
|
||||
Add the @code{#EXT-X-INDEPENDENT-SEGMENTS} to playlists that has video segments
|
||||
and when all the segments of that playlist are guaranteed to start with a Key frame.
|
||||
|
||||
@item split_by_time
|
||||
Allow segments to start on frames other than keyframes. This improves
|
||||
behavior on some players when the time between keyframes is inconsistent,
|
||||
@@ -794,6 +842,88 @@ files.
|
||||
@item http_user_agent
|
||||
Override User-Agent field in HTTP header. Applicable only for HTTP output.
|
||||
|
||||
@item var_stream_map
|
||||
Map string which specifies how to group the audio, video and subtitle streams
|
||||
into different variant streams. The variant stream groups are separated
|
||||
by space.
|
||||
Expected string format is like this "a:0,v:0 a:1,v:1 ....". Here a:, v:, s: are
|
||||
the keys to specify audio, video and subtitle streams respectively.
|
||||
Allowed values are 0 to 9 (limited just based on practical usage).
|
||||
|
||||
When there are two or more variant streams, the output filename pattern must
|
||||
contain the string "%v", this string specifies the position of variant stream
|
||||
index in the output media playlist filenames. The string "%v" may be present in
|
||||
the filename or in the last directory name containing the file. If the string is
|
||||
present in the directory name, then sub-directories are created after expanding
|
||||
the directory name pattern. This enables creation of variant streams in
|
||||
subdirectories.
|
||||
|
||||
@example
|
||||
ffmpeg -re -i in.ts -b:v:0 1000k -b:v:1 256k -b:a:0 64k -b:a:1 32k \
|
||||
-map 0:v -map 0:a -map 0:v -map 0:a -f hls -var_stream_map "v:0,a:0 v:1,a:1" \
|
||||
http://example.com/live/out_%v.m3u8
|
||||
@end example
|
||||
This example creates two hls variant streams. The first variant stream will
|
||||
contain video stream of bitrate 1000k and audio stream of bitrate 64k and the
|
||||
second variant stream will contain video stream of bitrate 256k and audio
|
||||
stream of bitrate 32k. Here, two media playlist with file names out_0.m3u8 and
|
||||
out_1.m3u8 will be created.
|
||||
@example
|
||||
ffmpeg -re -i in.ts -b:v:0 1000k -b:v:1 256k -b:a:0 64k \
|
||||
-map 0:v -map 0:a -map 0:v -f hls -var_stream_map "v:0 a:0 v:1" \
|
||||
http://example.com/live/out_%v.m3u8
|
||||
@end example
|
||||
This example creates three hls variant streams. The first variant stream will
|
||||
be a video only stream with video bitrate 1000k, the second variant stream will
|
||||
be an audio only stream with bitrate 64k and the third variant stream will be a
|
||||
video only stream with bitrate 256k. Here, three media playlist with file names
|
||||
out_0.m3u8, out_1.m3u8 and out_2.m3u8 will be created.
|
||||
@example
|
||||
ffmpeg -re -i in.ts -b:v:0 1000k -b:v:1 256k -b:a:0 64k -b:a:1 32k \
|
||||
-map 0:v -map 0:a -map 0:v -map 0:a -f hls -var_stream_map "v:0,a:0 v:1,a:1" \
|
||||
http://example.com/live/vs_%v/out.m3u8
|
||||
@end example
|
||||
This example creates the variant streams in subdirectories. Here, the first
|
||||
media playlist is created at @file{http://example.com/live/vs_0/out.m3u8} and
|
||||
the second one at @file{http://example.com/live/vs_1/out.m3u8}.
|
||||
@example
|
||||
ffmpeg -re -i in.ts -b:a:0 32k -b:a:1 64k -b:v:0 1000k -b:v:1 3000k \
|
||||
-map 0:a -map 0:a -map 0:v -map 0:v -f hls \
|
||||
-var_stream_map "a:0,agroup:aud_low a:1,agroup:aud_high v:0,agroup:aud_low v:1,agroup:aud_high" \
|
||||
-master_pl_name master.m3u8 \
|
||||
http://example.com/live/out_%v.m3u8
|
||||
@end example
|
||||
This example creates two audio only and two video only variant streams. In
|
||||
addition to the #EXT-X-STREAM-INF tag for each variant stream in the master
|
||||
playlist, #EXT-X-MEDIA tag is also added for the two audio only variant streams
|
||||
and they are mapped to the two video only variant streams with audio group names
|
||||
'aud_low' and 'aud_high'.
|
||||
|
||||
By default, a single hls variant containing all the encoded streams is created.
|
||||
|
||||
@item master_pl_name
|
||||
Create HLS master playlist with the given name.
|
||||
|
||||
@example
|
||||
ffmpeg -re -i in.ts -f hls -master_pl_name master.m3u8 http://example.com/live/out.m3u8
|
||||
@end example
|
||||
This example creates HLS master playlist with name master.m3u8 and it is
|
||||
published at http://example.com/live/
|
||||
|
||||
@item master_pl_publish_rate
|
||||
Publish master play list repeatedly every after specified number of segment intervals.
|
||||
|
||||
@example
|
||||
ffmpeg -re -i in.ts -f hls -master_pl_name master.m3u8 \
|
||||
-hls_time 2 -master_pl_publish_rate 30 http://example.com/live/out.m3u8
|
||||
@end example
|
||||
|
||||
This example creates HLS master playlist with name master.m3u8 and keep
|
||||
publishing it repeatedly every after 30 segments i.e. every after 60s.
|
||||
|
||||
@item http_persistent
|
||||
Use persistent HTTP connections. Applicable only for HTTP output.
|
||||
|
||||
@end table
|
||||
|
||||
@anchor{ico}
|
||||
@@ -894,9 +1024,18 @@ can be used:
|
||||
ffmpeg -f v4l2 -r 1 -i /dev/video0 -f image2 -strftime 1 "%Y-%m-%d_%H-%M-%S.jpg"
|
||||
@end example
|
||||
|
||||
You can set the file name with current frame's PTS:
|
||||
@example
|
||||
ffmpeg -f v4l2 -r 1 -i /dev/video0 -copyts -f image2 -frame_pts true %d.jpg"
|
||||
@end example
|
||||
|
||||
@subsection Options
|
||||
|
||||
@table @option
|
||||
@item frame_pts
|
||||
If set to 1, expand the filename with pts from pkt->pts.
|
||||
Default value is 0.
|
||||
|
||||
@item start_number
|
||||
Start the sequence from the specified number. Default value is 1.
|
||||
|
||||
@@ -1649,6 +1788,9 @@ segment would usually span. Otherwise, the segment will be filled with the next
|
||||
packet written. Defaults to @code{0}.
|
||||
@end table
|
||||
|
||||
Make sure to require a closed GOP when encoding and to set the GOP
|
||||
size to fit your segment time constraint.
|
||||
|
||||
@subsection Examples
|
||||
|
||||
@itemize
|
||||
@@ -1657,7 +1799,7 @@ Remux the content of file @file{in.mkv} to a list of segments
|
||||
@file{out-000.nut}, @file{out-001.nut}, etc., and write the list of
|
||||
generated segments to @file{out.list}:
|
||||
@example
|
||||
ffmpeg -i in.mkv -codec copy -map 0 -f segment -segment_list out.list out%03d.nut
|
||||
ffmpeg -i in.mkv -codec hevc -flags +cgop -g 60 -map 0 -f segment -segment_list out.list out%03d.nut
|
||||
@end example
|
||||
|
||||
@item
|
||||
|
||||
+14
-2
@@ -321,6 +321,9 @@ Sets the maximum delay in seconds after which to give up reconnecting
|
||||
@item mime_type
|
||||
Export the MIME type.
|
||||
|
||||
@item http_version
|
||||
Exports the HTTP response version number. Usually "1.0" or "1.1".
|
||||
|
||||
@item icy
|
||||
If set to 1 request ICY (SHOUTcast) metadata from the server. If the server
|
||||
supports this, the metadata has to be retrieved by the application by reading
|
||||
@@ -363,7 +366,7 @@ If set to 1 enables experimental HTTP server. This can be used to send data when
|
||||
used as an output option, or read data from a client with HTTP POST when used as
|
||||
an input option.
|
||||
If set to 2 enables experimental multi-client HTTP server. This is not yet implemented
|
||||
in ffmpeg.c or ffserver.c and thus must not be used as a command line option.
|
||||
in ffmpeg.c and thus must not be used as a command line option.
|
||||
@example
|
||||
# Server side (sending):
|
||||
ffmpeg -i somefile.ogg -c copy -listen 1 -f ogg http://@var{server}:@var{port}
|
||||
@@ -1186,6 +1189,7 @@ Accepted options:
|
||||
Start offset of the extracted segment, in bytes.
|
||||
@item end
|
||||
End offset of the extracted segment, in bytes.
|
||||
If set to 0, extract till end of file.
|
||||
@end table
|
||||
|
||||
Examples:
|
||||
@@ -1201,6 +1205,11 @@ Play an AVI file directly from a TAR archive:
|
||||
subfile,,start,183241728,end,366490624,,:archive.tar
|
||||
@end example
|
||||
|
||||
Play a MPEG-TS file from start offset till end:
|
||||
@example
|
||||
subfile,,start,32815239,end,0,,:video.ts
|
||||
@end example
|
||||
|
||||
@section tee
|
||||
|
||||
Writes the output to multiple protocols. The individual outputs are separated
|
||||
@@ -1242,6 +1251,9 @@ Set receive buffer size, expressed bytes.
|
||||
|
||||
@item send_buffer_size=@var{bytes}
|
||||
Set send buffer size, expressed bytes.
|
||||
|
||||
@item tcp_nodelay=@var{1|0}
|
||||
Set TCP_NODELAY to disable Nagle's algorithm. Default value is 0.
|
||||
@end table
|
||||
|
||||
The following example shows how to setup a listening TCP connection
|
||||
@@ -1277,7 +1289,7 @@ If enabled, try to verify the peer that we are communicating with.
|
||||
Note, if using OpenSSL, this currently only makes sure that the
|
||||
peer certificate is signed by one of the root certificates in the CA
|
||||
database, but it does not validate that the certificate actually
|
||||
matches the host name we are trying to connect to. (With GnuTLS,
|
||||
matches the host name we are trying to connect to. (With other backends,
|
||||
the host name is validated as well.)
|
||||
|
||||
This is disabled by default since it requires a CA database to be
|
||||
|
||||
@@ -1057,33 +1057,3 @@ indication of the corresponding powers of 10 and of 2.
|
||||
@end table
|
||||
|
||||
@c man end EXPRESSION EVALUATION
|
||||
|
||||
@chapter OpenCL Options
|
||||
@c man begin OPENCL OPTIONS
|
||||
|
||||
When FFmpeg is configured with @code{--enable-opencl}, it is possible
|
||||
to set the options for the global OpenCL context.
|
||||
|
||||
The list of supported options follows:
|
||||
|
||||
@table @option
|
||||
@item build_options
|
||||
Set build options used to compile the registered kernels.
|
||||
|
||||
See reference "OpenCL Specification Version: 1.2 chapter 5.6.4".
|
||||
|
||||
@item platform_idx
|
||||
Select the index of the platform to run OpenCL code.
|
||||
|
||||
The specified index must be one of the indexes in the device list
|
||||
which can be obtained with @code{ffmpeg -opencl_bench} or @code{av_opencl_get_device_list()}.
|
||||
|
||||
@item device_idx
|
||||
Select the index of the device used to run OpenCL code.
|
||||
|
||||
The specified index must be one of the indexes in the device list which
|
||||
can be obtained with @code{ffmpeg -opencl_bench} or @code{av_opencl_get_device_list()}.
|
||||
|
||||
@end table
|
||||
|
||||
@c man end OPENCL OPTIONS
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
/.config
|
||||
/config.fate
|
||||
/config.log
|
||||
/config.mak
|
||||
/config.sh
|
||||
+2
-3
@@ -119,7 +119,7 @@ FFLIBS := $($(NAME)_FFLIBS) $(FFLIBS-yes) $(FFLIBS)
|
||||
TESTPROGS += $(TESTPROGS-yes)
|
||||
|
||||
LDLIBS = $(FFLIBS:%=%$(BUILDSUF))
|
||||
FFEXTRALIBS := $(LDLIBS:%=$(LD_LIB)) $(EXTRALIBS)
|
||||
FFEXTRALIBS := $(LDLIBS:%=$(LD_LIB)) $(foreach lib,EXTRALIBS-$(NAME) $(FFLIBS:%=EXTRALIBS-%),$($(lib))) $(EXTRALIBS)
|
||||
|
||||
OBJS := $(sort $(OBJS:%=$(SUBDIR)%))
|
||||
SLIBOBJS := $(sort $(SLIBOBJS:%=$(SUBDIR)%))
|
||||
@@ -163,8 +163,7 @@ $(TOOLOBJS): | tools
|
||||
|
||||
OBJDIRS := $(OBJDIRS) $(dir $(OBJS) $(HOBJS) $(HOSTOBJS) $(SLIBOBJS) $(TESTOBJS))
|
||||
|
||||
CLEANSUFFIXES = *.d *.o *~ *.h.c *.gcda *.gcno *.map *.ver *.version *.ho *$(DEFAULT_X86ASMD).asm *.ptx *.ptx.c
|
||||
DISTCLEANSUFFIXES = *.pc
|
||||
CLEANSUFFIXES = *.d *.gcda *.gcno *.h.c *.ho *.map *.o *.pc *.ptx *.ptx.c *.ver *.version *$(DEFAULT_X86ASMD).asm *~
|
||||
LIBSUFFIXES = *.a *.lib *.so *.so.* *.dylib *.dll *.def *.dll.a
|
||||
|
||||
define RULES
|
||||
|
||||
+9
-9
@@ -1,6 +1,6 @@
|
||||
include $(SRC_PATH)/ffbuild/common.mak
|
||||
|
||||
ifeq (,$(filter %clean,$(MAKECMDGOALS)))
|
||||
ifeq (,$(filter %clean config,$(MAKECMDGOALS)))
|
||||
-include $(SUBDIR)lib$(NAME).version
|
||||
endif
|
||||
|
||||
@@ -31,13 +31,15 @@ define RULES
|
||||
$(TOOLS): THISLIB = $(FULLNAME:%=$(LD_LIB))
|
||||
$(TESTPROGS): THISLIB = $(SUBDIR)$(LIBNAME)
|
||||
|
||||
$(LIBOBJS): CPPFLAGS += -DBUILDING_$(NAME)
|
||||
|
||||
$(TESTPROGS) $(TOOLS): %$(EXESUF): %.o
|
||||
$$(LD) $(LDFLAGS) $(LDEXEFLAGS) $$(LD_O) $$(filter %.o,$$^) $$(THISLIB) $(FFEXTRALIBS) $$(ELIBS)
|
||||
$$(LD) $(LDFLAGS) $(LDEXEFLAGS) $$(LD_O) $$(filter %.o,$$^) $$(THISLIB) $(FFEXTRALIBS) $$(EXTRALIBS-$$(*F)) $$(ELIBS)
|
||||
|
||||
$(SUBDIR)lib$(NAME).version: $(SUBDIR)version.h | $(SUBDIR)
|
||||
$$(M) $$(SRC_PATH)/ffbuild/libversion.sh $(NAME) $$< > $$@
|
||||
|
||||
$(SUBDIR)lib$(FULLNAME).pc: $(SUBDIR)version.h | $(SUBDIR)
|
||||
$(SUBDIR)lib$(FULLNAME).pc: $(SUBDIR)version.h ffbuild/config.sh | $(SUBDIR)
|
||||
$$(M) $$(SRC_PATH)/ffbuild/pkgconfig_generate.sh $(NAME) "$(DESC)"
|
||||
|
||||
$(SUBDIR)lib$(NAME).ver: $(SUBDIR)lib$(NAME).v $(OBJS)
|
||||
@@ -48,7 +50,7 @@ $(SUBDIR)$(SLIBNAME): $(SUBDIR)$(SLIBNAME_WITH_MAJOR)
|
||||
|
||||
$(SUBDIR)$(SLIBNAME_WITH_MAJOR): $(OBJS) $(SLIBOBJS) $(SUBDIR)lib$(NAME).ver
|
||||
$(SLIB_CREATE_DEF_CMD)
|
||||
$$(LD) $(SHFLAGS) $(LDFLAGS) $(LDLIBFLAGS) $$(LD_O) $$(filter %.o,$$^) $(FFEXTRALIBS)
|
||||
$$(LD) $(SHFLAGS) $(LDFLAGS) $(LDSOFLAGS) $$(LD_O) $$(filter %.o,$$^) $(FFEXTRALIBS)
|
||||
$(SLIB_EXTRA_CMD)
|
||||
|
||||
ifdef SUBDIR
|
||||
@@ -59,10 +61,6 @@ clean::
|
||||
$(RM) $(addprefix $(SUBDIR),$(CLEANFILES) $(CLEANSUFFIXES) $(LIBSUFFIXES)) \
|
||||
$(CLEANSUFFIXES:%=$(SUBDIR)$(ARCH)/%) $(CLEANSUFFIXES:%=$(SUBDIR)tests/%)
|
||||
|
||||
distclean:: clean
|
||||
$(RM) $(DISTCLEANSUFFIXES:%=$(SUBDIR)%) $(DISTCLEANSUFFIXES:%=$(SUBDIR)$(ARCH)/%) \
|
||||
$(DISTCLEANSUFFIXES:%=$(SUBDIR)tests/%)
|
||||
|
||||
install-lib$(NAME)-shared: $(SUBDIR)$(SLIBNAME)
|
||||
$(Q)mkdir -p "$(SHLIBDIR)"
|
||||
$$(INSTALL) -m 755 $$< "$(SHLIBDIR)/$(SLIB_INSTALL_NAME)"
|
||||
@@ -95,8 +93,10 @@ uninstall-libs::
|
||||
|
||||
uninstall-headers::
|
||||
$(RM) $(addprefix "$(INCINSTDIR)/",$(HEADERS) $(BUILT_HEADERS))
|
||||
$(RM) "$(PKGCONFIGDIR)/lib$(FULLNAME).pc"
|
||||
-rmdir "$(INCINSTDIR)"
|
||||
|
||||
uninstall-pkgconfig::
|
||||
$(RM) "$(PKGCONFIGDIR)/lib$(FULLNAME).pc"
|
||||
endef
|
||||
|
||||
$(eval $(RULES))
|
||||
|
||||
+1
-4
@@ -1,12 +1,11 @@
|
||||
AVPROGS-$(CONFIG_FFMPEG) += ffmpeg
|
||||
AVPROGS-$(CONFIG_FFPLAY) += ffplay
|
||||
AVPROGS-$(CONFIG_FFPROBE) += ffprobe
|
||||
AVPROGS-$(CONFIG_FFSERVER) += ffserver
|
||||
|
||||
AVPROGS := $(AVPROGS-yes:%=%$(PROGSSUF)$(EXESUF))
|
||||
PROGS += $(AVPROGS)
|
||||
|
||||
AVBASENAMES = ffmpeg ffplay ffprobe ffserver
|
||||
AVBASENAMES = ffmpeg ffplay ffprobe
|
||||
ALLAVPROGS = $(AVBASENAMES:%=%$(PROGSSUF)$(EXESUF))
|
||||
ALLAVPROGS_G = $(AVBASENAMES:%=%$(PROGSSUF)_g$(EXESUF))
|
||||
|
||||
@@ -17,7 +16,6 @@ ifndef CONFIG_VIDEOTOOLBOX
|
||||
OBJS-ffmpeg-$(CONFIG_VDA) += fftools/ffmpeg_videotoolbox.o
|
||||
endif
|
||||
OBJS-ffmpeg-$(CONFIG_VIDEOTOOLBOX) += fftools/ffmpeg_videotoolbox.o
|
||||
OBJS-ffserver += fftools/ffserver_config.o
|
||||
|
||||
define DOFFTOOL
|
||||
OBJS-$(1) += fftools/cmdutils.o fftools/$(1).o $(OBJS-$(1)-yes)
|
||||
@@ -29,7 +27,6 @@ $(1)$(PROGSSUF)_g$(EXESUF): FF_EXTRALIBS += $(EXTRALIBS-$(1))
|
||||
-include $$(OBJS-$(1):.o=.d)
|
||||
endef
|
||||
|
||||
$(foreach P,$(AVPROGS-yes),$(eval OBJS-$(P)-$(CONFIG_OPENCL) += fftools/cmdutils_opencl.o))
|
||||
$(foreach P,$(AVPROGS-yes),$(eval $(call DOFFTOOL,$(P))))
|
||||
|
||||
all: $(AVPROGS)
|
||||
|
||||
+2
-1
@@ -38,6 +38,7 @@
|
||||
#include "libswscale/swscale.h"
|
||||
#include "libswresample/swresample.h"
|
||||
#include "libpostproc/postprocess.h"
|
||||
#include "libavutil/attributes.h"
|
||||
#include "libavutil/avassert.h"
|
||||
#include "libavutil/avstring.h"
|
||||
#include "libavutil/bprint.h"
|
||||
@@ -1702,7 +1703,7 @@ int show_pix_fmts(void *optctx, const char *opt, const char *arg)
|
||||
#endif
|
||||
|
||||
while ((pix_desc = av_pix_fmt_desc_next(pix_desc))) {
|
||||
enum AVPixelFormat pix_fmt = av_pix_fmt_desc_get_id(pix_desc);
|
||||
enum AVPixelFormat av_unused pix_fmt = av_pix_fmt_desc_get_id(pix_desc);
|
||||
printf("%c%c%c%c%c %-16s %d %2d\n",
|
||||
sws_isSupportedInput (pix_fmt) ? 'I' : '.',
|
||||
sws_isSupportedOutput(pix_fmt) ? 'O' : '.',
|
||||
|
||||
+1
-18
@@ -105,12 +105,6 @@ int opt_max_alloc(void *optctx, const char *opt, const char *arg);
|
||||
|
||||
int opt_codec_debug(void *optctx, const char *opt, const char *arg);
|
||||
|
||||
#if CONFIG_OPENCL
|
||||
int opt_opencl(void *optctx, const char *opt, const char *arg);
|
||||
|
||||
int opt_opencl_bench(void *optctx, const char *opt, const char *arg);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Limit the execution time.
|
||||
*/
|
||||
@@ -155,6 +149,7 @@ typedef struct SpecifierOpt {
|
||||
uint8_t *str;
|
||||
int i;
|
||||
int64_t i64;
|
||||
uint64_t ui64;
|
||||
float f;
|
||||
double dbl;
|
||||
} u;
|
||||
@@ -206,17 +201,6 @@ typedef struct OptionDef {
|
||||
void show_help_options(const OptionDef *options, const char *msg, int req_flags,
|
||||
int rej_flags, int alt_flags);
|
||||
|
||||
#if CONFIG_OPENCL
|
||||
#define CMDUTILS_COMMON_OPTIONS_OPENCL \
|
||||
{ "opencl_bench", OPT_EXIT, {.func_arg = opt_opencl_bench}, \
|
||||
"run benchmark on all OpenCL devices and show results" }, \
|
||||
{ "opencl_options", HAS_ARG, {.func_arg = opt_opencl}, \
|
||||
"set OpenCL environment options" }, \
|
||||
|
||||
#else
|
||||
#define CMDUTILS_COMMON_OPTIONS_OPENCL
|
||||
#endif
|
||||
|
||||
#if CONFIG_AVDEVICE
|
||||
#define CMDUTILS_COMMON_OPTIONS_AVDEVICE \
|
||||
{ "sources" , OPT_EXIT | HAS_ARG, { .func_arg = show_sources }, \
|
||||
@@ -256,7 +240,6 @@ void show_help_options(const OptionDef *options, const char *msg, int req_flags,
|
||||
{ "max_alloc", HAS_ARG, { .func_arg = opt_max_alloc }, "set maximum size of a single allocated block", "bytes" }, \
|
||||
{ "cpuflags", HAS_ARG | OPT_EXPERT, { .func_arg = opt_cpuflags }, "force specific cpu flags", "flags" }, \
|
||||
{ "hide_banner", OPT_BOOL | OPT_EXPERT, {&hide_banner}, "do not show program banner", "hide_banner" }, \
|
||||
CMDUTILS_COMMON_OPTIONS_OPENCL \
|
||||
CMDUTILS_COMMON_OPTIONS_AVDEVICE \
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,283 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Lenny Wang
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include "libavutil/opt.h"
|
||||
#include "libavutil/time.h"
|
||||
#include "libavutil/log.h"
|
||||
#include "libavutil/opencl.h"
|
||||
#include "libavutil/avstring.h"
|
||||
#include "cmdutils.h"
|
||||
|
||||
typedef struct {
|
||||
int platform_idx;
|
||||
int device_idx;
|
||||
char device_name[64];
|
||||
int64_t runtime;
|
||||
} OpenCLDeviceBenchmark;
|
||||
|
||||
const char *ocl_bench_source = AV_OPENCL_KERNEL(
|
||||
inline unsigned char clip_uint8(int a)
|
||||
{
|
||||
if (a & (~0xFF))
|
||||
return (-a)>>31;
|
||||
else
|
||||
return a;
|
||||
}
|
||||
|
||||
kernel void unsharp_bench(
|
||||
global unsigned char *src,
|
||||
global unsigned char *dst,
|
||||
global int *mask,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
int i, j, local_idx, lc_idx, sum = 0;
|
||||
int2 thread_idx, block_idx, global_idx, lm_idx;
|
||||
thread_idx.x = get_local_id(0);
|
||||
thread_idx.y = get_local_id(1);
|
||||
block_idx.x = get_group_id(0);
|
||||
block_idx.y = get_group_id(1);
|
||||
global_idx.x = get_global_id(0);
|
||||
global_idx.y = get_global_id(1);
|
||||
local uchar data[32][32];
|
||||
local int lc[128];
|
||||
|
||||
for (i = 0; i <= 1; i++) {
|
||||
lm_idx.y = -8 + (block_idx.y + i) * 16 + thread_idx.y;
|
||||
lm_idx.y = lm_idx.y < 0 ? 0 : lm_idx.y;
|
||||
lm_idx.y = lm_idx.y >= height ? height - 1: lm_idx.y;
|
||||
for (j = 0; j <= 1; j++) {
|
||||
lm_idx.x = -8 + (block_idx.x + j) * 16 + thread_idx.x;
|
||||
lm_idx.x = lm_idx.x < 0 ? 0 : lm_idx.x;
|
||||
lm_idx.x = lm_idx.x >= width ? width - 1: lm_idx.x;
|
||||
data[i*16 + thread_idx.y][j*16 + thread_idx.x] = src[lm_idx.y*width + lm_idx.x];
|
||||
}
|
||||
}
|
||||
local_idx = thread_idx.y*16 + thread_idx.x;
|
||||
if (local_idx < 128)
|
||||
lc[local_idx] = mask[local_idx];
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
\n#pragma unroll\n
|
||||
for (i = -4; i <= 4; i++) {
|
||||
lm_idx.y = 8 + i + thread_idx.y;
|
||||
\n#pragma unroll\n
|
||||
for (j = -4; j <= 4; j++) {
|
||||
lm_idx.x = 8 + j + thread_idx.x;
|
||||
lc_idx = (i + 4)*8 + j + 4;
|
||||
sum += (int)data[lm_idx.y][lm_idx.x] * lc[lc_idx];
|
||||
}
|
||||
}
|
||||
int temp = (int)data[thread_idx.y + 8][thread_idx.x + 8];
|
||||
int res = temp + (((temp - (int)((sum + 1<<15) >> 16))) >> 16);
|
||||
if (global_idx.x < width && global_idx.y < height)
|
||||
dst[global_idx.x + global_idx.y*width] = clip_uint8(res);
|
||||
}
|
||||
);
|
||||
|
||||
#define OCLCHECK(method, ... ) \
|
||||
do { \
|
||||
status = method(__VA_ARGS__); \
|
||||
if (status != CL_SUCCESS) { \
|
||||
av_log(NULL, AV_LOG_ERROR, # method " error '%s'\n", \
|
||||
av_opencl_errstr(status)); \
|
||||
ret = AVERROR_EXTERNAL; \
|
||||
goto end; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define CREATEBUF(out, flags, size) \
|
||||
do { \
|
||||
out = clCreateBuffer(ext_opencl_env->context, flags, size, NULL, &status); \
|
||||
if (status != CL_SUCCESS) { \
|
||||
av_log(NULL, AV_LOG_ERROR, "Could not create OpenCL buffer\n"); \
|
||||
ret = AVERROR_EXTERNAL; \
|
||||
goto end; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
static void fill_rand_int(int *data, int n)
|
||||
{
|
||||
int i;
|
||||
srand(av_gettime());
|
||||
for (i = 0; i < n; i++)
|
||||
data[i] = rand();
|
||||
}
|
||||
|
||||
#define OPENCL_NB_ITER 5
|
||||
static int64_t run_opencl_bench(AVOpenCLExternalEnv *ext_opencl_env)
|
||||
{
|
||||
int i, arg = 0, width = 1920, height = 1088;
|
||||
int64_t start, ret = 0;
|
||||
cl_int status;
|
||||
size_t kernel_len;
|
||||
char *inbuf;
|
||||
int *mask = NULL;
|
||||
int buf_size = width * height * sizeof(char);
|
||||
int mask_size = sizeof(uint32_t) * 128;
|
||||
|
||||
cl_mem cl_mask = NULL, cl_inbuf = NULL, cl_outbuf = NULL;
|
||||
cl_kernel kernel = NULL;
|
||||
cl_program program = NULL;
|
||||
size_t local_work_size_2d[2] = {16, 16};
|
||||
size_t global_work_size_2d[2] = {(size_t)width, (size_t)height};
|
||||
|
||||
if (!(inbuf = av_malloc(buf_size)) || !(mask = av_malloc(mask_size))) {
|
||||
av_log(NULL, AV_LOG_ERROR, "Out of memory\n");
|
||||
ret = AVERROR(ENOMEM);
|
||||
goto end;
|
||||
}
|
||||
fill_rand_int((int*)inbuf, buf_size/4);
|
||||
fill_rand_int(mask, mask_size/4);
|
||||
|
||||
CREATEBUF(cl_mask, CL_MEM_READ_ONLY, mask_size);
|
||||
CREATEBUF(cl_inbuf, CL_MEM_READ_ONLY, buf_size);
|
||||
CREATEBUF(cl_outbuf, CL_MEM_READ_WRITE, buf_size);
|
||||
|
||||
kernel_len = strlen(ocl_bench_source);
|
||||
program = clCreateProgramWithSource(ext_opencl_env->context, 1, &ocl_bench_source,
|
||||
&kernel_len, &status);
|
||||
if (status != CL_SUCCESS || !program) {
|
||||
av_log(NULL, AV_LOG_ERROR, "OpenCL unable to create benchmark program\n");
|
||||
ret = AVERROR_EXTERNAL;
|
||||
goto end;
|
||||
}
|
||||
status = clBuildProgram(program, 1, &(ext_opencl_env->device_id), NULL, NULL, NULL);
|
||||
if (status != CL_SUCCESS) {
|
||||
av_log(NULL, AV_LOG_ERROR, "OpenCL unable to build benchmark program\n");
|
||||
ret = AVERROR_EXTERNAL;
|
||||
goto end;
|
||||
}
|
||||
kernel = clCreateKernel(program, "unsharp_bench", &status);
|
||||
if (status != CL_SUCCESS) {
|
||||
av_log(NULL, AV_LOG_ERROR, "OpenCL unable to create benchmark kernel\n");
|
||||
ret = AVERROR_EXTERNAL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
OCLCHECK(clEnqueueWriteBuffer, ext_opencl_env->command_queue, cl_inbuf, CL_TRUE, 0,
|
||||
buf_size, inbuf, 0, NULL, NULL);
|
||||
OCLCHECK(clEnqueueWriteBuffer, ext_opencl_env->command_queue, cl_mask, CL_TRUE, 0,
|
||||
mask_size, mask, 0, NULL, NULL);
|
||||
OCLCHECK(clSetKernelArg, kernel, arg++, sizeof(cl_mem), &cl_inbuf);
|
||||
OCLCHECK(clSetKernelArg, kernel, arg++, sizeof(cl_mem), &cl_outbuf);
|
||||
OCLCHECK(clSetKernelArg, kernel, arg++, sizeof(cl_mem), &cl_mask);
|
||||
OCLCHECK(clSetKernelArg, kernel, arg++, sizeof(cl_int), &width);
|
||||
OCLCHECK(clSetKernelArg, kernel, arg++, sizeof(cl_int), &height);
|
||||
|
||||
start = av_gettime_relative();
|
||||
for (i = 0; i < OPENCL_NB_ITER; i++)
|
||||
OCLCHECK(clEnqueueNDRangeKernel, ext_opencl_env->command_queue, kernel, 2, NULL,
|
||||
global_work_size_2d, local_work_size_2d, 0, NULL, NULL);
|
||||
clFinish(ext_opencl_env->command_queue);
|
||||
ret = (av_gettime_relative() - start)/OPENCL_NB_ITER;
|
||||
end:
|
||||
if (kernel)
|
||||
clReleaseKernel(kernel);
|
||||
if (program)
|
||||
clReleaseProgram(program);
|
||||
if (cl_inbuf)
|
||||
clReleaseMemObject(cl_inbuf);
|
||||
if (cl_outbuf)
|
||||
clReleaseMemObject(cl_outbuf);
|
||||
if (cl_mask)
|
||||
clReleaseMemObject(cl_mask);
|
||||
av_free(inbuf);
|
||||
av_free(mask);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int compare_ocl_device_desc(const void *a, const void *b)
|
||||
{
|
||||
const OpenCLDeviceBenchmark* va = (const OpenCLDeviceBenchmark*)a;
|
||||
const OpenCLDeviceBenchmark* vb = (const OpenCLDeviceBenchmark*)b;
|
||||
return FFDIFFSIGN(va->runtime , vb->runtime);
|
||||
}
|
||||
|
||||
int opt_opencl_bench(void *optctx, const char *opt, const char *arg)
|
||||
{
|
||||
int i, j, nb_devices = 0, count = 0, ret = 0;
|
||||
int64_t score = 0;
|
||||
AVOpenCLDeviceList *device_list;
|
||||
AVOpenCLDeviceNode *device_node = NULL;
|
||||
OpenCLDeviceBenchmark *devices = NULL;
|
||||
cl_platform_id platform;
|
||||
|
||||
ret = av_opencl_get_device_list(&device_list);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
for (i = 0; i < device_list->platform_num; i++)
|
||||
nb_devices += device_list->platform_node[i]->device_num;
|
||||
if (!nb_devices) {
|
||||
av_log(NULL, AV_LOG_ERROR, "No OpenCL device detected!\n");
|
||||
av_opencl_free_device_list(&device_list);
|
||||
return AVERROR(EINVAL);
|
||||
}
|
||||
if (!(devices = av_malloc_array(nb_devices, sizeof(OpenCLDeviceBenchmark)))) {
|
||||
av_log(NULL, AV_LOG_ERROR, "Could not allocate buffer\n");
|
||||
av_opencl_free_device_list(&device_list);
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
|
||||
for (i = 0; i < device_list->platform_num; i++) {
|
||||
for (j = 0; j < device_list->platform_node[i]->device_num; j++) {
|
||||
device_node = device_list->platform_node[i]->device_node[j];
|
||||
platform = device_list->platform_node[i]->platform_id;
|
||||
score = av_opencl_benchmark(device_node, platform, run_opencl_bench);
|
||||
if (score > 0) {
|
||||
devices[count].platform_idx = i;
|
||||
devices[count].device_idx = j;
|
||||
devices[count].runtime = score;
|
||||
av_strlcpy(devices[count].device_name, device_node->device_name,
|
||||
sizeof(devices[count].device_name));
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
qsort(devices, count, sizeof(OpenCLDeviceBenchmark), compare_ocl_device_desc);
|
||||
fprintf(stderr, "platform_idx\tdevice_idx\tdevice_name\truntime\n");
|
||||
for (i = 0; i < count; i++)
|
||||
fprintf(stdout, "%d\t%d\t%s\t%"PRId64"\n",
|
||||
devices[i].platform_idx, devices[i].device_idx,
|
||||
devices[i].device_name, devices[i].runtime);
|
||||
|
||||
av_opencl_free_device_list(&device_list);
|
||||
av_free(devices);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int opt_opencl(void *optctx, const char *opt, const char *arg)
|
||||
{
|
||||
char *key, *value;
|
||||
const char *opts = arg;
|
||||
int ret = 0;
|
||||
while (*opts) {
|
||||
ret = av_opt_get_key_value(&opts, "=", ":", 0, &key, &value);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = av_opencl_set_option(key, value);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (*opts)
|
||||
opts++;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
+106
-87
@@ -61,6 +61,7 @@
|
||||
#include "libavutil/timestamp.h"
|
||||
#include "libavutil/bprint.h"
|
||||
#include "libavutil/time.h"
|
||||
#include "libavutil/thread.h"
|
||||
#include "libavutil/threadmessage.h"
|
||||
#include "libavcodec/mathops.h"
|
||||
#include "libavformat/os_support.h"
|
||||
@@ -98,10 +99,6 @@
|
||||
#include <conio.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_PTHREADS
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#include "ffmpeg.h"
|
||||
@@ -161,7 +158,7 @@ static struct termios oldtty;
|
||||
static int restore_tty;
|
||||
#endif
|
||||
|
||||
#if HAVE_PTHREADS
|
||||
#if HAVE_THREADS
|
||||
static void free_input_threads(void);
|
||||
#endif
|
||||
|
||||
@@ -220,13 +217,18 @@ static void sub2video_push_ref(InputStream *ist, int64_t pts)
|
||||
{
|
||||
AVFrame *frame = ist->sub2video.frame;
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
av_assert1(frame->data[0]);
|
||||
ist->sub2video.last_pts = frame->pts = pts;
|
||||
for (i = 0; i < ist->nb_filters; i++)
|
||||
av_buffersrc_add_frame_flags(ist->filters[i]->filter, frame,
|
||||
for (i = 0; i < ist->nb_filters; i++) {
|
||||
ret = av_buffersrc_add_frame_flags(ist->filters[i]->filter, frame,
|
||||
AV_BUFFERSRC_FLAG_KEEP_REF |
|
||||
AV_BUFFERSRC_FLAG_PUSH);
|
||||
if (ret != AVERROR_EOF && ret < 0)
|
||||
av_log(NULL, AV_LOG_WARNING, "Error while add the frame to buffer source(%s).\n",
|
||||
av_err2str(ret));
|
||||
}
|
||||
}
|
||||
|
||||
void sub2video_update(InputStream *ist, AVSubtitle *sub)
|
||||
@@ -295,11 +297,15 @@ static void sub2video_heartbeat(InputStream *ist, int64_t pts)
|
||||
static void sub2video_flush(InputStream *ist)
|
||||
{
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
if (ist->sub2video.end_pts < INT64_MAX)
|
||||
sub2video_update(ist, NULL);
|
||||
for (i = 0; i < ist->nb_filters; i++)
|
||||
av_buffersrc_add_frame(ist->filters[i]->filter, NULL);
|
||||
for (i = 0; i < ist->nb_filters; i++) {
|
||||
ret = av_buffersrc_add_frame(ist->filters[i]->filter, NULL);
|
||||
if (ret != AVERROR_EOF && ret < 0)
|
||||
av_log(NULL, AV_LOG_WARNING, "Flush the frame error.\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* end of sub2video hack */
|
||||
@@ -327,13 +333,14 @@ static int main_return_code = 0;
|
||||
static void
|
||||
sigterm_handler(int sig)
|
||||
{
|
||||
int ret;
|
||||
received_sigterm = sig;
|
||||
received_nb_signals++;
|
||||
term_exit_sigsafe();
|
||||
if(received_nb_signals > 3) {
|
||||
write(2/*STDERR_FILENO*/, "Received > 3 system signals, hard exiting\n",
|
||||
ret = write(2/*STDERR_FILENO*/, "Received > 3 system signals, hard exiting\n",
|
||||
strlen("Received > 3 system signals, hard exiting\n"));
|
||||
|
||||
if (ret < 0) { /* Do nothing */ };
|
||||
exit(123);
|
||||
}
|
||||
}
|
||||
@@ -568,7 +575,7 @@ static void ffmpeg_cleanup(int ret)
|
||||
|
||||
av_freep(&output_streams[i]);
|
||||
}
|
||||
#if HAVE_PTHREADS
|
||||
#if HAVE_THREADS
|
||||
free_input_threads();
|
||||
#endif
|
||||
for (i = 0; i < nb_input_files; i++) {
|
||||
@@ -1199,24 +1206,6 @@ static void do_video_out(OutputFile *of,
|
||||
#endif
|
||||
return;
|
||||
|
||||
#if FF_API_LAVF_FMT_RAWPICTURE
|
||||
if (of->ctx->oformat->flags & AVFMT_RAWPICTURE &&
|
||||
enc->codec->id == AV_CODEC_ID_RAWVIDEO) {
|
||||
/* raw pictures are written as AVPicture structure to
|
||||
avoid any copies. We support temporarily the older
|
||||
method. */
|
||||
if (in_picture->interlaced_frame)
|
||||
mux_par->field_order = in_picture->top_field_first ? AV_FIELD_TB:AV_FIELD_BT;
|
||||
else
|
||||
mux_par->field_order = AV_FIELD_PROGRESSIVE;
|
||||
pkt.data = (uint8_t *)in_picture;
|
||||
pkt.size = sizeof(AVPicture);
|
||||
pkt.pts = av_rescale_q(in_picture->pts, enc->time_base, ost->mux_timebase);
|
||||
pkt.flags |= AV_PKT_FLAG_KEY;
|
||||
|
||||
output_packet(of, &pkt, ost, 0);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
int forced_keyframe = 0;
|
||||
double pts_time;
|
||||
@@ -1897,10 +1886,6 @@ static void flush_encoders(void)
|
||||
|
||||
if (enc->codec_type == AVMEDIA_TYPE_AUDIO && enc->frame_size <= 1)
|
||||
continue;
|
||||
#if FF_API_LAVF_FMT_RAWPICTURE
|
||||
if (enc->codec_type == AVMEDIA_TYPE_VIDEO && (of->ctx->oformat->flags & AVFMT_RAWPICTURE) && enc->codec->id == AV_CODEC_ID_RAWVIDEO)
|
||||
continue;
|
||||
#endif
|
||||
|
||||
if (enc->codec_type != AVMEDIA_TYPE_VIDEO && enc->codec_type != AVMEDIA_TYPE_AUDIO)
|
||||
continue;
|
||||
@@ -1991,11 +1976,16 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p
|
||||
InputFile *f = input_files [ist->file_index];
|
||||
int64_t start_time = (of->start_time == AV_NOPTS_VALUE) ? 0 : of->start_time;
|
||||
int64_t ost_tb_start_time = av_rescale_q(start_time, AV_TIME_BASE_Q, ost->mux_timebase);
|
||||
AVPicture pict;
|
||||
AVPacket opkt;
|
||||
AVPacket opkt = { 0 };
|
||||
|
||||
av_init_packet(&opkt);
|
||||
|
||||
// EOF: flush output bitstream filters.
|
||||
if (!pkt) {
|
||||
output_packet(of, &opkt, ost, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((!ost->frame_number && !(pkt->flags & AV_PKT_FLAG_KEY)) &&
|
||||
!ost->copy_initial_nonkeyframes)
|
||||
return;
|
||||
@@ -2079,23 +2069,6 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p
|
||||
}
|
||||
av_copy_packet_side_data(&opkt, pkt);
|
||||
|
||||
#if FF_API_LAVF_FMT_RAWPICTURE
|
||||
if (ost->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
|
||||
ost->st->codecpar->codec_id == AV_CODEC_ID_RAWVIDEO &&
|
||||
(of->ctx->oformat->flags & AVFMT_RAWPICTURE)) {
|
||||
/* store AVPicture in AVPacket, as expected by the output format */
|
||||
int ret = avpicture_fill(&pict, opkt.data, ost->st->codecpar->format, ost->st->codecpar->width, ost->st->codecpar->height);
|
||||
if (ret < 0) {
|
||||
av_log(NULL, AV_LOG_FATAL, "avpicture_fill failed: %s\n",
|
||||
av_err2str(ret));
|
||||
exit_program(1);
|
||||
}
|
||||
opkt.data = (uint8_t *)&pict;
|
||||
opkt.size = sizeof(AVPicture);
|
||||
opkt.flags |= AV_PKT_FLAG_KEY;
|
||||
}
|
||||
#endif
|
||||
|
||||
output_packet(of, &opkt, ost, 0);
|
||||
}
|
||||
|
||||
@@ -2733,7 +2706,7 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo
|
||||
}
|
||||
|
||||
/* handle stream copy */
|
||||
if (!ist->decoding_needed) {
|
||||
if (!ist->decoding_needed && pkt) {
|
||||
ist->dts = ist->next_dts;
|
||||
switch (ist->dec_ctx->codec_type) {
|
||||
case AVMEDIA_TYPE_AUDIO:
|
||||
@@ -2759,7 +2732,7 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo
|
||||
ist->pts = ist->dts;
|
||||
ist->next_pts = ist->next_dts;
|
||||
}
|
||||
for (i = 0; pkt && i < nb_output_streams; i++) {
|
||||
for (i = 0; i < nb_output_streams; i++) {
|
||||
OutputStream *ost = output_streams[i];
|
||||
|
||||
if (!check_output_constraints(ist, ost) || ost->encoding_needed)
|
||||
@@ -2816,44 +2789,77 @@ fail:
|
||||
av_freep(&avc);
|
||||
}
|
||||
|
||||
static const HWAccel *get_hwaccel(enum AVPixelFormat pix_fmt)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; hwaccels[i].name; i++)
|
||||
if (hwaccels[i].pix_fmt == pix_fmt)
|
||||
return &hwaccels[i];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static enum AVPixelFormat get_format(AVCodecContext *s, const enum AVPixelFormat *pix_fmts)
|
||||
{
|
||||
InputStream *ist = s->opaque;
|
||||
const enum AVPixelFormat *p;
|
||||
int ret;
|
||||
|
||||
for (p = pix_fmts; *p != -1; p++) {
|
||||
for (p = pix_fmts; *p != AV_PIX_FMT_NONE; p++) {
|
||||
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(*p);
|
||||
const HWAccel *hwaccel;
|
||||
const AVCodecHWConfig *config = NULL;
|
||||
int i;
|
||||
|
||||
if (!(desc->flags & AV_PIX_FMT_FLAG_HWACCEL))
|
||||
break;
|
||||
|
||||
hwaccel = get_hwaccel(*p);
|
||||
if (!hwaccel ||
|
||||
(ist->active_hwaccel_id && ist->active_hwaccel_id != hwaccel->id) ||
|
||||
(ist->hwaccel_id != HWACCEL_AUTO && ist->hwaccel_id != hwaccel->id))
|
||||
if (ist->hwaccel_id == HWACCEL_GENERIC ||
|
||||
ist->hwaccel_id == HWACCEL_AUTO) {
|
||||
for (i = 0;; i++) {
|
||||
config = avcodec_get_hw_config(s->codec, i);
|
||||
if (!config)
|
||||
break;
|
||||
if (!(config->methods &
|
||||
AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX))
|
||||
continue;
|
||||
if (config->pix_fmt == *p)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (config) {
|
||||
if (config->device_type != ist->hwaccel_device_type) {
|
||||
// Different hwaccel offered, ignore.
|
||||
continue;
|
||||
}
|
||||
|
||||
ret = hwaccel_decode_init(s);
|
||||
if (ret < 0) {
|
||||
if (ist->hwaccel_id == HWACCEL_GENERIC) {
|
||||
av_log(NULL, AV_LOG_FATAL,
|
||||
"%s hwaccel requested for input stream #%d:%d, "
|
||||
"but cannot be initialized.\n",
|
||||
av_hwdevice_get_type_name(config->device_type),
|
||||
ist->file_index, ist->st->index);
|
||||
return AV_PIX_FMT_NONE;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
const HWAccel *hwaccel = NULL;
|
||||
int i;
|
||||
for (i = 0; hwaccels[i].name; i++) {
|
||||
if (hwaccels[i].pix_fmt == *p) {
|
||||
hwaccel = &hwaccels[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!hwaccel) {
|
||||
// No hwaccel supporting this pixfmt.
|
||||
continue;
|
||||
}
|
||||
if (hwaccel->id != ist->hwaccel_id) {
|
||||
// Does not match requested hwaccel.
|
||||
continue;
|
||||
}
|
||||
|
||||
ret = hwaccel->init(s);
|
||||
if (ret < 0) {
|
||||
if (ist->hwaccel_id == hwaccel->id) {
|
||||
av_log(NULL, AV_LOG_FATAL,
|
||||
"%s hwaccel requested for input stream #%d:%d, "
|
||||
"but cannot be initialized.\n", hwaccel->name,
|
||||
ist->file_index, ist->st->index);
|
||||
return AV_PIX_FMT_NONE;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ist->hw_frames_ctx) {
|
||||
@@ -2862,7 +2868,6 @@ static enum AVPixelFormat get_format(AVCodecContext *s, const enum AVPixelFormat
|
||||
return AV_PIX_FMT_NONE;
|
||||
}
|
||||
|
||||
ist->active_hwaccel_id = hwaccel->id;
|
||||
ist->hwaccel_pix_fmt = *p;
|
||||
break;
|
||||
}
|
||||
@@ -2910,7 +2915,7 @@ static int init_input_stream(int ist_index, char *error, int error_len)
|
||||
|
||||
/* Useful for subtitles retiming by lavf (FIXME), skipping samples in
|
||||
* audio, and video decoders such as cuvid or mediacodec */
|
||||
av_codec_set_pkt_timebase(ist->dec_ctx, ist->st->time_base);
|
||||
ist->dec_ctx->pkt_timebase = ist->st->time_base;
|
||||
|
||||
if (!av_dict_get(ist->decoder_opts, "threads", NULL, 0))
|
||||
av_dict_set(&ist->decoder_opts, "threads", "auto", 0);
|
||||
@@ -3160,7 +3165,7 @@ static void set_encoder_id(OutputFile *of, OutputStream *ost)
|
||||
uint8_t *encoder_string;
|
||||
int encoder_string_len;
|
||||
int format_flags = 0;
|
||||
int codec_flags = 0;
|
||||
int codec_flags = ost->enc_ctx->flags;
|
||||
|
||||
if (av_dict_get(ost->st->metadata, "encoder", NULL, 0))
|
||||
return;
|
||||
@@ -3988,7 +3993,7 @@ static int check_keyboard_interaction(int64_t cur_time)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if HAVE_PTHREADS
|
||||
#if HAVE_THREADS
|
||||
static void *input_thread(void *arg)
|
||||
{
|
||||
InputFile *f = arg;
|
||||
@@ -4098,7 +4103,7 @@ static int get_input_packet(InputFile *f, AVPacket *pkt)
|
||||
}
|
||||
}
|
||||
|
||||
#if HAVE_PTHREADS
|
||||
#if HAVE_THREADS
|
||||
if (nb_input_files > 1)
|
||||
return get_input_packet_mt(f, pkt);
|
||||
#endif
|
||||
@@ -4180,14 +4185,17 @@ static int seek_to_start(InputFile *ifile, AVFormatContext *is)
|
||||
AVRational sample_rate = {1, avctx->sample_rate};
|
||||
|
||||
duration = av_rescale_q(ist->nb_samples, sample_rate, ist->st->time_base);
|
||||
} else
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
if (ist->framerate.num) {
|
||||
duration = av_rescale_q(1, ist->framerate, ist->st->time_base);
|
||||
duration = av_rescale_q(1, av_inv_q(ist->framerate), ist->st->time_base);
|
||||
} else if (ist->st->avg_frame_rate.num) {
|
||||
duration = av_rescale_q(1, ist->st->avg_frame_rate, ist->st->time_base);
|
||||
} else duration = 1;
|
||||
duration = av_rescale_q(1, av_inv_q(ist->st->avg_frame_rate), ist->st->time_base);
|
||||
} else {
|
||||
duration = 1;
|
||||
}
|
||||
}
|
||||
if (!ifile->duration)
|
||||
ifile->time_base = ist->st->time_base;
|
||||
@@ -4229,8 +4237,10 @@ static int process_input(int file_index)
|
||||
return ret;
|
||||
}
|
||||
if (ret < 0 && ifile->loop) {
|
||||
if ((ret = seek_to_start(ifile, is)) < 0)
|
||||
return ret;
|
||||
ret = seek_to_start(ifile, is);
|
||||
if (ret < 0)
|
||||
av_log(NULL, AV_LOG_WARNING, "Seek to start failed.\n");
|
||||
else
|
||||
ret = get_input_packet(ifile, &pkt);
|
||||
if (ret == AVERROR(EAGAIN)) {
|
||||
ifile->eagain = 1;
|
||||
@@ -4536,6 +4546,15 @@ static int transcode_step(void)
|
||||
}
|
||||
|
||||
if (ost->filter && ost->filter->graph->graph) {
|
||||
if (!ost->initialized) {
|
||||
char error[1024] = {0};
|
||||
ret = init_output_stream(ost, error, sizeof(error));
|
||||
if (ret < 0) {
|
||||
av_log(NULL, AV_LOG_ERROR, "Error initializing output stream %d:%d -- %s\n",
|
||||
ost->file_index, ost->index, error);
|
||||
exit_program(1);
|
||||
}
|
||||
}
|
||||
if ((ret = transcode_from_filter(ost->filter->graph, &ist)) < 0)
|
||||
return ret;
|
||||
if (!ist)
|
||||
@@ -4593,7 +4612,7 @@ static int transcode(void)
|
||||
|
||||
timer_start = av_gettime_relative();
|
||||
|
||||
#if HAVE_PTHREADS
|
||||
#if HAVE_THREADS
|
||||
if ((ret = init_input_threads()) < 0)
|
||||
goto fail;
|
||||
#endif
|
||||
@@ -4624,14 +4643,14 @@ static int transcode(void)
|
||||
/* dump report by using the output first video and audio streams */
|
||||
print_report(0, timer_start, cur_time);
|
||||
}
|
||||
#if HAVE_PTHREADS
|
||||
#if HAVE_THREADS
|
||||
free_input_threads();
|
||||
#endif
|
||||
|
||||
/* at the end of stream, we must flush the decoder buffers */
|
||||
for (i = 0; i < nb_input_streams; i++) {
|
||||
ist = input_streams[i];
|
||||
if (!input_files[ist->file_index]->eof_reached && ist->decoding_needed) {
|
||||
if (!input_files[ist->file_index]->eof_reached) {
|
||||
process_input_packet(ist, NULL, 0);
|
||||
}
|
||||
}
|
||||
@@ -4690,7 +4709,7 @@ static int transcode(void)
|
||||
ret = 0;
|
||||
|
||||
fail:
|
||||
#if HAVE_PTHREADS
|
||||
#if HAVE_THREADS
|
||||
free_input_threads();
|
||||
#endif
|
||||
|
||||
|
||||
+5
-14
@@ -25,10 +25,6 @@
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
|
||||
#if HAVE_PTHREADS
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#include "cmdutils.h"
|
||||
|
||||
#include "libavformat/avformat.h"
|
||||
@@ -45,6 +41,7 @@
|
||||
#include "libavutil/hwcontext.h"
|
||||
#include "libavutil/pixfmt.h"
|
||||
#include "libavutil/rational.h"
|
||||
#include "libavutil/thread.h"
|
||||
#include "libavutil/threadmessage.h"
|
||||
|
||||
#include "libswresample/swresample.h"
|
||||
@@ -61,14 +58,10 @@
|
||||
enum HWAccelID {
|
||||
HWACCEL_NONE = 0,
|
||||
HWACCEL_AUTO,
|
||||
HWACCEL_VDPAU,
|
||||
HWACCEL_DXVA2,
|
||||
HWACCEL_VDA,
|
||||
HWACCEL_GENERIC,
|
||||
HWACCEL_VIDEOTOOLBOX,
|
||||
HWACCEL_QSV,
|
||||
HWACCEL_VAAPI,
|
||||
HWACCEL_CUVID,
|
||||
HWACCEL_D3D11VA,
|
||||
};
|
||||
|
||||
typedef struct HWAccel {
|
||||
@@ -76,7 +69,6 @@ typedef struct HWAccel {
|
||||
int (*init)(AVCodecContext *s);
|
||||
enum HWAccelID id;
|
||||
enum AVPixelFormat pix_fmt;
|
||||
enum AVHWDeviceType device_type;
|
||||
} HWAccel;
|
||||
|
||||
typedef struct HWDevice {
|
||||
@@ -161,6 +153,7 @@ typedef struct OptionsContext {
|
||||
float mux_preload;
|
||||
float mux_max_delay;
|
||||
int shortest;
|
||||
int bitexact;
|
||||
|
||||
int video_disable;
|
||||
int audio_disable;
|
||||
@@ -369,11 +362,11 @@ typedef struct InputStream {
|
||||
|
||||
/* hwaccel options */
|
||||
enum HWAccelID hwaccel_id;
|
||||
enum AVHWDeviceType hwaccel_device_type;
|
||||
char *hwaccel_device;
|
||||
enum AVPixelFormat hwaccel_output_format;
|
||||
|
||||
/* hwaccel context */
|
||||
enum HWAccelID active_hwaccel_id;
|
||||
void *hwaccel_ctx;
|
||||
void (*hwaccel_uninit)(AVCodecContext *s);
|
||||
int (*hwaccel_get_buffer)(AVCodecContext *s, AVFrame *frame, int flags);
|
||||
@@ -419,7 +412,7 @@ typedef struct InputFile {
|
||||
int rate_emu;
|
||||
int accurate_seek;
|
||||
|
||||
#if HAVE_PTHREADS
|
||||
#if HAVE_THREADS
|
||||
AVThreadMessageQueue *in_thread_queue;
|
||||
pthread_t thread; /* thread reading from this file */
|
||||
int non_blocking; /* reading packets from the thread should not block */
|
||||
@@ -624,7 +617,6 @@ extern const AVIOInterruptCB int_cb;
|
||||
|
||||
extern const OptionDef options[];
|
||||
extern const HWAccel hwaccels[];
|
||||
extern int hwaccel_lax_profile_check;
|
||||
extern AVBufferRef *hw_device_ctx;
|
||||
#if CONFIG_QSV
|
||||
extern char *qsv_device;
|
||||
@@ -662,7 +654,6 @@ int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *frame);
|
||||
|
||||
int ffmpeg_parse_options(int argc, char **argv);
|
||||
|
||||
int vda_init(AVCodecContext *s);
|
||||
int videotoolbox_init(AVCodecContext *s);
|
||||
int qsv_init(AVCodecContext *s);
|
||||
int cuvid_init(AVCodecContext *s);
|
||||
|
||||
@@ -340,6 +340,7 @@ int init_complex_filtergraph(FilterGraph *fg)
|
||||
graph = avfilter_graph_alloc();
|
||||
if (!graph)
|
||||
return AVERROR(ENOMEM);
|
||||
graph->nb_threads = 1;
|
||||
|
||||
ret = avfilter_graph_parse2(graph, fg->graph_desc, &inputs, &outputs);
|
||||
if (ret < 0)
|
||||
|
||||
+172
-78
@@ -64,6 +64,31 @@ static HWDevice *hw_device_add(void)
|
||||
return hw_devices[nb_hw_devices++];
|
||||
}
|
||||
|
||||
static char *hw_device_default_name(enum AVHWDeviceType type)
|
||||
{
|
||||
// Make an automatic name of the form "type%d". We arbitrarily
|
||||
// limit at 1000 anonymous devices of the same type - there is
|
||||
// probably something else very wrong if you get to this limit.
|
||||
const char *type_name = av_hwdevice_get_type_name(type);
|
||||
char *name;
|
||||
size_t index_pos;
|
||||
int index, index_limit = 1000;
|
||||
index_pos = strlen(type_name);
|
||||
name = av_malloc(index_pos + 4);
|
||||
if (!name)
|
||||
return NULL;
|
||||
for (index = 0; index < index_limit; index++) {
|
||||
snprintf(name, index_pos + 4, "%s%d", type_name, index);
|
||||
if (!hw_device_get_by_name(name))
|
||||
break;
|
||||
}
|
||||
if (index >= index_limit) {
|
||||
av_freep(&name);
|
||||
return NULL;
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
int hw_device_init_from_string(const char *arg, HWDevice **dev_out)
|
||||
{
|
||||
// "type=name:device,key=value,key2=value2"
|
||||
@@ -111,27 +136,11 @@ int hw_device_init_from_string(const char *arg, HWDevice **dev_out)
|
||||
|
||||
p += 1 + k;
|
||||
} else {
|
||||
// Give the device an automatic name of the form "type%d".
|
||||
// We arbitrarily limit at 1000 anonymous devices of the same
|
||||
// type - there is probably something else very wrong if you
|
||||
// get to this limit.
|
||||
size_t index_pos;
|
||||
int index, index_limit = 1000;
|
||||
index_pos = strlen(type_name);
|
||||
name = av_malloc(index_pos + 4);
|
||||
name = hw_device_default_name(type);
|
||||
if (!name) {
|
||||
err = AVERROR(ENOMEM);
|
||||
goto fail;
|
||||
}
|
||||
for (index = 0; index < index_limit; index++) {
|
||||
snprintf(name, index_pos + 4, "%s%d", type_name, index);
|
||||
if (!hw_device_get_by_name(name))
|
||||
break;
|
||||
}
|
||||
if (index >= index_limit) {
|
||||
errmsg = "too many devices";
|
||||
goto invalid;
|
||||
}
|
||||
}
|
||||
|
||||
if (!*p) {
|
||||
@@ -214,6 +223,49 @@ fail:
|
||||
goto done;
|
||||
}
|
||||
|
||||
static int hw_device_init_from_type(enum AVHWDeviceType type,
|
||||
const char *device,
|
||||
HWDevice **dev_out)
|
||||
{
|
||||
AVBufferRef *device_ref = NULL;
|
||||
HWDevice *dev;
|
||||
char *name;
|
||||
int err;
|
||||
|
||||
name = hw_device_default_name(type);
|
||||
if (!name) {
|
||||
err = AVERROR(ENOMEM);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
err = av_hwdevice_ctx_create(&device_ref, type, device, NULL, 0);
|
||||
if (err < 0) {
|
||||
av_log(NULL, AV_LOG_ERROR,
|
||||
"Device creation failed: %d.\n", err);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
dev = hw_device_add();
|
||||
if (!dev) {
|
||||
err = AVERROR(ENOMEM);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
dev->name = name;
|
||||
dev->type = type;
|
||||
dev->device_ref = device_ref;
|
||||
|
||||
if (dev_out)
|
||||
*dev_out = dev;
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
av_freep(&name);
|
||||
av_buffer_unref(&device_ref);
|
||||
return err;
|
||||
}
|
||||
|
||||
void hw_device_free_all(void)
|
||||
{
|
||||
int i;
|
||||
@@ -226,80 +278,130 @@ void hw_device_free_all(void)
|
||||
nb_hw_devices = 0;
|
||||
}
|
||||
|
||||
static enum AVHWDeviceType hw_device_match_type_by_hwaccel(enum HWAccelID hwaccel_id)
|
||||
static HWDevice *hw_device_match_by_codec(const AVCodec *codec)
|
||||
{
|
||||
const AVCodecHWConfig *config;
|
||||
HWDevice *dev;
|
||||
int i;
|
||||
if (hwaccel_id == HWACCEL_NONE)
|
||||
return AV_HWDEVICE_TYPE_NONE;
|
||||
for (i = 0; hwaccels[i].name; i++) {
|
||||
if (hwaccels[i].id == hwaccel_id)
|
||||
return hwaccels[i].device_type;
|
||||
for (i = 0;; i++) {
|
||||
config = avcodec_get_hw_config(codec, i);
|
||||
if (!config)
|
||||
return NULL;
|
||||
if (!(config->methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX))
|
||||
continue;
|
||||
dev = hw_device_get_by_type(config->device_type);
|
||||
if (dev)
|
||||
return dev;
|
||||
}
|
||||
return AV_HWDEVICE_TYPE_NONE;
|
||||
}
|
||||
|
||||
static enum AVHWDeviceType hw_device_match_type_in_name(const char *codec_name)
|
||||
{
|
||||
const char *type_name;
|
||||
enum AVHWDeviceType type;
|
||||
for (type = av_hwdevice_iterate_types(AV_HWDEVICE_TYPE_NONE);
|
||||
type != AV_HWDEVICE_TYPE_NONE;
|
||||
type = av_hwdevice_iterate_types(type)) {
|
||||
type_name = av_hwdevice_get_type_name(type);
|
||||
if (strstr(codec_name, type_name))
|
||||
return type;
|
||||
}
|
||||
return AV_HWDEVICE_TYPE_NONE;
|
||||
}
|
||||
|
||||
int hw_device_setup_for_decode(InputStream *ist)
|
||||
{
|
||||
const AVCodecHWConfig *config;
|
||||
enum AVHWDeviceType type;
|
||||
HWDevice *dev;
|
||||
int err;
|
||||
HWDevice *dev = NULL;
|
||||
int err, auto_device = 0;
|
||||
|
||||
if (ist->hwaccel_device) {
|
||||
dev = hw_device_get_by_name(ist->hwaccel_device);
|
||||
if (!dev) {
|
||||
char *tmp;
|
||||
type = hw_device_match_type_by_hwaccel(ist->hwaccel_id);
|
||||
if (type == AV_HWDEVICE_TYPE_NONE) {
|
||||
// No match - this isn't necessarily invalid, though,
|
||||
// because an explicit device might not be needed or
|
||||
// the hwaccel setup could be handled elsewhere.
|
||||
if (ist->hwaccel_id == HWACCEL_AUTO) {
|
||||
auto_device = 1;
|
||||
} else if (ist->hwaccel_id == HWACCEL_GENERIC) {
|
||||
type = ist->hwaccel_device_type;
|
||||
err = hw_device_init_from_type(type, ist->hwaccel_device,
|
||||
&dev);
|
||||
} else {
|
||||
// This will be dealt with by API-specific initialisation
|
||||
// (using hwaccel_device), so nothing further needed here.
|
||||
return 0;
|
||||
}
|
||||
tmp = av_asprintf("%s:%s", av_hwdevice_get_type_name(type),
|
||||
ist->hwaccel_device);
|
||||
if (!tmp)
|
||||
return AVERROR(ENOMEM);
|
||||
err = hw_device_init_from_string(tmp, &dev);
|
||||
av_free(tmp);
|
||||
if (err < 0)
|
||||
return err;
|
||||
} else {
|
||||
if (ist->hwaccel_id == HWACCEL_AUTO) {
|
||||
ist->hwaccel_device_type = dev->type;
|
||||
} else if (ist->hwaccel_device_type != dev->type) {
|
||||
av_log(ist->dec_ctx, AV_LOG_ERROR, "Invalid hwaccel device "
|
||||
"specified for decoder: device %s of type %s is not "
|
||||
"usable with hwaccel %s.\n", dev->name,
|
||||
av_hwdevice_get_type_name(dev->type),
|
||||
av_hwdevice_get_type_name(ist->hwaccel_device_type));
|
||||
return AVERROR(EINVAL);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (ist->hwaccel_id != HWACCEL_NONE)
|
||||
type = hw_device_match_type_by_hwaccel(ist->hwaccel_id);
|
||||
else
|
||||
type = hw_device_match_type_in_name(ist->dec->name);
|
||||
if (type != AV_HWDEVICE_TYPE_NONE) {
|
||||
if (ist->hwaccel_id == HWACCEL_AUTO) {
|
||||
auto_device = 1;
|
||||
} else if (ist->hwaccel_id == HWACCEL_GENERIC) {
|
||||
type = ist->hwaccel_device_type;
|
||||
dev = hw_device_get_by_type(type);
|
||||
if (!dev) {
|
||||
hw_device_init_from_string(av_hwdevice_get_type_name(type),
|
||||
&dev);
|
||||
}
|
||||
if (!dev)
|
||||
err = hw_device_init_from_type(type, NULL, &dev);
|
||||
} else {
|
||||
// No device required.
|
||||
dev = hw_device_match_by_codec(ist->dec);
|
||||
if (!dev) {
|
||||
// No device for this codec, but not using generic hwaccel
|
||||
// and therefore may well not need one - ignore.
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (auto_device) {
|
||||
int i;
|
||||
if (!avcodec_get_hw_config(ist->dec, 0)) {
|
||||
// Decoder does not support any hardware devices.
|
||||
return 0;
|
||||
}
|
||||
for (i = 0; !dev; i++) {
|
||||
config = avcodec_get_hw_config(ist->dec, i);
|
||||
if (!config)
|
||||
break;
|
||||
type = config->device_type;
|
||||
dev = hw_device_get_by_type(type);
|
||||
if (dev) {
|
||||
av_log(ist->dec_ctx, AV_LOG_INFO, "Using auto "
|
||||
"hwaccel type %s with existing device %s.\n",
|
||||
av_hwdevice_get_type_name(type), dev->name);
|
||||
}
|
||||
}
|
||||
for (i = 0; !dev; i++) {
|
||||
config = avcodec_get_hw_config(ist->dec, i);
|
||||
if (!config)
|
||||
break;
|
||||
type = config->device_type;
|
||||
// Try to make a new device of this type.
|
||||
err = hw_device_init_from_type(type, ist->hwaccel_device,
|
||||
&dev);
|
||||
if (err < 0) {
|
||||
// Can't make a device of this type.
|
||||
continue;
|
||||
}
|
||||
if (ist->hwaccel_device) {
|
||||
av_log(ist->dec_ctx, AV_LOG_INFO, "Using auto "
|
||||
"hwaccel type %s with new device created "
|
||||
"from %s.\n", av_hwdevice_get_type_name(type),
|
||||
ist->hwaccel_device);
|
||||
} else {
|
||||
av_log(ist->dec_ctx, AV_LOG_INFO, "Using auto "
|
||||
"hwaccel type %s with new default device.\n",
|
||||
av_hwdevice_get_type_name(type));
|
||||
}
|
||||
}
|
||||
if (dev) {
|
||||
ist->hwaccel_device_type = type;
|
||||
} else {
|
||||
av_log(ist->dec_ctx, AV_LOG_INFO, "Auto hwaccel "
|
||||
"disabled: no device found.\n");
|
||||
ist->hwaccel_id = HWACCEL_NONE;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!dev) {
|
||||
av_log(ist->dec_ctx, AV_LOG_WARNING, "No device available "
|
||||
"for decoder (device type %s for codec %s).\n",
|
||||
av_log(ist->dec_ctx, AV_LOG_ERROR, "No device available "
|
||||
"for decoder: device type %s needed for codec %s.\n",
|
||||
av_hwdevice_get_type_name(type), ist->dec->name);
|
||||
return 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
ist->dec_ctx->hw_device_ctx = av_buffer_ref(dev->device_ref);
|
||||
@@ -311,24 +413,16 @@ int hw_device_setup_for_decode(InputStream *ist)
|
||||
|
||||
int hw_device_setup_for_encode(OutputStream *ost)
|
||||
{
|
||||
enum AVHWDeviceType type;
|
||||
HWDevice *dev;
|
||||
|
||||
type = hw_device_match_type_in_name(ost->enc->name);
|
||||
if (type != AV_HWDEVICE_TYPE_NONE) {
|
||||
dev = hw_device_get_by_type(type);
|
||||
if (!dev) {
|
||||
av_log(ost->enc_ctx, AV_LOG_WARNING, "No device available "
|
||||
"for encoder (device type %s for codec %s).\n",
|
||||
av_hwdevice_get_type_name(type), ost->enc->name);
|
||||
return 0;
|
||||
}
|
||||
dev = hw_device_match_by_codec(ost->enc);
|
||||
if (dev) {
|
||||
ost->enc_ctx->hw_device_ctx = av_buffer_ref(dev->device_ref);
|
||||
if (!ost->enc_ctx->hw_device_ctx)
|
||||
return AVERROR(ENOMEM);
|
||||
return 0;
|
||||
} else {
|
||||
// No device required.
|
||||
// No device required, or no device available.
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
+75
-152
@@ -66,41 +66,17 @@
|
||||
}
|
||||
|
||||
const HWAccel hwaccels[] = {
|
||||
#if HAVE_VDPAU_X11
|
||||
{ "vdpau", hwaccel_decode_init, HWACCEL_VDPAU, AV_PIX_FMT_VDPAU,
|
||||
AV_HWDEVICE_TYPE_VDPAU },
|
||||
#endif
|
||||
#if CONFIG_D3D11VA
|
||||
{ "d3d11va", hwaccel_decode_init, HWACCEL_D3D11VA, AV_PIX_FMT_D3D11,
|
||||
AV_HWDEVICE_TYPE_D3D11VA },
|
||||
#endif
|
||||
#if CONFIG_DXVA2
|
||||
{ "dxva2", hwaccel_decode_init, HWACCEL_DXVA2, AV_PIX_FMT_DXVA2_VLD,
|
||||
AV_HWDEVICE_TYPE_DXVA2 },
|
||||
#endif
|
||||
#if CONFIG_VDA
|
||||
{ "vda", videotoolbox_init, HWACCEL_VDA, AV_PIX_FMT_VDA,
|
||||
AV_HWDEVICE_TYPE_NONE },
|
||||
#endif
|
||||
#if CONFIG_VIDEOTOOLBOX
|
||||
{ "videotoolbox", videotoolbox_init, HWACCEL_VIDEOTOOLBOX, AV_PIX_FMT_VIDEOTOOLBOX,
|
||||
AV_HWDEVICE_TYPE_NONE },
|
||||
{ "videotoolbox", videotoolbox_init, HWACCEL_VIDEOTOOLBOX, AV_PIX_FMT_VIDEOTOOLBOX },
|
||||
#endif
|
||||
#if CONFIG_LIBMFX
|
||||
{ "qsv", qsv_init, HWACCEL_QSV, AV_PIX_FMT_QSV,
|
||||
AV_HWDEVICE_TYPE_NONE },
|
||||
#endif
|
||||
#if CONFIG_VAAPI
|
||||
{ "vaapi", hwaccel_decode_init, HWACCEL_VAAPI, AV_PIX_FMT_VAAPI,
|
||||
AV_HWDEVICE_TYPE_VAAPI },
|
||||
{ "qsv", qsv_init, HWACCEL_QSV, AV_PIX_FMT_QSV },
|
||||
#endif
|
||||
#if CONFIG_CUVID
|
||||
{ "cuvid", cuvid_init, HWACCEL_CUVID, AV_PIX_FMT_CUDA,
|
||||
AV_HWDEVICE_TYPE_NONE },
|
||||
{ "cuvid", cuvid_init, HWACCEL_CUVID, AV_PIX_FMT_CUDA },
|
||||
#endif
|
||||
{ 0 },
|
||||
};
|
||||
int hwaccel_lax_profile_check = 0;
|
||||
AVBufferRef *hw_device_ctx;
|
||||
HWDevice *filter_hw_device;
|
||||
|
||||
@@ -141,7 +117,6 @@ static int file_overwrite = 0;
|
||||
static int no_file_overwrite = 0;
|
||||
static int do_psnr = 0;
|
||||
static int input_sync;
|
||||
static int override_ffserver = 0;
|
||||
static int input_stream_potentially_available = 0;
|
||||
static int ignore_unknown_streams = 0;
|
||||
static int copy_unknown_streams = 0;
|
||||
@@ -195,12 +170,15 @@ static void init_options(OptionsContext *o)
|
||||
|
||||
static int show_hwaccels(void *optctx, const char *opt, const char *arg)
|
||||
{
|
||||
enum AVHWDeviceType type = AV_HWDEVICE_TYPE_NONE;
|
||||
int i;
|
||||
|
||||
printf("Hardware acceleration methods:\n");
|
||||
for (i = 0; hwaccels[i].name; i++) {
|
||||
while ((type = av_hwdevice_iterate_types(type)) !=
|
||||
AV_HWDEVICE_TYPE_NONE)
|
||||
printf("%s\n", av_hwdevice_get_type_name(type));
|
||||
for (i = 0; hwaccels[i].name; i++)
|
||||
printf("%s\n", hwaccels[i].name);
|
||||
}
|
||||
printf("\n");
|
||||
return 0;
|
||||
}
|
||||
@@ -723,7 +701,8 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic)
|
||||
AVStream *st = ic->streams[i];
|
||||
AVCodecParameters *par = st->codecpar;
|
||||
InputStream *ist = av_mallocz(sizeof(*ist));
|
||||
char *framerate = NULL, *hwaccel = NULL, *hwaccel_device = NULL;
|
||||
char *framerate = NULL, *hwaccel_device = NULL;
|
||||
const char *hwaccel = NULL;
|
||||
char *hwaccel_output_format = NULL;
|
||||
char *codec_tag = NULL;
|
||||
char *next;
|
||||
@@ -787,20 +766,20 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic)
|
||||
exit_program(1);
|
||||
}
|
||||
|
||||
if (o->bitexact)
|
||||
ist->dec_ctx->flags |= AV_CODEC_FLAG_BITEXACT;
|
||||
|
||||
switch (par->codec_type) {
|
||||
case AVMEDIA_TYPE_VIDEO:
|
||||
if(!ist->dec)
|
||||
ist->dec = avcodec_find_decoder(par->codec_id);
|
||||
#if FF_API_LOWRES
|
||||
if (av_codec_get_lowres(st->codec)) {
|
||||
av_codec_set_lowres(ist->dec_ctx, av_codec_get_lowres(st->codec));
|
||||
if (st->codec->lowres) {
|
||||
ist->dec_ctx->lowres = st->codec->lowres;
|
||||
ist->dec_ctx->width = st->codec->width;
|
||||
ist->dec_ctx->height = st->codec->height;
|
||||
ist->dec_ctx->coded_width = st->codec->coded_width;
|
||||
ist->dec_ctx->coded_height = st->codec->coded_height;
|
||||
#if FF_API_EMU_EDGE
|
||||
ist->dec_ctx->flags |= CODEC_FLAG_EMU_EDGE;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -820,11 +799,16 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic)
|
||||
|
||||
MATCH_PER_STREAM_OPT(hwaccels, str, hwaccel, ic, st);
|
||||
if (hwaccel) {
|
||||
// The NVDEC hwaccels use a CUDA device, so remap the name here.
|
||||
if (!strcmp(hwaccel, "nvdec"))
|
||||
hwaccel = "cuda";
|
||||
|
||||
if (!strcmp(hwaccel, "none"))
|
||||
ist->hwaccel_id = HWACCEL_NONE;
|
||||
else if (!strcmp(hwaccel, "auto"))
|
||||
ist->hwaccel_id = HWACCEL_AUTO;
|
||||
else {
|
||||
enum AVHWDeviceType type;
|
||||
int i;
|
||||
for (i = 0; hwaccels[i].name; i++) {
|
||||
if (!strcmp(hwaccels[i].name, hwaccel)) {
|
||||
@@ -833,10 +817,23 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic)
|
||||
}
|
||||
}
|
||||
|
||||
if (!ist->hwaccel_id) {
|
||||
type = av_hwdevice_find_type_by_name(hwaccel);
|
||||
if (type != AV_HWDEVICE_TYPE_NONE) {
|
||||
ist->hwaccel_id = HWACCEL_GENERIC;
|
||||
ist->hwaccel_device_type = type;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ist->hwaccel_id) {
|
||||
av_log(NULL, AV_LOG_FATAL, "Unrecognized hwaccel: %s.\n",
|
||||
hwaccel);
|
||||
av_log(NULL, AV_LOG_FATAL, "Supported hwaccels: ");
|
||||
type = AV_HWDEVICE_TYPE_NONE;
|
||||
while ((type = av_hwdevice_iterate_types(type)) !=
|
||||
AV_HWDEVICE_TYPE_NONE)
|
||||
av_log(NULL, AV_LOG_FATAL, "%s ",
|
||||
av_hwdevice_get_type_name(type));
|
||||
for (i = 0; hwaccels[i].name; i++)
|
||||
av_log(NULL, AV_LOG_FATAL, "%s ", hwaccels[i].name);
|
||||
av_log(NULL, AV_LOG_FATAL, "\n");
|
||||
@@ -977,6 +974,21 @@ static int open_input_file(OptionsContext *o, const char *filename)
|
||||
char * data_codec_name = NULL;
|
||||
int scan_all_pmts_set = 0;
|
||||
|
||||
if (o->stop_time != INT64_MAX && o->recording_time != INT64_MAX) {
|
||||
o->stop_time = INT64_MAX;
|
||||
av_log(NULL, AV_LOG_WARNING, "-t and -to cannot be used together; using -t.\n");
|
||||
}
|
||||
|
||||
if (o->stop_time != INT64_MAX && o->recording_time == INT64_MAX) {
|
||||
int64_t start_time = o->start_time == AV_NOPTS_VALUE ? 0 : o->start_time;
|
||||
if (o->stop_time <= start_time) {
|
||||
av_log(NULL, AV_LOG_ERROR, "-to value smaller than -ss; aborting.\n");
|
||||
exit_program(1);
|
||||
} else {
|
||||
o->recording_time = o->stop_time - start_time;
|
||||
}
|
||||
}
|
||||
|
||||
if (o->format) {
|
||||
if (!(file_iformat = av_find_input_format(o->format))) {
|
||||
av_log(NULL, AV_LOG_FATAL, "Unknown input format: '%s'\n", o->format);
|
||||
@@ -996,7 +1008,6 @@ static int open_input_file(OptionsContext *o, const char *filename)
|
||||
print_error(filename, AVERROR(ENOMEM));
|
||||
exit_program(1);
|
||||
}
|
||||
ic->flags |= AVFMT_FLAG_KEEP_SIDE_DATA;
|
||||
if (o->nb_audio_sample_rate) {
|
||||
av_dict_set_int(&o->g->format_opts, "sample_rate", o->audio_sample_rate[o->nb_audio_sample_rate - 1].u.i, 0);
|
||||
}
|
||||
@@ -1031,25 +1042,23 @@ static int open_input_file(OptionsContext *o, const char *filename)
|
||||
MATCH_PER_TYPE_OPT(codec_names, str, subtitle_codec_name, ic, "s");
|
||||
MATCH_PER_TYPE_OPT(codec_names, str, data_codec_name, ic, "d");
|
||||
|
||||
ic->video_codec_id = video_codec_name ?
|
||||
find_codec_or_die(video_codec_name , AVMEDIA_TYPE_VIDEO , 0)->id : AV_CODEC_ID_NONE;
|
||||
ic->audio_codec_id = audio_codec_name ?
|
||||
find_codec_or_die(audio_codec_name , AVMEDIA_TYPE_AUDIO , 0)->id : AV_CODEC_ID_NONE;
|
||||
ic->subtitle_codec_id= subtitle_codec_name ?
|
||||
find_codec_or_die(subtitle_codec_name, AVMEDIA_TYPE_SUBTITLE, 0)->id : AV_CODEC_ID_NONE;
|
||||
ic->data_codec_id = data_codec_name ?
|
||||
find_codec_or_die(data_codec_name, AVMEDIA_TYPE_DATA, 0)->id : AV_CODEC_ID_NONE;
|
||||
|
||||
if (video_codec_name)
|
||||
av_format_set_video_codec (ic, find_codec_or_die(video_codec_name , AVMEDIA_TYPE_VIDEO , 0));
|
||||
ic->video_codec = find_codec_or_die(video_codec_name , AVMEDIA_TYPE_VIDEO , 0);
|
||||
if (audio_codec_name)
|
||||
av_format_set_audio_codec (ic, find_codec_or_die(audio_codec_name , AVMEDIA_TYPE_AUDIO , 0));
|
||||
ic->audio_codec = find_codec_or_die(audio_codec_name , AVMEDIA_TYPE_AUDIO , 0);
|
||||
if (subtitle_codec_name)
|
||||
av_format_set_subtitle_codec(ic, find_codec_or_die(subtitle_codec_name, AVMEDIA_TYPE_SUBTITLE, 0));
|
||||
ic->subtitle_codec = find_codec_or_die(subtitle_codec_name, AVMEDIA_TYPE_SUBTITLE, 0);
|
||||
if (data_codec_name)
|
||||
av_format_set_data_codec(ic, find_codec_or_die(data_codec_name, AVMEDIA_TYPE_DATA, 0));
|
||||
ic->data_codec = find_codec_or_die(data_codec_name , AVMEDIA_TYPE_DATA , 0);
|
||||
|
||||
ic->video_codec_id = video_codec_name ? ic->video_codec->id : AV_CODEC_ID_NONE;
|
||||
ic->audio_codec_id = audio_codec_name ? ic->audio_codec->id : AV_CODEC_ID_NONE;
|
||||
ic->subtitle_codec_id = subtitle_codec_name ? ic->subtitle_codec->id : AV_CODEC_ID_NONE;
|
||||
ic->data_codec_id = data_codec_name ? ic->data_codec->id : AV_CODEC_ID_NONE;
|
||||
|
||||
ic->flags |= AVFMT_FLAG_NONBLOCK;
|
||||
if (o->bitexact)
|
||||
ic->flags |= AVFMT_FLAG_BITEXACT;
|
||||
ic->interrupt_callback = int_cb;
|
||||
|
||||
if (!av_dict_get(o->g->format_opts, "scan_all_pmts", NULL, AV_DICT_MATCH_CASE)) {
|
||||
@@ -1151,7 +1160,7 @@ static int open_input_file(OptionsContext *o, const char *filename)
|
||||
f->loop = o->loop;
|
||||
f->duration = 0;
|
||||
f->time_base = (AVRational){ 1, 1 };
|
||||
#if HAVE_PTHREADS
|
||||
#if HAVE_THREADS
|
||||
f->thread_queue_size = o->thread_queue_size > 0 ? o->thread_queue_size : 8;
|
||||
#endif
|
||||
|
||||
@@ -1371,6 +1380,10 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e
|
||||
ost->encoder_opts = filter_codec_opts(o->g->codec_opts, AV_CODEC_ID_NONE, oc, st, NULL);
|
||||
}
|
||||
|
||||
|
||||
if (o->bitexact)
|
||||
ost->enc_ctx->flags |= AV_CODEC_FLAG_BITEXACT;
|
||||
|
||||
MATCH_PER_STREAM_OPT(time_bases, str, time_base, oc, st);
|
||||
if (time_base) {
|
||||
AVRational q;
|
||||
@@ -1663,7 +1676,7 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc, in
|
||||
av_log(NULL, AV_LOG_FATAL, "Could not allocate memory for intra matrix.\n");
|
||||
exit_program(1);
|
||||
}
|
||||
av_codec_set_chroma_intra_matrix(video_enc, p);
|
||||
video_enc->chroma_intra_matrix = p;
|
||||
parse_matrix_coeffs(p, chroma_intra_matrix);
|
||||
}
|
||||
MATCH_PER_STREAM_OPT(inter_matrices, str, inter_matrix, oc, st);
|
||||
@@ -1983,57 +1996,6 @@ static int copy_chapters(InputFile *ifile, OutputFile *ofile, int copy_metadata)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int read_ffserver_streams(OptionsContext *o, AVFormatContext *s, const char *filename)
|
||||
{
|
||||
int i, err;
|
||||
AVFormatContext *ic = avformat_alloc_context();
|
||||
|
||||
ic->flags |= AVFMT_FLAG_KEEP_SIDE_DATA;
|
||||
ic->interrupt_callback = int_cb;
|
||||
err = avformat_open_input(&ic, filename, NULL, NULL);
|
||||
if (err < 0)
|
||||
return err;
|
||||
/* copy stream format */
|
||||
for(i=0;i<ic->nb_streams;i++) {
|
||||
AVStream *st;
|
||||
OutputStream *ost;
|
||||
AVCodec *codec;
|
||||
const char *enc_config;
|
||||
|
||||
codec = avcodec_find_encoder(ic->streams[i]->codecpar->codec_id);
|
||||
if (!codec) {
|
||||
av_log(s, AV_LOG_ERROR, "no encoder found for codec id %i\n", ic->streams[i]->codecpar->codec_id);
|
||||
return AVERROR(EINVAL);
|
||||
}
|
||||
if (codec->type == AVMEDIA_TYPE_AUDIO)
|
||||
opt_audio_codec(o, "c:a", codec->name);
|
||||
else if (codec->type == AVMEDIA_TYPE_VIDEO)
|
||||
opt_video_codec(o, "c:v", codec->name);
|
||||
ost = new_output_stream(o, s, codec->type, -1);
|
||||
st = ost->st;
|
||||
|
||||
avcodec_get_context_defaults3(st->codec, codec);
|
||||
enc_config = av_stream_get_recommended_encoder_configuration(ic->streams[i]);
|
||||
if (enc_config) {
|
||||
AVDictionary *opts = NULL;
|
||||
av_dict_parse_string(&opts, enc_config, "=", ",", 0);
|
||||
av_opt_set_dict2(st->codec, &opts, AV_OPT_SEARCH_CHILDREN);
|
||||
av_dict_free(&opts);
|
||||
}
|
||||
|
||||
if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && !ost->stream_copy)
|
||||
choose_sample_fmt(st, codec);
|
||||
else if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && !ost->stream_copy)
|
||||
choose_pixel_fmt(st, st->codec, codec, st->codecpar->format);
|
||||
avcodec_copy_context(ost->enc_ctx, st->codec);
|
||||
if (enc_config)
|
||||
av_dict_parse_string(&ost->encoder_opts, enc_config, "=", ",", 0);
|
||||
}
|
||||
|
||||
avformat_close_input(&ic);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void init_output_filter(OutputFilter *ofilter, OptionsContext *o,
|
||||
AVFormatContext *oc)
|
||||
{
|
||||
@@ -2092,7 +2054,6 @@ static int open_output_file(OptionsContext *o, const char *filename)
|
||||
{
|
||||
AVFormatContext *oc;
|
||||
int i, j, err;
|
||||
AVOutputFormat *file_oformat;
|
||||
OutputFile *of;
|
||||
OutputStream *ost;
|
||||
InputStream *ist;
|
||||
@@ -2141,7 +2102,6 @@ static int open_output_file(OptionsContext *o, const char *filename)
|
||||
if (o->recording_time != INT64_MAX)
|
||||
oc->duration = o->recording_time;
|
||||
|
||||
file_oformat= oc->oformat;
|
||||
oc->interrupt_callback = int_cb;
|
||||
|
||||
e = av_dict_get(o->g->format_opts, "fflags", NULL, 0);
|
||||
@@ -2149,6 +2109,10 @@ static int open_output_file(OptionsContext *o, const char *filename)
|
||||
const AVOption *o = av_opt_find(oc, "fflags", NULL, 0, 0);
|
||||
av_opt_eval_flags(oc, o, e->value, &format_flags);
|
||||
}
|
||||
if (o->bitexact) {
|
||||
format_flags |= AVFMT_FLAG_BITEXACT;
|
||||
oc->flags |= AVFMT_FLAG_BITEXACT;
|
||||
}
|
||||
|
||||
/* create streams for all unlabeled output pads */
|
||||
for (i = 0; i < nb_filtergraphs; i++) {
|
||||
@@ -2168,47 +2132,7 @@ static int open_output_file(OptionsContext *o, const char *filename)
|
||||
}
|
||||
}
|
||||
|
||||
/* ffserver seeking with date=... needs a date reference */
|
||||
if (!strcmp(file_oformat->name, "ffm") &&
|
||||
!(format_flags & AVFMT_FLAG_BITEXACT) &&
|
||||
av_strstart(filename, "http:", NULL)) {
|
||||
int err = parse_option(o, "metadata", "creation_time=now", options);
|
||||
if (err < 0) {
|
||||
print_error(filename, err);
|
||||
exit_program(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (!strcmp(file_oformat->name, "ffm") && !override_ffserver &&
|
||||
av_strstart(filename, "http:", NULL)) {
|
||||
int j;
|
||||
/* special case for files sent to ffserver: we get the stream
|
||||
parameters from ffserver */
|
||||
int err = read_ffserver_streams(o, oc, filename);
|
||||
if (err < 0) {
|
||||
print_error(filename, err);
|
||||
exit_program(1);
|
||||
}
|
||||
for(j = nb_output_streams - oc->nb_streams; j < nb_output_streams; j++) {
|
||||
ost = output_streams[j];
|
||||
for (i = 0; i < nb_input_streams; i++) {
|
||||
ist = input_streams[i];
|
||||
if(ist->st->codecpar->codec_type == ost->st->codecpar->codec_type){
|
||||
ost->sync_ist= ist;
|
||||
ost->source_index= i;
|
||||
if(ost->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) ost->avfilter = av_strdup("anull");
|
||||
if(ost->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) ost->avfilter = av_strdup("null");
|
||||
ist->discard = 0;
|
||||
ist->st->discard = ist->user_set_discard;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!ost->sync_ist){
|
||||
av_log(NULL, AV_LOG_FATAL, "Missing %s stream which is required by this ffm\n", av_get_media_type_string(ost->st->codecpar->codec_type));
|
||||
exit_program(1);
|
||||
}
|
||||
}
|
||||
} else if (!o->nb_stream_maps) {
|
||||
if (!o->nb_stream_maps) {
|
||||
char *subtitle_codec_name = NULL;
|
||||
/* pick the "best" stream of each type */
|
||||
|
||||
@@ -3404,7 +3328,7 @@ const OptionDef options[] = {
|
||||
OPT_INPUT | OPT_OUTPUT, { .off = OFFSET(recording_time) },
|
||||
"record or transcode \"duration\" seconds of audio/video",
|
||||
"duration" },
|
||||
{ "to", HAS_ARG | OPT_TIME | OPT_OFFSET | OPT_OUTPUT, { .off = OFFSET(stop_time) },
|
||||
{ "to", HAS_ARG | OPT_TIME | OPT_OFFSET | OPT_INPUT | OPT_OUTPUT, { .off = OFFSET(stop_time) },
|
||||
"record or transcode stop time", "time_stop" },
|
||||
{ "fs", HAS_ARG | OPT_INT64 | OPT_OFFSET | OPT_OUTPUT, { .off = OFFSET(limit_filesize) },
|
||||
"set the limit file size in bytes", "limit_size" },
|
||||
@@ -3472,6 +3396,9 @@ const OptionDef options[] = {
|
||||
{ "shortest", OPT_BOOL | OPT_EXPERT | OPT_OFFSET |
|
||||
OPT_OUTPUT, { .off = OFFSET(shortest) },
|
||||
"finish encoding within shortest input" },
|
||||
{ "bitexact", OPT_BOOL | OPT_EXPERT | OPT_OFFSET |
|
||||
OPT_OUTPUT | OPT_INPUT, { .off = OFFSET(bitexact) },
|
||||
"bitexact mode" },
|
||||
{ "apad", OPT_STRING | HAS_ARG | OPT_SPEC |
|
||||
OPT_OUTPUT, { .off = OFFSET(apad) },
|
||||
"audio pad", "" },
|
||||
@@ -3632,7 +3559,7 @@ const OptionDef options[] = {
|
||||
{ "hwaccel_output_format", OPT_VIDEO | OPT_STRING | HAS_ARG | OPT_EXPERT |
|
||||
OPT_SPEC | OPT_INPUT, { .off = OFFSET(hwaccel_output_formats) },
|
||||
"select output format used with HW accelerated decoding", "format" },
|
||||
#if CONFIG_VDA || CONFIG_VIDEOTOOLBOX
|
||||
#if CONFIG_VIDEOTOOLBOX
|
||||
{ "videotoolbox_pixfmt", HAS_ARG | OPT_STRING | OPT_EXPERT, { &videotoolbox_pixfmt}, "" },
|
||||
#endif
|
||||
{ "hwaccels", OPT_EXIT, { .func_arg = show_hwaccels },
|
||||
@@ -3640,8 +3567,6 @@ const OptionDef options[] = {
|
||||
{ "autorotate", HAS_ARG | OPT_BOOL | OPT_SPEC |
|
||||
OPT_EXPERT | OPT_INPUT, { .off = OFFSET(autorotate) },
|
||||
"automatically insert correct rotate filters" },
|
||||
{ "hwaccel_lax_profile_check", OPT_BOOL | OPT_EXPERT, { &hwaccel_lax_profile_check},
|
||||
"attempt to decode anyway if HW accelerated decoder's supported profiles do not exactly match the stream" },
|
||||
|
||||
/* audio options */
|
||||
{ "aframes", OPT_AUDIO | HAS_ARG | OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_audio_frames },
|
||||
@@ -3699,8 +3624,6 @@ const OptionDef options[] = {
|
||||
"set the maximum demux-decode delay", "seconds" },
|
||||
{ "muxpreload", OPT_FLOAT | HAS_ARG | OPT_EXPERT | OPT_OFFSET | OPT_OUTPUT, { .off = OFFSET(mux_preload) },
|
||||
"set the initial demux-decode delay", "seconds" },
|
||||
{ "override_ffserver", OPT_BOOL | OPT_EXPERT | OPT_OUTPUT, { &override_ffserver },
|
||||
"override the options from ffserver", "" },
|
||||
{ "sdp_file", HAS_ARG | OPT_EXPERT | OPT_OUTPUT, { .func_arg = opt_sdp_file },
|
||||
"specify a file in which to print sdp information", "file" },
|
||||
|
||||
|
||||
@@ -23,12 +23,7 @@
|
||||
#endif
|
||||
|
||||
#include "libavcodec/avcodec.h"
|
||||
#if CONFIG_VDA
|
||||
# include "libavcodec/vda.h"
|
||||
#endif
|
||||
#if CONFIG_VIDEOTOOLBOX
|
||||
#include "libavcodec/videotoolbox.h"
|
||||
#endif
|
||||
#include "libavutil/imgutils.h"
|
||||
#include "ffmpeg.h"
|
||||
|
||||
@@ -114,15 +109,7 @@ static void videotoolbox_uninit(AVCodecContext *s)
|
||||
|
||||
av_frame_free(&vt->tmp_frame);
|
||||
|
||||
if (ist->hwaccel_id == HWACCEL_VIDEOTOOLBOX) {
|
||||
#if CONFIG_VIDEOTOOLBOX
|
||||
av_videotoolbox_default_free(s);
|
||||
#endif
|
||||
} else {
|
||||
#if CONFIG_VDA
|
||||
av_vda_default_free(s);
|
||||
#endif
|
||||
}
|
||||
av_freep(&ist->hwaccel_ctx);
|
||||
}
|
||||
|
||||
@@ -147,8 +134,7 @@ int videotoolbox_init(AVCodecContext *s)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (ist->hwaccel_id == HWACCEL_VIDEOTOOLBOX) {
|
||||
#if CONFIG_VIDEOTOOLBOX
|
||||
// TODO: reindent
|
||||
if (!videotoolbox_pixfmt) {
|
||||
ret = av_videotoolbox_default_init(s);
|
||||
} else {
|
||||
@@ -166,31 +152,8 @@ int videotoolbox_init(AVCodecContext *s)
|
||||
ret = av_videotoolbox_default_init2(s, vtctx);
|
||||
CFRelease(pixfmt_str);
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
#if CONFIG_VDA
|
||||
if (!videotoolbox_pixfmt) {
|
||||
ret = av_vda_default_init(s);
|
||||
} else {
|
||||
AVVDAContext *vdactx = av_vda_alloc_context();
|
||||
CFStringRef pixfmt_str = CFStringCreateWithCString(kCFAllocatorDefault,
|
||||
videotoolbox_pixfmt,
|
||||
kCFStringEncodingUTF8);
|
||||
#if HAVE_UTGETOSTYPEFROMSTRING
|
||||
vdactx->cv_pix_fmt_type = UTGetOSTypeFromString(pixfmt_str);
|
||||
#else
|
||||
av_log(s, loglevel, "UTGetOSTypeFromString() is not available "
|
||||
"on this platform, %s pixel format can not be honored from "
|
||||
"the command line\n", videotoolbox_pixfmt);
|
||||
#endif
|
||||
ret = av_vda_default_init2(s, vdactx);
|
||||
CFRelease(pixfmt_str);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (ret < 0) {
|
||||
av_log(NULL, loglevel,
|
||||
"Error creating %s decoder.\n", ist->hwaccel_id == HWACCEL_VIDEOTOOLBOX ? "Videotoolbox" : "VDA");
|
||||
av_log(NULL, loglevel, "Error creating Videotoolbox decoder.\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
||||
+55
-77
@@ -361,6 +361,8 @@ static AVPacket flush_pkt;
|
||||
|
||||
static SDL_Window *window;
|
||||
static SDL_Renderer *renderer;
|
||||
static SDL_RendererInfo renderer_info = {0};
|
||||
static SDL_AudioDeviceID audio_dev;
|
||||
|
||||
static const struct TextureFormatEntry {
|
||||
enum AVPixelFormat format;
|
||||
@@ -607,7 +609,7 @@ static int decoder_decode_frame(Decoder *d, AVFrame *frame, AVSubtitle *sub) {
|
||||
if (ret >= 0) {
|
||||
AVRational tb = (AVRational){1, frame->sample_rate};
|
||||
if (frame->pts != AV_NOPTS_VALUE)
|
||||
frame->pts = av_rescale_q(frame->pts, av_codec_get_pkt_timebase(d->avctx), tb);
|
||||
frame->pts = av_rescale_q(frame->pts, d->avctx->pkt_timebase, tb);
|
||||
else if (d->next_pts != AV_NOPTS_VALUE)
|
||||
frame->pts = av_rescale_q(d->next_pts, d->next_pts_tb, tb);
|
||||
if (frame->pts != AV_NOPTS_VALUE) {
|
||||
@@ -1191,7 +1193,7 @@ static void stream_component_close(VideoState *is, int stream_index)
|
||||
switch (codecpar->codec_type) {
|
||||
case AVMEDIA_TYPE_AUDIO:
|
||||
decoder_abort(&is->auddec, &is->sampq);
|
||||
SDL_CloseAudio();
|
||||
SDL_CloseAudioDevice(audio_dev);
|
||||
decoder_destroy(&is->auddec);
|
||||
swr_free(&is->swr_ctx);
|
||||
av_freep(&is->audio_buf1);
|
||||
@@ -1282,7 +1284,6 @@ static void do_exit(VideoState *is)
|
||||
SDL_DestroyRenderer(renderer);
|
||||
if (window)
|
||||
SDL_DestroyWindow(window);
|
||||
av_lockmgr_register(NULL);
|
||||
uninit_opts();
|
||||
#if CONFIG_AVFILTER
|
||||
av_freep(&vfilters_list);
|
||||
@@ -1320,38 +1321,15 @@ static int video_open(VideoState *is)
|
||||
h = default_height;
|
||||
}
|
||||
|
||||
if (!window) {
|
||||
int flags = SDL_WINDOW_SHOWN;
|
||||
if (!window_title)
|
||||
window_title = input_filename;
|
||||
if (is_full_screen)
|
||||
flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
|
||||
if (borderless)
|
||||
flags |= SDL_WINDOW_BORDERLESS;
|
||||
else
|
||||
flags |= SDL_WINDOW_RESIZABLE;
|
||||
window = SDL_CreateWindow(window_title, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, w, h, flags);
|
||||
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");
|
||||
if (window) {
|
||||
SDL_RendererInfo info;
|
||||
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
|
||||
if (!renderer) {
|
||||
av_log(NULL, AV_LOG_WARNING, "Failed to initialize a hardware accelerated renderer: %s\n", SDL_GetError());
|
||||
renderer = SDL_CreateRenderer(window, -1, 0);
|
||||
}
|
||||
if (renderer) {
|
||||
if (!SDL_GetRendererInfo(renderer, &info))
|
||||
av_log(NULL, AV_LOG_VERBOSE, "Initialized %s renderer.\n", info.name);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
SDL_SetWindowSize(window, w, h);
|
||||
}
|
||||
SDL_SetWindowTitle(window, window_title);
|
||||
|
||||
if (!window || !renderer) {
|
||||
av_log(NULL, AV_LOG_FATAL, "SDL: could not set video mode - exiting\n");
|
||||
do_exit(is);
|
||||
}
|
||||
SDL_SetWindowSize(window, w, h);
|
||||
SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
|
||||
if (is_full_screen)
|
||||
SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP);
|
||||
SDL_ShowWindow(window);
|
||||
|
||||
is->width = w;
|
||||
is->height = h;
|
||||
@@ -1362,7 +1340,7 @@ static int video_open(VideoState *is)
|
||||
/* display the current picture, if any */
|
||||
static void video_display(VideoState *is)
|
||||
{
|
||||
if (!window)
|
||||
if (!is->width)
|
||||
video_open(is);
|
||||
|
||||
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
|
||||
@@ -1850,10 +1828,18 @@ static int configure_video_filters(AVFilterGraph *graph, VideoState *is, const c
|
||||
AVCodecParameters *codecpar = is->video_st->codecpar;
|
||||
AVRational fr = av_guess_frame_rate(is->ic, is->video_st, NULL);
|
||||
AVDictionaryEntry *e = NULL;
|
||||
int i;
|
||||
int nb_pix_fmts = 0;
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < FF_ARRAY_ELEMS(pix_fmts); i++)
|
||||
pix_fmts[i] = sdl_texture_format_map[i].format;
|
||||
for (i = 0; i < renderer_info.num_texture_formats; i++) {
|
||||
for (j = 0; j < FF_ARRAY_ELEMS(sdl_texture_format_map) - 1; j++) {
|
||||
if (renderer_info.texture_formats[i] == sdl_texture_format_map[j].texture_fmt) {
|
||||
pix_fmts[nb_pix_fmts++] = sdl_texture_format_map[j].format;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
pix_fmts[nb_pix_fmts] = AV_PIX_FMT_NONE;
|
||||
|
||||
while ((e = av_dict_get(sws_dict, "", e, AV_DICT_IGNORE_SUFFIX))) {
|
||||
if (!strcmp(e->key, "sws_flags")) {
|
||||
@@ -2465,7 +2451,7 @@ static void sdl_audio_callback(void *opaque, Uint8 *stream, int len)
|
||||
else {
|
||||
memset(stream, 0, len1);
|
||||
if (!is->muted && is->audio_buf)
|
||||
SDL_MixAudio(stream, (uint8_t *)is->audio_buf + is->audio_buf_index, len1, is->audio_volume);
|
||||
SDL_MixAudioFormat(stream, (uint8_t *)is->audio_buf + is->audio_buf_index, AUDIO_S16SYS, len1, is->audio_volume);
|
||||
}
|
||||
len -= len1;
|
||||
stream += len1;
|
||||
@@ -2510,7 +2496,7 @@ static int audio_open(void *opaque, int64_t wanted_channel_layout, int wanted_nb
|
||||
wanted_spec.samples = FFMAX(SDL_AUDIO_MIN_BUFFER_SIZE, 2 << av_log2(wanted_spec.freq / SDL_AUDIO_MAX_CALLBACKS_PER_SEC));
|
||||
wanted_spec.callback = sdl_audio_callback;
|
||||
wanted_spec.userdata = opaque;
|
||||
while (SDL_OpenAudio(&wanted_spec, &spec) < 0) {
|
||||
while (!(audio_dev = SDL_OpenAudioDevice(NULL, 0, &wanted_spec, &spec, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE | SDL_AUDIO_ALLOW_CHANNELS_CHANGE))) {
|
||||
av_log(NULL, AV_LOG_WARNING, "SDL_OpenAudio (%d channels, %d Hz): %s\n",
|
||||
wanted_spec.channels, wanted_spec.freq, SDL_GetError());
|
||||
wanted_spec.channels = next_nb_channels[FFMIN(7, wanted_spec.channels)];
|
||||
@@ -2576,7 +2562,7 @@ static int stream_component_open(VideoState *is, int stream_index)
|
||||
ret = avcodec_parameters_to_context(avctx, ic->streams[stream_index]->codecpar);
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
av_codec_set_pkt_timebase(avctx, ic->streams[stream_index]->time_base);
|
||||
avctx->pkt_timebase = ic->streams[stream_index]->time_base;
|
||||
|
||||
codec = avcodec_find_decoder(avctx->codec_id);
|
||||
|
||||
@@ -2597,22 +2583,15 @@ static int stream_component_open(VideoState *is, int stream_index)
|
||||
}
|
||||
|
||||
avctx->codec_id = codec->id;
|
||||
if(stream_lowres > av_codec_get_max_lowres(codec)){
|
||||
if (stream_lowres > codec->max_lowres) {
|
||||
av_log(avctx, AV_LOG_WARNING, "The maximum value for lowres supported by the decoder is %d\n",
|
||||
av_codec_get_max_lowres(codec));
|
||||
stream_lowres = av_codec_get_max_lowres(codec);
|
||||
codec->max_lowres);
|
||||
stream_lowres = codec->max_lowres;
|
||||
}
|
||||
av_codec_set_lowres(avctx, stream_lowres);
|
||||
avctx->lowres = stream_lowres;
|
||||
|
||||
#if FF_API_EMU_EDGE
|
||||
if(stream_lowres) avctx->flags |= CODEC_FLAG_EMU_EDGE;
|
||||
#endif
|
||||
if (fast)
|
||||
avctx->flags2 |= AV_CODEC_FLAG2_FAST;
|
||||
#if FF_API_EMU_EDGE
|
||||
if(codec->capabilities & AV_CODEC_CAP_DR1)
|
||||
avctx->flags |= CODEC_FLAG_EMU_EDGE;
|
||||
#endif
|
||||
|
||||
opts = filter_codec_opts(codec_opts, avctx->codec_id, ic, ic->streams[stream_index], codec);
|
||||
if (!av_dict_get(opts, "threads", NULL, 0))
|
||||
@@ -2680,7 +2659,7 @@ static int stream_component_open(VideoState *is, int stream_index)
|
||||
}
|
||||
if ((ret = decoder_start(&is->auddec, audio_thread, is)) < 0)
|
||||
goto out;
|
||||
SDL_PauseAudio(0);
|
||||
SDL_PauseAudioDevice(audio_dev, 0);
|
||||
break;
|
||||
case AVMEDIA_TYPE_VIDEO:
|
||||
is->video_stream = stream_index;
|
||||
@@ -3661,27 +3640,6 @@ void show_help_default(const char *opt, const char *arg)
|
||||
);
|
||||
}
|
||||
|
||||
static int lockmgr(void **mtx, enum AVLockOp op)
|
||||
{
|
||||
switch(op) {
|
||||
case AV_LOCK_CREATE:
|
||||
*mtx = SDL_CreateMutex();
|
||||
if(!*mtx) {
|
||||
av_log(NULL, AV_LOG_FATAL, "SDL_CreateMutex(): %s\n", SDL_GetError());
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
case AV_LOCK_OBTAIN:
|
||||
return !!SDL_LockMutex(*mtx);
|
||||
case AV_LOCK_RELEASE:
|
||||
return !!SDL_UnlockMutex(*mtx);
|
||||
case AV_LOCK_DESTROY:
|
||||
SDL_DestroyMutex(*mtx);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Called from the main */
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
@@ -3743,14 +3701,34 @@ int main(int argc, char **argv)
|
||||
SDL_EventState(SDL_SYSWMEVENT, SDL_IGNORE);
|
||||
SDL_EventState(SDL_USEREVENT, SDL_IGNORE);
|
||||
|
||||
if (av_lockmgr_register(lockmgr)) {
|
||||
av_log(NULL, AV_LOG_FATAL, "Could not initialize lock manager!\n");
|
||||
do_exit(NULL);
|
||||
}
|
||||
|
||||
av_init_packet(&flush_pkt);
|
||||
flush_pkt.data = (uint8_t *)&flush_pkt;
|
||||
|
||||
if (!display_disable) {
|
||||
int flags = SDL_WINDOW_HIDDEN;
|
||||
if (borderless)
|
||||
flags |= SDL_WINDOW_BORDERLESS;
|
||||
else
|
||||
flags |= SDL_WINDOW_RESIZABLE;
|
||||
window = SDL_CreateWindow(program_name, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, default_width, default_height, flags);
|
||||
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");
|
||||
if (window) {
|
||||
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
|
||||
if (!renderer) {
|
||||
av_log(NULL, AV_LOG_WARNING, "Failed to initialize a hardware accelerated renderer: %s\n", SDL_GetError());
|
||||
renderer = SDL_CreateRenderer(window, -1, 0);
|
||||
}
|
||||
if (renderer) {
|
||||
if (!SDL_GetRendererInfo(renderer, &renderer_info))
|
||||
av_log(NULL, AV_LOG_VERBOSE, "Initialized %s renderer.\n", renderer_info.name);
|
||||
}
|
||||
}
|
||||
if (!window || !renderer || !renderer_info.num_texture_formats) {
|
||||
av_log(NULL, AV_LOG_FATAL, "Failed to create window or renderer: %s", SDL_GetError());
|
||||
do_exit(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
is = stream_open(input_filename, file_iformat);
|
||||
if (!is) {
|
||||
av_log(NULL, AV_LOG_FATAL, "Failed to initialize VideoState!\n");
|
||||
|
||||
+2
-4
@@ -2792,7 +2792,7 @@ static int show_format(WriterContext *w, InputFile *ifile)
|
||||
else print_str_opt("size", "N/A");
|
||||
if (fmt_ctx->bit_rate > 0) print_val ("bit_rate", fmt_ctx->bit_rate, unit_bit_per_second_str);
|
||||
else print_str_opt("bit_rate", "N/A");
|
||||
print_int("probe_score", av_format_get_probe_score(fmt_ctx));
|
||||
print_int("probe_score", fmt_ctx->probe_score);
|
||||
if (do_show_format_tags)
|
||||
ret = show_tags(w, fmt_ctx->metadata, SECTION_ID_FORMAT_TAGS);
|
||||
|
||||
@@ -2828,8 +2828,6 @@ static int open_input_file(InputFile *ifile, const char *filename)
|
||||
exit_program(1);
|
||||
}
|
||||
|
||||
fmt_ctx->flags |= AVFMT_FLAG_KEEP_SIDE_DATA;
|
||||
|
||||
if (!av_dict_get(format_opts, "scan_all_pmts", NULL, AV_DICT_MATCH_CASE)) {
|
||||
av_dict_set(&format_opts, "scan_all_pmts", "1", AV_DICT_DONT_OVERWRITE);
|
||||
scan_all_pmts_set = 1;
|
||||
@@ -2912,7 +2910,7 @@ static int open_input_file(InputFile *ifile, const char *filename)
|
||||
av_dict_set(&codec_opts, "threads", "1", 0);
|
||||
}
|
||||
|
||||
av_codec_set_pkt_timebase(ist->dec_ctx, stream->time_base);
|
||||
ist->dec_ctx->pkt_timebase = stream->time_base;
|
||||
ist->dec_ctx->framerate = stream->avg_frame_rate;
|
||||
|
||||
if (avcodec_open2(ist->dec_ctx, codec, &opts) < 0) {
|
||||
|
||||
-4026
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,155 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2001, 2002 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 FFTOOLS_FFSERVER_CONFIG_H
|
||||
#define FFTOOLS_FFSERVER_CONFIG_H
|
||||
|
||||
#define FFM_PACKET_SIZE 4096
|
||||
|
||||
#include "libavutil/dict.h"
|
||||
#include "libavformat/avformat.h"
|
||||
#include "libavformat/network.h"
|
||||
|
||||
#define FFSERVER_MAX_STREAMS 20
|
||||
|
||||
/* each generated stream is described here */
|
||||
enum FFServerStreamType {
|
||||
STREAM_TYPE_LIVE,
|
||||
STREAM_TYPE_STATUS,
|
||||
STREAM_TYPE_REDIRECT,
|
||||
};
|
||||
|
||||
enum FFServerIPAddressAction {
|
||||
IP_ALLOW = 1,
|
||||
IP_DENY,
|
||||
};
|
||||
|
||||
typedef struct FFServerIPAddressACL {
|
||||
struct FFServerIPAddressACL *next;
|
||||
enum FFServerIPAddressAction action;
|
||||
/* These are in host order */
|
||||
struct in_addr first;
|
||||
struct in_addr last;
|
||||
} FFServerIPAddressACL;
|
||||
|
||||
/**
|
||||
* This holds the stream parameters for an AVStream, it cannot be a AVStream
|
||||
* because AVStreams cannot be instanciated without a AVFormatContext, especially
|
||||
* not outside libavformat.
|
||||
*
|
||||
* The fields of this struct have the same semantics as the fields of an AVStream.
|
||||
*/
|
||||
typedef struct LayeredAVStream {
|
||||
int index;
|
||||
int id;
|
||||
AVCodecParameters *codecpar;
|
||||
AVCodecContext *codec;
|
||||
AVRational time_base;
|
||||
int pts_wrap_bits;
|
||||
AVRational sample_aspect_ratio;
|
||||
char *recommended_encoder_configuration;
|
||||
} LayeredAVStream;
|
||||
|
||||
/* description of each stream of the ffserver.conf file */
|
||||
typedef struct FFServerStream {
|
||||
enum FFServerStreamType stream_type;
|
||||
char filename[1024]; /* stream filename */
|
||||
struct FFServerStream *feed; /* feed we are using (can be null if coming from file) */
|
||||
AVDictionary *in_opts; /* input parameters */
|
||||
AVDictionary *metadata; /* metadata to set on the stream */
|
||||
AVInputFormat *ifmt; /* if non NULL, force input format */
|
||||
AVOutputFormat *fmt;
|
||||
FFServerIPAddressACL *acl;
|
||||
char dynamic_acl[1024];
|
||||
int nb_streams;
|
||||
int prebuffer; /* Number of milliseconds early to start */
|
||||
int64_t max_time; /* Number of milliseconds to run */
|
||||
int send_on_key;
|
||||
LayeredAVStream *streams[FFSERVER_MAX_STREAMS];
|
||||
int feed_streams[FFSERVER_MAX_STREAMS]; /* index of streams in the feed */
|
||||
char feed_filename[1024]; /* file name of the feed storage, or
|
||||
input file name for a stream */
|
||||
pid_t pid; /* Of ffmpeg process */
|
||||
time_t pid_start; /* Of ffmpeg process */
|
||||
char **child_argv;
|
||||
struct FFServerStream *next;
|
||||
unsigned bandwidth; /* bandwidth, in kbits/s */
|
||||
/* RTSP options */
|
||||
char *rtsp_option;
|
||||
/* multicast specific */
|
||||
int is_multicast;
|
||||
struct in_addr multicast_ip;
|
||||
int multicast_port; /* first port used for multicast */
|
||||
int multicast_ttl;
|
||||
int loop; /* if true, send the stream in loops (only meaningful if file) */
|
||||
char single_frame; /* only single frame */
|
||||
|
||||
/* feed specific */
|
||||
int feed_opened; /* true if someone is writing to the feed */
|
||||
int is_feed; /* true if it is a feed */
|
||||
int readonly; /* True if writing is prohibited to the file */
|
||||
int truncate; /* True if feeder connection truncate the feed file */
|
||||
int conns_served;
|
||||
int64_t bytes_served;
|
||||
int64_t feed_max_size; /* maximum storage size, zero means unlimited */
|
||||
int64_t feed_write_index; /* current write position in feed (it wraps around) */
|
||||
int64_t feed_size; /* current size of feed */
|
||||
struct FFServerStream *next_feed;
|
||||
} FFServerStream;
|
||||
|
||||
typedef struct FFServerConfig {
|
||||
char *filename;
|
||||
FFServerStream *first_feed; /* contains only feeds */
|
||||
FFServerStream *first_stream; /* contains all streams, including feeds */
|
||||
unsigned int nb_max_http_connections;
|
||||
unsigned int nb_max_connections;
|
||||
uint64_t max_bandwidth;
|
||||
int debug;
|
||||
int bitexact;
|
||||
char logfilename[1024];
|
||||
struct sockaddr_in http_addr;
|
||||
struct sockaddr_in rtsp_addr;
|
||||
int errors;
|
||||
int warnings;
|
||||
int use_defaults;
|
||||
// Following variables MUST NOT be used outside configuration parsing code.
|
||||
enum AVCodecID guessed_audio_codec_id;
|
||||
enum AVCodecID guessed_video_codec_id;
|
||||
AVDictionary *video_opts; /* AVOptions for video encoder */
|
||||
AVDictionary *audio_opts; /* AVOptions for audio encoder */
|
||||
AVCodecContext *dummy_actx; /* Used internally to test audio AVOptions. */
|
||||
AVCodecContext *dummy_vctx; /* Used internally to test video AVOptions. */
|
||||
int no_audio;
|
||||
int no_video;
|
||||
int line_num;
|
||||
int stream_use_defaults;
|
||||
} FFServerConfig;
|
||||
|
||||
void ffserver_get_arg(char *buf, int buf_size, const char **pp);
|
||||
|
||||
void ffserver_parse_acl_row(FFServerStream *stream, FFServerStream* feed,
|
||||
FFServerIPAddressACL *ext_acl,
|
||||
const char *p, const char *filename, int line_num);
|
||||
|
||||
int ffserver_parse_ffconfig(const char *filename, FFServerConfig *config);
|
||||
|
||||
void ffserver_free_child_args(void *argsp);
|
||||
|
||||
#endif /* FFTOOLS_FFSERVER_CONFIG_H */
|
||||
@@ -0,0 +1,4 @@
|
||||
/*_tablegen
|
||||
/*_tables.c
|
||||
/*_tables.h
|
||||
/bsf_list.c
|
||||
+51
-29
@@ -1,7 +1,9 @@
|
||||
NAME = avcodec
|
||||
DESC = FFmpeg codec library
|
||||
|
||||
HEADERS = avcodec.h \
|
||||
HEADERS = ac3_parser.h \
|
||||
adts_parser.h \
|
||||
avcodec.h \
|
||||
avdct.h \
|
||||
avfft.h \
|
||||
d3d11va.h \
|
||||
@@ -12,15 +14,15 @@ HEADERS = avcodec.h \
|
||||
mediacodec.h \
|
||||
qsv.h \
|
||||
vaapi.h \
|
||||
vda.h \
|
||||
vdpau.h \
|
||||
version.h \
|
||||
videotoolbox.h \
|
||||
vorbis_parser.h \
|
||||
xvmc.h \
|
||||
|
||||
OBJS = allcodecs.o \
|
||||
audioconvert.o \
|
||||
OBJS = ac3_parser.o \
|
||||
adts_parser.o \
|
||||
allcodecs.o \
|
||||
avdct.o \
|
||||
avpacket.o \
|
||||
avpicture.o \
|
||||
@@ -45,8 +47,6 @@ OBJS = allcodecs.o \
|
||||
profiles.o \
|
||||
qsv_api.o \
|
||||
raw.o \
|
||||
resample.o \
|
||||
resample2.o \
|
||||
utils.o \
|
||||
vorbis_parser.o \
|
||||
xiph.o \
|
||||
@@ -54,11 +54,17 @@ OBJS = allcodecs.o \
|
||||
# subsystems
|
||||
OBJS-$(CONFIG_AANDCTTABLES) += aandcttab.o
|
||||
OBJS-$(CONFIG_AC3DSP) += ac3dsp.o ac3.o ac3tab.o
|
||||
OBJS-$(CONFIG_ADTS_HEADER) += adts_header.o mpeg4audio.o
|
||||
OBJS-$(CONFIG_AMF) += amfenc.o
|
||||
OBJS-$(CONFIG_AUDIO_FRAME_QUEUE) += audio_frame_queue.o
|
||||
OBJS-$(CONFIG_AUDIODSP) += audiodsp.o
|
||||
OBJS-$(CONFIG_BLOCKDSP) += blockdsp.o
|
||||
OBJS-$(CONFIG_BSWAPDSP) += bswapdsp.o
|
||||
OBJS-$(CONFIG_CABAC) += cabac.o
|
||||
OBJS-$(CONFIG_CBS) += cbs.o
|
||||
OBJS-$(CONFIG_CBS_H264) += cbs_h2645.o h2645_parse.o
|
||||
OBJS-$(CONFIG_CBS_H265) += cbs_h2645.o h2645_parse.o
|
||||
OBJS-$(CONFIG_CBS_MPEG2) += cbs_mpeg2.o
|
||||
OBJS-$(CONFIG_CRYSTALHD) += crystalhd.o
|
||||
OBJS-$(CONFIG_DCT) += dct.o dct32_fixed.o dct32_float.o
|
||||
OBJS-$(CONFIG_ERROR_RESILIENCE) += error_resilience.o
|
||||
@@ -91,7 +97,6 @@ OBJS-$(CONFIG_INTRAX8) += intrax8.o intrax8dsp.o msmpeg4data.o
|
||||
OBJS-$(CONFIG_IVIDSP) += ivi_dsp.o
|
||||
OBJS-$(CONFIG_JNI) += ffjni.o jni.o
|
||||
OBJS-$(CONFIG_JPEGTABLES) += jpegtables.o
|
||||
OBJS-$(CONFIG_LIBXVID) += libxvid_rc.o
|
||||
OBJS-$(CONFIG_LLAUDDSP) += lossless_audiodsp.o
|
||||
OBJS-$(CONFIG_LLVIDDSP) += lossless_videodsp.o
|
||||
OBJS-$(CONFIG_LLVIDENCDSP) += lossless_videoencdsp.o
|
||||
@@ -146,10 +151,10 @@ OBJS-$(CONFIG_ZERO12V_DECODER) += 012v.o
|
||||
OBJS-$(CONFIG_A64MULTI_ENCODER) += a64multienc.o elbg.o
|
||||
OBJS-$(CONFIG_A64MULTI5_ENCODER) += a64multienc.o elbg.o
|
||||
OBJS-$(CONFIG_AAC_DECODER) += aacdec.o aactab.o aacsbr.o aacps_float.o \
|
||||
aacadtsdec.o mpeg4audio.o kbdwin.o \
|
||||
mpeg4audio.o kbdwin.o \
|
||||
sbrdsp.o aacpsdsp_float.o cbrt_data.o
|
||||
OBJS-$(CONFIG_AAC_FIXED_DECODER) += aacdec_fixed.o aactab.o aacsbr_fixed.o aacps_fixed.o \
|
||||
aacadtsdec.o mpeg4audio.o kbdwin.o \
|
||||
mpeg4audio.o kbdwin.o \
|
||||
sbrdsp_fixed.o aacpsdsp_fixed.o cbrt_data_fixed.o
|
||||
OBJS-$(CONFIG_AAC_ENCODER) += aacenc.o aaccoder.o aacenctab.o \
|
||||
aacpsy.o aactab.o \
|
||||
@@ -183,6 +188,8 @@ OBJS-$(CONFIG_AMV_ENCODER) += mjpegenc.o mjpegenc_common.o \
|
||||
OBJS-$(CONFIG_ANM_DECODER) += anm.o
|
||||
OBJS-$(CONFIG_ANSI_DECODER) += ansi.o cga_data.o
|
||||
OBJS-$(CONFIG_APE_DECODER) += apedec.o
|
||||
OBJS-$(CONFIG_APTX_DECODER) += aptx.o
|
||||
OBJS-$(CONFIG_APTX_ENCODER) += aptx.o
|
||||
OBJS-$(CONFIG_APNG_DECODER) += png.o pngdec.o pngdsp.o
|
||||
OBJS-$(CONFIG_APNG_ENCODER) += png.o pngenc.o
|
||||
OBJS-$(CONFIG_SSA_DECODER) += assdec.o ass.o
|
||||
@@ -331,18 +338,18 @@ OBJS-$(CONFIG_H264_DECODER) += h264dec.o h264_cabac.o h264_cavlc.o \
|
||||
h264_mb.o h264_picture.o \
|
||||
h264_refs.o h264_sei.o \
|
||||
h264_slice.o h264data.o
|
||||
OBJS-$(CONFIG_H264_CUVID_DECODER) += cuvid.o
|
||||
OBJS-$(CONFIG_H264_AMF_ENCODER) += amfenc_h264.o
|
||||
OBJS-$(CONFIG_H264_CUVID_DECODER) += cuviddec.o
|
||||
OBJS-$(CONFIG_H264_MEDIACODEC_DECODER) += mediacodecdec.o
|
||||
OBJS-$(CONFIG_H264_MMAL_DECODER) += mmaldec.o
|
||||
OBJS-$(CONFIG_H264_NVENC_ENCODER) += nvenc_h264.o
|
||||
OBJS-$(CONFIG_NVENC_ENCODER) += nvenc_h264.o
|
||||
OBJS-$(CONFIG_NVENC_H264_ENCODER) += nvenc_h264.o
|
||||
OBJS-$(CONFIG_H264_VDA_DECODER) += vda_h264_dec.o
|
||||
OBJS-$(CONFIG_H264_OMX_ENCODER) += omx.o
|
||||
OBJS-$(CONFIG_H264_QSV_DECODER) += qsvdec_h2645.o
|
||||
OBJS-$(CONFIG_H264_QSV_ENCODER) += qsvenc_h264.o
|
||||
OBJS-$(CONFIG_H264_RKMPP_DECODER) += rkmppdec.o
|
||||
OBJS-$(CONFIG_H264_VAAPI_ENCODER) += vaapi_encode_h264.o vaapi_encode_h26x.o
|
||||
OBJS-$(CONFIG_H264_VAAPI_ENCODER) += vaapi_encode_h264.o
|
||||
OBJS-$(CONFIG_H264_VIDEOTOOLBOX_ENCODER) += videotoolboxenc.o
|
||||
OBJS-$(CONFIG_H264_V4L2M2M_DECODER) += v4l2_m2m_dec.o
|
||||
OBJS-$(CONFIG_H264_V4L2M2M_ENCODER) += v4l2_m2m_enc.o
|
||||
@@ -351,7 +358,8 @@ OBJS-$(CONFIG_HAP_ENCODER) += hapenc.o hap.o
|
||||
OBJS-$(CONFIG_HEVC_DECODER) += hevcdec.o hevc_mvs.o \
|
||||
hevc_cabac.o hevc_refs.o hevcpred.o \
|
||||
hevcdsp.o hevc_filter.o hevc_data.o
|
||||
OBJS-$(CONFIG_HEVC_CUVID_DECODER) += cuvid.o
|
||||
OBJS-$(CONFIG_HEVC_AMF_ENCODER) += amfenc_hevc.o
|
||||
OBJS-$(CONFIG_HEVC_CUVID_DECODER) += cuviddec.o
|
||||
OBJS-$(CONFIG_HEVC_MEDIACODEC_DECODER) += mediacodecdec.o
|
||||
OBJS-$(CONFIG_HEVC_NVENC_ENCODER) += nvenc_hevc.o
|
||||
OBJS-$(CONFIG_NVENC_HEVC_ENCODER) += nvenc_hevc.o
|
||||
@@ -359,7 +367,7 @@ OBJS-$(CONFIG_HEVC_QSV_DECODER) += qsvdec_h2645.o
|
||||
OBJS-$(CONFIG_HEVC_QSV_ENCODER) += qsvenc_hevc.o hevc_ps_enc.o \
|
||||
hevc_data.o
|
||||
OBJS-$(CONFIG_HEVC_RKMPP_DECODER) += rkmppdec.o
|
||||
OBJS-$(CONFIG_HEVC_VAAPI_ENCODER) += vaapi_encode_h265.o vaapi_encode_h26x.o
|
||||
OBJS-$(CONFIG_HEVC_VAAPI_ENCODER) += vaapi_encode_h265.o
|
||||
OBJS-$(CONFIG_HEVC_V4L2M2M_DECODER) += v4l2_m2m_dec.o
|
||||
OBJS-$(CONFIG_HEVC_V4L2M2M_ENCODER) += v4l2_m2m_enc.o
|
||||
OBJS-$(CONFIG_HNM4_VIDEO_DECODER) += hnm4video.o
|
||||
@@ -396,6 +404,7 @@ OBJS-$(CONFIG_M101_DECODER) += m101.o
|
||||
OBJS-$(CONFIG_MACE3_DECODER) += mace.o
|
||||
OBJS-$(CONFIG_MACE6_DECODER) += mace.o
|
||||
OBJS-$(CONFIG_MAGICYUV_DECODER) += magicyuv.o
|
||||
OBJS-$(CONFIG_MAGICYUV_ENCODER) += magicyuvenc.o
|
||||
OBJS-$(CONFIG_MDEC_DECODER) += mdec.o mpeg12.o mpeg12data.o
|
||||
OBJS-$(CONFIG_METASOUND_DECODER) += metasound.o metasound_data.o \
|
||||
twinvq.o
|
||||
@@ -405,6 +414,7 @@ OBJS-$(CONFIG_MJPEG_DECODER) += mjpegdec.o
|
||||
OBJS-$(CONFIG_MJPEG_ENCODER) += mjpegenc.o mjpegenc_common.o \
|
||||
mjpegenc_huffman.o
|
||||
OBJS-$(CONFIG_MJPEGB_DECODER) += mjpegbdec.o
|
||||
OBJS-$(CONFIG_MJPEG_QSV_ENCODER) += qsvenc_jpeg.o
|
||||
OBJS-$(CONFIG_MJPEG_VAAPI_ENCODER) += vaapi_encode_mjpeg.o
|
||||
OBJS-$(CONFIG_MLP_DECODER) += mlpdec.o mlpdsp.o
|
||||
OBJS-$(CONFIG_MLP_ENCODER) += mlpenc.o mlp.o
|
||||
@@ -616,7 +626,7 @@ OBJS-$(CONFIG_VC1_DECODER) += vc1dec.o vc1_block.o vc1_loopfilter.o
|
||||
vc1_mc.o vc1_pred.o vc1.o vc1data.o \
|
||||
msmpeg4dec.o msmpeg4.o msmpeg4data.o \
|
||||
wmv2dsp.o wmv2data.o
|
||||
OBJS-$(CONFIG_VC1_CUVID_DECODER) += cuvid.o
|
||||
OBJS-$(CONFIG_VC1_CUVID_DECODER) += cuviddec.o
|
||||
OBJS-$(CONFIG_VC1_MMAL_DECODER) += mmaldec.o
|
||||
OBJS-$(CONFIG_VC1_QSV_DECODER) += qsvdec_other.o
|
||||
OBJS-$(CONFIG_VC1_V4L2M2M_DECODER) += v4l2_m2m_dec.o
|
||||
@@ -635,7 +645,7 @@ OBJS-$(CONFIG_VP6_DECODER) += vp6.o vp56.o vp56data.o \
|
||||
vp6dsp.o vp56rac.o
|
||||
OBJS-$(CONFIG_VP7_DECODER) += vp8.o vp56rac.o
|
||||
OBJS-$(CONFIG_VP8_DECODER) += vp8.o vp56rac.o
|
||||
OBJS-$(CONFIG_VP8_CUVID_DECODER) += cuvid.o
|
||||
OBJS-$(CONFIG_VP8_CUVID_DECODER) += cuviddec.o
|
||||
OBJS-$(CONFIG_VP8_MEDIACODEC_DECODER) += mediacodecdec.o
|
||||
OBJS-$(CONFIG_VP8_QSV_DECODER) += qsvdec_other.o
|
||||
OBJS-$(CONFIG_VP8_RKMPP_DECODER) += rkmppdec.o
|
||||
@@ -645,7 +655,7 @@ OBJS-$(CONFIG_VP8_V4L2M2M_ENCODER) += v4l2_m2m_enc.o
|
||||
OBJS-$(CONFIG_VP9_DECODER) += vp9.o vp9data.o vp9dsp.o vp9lpf.o vp9recon.o \
|
||||
vp9block.o vp9prob.o vp9mvs.o vp56rac.o \
|
||||
vp9dsp_8bpp.o vp9dsp_10bpp.o vp9dsp_12bpp.o
|
||||
OBJS-$(CONFIG_VP9_CUVID_DECODER) += cuvid.o
|
||||
OBJS-$(CONFIG_VP9_CUVID_DECODER) += cuviddec.o
|
||||
OBJS-$(CONFIG_VP9_MEDIACODEC_DECODER) += mediacodecdec.o
|
||||
OBJS-$(CONFIG_VP9_RKMPP_DECODER) += rkmppdec.o
|
||||
OBJS-$(CONFIG_VP9_VAAPI_ENCODER) += vaapi_encode_vp9.o
|
||||
@@ -822,8 +832,8 @@ OBJS-$(CONFIG_ADPCM_YAMAHA_ENCODER) += adpcmenc.o adpcm_data.o
|
||||
# hardware accelerators
|
||||
OBJS-$(CONFIG_D3D11VA) += dxva2.o
|
||||
OBJS-$(CONFIG_DXVA2) += dxva2.o
|
||||
OBJS-$(CONFIG_NVDEC) += nvdec.o
|
||||
OBJS-$(CONFIG_VAAPI) += vaapi_decode.o
|
||||
OBJS-$(CONFIG_VDA) += vda.o videotoolbox.o
|
||||
OBJS-$(CONFIG_VIDEOTOOLBOX) += videotoolbox.o
|
||||
OBJS-$(CONFIG_VDPAU) += vdpau.o
|
||||
|
||||
@@ -831,36 +841,44 @@ OBJS-$(CONFIG_H263_VAAPI_HWACCEL) += vaapi_mpeg4.o
|
||||
OBJS-$(CONFIG_H263_VIDEOTOOLBOX_HWACCEL) += videotoolbox.o
|
||||
OBJS-$(CONFIG_H264_D3D11VA_HWACCEL) += dxva2_h264.o
|
||||
OBJS-$(CONFIG_H264_DXVA2_HWACCEL) += dxva2_h264.o
|
||||
OBJS-$(CONFIG_H264_NVDEC_HWACCEL) += nvdec_h264.o
|
||||
OBJS-$(CONFIG_H264_QSV_HWACCEL) += qsvdec_h2645.o
|
||||
OBJS-$(CONFIG_H264_VAAPI_HWACCEL) += vaapi_h264.o
|
||||
OBJS-$(CONFIG_H264_VDA_HWACCEL) += vda_h264.o
|
||||
OBJS-$(CONFIG_H264_VDPAU_HWACCEL) += vdpau_h264.o
|
||||
OBJS-$(CONFIG_H264_VIDEOTOOLBOX_HWACCEL) += videotoolbox.o
|
||||
OBJS-$(CONFIG_HEVC_D3D11VA_HWACCEL) += dxva2_hevc.o
|
||||
OBJS-$(CONFIG_HEVC_DXVA2_HWACCEL) += dxva2_hevc.o
|
||||
OBJS-$(CONFIG_HEVC_NVDEC_HWACCEL) += nvdec_hevc.o
|
||||
OBJS-$(CONFIG_HEVC_QSV_HWACCEL) += qsvdec_h2645.o
|
||||
OBJS-$(CONFIG_HEVC_VAAPI_HWACCEL) += vaapi_hevc.o
|
||||
OBJS-$(CONFIG_HEVC_VDPAU_HWACCEL) += vdpau_hevc.o
|
||||
OBJS-$(CONFIG_MPEG1_NVDEC_HWACCEL) += nvdec_mpeg12.o
|
||||
OBJS-$(CONFIG_MPEG1_VDPAU_HWACCEL) += vdpau_mpeg12.o
|
||||
OBJS-$(CONFIG_MPEG1_VIDEOTOOLBOX_HWACCEL) += videotoolbox.o
|
||||
OBJS-$(CONFIG_MPEG1_XVMC_HWACCEL) += mpegvideo_xvmc.o
|
||||
OBJS-$(CONFIG_MPEG2_D3D11VA_HWACCEL) += dxva2_mpeg2.o
|
||||
OBJS-$(CONFIG_MPEG2_DXVA2_HWACCEL) += dxva2_mpeg2.o
|
||||
OBJS-$(CONFIG_MPEG2_NVDEC_HWACCEL) += nvdec_mpeg12.o
|
||||
OBJS-$(CONFIG_MPEG2_QSV_HWACCEL) += qsvdec_other.o
|
||||
OBJS-$(CONFIG_MPEG2_VAAPI_HWACCEL) += vaapi_mpeg2.o
|
||||
OBJS-$(CONFIG_MPEG2_VDPAU_HWACCEL) += vdpau_mpeg12.o
|
||||
OBJS-$(CONFIG_MPEG2_VIDEOTOOLBOX_HWACCEL) += videotoolbox.o
|
||||
OBJS-$(CONFIG_MPEG2_XVMC_HWACCEL) += mpegvideo_xvmc.o
|
||||
OBJS-$(CONFIG_MPEG4_NVDEC_HWACCEL) += nvdec_mpeg4.o
|
||||
OBJS-$(CONFIG_MPEG4_VAAPI_HWACCEL) += vaapi_mpeg4.o
|
||||
OBJS-$(CONFIG_MPEG4_VDPAU_HWACCEL) += vdpau_mpeg4.o
|
||||
OBJS-$(CONFIG_MPEG4_VIDEOTOOLBOX_HWACCEL) += videotoolbox.o
|
||||
OBJS-$(CONFIG_VC1_D3D11VA_HWACCEL) += dxva2_vc1.o
|
||||
OBJS-$(CONFIG_VC1_DXVA2_HWACCEL) += dxva2_vc1.o
|
||||
OBJS-$(CONFIG_VC1_NVDEC_HWACCEL) += nvdec_vc1.o
|
||||
OBJS-$(CONFIG_VC1_QSV_HWACCEL) += qsvdec_other.o
|
||||
OBJS-$(CONFIG_VC1_VAAPI_HWACCEL) += vaapi_vc1.o
|
||||
OBJS-$(CONFIG_VC1_VDPAU_HWACCEL) += vdpau_vc1.o
|
||||
OBJS-$(CONFIG_VP8_NVDEC_HWACCEL) += nvdec_vp8.o
|
||||
OBJS-$(CONFIG_VP8_VAAPI_HWACCEL) += vaapi_vp8.o
|
||||
OBJS-$(CONFIG_VP9_D3D11VA_HWACCEL) += dxva2_vp9.o
|
||||
OBJS-$(CONFIG_VP9_DXVA2_HWACCEL) += dxva2_vp9.o
|
||||
OBJS-$(CONFIG_VP9_NVDEC_HWACCEL) += nvdec_vp9.o
|
||||
OBJS-$(CONFIG_VP9_VAAPI_HWACCEL) += vaapi_vp9.o
|
||||
OBJS-$(CONFIG_VP8_QSV_HWACCEL) += qsvdec_other.o
|
||||
|
||||
@@ -880,7 +898,6 @@ OBJS-$(CONFIG_MXF_MUXER) += dnxhddata.o
|
||||
OBJS-$(CONFIG_NUT_MUXER) += mpegaudiodata.o
|
||||
OBJS-$(CONFIG_NUT_DEMUXER) += mpegaudiodata.o mpeg4audio.o
|
||||
OBJS-$(CONFIG_RTP_MUXER) += mpeg4audio.o
|
||||
OBJS-$(CONFIG_SPDIF_DEMUXER) += aacadtsdec.o mpeg4audio.o
|
||||
OBJS-$(CONFIG_SPDIF_MUXER) += dca.o
|
||||
OBJS-$(CONFIG_TAK_DEMUXER) += tak.o
|
||||
OBJS-$(CONFIG_WEBM_MUXER) += mpeg4audio.o
|
||||
@@ -951,15 +968,14 @@ OBJS-$(CONFIG_LIBX262_ENCODER) += libx264.o
|
||||
OBJS-$(CONFIG_LIBX264_ENCODER) += libx264.o
|
||||
OBJS-$(CONFIG_LIBX265_ENCODER) += libx265.o
|
||||
OBJS-$(CONFIG_LIBXAVS_ENCODER) += libxavs.o
|
||||
OBJS-$(CONFIG_LIBXVID_ENCODER) += libxvid.o
|
||||
OBJS-$(CONFIG_LIBXVID_ENCODER) += libxvid.o libxvid_rc.o
|
||||
OBJS-$(CONFIG_LIBZVBI_TELETEXT_DECODER) += libzvbi-teletextdec.o ass.o
|
||||
|
||||
# parsers
|
||||
OBJS-$(CONFIG_AAC_LATM_PARSER) += latm_parser.o
|
||||
OBJS-$(CONFIG_AAC_PARSER) += aac_parser.o aac_ac3_parser.o \
|
||||
aacadtsdec.o mpeg4audio.o
|
||||
OBJS-$(CONFIG_AC3_PARSER) += ac3_parser.o ac3tab.o \
|
||||
aac_ac3_parser.o
|
||||
mpeg4audio.o
|
||||
OBJS-$(CONFIG_AC3_PARSER) += ac3tab.o aac_ac3_parser.o
|
||||
OBJS-$(CONFIG_ADX_PARSER) += adx_parser.o adx.o
|
||||
OBJS-$(CONFIG_BMP_PARSER) += bmp_parser.o
|
||||
OBJS-$(CONFIG_CAVSVIDEO_PARSER) += cavs_parser.o
|
||||
@@ -989,7 +1005,8 @@ OBJS-$(CONFIG_PNG_PARSER) += png_parser.o
|
||||
OBJS-$(CONFIG_MPEGAUDIO_PARSER) += mpegaudio_parser.o
|
||||
OBJS-$(CONFIG_MPEGVIDEO_PARSER) += mpegvideo_parser.o \
|
||||
mpeg12.o mpeg12data.o
|
||||
OBJS-$(CONFIG_OPUS_PARSER) += opus_parser.o opus.o vorbis_data.o
|
||||
OBJS-$(CONFIG_OPUS_PARSER) += opus_parser.o opus.o opustab.o \
|
||||
opus_rc.o vorbis_data.o
|
||||
OBJS-$(CONFIG_PNG_PARSER) += png_parser.o
|
||||
OBJS-$(CONFIG_PNM_PARSER) += pnm_parser.o pnm.o
|
||||
OBJS-$(CONFIG_RV30_PARSER) += rv34_parser.o
|
||||
@@ -1004,14 +1021,16 @@ OBJS-$(CONFIG_VP9_PARSER) += vp9_parser.o
|
||||
OBJS-$(CONFIG_XMA_PARSER) += xma_parser.o
|
||||
|
||||
# bitstream filters
|
||||
OBJS-$(CONFIG_AAC_ADTSTOASC_BSF) += aac_adtstoasc_bsf.o aacadtsdec.o \
|
||||
mpeg4audio.o
|
||||
OBJS-$(CONFIG_AAC_ADTSTOASC_BSF) += aac_adtstoasc_bsf.o mpeg4audio.o
|
||||
OBJS-$(CONFIG_CHOMP_BSF) += chomp_bsf.o
|
||||
OBJS-$(CONFIG_DUMP_EXTRADATA_BSF) += dump_extradata_bsf.o
|
||||
OBJS-$(CONFIG_DCA_CORE_BSF) += dca_core_bsf.o
|
||||
OBJS-$(CONFIG_EXTRACT_EXTRADATA_BSF) += extract_extradata_bsf.o \
|
||||
h2645_parse.o
|
||||
OBJS-$(CONFIG_H264_METADATA_BSF) += h264_metadata_bsf.o
|
||||
OBJS-$(CONFIG_H264_MP4TOANNEXB_BSF) += h264_mp4toannexb_bsf.o
|
||||
OBJS-$(CONFIG_H264_REDUNDANT_PPS_BSF) += h264_redundant_pps_bsf.o
|
||||
OBJS-$(CONFIG_HEVC_METADATA_BSF) += h265_metadata_bsf.o
|
||||
OBJS-$(CONFIG_HEVC_MP4TOANNEXB_BSF) += hevc_mp4toannexb_bsf.o
|
||||
OBJS-$(CONFIG_IMX_DUMP_HEADER_BSF) += imx_dump_header_bsf.o
|
||||
OBJS-$(CONFIG_MJPEG2JPEG_BSF) += mjpeg2jpeg_bsf.o
|
||||
@@ -1020,10 +1039,12 @@ OBJS-$(CONFIG_MPEG4_UNPACK_BFRAMES_BSF) += mpeg4_unpack_bframes_bsf.o
|
||||
OBJS-$(CONFIG_MOV2TEXTSUB_BSF) += movsub_bsf.o
|
||||
OBJS-$(CONFIG_MP3_HEADER_DECOMPRESS_BSF) += mp3_header_decompress_bsf.o \
|
||||
mpegaudiodata.o
|
||||
OBJS-$(CONFIG_MPEG2_METADATA_BSF) += mpeg2_metadata_bsf.o
|
||||
OBJS-$(CONFIG_NOISE_BSF) += noise_bsf.o
|
||||
OBJS-$(CONFIG_NULL_BSF) += null_bsf.o
|
||||
OBJS-$(CONFIG_REMOVE_EXTRADATA_BSF) += remove_extradata_bsf.o
|
||||
OBJS-$(CONFIG_TEXT2MOVSUB_BSF) += movsub_bsf.o
|
||||
OBJS-$(CONFIG_TRACE_HEADERS_BSF) += trace_headers_bsf.o
|
||||
OBJS-$(CONFIG_VP9_RAW_REORDER_BSF) += vp9_raw_reorder_bsf.o
|
||||
OBJS-$(CONFIG_VP9_SUPERFRAME_BSF) += vp9_superframe_bsf.o
|
||||
OBJS-$(CONFIG_VP9_SUPERFRAME_SPLIT_BSF) += vp9_superframe_split_bsf.o
|
||||
@@ -1048,6 +1069,7 @@ SKIPHEADERS += %_tablegen.h \
|
||||
aacenc_quantization_misc.h \
|
||||
$(ARCH)/vp56_arith.h \
|
||||
|
||||
SKIPHEADERS-$(CONFIG_AMF) += amfenc.h
|
||||
SKIPHEADERS-$(CONFIG_D3D11VA) += d3d11va.h dxva2_internal.h
|
||||
SKIPHEADERS-$(CONFIG_DXVA2) += dxva2.h dxva2_internal.h
|
||||
SKIPHEADERS-$(CONFIG_JNI) += ffjni.h
|
||||
@@ -1060,9 +1082,8 @@ SKIPHEADERS-$(CONFIG_QSVDEC) += qsvdec.h
|
||||
SKIPHEADERS-$(CONFIG_QSVENC) += qsvenc.h
|
||||
SKIPHEADERS-$(CONFIG_XVMC) += xvmc.h
|
||||
SKIPHEADERS-$(CONFIG_VAAPI) += vaapi_decode.h vaapi_encode.h
|
||||
SKIPHEADERS-$(CONFIG_VDA) += vda.h vda_vt_internal.h
|
||||
SKIPHEADERS-$(CONFIG_VDPAU) += vdpau.h vdpau_internal.h
|
||||
SKIPHEADERS-$(CONFIG_VIDEOTOOLBOX) += videotoolbox.h vda_vt_internal.h
|
||||
SKIPHEADERS-$(CONFIG_VIDEOTOOLBOX) += videotoolbox.h vt_internal.h
|
||||
SKIPHEADERS-$(CONFIG_V4L2_M2M) += v4l2_buffers.h v4l2_context.h v4l2_m2m.h
|
||||
|
||||
TESTPROGS = avpacket \
|
||||
@@ -1082,6 +1103,7 @@ TESTPROGS-$(CONFIG_GOLOMB) += golomb
|
||||
TESTPROGS-$(CONFIG_IDCTDSP) += dct
|
||||
TESTPROGS-$(CONFIG_IIRFILTER) += iirfilter
|
||||
TESTPROGS-$(HAVE_MMX) += motion
|
||||
TESTPROGS-$(CONFIG_MPEGVIDEO) += mpeg12framerate
|
||||
TESTPROGS-$(CONFIG_RANGECODER) += rangecoder
|
||||
TESTPROGS-$(CONFIG_SNOW_ENCODER) += snowenc
|
||||
|
||||
|
||||
@@ -86,20 +86,8 @@ get_next:
|
||||
the frame). */
|
||||
if (avctx->codec_id != AV_CODEC_ID_AAC) {
|
||||
avctx->sample_rate = s->sample_rate;
|
||||
|
||||
/* (E-)AC-3: allow downmixing to stereo or mono */
|
||||
if (s->channels > 1 &&
|
||||
avctx->request_channel_layout == AV_CH_LAYOUT_MONO) {
|
||||
avctx->channels = 1;
|
||||
avctx->channel_layout = AV_CH_LAYOUT_MONO;
|
||||
} else if (s->channels > 2 &&
|
||||
avctx->request_channel_layout == AV_CH_LAYOUT_STEREO) {
|
||||
avctx->channels = 2;
|
||||
avctx->channel_layout = AV_CH_LAYOUT_STEREO;
|
||||
} else {
|
||||
avctx->channels = s->channels;
|
||||
avctx->channel_layout = s->channel_layout;
|
||||
}
|
||||
s1->duration = s->samples;
|
||||
avctx->audio_service_type = s->service_type;
|
||||
}
|
||||
|
||||
@@ -19,8 +19,9 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "adts_header.h"
|
||||
#include "adts_parser.h"
|
||||
#include "avcodec.h"
|
||||
#include "aacadtsdec.h"
|
||||
#include "bsf.h"
|
||||
#include "put_bits.h"
|
||||
#include "get_bits.h"
|
||||
@@ -52,12 +53,12 @@ static int aac_adtstoasc_filter(AVBSFContext *bsfc, AVPacket *out)
|
||||
if (bsfc->par_in->extradata && in->size >= 2 && (AV_RB16(in->data) >> 4) != 0xfff)
|
||||
goto finish;
|
||||
|
||||
if (in->size < AAC_ADTS_HEADER_SIZE)
|
||||
if (in->size < AV_AAC_ADTS_HEADER_SIZE)
|
||||
goto packet_too_small;
|
||||
|
||||
init_get_bits(&gb, in->data, AAC_ADTS_HEADER_SIZE * 8);
|
||||
init_get_bits(&gb, in->data, AV_AAC_ADTS_HEADER_SIZE * 8);
|
||||
|
||||
if (avpriv_aac_parse_header(&gb, &hdr) < 0) {
|
||||
if (ff_adts_header_parse(&gb, &hdr) < 0) {
|
||||
av_log(bsfc, AV_LOG_ERROR, "Error parsing ADTS frame header!\n");
|
||||
ret = AVERROR_INVALIDDATA;
|
||||
goto fail;
|
||||
@@ -70,10 +71,10 @@ static int aac_adtstoasc_filter(AVBSFContext *bsfc, AVPacket *out)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
in->size -= AAC_ADTS_HEADER_SIZE + 2 * !hdr.crc_absent;
|
||||
in->size -= AV_AAC_ADTS_HEADER_SIZE + 2 * !hdr.crc_absent;
|
||||
if (in->size <= 0)
|
||||
goto packet_too_small;
|
||||
in->data += AAC_ADTS_HEADER_SIZE + 2 * !hdr.crc_absent;
|
||||
in->data += AV_AAC_ADTS_HEADER_SIZE + 2 * !hdr.crc_absent;
|
||||
|
||||
if (!ctx->first_frame_done) {
|
||||
int pce_size = 0;
|
||||
@@ -91,7 +92,7 @@ static int aac_adtstoasc_filter(AVBSFContext *bsfc, AVPacket *out)
|
||||
goto fail;
|
||||
}
|
||||
init_put_bits(&pb, pce_data, MAX_PCE_SIZE);
|
||||
pce_size = avpriv_copy_pce_data(&pb, &gb)/8;
|
||||
pce_size = ff_copy_pce_data(&pb, &gb) / 8;
|
||||
flush_put_bits(&pb);
|
||||
in->size -= get_bits_count(&gb)/8;
|
||||
in->data += get_bits_count(&gb)/8;
|
||||
|
||||
@@ -22,7 +22,8 @@
|
||||
|
||||
#include "parser.h"
|
||||
#include "aac_ac3_parser.h"
|
||||
#include "aacadtsdec.h"
|
||||
#include "adts_header.h"
|
||||
#include "adts_parser.h"
|
||||
#include "get_bits.h"
|
||||
#include "mpeg4audio.h"
|
||||
|
||||
@@ -38,9 +39,10 @@ static int aac_sync(uint64_t state, AACAC3ParseContext *hdr_info,
|
||||
} tmp;
|
||||
|
||||
tmp.u64 = av_be2ne64(state);
|
||||
init_get_bits(&bits, tmp.u8+8-AAC_ADTS_HEADER_SIZE, AAC_ADTS_HEADER_SIZE * 8);
|
||||
init_get_bits(&bits, tmp.u8 + 8 - AV_AAC_ADTS_HEADER_SIZE,
|
||||
AV_AAC_ADTS_HEADER_SIZE * 8);
|
||||
|
||||
if ((size = avpriv_aac_parse_header(&bits, &hdr)) < 0)
|
||||
if ((size = ff_adts_header_parse(&bits, &hdr)) < 0)
|
||||
return 0;
|
||||
*need_next_header = 0;
|
||||
*new_frame_start = 1;
|
||||
@@ -54,7 +56,7 @@ static int aac_sync(uint64_t state, AACAC3ParseContext *hdr_info,
|
||||
static av_cold int aac_parse_init(AVCodecParserContext *s1)
|
||||
{
|
||||
AACAC3ParseContext *s = s1->priv_data;
|
||||
s->header_size = AAC_ADTS_HEADER_SIZE;
|
||||
s->header_size = AV_AAC_ADTS_HEADER_SIZE;
|
||||
s->sync = aac_sync;
|
||||
return 0;
|
||||
}
|
||||
|
||||
+1
-1
@@ -50,11 +50,11 @@
|
||||
#include "aac.h"
|
||||
#include "aactab.h"
|
||||
#include "aacdectab.h"
|
||||
#include "adts_header.h"
|
||||
#include "cbrt_data.h"
|
||||
#include "sbr.h"
|
||||
#include "aacsbr.h"
|
||||
#include "mpeg4audio.h"
|
||||
#include "aacadtsdec.h"
|
||||
#include "profiles.h"
|
||||
#include "libavutil/intfloat.h"
|
||||
|
||||
|
||||
@@ -75,11 +75,11 @@
|
||||
#include "aac.h"
|
||||
#include "aactab.h"
|
||||
#include "aacdectab.h"
|
||||
#include "adts_header.h"
|
||||
#include "cbrt_data.h"
|
||||
#include "sbr.h"
|
||||
#include "aacsbr.h"
|
||||
#include "mpeg4audio.h"
|
||||
#include "aacadtsdec.h"
|
||||
#include "profiles.h"
|
||||
#include "libavutil/intfloat.h"
|
||||
|
||||
@@ -307,9 +307,9 @@ static av_always_inline void predict(PredictorState *ps, int *coef,
|
||||
|
||||
if (shift < 31) {
|
||||
if (shift > 0) {
|
||||
*coef += (pv.mant + (1 << (shift - 1))) >> shift;
|
||||
*coef += (unsigned)((pv.mant + (1 << (shift - 1))) >> shift);
|
||||
} else
|
||||
*coef += pv.mant << -shift;
|
||||
*coef += (unsigned)pv.mant << -shift;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -394,7 +394,7 @@ static void apply_dependent_coupling_fixed(AACContext *ac,
|
||||
for (k = offsets[i]; k < offsets[i + 1]; k++) {
|
||||
tmp = (int)(((int64_t)src[group * 128 + k] * c + \
|
||||
(int64_t)0x1000000000) >> 37);
|
||||
dest[group * 128 + k] += tmp * (1 << shift);
|
||||
dest[group * 128 + k] += tmp * (1U << shift);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2955,7 +2955,7 @@ static int parse_adts_frame_header(AACContext *ac, GetBitContext *gb)
|
||||
uint8_t layout_map[MAX_ELEM_ID*4][3];
|
||||
int layout_map_tags, ret;
|
||||
|
||||
size = avpriv_aac_parse_header(gb, &hdr_info);
|
||||
size = ff_adts_header_parse(gb, &hdr_info);
|
||||
if (size > 0) {
|
||||
if (!ac->warned_num_aac_frames && hdr_info.num_aac_frames != 1) {
|
||||
// This is 2 for "VLB " audio in NSV files.
|
||||
|
||||
+82
-15
@@ -50,17 +50,59 @@
|
||||
|
||||
static AVOnce aac_table_init = AV_ONCE_INIT;
|
||||
|
||||
static void put_pce(PutBitContext *pb, AVCodecContext *avctx)
|
||||
{
|
||||
int i, j;
|
||||
AACEncContext *s = avctx->priv_data;
|
||||
AACPCEInfo *pce = &s->pce;
|
||||
const int bitexact = avctx->flags & AV_CODEC_FLAG_BITEXACT;
|
||||
const char *aux_data = bitexact ? "Lavc" : LIBAVCODEC_IDENT;
|
||||
|
||||
put_bits(pb, 4, 0);
|
||||
|
||||
put_bits(pb, 2, avctx->profile);
|
||||
put_bits(pb, 4, s->samplerate_index);
|
||||
|
||||
put_bits(pb, 4, pce->num_ele[0]); /* Front */
|
||||
put_bits(pb, 4, pce->num_ele[1]); /* Side */
|
||||
put_bits(pb, 4, pce->num_ele[2]); /* Back */
|
||||
put_bits(pb, 2, pce->num_ele[3]); /* LFE */
|
||||
put_bits(pb, 3, 0); /* Assoc data */
|
||||
put_bits(pb, 4, 0); /* CCs */
|
||||
|
||||
put_bits(pb, 1, 0); /* Stereo mixdown */
|
||||
put_bits(pb, 1, 0); /* Mono mixdown */
|
||||
put_bits(pb, 1, 0); /* Something else */
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (j = 0; j < pce->num_ele[i]; j++) {
|
||||
if (i < 3)
|
||||
put_bits(pb, 1, pce->pairing[i][j]);
|
||||
put_bits(pb, 4, pce->index[i][j]);
|
||||
}
|
||||
}
|
||||
|
||||
avpriv_align_put_bits(pb);
|
||||
put_bits(pb, 8, strlen(aux_data));
|
||||
avpriv_put_string(pb, aux_data, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make AAC audio config object.
|
||||
* @see 1.6.2.1 "Syntax - AudioSpecificConfig"
|
||||
*/
|
||||
static void put_audio_specific_config(AVCodecContext *avctx)
|
||||
static int put_audio_specific_config(AVCodecContext *avctx)
|
||||
{
|
||||
PutBitContext pb;
|
||||
AACEncContext *s = avctx->priv_data;
|
||||
int channels = s->channels - (s->channels == 8 ? 1 : 0);
|
||||
int channels = (!s->needs_pce)*(s->channels - (s->channels == 8 ? 1 : 0));
|
||||
const int max_size = 32;
|
||||
|
||||
init_put_bits(&pb, avctx->extradata, avctx->extradata_size);
|
||||
avctx->extradata = av_mallocz(max_size);
|
||||
if (!avctx->extradata)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
init_put_bits(&pb, avctx->extradata, max_size);
|
||||
put_bits(&pb, 5, s->profile+1); //profile
|
||||
put_bits(&pb, 4, s->samplerate_index); //sample rate index
|
||||
put_bits(&pb, 4, channels);
|
||||
@@ -68,12 +110,17 @@ static void put_audio_specific_config(AVCodecContext *avctx)
|
||||
put_bits(&pb, 1, 0); //frame length - 1024 samples
|
||||
put_bits(&pb, 1, 0); //does not depend on core coder
|
||||
put_bits(&pb, 1, 0); //is not extension
|
||||
if (s->needs_pce)
|
||||
put_pce(&pb, avctx);
|
||||
|
||||
//Explicitly Mark SBR absent
|
||||
put_bits(&pb, 11, 0x2b7); //sync extension
|
||||
put_bits(&pb, 5, AOT_SBR);
|
||||
put_bits(&pb, 1, 0);
|
||||
flush_put_bits(&pb);
|
||||
avctx->extradata_size = put_bits_count(&pb) >> 3;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ff_quantize_band_cost_cache_init(struct AACEncContext *s)
|
||||
@@ -488,7 +535,7 @@ static void copy_input_samples(AACEncContext *s, const AVFrame *frame)
|
||||
{
|
||||
int ch;
|
||||
int end = 2048 + (frame ? frame->nb_samples : 0);
|
||||
const uint8_t *channel_map = aac_chan_maps[s->channels - 1];
|
||||
const uint8_t *channel_map = s->reorder_map;
|
||||
|
||||
/* copy and remap input samples */
|
||||
for (ch = 0; ch < s->channels; ch++) {
|
||||
@@ -895,7 +942,6 @@ static av_cold int alloc_buffers(AVCodecContext *avctx, AACEncContext *s)
|
||||
int ch;
|
||||
FF_ALLOCZ_ARRAY_OR_GOTO(avctx, s->buffer.samples, s->channels, 3 * 1024 * sizeof(s->buffer.samples[0]), alloc_fail);
|
||||
FF_ALLOCZ_ARRAY_OR_GOTO(avctx, s->cpe, s->chan_map[0], sizeof(ChannelElement), alloc_fail);
|
||||
FF_ALLOCZ_OR_GOTO(avctx, avctx->extradata, 5 + AV_INPUT_BUFFER_PADDING_SIZE, alloc_fail);
|
||||
|
||||
for(ch = 0; ch < s->channels; ch++)
|
||||
s->planar_samples[ch] = s->buffer.samples + 3 * 1024 * ch;
|
||||
@@ -920,16 +966,35 @@ static av_cold int aac_encode_init(AVCodecContext *avctx)
|
||||
|
||||
/* Constants */
|
||||
s->last_frame_pb_count = 0;
|
||||
avctx->extradata_size = 5;
|
||||
avctx->frame_size = 1024;
|
||||
avctx->initial_padding = 1024;
|
||||
s->lambda = avctx->global_quality > 0 ? avctx->global_quality : 120;
|
||||
|
||||
/* Channel map and unspecified bitrate guessing */
|
||||
s->channels = avctx->channels;
|
||||
ERROR_IF(s->channels > AAC_MAX_CHANNELS || s->channels == 7,
|
||||
"Unsupported number of channels: %d\n", s->channels);
|
||||
|
||||
s->needs_pce = 1;
|
||||
for (i = 0; i < FF_ARRAY_ELEMS(aac_normal_chan_layouts); i++) {
|
||||
if (avctx->channel_layout == aac_normal_chan_layouts[i]) {
|
||||
s->needs_pce = s->options.pce;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (s->needs_pce) {
|
||||
for (i = 0; i < FF_ARRAY_ELEMS(aac_pce_configs); i++)
|
||||
if (avctx->channel_layout == aac_pce_configs[i].layout)
|
||||
break;
|
||||
ERROR_IF(i == FF_ARRAY_ELEMS(aac_pce_configs), "Unsupported channel layout\n");
|
||||
av_log(avctx, AV_LOG_INFO, "Using a PCE to encode channel layout\n");
|
||||
s->pce = aac_pce_configs[i];
|
||||
s->reorder_map = s->pce.reorder_map;
|
||||
s->chan_map = s->pce.config_map;
|
||||
} else {
|
||||
s->reorder_map = aac_chan_maps[s->channels - 1];
|
||||
s->chan_map = aac_chan_configs[s->channels - 1];
|
||||
}
|
||||
|
||||
if (!avctx->bit_rate) {
|
||||
for (i = 1; i <= s->chan_map[0]; i++) {
|
||||
avctx->bit_rate += s->chan_map[i] == TYPE_CPE ? 128000 : /* Pair */
|
||||
@@ -1015,7 +1080,8 @@ static av_cold int aac_encode_init(AVCodecContext *avctx)
|
||||
if ((ret = alloc_buffers(avctx, s)) < 0)
|
||||
goto fail;
|
||||
|
||||
put_audio_specific_config(avctx);
|
||||
if ((ret = put_audio_specific_config(avctx)))
|
||||
goto fail;
|
||||
|
||||
sizes[0] = ff_aac_swb_size_1024[s->samplerate_index];
|
||||
sizes[1] = ff_aac_swb_size_128[s->samplerate_index];
|
||||
@@ -1052,24 +1118,25 @@ fail:
|
||||
|
||||
#define AACENC_FLAGS AV_OPT_FLAG_ENCODING_PARAM | AV_OPT_FLAG_AUDIO_PARAM
|
||||
static const AVOption aacenc_options[] = {
|
||||
{"aac_coder", "Coding algorithm", offsetof(AACEncContext, options.coder), AV_OPT_TYPE_INT, {.i64 = AAC_CODER_TWOLOOP}, 0, AAC_CODER_NB-1, AACENC_FLAGS, "coder"},
|
||||
{"aac_coder", "Coding algorithm", offsetof(AACEncContext, options.coder), AV_OPT_TYPE_INT, {.i64 = AAC_CODER_FAST}, 0, AAC_CODER_NB-1, AACENC_FLAGS, "coder"},
|
||||
{"anmr", "ANMR method", 0, AV_OPT_TYPE_CONST, {.i64 = AAC_CODER_ANMR}, INT_MIN, INT_MAX, AACENC_FLAGS, "coder"},
|
||||
{"twoloop", "Two loop searching method", 0, AV_OPT_TYPE_CONST, {.i64 = AAC_CODER_TWOLOOP}, INT_MIN, INT_MAX, AACENC_FLAGS, "coder"},
|
||||
{"fast", "Constant quantizer", 0, AV_OPT_TYPE_CONST, {.i64 = AAC_CODER_FAST}, INT_MIN, INT_MAX, AACENC_FLAGS, "coder"},
|
||||
{"fast", "Default fast search", 0, AV_OPT_TYPE_CONST, {.i64 = AAC_CODER_FAST}, INT_MIN, INT_MAX, AACENC_FLAGS, "coder"},
|
||||
{"aac_ms", "Force M/S stereo coding", offsetof(AACEncContext, options.mid_side), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, AACENC_FLAGS},
|
||||
{"aac_is", "Intensity stereo coding", offsetof(AACEncContext, options.intensity_stereo), AV_OPT_TYPE_BOOL, {.i64 = 1}, -1, 1, AACENC_FLAGS},
|
||||
{"aac_pns", "Perceptual noise substitution", offsetof(AACEncContext, options.pns), AV_OPT_TYPE_BOOL, {.i64 = 1}, -1, 1, AACENC_FLAGS},
|
||||
{"aac_tns", "Temporal noise shaping", offsetof(AACEncContext, options.tns), AV_OPT_TYPE_BOOL, {.i64 = 1}, -1, 1, AACENC_FLAGS},
|
||||
{"aac_ltp", "Long term prediction", offsetof(AACEncContext, options.ltp), AV_OPT_TYPE_BOOL, {.i64 = 0}, -1, 1, AACENC_FLAGS},
|
||||
{"aac_pred", "AAC-Main prediction", offsetof(AACEncContext, options.pred), AV_OPT_TYPE_BOOL, {.i64 = 0}, -1, 1, AACENC_FLAGS},
|
||||
{"aac_pce", "Forces the use of PCEs", offsetof(AACEncContext, options.pce), AV_OPT_TYPE_BOOL, {.i64 = 0}, -1, 1, AACENC_FLAGS},
|
||||
{NULL}
|
||||
};
|
||||
|
||||
static const AVClass aacenc_class = {
|
||||
"AAC encoder",
|
||||
av_default_item_name,
|
||||
aacenc_options,
|
||||
LIBAVUTIL_VERSION_INT,
|
||||
.class_name = "AAC encoder",
|
||||
.item_name = av_default_item_name,
|
||||
.option = aacenc_options,
|
||||
.version = LIBAVUTIL_VERSION_INT,
|
||||
};
|
||||
|
||||
static const AVCodecDefault aac_encode_defaults[] = {
|
||||
|
||||
+285
-1
@@ -45,6 +45,7 @@ typedef struct AACEncOptions {
|
||||
int pns;
|
||||
int tns;
|
||||
int ltp;
|
||||
int pce;
|
||||
int pred;
|
||||
int mid_side;
|
||||
int intensity_stereo;
|
||||
@@ -89,6 +90,286 @@ typedef struct AACQuantizeBandCostCacheEntry {
|
||||
uint16_t generation;
|
||||
} AACQuantizeBandCostCacheEntry;
|
||||
|
||||
typedef struct AACPCEInfo {
|
||||
int64_t layout;
|
||||
int num_ele[4]; ///< front, side, back, lfe
|
||||
int pairing[3][8]; ///< front, side, back
|
||||
int index[4][8]; ///< front, side, back, lfe
|
||||
uint8_t config_map[16]; ///< configs the encoder's channel specific settings
|
||||
uint8_t reorder_map[16]; ///< maps channels from lavc to aac order
|
||||
} AACPCEInfo;
|
||||
|
||||
/**
|
||||
* List of PCE (Program Configuration Element) for the channel layouts listed
|
||||
* in channel_layout.h
|
||||
*
|
||||
* For those wishing in the future to add other layouts:
|
||||
*
|
||||
* - num_ele: number of elements in each group of front, side, back, lfe channels
|
||||
* (an element is of type SCE (single channel), CPE (channel pair) for
|
||||
* the first 3 groups; and is LFE for LFE group).
|
||||
*
|
||||
* - pairing: 0 for an SCE element or 1 for a CPE; does not apply to LFE group
|
||||
*
|
||||
* - index: there are three independent indices for SCE, CPE and LFE;
|
||||
* they are incremented irrespective of the group to which the element belongs;
|
||||
* they are not reset when going from one group to another
|
||||
*
|
||||
* Example: for 7.0 channel layout,
|
||||
* .pairing = { { 1, 0 }, { 1 }, { 1 }, }, (3 CPE and 1 SCE in front group)
|
||||
* .index = { { 0, 0 }, { 1 }, { 2 }, },
|
||||
* (index is 0 for the single SCE but goes from 0 to 2 for the CPEs)
|
||||
*
|
||||
* The index order impacts the channel ordering. But is otherwise arbitrary
|
||||
* (the sequence could have been 2, 0, 1 instead of 0, 1, 2).
|
||||
*
|
||||
* Spec allows for discontinuous indices, e.g. if one has a total of two SCE,
|
||||
* SCE.0 SCE.15 is OK per spec; BUT it won't be decoded by our AAC decoder
|
||||
* which at this time requires that indices fully cover some range starting
|
||||
* from 0 (SCE.1 SCE.0 is OK but not SCE.0 SCE.15).
|
||||
*
|
||||
* - config_map: total number of elements and their types. Beware, the way the
|
||||
* types are ordered impacts the final channel ordering.
|
||||
*
|
||||
* - reorder_map: reorders the channels.
|
||||
*
|
||||
*/
|
||||
static const AACPCEInfo aac_pce_configs[] = {
|
||||
{
|
||||
.layout = AV_CH_LAYOUT_MONO,
|
||||
.num_ele = { 1, 0, 0, 0 },
|
||||
.pairing = { { 0 }, },
|
||||
.index = { { 0 }, },
|
||||
.config_map = { 1, TYPE_SCE, },
|
||||
.reorder_map = { 0 },
|
||||
},
|
||||
{
|
||||
.layout = AV_CH_LAYOUT_STEREO,
|
||||
.num_ele = { 1, 0, 0, 0 },
|
||||
.pairing = { { 1 }, },
|
||||
.index = { { 0 }, },
|
||||
.config_map = { 1, TYPE_CPE, },
|
||||
.reorder_map = { 0, 1 },
|
||||
},
|
||||
{
|
||||
.layout = AV_CH_LAYOUT_2POINT1,
|
||||
.num_ele = { 1, 0, 0, 1 },
|
||||
.pairing = { { 1 }, },
|
||||
.index = { { 0 },{ 0 },{ 0 },{ 0 } },
|
||||
.config_map = { 2, TYPE_CPE, TYPE_LFE },
|
||||
.reorder_map = { 0, 1, 2 },
|
||||
},
|
||||
{
|
||||
.layout = AV_CH_LAYOUT_2_1,
|
||||
.num_ele = { 1, 0, 1, 0 },
|
||||
.pairing = { { 1 },{ 0 },{ 0 } },
|
||||
.index = { { 0 },{ 0 },{ 0 }, },
|
||||
.config_map = { 2, TYPE_CPE, TYPE_SCE },
|
||||
.reorder_map = { 0, 1, 2 },
|
||||
},
|
||||
{
|
||||
.layout = AV_CH_LAYOUT_SURROUND,
|
||||
.num_ele = { 2, 0, 0, 0 },
|
||||
.pairing = { { 1, 0 }, },
|
||||
.index = { { 0, 0 }, },
|
||||
.config_map = { 2, TYPE_CPE, TYPE_SCE, },
|
||||
.reorder_map = { 0, 1, 2 },
|
||||
},
|
||||
{
|
||||
.layout = AV_CH_LAYOUT_3POINT1,
|
||||
.num_ele = { 2, 0, 0, 1 },
|
||||
.pairing = { { 1, 0 }, },
|
||||
.index = { { 0, 0 }, { 0 }, { 0 }, { 0 }, },
|
||||
.config_map = { 3, TYPE_CPE, TYPE_SCE, TYPE_LFE },
|
||||
.reorder_map = { 0, 1, 2, 3 },
|
||||
},
|
||||
{
|
||||
.layout = AV_CH_LAYOUT_4POINT0,
|
||||
.num_ele = { 2, 0, 1, 0 },
|
||||
.pairing = { { 1, 0 }, { 0 }, { 0 }, },
|
||||
.index = { { 0, 0 }, { 0 }, { 1 } },
|
||||
.config_map = { 3, TYPE_CPE, TYPE_SCE, TYPE_SCE },
|
||||
.reorder_map = { 0, 1, 2, 3 },
|
||||
},
|
||||
{
|
||||
.layout = AV_CH_LAYOUT_4POINT1,
|
||||
.num_ele = { 2, 1, 1, 0 },
|
||||
.pairing = { { 1, 0 }, { 0 }, { 0 }, },
|
||||
.index = { { 0, 0 }, { 1 }, { 2 }, { 0 } },
|
||||
.config_map = { 4, TYPE_CPE, TYPE_SCE, TYPE_SCE, TYPE_SCE },
|
||||
.reorder_map = { 0, 1, 2, 3, 4 },
|
||||
},
|
||||
{
|
||||
.layout = AV_CH_LAYOUT_2_2,
|
||||
.num_ele = { 1, 1, 0, 0 },
|
||||
.pairing = { { 1 }, { 1 }, },
|
||||
.index = { { 0 }, { 1 }, },
|
||||
.config_map = { 2, TYPE_CPE, TYPE_CPE },
|
||||
.reorder_map = { 0, 1, 2, 3 },
|
||||
},
|
||||
{
|
||||
.layout = AV_CH_LAYOUT_QUAD,
|
||||
.num_ele = { 1, 0, 1, 0 },
|
||||
.pairing = { { 1 }, { 0 }, { 1 }, },
|
||||
.index = { { 0 }, { 0 }, { 1 } },
|
||||
.config_map = { 2, TYPE_CPE, TYPE_CPE },
|
||||
.reorder_map = { 0, 1, 2, 3 },
|
||||
},
|
||||
{
|
||||
.layout = AV_CH_LAYOUT_5POINT0,
|
||||
.num_ele = { 2, 1, 0, 0 },
|
||||
.pairing = { { 1, 0 }, { 1 }, },
|
||||
.index = { { 0, 0 }, { 1 } },
|
||||
.config_map = { 3, TYPE_CPE, TYPE_SCE, TYPE_CPE },
|
||||
.reorder_map = { 0, 1, 2, 3, 4 },
|
||||
},
|
||||
{
|
||||
.layout = AV_CH_LAYOUT_5POINT1,
|
||||
.num_ele = { 2, 1, 1, 0 },
|
||||
.pairing = { { 1, 0 }, { 0 }, { 1 }, },
|
||||
.index = { { 0, 0 }, { 1 }, { 1 } },
|
||||
.config_map = { 4, TYPE_CPE, TYPE_SCE, TYPE_SCE, TYPE_CPE },
|
||||
.reorder_map = { 0, 1, 2, 3, 4, 5 },
|
||||
},
|
||||
{
|
||||
.layout = AV_CH_LAYOUT_5POINT0_BACK,
|
||||
.num_ele = { 2, 0, 1, 0 },
|
||||
.pairing = { { 1, 0 }, { 0 }, { 1 } },
|
||||
.index = { { 0, 0 }, { 0 }, { 1 } },
|
||||
.config_map = { 3, TYPE_CPE, TYPE_SCE, TYPE_CPE },
|
||||
.reorder_map = { 0, 1, 2, 3, 4 },
|
||||
},
|
||||
{
|
||||
.layout = AV_CH_LAYOUT_5POINT1_BACK,
|
||||
.num_ele = { 2, 1, 1, 0 },
|
||||
.pairing = { { 1, 0 }, { 0 }, { 1 }, },
|
||||
.index = { { 0, 0 }, { 1 }, { 1 } },
|
||||
.config_map = { 4, TYPE_CPE, TYPE_SCE, TYPE_SCE, TYPE_CPE },
|
||||
.reorder_map = { 0, 1, 2, 3, 4, 5 },
|
||||
},
|
||||
{
|
||||
.layout = AV_CH_LAYOUT_6POINT0,
|
||||
.num_ele = { 2, 1, 1, 0 },
|
||||
.pairing = { { 1, 0 }, { 1 }, { 0 }, },
|
||||
.index = { { 0, 0 }, { 1 }, { 1 } },
|
||||
.config_map = { 4, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_SCE },
|
||||
.reorder_map = { 0, 1, 2, 3, 4, 5 },
|
||||
},
|
||||
{
|
||||
.layout = AV_CH_LAYOUT_6POINT0_FRONT,
|
||||
.num_ele = { 2, 1, 0, 0 },
|
||||
.pairing = { { 1, 1 }, { 1 } },
|
||||
.index = { { 1, 0 }, { 2 }, },
|
||||
.config_map = { 3, TYPE_CPE, TYPE_CPE, TYPE_CPE, },
|
||||
.reorder_map = { 0, 1, 2, 3, 4, 5 },
|
||||
},
|
||||
{
|
||||
.layout = AV_CH_LAYOUT_HEXAGONAL,
|
||||
.num_ele = { 2, 0, 2, 0 },
|
||||
.pairing = { { 1, 0 },{ 0 },{ 1, 0 }, },
|
||||
.index = { { 0, 0 },{ 0 },{ 1, 1 } },
|
||||
.config_map = { 4, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_SCE, },
|
||||
.reorder_map = { 0, 1, 2, 3, 4, 5 },
|
||||
},
|
||||
{
|
||||
.layout = AV_CH_LAYOUT_6POINT1,
|
||||
.num_ele = { 2, 1, 2, 0 },
|
||||
.pairing = { { 1, 0 },{ 0 },{ 1, 0 }, },
|
||||
.index = { { 0, 0 },{ 1 },{ 1, 2 } },
|
||||
.config_map = { 5, TYPE_CPE, TYPE_SCE, TYPE_SCE, TYPE_CPE, TYPE_SCE },
|
||||
.reorder_map = { 0, 1, 2, 3, 4, 5, 6 },
|
||||
},
|
||||
{
|
||||
.layout = AV_CH_LAYOUT_6POINT1_BACK,
|
||||
.num_ele = { 2, 1, 2, 0 },
|
||||
.pairing = { { 1, 0 }, { 0 }, { 1, 0 }, },
|
||||
.index = { { 0, 0 }, { 1 }, { 1, 2 } },
|
||||
.config_map = { 5, TYPE_CPE, TYPE_SCE, TYPE_SCE, TYPE_CPE, TYPE_SCE },
|
||||
.reorder_map = { 0, 1, 2, 3, 4, 5, 6 },
|
||||
},
|
||||
{
|
||||
.layout = AV_CH_LAYOUT_6POINT1_FRONT,
|
||||
.num_ele = { 2, 1, 2, 0 },
|
||||
.pairing = { { 1, 0 }, { 0 }, { 1, 0 }, },
|
||||
.index = { { 0, 0 }, { 1 }, { 1, 2 } },
|
||||
.config_map = { 5, TYPE_CPE, TYPE_SCE, TYPE_SCE, TYPE_CPE, TYPE_SCE },
|
||||
.reorder_map = { 0, 1, 2, 3, 4, 5, 6 },
|
||||
},
|
||||
{
|
||||
.layout = AV_CH_LAYOUT_7POINT0,
|
||||
.num_ele = { 2, 1, 1, 0 },
|
||||
.pairing = { { 1, 0 }, { 1 }, { 1 }, },
|
||||
.index = { { 0, 0 }, { 1 }, { 2 }, },
|
||||
.config_map = { 4, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_CPE },
|
||||
.reorder_map = { 0, 1, 2, 3, 4, 5, 6 },
|
||||
},
|
||||
{
|
||||
.layout = AV_CH_LAYOUT_7POINT0_FRONT,
|
||||
.num_ele = { 2, 1, 1, 0 },
|
||||
.pairing = { { 1, 0 }, { 1 }, { 1 }, },
|
||||
.index = { { 0, 0 }, { 1 }, { 2 }, },
|
||||
.config_map = { 4, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_CPE },
|
||||
.reorder_map = { 0, 1, 2, 3, 4, 5, 6 },
|
||||
},
|
||||
{
|
||||
.layout = AV_CH_LAYOUT_7POINT1,
|
||||
.num_ele = { 2, 1, 2, 0 },
|
||||
.pairing = { { 1, 0 }, { 0 }, { 1, 1 }, },
|
||||
.index = { { 0, 0 }, { 1 }, { 1, 2 }, { 0 } },
|
||||
.config_map = { 5, TYPE_CPE, TYPE_SCE, TYPE_SCE, TYPE_CPE, TYPE_CPE },
|
||||
.reorder_map = { 0, 1, 2, 3, 4, 5, 6, 7 },
|
||||
},
|
||||
{
|
||||
.layout = AV_CH_LAYOUT_7POINT1_WIDE,
|
||||
.num_ele = { 2, 1, 2, 0 },
|
||||
.pairing = { { 1, 0 }, { 0 },{ 1, 1 }, },
|
||||
.index = { { 0, 0 }, { 1 }, { 1, 2 }, { 0 } },
|
||||
.config_map = { 5, TYPE_CPE, TYPE_SCE, TYPE_SCE, TYPE_CPE, TYPE_CPE },
|
||||
.reorder_map = { 0, 1, 2, 3, 4, 5, 6, 7 },
|
||||
},
|
||||
{
|
||||
.layout = AV_CH_LAYOUT_7POINT1_WIDE_BACK,
|
||||
.num_ele = { 2, 1, 2, 0 },
|
||||
.pairing = { { 1, 0 }, { 0 }, { 1, 1 }, },
|
||||
.index = { { 0, 0 }, { 1 }, { 1, 2 }, { 0 } },
|
||||
.config_map = { 5, TYPE_CPE, TYPE_SCE, TYPE_SCE, TYPE_CPE, TYPE_CPE },
|
||||
.reorder_map = { 0, 1, 2, 3, 4, 5, 6, 7 },
|
||||
},
|
||||
{
|
||||
.layout = AV_CH_LAYOUT_OCTAGONAL,
|
||||
.num_ele = { 2, 1, 2, 0 },
|
||||
.pairing = { { 1, 0 }, { 1 }, { 1, 0 }, },
|
||||
.index = { { 0, 0 }, { 1 }, { 2, 1 } },
|
||||
.config_map = { 5, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_CPE, TYPE_SCE },
|
||||
.reorder_map = { 0, 1, 2, 3, 4, 5, 6, 7 },
|
||||
},
|
||||
{ /* Meant for order 2/mixed ambisonics */
|
||||
.layout = AV_CH_LAYOUT_OCTAGONAL | AV_CH_TOP_CENTER,
|
||||
.num_ele = { 2, 2, 2, 0 },
|
||||
.pairing = { { 1, 0 }, { 1, 0 }, { 1, 0 }, },
|
||||
.index = { { 0, 0 }, { 1, 1 }, { 2, 2 } },
|
||||
.config_map = { 6, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_SCE },
|
||||
.reorder_map = { 0, 1, 2, 3, 4, 5, 6, 7, 8 },
|
||||
},
|
||||
{ /* Meant for order 2/mixed ambisonics */
|
||||
.layout = AV_CH_LAYOUT_6POINT0_FRONT | AV_CH_BACK_CENTER |
|
||||
AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT | AV_CH_TOP_CENTER,
|
||||
.num_ele = { 2, 2, 2, 0 },
|
||||
.pairing = { { 1, 1 }, { 1, 0 }, { 1, 0 }, },
|
||||
.index = { { 0, 1 }, { 2, 0 }, { 3, 1 } },
|
||||
.config_map = { 6, TYPE_CPE, TYPE_CPE, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_SCE },
|
||||
.reorder_map = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
|
||||
},
|
||||
{
|
||||
.layout = AV_CH_LAYOUT_HEXADECAGONAL,
|
||||
.num_ele = { 4, 2, 4, 0 },
|
||||
.pairing = { { 1, 0, 1, 0 }, { 1, 1 }, { 1, 0, 1, 0 }, },
|
||||
.index = { { 0, 0, 1, 1 }, { 2, 3 }, { 4, 2, 5, 3 } },
|
||||
.config_map = { 10, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_CPE, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_SCE },
|
||||
.reorder_map = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* AAC encoder context
|
||||
*/
|
||||
@@ -99,12 +380,15 @@ typedef struct AACEncContext {
|
||||
FFTContext mdct1024; ///< long (1024 samples) frame transform context
|
||||
FFTContext mdct128; ///< short (128 samples) frame transform context
|
||||
AVFloatDSPContext *fdsp;
|
||||
float *planar_samples[8]; ///< saved preprocessed input
|
||||
AACPCEInfo pce; ///< PCE data, if needed
|
||||
float *planar_samples[16]; ///< saved preprocessed input
|
||||
|
||||
int profile; ///< copied from avctx
|
||||
int needs_pce; ///< flag for non-standard layout
|
||||
LPCContext lpc; ///< used by TNS
|
||||
int samplerate_index; ///< MPEG-4 samplerate index
|
||||
int channels; ///< channel count
|
||||
const uint8_t *reorder_map; ///< lavc to aac reorder map
|
||||
const uint8_t *chan_map; ///< channel configuration map
|
||||
|
||||
ChannelElement *cpe; ///< channel elements
|
||||
|
||||
+12
-1
@@ -36,13 +36,24 @@
|
||||
/** Total number of codebooks, including special ones **/
|
||||
#define CB_TOT_ALL 15
|
||||
|
||||
#define AAC_MAX_CHANNELS 8
|
||||
#define AAC_MAX_CHANNELS 16
|
||||
|
||||
extern const uint8_t *ff_aac_swb_size_1024[];
|
||||
extern const int ff_aac_swb_size_1024_len;
|
||||
extern const uint8_t *ff_aac_swb_size_128[];
|
||||
extern const int ff_aac_swb_size_128_len;
|
||||
|
||||
/* Supported layouts without using a PCE */
|
||||
static const int64_t aac_normal_chan_layouts[7] = {
|
||||
AV_CH_LAYOUT_MONO,
|
||||
AV_CH_LAYOUT_STEREO,
|
||||
AV_CH_LAYOUT_SURROUND,
|
||||
AV_CH_LAYOUT_4POINT0,
|
||||
AV_CH_LAYOUT_5POINT0_BACK,
|
||||
AV_CH_LAYOUT_5POINT1_BACK,
|
||||
AV_CH_LAYOUT_7POINT1,
|
||||
};
|
||||
|
||||
/** default channel configurations */
|
||||
static const uint8_t aac_chan_configs[AAC_MAX_CHANNELS][6] = {
|
||||
{1, TYPE_SCE}, // 1 channel - single channel element
|
||||
|
||||
@@ -130,12 +130,12 @@ static void ps_decorrelate_c(INTFLOAT (*out)[2], INTFLOAT (*delay)[2],
|
||||
INTFLOAT apd_im = in_im;
|
||||
in_re = AAC_MSUB30(link_delay_re, fractional_delay_re,
|
||||
link_delay_im, fractional_delay_im);
|
||||
in_re -= a_re;
|
||||
in_re -= (UINTFLOAT)a_re;
|
||||
in_im = AAC_MADD30(link_delay_re, fractional_delay_im,
|
||||
link_delay_im, fractional_delay_re);
|
||||
in_im -= a_im;
|
||||
ap_delay[m][n+5][0] = apd_re + AAC_MUL31(ag[m], in_re);
|
||||
ap_delay[m][n+5][1] = apd_im + AAC_MUL31(ag[m], in_im);
|
||||
in_im -= (UINTFLOAT)a_im;
|
||||
ap_delay[m][n+5][0] = apd_re + (UINTFLOAT)AAC_MUL31(ag[m], in_re);
|
||||
ap_delay[m][n+5][1] = apd_im + (UINTFLOAT)AAC_MUL31(ag[m], in_im);
|
||||
}
|
||||
out[n][0] = AAC_MUL16(transient_gain[n], in_re);
|
||||
out[n][1] = AAC_MUL16(transient_gain[n], in_im);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user