mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-27 02:47:31 +09:00
[ffvpx] Update ffvp9/ffvp8 to 3.4.2-release
Structure of code was slightly modified so that it should be no longer necessary to re-generate the config_*.h files, greatly simplifying the resync process in the future.
This commit is contained in:
parent
705e180aea
commit
d1361d3c21
183 changed files with 17773 additions and 28489 deletions
|
|
@ -28,40 +28,27 @@
|
|||
#define avpriv_atomic_int_get atomic_int_get_gcc
|
||||
static inline int atomic_int_get_gcc(volatile int *ptr)
|
||||
{
|
||||
#if HAVE_ATOMIC_COMPARE_EXCHANGE
|
||||
return __atomic_load_n(ptr, __ATOMIC_SEQ_CST);
|
||||
#else
|
||||
__sync_synchronize();
|
||||
return *ptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
#define avpriv_atomic_int_set atomic_int_set_gcc
|
||||
static inline void atomic_int_set_gcc(volatile int *ptr, int val)
|
||||
{
|
||||
#if HAVE_ATOMIC_COMPARE_EXCHANGE
|
||||
__atomic_store_n(ptr, val, __ATOMIC_SEQ_CST);
|
||||
#else
|
||||
*ptr = val;
|
||||
__sync_synchronize();
|
||||
#endif
|
||||
}
|
||||
|
||||
#define avpriv_atomic_int_add_and_fetch atomic_int_add_and_fetch_gcc
|
||||
static inline int atomic_int_add_and_fetch_gcc(volatile int *ptr, int inc)
|
||||
{
|
||||
#if HAVE_ATOMIC_COMPARE_EXCHANGE
|
||||
return __atomic_add_fetch(ptr, inc, __ATOMIC_SEQ_CST);
|
||||
#else
|
||||
return __sync_add_and_fetch(ptr, inc);
|
||||
#endif
|
||||
}
|
||||
|
||||
#define avpriv_atomic_ptr_cas atomic_ptr_cas_gcc
|
||||
static inline void *atomic_ptr_cas_gcc(void * volatile *ptr,
|
||||
void *oldval, void *newval)
|
||||
{
|
||||
#if HAVE_SYNC_VAL_COMPARE_AND_SWAP
|
||||
#ifdef __ARMCC_VERSION
|
||||
// armcc will throw an error if ptr is not an integer type
|
||||
volatile uintptr_t *tmp = (volatile uintptr_t*)ptr;
|
||||
|
|
@ -69,10 +56,6 @@ static inline void *atomic_ptr_cas_gcc(void * volatile *ptr,
|
|||
#else
|
||||
return __sync_val_compare_and_swap(ptr, oldval, newval);
|
||||
#endif
|
||||
#else
|
||||
__atomic_compare_exchange_n(ptr, &oldval, newval, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
|
||||
return oldval;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* AVUTIL_ATOMIC_GCC_H */
|
||||
|
|
|
|||
|
|
@ -121,8 +121,7 @@
|
|||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
# define av_unused __attribute__((unused))
|
||||
#else
|
||||
# define av_unused
|
||||
|
|
@ -133,7 +132,7 @@
|
|||
* away. This is useful for variables accessed only from inline
|
||||
* assembler without the compiler being aware.
|
||||
*/
|
||||
#if AV_GCC_VERSION_AT_LEAST(3,1)
|
||||
#if AV_GCC_VERSION_AT_LEAST(3,1) || defined(__clang__)
|
||||
# define av_used __attribute__((used))
|
||||
#else
|
||||
# define av_used
|
||||
|
|
|
|||
|
|
@ -231,6 +231,29 @@ int av_strncasecmp(const char *a, const char *b, size_t n)
|
|||
return c1 - c2;
|
||||
}
|
||||
|
||||
char *av_strireplace(const char *str, const char *from, const char *to)
|
||||
{
|
||||
char *ret = NULL;
|
||||
const char *pstr2, *pstr = str;
|
||||
size_t tolen = strlen(to), fromlen = strlen(from);
|
||||
AVBPrint pbuf;
|
||||
|
||||
av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
|
||||
while ((pstr2 = av_stristr(pstr, from))) {
|
||||
av_bprint_append_data(&pbuf, pstr, pstr2 - pstr);
|
||||
pstr = pstr2 + fromlen;
|
||||
av_bprint_append_data(&pbuf, to, tolen);
|
||||
}
|
||||
av_bprint_append_data(&pbuf, pstr, strlen(pstr));
|
||||
if (!av_bprint_is_complete(&pbuf)) {
|
||||
av_bprint_finalize(&pbuf, NULL);
|
||||
} else {
|
||||
av_bprint_finalize(&pbuf, &ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
const char *av_basename(const char *path)
|
||||
{
|
||||
char *p = strrchr(path, '/');
|
||||
|
|
|
|||
|
|
@ -266,6 +266,11 @@ int av_strcasecmp(const char *a, const char *b);
|
|||
*/
|
||||
int av_strncasecmp(const char *a, const char *b, size_t n);
|
||||
|
||||
/**
|
||||
* Locale-independent strings replace.
|
||||
* @note This means only ASCII-range characters are replace
|
||||
*/
|
||||
char *av_strireplace(const char *str, const char *from, const char *to);
|
||||
|
||||
/**
|
||||
* Thread safe basename.
|
||||
|
|
|
|||
|
|
@ -118,6 +118,12 @@
|
|||
*
|
||||
* @}
|
||||
*
|
||||
* @defgroup lavu_video Video related
|
||||
*
|
||||
* @{
|
||||
*
|
||||
* @}
|
||||
*
|
||||
* @defgroup lavu_audio Audio related
|
||||
*
|
||||
* @{
|
||||
|
|
@ -337,6 +343,20 @@ FILE *av_fopen_utf8(const char *path, const char *mode);
|
|||
*/
|
||||
AVRational av_get_time_base_q(void);
|
||||
|
||||
#define AV_FOURCC_MAX_STRING_SIZE 32
|
||||
|
||||
#define av_fourcc2str(fourcc) av_fourcc_make_string((char[AV_FOURCC_MAX_STRING_SIZE]){0}, fourcc)
|
||||
|
||||
/**
|
||||
* Fill the provided buffer with a string containing a FourCC (four-character
|
||||
* code) representation.
|
||||
*
|
||||
* @param buf a buffer with size in bytes of at least AV_FOURCC_MAX_STRING_SIZE
|
||||
* @param fourcc the fourcc to represent
|
||||
* @return the buffer in input
|
||||
*/
|
||||
char *av_fourcc_make_string(char *buf, uint32_t fourcc);
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
|
|
|
|||
|
|
@ -88,7 +88,9 @@ av_find_best_pix_fmt_of_2
|
|||
av_find_info_tag
|
||||
av_find_nearest_q_idx
|
||||
av_force_cpu_flags
|
||||
av_fourcc_make_string
|
||||
av_frame_alloc
|
||||
av_frame_apply_cropping
|
||||
av_frame_clone
|
||||
av_frame_copy
|
||||
av_frame_copy_props
|
||||
|
|
@ -166,6 +168,7 @@ av_hwframe_get_buffer
|
|||
av_image_alloc
|
||||
av_image_check_sar
|
||||
av_image_check_size
|
||||
av_image_check_size2
|
||||
av_image_copy
|
||||
av_image_copy_plane
|
||||
av_image_copy_to_buffer
|
||||
|
|
@ -332,5 +335,8 @@ avutil_configuration
|
|||
avutil_license
|
||||
avutil_version
|
||||
#ifdef XP_WIN
|
||||
avpriv_emms_yasm
|
||||
avpriv_emms_asm
|
||||
#endif
|
||||
avpriv_slicethread_create
|
||||
avpriv_slicethread_execute
|
||||
avpriv_slicethread_free
|
||||
|
|
|
|||
|
|
@ -16,10 +16,10 @@
|
|||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <stdatomic.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "atomic.h"
|
||||
#include "buffer_internal.h"
|
||||
#include "common.h"
|
||||
#include "mem.h"
|
||||
|
|
@ -40,7 +40,8 @@ AVBufferRef *av_buffer_create(uint8_t *data, int size,
|
|||
buf->size = size;
|
||||
buf->free = free ? free : av_buffer_default_free;
|
||||
buf->opaque = opaque;
|
||||
buf->refcount = 1;
|
||||
|
||||
atomic_init(&buf->refcount, 1);
|
||||
|
||||
if (flags & AV_BUFFER_FLAG_READONLY)
|
||||
buf->flags |= BUFFER_FLAG_READONLY;
|
||||
|
|
@ -98,7 +99,7 @@ AVBufferRef *av_buffer_ref(AVBufferRef *buf)
|
|||
|
||||
*ret = *buf;
|
||||
|
||||
avpriv_atomic_int_add_and_fetch(&buf->buffer->refcount, 1);
|
||||
atomic_fetch_add_explicit(&buf->buffer->refcount, 1, memory_order_relaxed);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -115,7 +116,7 @@ static void buffer_replace(AVBufferRef **dst, AVBufferRef **src)
|
|||
} else
|
||||
av_freep(dst);
|
||||
|
||||
if (!avpriv_atomic_int_add_and_fetch(&b->refcount, -1)) {
|
||||
if (atomic_fetch_add_explicit(&b->refcount, -1, memory_order_acq_rel) == 1) {
|
||||
b->free(b->opaque, b->data);
|
||||
av_freep(&b);
|
||||
}
|
||||
|
|
@ -134,7 +135,7 @@ int av_buffer_is_writable(const AVBufferRef *buf)
|
|||
if (buf->buffer->flags & AV_BUFFER_FLAG_READONLY)
|
||||
return 0;
|
||||
|
||||
return avpriv_atomic_int_get(&buf->buffer->refcount) == 1;
|
||||
return atomic_load(&buf->buffer->refcount) == 1;
|
||||
}
|
||||
|
||||
void *av_buffer_get_opaque(const AVBufferRef *buf)
|
||||
|
|
@ -144,7 +145,7 @@ void *av_buffer_get_opaque(const AVBufferRef *buf)
|
|||
|
||||
int av_buffer_get_ref_count(const AVBufferRef *buf)
|
||||
{
|
||||
return buf->buffer->refcount;
|
||||
return atomic_load(&buf->buffer->refcount);
|
||||
}
|
||||
|
||||
int av_buffer_make_writable(AVBufferRef **pbuf)
|
||||
|
|
@ -191,7 +192,7 @@ int av_buffer_realloc(AVBufferRef **pbuf, int size)
|
|||
return 0;
|
||||
|
||||
if (!(buf->buffer->flags & BUFFER_FLAG_REALLOCATABLE) ||
|
||||
!av_buffer_is_writable(buf)) {
|
||||
!av_buffer_is_writable(buf) || buf->data != buf->buffer->data) {
|
||||
/* cannot realloc, allocate a new reallocable buffer and copy data */
|
||||
AVBufferRef *new = NULL;
|
||||
|
||||
|
|
@ -229,7 +230,7 @@ AVBufferPool *av_buffer_pool_init2(int size, void *opaque,
|
|||
pool->alloc2 = alloc;
|
||||
pool->pool_free = pool_free;
|
||||
|
||||
avpriv_atomic_int_set(&pool->refcount, 1);
|
||||
atomic_init(&pool->refcount, 1);
|
||||
|
||||
return pool;
|
||||
}
|
||||
|
|
@ -245,7 +246,7 @@ AVBufferPool *av_buffer_pool_init(int size, AVBufferRef* (*alloc)(int size))
|
|||
pool->size = size;
|
||||
pool->alloc = alloc ? alloc : av_buffer_alloc;
|
||||
|
||||
avpriv_atomic_int_set(&pool->refcount, 1);
|
||||
atomic_init(&pool->refcount, 1);
|
||||
|
||||
return pool;
|
||||
}
|
||||
|
|
@ -280,48 +281,10 @@ void av_buffer_pool_uninit(AVBufferPool **ppool)
|
|||
pool = *ppool;
|
||||
*ppool = NULL;
|
||||
|
||||
if (!avpriv_atomic_int_add_and_fetch(&pool->refcount, -1))
|
||||
if (atomic_fetch_add_explicit(&pool->refcount, -1, memory_order_acq_rel) == 1)
|
||||
buffer_pool_free(pool);
|
||||
}
|
||||
|
||||
#if USE_ATOMICS
|
||||
/* remove the whole buffer list from the pool and return it */
|
||||
static BufferPoolEntry *get_pool(AVBufferPool *pool)
|
||||
{
|
||||
BufferPoolEntry *cur = *(void * volatile *)&pool->pool, *last = NULL;
|
||||
|
||||
while (cur != last) {
|
||||
last = cur;
|
||||
cur = avpriv_atomic_ptr_cas((void * volatile *)&pool->pool, last, NULL);
|
||||
if (!cur)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return cur;
|
||||
}
|
||||
|
||||
static void add_to_pool(BufferPoolEntry *buf)
|
||||
{
|
||||
AVBufferPool *pool;
|
||||
BufferPoolEntry *cur, *end = buf;
|
||||
|
||||
if (!buf)
|
||||
return;
|
||||
pool = buf->pool;
|
||||
|
||||
while (end->next)
|
||||
end = end->next;
|
||||
|
||||
while (avpriv_atomic_ptr_cas((void * volatile *)&pool->pool, NULL, buf)) {
|
||||
/* pool is not empty, retrieve it and append it to our list */
|
||||
cur = get_pool(pool);
|
||||
end->next = cur;
|
||||
while (end->next)
|
||||
end = end->next;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void pool_release_buffer(void *opaque, uint8_t *data)
|
||||
{
|
||||
BufferPoolEntry *buf = opaque;
|
||||
|
|
@ -330,16 +293,12 @@ static void pool_release_buffer(void *opaque, uint8_t *data)
|
|||
if(CONFIG_MEMORY_POISONING)
|
||||
memset(buf->data, FF_MEMORY_POISON, pool->size);
|
||||
|
||||
#if USE_ATOMICS
|
||||
add_to_pool(buf);
|
||||
#else
|
||||
ff_mutex_lock(&pool->mutex);
|
||||
buf->next = pool->pool;
|
||||
pool->pool = buf;
|
||||
ff_mutex_unlock(&pool->mutex);
|
||||
#endif
|
||||
|
||||
if (!avpriv_atomic_int_add_and_fetch(&pool->refcount, -1))
|
||||
if (atomic_fetch_add_explicit(&pool->refcount, -1, memory_order_acq_rel) == 1)
|
||||
buffer_pool_free(pool);
|
||||
}
|
||||
|
||||
|
|
@ -369,11 +328,6 @@ static AVBufferRef *pool_alloc_buffer(AVBufferPool *pool)
|
|||
ret->buffer->opaque = buf;
|
||||
ret->buffer->free = pool_release_buffer;
|
||||
|
||||
#if USE_ATOMICS
|
||||
avpriv_atomic_int_add_and_fetch(&pool->refcount, 1);
|
||||
avpriv_atomic_int_add_and_fetch(&pool->nb_allocated, 1);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -382,29 +336,6 @@ AVBufferRef *av_buffer_pool_get(AVBufferPool *pool)
|
|||
AVBufferRef *ret;
|
||||
BufferPoolEntry *buf;
|
||||
|
||||
#if USE_ATOMICS
|
||||
/* check whether the pool is empty */
|
||||
buf = get_pool(pool);
|
||||
if (!buf && pool->refcount <= pool->nb_allocated) {
|
||||
av_log(NULL, AV_LOG_DEBUG, "Pool race dectected, spining to avoid overallocation and eventual OOM\n");
|
||||
while (!buf && avpriv_atomic_int_get(&pool->refcount) <= avpriv_atomic_int_get(&pool->nb_allocated))
|
||||
buf = get_pool(pool);
|
||||
}
|
||||
|
||||
if (!buf)
|
||||
return pool_alloc_buffer(pool);
|
||||
|
||||
/* keep the first entry, return the rest of the list to the pool */
|
||||
add_to_pool(buf->next);
|
||||
buf->next = NULL;
|
||||
|
||||
ret = av_buffer_create(buf->data, pool->size, pool_release_buffer,
|
||||
buf, 0);
|
||||
if (!ret) {
|
||||
add_to_pool(buf);
|
||||
return NULL;
|
||||
}
|
||||
#else
|
||||
ff_mutex_lock(&pool->mutex);
|
||||
buf = pool->pool;
|
||||
if (buf) {
|
||||
|
|
@ -418,10 +349,9 @@ AVBufferRef *av_buffer_pool_get(AVBufferPool *pool)
|
|||
ret = pool_alloc_buffer(pool);
|
||||
}
|
||||
ff_mutex_unlock(&pool->mutex);
|
||||
#endif
|
||||
|
||||
if (ret)
|
||||
avpriv_atomic_int_add_and_fetch(&pool->refcount, 1);
|
||||
atomic_fetch_add_explicit(&pool->refcount, 1, memory_order_relaxed);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -256,9 +256,10 @@ AVBufferPool *av_buffer_pool_init(int size, AVBufferRef* (*alloc)(int size));
|
|||
* @param alloc a function that will be used to allocate new buffers when the
|
||||
* pool is empty.
|
||||
* @param pool_free a function that will be called immediately before the pool
|
||||
* is freed. I.e. after av_buffer_pool_can_uninit() is called
|
||||
* by the pool and all the frames are returned to the pool and
|
||||
* freed. It is intended to uninitialize the user opaque data.
|
||||
* is freed. I.e. after av_buffer_pool_uninit() is called
|
||||
* by the caller and all the frames are returned to the pool
|
||||
* and freed. It is intended to uninitialize the user opaque
|
||||
* data.
|
||||
* @return newly created buffer pool on success, NULL on error.
|
||||
*/
|
||||
AVBufferPool *av_buffer_pool_init2(int size, void *opaque,
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
#ifndef AVUTIL_BUFFER_INTERNAL_H
|
||||
#define AVUTIL_BUFFER_INTERNAL_H
|
||||
|
||||
#include <stdatomic.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "buffer.h"
|
||||
|
|
@ -40,7 +41,7 @@ struct AVBuffer {
|
|||
/**
|
||||
* number of existing AVBufferRef instances referring to this buffer
|
||||
*/
|
||||
volatile int refcount;
|
||||
atomic_uint refcount;
|
||||
|
||||
/**
|
||||
* a callback for freeing the data
|
||||
|
|
@ -85,9 +86,7 @@ struct AVBufferPool {
|
|||
* buffers have been released, then it's safe to free the pool and all
|
||||
* the buffers in it.
|
||||
*/
|
||||
volatile int refcount;
|
||||
|
||||
volatile int nb_allocated;
|
||||
atomic_uint refcount;
|
||||
|
||||
int size;
|
||||
void *opaque;
|
||||
|
|
|
|||
|
|
@ -152,6 +152,28 @@ uint64_t av_get_channel_layout(const char *name)
|
|||
return layout;
|
||||
}
|
||||
|
||||
int av_get_extended_channel_layout(const char *name, uint64_t* channel_layout, int* nb_channels)
|
||||
{
|
||||
int nb = 0;
|
||||
char *end;
|
||||
uint64_t layout = av_get_channel_layout(name);
|
||||
|
||||
if (layout) {
|
||||
*channel_layout = layout;
|
||||
*nb_channels = av_get_channel_layout_nb_channels(layout);
|
||||
return 0;
|
||||
}
|
||||
|
||||
nb = strtol(name, &end, 10);
|
||||
if (!errno && *end == 'C' && *(end + 1) == '\0' && nb > 0 && nb < 64) {
|
||||
*channel_layout = 0;
|
||||
*nb_channels = nb;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return AVERROR(EINVAL);
|
||||
}
|
||||
|
||||
void av_bprint_channel_layout(struct AVBPrint *bp,
|
||||
int nb_channels, uint64_t channel_layout)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -131,21 +131,30 @@ enum AVMatrixEncoding {
|
|||
* 5.0(side), 5.1, 5.1(side), 7.1, 7.1(wide), downmix);
|
||||
* - the name of a single channel (FL, FR, FC, LFE, BL, BR, FLC, FRC, BC,
|
||||
* SL, SR, TC, TFL, TFC, TFR, TBL, TBC, TBR, DL, DR);
|
||||
* - a number of channels, in decimal, optionally followed by 'c', yielding
|
||||
* - a number of channels, in decimal, followed by 'c', yielding
|
||||
* the default channel layout for that number of channels (@see
|
||||
* av_get_default_channel_layout);
|
||||
* - a channel layout mask, in hexadecimal starting with "0x" (see the
|
||||
* AV_CH_* macros).
|
||||
*
|
||||
* @warning Starting from the next major bump the trailing character
|
||||
* 'c' to specify a number of channels will be required, while a
|
||||
* channel layout mask could also be specified as a decimal number
|
||||
* (if and only if not followed by "c").
|
||||
*
|
||||
* Example: "stereo+FC" = "2c+FC" = "2c+1c" = "0x7"
|
||||
*/
|
||||
uint64_t av_get_channel_layout(const char *name);
|
||||
|
||||
/**
|
||||
* Return a channel layout and the number of channels based on the specified name.
|
||||
*
|
||||
* This function is similar to (@see av_get_channel_layout), but can also parse
|
||||
* unknown channel layout specifications.
|
||||
*
|
||||
* @param[in] name channel layout specification string
|
||||
* @param[out] channel_layout parsed channel layout (0 if unknown)
|
||||
* @param[out] nb_channels number of channels
|
||||
*
|
||||
* @return 0 on success, AVERROR(EINVAL) if the parsing fails.
|
||||
*/
|
||||
int av_get_extended_channel_layout(const char *name, uint64_t* channel_layout, int* nb_channels);
|
||||
|
||||
/**
|
||||
* Return a description of a channel layout.
|
||||
* If nb_channels is <= 0, it is guessed from the channel_layout.
|
||||
|
|
|
|||
|
|
@ -16,8 +16,11 @@
|
|||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdatomic.h>
|
||||
|
||||
#include "attributes.h"
|
||||
#include "cpu.h"
|
||||
#include "cpu_internal.h"
|
||||
#include "config.h"
|
||||
|
|
@ -44,10 +47,24 @@
|
|||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
static int flags, checked;
|
||||
static atomic_int cpu_flags = ATOMIC_VAR_INIT(-1);
|
||||
|
||||
static int get_cpu_flags(void)
|
||||
{
|
||||
if (ARCH_AARCH64)
|
||||
return ff_get_cpu_flags_aarch64();
|
||||
if (ARCH_ARM)
|
||||
return ff_get_cpu_flags_arm();
|
||||
if (ARCH_PPC)
|
||||
return ff_get_cpu_flags_ppc();
|
||||
if (ARCH_X86)
|
||||
return ff_get_cpu_flags_x86();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void av_force_cpu_flags(int arg){
|
||||
if ( (arg & ( AV_CPU_FLAG_3DNOW |
|
||||
if (ARCH_X86 &&
|
||||
(arg & ( AV_CPU_FLAG_3DNOW |
|
||||
AV_CPU_FLAG_3DNOWEXT |
|
||||
AV_CPU_FLAG_MMXEXT |
|
||||
AV_CPU_FLAG_SSE |
|
||||
|
|
@ -69,33 +86,23 @@ void av_force_cpu_flags(int arg){
|
|||
arg |= AV_CPU_FLAG_MMX;
|
||||
}
|
||||
|
||||
flags = arg;
|
||||
checked = arg != -1;
|
||||
atomic_store_explicit(&cpu_flags, arg, memory_order_relaxed);
|
||||
}
|
||||
|
||||
int av_get_cpu_flags(void)
|
||||
{
|
||||
if (checked)
|
||||
return flags;
|
||||
|
||||
if (ARCH_AARCH64)
|
||||
flags = ff_get_cpu_flags_aarch64();
|
||||
if (ARCH_ARM)
|
||||
flags = ff_get_cpu_flags_arm();
|
||||
if (ARCH_PPC)
|
||||
flags = ff_get_cpu_flags_ppc();
|
||||
if (ARCH_X86)
|
||||
flags = ff_get_cpu_flags_x86();
|
||||
|
||||
checked = 1;
|
||||
int flags = atomic_load_explicit(&cpu_flags, memory_order_relaxed);
|
||||
if (flags == -1) {
|
||||
flags = get_cpu_flags();
|
||||
atomic_store_explicit(&cpu_flags, flags, memory_order_relaxed);
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
void av_set_cpu_flags_mask(int mask)
|
||||
{
|
||||
checked = 0;
|
||||
flags = av_get_cpu_flags() & mask;
|
||||
checked = 1;
|
||||
atomic_store_explicit(&cpu_flags, get_cpu_flags() & mask,
|
||||
memory_order_relaxed);
|
||||
}
|
||||
|
||||
int av_parse_cpu_flags(const char *s)
|
||||
|
|
@ -294,3 +301,17 @@ int av_cpu_count(void)
|
|||
|
||||
return nb_cpus;
|
||||
}
|
||||
|
||||
size_t av_cpu_max_align(void)
|
||||
{
|
||||
if (ARCH_AARCH64)
|
||||
return ff_get_cpu_max_align_aarch64();
|
||||
if (ARCH_ARM)
|
||||
return ff_get_cpu_max_align_arm();
|
||||
if (ARCH_PPC)
|
||||
return ff_get_cpu_max_align_ppc();
|
||||
if (ARCH_X86)
|
||||
return ff_get_cpu_max_align_x86();
|
||||
|
||||
return 8;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@
|
|||
#ifndef AVUTIL_CPU_H
|
||||
#define AVUTIL_CPU_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "attributes.h"
|
||||
|
||||
#define AV_CPU_FLAG_FORCE 0x80000000 /* force usage of selected flags (OR) */
|
||||
|
|
@ -39,6 +41,7 @@
|
|||
#define AV_CPU_FLAG_SSE3SLOW 0x20000000 ///< SSE3 supported, but usually not faster
|
||||
///< than regular MMX/SSE (e.g. Core1)
|
||||
#define AV_CPU_FLAG_SSSE3 0x0080 ///< Conroe SSSE3 functions
|
||||
#define AV_CPU_FLAG_SSSE3SLOW 0x4000000 ///< SSSE3 supported, but usually not faster
|
||||
#define AV_CPU_FLAG_ATOM 0x10000000 ///< Atom processor, some SSSE3 instructions are slower
|
||||
#define AV_CPU_FLAG_SSE4 0x0100 ///< Penryn SSE4.1 functions
|
||||
#define AV_CPU_FLAG_SSE42 0x0200 ///< Nehalem SSE4.2 functions
|
||||
|
|
@ -85,8 +88,6 @@ void av_force_cpu_flags(int flags);
|
|||
* Set a mask on flags returned by av_get_cpu_flags().
|
||||
* This function is mainly useful for testing.
|
||||
* Please use av_force_cpu_flags() and av_get_cpu_flags() instead which are more flexible
|
||||
*
|
||||
* @warning this function is not thread safe.
|
||||
*/
|
||||
attribute_deprecated void av_set_cpu_flags_mask(int mask);
|
||||
|
||||
|
|
@ -114,4 +115,15 @@ int av_parse_cpu_caps(unsigned *flags, const char *s);
|
|||
*/
|
||||
int av_cpu_count(void);
|
||||
|
||||
/**
|
||||
* Get the maximum data alignment that may be required by FFmpeg.
|
||||
*
|
||||
* Note that this is affected by the build configuration and the CPU flags mask,
|
||||
* so e.g. if the CPU supports AVX, but libavutil has been built with
|
||||
* --disable-avx or the AV_CPU_FLAG_AVX flag has been disabled through
|
||||
* av_set_cpu_flags_mask(), then this function will behave as if AVX is not
|
||||
* present.
|
||||
*/
|
||||
size_t av_cpu_max_align(void);
|
||||
|
||||
#endif /* AVUTIL_CPU_H */
|
||||
|
|
|
|||
|
|
@ -44,4 +44,9 @@ int ff_get_cpu_flags_arm(void);
|
|||
int ff_get_cpu_flags_ppc(void);
|
||||
int ff_get_cpu_flags_x86(void);
|
||||
|
||||
size_t ff_get_cpu_max_align_aarch64(void);
|
||||
size_t ff_get_cpu_max_align_arm(void);
|
||||
size_t ff_get_cpu_max_align_ppc(void);
|
||||
size_t ff_get_cpu_max_align_x86(void);
|
||||
|
||||
#endif /* AVUTIL_CPU_INTERNAL_H */
|
||||
|
|
|
|||
|
|
@ -18,6 +18,11 @@
|
|||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Display matrix
|
||||
*/
|
||||
|
||||
#ifndef AVUTIL_DISPLAY_H
|
||||
#define AVUTIL_DISPLAY_H
|
||||
|
||||
|
|
@ -25,15 +30,26 @@
|
|||
#include "common.h"
|
||||
|
||||
/**
|
||||
* @addtogroup lavu_video
|
||||
* @{
|
||||
*
|
||||
* @defgroup lavu_video_display Display transformation matrix functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup lavu_video_display
|
||||
* The display transformation matrix specifies an affine transformation that
|
||||
* should be applied to video frames for correct presentation. It is compatible
|
||||
* with the matrices stored in the ISO/IEC 14496-12 container format.
|
||||
*
|
||||
* The data is a 3x3 matrix represented as a 9-element array:
|
||||
*
|
||||
* @code{.unparsed}
|
||||
* | a b u |
|
||||
* (a, b, u, c, d, v, x, y, w) -> | c d v |
|
||||
* | x y w |
|
||||
* @endcode
|
||||
*
|
||||
* All numbers are stored in native endianness, as 16.16 fixed-point values,
|
||||
* except for u, v and w, which are stored as 2.30 fixed-point values.
|
||||
|
|
@ -41,15 +57,21 @@
|
|||
* The transformation maps a point (p, q) in the source (pre-transformation)
|
||||
* frame to the point (p', q') in the destination (post-transformation) frame as
|
||||
* follows:
|
||||
*
|
||||
* @code{.unparsed}
|
||||
* | a b u |
|
||||
* (p, q, 1) . | c d v | = z * (p', q', 1)
|
||||
* | x y w |
|
||||
* @endcode
|
||||
*
|
||||
* The transformation can also be more explicitly written in components as
|
||||
* follows:
|
||||
*
|
||||
* @code{.unparsed}
|
||||
* p' = (a * p + c * q + x) / z;
|
||||
* q' = (b * p + d * q + y) / z;
|
||||
* z = u * p + v * q + w
|
||||
* @endcode
|
||||
*/
|
||||
|
||||
/**
|
||||
|
|
@ -84,4 +106,9 @@ void av_display_rotation_set(int32_t matrix[9], double angle);
|
|||
*/
|
||||
void av_display_matrix_flip(int32_t matrix[9], int hflip, int vflip);
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* AVUTIL_DISPLAY_H */
|
||||
|
|
|
|||
|
|
@ -19,3 +19,8 @@ void ff_float_dsp_init_ppc(AVFloatDSPContext *fdsp, int strict) {}
|
|||
void ff_float_dsp_init_mips(AVFloatDSPContext *fdsp) {}
|
||||
|
||||
int av_hwframe_get_buffer(struct AVBufferRef* hwframe_ref, struct AVFrame* frame, int flags) { return 0; }
|
||||
|
||||
// cpu.c
|
||||
size_t ff_get_cpu_max_align_aarch64() { return 0; }
|
||||
size_t ff_get_cpu_max_align_arm() { return 0; }
|
||||
size_t ff_get_cpu_max_align_ppc() { return 0; }
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@
|
|||
#include "fftime.h"
|
||||
#include "avstring.h"
|
||||
#include "timer.h"
|
||||
#include "reverse.h"
|
||||
|
||||
typedef struct Parser {
|
||||
const AVClass *class;
|
||||
|
|
@ -152,9 +153,9 @@ struct AVExpr {
|
|||
e_squish, e_gauss, e_ld, e_isnan, e_isinf,
|
||||
e_mod, e_max, e_min, e_eq, e_gt, e_gte, e_lte, e_lt,
|
||||
e_pow, e_mul, e_div, e_add,
|
||||
e_last, e_st, e_while, e_taylor, e_root, e_floor, e_ceil, e_trunc,
|
||||
e_last, e_st, e_while, e_taylor, e_root, e_floor, e_ceil, e_trunc, e_round,
|
||||
e_sqrt, e_not, e_random, e_hypot, e_gcd,
|
||||
e_if, e_ifnot, e_print, e_bitand, e_bitor, e_between, e_clip
|
||||
e_if, e_ifnot, e_print, e_bitand, e_bitor, e_between, e_clip, e_atan2, e_lerp,
|
||||
} type;
|
||||
double value; // is sign in other types
|
||||
union {
|
||||
|
|
@ -188,6 +189,7 @@ static double eval_expr(Parser *p, AVExpr *e)
|
|||
case e_floor: return e->value * floor(eval_expr(p, e->param[0]));
|
||||
case e_ceil : return e->value * ceil (eval_expr(p, e->param[0]));
|
||||
case e_trunc: return e->value * trunc(eval_expr(p, e->param[0]));
|
||||
case e_round: return e->value * round(eval_expr(p, e->param[0]));
|
||||
case e_sqrt: return e->value * sqrt (eval_expr(p, e->param[0]));
|
||||
case e_not: return e->value * (eval_expr(p, e->param[0]) == 0);
|
||||
case e_if: return e->value * (eval_expr(p, e->param[0]) ? eval_expr(p, e->param[1]) :
|
||||
|
|
@ -206,6 +208,12 @@ static double eval_expr(Parser *p, AVExpr *e)
|
|||
return e->value * (d >= eval_expr(p, e->param[1]) &&
|
||||
d <= eval_expr(p, e->param[2]));
|
||||
}
|
||||
case e_lerp: {
|
||||
double v0 = eval_expr(p, e->param[0]);
|
||||
double v1 = eval_expr(p, e->param[1]);
|
||||
double f = eval_expr(p, e->param[2]);
|
||||
return v0 + (v1 - v0) * f;
|
||||
}
|
||||
case e_print: {
|
||||
double x = eval_expr(p, e->param[0]);
|
||||
int level = e->param[1] ? av_clip(eval_expr(p, e->param[1]), INT_MIN, INT_MAX) : AV_LOG_INFO;
|
||||
|
|
@ -305,6 +313,7 @@ static double eval_expr(Parser *p, AVExpr *e)
|
|||
case e_last:return e->value * d2;
|
||||
case e_st : return e->value * (p->var[av_clip(d, 0, VARS-1)]= d2);
|
||||
case e_hypot:return e->value * hypot(d, d2);
|
||||
case e_atan2:return e->value * atan2(d, d2);
|
||||
case e_bitand: return isnan(d) || isnan(d2) ? NAN : e->value * ((long int)d & (long int)d2);
|
||||
case e_bitor: return isnan(d) || isnan(d2) ? NAN : e->value * ((long int)d | (long int)d2);
|
||||
}
|
||||
|
|
@ -438,6 +447,7 @@ static int parse_primary(AVExpr **e, Parser *p)
|
|||
else if (strmatch(next, "floor" )) d->type = e_floor;
|
||||
else if (strmatch(next, "ceil" )) d->type = e_ceil;
|
||||
else if (strmatch(next, "trunc" )) d->type = e_trunc;
|
||||
else if (strmatch(next, "round" )) d->type = e_round;
|
||||
else if (strmatch(next, "sqrt" )) d->type = e_sqrt;
|
||||
else if (strmatch(next, "not" )) d->type = e_not;
|
||||
else if (strmatch(next, "pow" )) d->type = e_pow;
|
||||
|
|
@ -451,6 +461,8 @@ static int parse_primary(AVExpr **e, Parser *p)
|
|||
else if (strmatch(next, "bitor" )) d->type = e_bitor;
|
||||
else if (strmatch(next, "between"))d->type = e_between;
|
||||
else if (strmatch(next, "clip" )) d->type = e_clip;
|
||||
else if (strmatch(next, "atan2" )) d->type = e_atan2;
|
||||
else if (strmatch(next, "lerp" )) d->type = e_lerp;
|
||||
else {
|
||||
for (i=0; p->func1_names && p->func1_names[i]; i++) {
|
||||
if (strmatch(next, p->func1_names[i])) {
|
||||
|
|
@ -634,6 +646,7 @@ static int verify_expr(AVExpr *e)
|
|||
case e_floor:
|
||||
case e_ceil:
|
||||
case e_trunc:
|
||||
case e_round:
|
||||
case e_sqrt:
|
||||
case e_not:
|
||||
case e_random:
|
||||
|
|
@ -648,6 +661,7 @@ static int verify_expr(AVExpr *e)
|
|||
&& (!e->param[2] || verify_expr(e->param[2]));
|
||||
case e_between:
|
||||
case e_clip:
|
||||
case e_lerp:
|
||||
return verify_expr(e->param[0]) &&
|
||||
verify_expr(e->param[1]) &&
|
||||
verify_expr(e->param[2]);
|
||||
|
|
|
|||
|
|
@ -40,6 +40,14 @@ static void vector_fmac_scalar_c(float *dst, const float *src, float mul,
|
|||
dst[i] += src[i] * mul;
|
||||
}
|
||||
|
||||
static void vector_dmac_scalar_c(double *dst, const double *src, double mul,
|
||||
int len)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < len; i++)
|
||||
dst[i] += src[i] * mul;
|
||||
}
|
||||
|
||||
static void vector_fmul_scalar_c(float *dst, const float *src, float mul,
|
||||
int len)
|
||||
{
|
||||
|
|
@ -125,6 +133,7 @@ av_cold AVFloatDSPContext *avpriv_float_dsp_alloc(int bit_exact)
|
|||
fdsp->vector_fmul = vector_fmul_c;
|
||||
fdsp->vector_fmac_scalar = vector_fmac_scalar_c;
|
||||
fdsp->vector_fmul_scalar = vector_fmul_scalar_c;
|
||||
fdsp->vector_dmac_scalar = vector_dmac_scalar_c;
|
||||
fdsp->vector_dmul_scalar = vector_dmul_scalar_c;
|
||||
fdsp->vector_fmul_window = vector_fmul_window_c;
|
||||
fdsp->vector_fmul_add = vector_fmul_add_c;
|
||||
|
|
|
|||
|
|
@ -54,6 +54,22 @@ typedef struct AVFloatDSPContext {
|
|||
void (*vector_fmac_scalar)(float *dst, const float *src, float mul,
|
||||
int len);
|
||||
|
||||
/**
|
||||
* Multiply a vector of doubles by a scalar double and add to
|
||||
* destination vector. Source and destination vectors must
|
||||
* overlap exactly or not at all.
|
||||
*
|
||||
* @param dst result vector
|
||||
* constraints: 32-byte aligned
|
||||
* @param src input vector
|
||||
* constraints: 32-byte aligned
|
||||
* @param mul scalar value
|
||||
* @param len length of vector
|
||||
* constraints: multiple of 16
|
||||
*/
|
||||
void (*vector_dmac_scalar)(double *dst, const double *src, double mul,
|
||||
int len);
|
||||
|
||||
/**
|
||||
* Multiply a vector of floats by a scalar float. Source and
|
||||
* destination vectors must overlap exactly or not at all.
|
||||
|
|
|
|||
|
|
@ -26,6 +26,11 @@
|
|||
#include "mem.h"
|
||||
#include "samplefmt.h"
|
||||
|
||||
|
||||
static AVFrameSideData *frame_new_side_data(AVFrame *frame,
|
||||
enum AVFrameSideDataType type,
|
||||
AVBufferRef *buf);
|
||||
|
||||
MAKE_ACCESSORS(AVFrame, frame, int64_t, best_effort_timestamp)
|
||||
MAKE_ACCESSORS(AVFrame, frame, int64_t, pkt_duration)
|
||||
MAKE_ACCESSORS(AVFrame, frame, int64_t, pkt_pos)
|
||||
|
|
@ -176,6 +181,9 @@ static int get_video_buffer(AVFrame *frame, int align)
|
|||
return ret;
|
||||
|
||||
if (!frame->linesize[0]) {
|
||||
if (align <= 0)
|
||||
align = 32; /* STRIDE_ALIGN. Should be av_cpu_max_align() */
|
||||
|
||||
for(i=1; i<=align; i+=i) {
|
||||
ret = av_image_fill_linesizes(frame->linesize, frame->format,
|
||||
FFALIGN(frame->width, i));
|
||||
|
|
@ -292,6 +300,10 @@ static int frame_copy_props(AVFrame *dst, const AVFrame *src, int force_copy)
|
|||
dst->key_frame = src->key_frame;
|
||||
dst->pict_type = src->pict_type;
|
||||
dst->sample_aspect_ratio = src->sample_aspect_ratio;
|
||||
dst->crop_top = src->crop_top;
|
||||
dst->crop_bottom = src->crop_bottom;
|
||||
dst->crop_left = src->crop_left;
|
||||
dst->crop_right = src->crop_right;
|
||||
dst->pts = src->pts;
|
||||
dst->repeat_pict = src->repeat_pict;
|
||||
dst->interlaced_frame = src->interlaced_frame;
|
||||
|
|
@ -344,18 +356,11 @@ FF_ENABLE_DEPRECATION_WARNINGS
|
|||
}
|
||||
memcpy(sd_dst->data, sd_src->data, sd_src->size);
|
||||
} else {
|
||||
sd_dst = av_frame_new_side_data(dst, sd_src->type, 0);
|
||||
sd_dst = frame_new_side_data(dst, sd_src->type, av_buffer_ref(sd_src->buf));
|
||||
if (!sd_dst) {
|
||||
wipe_side_data(dst);
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
sd_dst->buf = av_buffer_ref(sd_src->buf);
|
||||
if (!sd_dst->buf) {
|
||||
wipe_side_data(dst);
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
sd_dst->data = sd_dst->buf->data;
|
||||
sd_dst->size = sd_dst->buf->size;
|
||||
}
|
||||
av_dict_copy(&sd_dst->metadata, sd_src->metadata, 0);
|
||||
}
|
||||
|
|
@ -377,6 +382,13 @@ FF_DISABLE_DEPRECATION_WARNINGS
|
|||
FF_ENABLE_DEPRECATION_WARNINGS
|
||||
#endif
|
||||
|
||||
av_buffer_unref(&dst->opaque_ref);
|
||||
if (src->opaque_ref) {
|
||||
dst->opaque_ref = av_buffer_ref(src->opaque_ref);
|
||||
if (!dst->opaque_ref)
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -511,6 +523,8 @@ void av_frame_unref(AVFrame *frame)
|
|||
|
||||
av_buffer_unref(&frame->hw_frames_ctx);
|
||||
|
||||
av_buffer_unref(&frame->opaque_ref);
|
||||
|
||||
get_frame_defaults(frame);
|
||||
}
|
||||
|
||||
|
|
@ -622,40 +636,47 @@ AVBufferRef *av_frame_get_plane_buffer(AVFrame *frame, int plane)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
AVFrameSideData *av_frame_new_side_data(AVFrame *frame,
|
||||
enum AVFrameSideDataType type,
|
||||
int size)
|
||||
static AVFrameSideData *frame_new_side_data(AVFrame *frame,
|
||||
enum AVFrameSideDataType type,
|
||||
AVBufferRef *buf)
|
||||
{
|
||||
AVFrameSideData *ret, **tmp;
|
||||
|
||||
if (frame->nb_side_data > INT_MAX / sizeof(*frame->side_data) - 1)
|
||||
if (!buf)
|
||||
return NULL;
|
||||
|
||||
if (frame->nb_side_data > INT_MAX / sizeof(*frame->side_data) - 1)
|
||||
goto fail;
|
||||
|
||||
tmp = av_realloc(frame->side_data,
|
||||
(frame->nb_side_data + 1) * sizeof(*frame->side_data));
|
||||
if (!tmp)
|
||||
return NULL;
|
||||
goto fail;
|
||||
frame->side_data = tmp;
|
||||
|
||||
ret = av_mallocz(sizeof(*ret));
|
||||
if (!ret)
|
||||
return NULL;
|
||||
goto fail;
|
||||
|
||||
if (size > 0) {
|
||||
ret->buf = av_buffer_alloc(size);
|
||||
if (!ret->buf) {
|
||||
av_freep(&ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret->data = ret->buf->data;
|
||||
ret->size = size;
|
||||
}
|
||||
ret->buf = buf;
|
||||
ret->data = ret->buf->data;
|
||||
ret->size = buf->size;
|
||||
ret->type = type;
|
||||
|
||||
frame->side_data[frame->nb_side_data++] = ret;
|
||||
|
||||
return ret;
|
||||
fail:
|
||||
av_buffer_unref(&buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
AVFrameSideData *av_frame_new_side_data(AVFrame *frame,
|
||||
enum AVFrameSideDataType type,
|
||||
int size)
|
||||
{
|
||||
|
||||
return frame_new_side_data(frame, type, av_buffer_alloc(size));
|
||||
}
|
||||
|
||||
AVFrameSideData *av_frame_get_side_data(const AVFrame *frame,
|
||||
|
|
@ -723,7 +744,7 @@ int av_frame_copy(AVFrame *dst, const AVFrame *src)
|
|||
|
||||
if (dst->width > 0 && dst->height > 0)
|
||||
return frame_copy_video(dst, src);
|
||||
else if (dst->nb_samples > 0 && dst->channel_layout)
|
||||
else if (dst->nb_samples > 0 && dst->channels > 0)
|
||||
return frame_copy_audio(dst, src);
|
||||
|
||||
return AVERROR(EINVAL);
|
||||
|
|
@ -758,7 +779,109 @@ const char *av_frame_side_data_name(enum AVFrameSideDataType type)
|
|||
case AV_FRAME_DATA_SKIP_SAMPLES: return "Skip samples";
|
||||
case AV_FRAME_DATA_AUDIO_SERVICE_TYPE: return "Audio service type";
|
||||
case AV_FRAME_DATA_MASTERING_DISPLAY_METADATA: return "Mastering display metadata";
|
||||
case AV_FRAME_DATA_CONTENT_LIGHT_LEVEL: return "Content light level metadata";
|
||||
case AV_FRAME_DATA_GOP_TIMECODE: return "GOP timecode";
|
||||
case AV_FRAME_DATA_ICC_PROFILE: return "ICC profile";
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int calc_cropping_offsets(size_t offsets[4], const AVFrame *frame,
|
||||
const AVPixFmtDescriptor *desc)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = 0; frame->data[i]; i++) {
|
||||
const AVComponentDescriptor *comp = NULL;
|
||||
int shift_x = (i == 1 || i == 2) ? desc->log2_chroma_w : 0;
|
||||
int shift_y = (i == 1 || i == 2) ? desc->log2_chroma_h : 0;
|
||||
|
||||
if (desc->flags & (AV_PIX_FMT_FLAG_PAL | AV_PIX_FMT_FLAG_PSEUDOPAL) && i == 1) {
|
||||
offsets[i] = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
/* find any component descriptor for this plane */
|
||||
for (j = 0; j < desc->nb_components; j++) {
|
||||
if (desc->comp[j].plane == i) {
|
||||
comp = &desc->comp[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!comp)
|
||||
return AVERROR_BUG;
|
||||
|
||||
offsets[i] = (frame->crop_top >> shift_y) * frame->linesize[i] +
|
||||
(frame->crop_left >> shift_x) * comp->step;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int av_frame_apply_cropping(AVFrame *frame, int flags)
|
||||
{
|
||||
const AVPixFmtDescriptor *desc;
|
||||
size_t offsets[4];
|
||||
int i;
|
||||
|
||||
if (!(frame->width > 0 && frame->height > 0))
|
||||
return AVERROR(EINVAL);
|
||||
|
||||
if (frame->crop_left >= INT_MAX - frame->crop_right ||
|
||||
frame->crop_top >= INT_MAX - frame->crop_bottom ||
|
||||
(frame->crop_left + frame->crop_right) >= frame->width ||
|
||||
(frame->crop_top + frame->crop_bottom) >= frame->height)
|
||||
return AVERROR(ERANGE);
|
||||
|
||||
desc = av_pix_fmt_desc_get(frame->format);
|
||||
if (!desc)
|
||||
return AVERROR_BUG;
|
||||
|
||||
/* Apply just the right/bottom cropping for hwaccel formats. Bitstream
|
||||
* formats cannot be easily handled here either (and corresponding decoders
|
||||
* should not export any cropping anyway), so do the same for those as well.
|
||||
* */
|
||||
if (desc->flags & (AV_PIX_FMT_FLAG_BITSTREAM | AV_PIX_FMT_FLAG_HWACCEL)) {
|
||||
frame->width -= frame->crop_right;
|
||||
frame->height -= frame->crop_bottom;
|
||||
frame->crop_right = 0;
|
||||
frame->crop_bottom = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* calculate the offsets for each plane */
|
||||
calc_cropping_offsets(offsets, frame, desc);
|
||||
|
||||
/* adjust the offsets to avoid breaking alignment */
|
||||
if (!(flags & AV_FRAME_CROP_UNALIGNED)) {
|
||||
int log2_crop_align = frame->crop_left ? ff_ctz(frame->crop_left) : INT_MAX;
|
||||
int min_log2_align = INT_MAX;
|
||||
|
||||
for (i = 0; frame->data[i]; i++) {
|
||||
int log2_align = offsets[i] ? ff_ctz(offsets[i]) : INT_MAX;
|
||||
min_log2_align = FFMIN(log2_align, min_log2_align);
|
||||
}
|
||||
|
||||
/* we assume, and it should always be true, that the data alignment is
|
||||
* related to the cropping alignment by a constant power-of-2 factor */
|
||||
if (log2_crop_align < min_log2_align)
|
||||
return AVERROR_BUG;
|
||||
|
||||
if (min_log2_align < 5) {
|
||||
frame->crop_left &= ~((1 << (5 + log2_crop_align - min_log2_align)) - 1);
|
||||
calc_cropping_offsets(offsets, frame, desc);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; frame->data[i]; i++)
|
||||
frame->data[i] += offsets[i];
|
||||
|
||||
frame->width -= (frame->crop_left + frame->crop_right);
|
||||
frame->height -= (frame->crop_top + frame->crop_bottom);
|
||||
frame->crop_left = 0;
|
||||
frame->crop_right = 0;
|
||||
frame->crop_top = 0;
|
||||
frame->crop_bottom = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
#ifndef AVUTIL_FRAME_H
|
||||
#define AVUTIL_FRAME_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "avutil.h"
|
||||
|
|
@ -120,7 +121,26 @@ enum AVFrameSideDataType {
|
|||
* The GOP timecode in 25 bit timecode format. Data format is 64-bit integer.
|
||||
* This is set on the first frame of a GOP that has a temporal reference of 0.
|
||||
*/
|
||||
AV_FRAME_DATA_GOP_TIMECODE
|
||||
AV_FRAME_DATA_GOP_TIMECODE,
|
||||
|
||||
/**
|
||||
* The data represents the AVSphericalMapping structure defined in
|
||||
* libavutil/spherical.h.
|
||||
*/
|
||||
AV_FRAME_DATA_SPHERICAL,
|
||||
|
||||
/**
|
||||
* Content light level (based on CTA-861.3). This payload contains data in
|
||||
* the form of the AVContentLightMetadata struct.
|
||||
*/
|
||||
AV_FRAME_DATA_CONTENT_LIGHT_LEVEL,
|
||||
|
||||
/**
|
||||
* The data contains an ICC profile as an opaque octet buffer following the
|
||||
* format described by ISO 15076-1 with an optional name defined in the
|
||||
* metadata key entry "name".
|
||||
*/
|
||||
AV_FRAME_DATA_ICC_PROFILE,
|
||||
};
|
||||
|
||||
enum AVActiveFormatDescription {
|
||||
|
|
@ -173,9 +193,6 @@ typedef struct AVFrameSideData {
|
|||
*
|
||||
* sizeof(AVFrame) is not a part of the public ABI, so new fields may be added
|
||||
* to the end with a minor bump.
|
||||
* Similarly fields that are marked as to be only accessed by
|
||||
* av_opt_ptr() can be reordered. This allows 2 forks to add fields
|
||||
* without breaking compatibility with each other.
|
||||
*
|
||||
* Fields can be accessed through AVOptions, the name string used, matches the
|
||||
* C structure field name for fields accessible through AVOptions. The AVClass
|
||||
|
|
@ -231,9 +248,18 @@ typedef struct AVFrame {
|
|||
uint8_t **extended_data;
|
||||
|
||||
/**
|
||||
* width and height of the video frame
|
||||
* @name Video dimensions
|
||||
* Video frames only. The coded dimensions (in pixels) of the video frame,
|
||||
* i.e. the size of the rectangle that contains some well-defined values.
|
||||
*
|
||||
* @note The part of the frame intended for display/presentation is further
|
||||
* restricted by the @ref cropping "Cropping rectangle".
|
||||
* @{
|
||||
*/
|
||||
int width, height;
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* number of audio samples (per channel) described by this frame
|
||||
|
|
@ -414,8 +440,6 @@ typedef struct AVFrame {
|
|||
|
||||
/**
|
||||
* MPEG vs JPEG YUV range.
|
||||
* It must be accessed using av_frame_get_color_range() and
|
||||
* av_frame_set_color_range().
|
||||
* - encoding: Set by user
|
||||
* - decoding: Set by libavcodec
|
||||
*/
|
||||
|
|
@ -427,8 +451,6 @@ typedef struct AVFrame {
|
|||
|
||||
/**
|
||||
* YUV colorspace type.
|
||||
* It must be accessed using av_frame_get_colorspace() and
|
||||
* av_frame_set_colorspace().
|
||||
* - encoding: Set by user
|
||||
* - decoding: Set by libavcodec
|
||||
*/
|
||||
|
|
@ -438,8 +460,6 @@ typedef struct AVFrame {
|
|||
|
||||
/**
|
||||
* frame timestamp estimated using various heuristics, in stream time base
|
||||
* Code outside libavutil should access this field using:
|
||||
* av_frame_get_best_effort_timestamp(frame)
|
||||
* - encoding: unused
|
||||
* - decoding: set by libavcodec, read by user.
|
||||
*/
|
||||
|
|
@ -447,8 +467,6 @@ typedef struct AVFrame {
|
|||
|
||||
/**
|
||||
* reordered pos from the last AVPacket that has been input into the decoder
|
||||
* Code outside libavutil should access this field using:
|
||||
* av_frame_get_pkt_pos(frame)
|
||||
* - encoding: unused
|
||||
* - decoding: Read by user.
|
||||
*/
|
||||
|
|
@ -457,8 +475,6 @@ typedef struct AVFrame {
|
|||
/**
|
||||
* duration of the corresponding packet, expressed in
|
||||
* AVStream->time_base units, 0 if unknown.
|
||||
* Code outside libavutil should access this field using:
|
||||
* av_frame_get_pkt_duration(frame)
|
||||
* - encoding: unused
|
||||
* - decoding: Read by user.
|
||||
*/
|
||||
|
|
@ -466,8 +482,6 @@ typedef struct AVFrame {
|
|||
|
||||
/**
|
||||
* metadata.
|
||||
* Code outside libavutil should access this field using:
|
||||
* av_frame_get_metadata(frame)
|
||||
* - encoding: Set by user.
|
||||
* - decoding: Set by libavcodec.
|
||||
*/
|
||||
|
|
@ -477,8 +491,6 @@ typedef struct AVFrame {
|
|||
* decode error flags of the frame, set to a combination of
|
||||
* FF_DECODE_ERROR_xxx flags if the decoder produced a frame, but there
|
||||
* were errors during the decoding.
|
||||
* Code outside libavutil should access this field using:
|
||||
* av_frame_get_decode_error_flags(frame)
|
||||
* - encoding: unused
|
||||
* - decoding: set by libavcodec, read by user.
|
||||
*/
|
||||
|
|
@ -488,8 +500,6 @@ typedef struct AVFrame {
|
|||
|
||||
/**
|
||||
* number of audio channels, only used for audio.
|
||||
* Code outside libavutil should access this field using:
|
||||
* av_frame_get_channels(frame)
|
||||
* - encoding: unused
|
||||
* - decoding: Read by user.
|
||||
*/
|
||||
|
|
@ -497,8 +507,7 @@ typedef struct AVFrame {
|
|||
|
||||
/**
|
||||
* size of the corresponding packet containing the compressed
|
||||
* frame. It must be accessed using av_frame_get_pkt_size() and
|
||||
* av_frame_set_pkt_size().
|
||||
* frame.
|
||||
* It is set to a negative value if unknown.
|
||||
* - encoding: unused
|
||||
* - decoding: set by libavcodec, read by user.
|
||||
|
|
@ -508,13 +517,11 @@ typedef struct AVFrame {
|
|||
#if FF_API_FRAME_QP
|
||||
/**
|
||||
* QP table
|
||||
* Not to be accessed directly from outside libavutil
|
||||
*/
|
||||
attribute_deprecated
|
||||
int8_t *qscale_table;
|
||||
/**
|
||||
* QP store stride
|
||||
* Not to be accessed directly from outside libavutil
|
||||
*/
|
||||
attribute_deprecated
|
||||
int qstride;
|
||||
|
|
@ -522,9 +529,6 @@ typedef struct AVFrame {
|
|||
attribute_deprecated
|
||||
int qscale_type;
|
||||
|
||||
/**
|
||||
* Not to be accessed directly from outside libavutil
|
||||
*/
|
||||
AVBufferRef *qp_table_buf;
|
||||
#endif
|
||||
/**
|
||||
|
|
@ -532,12 +536,38 @@ typedef struct AVFrame {
|
|||
* AVHWFramesContext describing the frame.
|
||||
*/
|
||||
AVBufferRef *hw_frames_ctx;
|
||||
|
||||
/**
|
||||
* AVBufferRef for free use by the API user. FFmpeg will never check the
|
||||
* contents of the buffer ref. FFmpeg calls av_buffer_unref() on it when
|
||||
* the frame is unreferenced. av_frame_copy_props() calls create a new
|
||||
* reference with av_buffer_ref() for the target frame's opaque_ref field.
|
||||
*
|
||||
* This is unrelated to the opaque field, although it serves a similar
|
||||
* purpose.
|
||||
*/
|
||||
AVBufferRef *opaque_ref;
|
||||
|
||||
/**
|
||||
* @anchor cropping
|
||||
* @name Cropping
|
||||
* Video frames only. The number of pixels to discard from the the
|
||||
* top/bottom/left/right border of the frame to obtain the sub-rectangle of
|
||||
* the frame intended for presentation.
|
||||
* @{
|
||||
*/
|
||||
size_t crop_top;
|
||||
size_t crop_bottom;
|
||||
size_t crop_left;
|
||||
size_t crop_right;
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
} AVFrame;
|
||||
|
||||
/**
|
||||
* Accessors for some AVFrame fields.
|
||||
* The position of these field in the structure is not part of the ABI,
|
||||
* they should not be accessed directly outside libavutil.
|
||||
* Accessors for some AVFrame fields. These used to be provided for ABI
|
||||
* compatibility, and do not need to be used anymore.
|
||||
*/
|
||||
int64_t av_frame_get_best_effort_timestamp(const AVFrame *frame);
|
||||
void av_frame_set_best_effort_timestamp(AVFrame *frame, int64_t val);
|
||||
|
|
@ -651,7 +681,9 @@ void av_frame_move_ref(AVFrame *dst, AVFrame *src);
|
|||
* cases.
|
||||
*
|
||||
* @param frame frame in which to store the new buffers.
|
||||
* @param align required buffer size alignment
|
||||
* @param align Required buffer size alignment. If equal to 0, alignment will be
|
||||
* chosen automatically for the current CPU. It is highly
|
||||
* recommended to pass 0 here unless you know what you are doing.
|
||||
*
|
||||
* @return 0 on success, a negative AVERROR on error.
|
||||
*/
|
||||
|
|
@ -743,6 +775,40 @@ AVFrameSideData *av_frame_get_side_data(const AVFrame *frame,
|
|||
*/
|
||||
void av_frame_remove_side_data(AVFrame *frame, enum AVFrameSideDataType type);
|
||||
|
||||
|
||||
/**
|
||||
* Flags for frame cropping.
|
||||
*/
|
||||
enum {
|
||||
/**
|
||||
* Apply the maximum possible cropping, even if it requires setting the
|
||||
* AVFrame.data[] entries to unaligned pointers. Passing unaligned data
|
||||
* to FFmpeg API is generally not allowed, and causes undefined behavior
|
||||
* (such as crashes). You can pass unaligned data only to FFmpeg APIs that
|
||||
* are explicitly documented to accept it. Use this flag only if you
|
||||
* absolutely know what you are doing.
|
||||
*/
|
||||
AV_FRAME_CROP_UNALIGNED = 1 << 0,
|
||||
};
|
||||
|
||||
/**
|
||||
* Crop the given video AVFrame according to its crop_left/crop_top/crop_right/
|
||||
* crop_bottom fields. If cropping is successful, the function will adjust the
|
||||
* data pointers and the width/height fields, and set the crop fields to 0.
|
||||
*
|
||||
* In all cases, the cropping boundaries will be rounded to the inherent
|
||||
* alignment of the pixel format. In some cases, such as for opaque hwaccel
|
||||
* formats, the left/top cropping is ignored. The crop fields are set to 0 even
|
||||
* if the cropping was rounded or ignored.
|
||||
*
|
||||
* @param frame the frame which should be cropped
|
||||
* @param flags Some combination of AV_FRAME_CROP_* flags, or 0.
|
||||
*
|
||||
* @return >= 0 on success, a negative AVERROR on error. If the cropping fields
|
||||
* were invalid, AVERROR(ERANGE) is returned, and nothing is changed.
|
||||
*/
|
||||
int av_frame_apply_cropping(AVFrame *frame, int flags);
|
||||
|
||||
/**
|
||||
* @return a string identifying the side data type
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -30,6 +30,10 @@ enum AVHWDeviceType {
|
|||
AV_HWDEVICE_TYPE_VAAPI,
|
||||
AV_HWDEVICE_TYPE_DXVA2,
|
||||
AV_HWDEVICE_TYPE_QSV,
|
||||
AV_HWDEVICE_TYPE_VIDEOTOOLBOX,
|
||||
AV_HWDEVICE_TYPE_NONE,
|
||||
AV_HWDEVICE_TYPE_D3D11VA,
|
||||
AV_HWDEVICE_TYPE_DRM,
|
||||
};
|
||||
|
||||
typedef struct AVHWDeviceInternal AVHWDeviceInternal;
|
||||
|
|
@ -223,10 +227,36 @@ typedef struct AVHWFramesContext {
|
|||
} AVHWFramesContext;
|
||||
|
||||
/**
|
||||
* Allocate an AVHWDeviceContext for a given pixel format.
|
||||
* Look up an AVHWDeviceType by name.
|
||||
*
|
||||
* @param format a hwaccel pixel format (AV_PIX_FMT_FLAG_HWACCEL must be set
|
||||
* on the corresponding format descriptor)
|
||||
* @param name String name of the device type (case-insensitive).
|
||||
* @return The type from enum AVHWDeviceType, or AV_HWDEVICE_TYPE_NONE if
|
||||
* not found.
|
||||
*/
|
||||
enum AVHWDeviceType av_hwdevice_find_type_by_name(const char *name);
|
||||
|
||||
/** Get the string name of an AVHWDeviceType.
|
||||
*
|
||||
* @param type Type from enum AVHWDeviceType.
|
||||
* @return Pointer to a static string containing the name, or NULL if the type
|
||||
* is not valid.
|
||||
*/
|
||||
const char *av_hwdevice_get_type_name(enum AVHWDeviceType type);
|
||||
|
||||
/**
|
||||
* Iterate over supported device types.
|
||||
*
|
||||
* @param type AV_HWDEVICE_TYPE_NONE initially, then the previous type
|
||||
* returned by this function in subsequent iterations.
|
||||
* @return The next usable device type from enum AVHWDeviceType, or
|
||||
* AV_HWDEVICE_TYPE_NONE if there are no more.
|
||||
*/
|
||||
enum AVHWDeviceType av_hwdevice_iterate_types(enum AVHWDeviceType prev);
|
||||
|
||||
/**
|
||||
* Allocate an AVHWDeviceContext for a given hardware type.
|
||||
*
|
||||
* @param type the type of the hardware device to allocate.
|
||||
* @return a reference to the newly created AVHWDeviceContext on success or NULL
|
||||
* on failure.
|
||||
*/
|
||||
|
|
@ -270,6 +300,32 @@ int av_hwdevice_ctx_init(AVBufferRef *ref);
|
|||
int av_hwdevice_ctx_create(AVBufferRef **device_ctx, enum AVHWDeviceType type,
|
||||
const char *device, AVDictionary *opts, int flags);
|
||||
|
||||
/**
|
||||
* Create a new device of the specified type from an existing device.
|
||||
*
|
||||
* If the source device is a device of the target type or was originally
|
||||
* derived from such a device (possibly through one or more intermediate
|
||||
* devices of other types), then this will return a reference to the
|
||||
* existing device of the same type as is requested.
|
||||
*
|
||||
* Otherwise, it will attempt to derive a new device from the given source
|
||||
* device. If direct derivation to the new type is not implemented, it will
|
||||
* attempt the same derivation from each ancestor of the source device in
|
||||
* turn looking for an implemented derivation method.
|
||||
*
|
||||
* @param dst_ctx On success, a reference to the newly-created
|
||||
* AVHWDeviceContext.
|
||||
* @param type The type of the new device to create.
|
||||
* @param src_ctx A reference to an existing AVHWDeviceContext which will be
|
||||
* used to create the new device.
|
||||
* @param flags Currently unused; should be set to zero.
|
||||
* @return Zero on success, a negative AVERROR code on failure.
|
||||
*/
|
||||
int av_hwdevice_ctx_create_derived(AVBufferRef **dst_ctx,
|
||||
enum AVHWDeviceType type,
|
||||
AVBufferRef *src_ctx, int flags);
|
||||
|
||||
|
||||
/**
|
||||
* Allocate an AVHWFramesContext tied to a given device context.
|
||||
*
|
||||
|
|
@ -318,6 +374,14 @@ int av_hwframe_get_buffer(AVBufferRef *hwframe_ctx, AVFrame *frame, int flags);
|
|||
* If dst->format is set, then this format will be used, otherwise (when
|
||||
* dst->format is AV_PIX_FMT_NONE) the first acceptable format will be chosen.
|
||||
*
|
||||
* The two frames must have matching allocated dimensions (i.e. equal to
|
||||
* AVHWFramesContext.width/height), since not all device types support
|
||||
* transferring a sub-rectangle of the whole surface. The display dimensions
|
||||
* (i.e. AVFrame.width/height) may be smaller than the allocated dimensions, but
|
||||
* also have to be equal for both frames. When the display dimensions are
|
||||
* smaller than the allocated dimensions, the content of the padding in the
|
||||
* destination frame is unspecified.
|
||||
*
|
||||
* @param dst the destination frame. dst is not touched on failure.
|
||||
* @param src the source frame.
|
||||
* @param flags currently unused, should be set to zero
|
||||
|
|
@ -410,7 +474,7 @@ void *av_hwdevice_hwconfig_alloc(AVBufferRef *device_ctx);
|
|||
* configuration is provided, returns the maximum possible capabilities
|
||||
* of the device.
|
||||
*
|
||||
* @param device_ctx a reference to the associated AVHWDeviceContext.
|
||||
* @param ref a reference to the associated AVHWDeviceContext.
|
||||
* @param hwconfig a filled HW-specific configuration structure, or NULL
|
||||
* to return the maximum possible capabilities of the device.
|
||||
* @return AVHWFramesConstraints structure describing the constraints
|
||||
|
|
@ -426,4 +490,93 @@ AVHWFramesConstraints *av_hwdevice_get_hwframe_constraints(AVBufferRef *ref,
|
|||
*/
|
||||
void av_hwframe_constraints_free(AVHWFramesConstraints **constraints);
|
||||
|
||||
|
||||
/**
|
||||
* Flags to apply to frame mappings.
|
||||
*/
|
||||
enum {
|
||||
/**
|
||||
* The mapping must be readable.
|
||||
*/
|
||||
AV_HWFRAME_MAP_READ = 1 << 0,
|
||||
/**
|
||||
* The mapping must be writeable.
|
||||
*/
|
||||
AV_HWFRAME_MAP_WRITE = 1 << 1,
|
||||
/**
|
||||
* The mapped frame will be overwritten completely in subsequent
|
||||
* operations, so the current frame data need not be loaded. Any values
|
||||
* which are not overwritten are unspecified.
|
||||
*/
|
||||
AV_HWFRAME_MAP_OVERWRITE = 1 << 2,
|
||||
/**
|
||||
* The mapping must be direct. That is, there must not be any copying in
|
||||
* the map or unmap steps. Note that performance of direct mappings may
|
||||
* be much lower than normal memory.
|
||||
*/
|
||||
AV_HWFRAME_MAP_DIRECT = 1 << 3,
|
||||
};
|
||||
|
||||
/**
|
||||
* Map a hardware frame.
|
||||
*
|
||||
* This has a number of different possible effects, depending on the format
|
||||
* and origin of the src and dst frames. On input, src should be a usable
|
||||
* frame with valid buffers and dst should be blank (typically as just created
|
||||
* by av_frame_alloc()). src should have an associated hwframe context, and
|
||||
* dst may optionally have a format and associated hwframe context.
|
||||
*
|
||||
* If src was created by mapping a frame from the hwframe context of dst,
|
||||
* then this function undoes the mapping - dst is replaced by a reference to
|
||||
* the frame that src was originally mapped from.
|
||||
*
|
||||
* If both src and dst have an associated hwframe context, then this function
|
||||
* attempts to map the src frame from its hardware context to that of dst and
|
||||
* then fill dst with appropriate data to be usable there. This will only be
|
||||
* possible if the hwframe contexts and associated devices are compatible -
|
||||
* given compatible devices, av_hwframe_ctx_create_derived() can be used to
|
||||
* create a hwframe context for dst in which mapping should be possible.
|
||||
*
|
||||
* If src has a hwframe context but dst does not, then the src frame is
|
||||
* mapped to normal memory and should thereafter be usable as a normal frame.
|
||||
* If the format is set on dst, then the mapping will attempt to create dst
|
||||
* with that format and fail if it is not possible. If format is unset (is
|
||||
* AV_PIX_FMT_NONE) then dst will be mapped with whatever the most appropriate
|
||||
* format to use is (probably the sw_format of the src hwframe context).
|
||||
*
|
||||
* A return value of AVERROR(ENOSYS) indicates that the mapping is not
|
||||
* possible with the given arguments and hwframe setup, while other return
|
||||
* values indicate that it failed somehow.
|
||||
*
|
||||
* @param dst Destination frame, to contain the mapping.
|
||||
* @param src Source frame, to be mapped.
|
||||
* @param flags Some combination of AV_HWFRAME_MAP_* flags.
|
||||
* @return Zero on success, negative AVERROR code on failure.
|
||||
*/
|
||||
int av_hwframe_map(AVFrame *dst, const AVFrame *src, int flags);
|
||||
|
||||
|
||||
/**
|
||||
* Create and initialise an AVHWFramesContext as a mapping of another existing
|
||||
* AVHWFramesContext on a different device.
|
||||
*
|
||||
* av_hwframe_ctx_init() should not be called after this.
|
||||
*
|
||||
* @param derived_frame_ctx On success, a reference to the newly created
|
||||
* AVHWFramesContext.
|
||||
* @param derived_device_ctx A reference to the device to create the new
|
||||
* AVHWFramesContext on.
|
||||
* @param source_frame_ctx A reference to an existing AVHWFramesContext
|
||||
* which will be mapped to the derived context.
|
||||
* @param flags Some combination of AV_HWFRAME_MAP_* flags, defining the
|
||||
* mapping parameters to apply to frames which are allocated
|
||||
* in the derived device.
|
||||
* @return Zero on success, negative AVERROR code on failure.
|
||||
*/
|
||||
int av_hwframe_ctx_create_derived(AVBufferRef **derived_frame_ctx,
|
||||
enum AVPixelFormat format,
|
||||
AVBufferRef *derived_device_ctx,
|
||||
AVBufferRef *source_frame_ctx,
|
||||
int flags);
|
||||
|
||||
#endif /* AVUTIL_HWCONTEXT_H */
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
#include "avassert.h"
|
||||
#include "common.h"
|
||||
#include "imgutils.h"
|
||||
#include "imgutils_internal.h"
|
||||
#include "internal.h"
|
||||
#include "intreadwrite.h"
|
||||
#include "log.h"
|
||||
|
|
@ -248,19 +249,38 @@ static const AVClass imgutils_class = {
|
|||
.parent_log_context_offset = offsetof(ImgUtils, log_ctx),
|
||||
};
|
||||
|
||||
int av_image_check_size(unsigned int w, unsigned int h, int log_offset, void *log_ctx)
|
||||
int av_image_check_size2(unsigned int w, unsigned int h, int64_t max_pixels, enum AVPixelFormat pix_fmt, int log_offset, void *log_ctx)
|
||||
{
|
||||
ImgUtils imgutils = {
|
||||
.class = &imgutils_class,
|
||||
.log_offset = log_offset,
|
||||
.log_ctx = log_ctx,
|
||||
};
|
||||
int64_t stride = av_image_get_linesize(pix_fmt, w, 0);
|
||||
if (stride <= 0)
|
||||
stride = 8LL*w;
|
||||
stride += 128*8;
|
||||
|
||||
if ((int)w>0 && (int)h>0 && (w+128)*(uint64_t)(h+128) < INT_MAX/8)
|
||||
return 0;
|
||||
if ((int)w<=0 || (int)h<=0 || stride >= INT_MAX || stride*(uint64_t)(h+128) >= INT_MAX) {
|
||||
av_log(&imgutils, AV_LOG_ERROR, "Picture size %ux%u is invalid\n", w, h);
|
||||
return AVERROR(EINVAL);
|
||||
}
|
||||
|
||||
av_log(&imgutils, AV_LOG_ERROR, "Picture size %ux%u is invalid\n", w, h);
|
||||
return AVERROR(EINVAL);
|
||||
if (max_pixels < INT64_MAX) {
|
||||
if (w*(int64_t)h > max_pixels) {
|
||||
av_log(&imgutils, AV_LOG_ERROR,
|
||||
"Picture size %ux%u exceeds specified max pixel count %"PRId64", see the documentation if you wish to increase it\n",
|
||||
w, h, max_pixels);
|
||||
return AVERROR(EINVAL);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int av_image_check_size(unsigned int w, unsigned int h, int log_offset, void *log_ctx)
|
||||
{
|
||||
return av_image_check_size2(w, h, INT64_MAX, AV_PIX_FMT_NONE, log_offset, log_ctx);
|
||||
}
|
||||
|
||||
int av_image_check_sar(unsigned int w, unsigned int h, AVRational sar)
|
||||
|
|
@ -284,9 +304,9 @@ int av_image_check_sar(unsigned int w, unsigned int h, AVRational sar)
|
|||
return AVERROR(EINVAL);
|
||||
}
|
||||
|
||||
void av_image_copy_plane(uint8_t *dst, int dst_linesize,
|
||||
const uint8_t *src, int src_linesize,
|
||||
int bytewidth, int height)
|
||||
static void image_copy_plane(uint8_t *dst, ptrdiff_t dst_linesize,
|
||||
const uint8_t *src, ptrdiff_t src_linesize,
|
||||
ptrdiff_t bytewidth, int height)
|
||||
{
|
||||
if (!dst || !src)
|
||||
return;
|
||||
|
|
@ -299,9 +319,33 @@ void av_image_copy_plane(uint8_t *dst, int dst_linesize,
|
|||
}
|
||||
}
|
||||
|
||||
void av_image_copy(uint8_t *dst_data[4], int dst_linesizes[4],
|
||||
const uint8_t *src_data[4], const int src_linesizes[4],
|
||||
enum AVPixelFormat pix_fmt, int width, int height)
|
||||
static void image_copy_plane_uc_from(uint8_t *dst, ptrdiff_t dst_linesize,
|
||||
const uint8_t *src, ptrdiff_t src_linesize,
|
||||
ptrdiff_t bytewidth, int height)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
#if ARCH_X86
|
||||
ret = ff_image_copy_plane_uc_from_x86(dst, dst_linesize, src, src_linesize,
|
||||
bytewidth, height);
|
||||
#endif
|
||||
|
||||
if (ret < 0)
|
||||
image_copy_plane(dst, dst_linesize, src, src_linesize, bytewidth, height);
|
||||
}
|
||||
|
||||
void av_image_copy_plane(uint8_t *dst, int dst_linesize,
|
||||
const uint8_t *src, int src_linesize,
|
||||
int bytewidth, int height)
|
||||
{
|
||||
image_copy_plane(dst, dst_linesize, src, src_linesize, bytewidth, height);
|
||||
}
|
||||
|
||||
static void image_copy(uint8_t *dst_data[4], const ptrdiff_t dst_linesizes[4],
|
||||
const uint8_t *src_data[4], const ptrdiff_t src_linesizes[4],
|
||||
enum AVPixelFormat pix_fmt, int width, int height,
|
||||
void (*copy_plane)(uint8_t *, ptrdiff_t, const uint8_t *,
|
||||
ptrdiff_t, ptrdiff_t, int))
|
||||
{
|
||||
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
|
||||
|
||||
|
|
@ -310,9 +354,9 @@ void av_image_copy(uint8_t *dst_data[4], int dst_linesizes[4],
|
|||
|
||||
if (desc->flags & AV_PIX_FMT_FLAG_PAL ||
|
||||
desc->flags & AV_PIX_FMT_FLAG_PSEUDOPAL) {
|
||||
av_image_copy_plane(dst_data[0], dst_linesizes[0],
|
||||
src_data[0], src_linesizes[0],
|
||||
width, height);
|
||||
copy_plane(dst_data[0], dst_linesizes[0],
|
||||
src_data[0], src_linesizes[0],
|
||||
width, height);
|
||||
/* copy the palette */
|
||||
memcpy(dst_data[1], src_data[1], 4*256);
|
||||
} else {
|
||||
|
|
@ -323,7 +367,7 @@ void av_image_copy(uint8_t *dst_data[4], int dst_linesizes[4],
|
|||
|
||||
for (i = 0; i < planes_nb; i++) {
|
||||
int h = height;
|
||||
int bwidth = av_image_get_linesize(pix_fmt, width, i);
|
||||
ptrdiff_t bwidth = av_image_get_linesize(pix_fmt, width, i);
|
||||
if (bwidth < 0) {
|
||||
av_log(NULL, AV_LOG_ERROR, "av_image_get_linesize failed\n");
|
||||
return;
|
||||
|
|
@ -331,13 +375,37 @@ void av_image_copy(uint8_t *dst_data[4], int dst_linesizes[4],
|
|||
if (i == 1 || i == 2) {
|
||||
h = AV_CEIL_RSHIFT(height, desc->log2_chroma_h);
|
||||
}
|
||||
av_image_copy_plane(dst_data[i], dst_linesizes[i],
|
||||
src_data[i], src_linesizes[i],
|
||||
bwidth, h);
|
||||
copy_plane(dst_data[i], dst_linesizes[i],
|
||||
src_data[i], src_linesizes[i],
|
||||
bwidth, h);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void av_image_copy(uint8_t *dst_data[4], int dst_linesizes[4],
|
||||
const uint8_t *src_data[4], const int src_linesizes[4],
|
||||
enum AVPixelFormat pix_fmt, int width, int height)
|
||||
{
|
||||
ptrdiff_t dst_linesizes1[4], src_linesizes1[4];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
dst_linesizes1[i] = dst_linesizes[i];
|
||||
src_linesizes1[i] = src_linesizes[i];
|
||||
}
|
||||
|
||||
image_copy(dst_data, dst_linesizes1, src_data, src_linesizes1, pix_fmt,
|
||||
width, height, image_copy_plane);
|
||||
}
|
||||
|
||||
void av_image_copy_uc_from(uint8_t *dst_data[4], const ptrdiff_t dst_linesizes[4],
|
||||
const uint8_t *src_data[4], const ptrdiff_t src_linesizes[4],
|
||||
enum AVPixelFormat pix_fmt, int width, int height)
|
||||
{
|
||||
image_copy(dst_data, dst_linesizes, src_data, src_linesizes, pix_fmt,
|
||||
width, height, image_copy_plane_uc_from);
|
||||
}
|
||||
|
||||
int av_image_fill_arrays(uint8_t *dst_data[4], int dst_linesize[4],
|
||||
const uint8_t *src, enum AVPixelFormat pix_fmt,
|
||||
int width, int height, int align)
|
||||
|
|
@ -423,3 +491,170 @@ int av_image_copy_to_buffer(uint8_t *dst, int dst_size,
|
|||
|
||||
return size;
|
||||
}
|
||||
|
||||
// Fill dst[0..dst_size] with the bytes in clear[0..clear_size]. The clear
|
||||
// bytes are repeated until dst_size is reached. If dst_size is unaligned (i.e.
|
||||
// dst_size%clear_size!=0), the remaining data will be filled with the beginning
|
||||
// of the clear data only.
|
||||
static void memset_bytes(uint8_t *dst, size_t dst_size, uint8_t *clear,
|
||||
size_t clear_size)
|
||||
{
|
||||
size_t pos = 0;
|
||||
int same = 1;
|
||||
int i;
|
||||
|
||||
if (!clear_size)
|
||||
return;
|
||||
|
||||
// Reduce to memset() if possible.
|
||||
for (i = 0; i < clear_size; i++) {
|
||||
if (clear[i] != clear[0]) {
|
||||
same = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (same)
|
||||
clear_size = 1;
|
||||
|
||||
if (clear_size == 1) {
|
||||
memset(dst, clear[0], dst_size);
|
||||
dst_size = 0;
|
||||
} else if (clear_size == 2) {
|
||||
uint16_t val = AV_RN16(clear);
|
||||
for (; dst_size >= 2; dst_size -= 2) {
|
||||
AV_WN16(dst, val);
|
||||
dst += 2;
|
||||
}
|
||||
} else if (clear_size == 4) {
|
||||
uint32_t val = AV_RN32(clear);
|
||||
for (; dst_size >= 4; dst_size -= 4) {
|
||||
AV_WN32(dst, val);
|
||||
dst += 4;
|
||||
}
|
||||
} else if (clear_size == 8) {
|
||||
uint32_t val = AV_RN64(clear);
|
||||
for (; dst_size >= 8; dst_size -= 8) {
|
||||
AV_WN64(dst, val);
|
||||
dst += 8;
|
||||
}
|
||||
}
|
||||
|
||||
for (; dst_size; dst_size--)
|
||||
*dst++ = clear[pos++ % clear_size];
|
||||
}
|
||||
|
||||
// Maximum size in bytes of a plane element (usually a pixel, or multiple pixels
|
||||
// if it's a subsampled packed format).
|
||||
#define MAX_BLOCK_SIZE 32
|
||||
|
||||
int av_image_fill_black(uint8_t *dst_data[4], const ptrdiff_t dst_linesize[4],
|
||||
enum AVPixelFormat pix_fmt, enum AVColorRange range,
|
||||
int width, int height)
|
||||
{
|
||||
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
|
||||
int nb_planes = av_pix_fmt_count_planes(pix_fmt);
|
||||
// A pixel or a group of pixels on each plane, with a value that represents black.
|
||||
// Consider e.g. AV_PIX_FMT_UYVY422 for non-trivial cases.
|
||||
uint8_t clear_block[4][MAX_BLOCK_SIZE] = {{0}}; // clear padding with 0
|
||||
int clear_block_size[4] = {0};
|
||||
ptrdiff_t plane_line_bytes[4] = {0};
|
||||
int rgb, limited;
|
||||
int plane, c;
|
||||
|
||||
if (!desc || nb_planes < 1 || nb_planes > 4 || desc->flags & AV_PIX_FMT_FLAG_HWACCEL)
|
||||
return AVERROR(EINVAL);
|
||||
|
||||
rgb = !!(desc->flags & AV_PIX_FMT_FLAG_RGB);
|
||||
limited = !rgb && range != AVCOL_RANGE_JPEG;
|
||||
|
||||
if (desc->flags & AV_PIX_FMT_FLAG_BITSTREAM) {
|
||||
ptrdiff_t bytewidth = av_image_get_linesize(pix_fmt, width, 0);
|
||||
uint8_t *data;
|
||||
int mono = pix_fmt == AV_PIX_FMT_MONOWHITE || pix_fmt == AV_PIX_FMT_MONOBLACK;
|
||||
int fill = pix_fmt == AV_PIX_FMT_MONOWHITE ? 0xFF : 0;
|
||||
if (nb_planes != 1 || !(rgb || mono) || bytewidth < 1)
|
||||
return AVERROR(EINVAL);
|
||||
|
||||
if (!dst_data)
|
||||
return 0;
|
||||
|
||||
data = dst_data[0];
|
||||
|
||||
// (Bitstream + alpha will be handled incorrectly - it'll remain transparent.)
|
||||
for (;height > 0; height--) {
|
||||
memset(data, fill, bytewidth);
|
||||
data += dst_linesize[0];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (c = 0; c < desc->nb_components; c++) {
|
||||
const AVComponentDescriptor comp = desc->comp[c];
|
||||
|
||||
// We try to operate on entire non-subsampled pixel groups (for
|
||||
// AV_PIX_FMT_UYVY422 this would mean two consecutive pixels).
|
||||
clear_block_size[comp.plane] = FFMAX(clear_block_size[comp.plane], comp.step);
|
||||
|
||||
if (clear_block_size[comp.plane] > MAX_BLOCK_SIZE)
|
||||
return AVERROR(EINVAL);
|
||||
}
|
||||
|
||||
// Create a byte array for clearing 1 pixel (sometimes several pixels).
|
||||
for (c = 0; c < desc->nb_components; c++) {
|
||||
const AVComponentDescriptor comp = desc->comp[c];
|
||||
// (Multiple pixels happen e.g. with AV_PIX_FMT_UYVY422.)
|
||||
int w = clear_block_size[comp.plane] / comp.step;
|
||||
uint8_t *c_data[4];
|
||||
const int c_linesize[4] = {0};
|
||||
uint16_t src_array[MAX_BLOCK_SIZE];
|
||||
uint16_t src = 0;
|
||||
int x;
|
||||
|
||||
if (comp.depth > 16)
|
||||
return AVERROR(EINVAL);
|
||||
if (!rgb && comp.depth < 8)
|
||||
return AVERROR(EINVAL);
|
||||
if (w < 1)
|
||||
return AVERROR(EINVAL);
|
||||
|
||||
if (c == 0 && limited) {
|
||||
src = 16 << (comp.depth - 8);
|
||||
} else if ((c == 1 || c == 2) && !rgb) {
|
||||
src = 128 << (comp.depth - 8);
|
||||
} else if (c == 3) {
|
||||
// (Assume even limited YUV uses full range alpha.)
|
||||
src = (1 << comp.depth) - 1;
|
||||
}
|
||||
|
||||
for (x = 0; x < w; x++)
|
||||
src_array[x] = src;
|
||||
|
||||
for (x = 0; x < 4; x++)
|
||||
c_data[x] = &clear_block[x][0];
|
||||
|
||||
av_write_image_line(src_array, c_data, c_linesize, desc, 0, 0, c, w);
|
||||
}
|
||||
|
||||
for (plane = 0; plane < nb_planes; plane++) {
|
||||
plane_line_bytes[plane] = av_image_get_linesize(pix_fmt, width, plane);
|
||||
if (plane_line_bytes[plane] < 0)
|
||||
return AVERROR(EINVAL);
|
||||
}
|
||||
|
||||
if (!dst_data)
|
||||
return 0;
|
||||
|
||||
for (plane = 0; plane < nb_planes; plane++) {
|
||||
size_t bytewidth = plane_line_bytes[plane];
|
||||
uint8_t *data = dst_data[plane];
|
||||
int chroma_div = plane == 1 || plane == 2 ? desc->log2_chroma_h : 0;
|
||||
int plane_h = ((height + ( 1 << chroma_div) - 1)) >> chroma_div;
|
||||
|
||||
for (; plane_h > 0; plane_h--) {
|
||||
memset_bytes(data, bytewidth, &clear_block[plane][0], clear_block_size[plane]);
|
||||
data += dst_linesize[plane];
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -120,6 +120,24 @@ void av_image_copy(uint8_t *dst_data[4], int dst_linesizes[4],
|
|||
const uint8_t *src_data[4], const int src_linesizes[4],
|
||||
enum AVPixelFormat pix_fmt, int width, int height);
|
||||
|
||||
/**
|
||||
* Copy image data located in uncacheable (e.g. GPU mapped) memory. Where
|
||||
* available, this function will use special functionality for reading from such
|
||||
* memory, which may result in greatly improved performance compared to plain
|
||||
* av_image_copy().
|
||||
*
|
||||
* The data pointers and the linesizes must be aligned to the maximum required
|
||||
* by the CPU architecture.
|
||||
*
|
||||
* @note The linesize parameters have the type ptrdiff_t here, while they are
|
||||
* int for av_image_copy().
|
||||
* @note On x86, the linesizes currently need to be aligned to the cacheline
|
||||
* size (i.e. 64) to get improved performance.
|
||||
*/
|
||||
void av_image_copy_uc_from(uint8_t *dst_data[4], const ptrdiff_t dst_linesizes[4],
|
||||
const uint8_t *src_data[4], const ptrdiff_t src_linesizes[4],
|
||||
enum AVPixelFormat pix_fmt, int width, int height);
|
||||
|
||||
/**
|
||||
* Setup the data pointers and linesizes based on the specified image
|
||||
* parameters and the provided array.
|
||||
|
|
@ -137,7 +155,7 @@ void av_image_copy(uint8_t *dst_data[4], int dst_linesizes[4],
|
|||
* one call, use av_image_alloc().
|
||||
*
|
||||
* @param dst_data data pointers to be filled in
|
||||
* @param dst_linesizes linesizes for the image in dst_data to be filled in
|
||||
* @param dst_linesize linesizes for the image in dst_data to be filled in
|
||||
* @param src buffer which will contain or contains the actual image data, can be NULL
|
||||
* @param pix_fmt the pixel format of the image
|
||||
* @param width the width of the image in pixels
|
||||
|
|
@ -154,7 +172,11 @@ int av_image_fill_arrays(uint8_t *dst_data[4], int dst_linesize[4],
|
|||
* Return the size in bytes of the amount of data required to store an
|
||||
* image with the given parameters.
|
||||
*
|
||||
* @param[in] align the assumed linesize alignment
|
||||
* @param pix_fmt the pixel format of the image
|
||||
* @param width the width of the image in pixels
|
||||
* @param height the height of the image in pixels
|
||||
* @param align the assumed linesize alignment
|
||||
* @return the buffer size in bytes, a negative error code in case of failure
|
||||
*/
|
||||
int av_image_get_buffer_size(enum AVPixelFormat pix_fmt, int width, int height, int align);
|
||||
|
||||
|
|
@ -167,7 +189,7 @@ int av_image_get_buffer_size(enum AVPixelFormat pix_fmt, int width, int height,
|
|||
* @param dst a buffer into which picture data will be copied
|
||||
* @param dst_size the size in bytes of dst
|
||||
* @param src_data pointers containing the source image data
|
||||
* @param src_linesizes linesizes for the image in src_data
|
||||
* @param src_linesize linesizes for the image in src_data
|
||||
* @param pix_fmt the pixel format of the source image
|
||||
* @param width the width of the source image in pixels
|
||||
* @param height the height of the source image in pixels
|
||||
|
|
@ -191,6 +213,21 @@ int av_image_copy_to_buffer(uint8_t *dst, int dst_size,
|
|||
*/
|
||||
int av_image_check_size(unsigned int w, unsigned int h, int log_offset, void *log_ctx);
|
||||
|
||||
/**
|
||||
* Check if the given dimension of an image is valid, meaning that all
|
||||
* bytes of a plane of an image with the specified pix_fmt can be addressed
|
||||
* with a signed int.
|
||||
*
|
||||
* @param w the width of the picture
|
||||
* @param h the height of the picture
|
||||
* @param max_pixels the maximum number of pixels the user wants to accept
|
||||
* @param pix_fmt the pixel format, can be AV_PIX_FMT_NONE if unknown.
|
||||
* @param log_offset the offset to sum to the log level for logging with log_ctx
|
||||
* @param log_ctx the parent logging context, it may be NULL
|
||||
* @return >= 0 if valid, a negative error code otherwise
|
||||
*/
|
||||
int av_image_check_size2(unsigned int w, unsigned int h, int64_t max_pixels, enum AVPixelFormat pix_fmt, int log_offset, void *log_ctx);
|
||||
|
||||
/**
|
||||
* Check if the given sample aspect ratio of an image is valid.
|
||||
*
|
||||
|
|
@ -205,6 +242,33 @@ int av_image_check_size(unsigned int w, unsigned int h, int log_offset, void *lo
|
|||
*/
|
||||
int av_image_check_sar(unsigned int w, unsigned int h, AVRational sar);
|
||||
|
||||
/**
|
||||
* Overwrite the image data with black. This is suitable for filling a
|
||||
* sub-rectangle of an image, meaning the padding between the right most pixel
|
||||
* and the left most pixel on the next line will not be overwritten. For some
|
||||
* formats, the image size might be rounded up due to inherent alignment.
|
||||
*
|
||||
* If the pixel format has alpha, the alpha is cleared to opaque.
|
||||
*
|
||||
* This can return an error if the pixel format is not supported. Normally, all
|
||||
* non-hwaccel pixel formats should be supported.
|
||||
*
|
||||
* Passing NULL for dst_data is allowed. Then the function returns whether the
|
||||
* operation would have succeeded. (It can return an error if the pix_fmt is
|
||||
* not supported.)
|
||||
*
|
||||
* @param dst_data data pointers to destination image
|
||||
* @param dst_linesize linesizes for the destination image
|
||||
* @param pix_fmt the pixel format of the image
|
||||
* @param range the color range of the image (important for colorspaces such as YUV)
|
||||
* @param width the width of the image in pixels
|
||||
* @param height the height of the image in pixels
|
||||
* @return 0 if the image data was cleared, a negative AVERROR code otherwise
|
||||
*/
|
||||
int av_image_fill_black(uint8_t *dst_data[4], const ptrdiff_t dst_linesize[4],
|
||||
enum AVPixelFormat pix_fmt, enum AVColorRange range,
|
||||
int width, int height);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
|
|
|||
30
media/ffvpx/libavutil/imgutils_internal.h
Normal file
30
media/ffvpx/libavutil/imgutils_internal.h
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* 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 AVUTIL_IMGUTILS_INTERNAL_H
|
||||
#define AVUTIL_IMGUTILS_INTERNAL_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
int ff_image_copy_plane_uc_from_x86(uint8_t *dst, ptrdiff_t dst_linesize,
|
||||
const uint8_t *src, ptrdiff_t src_linesize,
|
||||
ptrdiff_t bytewidth, int height);
|
||||
|
||||
|
||||
#endif /* AVUTIL_IMGUTILS_INTERNAL_H */
|
||||
|
|
@ -30,6 +30,9 @@
|
|||
# define NDEBUG
|
||||
#endif
|
||||
|
||||
// This can be enabled to allow detection of additional integer overflows with ubsan
|
||||
//#define CHECKED
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
|
@ -258,6 +261,16 @@ void avpriv_request_sample(void *avc,
|
|||
# define ff_dlog(ctx, ...) do { if (0) av_log(ctx, AV_LOG_DEBUG, __VA_ARGS__); } while (0)
|
||||
#endif
|
||||
|
||||
// For debuging we use signed operations so overflows can be detected (by ubsan)
|
||||
// For production we use unsigned so there are no undefined operations
|
||||
#ifdef CHECKED
|
||||
#define SUINT int
|
||||
#define SUINT32 int32_t
|
||||
#else
|
||||
#define SUINT unsigned
|
||||
#define SUINT32 uint32_t
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Clip and convert a double value into the long long amin-amax range.
|
||||
* This function is needed because conversion of floating point to integers when
|
||||
|
|
@ -340,6 +353,4 @@ void ff_check_pixfmt_descriptors(void);
|
|||
*/
|
||||
int avpriv_dict_set_timestamp(AVDictionary **dict, const char *key, int64_t timestamp);
|
||||
|
||||
extern const uint8_t ff_reverse[256];
|
||||
|
||||
#endif /* AVUTIL_INTERNAL_H */
|
||||
|
|
|
|||
|
|
@ -229,6 +229,11 @@ union unaligned_16 { uint16_t l; } __attribute__((packed)) av_alias;
|
|||
# define AV_RN(s, p) (*((const __unaligned uint##s##_t*)(p)))
|
||||
# define AV_WN(s, p, v) (*((__unaligned uint##s##_t*)(p)) = (v))
|
||||
|
||||
#elif defined(_MSC_VER) && (defined(_M_ARM) || defined(_M_X64)) && AV_HAVE_FAST_UNALIGNED
|
||||
|
||||
# define AV_RN(s, p) (*((const __unaligned uint##s##_t*)(p)))
|
||||
# define AV_WN(s, p, v) (*((__unaligned uint##s##_t*)(p)) = (v))
|
||||
|
||||
#elif AV_HAVE_FAST_UNALIGNED
|
||||
|
||||
# define AV_RN(s, p) (((const av_alias##s*)(p))->u##s)
|
||||
|
|
@ -242,8 +247,8 @@ union unaligned_16 { uint16_t l; } __attribute__((packed)) av_alias;
|
|||
((const uint8_t*)(x))[1])
|
||||
#endif
|
||||
#ifndef AV_WB16
|
||||
# define AV_WB16(p, darg) do { \
|
||||
unsigned d = (darg); \
|
||||
# define AV_WB16(p, val) do { \
|
||||
uint16_t d = (val); \
|
||||
((uint8_t*)(p))[1] = (d); \
|
||||
((uint8_t*)(p))[0] = (d)>>8; \
|
||||
} while(0)
|
||||
|
|
@ -255,8 +260,8 @@ union unaligned_16 { uint16_t l; } __attribute__((packed)) av_alias;
|
|||
((const uint8_t*)(x))[0])
|
||||
#endif
|
||||
#ifndef AV_WL16
|
||||
# define AV_WL16(p, darg) do { \
|
||||
unsigned d = (darg); \
|
||||
# define AV_WL16(p, val) do { \
|
||||
uint16_t d = (val); \
|
||||
((uint8_t*)(p))[0] = (d); \
|
||||
((uint8_t*)(p))[1] = (d)>>8; \
|
||||
} while(0)
|
||||
|
|
@ -270,8 +275,8 @@ union unaligned_16 { uint16_t l; } __attribute__((packed)) av_alias;
|
|||
((const uint8_t*)(x))[3])
|
||||
#endif
|
||||
#ifndef AV_WB32
|
||||
# define AV_WB32(p, darg) do { \
|
||||
unsigned d = (darg); \
|
||||
# define AV_WB32(p, val) do { \
|
||||
uint32_t d = (val); \
|
||||
((uint8_t*)(p))[3] = (d); \
|
||||
((uint8_t*)(p))[2] = (d)>>8; \
|
||||
((uint8_t*)(p))[1] = (d)>>16; \
|
||||
|
|
@ -287,8 +292,8 @@ union unaligned_16 { uint16_t l; } __attribute__((packed)) av_alias;
|
|||
((const uint8_t*)(x))[0])
|
||||
#endif
|
||||
#ifndef AV_WL32
|
||||
# define AV_WL32(p, darg) do { \
|
||||
unsigned d = (darg); \
|
||||
# define AV_WL32(p, val) do { \
|
||||
uint32_t d = (val); \
|
||||
((uint8_t*)(p))[0] = (d); \
|
||||
((uint8_t*)(p))[1] = (d)>>8; \
|
||||
((uint8_t*)(p))[2] = (d)>>16; \
|
||||
|
|
@ -308,8 +313,8 @@ union unaligned_16 { uint16_t l; } __attribute__((packed)) av_alias;
|
|||
(uint64_t)((const uint8_t*)(x))[7])
|
||||
#endif
|
||||
#ifndef AV_WB64
|
||||
# define AV_WB64(p, darg) do { \
|
||||
uint64_t d = (darg); \
|
||||
# define AV_WB64(p, val) do { \
|
||||
uint64_t d = (val); \
|
||||
((uint8_t*)(p))[7] = (d); \
|
||||
((uint8_t*)(p))[6] = (d)>>8; \
|
||||
((uint8_t*)(p))[5] = (d)>>16; \
|
||||
|
|
@ -333,8 +338,8 @@ union unaligned_16 { uint16_t l; } __attribute__((packed)) av_alias;
|
|||
(uint64_t)((const uint8_t*)(x))[0])
|
||||
#endif
|
||||
#ifndef AV_WL64
|
||||
# define AV_WL64(p, darg) do { \
|
||||
uint64_t d = (darg); \
|
||||
# define AV_WL64(p, val) do { \
|
||||
uint64_t d = (val); \
|
||||
((uint8_t*)(p))[0] = (d); \
|
||||
((uint8_t*)(p))[1] = (d)>>8; \
|
||||
((uint8_t*)(p))[2] = (d)>>16; \
|
||||
|
|
|
|||
|
|
@ -168,19 +168,19 @@ static void colored_fputs(int level, int tint, const char *str)
|
|||
#else
|
||||
if (local_use_color == 1) {
|
||||
fprintf(stderr,
|
||||
"\033[%d;3%dm%s\033[0m",
|
||||
"\033[%"PRIu32";3%"PRIu32"m%s\033[0m",
|
||||
(color[level] >> 4) & 15,
|
||||
color[level] & 15,
|
||||
str);
|
||||
} else if (tint && use_color == 256) {
|
||||
fprintf(stderr,
|
||||
"\033[48;5;%dm\033[38;5;%dm%s\033[0m",
|
||||
"\033[48;5;%"PRIu32"m\033[38;5;%dm%s\033[0m",
|
||||
(color[level] >> 16) & 0xff,
|
||||
tint,
|
||||
str);
|
||||
} else if (local_use_color == 256) {
|
||||
fprintf(stderr,
|
||||
"\033[48;5;%dm\033[38;5;%dm%s\033[0m",
|
||||
"\033[48;5;%"PRIu32"m\033[38;5;%"PRIu32"m%s\033[0m",
|
||||
(color[level] >> 16) & 0xff,
|
||||
(color[level] >> 8) & 0xff,
|
||||
str);
|
||||
|
|
|
|||
|
|
@ -115,15 +115,15 @@ int64_t av_rescale_rnd(int64_t a, int64_t b, int64_t c, enum AVRounding rnd)
|
|||
if (t1 > INT64_MAX)
|
||||
return INT64_MIN;
|
||||
return t1;
|
||||
}
|
||||
#else
|
||||
/* reference code doing (a*b + r) / c, requires libavutil/integer.h */
|
||||
AVInteger ai;
|
||||
ai = av_mul_i(av_int2i(a), av_int2i(b));
|
||||
ai = av_add_i(ai, av_int2i(r));
|
||||
|
||||
return av_i2int(av_div_i(ai, av_int2i(c)));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
int64_t av_rescale(int64_t a, int64_t b, int64_t c)
|
||||
|
|
|
|||
|
|
@ -77,22 +77,12 @@ void av_max_alloc(size_t max){
|
|||
void *av_malloc(size_t size)
|
||||
{
|
||||
void *ptr = NULL;
|
||||
#if CONFIG_MEMALIGN_HACK
|
||||
long diff;
|
||||
#endif
|
||||
|
||||
/* let's disallow possibly ambiguous cases */
|
||||
if (size > (max_alloc_size - 32))
|
||||
return NULL;
|
||||
|
||||
#if CONFIG_MEMALIGN_HACK
|
||||
ptr = malloc(size + ALIGN);
|
||||
if (!ptr)
|
||||
return ptr;
|
||||
diff = ((~(long)ptr)&(ALIGN - 1)) + 1;
|
||||
ptr = (char *)ptr + diff;
|
||||
((char *)ptr)[-1] = diff;
|
||||
#elif HAVE_POSIX_MEMALIGN
|
||||
#if HAVE_POSIX_MEMALIGN
|
||||
if (size) //OS X on SDK 10.6 has a broken posix_memalign implementation
|
||||
if (posix_memalign(&ptr, ALIGN, size))
|
||||
ptr = NULL;
|
||||
|
|
@ -144,25 +134,11 @@ void *av_malloc(size_t size)
|
|||
|
||||
void *av_realloc(void *ptr, size_t size)
|
||||
{
|
||||
#if CONFIG_MEMALIGN_HACK
|
||||
int diff;
|
||||
#endif
|
||||
|
||||
/* let's disallow possibly ambiguous cases */
|
||||
if (size > (max_alloc_size - 32))
|
||||
return NULL;
|
||||
|
||||
#if CONFIG_MEMALIGN_HACK
|
||||
//FIXME this isn't aligned correctly, though it probably isn't needed
|
||||
if (!ptr)
|
||||
return av_malloc(size);
|
||||
diff = ((char *)ptr)[-1];
|
||||
av_assert0(diff>0 && diff<=ALIGN);
|
||||
ptr = realloc((char *)ptr - diff, size + diff);
|
||||
if (ptr)
|
||||
ptr = (char *)ptr + diff;
|
||||
return ptr;
|
||||
#elif HAVE_ALIGNED_MALLOC
|
||||
#if HAVE_ALIGNED_MALLOC
|
||||
return _aligned_realloc(ptr, size + !size, ALIGN);
|
||||
#else
|
||||
return realloc(ptr, size + !size);
|
||||
|
|
@ -227,13 +203,7 @@ int av_reallocp_array(void *ptr, size_t nmemb, size_t size)
|
|||
|
||||
void av_free(void *ptr)
|
||||
{
|
||||
#if CONFIG_MEMALIGN_HACK
|
||||
if (ptr) {
|
||||
int v= ((char *)ptr)[-1];
|
||||
av_assert0(v>0 && v<=ALIGN);
|
||||
free((char *)ptr - v);
|
||||
}
|
||||
#elif HAVE_ALIGNED_MALLOC
|
||||
#if HAVE_ALIGNED_MALLOC
|
||||
_aligned_free(ptr);
|
||||
#else
|
||||
free(ptr);
|
||||
|
|
|
|||
|
|
@ -97,7 +97,10 @@
|
|||
#define DECLARE_ASM_CONST(n,t,v) \
|
||||
AV_PRAGMA(DATA_ALIGN(v,n)) \
|
||||
static const t __attribute__((aligned(n))) v
|
||||
#elif defined(__GNUC__)
|
||||
#elif defined(__DJGPP__)
|
||||
#define DECLARE_ALIGNED(n,t,v) t __attribute__ ((aligned (FFMIN(n, 16)))) v
|
||||
#define DECLARE_ASM_CONST(n,t,v) static const t av_used __attribute__ ((aligned (FFMIN(n, 16)))) v
|
||||
#elif defined(__GNUC__) || defined(__clang__)
|
||||
#define DECLARE_ALIGNED(n,t,v) t __attribute__ ((aligned (n))) v
|
||||
#define DECLARE_ASM_CONST(n,t,v) static const t av_used __attribute__ ((aligned (n))) v
|
||||
#elif defined(_MSC_VER)
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ SOURCES += [
|
|||
'rational.c',
|
||||
'reverse.c',
|
||||
'samplefmt.c',
|
||||
'slicethread.c',
|
||||
'threadmessage.c',
|
||||
'time.c',
|
||||
'timecode.c',
|
||||
|
|
|
|||
|
|
@ -74,6 +74,7 @@ static int read_number(const AVOption *o, const void *dst, double *num, int *den
|
|||
case AV_OPT_TYPE_CHANNEL_LAYOUT:
|
||||
case AV_OPT_TYPE_DURATION:
|
||||
case AV_OPT_TYPE_INT64:
|
||||
case AV_OPT_TYPE_UINT64:
|
||||
*intnum = *(int64_t *)dst;
|
||||
return 0;
|
||||
case AV_OPT_TYPE_FLOAT:
|
||||
|
|
@ -96,8 +97,8 @@ static int read_number(const AVOption *o, const void *dst, double *num, int *den
|
|||
static int write_number(void *obj, const AVOption *o, void *dst, double num, int den, int64_t intnum)
|
||||
{
|
||||
if (o->type != AV_OPT_TYPE_FLAGS &&
|
||||
(o->max * den < num * intnum || o->min * den > num * intnum)) {
|
||||
num = den ? num * intnum / den : (num * intnum ? INFINITY : NAN);
|
||||
(!den || o->max * den < num * intnum || o->min * den > num * intnum)) {
|
||||
num = den ? num * intnum / den : (num && intnum ? INFINITY : NAN);
|
||||
av_log(obj, AV_LOG_ERROR, "Value %f for parameter '%s' out of range [%g - %g]\n",
|
||||
num, o->name, o->min, o->max);
|
||||
return AVERROR(ERANGE);
|
||||
|
|
@ -126,9 +127,27 @@ static int write_number(void *obj, const AVOption *o, void *dst, double num, int
|
|||
break;
|
||||
case AV_OPT_TYPE_DURATION:
|
||||
case AV_OPT_TYPE_CHANNEL_LAYOUT:
|
||||
case AV_OPT_TYPE_INT64:
|
||||
*(int64_t *)dst = llrint(num / den) * intnum;
|
||||
break;
|
||||
case AV_OPT_TYPE_INT64:{
|
||||
double d = num / den;
|
||||
if (intnum == 1 && d == (double)INT64_MAX) {
|
||||
*(int64_t *)dst = INT64_MAX;
|
||||
} else
|
||||
*(int64_t *)dst = llrint(d) * intnum;
|
||||
break;}
|
||||
case AV_OPT_TYPE_UINT64:{
|
||||
double d = num / den;
|
||||
// We must special case uint64_t here as llrint() does not support values
|
||||
// outside the int64_t range and there is no portable function which does
|
||||
// "INT64_MAX + 1ULL" is used as it is representable exactly as IEEE double
|
||||
// while INT64_MAX is not
|
||||
if (intnum == 1 && d == (double)UINT64_MAX) {
|
||||
*(uint64_t *)dst = UINT64_MAX;
|
||||
} else if (d > INT64_MAX + 1ULL) {
|
||||
*(uint64_t *)dst = (llrint(d - (INT64_MAX + 1ULL)) + (INT64_MAX + 1ULL))*intnum;
|
||||
} else {
|
||||
*(uint64_t *)dst = llrint(d) * intnum;
|
||||
}
|
||||
break;}
|
||||
case AV_OPT_TYPE_FLOAT:
|
||||
*(float *)dst = num * intnum / den;
|
||||
break;
|
||||
|
|
@ -200,6 +219,7 @@ static int set_string(void *obj, const AVOption *o, const char *val, uint8_t **d
|
|||
}
|
||||
|
||||
#define DEFAULT_NUMVAL(opt) ((opt->type == AV_OPT_TYPE_INT64 || \
|
||||
opt->type == AV_OPT_TYPE_UINT64 || \
|
||||
opt->type == AV_OPT_TYPE_CONST || \
|
||||
opt->type == AV_OPT_TYPE_FLAGS || \
|
||||
opt->type == AV_OPT_TYPE_INT) \
|
||||
|
|
@ -291,8 +311,6 @@ static int set_string_number(void *obj, void *target_obj, const AVOption *o, con
|
|||
if (!i || !*val)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_string_image_size(void *obj, const AVOption *o, const char *val, int *dst)
|
||||
|
|
@ -456,6 +474,7 @@ int av_opt_set(void *obj, const char *name, const char *val, int search_flags)
|
|||
case AV_OPT_TYPE_FLAGS:
|
||||
case AV_OPT_TYPE_INT:
|
||||
case AV_OPT_TYPE_INT64:
|
||||
case AV_OPT_TYPE_UINT64:
|
||||
case AV_OPT_TYPE_FLOAT:
|
||||
case AV_OPT_TYPE_DOUBLE:
|
||||
case AV_OPT_TYPE_RATIONAL:
|
||||
|
|
@ -756,6 +775,9 @@ int av_opt_get(void *obj, const char *name, int search_flags, uint8_t **out_val)
|
|||
case AV_OPT_TYPE_INT64:
|
||||
ret = snprintf(buf, sizeof(buf), "%"PRId64, *(int64_t *)dst);
|
||||
break;
|
||||
case AV_OPT_TYPE_UINT64:
|
||||
ret = snprintf(buf, sizeof(buf), "%"PRIu64, *(uint64_t *)dst);
|
||||
break;
|
||||
case AV_OPT_TYPE_FLOAT:
|
||||
ret = snprintf(buf, sizeof(buf), "%f", *(float *)dst);
|
||||
break;
|
||||
|
|
@ -1104,6 +1126,9 @@ static void opt_list(void *obj, void *av_log_obj, const char *unit,
|
|||
case AV_OPT_TYPE_INT64:
|
||||
av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<int64>");
|
||||
break;
|
||||
case AV_OPT_TYPE_UINT64:
|
||||
av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<uint64>");
|
||||
break;
|
||||
case AV_OPT_TYPE_DOUBLE:
|
||||
av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<double>");
|
||||
break;
|
||||
|
|
@ -1164,6 +1189,7 @@ static void opt_list(void *obj, void *av_log_obj, const char *unit,
|
|||
switch (opt->type) {
|
||||
case AV_OPT_TYPE_INT:
|
||||
case AV_OPT_TYPE_INT64:
|
||||
case AV_OPT_TYPE_UINT64:
|
||||
case AV_OPT_TYPE_DOUBLE:
|
||||
case AV_OPT_TYPE_FLOAT:
|
||||
case AV_OPT_TYPE_RATIONAL:
|
||||
|
|
@ -1208,6 +1234,7 @@ static void opt_list(void *obj, void *av_log_obj, const char *unit,
|
|||
break;
|
||||
}
|
||||
case AV_OPT_TYPE_INT:
|
||||
case AV_OPT_TYPE_UINT64:
|
||||
case AV_OPT_TYPE_INT64: {
|
||||
const char *def_const = get_opt_const_name(obj, opt->unit, opt->default_val.i64);
|
||||
if (def_const)
|
||||
|
|
@ -1286,6 +1313,7 @@ void av_opt_set_defaults2(void *s, int mask, int flags)
|
|||
case AV_OPT_TYPE_FLAGS:
|
||||
case AV_OPT_TYPE_INT:
|
||||
case AV_OPT_TYPE_INT64:
|
||||
case AV_OPT_TYPE_UINT64:
|
||||
case AV_OPT_TYPE_DURATION:
|
||||
case AV_OPT_TYPE_CHANNEL_LAYOUT:
|
||||
case AV_OPT_TYPE_PIXEL_FMT:
|
||||
|
|
@ -1646,6 +1674,7 @@ static int opt_size(enum AVOptionType type)
|
|||
case AV_OPT_TYPE_DURATION:
|
||||
case AV_OPT_TYPE_CHANNEL_LAYOUT:
|
||||
case AV_OPT_TYPE_INT64:
|
||||
case AV_OPT_TYPE_UINT64:
|
||||
return sizeof(int64_t);
|
||||
case AV_OPT_TYPE_DOUBLE:
|
||||
return sizeof(double);
|
||||
|
|
@ -1775,6 +1804,7 @@ int av_opt_query_ranges_default(AVOptionRanges **ranges_arg, void *obj, const ch
|
|||
case AV_OPT_TYPE_BOOL:
|
||||
case AV_OPT_TYPE_INT:
|
||||
case AV_OPT_TYPE_INT64:
|
||||
case AV_OPT_TYPE_UINT64:
|
||||
case AV_OPT_TYPE_PIXEL_FMT:
|
||||
case AV_OPT_TYPE_SAMPLE_FMT:
|
||||
case AV_OPT_TYPE_FLOAT:
|
||||
|
|
@ -1864,6 +1894,7 @@ int av_opt_is_set_to_default(void *obj, const AVOption *o)
|
|||
case AV_OPT_TYPE_CHANNEL_LAYOUT:
|
||||
case AV_OPT_TYPE_DURATION:
|
||||
case AV_OPT_TYPE_INT64:
|
||||
case AV_OPT_TYPE_UINT64:
|
||||
read_number(o, dst, NULL, NULL, &i64);
|
||||
return o->default_val.i64 == i64;
|
||||
case AV_OPT_TYPE_STRING:
|
||||
|
|
|
|||
|
|
@ -228,6 +228,7 @@ enum AVOptionType{
|
|||
AV_OPT_TYPE_RATIONAL,
|
||||
AV_OPT_TYPE_BINARY, ///< offset must point to a pointer immediately followed by an int for the length
|
||||
AV_OPT_TYPE_DICT,
|
||||
AV_OPT_TYPE_UINT64,
|
||||
AV_OPT_TYPE_CONST = 128,
|
||||
AV_OPT_TYPE_IMAGE_SIZE = MKBETAG('S','I','Z','E'), ///< offset must point to two consecutive integers
|
||||
AV_OPT_TYPE_PIXEL_FMT = MKBETAG('P','F','M','T'),
|
||||
|
|
|
|||
|
|
@ -140,6 +140,11 @@ static const VideoRateAbbr video_rate_abbrs[]= {
|
|||
{ "ntsc-film", { 24000, 1001 } },
|
||||
};
|
||||
|
||||
static const char *months[12] = {
|
||||
"january", "february", "march", "april", "may", "june", "july", "august",
|
||||
"september", "october", "november", "december"
|
||||
};
|
||||
|
||||
int av_parse_video_size(int *width_ptr, int *height_ptr, const char *str)
|
||||
{
|
||||
int i;
|
||||
|
|
@ -466,6 +471,21 @@ static int date_get_num(const char **pp,
|
|||
return val;
|
||||
}
|
||||
|
||||
static int date_get_month(const char **pp) {
|
||||
int i = 0;
|
||||
for (; i < 12; i++) {
|
||||
if (!av_strncasecmp(*pp, months[i], 3)) {
|
||||
const char *mo_full = months[i] + 3;
|
||||
int len = strlen(mo_full);
|
||||
*pp += 3;
|
||||
if (len > 0 && !av_strncasecmp(*pp, mo_full, len))
|
||||
*pp += len;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *av_small_strptime(const char *p, const char *fmt, struct tm *dt)
|
||||
{
|
||||
int c, val;
|
||||
|
|
@ -525,6 +545,14 @@ char *av_small_strptime(const char *p, const char *fmt, struct tm *dt)
|
|||
if (!p)
|
||||
return NULL;
|
||||
break;
|
||||
case 'b':
|
||||
case 'B':
|
||||
case 'h':
|
||||
val = date_get_month(&p);
|
||||
if (val == -1)
|
||||
return NULL;
|
||||
dt->tm_mon = val;
|
||||
break;
|
||||
case '%':
|
||||
if (*p++ != '%')
|
||||
return NULL;
|
||||
|
|
|
|||
|
|
@ -560,6 +560,69 @@ static const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = {
|
|||
},
|
||||
.flags = AV_PIX_FMT_FLAG_RGB,
|
||||
},
|
||||
[AV_PIX_FMT_GRAY9BE] = {
|
||||
.name = "gray9be",
|
||||
.nb_components = 1,
|
||||
.log2_chroma_w = 0,
|
||||
.log2_chroma_h = 0,
|
||||
.comp = {
|
||||
{ 0, 2, 0, 0, 9, 1, 8, 1 }, /* Y */
|
||||
},
|
||||
.flags = AV_PIX_FMT_FLAG_BE,
|
||||
.alias = "y9be",
|
||||
},
|
||||
[AV_PIX_FMT_GRAY9LE] = {
|
||||
.name = "gray9le",
|
||||
.nb_components = 1,
|
||||
.log2_chroma_w = 0,
|
||||
.log2_chroma_h = 0,
|
||||
.comp = {
|
||||
{ 0, 2, 0, 0, 9, 1, 8, 1 }, /* Y */
|
||||
},
|
||||
.alias = "y9le",
|
||||
},
|
||||
[AV_PIX_FMT_GRAY10BE] = {
|
||||
.name = "gray10be",
|
||||
.nb_components = 1,
|
||||
.log2_chroma_w = 0,
|
||||
.log2_chroma_h = 0,
|
||||
.comp = {
|
||||
{ 0, 2, 0, 0, 10, 1, 9, 1 }, /* Y */
|
||||
},
|
||||
.flags = AV_PIX_FMT_FLAG_BE,
|
||||
.alias = "y10be",
|
||||
},
|
||||
[AV_PIX_FMT_GRAY10LE] = {
|
||||
.name = "gray10le",
|
||||
.nb_components = 1,
|
||||
.log2_chroma_w = 0,
|
||||
.log2_chroma_h = 0,
|
||||
.comp = {
|
||||
{ 0, 2, 0, 0, 10, 1, 9, 1 }, /* Y */
|
||||
},
|
||||
.alias = "y10le",
|
||||
},
|
||||
[AV_PIX_FMT_GRAY12BE] = {
|
||||
.name = "gray12be",
|
||||
.nb_components = 1,
|
||||
.log2_chroma_w = 0,
|
||||
.log2_chroma_h = 0,
|
||||
.comp = {
|
||||
{ 0, 2, 0, 0, 12, 1, 11, 1 }, /* Y */
|
||||
},
|
||||
.flags = AV_PIX_FMT_FLAG_BE,
|
||||
.alias = "y12be",
|
||||
},
|
||||
[AV_PIX_FMT_GRAY12LE] = {
|
||||
.name = "gray12le",
|
||||
.nb_components = 1,
|
||||
.log2_chroma_w = 0,
|
||||
.log2_chroma_h = 0,
|
||||
.comp = {
|
||||
{ 0, 2, 0, 0, 12, 1, 11, 1 }, /* Y */
|
||||
},
|
||||
.alias = "y12le",
|
||||
},
|
||||
[AV_PIX_FMT_GRAY16BE] = {
|
||||
.name = "gray16be",
|
||||
.nb_components = 1,
|
||||
|
|
@ -1873,62 +1936,62 @@ static const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = {
|
|||
[AV_PIX_FMT_BAYER_BGGR8] = {
|
||||
.name = "bayer_bggr8",
|
||||
BAYER8_DESC_COMMON
|
||||
.flags = AV_PIX_FMT_FLAG_RGB,
|
||||
.flags = AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_BAYER,
|
||||
},
|
||||
[AV_PIX_FMT_BAYER_BGGR16LE] = {
|
||||
.name = "bayer_bggr16le",
|
||||
BAYER16_DESC_COMMON
|
||||
.flags = AV_PIX_FMT_FLAG_RGB,
|
||||
.flags = AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_BAYER,
|
||||
},
|
||||
[AV_PIX_FMT_BAYER_BGGR16BE] = {
|
||||
.name = "bayer_bggr16be",
|
||||
BAYER16_DESC_COMMON
|
||||
.flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_RGB,
|
||||
.flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_BAYER,
|
||||
},
|
||||
[AV_PIX_FMT_BAYER_RGGB8] = {
|
||||
.name = "bayer_rggb8",
|
||||
BAYER8_DESC_COMMON
|
||||
.flags = AV_PIX_FMT_FLAG_RGB,
|
||||
.flags = AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_BAYER,
|
||||
},
|
||||
[AV_PIX_FMT_BAYER_RGGB16LE] = {
|
||||
.name = "bayer_rggb16le",
|
||||
BAYER16_DESC_COMMON
|
||||
.flags = AV_PIX_FMT_FLAG_RGB,
|
||||
.flags = AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_BAYER,
|
||||
},
|
||||
[AV_PIX_FMT_BAYER_RGGB16BE] = {
|
||||
.name = "bayer_rggb16be",
|
||||
BAYER16_DESC_COMMON
|
||||
.flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_RGB,
|
||||
.flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_BAYER,
|
||||
},
|
||||
[AV_PIX_FMT_BAYER_GBRG8] = {
|
||||
.name = "bayer_gbrg8",
|
||||
BAYER8_DESC_COMMON
|
||||
.flags = AV_PIX_FMT_FLAG_RGB,
|
||||
.flags = AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_BAYER,
|
||||
},
|
||||
[AV_PIX_FMT_BAYER_GBRG16LE] = {
|
||||
.name = "bayer_gbrg16le",
|
||||
BAYER16_DESC_COMMON
|
||||
.flags = AV_PIX_FMT_FLAG_RGB,
|
||||
.flags = AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_BAYER,
|
||||
},
|
||||
[AV_PIX_FMT_BAYER_GBRG16BE] = {
|
||||
.name = "bayer_gbrg16be",
|
||||
BAYER16_DESC_COMMON
|
||||
.flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_RGB,
|
||||
.flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_BAYER,
|
||||
},
|
||||
[AV_PIX_FMT_BAYER_GRBG8] = {
|
||||
.name = "bayer_grbg8",
|
||||
BAYER8_DESC_COMMON
|
||||
.flags = AV_PIX_FMT_FLAG_RGB,
|
||||
.flags = AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_BAYER,
|
||||
},
|
||||
[AV_PIX_FMT_BAYER_GRBG16LE] = {
|
||||
.name = "bayer_grbg16le",
|
||||
BAYER16_DESC_COMMON
|
||||
.flags = AV_PIX_FMT_FLAG_RGB,
|
||||
.flags = AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_BAYER,
|
||||
},
|
||||
[AV_PIX_FMT_BAYER_GRBG16BE] = {
|
||||
.name = "bayer_grbg16be",
|
||||
BAYER16_DESC_COMMON
|
||||
.flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_RGB,
|
||||
.flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_BAYER,
|
||||
},
|
||||
[AV_PIX_FMT_NV16] = {
|
||||
.name = "nv16",
|
||||
|
|
@ -2036,6 +2099,30 @@ static const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = {
|
|||
},
|
||||
.flags = AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_BE,
|
||||
},
|
||||
[AV_PIX_FMT_P016LE] = {
|
||||
.name = "p016le",
|
||||
.nb_components = 3,
|
||||
.log2_chroma_w = 1,
|
||||
.log2_chroma_h = 1,
|
||||
.comp = {
|
||||
{ 0, 2, 0, 0, 16, 1, 15, 1 }, /* Y */
|
||||
{ 1, 4, 0, 0, 16, 3, 15, 1 }, /* U */
|
||||
{ 1, 4, 2, 0, 16, 3, 15, 3 }, /* V */
|
||||
},
|
||||
.flags = AV_PIX_FMT_FLAG_PLANAR,
|
||||
},
|
||||
[AV_PIX_FMT_P016BE] = {
|
||||
.name = "p016be",
|
||||
.nb_components = 3,
|
||||
.log2_chroma_w = 1,
|
||||
.log2_chroma_h = 1,
|
||||
.comp = {
|
||||
{ 0, 2, 0, 0, 16, 1, 15, 1 }, /* Y */
|
||||
{ 1, 4, 0, 0, 16, 3, 15, 1 }, /* U */
|
||||
{ 1, 4, 2, 0, 16, 3, 15, 3 }, /* V */
|
||||
},
|
||||
.flags = AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_BE,
|
||||
},
|
||||
[AV_PIX_FMT_GBRAP12LE] = {
|
||||
.name = "gbrap12le",
|
||||
.nb_components = 4,
|
||||
|
|
@ -2092,18 +2179,80 @@ static const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = {
|
|||
.flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_PLANAR |
|
||||
AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_ALPHA,
|
||||
},
|
||||
[AV_PIX_FMT_D3D11] = {
|
||||
.name = "d3d11",
|
||||
.flags = AV_PIX_FMT_FLAG_HWACCEL,
|
||||
},
|
||||
[AV_PIX_FMT_GBRPF32BE] = {
|
||||
.name = "gbrpf32be",
|
||||
.nb_components = 3,
|
||||
.log2_chroma_w = 0,
|
||||
.log2_chroma_h = 0,
|
||||
.comp = {
|
||||
{ 2, 4, 0, 0, 32, 3, 31, 1 }, /* R */
|
||||
{ 0, 4, 0, 0, 32, 3, 31, 1 }, /* G */
|
||||
{ 1, 4, 0, 0, 32, 3, 31, 1 }, /* B */
|
||||
},
|
||||
.flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_PLANAR |
|
||||
AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_FLOAT,
|
||||
},
|
||||
[AV_PIX_FMT_GBRPF32LE] = {
|
||||
.name = "gbrpf32le",
|
||||
.nb_components = 3,
|
||||
.log2_chroma_w = 0,
|
||||
.log2_chroma_h = 0,
|
||||
.comp = {
|
||||
{ 2, 4, 0, 0, 32, 3, 31, 1 }, /* R */
|
||||
{ 0, 4, 0, 0, 32, 3, 31, 1 }, /* G */
|
||||
{ 1, 4, 0, 0, 32, 3, 31, 1 }, /* B */
|
||||
},
|
||||
.flags = AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_FLOAT | AV_PIX_FMT_FLAG_RGB,
|
||||
},
|
||||
[AV_PIX_FMT_GBRAPF32BE] = {
|
||||
.name = "gbrapf32be",
|
||||
.nb_components = 4,
|
||||
.log2_chroma_w = 0,
|
||||
.log2_chroma_h = 0,
|
||||
.comp = {
|
||||
{ 2, 4, 0, 0, 32, 3, 31, 1 }, /* R */
|
||||
{ 0, 4, 0, 0, 32, 3, 31, 1 }, /* G */
|
||||
{ 1, 4, 0, 0, 32, 3, 31, 1 }, /* B */
|
||||
{ 3, 4, 0, 0, 32, 3, 31, 1 }, /* A */
|
||||
},
|
||||
.flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_PLANAR |
|
||||
AV_PIX_FMT_FLAG_ALPHA | AV_PIX_FMT_FLAG_RGB |
|
||||
AV_PIX_FMT_FLAG_FLOAT,
|
||||
},
|
||||
[AV_PIX_FMT_GBRAPF32LE] = {
|
||||
.name = "gbrapf32le",
|
||||
.nb_components = 4,
|
||||
.log2_chroma_w = 0,
|
||||
.log2_chroma_h = 0,
|
||||
.comp = {
|
||||
{ 2, 4, 0, 0, 32, 3, 31, 1 }, /* R */
|
||||
{ 0, 4, 0, 0, 32, 3, 31, 1 }, /* G */
|
||||
{ 1, 4, 0, 0, 32, 3, 31, 1 }, /* B */
|
||||
{ 3, 4, 0, 0, 32, 3, 31, 1 }, /* A */
|
||||
},
|
||||
.flags = AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_ALPHA |
|
||||
AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_FLOAT,
|
||||
},
|
||||
[AV_PIX_FMT_DRM_PRIME] = {
|
||||
.name = "drm_prime",
|
||||
.flags = AV_PIX_FMT_FLAG_HWACCEL,
|
||||
},
|
||||
};
|
||||
#if FF_API_PLUS1_MINUS1
|
||||
FF_ENABLE_DEPRECATION_WARNINGS
|
||||
#endif
|
||||
|
||||
static const char *color_range_names[] = {
|
||||
static const char * const color_range_names[] = {
|
||||
[AVCOL_RANGE_UNSPECIFIED] = "unknown",
|
||||
[AVCOL_RANGE_MPEG] = "tv",
|
||||
[AVCOL_RANGE_JPEG] = "pc",
|
||||
};
|
||||
|
||||
static const char *color_primaries_names[AVCOL_PRI_NB] = {
|
||||
static const char * const color_primaries_names[AVCOL_PRI_NB] = {
|
||||
[AVCOL_PRI_RESERVED0] = "reserved",
|
||||
[AVCOL_PRI_BT709] = "bt709",
|
||||
[AVCOL_PRI_UNSPECIFIED] = "unknown",
|
||||
|
|
@ -2114,12 +2263,13 @@ static const char *color_primaries_names[AVCOL_PRI_NB] = {
|
|||
[AVCOL_PRI_SMPTE240M] = "smpte240m",
|
||||
[AVCOL_PRI_FILM] = "film",
|
||||
[AVCOL_PRI_BT2020] = "bt2020",
|
||||
[AVCOL_PRI_SMPTEST428_1] = "smpte428-1",
|
||||
[AVCOL_PRI_SMPTE428] = "smpte428",
|
||||
[AVCOL_PRI_SMPTE431] = "smpte431",
|
||||
[AVCOL_PRI_SMPTE432] = "smpte432",
|
||||
[AVCOL_PRI_JEDEC_P22] = "jedec-p22",
|
||||
};
|
||||
|
||||
static const char *color_transfer_names[] = {
|
||||
static const char * const color_transfer_names[] = {
|
||||
[AVCOL_TRC_RESERVED0] = "reserved",
|
||||
[AVCOL_TRC_BT709] = "bt709",
|
||||
[AVCOL_TRC_UNSPECIFIED] = "unknown",
|
||||
|
|
@ -2135,13 +2285,13 @@ static const char *color_transfer_names[] = {
|
|||
[AVCOL_TRC_BT1361_ECG] = "bt1361e",
|
||||
[AVCOL_TRC_IEC61966_2_1] = "iec61966-2-1",
|
||||
[AVCOL_TRC_BT2020_10] = "bt2020-10",
|
||||
[AVCOL_TRC_BT2020_12] = "bt2020-20",
|
||||
[AVCOL_TRC_SMPTEST2084] = "smpte2084",
|
||||
[AVCOL_TRC_SMPTEST428_1] = "smpte428-1",
|
||||
[AVCOL_TRC_BT2020_12] = "bt2020-12",
|
||||
[AVCOL_TRC_SMPTE2084] = "smpte2084",
|
||||
[AVCOL_TRC_SMPTE428] = "smpte428",
|
||||
[AVCOL_TRC_ARIB_STD_B67] = "arib-std-b67",
|
||||
};
|
||||
|
||||
static const char *color_space_names[] = {
|
||||
static const char * const color_space_names[] = {
|
||||
[AVCOL_SPC_RGB] = "gbr",
|
||||
[AVCOL_SPC_BT709] = "bt709",
|
||||
[AVCOL_SPC_UNSPECIFIED] = "unknown",
|
||||
|
|
@ -2150,13 +2300,16 @@ static const char *color_space_names[] = {
|
|||
[AVCOL_SPC_BT470BG] = "bt470bg",
|
||||
[AVCOL_SPC_SMPTE170M] = "smpte170m",
|
||||
[AVCOL_SPC_SMPTE240M] = "smpte240m",
|
||||
[AVCOL_SPC_YCOCG] = "ycgco",
|
||||
[AVCOL_SPC_YCGCO] = "ycgco",
|
||||
[AVCOL_SPC_BT2020_NCL] = "bt2020nc",
|
||||
[AVCOL_SPC_BT2020_CL] = "bt2020c",
|
||||
[AVCOL_SPC_SMPTE2085] = "smpte2085",
|
||||
[AVCOL_SPC_CHROMA_DERIVED_NCL] = "chroma-derived-nc",
|
||||
[AVCOL_SPC_CHROMA_DERIVED_CL] = "chroma-derived-c",
|
||||
[AVCOL_SPC_ICTCP] = "ictcp",
|
||||
};
|
||||
|
||||
static const char *chroma_location_names[] = {
|
||||
static const char * const chroma_location_names[] = {
|
||||
[AVCHROMA_LOC_UNSPECIFIED] = "unspecified",
|
||||
[AVCHROMA_LOC_LEFT] = "left",
|
||||
[AVCHROMA_LOC_CENTER] = "center",
|
||||
|
|
@ -2349,7 +2502,7 @@ void ff_check_pixfmt_descriptors(void){
|
|||
} else {
|
||||
av_assert0(8*c->step >= c->depth);
|
||||
}
|
||||
if (!strncmp(d->name, "bayer_", 6))
|
||||
if (d->flags & AV_PIX_FMT_FLAG_BAYER)
|
||||
continue;
|
||||
av_read_image_line(tmp, (void*)data, linesize, d, 0, 0, j, 2, 0);
|
||||
av_assert0(tmp[0] == 0 && tmp[1] == 0);
|
||||
|
|
@ -2440,8 +2593,16 @@ static int get_pix_fmt_score(enum AVPixelFormat dst_pix_fmt,
|
|||
int ret, loss, i, nb_components;
|
||||
int score = INT_MAX - 1;
|
||||
|
||||
if (dst_pix_fmt >= AV_PIX_FMT_NB || dst_pix_fmt <= AV_PIX_FMT_NONE)
|
||||
return ~0;
|
||||
if (!src_desc || !dst_desc)
|
||||
return -4;
|
||||
|
||||
if ((src_desc->flags & AV_PIX_FMT_FLAG_HWACCEL) ||
|
||||
(dst_desc->flags & AV_PIX_FMT_FLAG_HWACCEL)) {
|
||||
if (dst_pix_fmt == src_pix_fmt)
|
||||
return -1;
|
||||
else
|
||||
return -2;
|
||||
}
|
||||
|
||||
/* compute loss */
|
||||
*lossp = loss = 0;
|
||||
|
|
@ -2450,9 +2611,9 @@ static int get_pix_fmt_score(enum AVPixelFormat dst_pix_fmt,
|
|||
return INT_MAX;
|
||||
|
||||
if ((ret = get_pix_fmt_depth(&src_min_depth, &src_max_depth, src_pix_fmt)) < 0)
|
||||
return ret;
|
||||
return -3;
|
||||
if ((ret = get_pix_fmt_depth(&dst_min_depth, &dst_max_depth, dst_pix_fmt)) < 0)
|
||||
return ret;
|
||||
return -3;
|
||||
|
||||
src_color = get_color_type(src_desc);
|
||||
dst_color = get_color_type(dst_desc);
|
||||
|
|
@ -2554,21 +2715,27 @@ enum AVPixelFormat av_find_best_pix_fmt_of_2(enum AVPixelFormat dst_pix_fmt1, en
|
|||
const AVPixFmtDescriptor *desc2 = av_pix_fmt_desc_get(dst_pix_fmt2);
|
||||
int score1, score2;
|
||||
|
||||
loss_mask= loss_ptr?~*loss_ptr:~0; /* use loss mask if provided */
|
||||
if(!has_alpha)
|
||||
loss_mask &= ~FF_LOSS_ALPHA;
|
||||
|
||||
score1 = get_pix_fmt_score(dst_pix_fmt1, src_pix_fmt, &loss1, loss_mask);
|
||||
score2 = get_pix_fmt_score(dst_pix_fmt2, src_pix_fmt, &loss2, loss_mask);
|
||||
|
||||
if (score1 == score2) {
|
||||
if(av_get_padded_bits_per_pixel(desc2) != av_get_padded_bits_per_pixel(desc1)) {
|
||||
dst_pix_fmt = av_get_padded_bits_per_pixel(desc2) < av_get_padded_bits_per_pixel(desc1) ? dst_pix_fmt2 : dst_pix_fmt1;
|
||||
} else {
|
||||
dst_pix_fmt = desc2->nb_components < desc1->nb_components ? dst_pix_fmt2 : dst_pix_fmt1;
|
||||
}
|
||||
if (!desc1) {
|
||||
dst_pix_fmt = dst_pix_fmt2;
|
||||
} else if (!desc2) {
|
||||
dst_pix_fmt = dst_pix_fmt1;
|
||||
} else {
|
||||
dst_pix_fmt = score1 < score2 ? dst_pix_fmt2 : dst_pix_fmt1;
|
||||
loss_mask= loss_ptr?~*loss_ptr:~0; /* use loss mask if provided */
|
||||
if(!has_alpha)
|
||||
loss_mask &= ~FF_LOSS_ALPHA;
|
||||
|
||||
score1 = get_pix_fmt_score(dst_pix_fmt1, src_pix_fmt, &loss1, loss_mask);
|
||||
score2 = get_pix_fmt_score(dst_pix_fmt2, src_pix_fmt, &loss2, loss_mask);
|
||||
|
||||
if (score1 == score2) {
|
||||
if(av_get_padded_bits_per_pixel(desc2) != av_get_padded_bits_per_pixel(desc1)) {
|
||||
dst_pix_fmt = av_get_padded_bits_per_pixel(desc2) < av_get_padded_bits_per_pixel(desc1) ? dst_pix_fmt2 : dst_pix_fmt1;
|
||||
} else {
|
||||
dst_pix_fmt = desc2->nb_components < desc1->nb_components ? dst_pix_fmt2 : dst_pix_fmt1;
|
||||
}
|
||||
} else {
|
||||
dst_pix_fmt = score1 < score2 ? dst_pix_fmt2 : dst_pix_fmt1;
|
||||
}
|
||||
}
|
||||
|
||||
if (loss_ptr)
|
||||
|
|
@ -2582,26 +2749,91 @@ const char *av_color_range_name(enum AVColorRange range)
|
|||
color_range_names[range] : NULL;
|
||||
}
|
||||
|
||||
int av_color_range_from_name(const char *name)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < FF_ARRAY_ELEMS(color_range_names); i++) {
|
||||
size_t len = strlen(color_range_names[i]);
|
||||
if (!strncmp(color_range_names[i], name, len))
|
||||
return i;
|
||||
}
|
||||
|
||||
return AVERROR(EINVAL);
|
||||
}
|
||||
|
||||
const char *av_color_primaries_name(enum AVColorPrimaries primaries)
|
||||
{
|
||||
return (unsigned) primaries < AVCOL_PRI_NB ?
|
||||
color_primaries_names[primaries] : NULL;
|
||||
}
|
||||
|
||||
int av_color_primaries_from_name(const char *name)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < FF_ARRAY_ELEMS(color_primaries_names); i++) {
|
||||
size_t len = strlen(color_primaries_names[i]);
|
||||
if (!strncmp(color_primaries_names[i], name, len))
|
||||
return i;
|
||||
}
|
||||
|
||||
return AVERROR(EINVAL);
|
||||
}
|
||||
|
||||
const char *av_color_transfer_name(enum AVColorTransferCharacteristic transfer)
|
||||
{
|
||||
return (unsigned) transfer < AVCOL_TRC_NB ?
|
||||
color_transfer_names[transfer] : NULL;
|
||||
}
|
||||
|
||||
int av_color_transfer_from_name(const char *name)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < FF_ARRAY_ELEMS(color_transfer_names); i++) {
|
||||
size_t len = strlen(color_transfer_names[i]);
|
||||
if (!strncmp(color_transfer_names[i], name, len))
|
||||
return i;
|
||||
}
|
||||
|
||||
return AVERROR(EINVAL);
|
||||
}
|
||||
|
||||
const char *av_color_space_name(enum AVColorSpace space)
|
||||
{
|
||||
return (unsigned) space < AVCOL_SPC_NB ?
|
||||
color_space_names[space] : NULL;
|
||||
}
|
||||
|
||||
int av_color_space_from_name(const char *name)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < FF_ARRAY_ELEMS(color_space_names); i++) {
|
||||
size_t len = strlen(color_space_names[i]);
|
||||
if (!strncmp(color_space_names[i], name, len))
|
||||
return i;
|
||||
}
|
||||
|
||||
return AVERROR(EINVAL);
|
||||
}
|
||||
|
||||
const char *av_chroma_location_name(enum AVChromaLocation location)
|
||||
{
|
||||
return (unsigned) location < AVCHROMA_LOC_NB ?
|
||||
chroma_location_names[location] : NULL;
|
||||
}
|
||||
|
||||
int av_chroma_location_from_name(const char *name)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < FF_ARRAY_ELEMS(chroma_location_names); i++) {
|
||||
size_t len = strlen(chroma_location_names[i]);
|
||||
if (!strncmp(chroma_location_names[i], name, len))
|
||||
return i;
|
||||
}
|
||||
|
||||
return AVERROR(EINVAL);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -172,6 +172,17 @@ typedef struct AVPixFmtDescriptor {
|
|||
*/
|
||||
#define AV_PIX_FMT_FLAG_ALPHA (1 << 7)
|
||||
|
||||
/**
|
||||
* The pixel format is following a Bayer pattern
|
||||
*/
|
||||
#define AV_PIX_FMT_FLAG_BAYER (1 << 8)
|
||||
|
||||
/**
|
||||
* The pixel format contains IEEE-754 floating point values. Precision (double,
|
||||
* single, or half) should be determined by the pixel size (64, 32, or 16 bits).
|
||||
*/
|
||||
#define AV_PIX_FMT_FLAG_FLOAT (1 << 9)
|
||||
|
||||
/**
|
||||
* Return the number of bits per pixel used by the pixel format
|
||||
* described by pixdesc. Note that this is not the same as the number
|
||||
|
|
@ -239,26 +250,51 @@ int av_pix_fmt_count_planes(enum AVPixelFormat pix_fmt);
|
|||
*/
|
||||
const char *av_color_range_name(enum AVColorRange range);
|
||||
|
||||
/**
|
||||
* @return the AVColorRange value for name or an AVError if not found.
|
||||
*/
|
||||
int av_color_range_from_name(const char *name);
|
||||
|
||||
/**
|
||||
* @return the name for provided color primaries or NULL if unknown.
|
||||
*/
|
||||
const char *av_color_primaries_name(enum AVColorPrimaries primaries);
|
||||
|
||||
/**
|
||||
* @return the AVColorPrimaries value for name or an AVError if not found.
|
||||
*/
|
||||
int av_color_primaries_from_name(const char *name);
|
||||
|
||||
/**
|
||||
* @return the name for provided color transfer or NULL if unknown.
|
||||
*/
|
||||
const char *av_color_transfer_name(enum AVColorTransferCharacteristic transfer);
|
||||
|
||||
/**
|
||||
* @return the AVColorTransferCharacteristic value for name or an AVError if not found.
|
||||
*/
|
||||
int av_color_transfer_from_name(const char *name);
|
||||
|
||||
/**
|
||||
* @return the name for provided color space or NULL if unknown.
|
||||
*/
|
||||
const char *av_color_space_name(enum AVColorSpace space);
|
||||
|
||||
/**
|
||||
* @return the AVColorSpace value for name or an AVError if not found.
|
||||
*/
|
||||
int av_color_space_from_name(const char *name);
|
||||
|
||||
/**
|
||||
* @return the name for provided chroma location or NULL if unknown.
|
||||
*/
|
||||
const char *av_chroma_location_name(enum AVChromaLocation location);
|
||||
|
||||
/**
|
||||
* @return the AVChromaLocation value for name or an AVError if not found.
|
||||
*/
|
||||
int av_chroma_location_from_name(const char *name);
|
||||
|
||||
/**
|
||||
* Return the pixel format corresponding to name.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -240,7 +240,7 @@ enum AVPixelFormat {
|
|||
*/
|
||||
AV_PIX_FMT_MMAL,
|
||||
|
||||
AV_PIX_FMT_D3D11VA_VLD, ///< HW decoding through Direct3D11, Picture.data[3] contains a ID3D11VideoDecoderOutputView pointer
|
||||
AV_PIX_FMT_D3D11VA_VLD, ///< HW decoding through Direct3D11 via old API, Picture.data[3] contains a ID3D11VideoDecoderOutputView pointer
|
||||
|
||||
/**
|
||||
* HW acceleration through CUDA. data[i] contain CUdeviceptr pointers
|
||||
|
|
@ -306,6 +306,41 @@ enum AVPixelFormat {
|
|||
|
||||
AV_PIX_FMT_MEDIACODEC, ///< hardware decoding through MediaCodec
|
||||
|
||||
AV_PIX_FMT_GRAY12BE, ///< Y , 12bpp, big-endian
|
||||
AV_PIX_FMT_GRAY12LE, ///< Y , 12bpp, little-endian
|
||||
AV_PIX_FMT_GRAY10BE, ///< Y , 10bpp, big-endian
|
||||
AV_PIX_FMT_GRAY10LE, ///< Y , 10bpp, little-endian
|
||||
|
||||
AV_PIX_FMT_P016LE, ///< like NV12, with 16bpp per component, little-endian
|
||||
AV_PIX_FMT_P016BE, ///< like NV12, with 16bpp per component, big-endian
|
||||
|
||||
/**
|
||||
* Hardware surfaces for Direct3D11.
|
||||
*
|
||||
* This is preferred over the legacy AV_PIX_FMT_D3D11VA_VLD. The new D3D11
|
||||
* hwaccel API and filtering support AV_PIX_FMT_D3D11 only.
|
||||
*
|
||||
* data[0] contains a ID3D11Texture2D pointer, and data[1] contains the
|
||||
* texture array index of the frame as intptr_t if the ID3D11Texture2D is
|
||||
* an array texture (or always 0 if it's a normal texture).
|
||||
*/
|
||||
AV_PIX_FMT_D3D11,
|
||||
|
||||
AV_PIX_FMT_GRAY9BE, ///< Y , 9bpp, big-endian
|
||||
AV_PIX_FMT_GRAY9LE, ///< Y , 9bpp, little-endian
|
||||
|
||||
AV_PIX_FMT_GBRPF32BE, ///< IEEE-754 single precision planar GBR 4:4:4, 96bpp, big-endian
|
||||
AV_PIX_FMT_GBRPF32LE, ///< IEEE-754 single precision planar GBR 4:4:4, 96bpp, little-endian
|
||||
AV_PIX_FMT_GBRAPF32BE, ///< IEEE-754 single precision planar GBRA 4:4:4:4, 128bpp, big-endian
|
||||
AV_PIX_FMT_GBRAPF32LE, ///< IEEE-754 single precision planar GBRA 4:4:4:4, 128bpp, little-endian
|
||||
|
||||
/**
|
||||
* DRM-managed buffers exposed through PRIME buffer sharing.
|
||||
*
|
||||
* data[0] points to an AVDRMFrameDescriptor.
|
||||
*/
|
||||
AV_PIX_FMT_DRM_PRIME,
|
||||
|
||||
AV_PIX_FMT_NB ///< number of pixel formats, DO NOT USE THIS if you want to link with shared libav* because the number of formats might differ between versions
|
||||
};
|
||||
|
||||
|
|
@ -322,6 +357,9 @@ enum AVPixelFormat {
|
|||
#define AV_PIX_FMT_0RGB32 AV_PIX_FMT_NE(0RGB, BGR0)
|
||||
#define AV_PIX_FMT_0BGR32 AV_PIX_FMT_NE(0BGR, RGB0)
|
||||
|
||||
#define AV_PIX_FMT_GRAY9 AV_PIX_FMT_NE(GRAY9BE, GRAY9LE)
|
||||
#define AV_PIX_FMT_GRAY10 AV_PIX_FMT_NE(GRAY10BE, GRAY10LE)
|
||||
#define AV_PIX_FMT_GRAY12 AV_PIX_FMT_NE(GRAY12BE, GRAY12LE)
|
||||
#define AV_PIX_FMT_GRAY16 AV_PIX_FMT_NE(GRAY16BE, GRAY16LE)
|
||||
#define AV_PIX_FMT_YA16 AV_PIX_FMT_NE(YA16BE, YA16LE)
|
||||
#define AV_PIX_FMT_RGB48 AV_PIX_FMT_NE(RGB48BE, RGB48LE)
|
||||
|
|
@ -367,6 +405,8 @@ enum AVPixelFormat {
|
|||
#define AV_PIX_FMT_BAYER_GBRG16 AV_PIX_FMT_NE(BAYER_GBRG16BE, BAYER_GBRG16LE)
|
||||
#define AV_PIX_FMT_BAYER_GRBG16 AV_PIX_FMT_NE(BAYER_GRBG16BE, BAYER_GRBG16LE)
|
||||
|
||||
#define AV_PIX_FMT_GBRPF32 AV_PIX_FMT_NE(GBRPF32BE, GBRPF32LE)
|
||||
#define AV_PIX_FMT_GBRAPF32 AV_PIX_FMT_NE(GBRAPF32BE, GBRAPF32LE)
|
||||
|
||||
#define AV_PIX_FMT_YUVA420P9 AV_PIX_FMT_NE(YUVA420P9BE , YUVA420P9LE)
|
||||
#define AV_PIX_FMT_YUVA422P9 AV_PIX_FMT_NE(YUVA422P9BE , YUVA422P9LE)
|
||||
|
|
@ -382,9 +422,11 @@ enum AVPixelFormat {
|
|||
#define AV_PIX_FMT_NV20 AV_PIX_FMT_NE(NV20BE, NV20LE)
|
||||
#define AV_PIX_FMT_AYUV64 AV_PIX_FMT_NE(AYUV64BE, AYUV64LE)
|
||||
#define AV_PIX_FMT_P010 AV_PIX_FMT_NE(P010BE, P010LE)
|
||||
#define AV_PIX_FMT_P016 AV_PIX_FMT_NE(P016BE, P016LE)
|
||||
|
||||
/**
|
||||
* Chromaticity coordinates of the source primaries.
|
||||
* These values match the ones defined by ISO/IEC 23001-8_2013 § 7.1.
|
||||
*/
|
||||
enum AVColorPrimaries {
|
||||
AVCOL_PRI_RESERVED0 = 0,
|
||||
|
|
@ -398,14 +440,17 @@ enum AVColorPrimaries {
|
|||
AVCOL_PRI_SMPTE240M = 7, ///< functionally identical to above
|
||||
AVCOL_PRI_FILM = 8, ///< colour filters using Illuminant C
|
||||
AVCOL_PRI_BT2020 = 9, ///< ITU-R BT2020
|
||||
AVCOL_PRI_SMPTEST428_1 = 10, ///< SMPTE ST 428-1 (CIE 1931 XYZ)
|
||||
AVCOL_PRI_SMPTE431 = 11, ///< SMPTE ST 431-2 (2011)
|
||||
AVCOL_PRI_SMPTE432 = 12, ///< SMPTE ST 432-1 D65 (2010)
|
||||
AVCOL_PRI_SMPTE428 = 10, ///< SMPTE ST 428-1 (CIE 1931 XYZ)
|
||||
AVCOL_PRI_SMPTEST428_1 = AVCOL_PRI_SMPTE428,
|
||||
AVCOL_PRI_SMPTE431 = 11, ///< SMPTE ST 431-2 (2011) / DCI P3
|
||||
AVCOL_PRI_SMPTE432 = 12, ///< SMPTE ST 432-1 (2010) / P3 D65 / Display P3
|
||||
AVCOL_PRI_JEDEC_P22 = 22, ///< JEDEC P22 phosphors
|
||||
AVCOL_PRI_NB ///< Not part of ABI
|
||||
};
|
||||
|
||||
/**
|
||||
* Color Transfer Characteristic.
|
||||
* These values match the ones defined by ISO/IEC 23001-8_2013 § 7.2.
|
||||
*/
|
||||
enum AVColorTransferCharacteristic {
|
||||
AVCOL_TRC_RESERVED0 = 0,
|
||||
|
|
@ -424,14 +469,17 @@ enum AVColorTransferCharacteristic {
|
|||
AVCOL_TRC_IEC61966_2_1 = 13, ///< IEC 61966-2-1 (sRGB or sYCC)
|
||||
AVCOL_TRC_BT2020_10 = 14, ///< ITU-R BT2020 for 10-bit system
|
||||
AVCOL_TRC_BT2020_12 = 15, ///< ITU-R BT2020 for 12-bit system
|
||||
AVCOL_TRC_SMPTEST2084 = 16, ///< SMPTE ST 2084 for 10-, 12-, 14- and 16-bit systems
|
||||
AVCOL_TRC_SMPTEST428_1 = 17, ///< SMPTE ST 428-1
|
||||
AVCOL_TRC_SMPTE2084 = 16, ///< SMPTE ST 2084 for 10-, 12-, 14- and 16-bit systems
|
||||
AVCOL_TRC_SMPTEST2084 = AVCOL_TRC_SMPTE2084,
|
||||
AVCOL_TRC_SMPTE428 = 17, ///< SMPTE ST 428-1
|
||||
AVCOL_TRC_SMPTEST428_1 = AVCOL_TRC_SMPTE428,
|
||||
AVCOL_TRC_ARIB_STD_B67 = 18, ///< ARIB STD-B67, known as "Hybrid log-gamma"
|
||||
AVCOL_TRC_NB ///< Not part of ABI
|
||||
};
|
||||
|
||||
/**
|
||||
* YUV colorspace type.
|
||||
* These values match the ones defined by ISO/IEC 23001-8_2013 § 7.3.
|
||||
*/
|
||||
enum AVColorSpace {
|
||||
AVCOL_SPC_RGB = 0, ///< order of coefficients is actually GBR, also IEC 61966-2-1 (sRGB)
|
||||
|
|
@ -442,14 +490,16 @@ enum AVColorSpace {
|
|||
AVCOL_SPC_BT470BG = 5, ///< also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAM / IEC 61966-2-4 xvYCC601
|
||||
AVCOL_SPC_SMPTE170M = 6, ///< also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC
|
||||
AVCOL_SPC_SMPTE240M = 7, ///< functionally identical to above
|
||||
AVCOL_SPC_YCOCG = 8, ///< Used by Dirac / VC-2 and H.264 FRext, see ITU-T SG16
|
||||
AVCOL_SPC_YCGCO = 8, ///< Used by Dirac / VC-2 and H.264 FRext, see ITU-T SG16
|
||||
AVCOL_SPC_YCOCG = AVCOL_SPC_YCGCO,
|
||||
AVCOL_SPC_BT2020_NCL = 9, ///< ITU-R BT2020 non-constant luminance system
|
||||
AVCOL_SPC_BT2020_CL = 10, ///< ITU-R BT2020 constant luminance system
|
||||
AVCOL_SPC_SMPTE2085 = 11, ///< SMPTE 2085, Y'D'zD'x
|
||||
AVCOL_SPC_CHROMA_DERIVED_NCL = 12, ///< Chromaticity-derived non-constant luminance system
|
||||
AVCOL_SPC_CHROMA_DERIVED_CL = 13, ///< Chromaticity-derived constant luminance system
|
||||
AVCOL_SPC_ICTCP = 14, ///< ITU-R BT.2100-0, ICtCp
|
||||
AVCOL_SPC_NB ///< Not part of ABI
|
||||
};
|
||||
#define AVCOL_SPC_YCGCO AVCOL_SPC_YCOCG
|
||||
|
||||
|
||||
/**
|
||||
* MPEG vs JPEG YUV range.
|
||||
|
|
|
|||
28
media/ffvpx/libavutil/reverse.h
Normal file
28
media/ffvpx/libavutil/reverse.h
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at>
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef AVUTIL_REVERSE_H
|
||||
#define AVUTIL_REVERSE_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
extern const uint8_t ff_reverse[256];
|
||||
|
||||
#endif /* AVUTIL_REVERSE_H */
|
||||
259
media/ffvpx/libavutil/slicethread.c
Normal file
259
media/ffvpx/libavutil/slicethread.c
Normal file
|
|
@ -0,0 +1,259 @@
|
|||
/*
|
||||
* 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 <stdatomic.h>
|
||||
#include "slicethread.h"
|
||||
#include "mem.h"
|
||||
#include "thread.h"
|
||||
#include "avassert.h"
|
||||
|
||||
#if HAVE_PTHREADS || HAVE_W32THREADS || HAVE_OS2THREADS
|
||||
|
||||
typedef struct WorkerContext {
|
||||
AVSliceThread *ctx;
|
||||
pthread_mutex_t mutex;
|
||||
pthread_cond_t cond;
|
||||
pthread_t thread;
|
||||
int done;
|
||||
} WorkerContext;
|
||||
|
||||
struct AVSliceThread {
|
||||
WorkerContext *workers;
|
||||
int nb_threads;
|
||||
int nb_active_threads;
|
||||
int nb_jobs;
|
||||
|
||||
atomic_uint first_job;
|
||||
atomic_uint current_job;
|
||||
pthread_mutex_t done_mutex;
|
||||
pthread_cond_t done_cond;
|
||||
int done;
|
||||
int finished;
|
||||
|
||||
void *priv;
|
||||
void (*worker_func)(void *priv, int jobnr, int threadnr, int nb_jobs, int nb_threads);
|
||||
void (*main_func)(void *priv);
|
||||
};
|
||||
|
||||
static int run_jobs(AVSliceThread *ctx)
|
||||
{
|
||||
unsigned nb_jobs = ctx->nb_jobs;
|
||||
unsigned nb_active_threads = ctx->nb_active_threads;
|
||||
unsigned first_job = atomic_fetch_add_explicit(&ctx->first_job, 1, memory_order_acq_rel);
|
||||
unsigned current_job = first_job;
|
||||
|
||||
do {
|
||||
ctx->worker_func(ctx->priv, current_job, first_job, nb_jobs, nb_active_threads);
|
||||
} while ((current_job = atomic_fetch_add_explicit(&ctx->current_job, 1, memory_order_acq_rel)) < nb_jobs);
|
||||
|
||||
return current_job == nb_jobs + nb_active_threads - 1;
|
||||
}
|
||||
|
||||
static void *attribute_align_arg thread_worker(void *v)
|
||||
{
|
||||
WorkerContext *w = v;
|
||||
AVSliceThread *ctx = w->ctx;
|
||||
|
||||
pthread_mutex_lock(&w->mutex);
|
||||
pthread_cond_signal(&w->cond);
|
||||
|
||||
while (1) {
|
||||
w->done = 1;
|
||||
while (w->done)
|
||||
pthread_cond_wait(&w->cond, &w->mutex);
|
||||
|
||||
if (ctx->finished) {
|
||||
pthread_mutex_unlock(&w->mutex);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (run_jobs(ctx)) {
|
||||
pthread_mutex_lock(&ctx->done_mutex);
|
||||
ctx->done = 1;
|
||||
pthread_cond_signal(&ctx->done_cond);
|
||||
pthread_mutex_unlock(&ctx->done_mutex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int avpriv_slicethread_create(AVSliceThread **pctx, void *priv,
|
||||
void (*worker_func)(void *priv, int jobnr, int threadnr, int nb_jobs, int nb_threads),
|
||||
void (*main_func)(void *priv),
|
||||
int nb_threads)
|
||||
{
|
||||
AVSliceThread *ctx;
|
||||
int nb_workers, i;
|
||||
|
||||
#if HAVE_W32THREADS
|
||||
w32thread_init();
|
||||
#endif
|
||||
|
||||
av_assert0(nb_threads >= 0);
|
||||
if (!nb_threads) {
|
||||
int nb_cpus = av_cpu_count();
|
||||
if (nb_cpus > 1)
|
||||
nb_threads = nb_cpus + 1;
|
||||
else
|
||||
nb_threads = 1;
|
||||
}
|
||||
|
||||
nb_workers = nb_threads;
|
||||
if (!main_func)
|
||||
nb_workers--;
|
||||
|
||||
*pctx = ctx = av_mallocz(sizeof(*ctx));
|
||||
if (!ctx)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
if (nb_workers && !(ctx->workers = av_calloc(nb_workers, sizeof(*ctx->workers)))) {
|
||||
av_freep(pctx);
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
|
||||
ctx->priv = priv;
|
||||
ctx->worker_func = worker_func;
|
||||
ctx->main_func = main_func;
|
||||
ctx->nb_threads = nb_threads;
|
||||
ctx->nb_active_threads = 0;
|
||||
ctx->nb_jobs = 0;
|
||||
ctx->finished = 0;
|
||||
|
||||
atomic_init(&ctx->first_job, 0);
|
||||
atomic_init(&ctx->current_job, 0);
|
||||
pthread_mutex_init(&ctx->done_mutex, NULL);
|
||||
pthread_cond_init(&ctx->done_cond, NULL);
|
||||
ctx->done = 0;
|
||||
|
||||
for (i = 0; i < nb_workers; i++) {
|
||||
WorkerContext *w = &ctx->workers[i];
|
||||
int ret;
|
||||
w->ctx = ctx;
|
||||
pthread_mutex_init(&w->mutex, NULL);
|
||||
pthread_cond_init(&w->cond, NULL);
|
||||
pthread_mutex_lock(&w->mutex);
|
||||
w->done = 0;
|
||||
|
||||
if (ret = pthread_create(&w->thread, NULL, thread_worker, w)) {
|
||||
ctx->nb_threads = main_func ? i : i + 1;
|
||||
pthread_mutex_unlock(&w->mutex);
|
||||
pthread_cond_destroy(&w->cond);
|
||||
pthread_mutex_destroy(&w->mutex);
|
||||
avpriv_slicethread_free(pctx);
|
||||
return AVERROR(ret);
|
||||
}
|
||||
|
||||
while (!w->done)
|
||||
pthread_cond_wait(&w->cond, &w->mutex);
|
||||
pthread_mutex_unlock(&w->mutex);
|
||||
}
|
||||
|
||||
return nb_threads;
|
||||
}
|
||||
|
||||
void avpriv_slicethread_execute(AVSliceThread *ctx, int nb_jobs, int execute_main)
|
||||
{
|
||||
int nb_workers, i, is_last = 0;
|
||||
|
||||
av_assert0(nb_jobs > 0);
|
||||
ctx->nb_jobs = nb_jobs;
|
||||
ctx->nb_active_threads = FFMIN(nb_jobs, ctx->nb_threads);
|
||||
atomic_store_explicit(&ctx->first_job, 0, memory_order_relaxed);
|
||||
atomic_store_explicit(&ctx->current_job, ctx->nb_active_threads, memory_order_relaxed);
|
||||
nb_workers = ctx->nb_active_threads;
|
||||
if (!ctx->main_func || !execute_main)
|
||||
nb_workers--;
|
||||
|
||||
for (i = 0; i < nb_workers; i++) {
|
||||
WorkerContext *w = &ctx->workers[i];
|
||||
pthread_mutex_lock(&w->mutex);
|
||||
w->done = 0;
|
||||
pthread_cond_signal(&w->cond);
|
||||
pthread_mutex_unlock(&w->mutex);
|
||||
}
|
||||
|
||||
if (ctx->main_func && execute_main)
|
||||
ctx->main_func(ctx->priv);
|
||||
else
|
||||
is_last = run_jobs(ctx);
|
||||
|
||||
if (!is_last) {
|
||||
pthread_mutex_lock(&ctx->done_mutex);
|
||||
while (!ctx->done)
|
||||
pthread_cond_wait(&ctx->done_cond, &ctx->done_mutex);
|
||||
ctx->done = 0;
|
||||
pthread_mutex_unlock(&ctx->done_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
void avpriv_slicethread_free(AVSliceThread **pctx)
|
||||
{
|
||||
AVSliceThread *ctx;
|
||||
int nb_workers, i;
|
||||
|
||||
if (!pctx || !*pctx)
|
||||
return;
|
||||
|
||||
ctx = *pctx;
|
||||
nb_workers = ctx->nb_threads;
|
||||
if (!ctx->main_func)
|
||||
nb_workers--;
|
||||
|
||||
ctx->finished = 1;
|
||||
for (i = 0; i < nb_workers; i++) {
|
||||
WorkerContext *w = &ctx->workers[i];
|
||||
pthread_mutex_lock(&w->mutex);
|
||||
w->done = 0;
|
||||
pthread_cond_signal(&w->cond);
|
||||
pthread_mutex_unlock(&w->mutex);
|
||||
}
|
||||
|
||||
for (i = 0; i < nb_workers; i++) {
|
||||
WorkerContext *w = &ctx->workers[i];
|
||||
pthread_join(w->thread, NULL);
|
||||
pthread_cond_destroy(&w->cond);
|
||||
pthread_mutex_destroy(&w->mutex);
|
||||
}
|
||||
|
||||
pthread_cond_destroy(&ctx->done_cond);
|
||||
pthread_mutex_destroy(&ctx->done_mutex);
|
||||
av_freep(&ctx->workers);
|
||||
av_freep(pctx);
|
||||
}
|
||||
|
||||
#else /* HAVE_PTHREADS || HAVE_W32THREADS || HAVE_OS32THREADS */
|
||||
|
||||
int avpriv_slicethread_create(AVSliceThread **pctx, void *priv,
|
||||
void (*worker_func)(void *priv, int jobnr, int threadnr, int nb_jobs, int nb_threads),
|
||||
void (*main_func)(void *priv),
|
||||
int nb_threads)
|
||||
{
|
||||
*pctx = NULL;
|
||||
return AVERROR(EINVAL);
|
||||
}
|
||||
|
||||
void avpriv_slicethread_execute(AVSliceThread *ctx, int nb_jobs, int execute_main)
|
||||
{
|
||||
av_assert0(0);
|
||||
}
|
||||
|
||||
void avpriv_slicethread_free(AVSliceThread **pctx)
|
||||
{
|
||||
av_assert0(!pctx || !*pctx);
|
||||
}
|
||||
|
||||
#endif /* HAVE_PTHREADS || HAVE_W32THREADS || HAVE_OS32THREADS */
|
||||
52
media/ffvpx/libavutil/slicethread.h
Normal file
52
media/ffvpx/libavutil/slicethread.h
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* 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 AVUTIL_SLICETHREAD_H
|
||||
#define AVUTIL_SLICETHREAD_H
|
||||
|
||||
typedef struct AVSliceThread AVSliceThread;
|
||||
|
||||
/**
|
||||
* Create slice threading context.
|
||||
* @param pctx slice threading context returned here
|
||||
* @param priv private pointer to be passed to callback function
|
||||
* @param worker_func callback function to be executed
|
||||
* @param main_func special callback function, called from main thread, may be NULL
|
||||
* @param nb_threads number of threads, 0 for automatic, must be >= 0
|
||||
* @return return number of threads or negative AVERROR on failure
|
||||
*/
|
||||
int avpriv_slicethread_create(AVSliceThread **pctx, void *priv,
|
||||
void (*worker_func)(void *priv, int jobnr, int threadnr, int nb_jobs, int nb_threads),
|
||||
void (*main_func)(void *priv),
|
||||
int nb_threads);
|
||||
|
||||
/**
|
||||
* Execute slice threading.
|
||||
* @param ctx slice threading context
|
||||
* @param nb_jobs number of jobs, must be > 0
|
||||
* @param execute_main also execute main_func
|
||||
*/
|
||||
void avpriv_slicethread_execute(AVSliceThread *ctx, int nb_jobs, int execute_main);
|
||||
|
||||
/**
|
||||
* Destroy slice threading context.
|
||||
* @param pctx pointer to context
|
||||
*/
|
||||
void avpriv_slicethread_free(AVSliceThread **pctx);
|
||||
|
||||
#endif
|
||||
|
|
@ -26,8 +26,6 @@
|
|||
|
||||
#if HAVE_PTHREADS || HAVE_W32THREADS || HAVE_OS2THREADS
|
||||
|
||||
#define USE_ATOMICS 0
|
||||
|
||||
#if HAVE_PTHREADS
|
||||
#include <pthread.h>
|
||||
|
||||
|
|
@ -38,8 +36,11 @@
|
|||
#define ASSERT_PTHREAD_NORET(func, ...) do { \
|
||||
int ret = func(__VA_ARGS__); \
|
||||
if (ret) { \
|
||||
char errbuf[AV_ERROR_MAX_STRING_SIZE] = ""; \
|
||||
av_log(NULL, AV_LOG_FATAL, AV_STRINGIFY(func) \
|
||||
" failed with error: %s\n", av_err2str(AVERROR(ret))); \
|
||||
" failed with error: %s\n", \
|
||||
av_make_error_string(errbuf, AV_ERROR_MAX_STRING_SIZE, \
|
||||
AVERROR(ret))); \
|
||||
abort(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
|
@ -146,8 +147,6 @@ static inline int strict_pthread_once(pthread_once_t *once_control, void (*init_
|
|||
|
||||
#else
|
||||
|
||||
#define USE_ATOMICS 1
|
||||
|
||||
#define AVMutex char
|
||||
|
||||
#define ff_mutex_init(mutex, attr) (0)
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ int av_thread_message_queue_alloc(AVThreadMessageQueue **mq,
|
|||
pthread_cond_destroy(&rmq->cond_recv);
|
||||
pthread_mutex_destroy(&rmq->lock);
|
||||
av_free(rmq);
|
||||
return AVERROR(ret);
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
rmq->elsize = elsize;
|
||||
*mq = rmq;
|
||||
|
|
|
|||
|
|
@ -56,17 +56,25 @@ int64_t av_gettime(void)
|
|||
int64_t av_gettime_relative(void)
|
||||
{
|
||||
#if HAVE_CLOCK_GETTIME && defined(CLOCK_MONOTONIC)
|
||||
struct timespec ts;
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
return (int64_t)ts.tv_sec * 1000000 + ts.tv_nsec / 1000;
|
||||
#else
|
||||
return av_gettime() + 42 * 60 * 60 * INT64_C(1000000);
|
||||
#ifdef __APPLE__
|
||||
if (clock_gettime)
|
||||
#endif
|
||||
{
|
||||
struct timespec ts;
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
return (int64_t)ts.tv_sec * 1000000 + ts.tv_nsec / 1000;
|
||||
}
|
||||
#endif
|
||||
return av_gettime() + 42 * 60 * 60 * INT64_C(1000000);
|
||||
}
|
||||
|
||||
int av_gettime_relative_is_monotonic(void)
|
||||
{
|
||||
#if HAVE_CLOCK_GETTIME && defined(CLOCK_MONOTONIC)
|
||||
#ifdef __APPLE__
|
||||
if (!clock_gettime)
|
||||
return 0;
|
||||
#endif
|
||||
return 1;
|
||||
#else
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -129,7 +129,8 @@ char *av_timecode_make_smpte_tc_string(char *buf, uint32_t tcsmpte, int prevent_
|
|||
|
||||
char *av_timecode_make_mpeg_tc_string(char *buf, uint32_t tc25bit)
|
||||
{
|
||||
snprintf(buf, AV_TIMECODE_STR_SIZE, "%02u:%02u:%02u%c%02u",
|
||||
snprintf(buf, AV_TIMECODE_STR_SIZE,
|
||||
"%02"PRIu32":%02"PRIu32":%02"PRIu32"%c%02"PRIu32,
|
||||
tc25bit>>19 & 0x1f, // 5-bit hours
|
||||
tc25bit>>13 & 0x3f, // 6-bit minutes
|
||||
tc25bit>>6 & 0x3f, // 6-bit seconds
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@
|
|||
#include <stdint.h>
|
||||
#include "rational.h"
|
||||
|
||||
#define AV_TIMECODE_STR_SIZE 16
|
||||
#define AV_TIMECODE_STR_SIZE 23
|
||||
|
||||
enum AVTimecodeFlag {
|
||||
AV_TIMECODE_FLAG_DROPFRAME = 1<<0, ///< timecode is drop frame
|
||||
|
|
|
|||
|
|
@ -26,12 +26,22 @@
|
|||
#ifndef AVUTIL_TIMER_H
|
||||
#define AVUTIL_TIMER_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#if CONFIG_LINUX_PERF
|
||||
# ifndef _GNU_SOURCE
|
||||
# define _GNU_SOURCE
|
||||
# endif
|
||||
# include <unistd.h> // read(3)
|
||||
# include <sys/ioctl.h>
|
||||
# include <asm/unistd.h>
|
||||
# include <linux/perf_event.h>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#if HAVE_MACH_MACH_TIME_H
|
||||
#include <mach/mach_time.h>
|
||||
#endif
|
||||
|
|
@ -60,23 +70,17 @@
|
|||
# define FF_TIMER_UNITS "UNITS"
|
||||
#endif
|
||||
|
||||
#ifdef AV_READ_TIME
|
||||
#define START_TIMER \
|
||||
uint64_t tend; \
|
||||
uint64_t tstart = AV_READ_TIME(); \
|
||||
|
||||
#define STOP_TIMER(id) \
|
||||
tend = AV_READ_TIME(); \
|
||||
#define TIMER_REPORT(id, tdiff) \
|
||||
{ \
|
||||
static uint64_t tsum = 0; \
|
||||
static int tcount = 0; \
|
||||
static int tskip_count = 0; \
|
||||
static int thistogram[32] = {0}; \
|
||||
thistogram[av_log2(tend - tstart)]++; \
|
||||
if (tcount < 2 || \
|
||||
tend - tstart < 8 * tsum / tcount || \
|
||||
tend - tstart < 2000) { \
|
||||
tsum+= tend - tstart; \
|
||||
thistogram[av_log2(tdiff)]++; \
|
||||
if (tcount < 2 || \
|
||||
(tdiff) < 8 * tsum / tcount || \
|
||||
(tdiff) < 2000) { \
|
||||
tsum += (tdiff); \
|
||||
tcount++; \
|
||||
} else \
|
||||
tskip_count++; \
|
||||
|
|
@ -90,6 +94,45 @@
|
|||
av_log(NULL, AV_LOG_ERROR, "\n"); \
|
||||
} \
|
||||
}
|
||||
|
||||
#if CONFIG_LINUX_PERF
|
||||
|
||||
#define START_TIMER \
|
||||
static int linux_perf_fd; \
|
||||
uint64_t tperf; \
|
||||
if (!linux_perf_fd) { \
|
||||
struct perf_event_attr attr = { \
|
||||
.type = PERF_TYPE_HARDWARE, \
|
||||
.size = sizeof(struct perf_event_attr), \
|
||||
.config = PERF_COUNT_HW_CPU_CYCLES, \
|
||||
.disabled = 1, \
|
||||
.exclude_kernel = 1, \
|
||||
.exclude_hv = 1, \
|
||||
}; \
|
||||
linux_perf_fd = syscall(__NR_perf_event_open, &attr, \
|
||||
0, -1, -1, 0); \
|
||||
} \
|
||||
if (linux_perf_fd == -1) { \
|
||||
av_log(NULL, AV_LOG_ERROR, "perf_event_open failed: %s\n", \
|
||||
av_err2str(AVERROR(errno))); \
|
||||
} else { \
|
||||
ioctl(linux_perf_fd, PERF_EVENT_IOC_RESET, 0); \
|
||||
ioctl(linux_perf_fd, PERF_EVENT_IOC_ENABLE, 0); \
|
||||
}
|
||||
|
||||
#define STOP_TIMER(id) \
|
||||
ioctl(linux_perf_fd, PERF_EVENT_IOC_DISABLE, 0); \
|
||||
read(linux_perf_fd, &tperf, sizeof(tperf)); \
|
||||
TIMER_REPORT(id, tperf)
|
||||
|
||||
#elif defined(AV_READ_TIME)
|
||||
#define START_TIMER \
|
||||
uint64_t tend; \
|
||||
uint64_t tstart = AV_READ_TIME(); \
|
||||
|
||||
#define STOP_TIMER(id) \
|
||||
tend = AV_READ_TIME(); \
|
||||
TIMER_REPORT(id, tend - tstart)
|
||||
#else
|
||||
#define START_TIMER
|
||||
#define STOP_TIMER(id) { }
|
||||
|
|
|
|||
|
|
@ -121,6 +121,29 @@ unsigned av_int_list_length_for_size(unsigned elsize,
|
|||
return i;
|
||||
}
|
||||
|
||||
char *av_fourcc_make_string(char *buf, uint32_t fourcc)
|
||||
{
|
||||
int i;
|
||||
char *orig_buf = buf;
|
||||
size_t buf_size = AV_FOURCC_MAX_STRING_SIZE;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
const int c = fourcc & 0xff;
|
||||
const int print_chr = (c >= '0' && c <= '9') ||
|
||||
(c >= 'a' && c <= 'z') ||
|
||||
(c >= 'A' && c <= 'Z') ||
|
||||
(c && strchr(". -_", c));
|
||||
const int len = snprintf(buf, buf_size, print_chr ? "%c" : "[%d]", c);
|
||||
if (len < 0)
|
||||
break;
|
||||
buf += len;
|
||||
buf_size = buf_size > len ? buf_size - len : 0;
|
||||
fourcc >>= 8;
|
||||
}
|
||||
|
||||
return orig_buf;
|
||||
}
|
||||
|
||||
AVRational av_get_time_base_q(void)
|
||||
{
|
||||
return (AVRational){1, AV_TIME_BASE};
|
||||
|
|
@ -129,7 +152,7 @@ AVRational av_get_time_base_q(void)
|
|||
void av_assert0_fpu(void) {
|
||||
#if HAVE_MMX_INLINE
|
||||
uint16_t state[14];
|
||||
__asm volatile (
|
||||
__asm__ volatile (
|
||||
"fstenv %0 \n\t"
|
||||
: "+m" (state)
|
||||
:
|
||||
|
|
|
|||
|
|
@ -78,8 +78,9 @@
|
|||
* @{
|
||||
*/
|
||||
|
||||
|
||||
#define LIBAVUTIL_VERSION_MAJOR 55
|
||||
#define LIBAVUTIL_VERSION_MINOR 34
|
||||
#define LIBAVUTIL_VERSION_MINOR 78
|
||||
#define LIBAVUTIL_VERSION_MICRO 100
|
||||
|
||||
#define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \
|
||||
|
|
@ -135,6 +136,9 @@
|
|||
#ifndef FF_API_PKT_PTS
|
||||
#define FF_API_PKT_PTS (LIBAVUTIL_VERSION_MAJOR < 56)
|
||||
#endif
|
||||
#ifndef FF_API_CRYPTO_SIZE_T
|
||||
#define FF_API_CRYPTO_SIZE_T (LIBAVUTIL_VERSION_MAJOR < 56)
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@
|
|||
#include "libavutil/cpu.h"
|
||||
#include "libavutil/cpu_internal.h"
|
||||
|
||||
#if HAVE_YASM
|
||||
#if HAVE_X86ASM
|
||||
|
||||
#define cpuid(index, eax, ebx, ecx, edx) \
|
||||
ff_cpu_cpuid(index, &eax, &ebx, &ecx, &edx)
|
||||
|
|
@ -66,7 +66,7 @@
|
|||
|
||||
#define cpuid_test() 1
|
||||
|
||||
#elif HAVE_YASM
|
||||
#elif HAVE_X86ASM
|
||||
|
||||
#define cpuid_test ff_cpu_cpuid_test
|
||||
|
||||
|
|
@ -221,9 +221,42 @@ int ff_get_cpu_flags_x86(void)
|
|||
* functions on the Atom. */
|
||||
if (family == 6 && model == 28)
|
||||
rval |= AV_CPU_FLAG_ATOM;
|
||||
|
||||
/* Conroe has a slow shuffle unit. Check the model number to ensure not
|
||||
* to include crippled low-end Penryns and Nehalems that lack SSE4. */
|
||||
if ((rval & AV_CPU_FLAG_SSSE3) && !(rval & AV_CPU_FLAG_SSE4) &&
|
||||
family == 6 && model < 23)
|
||||
rval |= AV_CPU_FLAG_SSSE3SLOW;
|
||||
}
|
||||
|
||||
#endif /* cpuid */
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
size_t ff_get_cpu_max_align_x86(void)
|
||||
{
|
||||
int flags = av_get_cpu_flags();
|
||||
|
||||
if (flags & (AV_CPU_FLAG_AVX2 |
|
||||
AV_CPU_FLAG_AVX |
|
||||
AV_CPU_FLAG_XOP |
|
||||
AV_CPU_FLAG_FMA4 |
|
||||
AV_CPU_FLAG_FMA3 |
|
||||
AV_CPU_FLAG_AVXSLOW))
|
||||
return 32;
|
||||
if (flags & (AV_CPU_FLAG_AESNI |
|
||||
AV_CPU_FLAG_SSE42 |
|
||||
AV_CPU_FLAG_SSE4 |
|
||||
AV_CPU_FLAG_SSSE3 |
|
||||
AV_CPU_FLAG_SSE3 |
|
||||
AV_CPU_FLAG_SSE2 |
|
||||
AV_CPU_FLAG_SSE |
|
||||
AV_CPU_FLAG_ATOM |
|
||||
AV_CPU_FLAG_SSSE3SLOW |
|
||||
AV_CPU_FLAG_SSE3SLOW |
|
||||
AV_CPU_FLAG_SSE2SLOW))
|
||||
return 16;
|
||||
|
||||
return 8;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,6 +38,8 @@
|
|||
#define X86_SSE3_FAST(flags) CPUEXT_FAST(flags, SSE3)
|
||||
#define X86_SSE3_SLOW(flags) CPUEXT_SLOW(flags, SSE3)
|
||||
#define X86_SSSE3(flags) CPUEXT(flags, SSSE3)
|
||||
#define X86_SSSE3_FAST(flags) CPUEXT_FAST(flags, SSSE3)
|
||||
#define X86_SSSE3_SLOW(flags) CPUEXT_SLOW(flags, SSSE3)
|
||||
#define X86_SSE4(flags) CPUEXT(flags, SSE4)
|
||||
#define X86_SSE42(flags) CPUEXT(flags, SSE42)
|
||||
#define X86_AVX(flags) CPUEXT(flags, AVX)
|
||||
|
|
@ -61,6 +63,8 @@
|
|||
#define EXTERNAL_SSE3_FAST(flags) CPUEXT_SUFFIX_FAST(flags, _EXTERNAL, SSE3)
|
||||
#define EXTERNAL_SSE3_SLOW(flags) CPUEXT_SUFFIX_SLOW(flags, _EXTERNAL, SSE3)
|
||||
#define EXTERNAL_SSSE3(flags) CPUEXT_SUFFIX(flags, _EXTERNAL, SSSE3)
|
||||
#define EXTERNAL_SSSE3_FAST(flags) CPUEXT_SUFFIX_FAST(flags, _EXTERNAL, SSSE3)
|
||||
#define EXTERNAL_SSSE3_SLOW(flags) CPUEXT_SUFFIX_SLOW(flags, _EXTERNAL, SSSE3)
|
||||
#define EXTERNAL_SSE4(flags) CPUEXT_SUFFIX(flags, _EXTERNAL, SSE4)
|
||||
#define EXTERNAL_SSE42(flags) CPUEXT_SUFFIX(flags, _EXTERNAL, SSE42)
|
||||
#define EXTERNAL_AVX(flags) CPUEXT_SUFFIX(flags, _EXTERNAL, AVX)
|
||||
|
|
@ -88,6 +92,8 @@
|
|||
#define INLINE_SSE3_FAST(flags) CPUEXT_SUFFIX_FAST(flags, _INLINE, SSE3)
|
||||
#define INLINE_SSE3_SLOW(flags) CPUEXT_SUFFIX_SLOW(flags, _INLINE, SSE3)
|
||||
#define INLINE_SSSE3(flags) CPUEXT_SUFFIX(flags, _INLINE, SSSE3)
|
||||
#define INLINE_SSSE3_FAST(flags) CPUEXT_SUFFIX_FAST(flags, _INLINE, SSSE3)
|
||||
#define INLINE_SSSE3_SLOW(flags) CPUEXT_SUFFIX_SLOW(flags, _INLINE, SSSE3)
|
||||
#define INLINE_SSE4(flags) CPUEXT_SUFFIX(flags, _INLINE, SSE4)
|
||||
#define INLINE_SSE42(flags) CPUEXT_SUFFIX(flags, _INLINE, SSE42)
|
||||
#define INLINE_AVX(flags) CPUEXT_SUFFIX(flags, _INLINE, AVX)
|
||||
|
|
|
|||
|
|
@ -23,8 +23,8 @@
|
|||
SECTION .text
|
||||
|
||||
;-----------------------------------------------------------------------------
|
||||
; void avpriv_emms_yasm(void)
|
||||
; void avpriv_emms_asm(void)
|
||||
;-----------------------------------------------------------------------------
|
||||
cvisible emms_yasm, 0, 0
|
||||
cvisible emms_asm, 0, 0
|
||||
emms
|
||||
RET
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
#include "libavutil/attributes.h"
|
||||
#include "libavutil/cpu.h"
|
||||
|
||||
void avpriv_emms_yasm(void);
|
||||
void avpriv_emms_asm(void);
|
||||
|
||||
#if HAVE_MMX_INLINE
|
||||
# define emms_c emms_c
|
||||
|
|
@ -49,7 +49,7 @@ static av_always_inline void emms_c(void)
|
|||
# include <mmintrin.h>
|
||||
# define emms_c _mm_empty
|
||||
#elif HAVE_MMX_EXTERNAL
|
||||
# define emms_c avpriv_emms_yasm
|
||||
# define emms_c avpriv_emms_asm
|
||||
#endif /* HAVE_MMX_INLINE */
|
||||
|
||||
#endif /* AVUTIL_X86_EMMS_H */
|
||||
|
|
|
|||
|
|
@ -22,6 +22,9 @@
|
|||
|
||||
%include "x86util.asm"
|
||||
|
||||
SECTION_RODATA 32
|
||||
pd_reverse: dd 7, 6, 5, 4, 3, 2, 1, 0
|
||||
|
||||
SECTION .text
|
||||
|
||||
;-----------------------------------------------------------------------------
|
||||
|
|
@ -148,6 +151,69 @@ cglobal vector_fmul_scalar, 4,4,3, dst, src, mul, len
|
|||
INIT_XMM sse
|
||||
VECTOR_FMUL_SCALAR
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
; void ff_vector_dmac_scalar(double *dst, const double *src, double mul,
|
||||
; int len)
|
||||
;------------------------------------------------------------------------------
|
||||
|
||||
%macro VECTOR_DMAC_SCALAR 0
|
||||
%if ARCH_X86_32
|
||||
cglobal vector_dmac_scalar, 2,4,5, dst, src, mul, len, lenaddr
|
||||
mov lenq, lenaddrm
|
||||
VBROADCASTSD m0, mulm
|
||||
%else
|
||||
%if UNIX64
|
||||
cglobal vector_dmac_scalar, 3,3,5, dst, src, len
|
||||
%else
|
||||
cglobal vector_dmac_scalar, 4,4,5, dst, src, mul, len
|
||||
SWAP 0, 2
|
||||
%endif
|
||||
movlhps xm0, xm0
|
||||
%if cpuflag(avx)
|
||||
vinsertf128 m0, m0, xm0, 1
|
||||
%endif
|
||||
%endif
|
||||
lea lenq, [lend*8-mmsize*4]
|
||||
.loop:
|
||||
%if cpuflag(fma3)
|
||||
movaps m1, [dstq+lenq]
|
||||
movaps m2, [dstq+lenq+1*mmsize]
|
||||
movaps m3, [dstq+lenq+2*mmsize]
|
||||
movaps m4, [dstq+lenq+3*mmsize]
|
||||
fmaddpd m1, m0, [srcq+lenq], m1
|
||||
fmaddpd m2, m0, [srcq+lenq+1*mmsize], m2
|
||||
fmaddpd m3, m0, [srcq+lenq+2*mmsize], m3
|
||||
fmaddpd m4, m0, [srcq+lenq+3*mmsize], m4
|
||||
%else ; cpuflag
|
||||
mulpd m1, m0, [srcq+lenq]
|
||||
mulpd m2, m0, [srcq+lenq+1*mmsize]
|
||||
mulpd m3, m0, [srcq+lenq+2*mmsize]
|
||||
mulpd m4, m0, [srcq+lenq+3*mmsize]
|
||||
addpd m1, m1, [dstq+lenq]
|
||||
addpd m2, m2, [dstq+lenq+1*mmsize]
|
||||
addpd m3, m3, [dstq+lenq+2*mmsize]
|
||||
addpd m4, m4, [dstq+lenq+3*mmsize]
|
||||
%endif ; cpuflag
|
||||
movaps [dstq+lenq], m1
|
||||
movaps [dstq+lenq+1*mmsize], m2
|
||||
movaps [dstq+lenq+2*mmsize], m3
|
||||
movaps [dstq+lenq+3*mmsize], m4
|
||||
sub lenq, mmsize*4
|
||||
jge .loop
|
||||
REP_RET
|
||||
%endmacro
|
||||
|
||||
INIT_XMM sse2
|
||||
VECTOR_DMAC_SCALAR
|
||||
%if HAVE_AVX_EXTERNAL
|
||||
INIT_YMM avx
|
||||
VECTOR_DMAC_SCALAR
|
||||
%endif
|
||||
%if HAVE_FMA3_EXTERNAL
|
||||
INIT_YMM fma3
|
||||
VECTOR_DMAC_SCALAR
|
||||
%endif
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
; void ff_vector_dmul_scalar(double *dst, const double *src, double mul,
|
||||
; int len)
|
||||
|
|
@ -177,8 +243,8 @@ cglobal vector_dmul_scalar, 4,4,3, dst, src, mul, len
|
|||
.loop:
|
||||
mulpd m1, m0, [srcq+lenq ]
|
||||
mulpd m2, m0, [srcq+lenq+mmsize]
|
||||
mova [dstq+lenq ], m1
|
||||
mova [dstq+lenq+mmsize], m2
|
||||
movaps [dstq+lenq ], m1
|
||||
movaps [dstq+lenq+mmsize], m2
|
||||
sub lenq, 2*mmsize
|
||||
jge .loop
|
||||
REP_RET
|
||||
|
|
@ -296,10 +362,16 @@ VECTOR_FMUL_ADD
|
|||
;-----------------------------------------------------------------------------
|
||||
%macro VECTOR_FMUL_REVERSE 0
|
||||
cglobal vector_fmul_reverse, 4,4,2, dst, src0, src1, len
|
||||
%if cpuflag(avx2)
|
||||
movaps m2, [pd_reverse]
|
||||
%endif
|
||||
lea lenq, [lend*4 - 2*mmsize]
|
||||
ALIGN 16
|
||||
.loop:
|
||||
%if cpuflag(avx)
|
||||
%if cpuflag(avx2)
|
||||
vpermps m0, m2, [src1q]
|
||||
vpermps m1, m2, [src1q+mmsize]
|
||||
%elif cpuflag(avx)
|
||||
vmovaps xmm0, [src1q + 16]
|
||||
vinsertf128 m0, m0, [src1q], 1
|
||||
vshufps m0, m0, m0, q0123
|
||||
|
|
@ -314,8 +386,8 @@ ALIGN 16
|
|||
%endif
|
||||
mulps m0, m0, [src0q + lenq + mmsize]
|
||||
mulps m1, m1, [src0q + lenq]
|
||||
mova [dstq + lenq + mmsize], m0
|
||||
mova [dstq + lenq], m1
|
||||
movaps [dstq + lenq + mmsize], m0
|
||||
movaps [dstq + lenq], m1
|
||||
add src1q, 2*mmsize
|
||||
sub lenq, 2*mmsize
|
||||
jge .loop
|
||||
|
|
@ -328,6 +400,10 @@ VECTOR_FMUL_REVERSE
|
|||
INIT_YMM avx
|
||||
VECTOR_FMUL_REVERSE
|
||||
%endif
|
||||
%if HAVE_AVX2_EXTERNAL
|
||||
INIT_YMM avx2
|
||||
VECTOR_FMUL_REVERSE
|
||||
%endif
|
||||
|
||||
; float scalarproduct_float_sse(const float *v1, const float *v2, int len)
|
||||
INIT_XMM sse
|
||||
|
|
|
|||
|
|
@ -39,6 +39,13 @@ void ff_vector_fmac_scalar_fma3(float *dst, const float *src, float mul,
|
|||
void ff_vector_fmul_scalar_sse(float *dst, const float *src, float mul,
|
||||
int len);
|
||||
|
||||
void ff_vector_dmac_scalar_sse2(double *dst, const double *src, double mul,
|
||||
int len);
|
||||
void ff_vector_dmac_scalar_avx(double *dst, const double *src, double mul,
|
||||
int len);
|
||||
void ff_vector_dmac_scalar_fma3(double *dst, const double *src, double mul,
|
||||
int len);
|
||||
|
||||
void ff_vector_dmul_scalar_sse2(double *dst, const double *src,
|
||||
double mul, int len);
|
||||
void ff_vector_dmul_scalar_avx(double *dst, const double *src,
|
||||
|
|
@ -60,10 +67,12 @@ void ff_vector_fmul_reverse_sse(float *dst, const float *src0,
|
|||
const float *src1, int len);
|
||||
void ff_vector_fmul_reverse_avx(float *dst, const float *src0,
|
||||
const float *src1, int len);
|
||||
void ff_vector_fmul_reverse_avx2(float *dst, const float *src0,
|
||||
const float *src1, int len);
|
||||
|
||||
float ff_scalarproduct_float_sse(const float *v1, const float *v2, int order);
|
||||
|
||||
void ff_butterflies_float_sse(float *src0, float *src1, int len);
|
||||
void ff_butterflies_float_sse(float *av_restrict src0, float *av_restrict src1, int len);
|
||||
|
||||
av_cold void ff_float_dsp_init_x86(AVFloatDSPContext *fdsp)
|
||||
{
|
||||
|
|
@ -83,17 +92,23 @@ av_cold void ff_float_dsp_init_x86(AVFloatDSPContext *fdsp)
|
|||
fdsp->butterflies_float = ff_butterflies_float_sse;
|
||||
}
|
||||
if (EXTERNAL_SSE2(cpu_flags)) {
|
||||
fdsp->vector_dmac_scalar = ff_vector_dmac_scalar_sse2;
|
||||
fdsp->vector_dmul_scalar = ff_vector_dmul_scalar_sse2;
|
||||
}
|
||||
if (EXTERNAL_AVX_FAST(cpu_flags)) {
|
||||
fdsp->vector_fmul = ff_vector_fmul_avx;
|
||||
fdsp->vector_fmac_scalar = ff_vector_fmac_scalar_avx;
|
||||
fdsp->vector_dmul_scalar = ff_vector_dmul_scalar_avx;
|
||||
fdsp->vector_dmac_scalar = ff_vector_dmac_scalar_avx;
|
||||
fdsp->vector_fmul_add = ff_vector_fmul_add_avx;
|
||||
fdsp->vector_fmul_reverse = ff_vector_fmul_reverse_avx;
|
||||
}
|
||||
if (EXTERNAL_AVX2_FAST(cpu_flags)) {
|
||||
fdsp->vector_fmul_reverse = ff_vector_fmul_reverse_avx2;
|
||||
}
|
||||
if (EXTERNAL_FMA3_FAST(cpu_flags)) {
|
||||
fdsp->vector_fmac_scalar = ff_vector_fmac_scalar_fma3;
|
||||
fdsp->vector_fmul_add = ff_vector_fmul_add_fma3;
|
||||
fdsp->vector_dmac_scalar = ff_vector_dmac_scalar_fma3;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
53
media/ffvpx/libavutil/x86/imgutils.asm
Normal file
53
media/ffvpx/libavutil/x86/imgutils.asm
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
;*****************************************************************************
|
||||
;* Copyright 2016 Anton Khirnov
|
||||
;*
|
||||
;* 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/x86/x86util.asm"
|
||||
|
||||
SECTION .text
|
||||
|
||||
INIT_XMM sse4
|
||||
cglobal image_copy_plane_uc_from, 6, 7, 4, dst, dst_linesize, src, src_linesize, bw, height, rowpos
|
||||
add dstq, bwq
|
||||
add srcq, bwq
|
||||
neg bwq
|
||||
|
||||
.row_start:
|
||||
mov rowposq, bwq
|
||||
|
||||
.loop:
|
||||
movntdqa m0, [srcq + rowposq + 0 * mmsize]
|
||||
movntdqa m1, [srcq + rowposq + 1 * mmsize]
|
||||
movntdqa m2, [srcq + rowposq + 2 * mmsize]
|
||||
movntdqa m3, [srcq + rowposq + 3 * mmsize]
|
||||
|
||||
mova [dstq + rowposq + 0 * mmsize], m0
|
||||
mova [dstq + rowposq + 1 * mmsize], m1
|
||||
mova [dstq + rowposq + 2 * mmsize], m2
|
||||
mova [dstq + rowposq + 3 * mmsize], m3
|
||||
|
||||
add rowposq, 4 * mmsize
|
||||
jnz .loop
|
||||
|
||||
add srcq, src_linesizeq
|
||||
add dstq, dst_linesizeq
|
||||
dec heightd
|
||||
jnz .row_start
|
||||
|
||||
RET
|
||||
49
media/ffvpx/libavutil/x86/imgutils_init.c
Normal file
49
media/ffvpx/libavutil/x86/imgutils_init.c
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* 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 <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "libavutil/cpu.h"
|
||||
#include "libavutil/error.h"
|
||||
#include "libavutil/imgutils.h"
|
||||
#include "libavutil/imgutils_internal.h"
|
||||
#include "libavutil/internal.h"
|
||||
|
||||
#include "cpu.h"
|
||||
|
||||
void ff_image_copy_plane_uc_from_sse4(uint8_t *dst, ptrdiff_t dst_linesize,
|
||||
const uint8_t *src, ptrdiff_t src_linesize,
|
||||
ptrdiff_t bytewidth, int height);
|
||||
|
||||
int ff_image_copy_plane_uc_from_x86(uint8_t *dst, ptrdiff_t dst_linesize,
|
||||
const uint8_t *src, ptrdiff_t src_linesize,
|
||||
ptrdiff_t bytewidth, int height)
|
||||
{
|
||||
int cpu_flags = av_get_cpu_flags();
|
||||
ptrdiff_t bw_aligned = FFALIGN(bytewidth, 64);
|
||||
|
||||
if (EXTERNAL_SSE4(cpu_flags) &&
|
||||
bw_aligned <= dst_linesize && bw_aligned <= src_linesize)
|
||||
ff_image_copy_plane_uc_from_sse4(dst, dst_linesize, src, src_linesize,
|
||||
bw_aligned, height);
|
||||
else
|
||||
return AVERROR(ENOSYS);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -12,6 +12,8 @@ SOURCES += [
|
|||
'fixed_dsp_init.c',
|
||||
'float_dsp.asm',
|
||||
'float_dsp_init.c',
|
||||
'imgutils.asm',
|
||||
'imgutils_init.c',
|
||||
'lls.asm',
|
||||
'lls_init.c'
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
;*****************************************************************************
|
||||
;* x86inc.asm: x264asm abstraction layer
|
||||
;*****************************************************************************
|
||||
;* Copyright (C) 2005-2016 x264 project
|
||||
;* Copyright (C) 2005-2017 x264 project
|
||||
;*
|
||||
;* Authors: Loren Merritt <lorenm@u.washington.edu>
|
||||
;* Anton Mitrofanov <BugMaster@narod.ru>
|
||||
|
|
@ -87,7 +87,9 @@
|
|||
; keep supporting OS/2.
|
||||
%macro SECTION_RODATA 0-1 16
|
||||
%ifidn __OUTPUT_FORMAT__,aout
|
||||
section .text
|
||||
SECTION .text
|
||||
%elifidn __OUTPUT_FORMAT__,coff
|
||||
SECTION .text
|
||||
%else
|
||||
SECTION .rodata align=%1
|
||||
%endif
|
||||
|
|
@ -385,7 +387,14 @@ DECLARE_REG_TMP_SIZE 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14
|
|||
%ifnum %1
|
||||
%if %1 != 0 && required_stack_alignment > STACK_ALIGNMENT
|
||||
%if %1 > 0
|
||||
; Reserve an additional register for storing the original stack pointer, but avoid using
|
||||
; eax/rax for this purpose since it can potentially get overwritten as a return value.
|
||||
%assign regs_used (regs_used + 1)
|
||||
%if ARCH_X86_64 && regs_used == 7
|
||||
%assign regs_used 8
|
||||
%elif ARCH_X86_64 == 0 && regs_used == 1
|
||||
%assign regs_used 2
|
||||
%endif
|
||||
%endif
|
||||
%if ARCH_X86_64 && regs_used < 5 + UNIX64 * 3
|
||||
; Ensure that we don't clobber any registers containing arguments. For UNIX64 we also preserve r6 (rax)
|
||||
|
|
@ -419,10 +428,10 @@ DECLARE_REG 7, rdi, 64
|
|||
DECLARE_REG 8, rsi, 72
|
||||
DECLARE_REG 9, rbx, 80
|
||||
DECLARE_REG 10, rbp, 88
|
||||
DECLARE_REG 11, R12, 96
|
||||
DECLARE_REG 12, R13, 104
|
||||
DECLARE_REG 13, R14, 112
|
||||
DECLARE_REG 14, R15, 120
|
||||
DECLARE_REG 11, R14, 96
|
||||
DECLARE_REG 12, R15, 104
|
||||
DECLARE_REG 13, R12, 112
|
||||
DECLARE_REG 14, R13, 120
|
||||
|
||||
%macro PROLOGUE 2-5+ 0 ; #args, #regs, #xmm_regs, [stack_size,] arg_names...
|
||||
%assign num_args %1
|
||||
|
|
@ -468,41 +477,42 @@ DECLARE_REG 14, R15, 120
|
|||
WIN64_PUSH_XMM
|
||||
%endmacro
|
||||
|
||||
%macro WIN64_RESTORE_XMM_INTERNAL 1
|
||||
%macro WIN64_RESTORE_XMM_INTERNAL 0
|
||||
%assign %%pad_size 0
|
||||
%if xmm_regs_used > 8
|
||||
%assign %%i xmm_regs_used
|
||||
%rep xmm_regs_used-8
|
||||
%assign %%i %%i-1
|
||||
movaps xmm %+ %%i, [%1 + (%%i-8)*16 + stack_size + 32]
|
||||
movaps xmm %+ %%i, [rsp + (%%i-8)*16 + stack_size + 32]
|
||||
%endrep
|
||||
%endif
|
||||
%if stack_size_padded > 0
|
||||
%if stack_size > 0 && required_stack_alignment > STACK_ALIGNMENT
|
||||
mov rsp, rstkm
|
||||
%else
|
||||
add %1, stack_size_padded
|
||||
add rsp, stack_size_padded
|
||||
%assign %%pad_size stack_size_padded
|
||||
%endif
|
||||
%endif
|
||||
%if xmm_regs_used > 7
|
||||
movaps xmm7, [%1 + stack_offset - %%pad_size + 24]
|
||||
movaps xmm7, [rsp + stack_offset - %%pad_size + 24]
|
||||
%endif
|
||||
%if xmm_regs_used > 6
|
||||
movaps xmm6, [%1 + stack_offset - %%pad_size + 8]
|
||||
movaps xmm6, [rsp + stack_offset - %%pad_size + 8]
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
%macro WIN64_RESTORE_XMM 1
|
||||
WIN64_RESTORE_XMM_INTERNAL %1
|
||||
%macro WIN64_RESTORE_XMM 0
|
||||
WIN64_RESTORE_XMM_INTERNAL
|
||||
%assign stack_offset (stack_offset-stack_size_padded)
|
||||
%assign stack_size_padded 0
|
||||
%assign xmm_regs_used 0
|
||||
%endmacro
|
||||
|
||||
%define has_epilogue regs_used > 7 || xmm_regs_used > 6 || mmsize == 32 || stack_size > 0
|
||||
|
||||
%macro RET 0
|
||||
WIN64_RESTORE_XMM_INTERNAL rsp
|
||||
WIN64_RESTORE_XMM_INTERNAL
|
||||
POP_IF_USED 14, 13, 12, 11, 10, 9, 8, 7
|
||||
%if mmsize == 32
|
||||
vzeroupper
|
||||
|
|
@ -523,10 +533,10 @@ DECLARE_REG 7, R10, 16
|
|||
DECLARE_REG 8, R11, 24
|
||||
DECLARE_REG 9, rbx, 32
|
||||
DECLARE_REG 10, rbp, 40
|
||||
DECLARE_REG 11, R12, 48
|
||||
DECLARE_REG 12, R13, 56
|
||||
DECLARE_REG 13, R14, 64
|
||||
DECLARE_REG 14, R15, 72
|
||||
DECLARE_REG 11, R14, 48
|
||||
DECLARE_REG 12, R15, 56
|
||||
DECLARE_REG 13, R12, 64
|
||||
DECLARE_REG 14, R13, 72
|
||||
|
||||
%macro PROLOGUE 2-5+ ; #args, #regs, #xmm_regs, [stack_size,] arg_names...
|
||||
%assign num_args %1
|
||||
|
|
@ -618,7 +628,7 @@ DECLARE_ARG 7, 8, 9, 10, 11, 12, 13, 14
|
|||
%if WIN64 == 0
|
||||
%macro WIN64_SPILL_XMM 1
|
||||
%endmacro
|
||||
%macro WIN64_RESTORE_XMM 1
|
||||
%macro WIN64_RESTORE_XMM 0
|
||||
%endmacro
|
||||
%macro WIN64_PUSH_XMM 0
|
||||
%endmacro
|
||||
|
|
@ -629,7 +639,7 @@ DECLARE_ARG 7, 8, 9, 10, 11, 12, 13, 14
|
|||
; We can automatically detect "follows a branch", but not a branch target.
|
||||
; (SSSE3 is a sufficient condition to know that your cpu doesn't have this problem.)
|
||||
%macro REP_RET 0
|
||||
%if has_epilogue
|
||||
%if has_epilogue || cpuflag(ssse3)
|
||||
RET
|
||||
%else
|
||||
rep ret
|
||||
|
|
@ -780,25 +790,25 @@ BRANCH_INSTR jz, je, jnz, jne, jl, jle, jnl, jnle, jg, jge, jng, jnge, ja, jae,
|
|||
%assign cpuflags_sse (1<<4) | cpuflags_mmx2
|
||||
%assign cpuflags_sse2 (1<<5) | cpuflags_sse
|
||||
%assign cpuflags_sse2slow (1<<6) | cpuflags_sse2
|
||||
%assign cpuflags_sse3 (1<<7) | cpuflags_sse2
|
||||
%assign cpuflags_ssse3 (1<<8) | cpuflags_sse3
|
||||
%assign cpuflags_sse4 (1<<9) | cpuflags_ssse3
|
||||
%assign cpuflags_sse42 (1<<10)| cpuflags_sse4
|
||||
%assign cpuflags_avx (1<<11)| cpuflags_sse42
|
||||
%assign cpuflags_xop (1<<12)| cpuflags_avx
|
||||
%assign cpuflags_fma4 (1<<13)| cpuflags_avx
|
||||
%assign cpuflags_fma3 (1<<14)| cpuflags_avx
|
||||
%assign cpuflags_avx2 (1<<15)| cpuflags_fma3
|
||||
%assign cpuflags_lzcnt (1<<7) | cpuflags_sse2
|
||||
%assign cpuflags_sse3 (1<<8) | cpuflags_sse2
|
||||
%assign cpuflags_ssse3 (1<<9) | cpuflags_sse3
|
||||
%assign cpuflags_sse4 (1<<10)| cpuflags_ssse3
|
||||
%assign cpuflags_sse42 (1<<11)| cpuflags_sse4
|
||||
%assign cpuflags_aesni (1<<12)| cpuflags_sse42
|
||||
%assign cpuflags_avx (1<<13)| cpuflags_sse42
|
||||
%assign cpuflags_xop (1<<14)| cpuflags_avx
|
||||
%assign cpuflags_fma4 (1<<15)| cpuflags_avx
|
||||
%assign cpuflags_fma3 (1<<16)| cpuflags_avx
|
||||
%assign cpuflags_bmi1 (1<<17)| cpuflags_avx|cpuflags_lzcnt
|
||||
%assign cpuflags_bmi2 (1<<18)| cpuflags_bmi1
|
||||
%assign cpuflags_avx2 (1<<19)| cpuflags_fma3|cpuflags_bmi2
|
||||
|
||||
%assign cpuflags_cache32 (1<<16)
|
||||
%assign cpuflags_cache64 (1<<17)
|
||||
%assign cpuflags_slowctz (1<<18)
|
||||
%assign cpuflags_lzcnt (1<<19)
|
||||
%assign cpuflags_aligned (1<<20) ; not a cpu feature, but a function variant
|
||||
%assign cpuflags_atom (1<<21)
|
||||
%assign cpuflags_bmi1 (1<<22)|cpuflags_lzcnt
|
||||
%assign cpuflags_bmi2 (1<<23)|cpuflags_bmi1
|
||||
%assign cpuflags_aesni (1<<24)|cpuflags_sse42
|
||||
%assign cpuflags_cache32 (1<<20)
|
||||
%assign cpuflags_cache64 (1<<21)
|
||||
%assign cpuflags_slowctz (1<<22)
|
||||
%assign cpuflags_aligned (1<<23) ; not a cpu feature, but a function variant
|
||||
%assign cpuflags_atom (1<<24)
|
||||
|
||||
; Returns a boolean value expressing whether or not the specified cpuflag is enabled.
|
||||
%define cpuflag(x) (((((cpuflags & (cpuflags_ %+ x)) ^ (cpuflags_ %+ x)) - 1) >> 31) & 1)
|
||||
|
|
@ -1030,7 +1040,11 @@ INIT_XMM
|
|||
|
||||
; Append cpuflags to the callee's name iff the appended name is known and the plain name isn't
|
||||
%macro call 1
|
||||
call_internal %1 %+ SUFFIX, %1
|
||||
%ifid %1
|
||||
call_internal %1 %+ SUFFIX, %1
|
||||
%else
|
||||
call %1
|
||||
%endif
|
||||
%endmacro
|
||||
%macro call_internal 2
|
||||
%xdefine %%i %2
|
||||
|
|
|
|||
|
|
@ -29,6 +29,21 @@
|
|||
|
||||
%include "libavutil/x86/x86inc.asm"
|
||||
|
||||
; expands to [base],...,[base+7*stride]
|
||||
%define PASS8ROWS(base, base3, stride, stride3) \
|
||||
[base], [base + stride], [base + 2*stride], [base3], \
|
||||
[base3 + stride], [base3 + 2*stride], [base3 + stride3], [base3 + stride*4]
|
||||
|
||||
; Interleave low src0 with low src1 and store in src0,
|
||||
; interleave high src0 with high src1 and store in src1.
|
||||
; %1 - types
|
||||
; %2 - index of the register with src0
|
||||
; %3 - index of the register with src1
|
||||
; %4 - index of the register for intermediate results
|
||||
; example for %1 - wd: input: src0: x0 x1 x2 x3 z0 z1 z2 z3
|
||||
; src1: y0 y1 y2 y3 q0 q1 q2 q3
|
||||
; output: src0: x0 y0 x1 y1 x2 y2 x3 y3
|
||||
; src1: z0 q0 z1 q1 z2 q2 z3 q3
|
||||
%macro SBUTTERFLY 4
|
||||
%ifidn %1, dqqq
|
||||
vperm2i128 m%4, m%2, m%3, q0301
|
||||
|
|
@ -56,6 +71,12 @@
|
|||
SWAP %1, %3, %2
|
||||
%endmacro
|
||||
|
||||
%macro SBUTTERFLYPD 3
|
||||
movlhps m%3, m%1, m%2
|
||||
movhlps m%2, m%2, m%1
|
||||
SWAP %1, %3
|
||||
%endmacro
|
||||
|
||||
%macro TRANSPOSE4x4B 5
|
||||
SBUTTERFLY bw, %1, %2, %5
|
||||
SBUTTERFLY bw, %3, %4, %5
|
||||
|
|
@ -102,12 +123,9 @@
|
|||
%macro TRANSPOSE4x4PS 5
|
||||
SBUTTERFLYPS %1, %2, %5
|
||||
SBUTTERFLYPS %3, %4, %5
|
||||
movlhps m%5, m%1, m%3
|
||||
movhlps m%3, m%1
|
||||
SWAP %5, %1
|
||||
movlhps m%5, m%2, m%4
|
||||
movhlps m%4, m%2
|
||||
SWAP %5, %2, %3
|
||||
SBUTTERFLYPD %1, %3, %5
|
||||
SBUTTERFLYPD %2, %4, %5
|
||||
SWAP %2, %3
|
||||
%endmacro
|
||||
|
||||
%macro TRANSPOSE8x4D 9-11
|
||||
|
|
@ -260,6 +278,21 @@
|
|||
SWAP %12, %15
|
||||
%endmacro
|
||||
|
||||
%macro TRANSPOSE_8X8B 8
|
||||
%if mmsize == 8
|
||||
%error "This macro does not support mmsize == 8"
|
||||
%endif
|
||||
punpcklbw m%1, m%2
|
||||
punpcklbw m%3, m%4
|
||||
punpcklbw m%5, m%6
|
||||
punpcklbw m%7, m%8
|
||||
TRANSPOSE4x4W %1, %3, %5, %7, %2
|
||||
MOVHL m%2, m%1
|
||||
MOVHL m%4, m%3
|
||||
MOVHL m%6, m%5
|
||||
MOVHL m%8, m%7
|
||||
%endmacro
|
||||
|
||||
; PABSW macro assumes %1 != %2, while ABS1/2 macros work in-place
|
||||
%macro PABSW 2
|
||||
%if cpuflag(ssse3)
|
||||
|
|
@ -799,12 +832,25 @@
|
|||
pmaxsd %1, %2
|
||||
%endmacro
|
||||
|
||||
%macro VBROADCASTSS 2 ; dst xmm/ymm, src m32
|
||||
%if cpuflag(avx)
|
||||
vbroadcastss %1, %2
|
||||
%else ; sse
|
||||
movss %1, %2
|
||||
shufps %1, %1, 0
|
||||
%macro VBROADCASTSS 2 ; dst xmm/ymm, src m32/xmm
|
||||
%if cpuflag(avx2)
|
||||
vbroadcastss %1, %2
|
||||
%elif cpuflag(avx)
|
||||
%ifnum sizeof%2 ; avx1 register
|
||||
shufps xmm%1, xmm%2, xmm%2, q0000
|
||||
%if sizeof%1 >= 32 ; mmsize>=32
|
||||
vinsertf128 %1, %1, xmm%1, 1
|
||||
%endif
|
||||
%else ; avx1 memory
|
||||
vbroadcastss %1, %2
|
||||
%endif
|
||||
%else
|
||||
%ifnum sizeof%2 ; sse register
|
||||
shufps %1, %2, %2, q0000
|
||||
%else ; sse memory
|
||||
movss %1, %2
|
||||
shufps %1, %1, 0
|
||||
%endif
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
|
|
@ -819,6 +865,21 @@
|
|||
%endif
|
||||
%endmacro
|
||||
|
||||
%macro VPBROADCASTD 2 ; dst xmm/ymm, src m32/xmm
|
||||
%if cpuflag(avx2)
|
||||
vpbroadcastd %1, %2
|
||||
%elif cpuflag(avx) && sizeof%1 >= 32
|
||||
%error vpbroadcastd not possible with ymm on avx1. try vbroadcastss
|
||||
%else
|
||||
%ifnum sizeof%2 ; sse2 register
|
||||
pshufd %1, %2, q0000
|
||||
%else ; sse memory
|
||||
movd %1, %2
|
||||
pshufd %1, %1, 0
|
||||
%endif
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
%macro SHUFFLE_MASK_W 8
|
||||
%rep 8
|
||||
%if %1>=0x80
|
||||
|
|
@ -871,3 +932,79 @@
|
|||
psrlq %1, 8*(%2)
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
%macro MOVHL 2 ; dst, src
|
||||
%ifidn %1, %2
|
||||
punpckhqdq %1, %2
|
||||
%elif cpuflag(avx)
|
||||
punpckhqdq %1, %2, %2
|
||||
%elif cpuflag(sse4)
|
||||
pshufd %1, %2, q3232 ; pshufd is slow on some older CPUs, so only use it on more modern ones
|
||||
%else
|
||||
movhlps %1, %2 ; may cause an int/float domain transition and has a dependency on dst
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
; Horizontal Sum of Packed Single precision floats
|
||||
; The resulting sum is in all elements.
|
||||
%macro HSUMPS 2 ; dst/src, tmp
|
||||
%if cpuflag(avx)
|
||||
%if sizeof%1>=32 ; avx
|
||||
vperm2f128 %2, %1, %1, (0)*16+(1)
|
||||
addps %1, %2
|
||||
%endif
|
||||
shufps %2, %1, %1, q1032
|
||||
addps %1, %2
|
||||
shufps %2, %1, %1, q0321
|
||||
addps %1, %2
|
||||
%else ; this form is a bit faster than the short avx-like emulation.
|
||||
movaps %2, %1
|
||||
shufps %1, %1, q1032
|
||||
addps %1, %2
|
||||
movaps %2, %1
|
||||
shufps %1, %1, q0321
|
||||
addps %1, %2
|
||||
; all %1 members should be equal for as long as float a+b==b+a
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
; Emulate blendvps if not available
|
||||
;
|
||||
; src_b is destroyed when using emulation with logical operands
|
||||
; SSE41 blendv instruction is hard coded to use xmm0 as mask
|
||||
%macro BLENDVPS 3 ; dst/src_a, src_b, mask
|
||||
%if cpuflag(avx)
|
||||
blendvps %1, %1, %2, %3
|
||||
%elif cpuflag(sse4)
|
||||
%ifnidn %3,xmm0
|
||||
%error sse41 blendvps uses xmm0 as default 3d operand, you used %3
|
||||
%endif
|
||||
blendvps %1, %2, %3
|
||||
%else
|
||||
xorps %2, %1
|
||||
andps %2, %3
|
||||
xorps %1, %2
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
; Emulate pblendvb if not available
|
||||
;
|
||||
; src_b is destroyed when using emulation with logical operands
|
||||
; SSE41 blendv instruction is hard coded to use xmm0 as mask
|
||||
%macro PBLENDVB 3 ; dst/src_a, src_b, mask
|
||||
%if cpuflag(avx)
|
||||
%if cpuflag(avx) && notcpuflag(avx2) && sizeof%1 >= 32
|
||||
%error pblendb not possible with ymm on avx1, try blendvps.
|
||||
%endif
|
||||
pblendvb %1, %1, %2, %3
|
||||
%elif cpuflag(sse4)
|
||||
%ifnidn %3,xmm0
|
||||
%error sse41 pblendvd uses xmm0 as default 3d operand, you used %3
|
||||
%endif
|
||||
pblendvb %1, %2, %3
|
||||
%else
|
||||
pxor %2, %1
|
||||
pand %2, %3
|
||||
pxor %1, %2
|
||||
%endif
|
||||
%endmacro
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue