summaryrefslogtreecommitdiffstats
path: root/media/ffvpx/libavutil
diff options
context:
space:
mode:
Diffstat (limited to 'media/ffvpx/libavutil')
-rw-r--r--media/ffvpx/libavutil/atomic_gcc.h17
-rw-r--r--media/ffvpx/libavutil/atomic_suncc.h54
-rw-r--r--media/ffvpx/libavutil/attributes.h5
-rw-r--r--media/ffvpx/libavutil/avconfig.h1
-rw-r--r--media/ffvpx/libavutil/avstring.c23
-rw-r--r--media/ffvpx/libavutil/avstring.h5
-rw-r--r--media/ffvpx/libavutil/avutil.h20
-rw-r--r--media/ffvpx/libavutil/avutil.symbols11
-rw-r--r--media/ffvpx/libavutil/buffer.c96
-rw-r--r--media/ffvpx/libavutil/buffer.h7
-rw-r--r--media/ffvpx/libavutil/buffer_internal.h7
-rw-r--r--media/ffvpx/libavutil/channel_layout.c22
-rw-r--r--media/ffvpx/libavutil/channel_layout.h21
-rw-r--r--media/ffvpx/libavutil/cpu.c61
-rw-r--r--media/ffvpx/libavutil/cpu.h16
-rw-r--r--media/ffvpx/libavutil/cpu_internal.h5
-rw-r--r--media/ffvpx/libavutil/display.c73
-rw-r--r--media/ffvpx/libavutil/display.h87
-rw-r--r--media/ffvpx/libavutil/dummy_funcs.c67
-rw-r--r--media/ffvpx/libavutil/eval.c18
-rw-r--r--media/ffvpx/libavutil/ffversion.h2
-rw-r--r--media/ffvpx/libavutil/float_dsp.c9
-rw-r--r--media/ffvpx/libavutil/float_dsp.h16
-rw-r--r--media/ffvpx/libavutil/frame.c173
-rw-r--r--media/ffvpx/libavutil/frame.h130
-rw-r--r--media/ffvpx/libavutil/hwcontext.h161
-rw-r--r--media/ffvpx/libavutil/imgutils.c271
-rw-r--r--media/ffvpx/libavutil/imgutils.h70
-rw-r--r--media/ffvpx/libavutil/imgutils_internal.h (renamed from media/ffvpx/libavutil/wchar_filename.h)33
-rw-r--r--media/ffvpx/libavutil/internal.h15
-rw-r--r--media/ffvpx/libavutil/intreadwrite.h29
-rw-r--r--media/ffvpx/libavutil/log.c6
-rw-r--r--media/ffvpx/libavutil/lzo.c205
-rw-r--r--media/ffvpx/libavutil/lzo.h66
-rw-r--r--media/ffvpx/libavutil/mathematics.c4
-rw-r--r--media/ffvpx/libavutil/mem.c36
-rw-r--r--media/ffvpx/libavutil/mem.h5
-rw-r--r--media/ffvpx/libavutil/motion_vector.h57
-rw-r--r--media/ffvpx/libavutil/moz.build3
-rw-r--r--media/ffvpx/libavutil/opt.c2025
-rw-r--r--media/ffvpx/libavutil/opt.h1
-rw-r--r--media/ffvpx/libavutil/parseutils.c28
-rw-r--r--media/ffvpx/libavutil/pixdesc.c308
-rw-r--r--media/ffvpx/libavutil/pixdesc.h36
-rw-r--r--media/ffvpx/libavutil/pixfmt.h68
-rw-r--r--media/ffvpx/libavutil/reverse.h28
-rw-r--r--media/ffvpx/libavutil/slicethread.c259
-rw-r--r--media/ffvpx/libavutil/slicethread.h52
-rw-r--r--media/ffvpx/libavutil/thread.h9
-rw-r--r--media/ffvpx/libavutil/threadmessage.c2
-rw-r--r--media/ffvpx/libavutil/time.c18
-rw-r--r--media/ffvpx/libavutil/timecode.c3
-rw-r--r--media/ffvpx/libavutil/timecode.h2
-rw-r--r--media/ffvpx/libavutil/timer.h71
-rw-r--r--media/ffvpx/libavutil/utils.c25
-rw-r--r--media/ffvpx/libavutil/version.h6
-rw-r--r--media/ffvpx/libavutil/x86/cpu.c37
-rw-r--r--media/ffvpx/libavutil/x86/cpu.h6
-rw-r--r--media/ffvpx/libavutil/x86/emms.asm4
-rw-r--r--media/ffvpx/libavutil/x86/emms.h4
-rw-r--r--media/ffvpx/libavutil/x86/float_dsp.asm86
-rw-r--r--media/ffvpx/libavutil/x86/float_dsp_init.c17
-rw-r--r--media/ffvpx/libavutil/x86/imgutils.asm53
-rw-r--r--media/ffvpx/libavutil/x86/imgutils_init.c49
-rw-r--r--media/ffvpx/libavutil/x86/moz.build2
-rw-r--r--media/ffvpx/libavutil/x86/x86inc.asm94
-rw-r--r--media/ffvpx/libavutil/x86/x86util.asm161
67 files changed, 4311 insertions, 1050 deletions
diff --git a/media/ffvpx/libavutil/atomic_gcc.h b/media/ffvpx/libavutil/atomic_gcc.h
index 5f9fc49ba..2bb43c3ce 100644
--- a/media/ffvpx/libavutil/atomic_gcc.h
+++ b/media/ffvpx/libavutil/atomic_gcc.h
@@ -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 */
diff --git a/media/ffvpx/libavutil/atomic_suncc.h b/media/ffvpx/libavutil/atomic_suncc.h
deleted file mode 100644
index a75a37b47..000000000
--- a/media/ffvpx/libavutil/atomic_suncc.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef AVUTIL_ATOMIC_SUNCC_H
-#define AVUTIL_ATOMIC_SUNCC_H
-
-#include <atomic.h>
-#include <mbarrier.h>
-
-#include "atomic.h"
-
-#define avpriv_atomic_int_get atomic_int_get_suncc
-static inline int atomic_int_get_suncc(volatile int *ptr)
-{
- __machine_rw_barrier();
- return *ptr;
-}
-
-#define avpriv_atomic_int_set atomic_int_set_suncc
-static inline void atomic_int_set_suncc(volatile int *ptr, int val)
-{
- *ptr = val;
- __machine_rw_barrier();
-}
-
-#define avpriv_atomic_int_add_and_fetch atomic_int_add_and_fetch_suncc
-static inline int atomic_int_add_and_fetch_suncc(volatile int *ptr, int inc)
-{
- return atomic_add_int_nv(ptr, inc);
-}
-
-#define avpriv_atomic_ptr_cas atomic_ptr_cas_suncc
-static inline void *atomic_ptr_cas_suncc(void * volatile *ptr,
- void *oldval, void *newval)
-{
- return atomic_cas_ptr(ptr, oldval, newval);
-}
-
-#endif /* AVUTIL_ATOMIC_SUNCC_H */
diff --git a/media/ffvpx/libavutil/attributes.h b/media/ffvpx/libavutil/attributes.h
index 5c6b9deec..54d190111 100644
--- a/media/ffvpx/libavutil/attributes.h
+++ b/media/ffvpx/libavutil/attributes.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
diff --git a/media/ffvpx/libavutil/avconfig.h b/media/ffvpx/libavutil/avconfig.h
index 2ec333d15..f10aa6186 100644
--- a/media/ffvpx/libavutil/avconfig.h
+++ b/media/ffvpx/libavutil/avconfig.h
@@ -3,5 +3,4 @@
#define AVUTIL_AVCONFIG_H
#define AV_HAVE_BIGENDIAN 0
#define AV_HAVE_FAST_UNALIGNED 1
-#define AV_HAVE_INCOMPATIBLE_FORK_ABI 0
#endif /* AVUTIL_AVCONFIG_H */
diff --git a/media/ffvpx/libavutil/avstring.c b/media/ffvpx/libavutil/avstring.c
index 1787a1ef5..f03dd2514 100644
--- a/media/ffvpx/libavutil/avstring.c
+++ b/media/ffvpx/libavutil/avstring.c
@@ -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, '/');
diff --git a/media/ffvpx/libavutil/avstring.h b/media/ffvpx/libavutil/avstring.h
index dd2876990..04d269564 100644
--- a/media/ffvpx/libavutil/avstring.h
+++ b/media/ffvpx/libavutil/avstring.h
@@ -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.
diff --git a/media/ffvpx/libavutil/avutil.h b/media/ffvpx/libavutil/avutil.h
index 29dd830bf..4d633156d 100644
--- a/media/ffvpx/libavutil/avutil.h
+++ b/media/ffvpx/libavutil/avutil.h
@@ -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);
+
/**
* @}
* @}
diff --git a/media/ffvpx/libavutil/avutil.symbols b/media/ffvpx/libavutil/avutil.symbols
index 81cf6a8ef..ba68dc33c 100644
--- a/media/ffvpx/libavutil/avutil.symbols
+++ b/media/ffvpx/libavutil/avutil.symbols
@@ -57,9 +57,6 @@ av_dict_parse_string
av_dict_set
av_dict_set_int
av_dirname
-av_display_matrix_flip
-av_display_rotation_get
-av_display_rotation_set
av_div_q
av_dynarray2_add
av_dynarray_add
@@ -88,7 +85,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 +165,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 +332,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
diff --git a/media/ffvpx/libavutil/buffer.c b/media/ffvpx/libavutil/buffer.c
index 694e116a3..8d1aa5fa8 100644
--- a/media/ffvpx/libavutil/buffer.c
+++ b/media/ffvpx/libavutil/buffer.c
@@ -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;
}
diff --git a/media/ffvpx/libavutil/buffer.h b/media/ffvpx/libavutil/buffer.h
index 0c0ce12cf..73b6bd0b1 100644
--- a/media/ffvpx/libavutil/buffer.h
+++ b/media/ffvpx/libavutil/buffer.h
@@ -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,
diff --git a/media/ffvpx/libavutil/buffer_internal.h b/media/ffvpx/libavutil/buffer_internal.h
index 29ce8a643..54b67047e 100644
--- a/media/ffvpx/libavutil/buffer_internal.h
+++ b/media/ffvpx/libavutil/buffer_internal.h
@@ -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;
diff --git a/media/ffvpx/libavutil/channel_layout.c b/media/ffvpx/libavutil/channel_layout.c
index 26c87c96a..3bd5ee29b 100644
--- a/media/ffvpx/libavutil/channel_layout.c
+++ b/media/ffvpx/libavutil/channel_layout.c
@@ -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)
{
diff --git a/media/ffvpx/libavutil/channel_layout.h b/media/ffvpx/libavutil/channel_layout.h
index ec7effead..50bb8f03c 100644
--- a/media/ffvpx/libavutil/channel_layout.h
+++ b/media/ffvpx/libavutil/channel_layout.h
@@ -131,22 +131,31 @@ 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.
*
diff --git a/media/ffvpx/libavutil/cpu.c b/media/ffvpx/libavutil/cpu.c
index f5785fc13..c8401b825 100644
--- a/media/ffvpx/libavutil/cpu.c
+++ b/media/ffvpx/libavutil/cpu.c
@@ -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;
+}
diff --git a/media/ffvpx/libavutil/cpu.h b/media/ffvpx/libavutil/cpu.h
index 4bff16714..9e5d40aff 100644
--- a/media/ffvpx/libavutil/cpu.h
+++ b/media/ffvpx/libavutil/cpu.h
@@ -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 */
diff --git a/media/ffvpx/libavutil/cpu_internal.h b/media/ffvpx/libavutil/cpu_internal.h
index 6c352abe1..b8bf1e539 100644
--- a/media/ffvpx/libavutil/cpu_internal.h
+++ b/media/ffvpx/libavutil/cpu_internal.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 */
diff --git a/media/ffvpx/libavutil/display.c b/media/ffvpx/libavutil/display.c
deleted file mode 100644
index a0076e067..000000000
--- a/media/ffvpx/libavutil/display.c
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (c) 2014 Vittorio Giovara <vittorio.giovara@gmail.com>
- *
- * 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 <stdint.h>
-#include <string.h>
-#include <math.h>
-
-#include "display.h"
-#include "mathematics.h"
-
-// fixed point to double
-#define CONV_FP(x) ((double) (x)) / (1 << 16)
-
-// double to fixed point
-#define CONV_DB(x) (int32_t) ((x) * (1 << 16))
-
-double av_display_rotation_get(const int32_t matrix[9])
-{
- double rotation, scale[2];
-
- scale[0] = hypot(CONV_FP(matrix[0]), CONV_FP(matrix[3]));
- scale[1] = hypot(CONV_FP(matrix[1]), CONV_FP(matrix[4]));
-
- if (scale[0] == 0.0 || scale[1] == 0.0)
- return NAN;
-
- rotation = atan2(CONV_FP(matrix[1]) / scale[1],
- CONV_FP(matrix[0]) / scale[0]) * 180 / M_PI;
-
- return -rotation;
-}
-
-void av_display_rotation_set(int32_t matrix[9], double angle)
-{
- double radians = -angle * M_PI / 180.0f;
- double c = cos(radians);
- double s = sin(radians);
-
- memset(matrix, 0, 9 * sizeof(int32_t));
-
- matrix[0] = CONV_DB(c);
- matrix[1] = CONV_DB(-s);
- matrix[3] = CONV_DB(s);
- matrix[4] = CONV_DB(c);
- matrix[8] = 1 << 30;
-}
-
-void av_display_matrix_flip(int32_t matrix[9], int hflip, int vflip)
-{
- int i;
- const int flip[] = { 1 - 2 * (!!hflip), 1 - 2 * (!!vflip), 1 };
-
- if (hflip || vflip)
- for (i = 0; i < 9; i++)
- matrix[i] *= flip[i % 3];
-}
diff --git a/media/ffvpx/libavutil/display.h b/media/ffvpx/libavutil/display.h
deleted file mode 100644
index 39c15ee6b..000000000
--- a/media/ffvpx/libavutil/display.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (c) 2014 Vittorio Giovara <vittorio.giovara@gmail.com>
- *
- * 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_DISPLAY_H
-#define AVUTIL_DISPLAY_H
-
-#include <stdint.h>
-#include "common.h"
-
-/**
- * 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:
- *
- * | a b u |
- * (a, b, u, c, d, v, x, y, w) -> | c d v |
- * | x y w |
- *
- * 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.
- *
- * 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:
- * | a b u |
- * (p, q, 1) . | c d v | = z * (p', q', 1)
- * | x y w |
- *
- * The transformation can also be more explicitly written in components as
- * follows:
- * p' = (a * p + c * q + x) / z;
- * q' = (b * p + d * q + y) / z;
- * z = u * p + v * q + w
- */
-
-/**
- * Extract the rotation component of the transformation matrix.
- *
- * @param matrix the transformation matrix
- * @return the angle (in degrees) by which the transformation rotates the frame
- * counterclockwise. The angle will be in range [-180.0, 180.0],
- * or NaN if the matrix is singular.
- *
- * @note floating point numbers are inherently inexact, so callers are
- * recommended to round the return value to nearest integer before use.
- */
-double av_display_rotation_get(const int32_t matrix[9]);
-
-/**
- * Initialize a transformation matrix describing a pure counterclockwise
- * rotation by the specified angle (in degrees).
- *
- * @param matrix an allocated transformation matrix (will be fully overwritten
- * by this function)
- * @param angle rotation angle in degrees.
- */
-void av_display_rotation_set(int32_t matrix[9], double angle);
-
-/**
- * Flip the input matrix horizontally and/or vertically.
- *
- * @param matrix an allocated transformation matrix
- * @param hflip whether the matrix should be flipped horizontally
- * @param vflip whether the matrix should be flipped vertically
- */
-void av_display_matrix_flip(int32_t matrix[9], int hflip, int vflip);
-
-#endif /* AVUTIL_DISPLAY_H */
diff --git a/media/ffvpx/libavutil/dummy_funcs.c b/media/ffvpx/libavutil/dummy_funcs.c
index 2ea84a140..3a2381074 100644
--- a/media/ffvpx/libavutil/dummy_funcs.c
+++ b/media/ffvpx/libavutil/dummy_funcs.c
@@ -5,7 +5,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "avutil.h"
-#include "opt.h"
// cpu_internal.c
int ff_get_cpu_flags_aarch64(void) { return 0; }
@@ -19,65 +18,9 @@ void ff_float_dsp_init_arm(AVFloatDSPContext *fdsp) {}
void ff_float_dsp_init_ppc(AVFloatDSPContext *fdsp, int strict) {}
void ff_float_dsp_init_mips(AVFloatDSPContext *fdsp) {}
-// opt.c
-int av_opt_show2(void *obj, void *av_log_obj, int req_flags, int rej_flags) { return 0; }
-void av_opt_set_defaults(void *s) {}
-void av_opt_set_defaults2(void *s, int mask, int flags) {}
-int av_set_options_string(void *ctx, const char *opts,
- const char *key_val_sep, const char *pairs_sep) { return 0; }
-int av_opt_set_from_string(void *ctx, const char *opts,
- const char *const *shorthand,
- const char *key_val_sep, const char *pairs_sep) { return 0; }
-void av_opt_free(void *obj) {}
-int av_opt_flag_is_set(void *obj, const char *field_name, const char *flag_name) { return 0; }
-int av_opt_set_dict(void *obj, struct AVDictionary **options) { return 0; }
-int av_opt_set_dict2(void *obj, struct AVDictionary **options, int search_flags) { return 0; }
-int av_opt_get_key_value(const char **ropts,
- const char *key_val_sep, const char *pairs_sep,
- unsigned flags,
- char **rkey, char **rval) { return 0; }
-int av_opt_eval_flags (void *obj, const AVOption *o, const char *val, int *flags_out) { return 0; }
-int av_opt_eval_int (void *obj, const AVOption *o, const char *val, int *int_out) { return 0; }
-int av_opt_eval_int64 (void *obj, const AVOption *o, const char *val, int64_t *int64_out) { return 0; }
-int av_opt_eval_float (void *obj, const AVOption *o, const char *val, float *float_out) { return 0; }
-int av_opt_eval_double(void *obj, const AVOption *o, const char *val, double *double_out) { return 0; }
-int av_opt_eval_q (void *obj, const AVOption *o, const char *val, AVRational *q_out) { return 0; }
-const AVOption *av_opt_find(void *obj, const char *name, const char *unit,
- int opt_flags, int search_flags) { return 0; }
-const AVOption *av_opt_find2(void *obj, const char *name, const char *unit,
- int opt_flags, int search_flags, void **target_obj) { return 0; }
-const AVOption *av_opt_next(const void *obj, const AVOption *prev) { return 0; }
-void *av_opt_child_next(void *obj, void *prev) { return 0; }
-const AVClass *av_opt_child_class_next(const AVClass *parent, const AVClass *prev) { return 0; }
-int av_opt_set (void *obj, const char *name, const char *val, int search_flags) { return 0; }
-int av_opt_set_int (void *obj, const char *name, int64_t val, int search_flags) { return 0; }
-int av_opt_set_double (void *obj, const char *name, double val, int search_flags) { return 0; }
-int av_opt_set_q (void *obj, const char *name, AVRational val, int search_flags) { return 0; }
-int av_opt_set_bin (void *obj, const char *name, const uint8_t *val, int size, int search_flags) { return 0; }
-int av_opt_set_image_size(void *obj, const char *name, int w, int h, int search_flags) { return 0; }
-int av_opt_set_pixel_fmt (void *obj, const char *name, enum AVPixelFormat fmt, int search_flags) { return 0; }
-int av_opt_set_sample_fmt(void *obj, const char *name, enum AVSampleFormat fmt, int search_flags) { return 0; }
-int av_opt_set_video_rate(void *obj, const char *name, AVRational val, int search_flags) { return 0; }
-int av_opt_set_channel_layout(void *obj, const char *name, int64_t ch_layout, int search_flags) { return 0; }
-int av_opt_set_dict_val(void *obj, const char *name, const AVDictionary *val, int search_flags) { return 0; }
-int av_opt_get (void *obj, const char *name, int search_flags, uint8_t **out_val) { return 0; }
-int av_opt_get_int (void *obj, const char *name, int search_flags, int64_t *out_val) { return 0; }
-int av_opt_get_double (void *obj, const char *name, int search_flags, double *out_val) { return 0; }
-int av_opt_get_q (void *obj, const char *name, int search_flags, AVRational *out_val) { return 0; }
-int av_opt_get_image_size(void *obj, const char *name, int search_flags, int *w_out, int *h_out) { return 0; }
-int av_opt_get_pixel_fmt (void *obj, const char *name, int search_flags, enum AVPixelFormat *out_fmt) { return 0; }
-int av_opt_get_sample_fmt(void *obj, const char *name, int search_flags, enum AVSampleFormat *out_fmt) { return 0; }
-int av_opt_get_video_rate(void *obj, const char *name, int search_flags, AVRational *out_val) { return 0; }
-int av_opt_get_channel_layout(void *obj, const char *name, int search_flags, int64_t *ch_layout) { return 0; }
-int av_opt_get_dict_val(void *obj, const char *name, int search_flags, AVDictionary **out_val) { return 0; }
-void *av_opt_ptr(const AVClass *avclass, void *obj, const char *name) { return 0; }
-void av_opt_freep_ranges(AVOptionRanges **ranges) {}
-int av_opt_query_ranges(AVOptionRanges **b, void *obj, const char *key, int flags) { return 0; }
-int av_opt_copy(void *dest, const void *src) { return 0; }
-int av_opt_query_ranges_default(AVOptionRanges **b, void *obj, const char *key, int flags) { return 0; }
-int av_opt_is_set_to_default(void *obj, const AVOption *o) { return 0; }
-int av_opt_is_set_to_default_by_name(void *obj, const char *name, int search_flags) { return 0; }
-int av_opt_serialize(void *obj, int opt_flags, int flags, char **buffer,
- const char key_val_sep, const char pairs_sep) { return 0; }
-
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; }
diff --git a/media/ffvpx/libavutil/eval.c b/media/ffvpx/libavutil/eval.c
index fc12885c2..e5948793b 100644
--- a/media/ffvpx/libavutil/eval.c
+++ b/media/ffvpx/libavutil/eval.c
@@ -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]);
diff --git a/media/ffvpx/libavutil/ffversion.h b/media/ffvpx/libavutil/ffversion.h
index cbeaf627b..3da2a6bf1 100644
--- a/media/ffvpx/libavutil/ffversion.h
+++ b/media/ffvpx/libavutil/ffversion.h
@@ -1,5 +1,5 @@
/* Automatically generated by version.sh, do not manually edit! */
#ifndef AVUTIL_FFVERSION_H
#define AVUTIL_FFVERSION_H
-#define FFMPEG_VERSION "n3.1.1-6-g86f9228"
+#define FFMPEG_VERSION "n3.4.2"
#endif /* AVUTIL_FFVERSION_H */
diff --git a/media/ffvpx/libavutil/float_dsp.c b/media/ffvpx/libavutil/float_dsp.c
index c85daffc6..1d4911d81 100644
--- a/media/ffvpx/libavutil/float_dsp.c
+++ b/media/ffvpx/libavutil/float_dsp.c
@@ -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;
diff --git a/media/ffvpx/libavutil/float_dsp.h b/media/ffvpx/libavutil/float_dsp.h
index d1be38f94..2c24d9347 100644
--- a/media/ffvpx/libavutil/float_dsp.h
+++ b/media/ffvpx/libavutil/float_dsp.h
@@ -55,6 +55,22 @@ typedef struct AVFloatDSPContext {
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.
*
diff --git a/media/ffvpx/libavutil/frame.c b/media/ffvpx/libavutil/frame.c
index 53e617422..d5fd2932e 100644
--- a/media/ffvpx/libavutil/frame.c
+++ b/media/ffvpx/libavutil/frame.c
@@ -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;
+}
diff --git a/media/ffvpx/libavutil/frame.h b/media/ffvpx/libavutil/frame.h
index 8e51361e2..abe4f4fd1 100644
--- a/media/ffvpx/libavutil/frame.h
+++ b/media/ffvpx/libavutil/frame.h
@@ -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
*/
diff --git a/media/ffvpx/libavutil/hwcontext.h b/media/ffvpx/libavutil/hwcontext.h
index 5e2af092a..03334e20e 100644
--- a/media/ffvpx/libavutil/hwcontext.h
+++ b/media/ffvpx/libavutil/hwcontext.h
@@ -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.
*/
@@ -271,6 +301,32 @@ 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.
*
* @param device_ctx a reference to a AVHWDeviceContext. This function will make
@@ -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 */
diff --git a/media/ffvpx/libavutil/imgutils.c b/media/ffvpx/libavutil/imgutils.c
index 37808e53d..500517880 100644
--- a/media/ffvpx/libavutil/imgutils.c
+++ b/media/ffvpx/libavutil/imgutils.c
@@ -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;
+}
diff --git a/media/ffvpx/libavutil/imgutils.h b/media/ffvpx/libavutil/imgutils.h
index 23282a38f..5b790ecf0 100644
--- a/media/ffvpx/libavutil/imgutils.h
+++ b/media/ffvpx/libavutil/imgutils.h
@@ -121,6 +121,24 @@ void av_image_copy(uint8_t *dst_data[4], int dst_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
@@ -192,6 +214,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.
*
* It is considered invalid if the denominator is 0 or if applying the ratio
@@ -206,6 +243,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);
+
+/**
* @}
*/
diff --git a/media/ffvpx/libavutil/wchar_filename.h b/media/ffvpx/libavutil/imgutils_internal.h
index 2ade321be..d51585841 100644
--- a/media/ffvpx/libavutil/wchar_filename.h
+++ b/media/ffvpx/libavutil/imgutils_internal.h
@@ -16,30 +16,15 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#ifndef AVUTIL_WCHAR_FILENAME_H
-#define AVUTIL_WCHAR_FILENAME_H
+#ifndef AVUTIL_IMGUTILS_INTERNAL_H
+#define AVUTIL_IMGUTILS_INTERNAL_H
-#if defined(_WIN32) && !defined(__MINGW32CE__)
-#include <windows.h>
-#include "mem.h"
+#include <stddef.h>
+#include <stdint.h>
-av_warn_unused_result
-static inline int utf8towchar(const char *filename_utf8, wchar_t **filename_w)
-{
- int num_chars;
- num_chars = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, filename_utf8, -1, NULL, 0);
- if (num_chars <= 0) {
- *filename_w = NULL;
- return 0;
- }
- *filename_w = (wchar_t *)av_mallocz_array(num_chars, sizeof(wchar_t));
- if (!*filename_w) {
- errno = ENOMEM;
- return -1;
- }
- MultiByteToWideChar(CP_UTF8, 0, filename_utf8, -1, *filename_w, num_chars);
- return 0;
-}
-#endif
+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_WCHAR_FILENAME_H */
+
+#endif /* AVUTIL_IMGUTILS_INTERNAL_H */
diff --git a/media/ffvpx/libavutil/internal.h b/media/ffvpx/libavutil/internal.h
index e995af97e..a2d73e3cc 100644
--- a/media/ffvpx/libavutil/internal.h
+++ b/media/ffvpx/libavutil/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 */
diff --git a/media/ffvpx/libavutil/intreadwrite.h b/media/ffvpx/libavutil/intreadwrite.h
index 51fbe30a2..d54d4b91d 100644
--- a/media/ffvpx/libavutil/intreadwrite.h
+++ b/media/ffvpx/libavutil/intreadwrite.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; \
diff --git a/media/ffvpx/libavutil/log.c b/media/ffvpx/libavutil/log.c
index 44c11cb09..be806202f 100644
--- a/media/ffvpx/libavutil/log.c
+++ b/media/ffvpx/libavutil/log.c
@@ -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);
diff --git a/media/ffvpx/libavutil/lzo.c b/media/ffvpx/libavutil/lzo.c
deleted file mode 100644
index 1ae076e33..000000000
--- a/media/ffvpx/libavutil/lzo.c
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * LZO 1x decompression
- * Copyright (c) 2006 Reimar Doeffinger
- *
- * 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 <string.h>
-
-#include "avutil.h"
-#include "avassert.h"
-#include "common.h"
-#include "intreadwrite.h"
-#include "lzo.h"
-
-/// Define if we may write up to 12 bytes beyond the output buffer.
-#define OUTBUF_PADDED 1
-/// Define if we may read up to 8 bytes beyond the input buffer.
-#define INBUF_PADDED 1
-
-typedef struct LZOContext {
- const uint8_t *in, *in_end;
- uint8_t *out_start, *out, *out_end;
- int error;
-} LZOContext;
-
-/**
- * @brief Reads one byte from the input buffer, avoiding an overrun.
- * @return byte read
- */
-static inline int get_byte(LZOContext *c)
-{
- if (c->in < c->in_end)
- return *c->in++;
- c->error |= AV_LZO_INPUT_DEPLETED;
- return 1;
-}
-
-#ifdef INBUF_PADDED
-#define GETB(c) (*(c).in++)
-#else
-#define GETB(c) get_byte(&(c))
-#endif
-
-/**
- * @brief Decodes a length value in the coding used by lzo.
- * @param x previous byte value
- * @param mask bits used from x
- * @return decoded length value
- */
-static inline int get_len(LZOContext *c, int x, int mask)
-{
- int cnt = x & mask;
- if (!cnt) {
- while (!(x = get_byte(c))) {
- if (cnt >= INT_MAX - 1000) {
- c->error |= AV_LZO_ERROR;
- break;
- }
- cnt += 255;
- }
- cnt += mask + x;
- }
- return cnt;
-}
-
-/**
- * @brief Copies bytes from input to output buffer with checking.
- * @param cnt number of bytes to copy, must be >= 0
- */
-static inline void copy(LZOContext *c, int cnt)
-{
- register const uint8_t *src = c->in;
- register uint8_t *dst = c->out;
- av_assert0(cnt >= 0);
- if (cnt > c->in_end - src) {
- cnt = FFMAX(c->in_end - src, 0);
- c->error |= AV_LZO_INPUT_DEPLETED;
- }
- if (cnt > c->out_end - dst) {
- cnt = FFMAX(c->out_end - dst, 0);
- c->error |= AV_LZO_OUTPUT_FULL;
- }
-#if defined(INBUF_PADDED) && defined(OUTBUF_PADDED)
- AV_COPY32U(dst, src);
- src += 4;
- dst += 4;
- cnt -= 4;
- if (cnt > 0)
-#endif
- memcpy(dst, src, cnt);
- c->in = src + cnt;
- c->out = dst + cnt;
-}
-
-/**
- * @brief Copies previously decoded bytes to current position.
- * @param back how many bytes back we start, must be > 0
- * @param cnt number of bytes to copy, must be > 0
- *
- * cnt > back is valid, this will copy the bytes we just copied,
- * thus creating a repeating pattern with a period length of back.
- */
-static inline void copy_backptr(LZOContext *c, int back, int cnt)
-{
- register uint8_t *dst = c->out;
- av_assert0(cnt > 0);
- if (dst - c->out_start < back) {
- c->error |= AV_LZO_INVALID_BACKPTR;
- return;
- }
- if (cnt > c->out_end - dst) {
- cnt = FFMAX(c->out_end - dst, 0);
- c->error |= AV_LZO_OUTPUT_FULL;
- }
- av_memcpy_backptr(dst, back, cnt);
- c->out = dst + cnt;
-}
-
-int av_lzo1x_decode(void *out, int *outlen, const void *in, int *inlen)
-{
- int state = 0;
- int x;
- LZOContext c;
- if (*outlen <= 0 || *inlen <= 0) {
- int res = 0;
- if (*outlen <= 0)
- res |= AV_LZO_OUTPUT_FULL;
- if (*inlen <= 0)
- res |= AV_LZO_INPUT_DEPLETED;
- return res;
- }
- c.in = in;
- c.in_end = (const uint8_t *)in + *inlen;
- c.out = c.out_start = out;
- c.out_end = (uint8_t *)out + *outlen;
- c.error = 0;
- x = GETB(c);
- if (x > 17) {
- copy(&c, x - 17);
- x = GETB(c);
- if (x < 16)
- c.error |= AV_LZO_ERROR;
- }
- if (c.in > c.in_end)
- c.error |= AV_LZO_INPUT_DEPLETED;
- while (!c.error) {
- int cnt, back;
- if (x > 15) {
- if (x > 63) {
- cnt = (x >> 5) - 1;
- back = (GETB(c) << 3) + ((x >> 2) & 7) + 1;
- } else if (x > 31) {
- cnt = get_len(&c, x, 31);
- x = GETB(c);
- back = (GETB(c) << 6) + (x >> 2) + 1;
- } else {
- cnt = get_len(&c, x, 7);
- back = (1 << 14) + ((x & 8) << 11);
- x = GETB(c);
- back += (GETB(c) << 6) + (x >> 2);
- if (back == (1 << 14)) {
- if (cnt != 1)
- c.error |= AV_LZO_ERROR;
- break;
- }
- }
- } else if (!state) {
- cnt = get_len(&c, x, 15);
- copy(&c, cnt + 3);
- x = GETB(c);
- if (x > 15)
- continue;
- cnt = 1;
- back = (1 << 11) + (GETB(c) << 2) + (x >> 2) + 1;
- } else {
- cnt = 0;
- back = (GETB(c) << 2) + (x >> 2) + 1;
- }
- copy_backptr(&c, back, cnt + 2);
- state =
- cnt = x & 3;
- copy(&c, cnt);
- x = GETB(c);
- }
- *inlen = c.in_end - c.in;
- if (c.in > c.in_end)
- *inlen = 0;
- *outlen = c.out_end - c.out;
- return c.error;
-}
diff --git a/media/ffvpx/libavutil/lzo.h b/media/ffvpx/libavutil/lzo.h
deleted file mode 100644
index c03403992..000000000
--- a/media/ffvpx/libavutil/lzo.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * LZO 1x decompression
- * copyright (c) 2006 Reimar Doeffinger
- *
- * 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_LZO_H
-#define AVUTIL_LZO_H
-
-/**
- * @defgroup lavu_lzo LZO
- * @ingroup lavu_crypto
- *
- * @{
- */
-
-#include <stdint.h>
-
-/** @name Error flags returned by av_lzo1x_decode
- * @{ */
-/// end of the input buffer reached before decoding finished
-#define AV_LZO_INPUT_DEPLETED 1
-/// decoded data did not fit into output buffer
-#define AV_LZO_OUTPUT_FULL 2
-/// a reference to previously decoded data was wrong
-#define AV_LZO_INVALID_BACKPTR 4
-/// a non-specific error in the compressed bitstream
-#define AV_LZO_ERROR 8
-/** @} */
-
-#define AV_LZO_INPUT_PADDING 8
-#define AV_LZO_OUTPUT_PADDING 12
-
-/**
- * @brief Decodes LZO 1x compressed data.
- * @param out output buffer
- * @param outlen size of output buffer, number of bytes left are returned here
- * @param in input buffer
- * @param inlen size of input buffer, number of bytes left are returned here
- * @return 0 on success, otherwise a combination of the error flags above
- *
- * Make sure all buffers are appropriately padded, in must provide
- * AV_LZO_INPUT_PADDING, out must provide AV_LZO_OUTPUT_PADDING additional bytes.
- */
-int av_lzo1x_decode(void *out, int *outlen, const void *in, int *inlen);
-
-/**
- * @}
- */
-
-#endif /* AVUTIL_LZO_H */
diff --git a/media/ffvpx/libavutil/mathematics.c b/media/ffvpx/libavutil/mathematics.c
index 20ff37f5e..1bf044cdf 100644
--- a/media/ffvpx/libavutil/mathematics.c
+++ b/media/ffvpx/libavutil/mathematics.c
@@ -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)
diff --git a/media/ffvpx/libavutil/mem.c b/media/ffvpx/libavutil/mem.c
index 1a8fc21e9..36740f115 100644
--- a/media/ffvpx/libavutil/mem.c
+++ b/media/ffvpx/libavutil/mem.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);
diff --git a/media/ffvpx/libavutil/mem.h b/media/ffvpx/libavutil/mem.h
index f9d888478..527cd0319 100644
--- a/media/ffvpx/libavutil/mem.h
+++ b/media/ffvpx/libavutil/mem.h
@@ -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)
diff --git a/media/ffvpx/libavutil/motion_vector.h b/media/ffvpx/libavutil/motion_vector.h
deleted file mode 100644
index ec2955638..000000000
--- a/media/ffvpx/libavutil/motion_vector.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef AVUTIL_MOTION_VECTOR_H
-#define AVUTIL_MOTION_VECTOR_H
-
-#include <stdint.h>
-
-typedef struct AVMotionVector {
- /**
- * Where the current macroblock comes from; negative value when it comes
- * from the past, positive value when it comes from the future.
- * XXX: set exact relative ref frame reference instead of a +/- 1 "direction".
- */
- int32_t source;
- /**
- * Width and height of the block.
- */
- uint8_t w, h;
- /**
- * Absolute source position. Can be outside the frame area.
- */
- int16_t src_x, src_y;
- /**
- * Absolute destination position. Can be outside the frame area.
- */
- int16_t dst_x, dst_y;
- /**
- * Extra flag information.
- * Currently unused.
- */
- uint64_t flags;
- /**
- * Motion vector
- * src_x = dst_x + motion_x / motion_scale
- * src_y = dst_y + motion_y / motion_scale
- */
- int32_t motion_x, motion_y;
- uint16_t motion_scale;
-} AVMotionVector;
-
-#endif /* AVUTIL_MOTION_VECTOR_H */
diff --git a/media/ffvpx/libavutil/moz.build b/media/ffvpx/libavutil/moz.build
index edc0888b1..201b62fed 100644
--- a/media/ffvpx/libavutil/moz.build
+++ b/media/ffvpx/libavutil/moz.build
@@ -22,7 +22,6 @@ SOURCES += [
'cpu.c',
'crc.c',
'dict.c',
- 'display.c',
'dummy_funcs.c',
'error.c',
'eval.c',
@@ -38,12 +37,14 @@ SOURCES += [
'log2_tab.c',
'mathematics.c',
'mem.c',
+ 'opt.c',
'parseutils.c',
'pixdesc.c',
'pixelutils.c',
'rational.c',
'reverse.c',
'samplefmt.c',
+ 'slicethread.c',
'threadmessage.c',
'time.c',
'timecode.c',
diff --git a/media/ffvpx/libavutil/opt.c b/media/ffvpx/libavutil/opt.c
new file mode 100644
index 000000000..df88663e3
--- /dev/null
+++ b/media/ffvpx/libavutil/opt.c
@@ -0,0 +1,2025 @@
+/*
+ * AVOptions
+ * Copyright (c) 2005 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
+ */
+
+/**
+ * @file
+ * AVOptions
+ * @author Michael Niedermayer <michaelni@gmx.at>
+ */
+
+#include "avutil.h"
+#include "avassert.h"
+#include "avstring.h"
+#include "channel_layout.h"
+#include "common.h"
+#include "dict.h"
+#include "eval.h"
+#include "log.h"
+#include "parseutils.h"
+#include "pixdesc.h"
+#include "mathematics.h"
+#include "opt.h"
+#include "samplefmt.h"
+#include "bprint.h"
+
+#include <float.h>
+
+const AVOption *av_opt_next(const void *obj, const AVOption *last)
+{
+ const AVClass *class;
+ if (!obj)
+ return NULL;
+ class = *(const AVClass**)obj;
+ if (!last && class && class->option && class->option[0].name)
+ return class->option;
+ if (last && last[1].name)
+ return ++last;
+ return NULL;
+}
+
+static int read_number(const AVOption *o, const void *dst, double *num, int *den, int64_t *intnum)
+{
+ switch (o->type) {
+ case AV_OPT_TYPE_FLAGS:
+ *intnum = *(unsigned int*)dst;
+ return 0;
+ case AV_OPT_TYPE_PIXEL_FMT:
+ *intnum = *(enum AVPixelFormat *)dst;
+ return 0;
+ case AV_OPT_TYPE_SAMPLE_FMT:
+ *intnum = *(enum AVSampleFormat *)dst;
+ return 0;
+ case AV_OPT_TYPE_BOOL:
+ case AV_OPT_TYPE_INT:
+ *intnum = *(int *)dst;
+ return 0;
+ 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:
+ *num = *(float *)dst;
+ return 0;
+ case AV_OPT_TYPE_DOUBLE:
+ *num = *(double *)dst;
+ return 0;
+ case AV_OPT_TYPE_RATIONAL:
+ *intnum = ((AVRational *)dst)->num;
+ *den = ((AVRational *)dst)->den;
+ return 0;
+ case AV_OPT_TYPE_CONST:
+ *num = o->default_val.dbl;
+ return 0;
+ }
+ return AVERROR(EINVAL);
+}
+
+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 &&
+ (!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);
+ }
+ if (o->type == AV_OPT_TYPE_FLAGS) {
+ double d = num*intnum/den;
+ if (d < -1.5 || d > 0xFFFFFFFF+0.5 || (llrint(d*256) & 255)) {
+ av_log(obj, AV_LOG_ERROR,
+ "Value %f for parameter '%s' is not a valid set of 32bit integer flags\n",
+ num*intnum/den, o->name);
+ return AVERROR(ERANGE);
+ }
+ }
+
+ switch (o->type) {
+ case AV_OPT_TYPE_PIXEL_FMT:
+ *(enum AVPixelFormat *)dst = llrint(num / den) * intnum;
+ break;
+ case AV_OPT_TYPE_SAMPLE_FMT:
+ *(enum AVSampleFormat *)dst = llrint(num / den) * intnum;
+ break;
+ case AV_OPT_TYPE_BOOL:
+ case AV_OPT_TYPE_FLAGS:
+ case AV_OPT_TYPE_INT:
+ *(int *)dst = llrint(num / den) * intnum;
+ break;
+ case AV_OPT_TYPE_DURATION:
+ case AV_OPT_TYPE_CHANNEL_LAYOUT:
+ 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;
+ case AV_OPT_TYPE_DOUBLE:
+ *(double *)dst = num * intnum / den;
+ break;
+ case AV_OPT_TYPE_RATIONAL:
+ case AV_OPT_TYPE_VIDEO_RATE:
+ if ((int) num == num)
+ *(AVRational *)dst = (AVRational) { num *intnum, den };
+ else
+ *(AVRational *)dst = av_d2q(num * intnum / den, 1 << 24);
+ break;
+ default:
+ return AVERROR(EINVAL);
+ }
+ return 0;
+}
+
+static int hexchar2int(char c) {
+ if (c >= '0' && c <= '9')
+ return c - '0';
+ if (c >= 'a' && c <= 'f')
+ return c - 'a' + 10;
+ if (c >= 'A' && c <= 'F')
+ return c - 'A' + 10;
+ return -1;
+}
+
+static int set_string_binary(void *obj, const AVOption *o, const char *val, uint8_t **dst)
+{
+ int *lendst = (int *)(dst + 1);
+ uint8_t *bin, *ptr;
+ int len;
+
+ av_freep(dst);
+ *lendst = 0;
+
+ if (!val || !(len = strlen(val)))
+ return 0;
+
+ if (len & 1)
+ return AVERROR(EINVAL);
+ len /= 2;
+
+ ptr = bin = av_malloc(len);
+ if (!ptr)
+ return AVERROR(ENOMEM);
+ while (*val) {
+ int a = hexchar2int(*val++);
+ int b = hexchar2int(*val++);
+ if (a < 0 || b < 0) {
+ av_free(bin);
+ return AVERROR(EINVAL);
+ }
+ *ptr++ = (a << 4) | b;
+ }
+ *dst = bin;
+ *lendst = len;
+
+ return 0;
+}
+
+static int set_string(void *obj, const AVOption *o, const char *val, uint8_t **dst)
+{
+ av_freep(dst);
+ *dst = av_strdup(val);
+ return *dst ? 0 : AVERROR(ENOMEM);
+}
+
+#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) \
+ ? opt->default_val.i64 \
+ : opt->default_val.dbl)
+
+static int set_string_number(void *obj, void *target_obj, const AVOption *o, const char *val, void *dst)
+{
+ int ret = 0;
+ int num, den;
+ char c;
+
+ if (sscanf(val, "%d%*1[:/]%d%c", &num, &den, &c) == 2) {
+ if ((ret = write_number(obj, o, dst, 1, den, num)) >= 0)
+ return ret;
+ ret = 0;
+ }
+
+ for (;;) {
+ int i = 0;
+ char buf[256];
+ int cmd = 0;
+ double d;
+ int64_t intnum = 1;
+
+ if (o->type == AV_OPT_TYPE_FLAGS) {
+ if (*val == '+' || *val == '-')
+ cmd = *(val++);
+ for (; i < sizeof(buf) - 1 && val[i] && val[i] != '+' && val[i] != '-'; i++)
+ buf[i] = val[i];
+ buf[i] = 0;
+ }
+
+ {
+ const AVOption *o_named = av_opt_find(target_obj, i ? buf : val, o->unit, 0, 0);
+ int res;
+ int ci = 0;
+ double const_values[64];
+ const char * const_names[64];
+ if (o_named && o_named->type == AV_OPT_TYPE_CONST)
+ d = DEFAULT_NUMVAL(o_named);
+ else {
+ if (o->unit) {
+ for (o_named = NULL; o_named = av_opt_next(target_obj, o_named); ) {
+ if (o_named->type == AV_OPT_TYPE_CONST &&
+ o_named->unit &&
+ !strcmp(o_named->unit, o->unit)) {
+ if (ci + 6 >= FF_ARRAY_ELEMS(const_values)) {
+ av_log(obj, AV_LOG_ERROR, "const_values array too small for %s\n", o->unit);
+ return AVERROR_PATCHWELCOME;
+ }
+ const_names [ci ] = o_named->name;
+ const_values[ci++] = DEFAULT_NUMVAL(o_named);
+ }
+ }
+ }
+ const_names [ci ] = "default";
+ const_values[ci++] = DEFAULT_NUMVAL(o);
+ const_names [ci ] = "max";
+ const_values[ci++] = o->max;
+ const_names [ci ] = "min";
+ const_values[ci++] = o->min;
+ const_names [ci ] = "none";
+ const_values[ci++] = 0;
+ const_names [ci ] = "all";
+ const_values[ci++] = ~0;
+ const_names [ci] = NULL;
+ const_values[ci] = 0;
+
+ res = av_expr_parse_and_eval(&d, i ? buf : val, const_names,
+ const_values, NULL, NULL, NULL, NULL, NULL, 0, obj);
+ if (res < 0) {
+ av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\"\n", val);
+ return res;
+ }
+ }
+ }
+ if (o->type == AV_OPT_TYPE_FLAGS) {
+ read_number(o, dst, NULL, NULL, &intnum);
+ if (cmd == '+')
+ d = intnum | (int64_t)d;
+ else if (cmd == '-')
+ d = intnum &~(int64_t)d;
+ }
+
+ if ((ret = write_number(obj, o, dst, d, 1, 1)) < 0)
+ return ret;
+ val += i;
+ if (!i || !*val)
+ return 0;
+ }
+}
+
+static int set_string_image_size(void *obj, const AVOption *o, const char *val, int *dst)
+{
+ int ret;
+
+ if (!val || !strcmp(val, "none")) {
+ dst[0] =
+ dst[1] = 0;
+ return 0;
+ }
+ ret = av_parse_video_size(dst, dst + 1, val);
+ if (ret < 0)
+ av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\" as image size\n", val);
+ return ret;
+}
+
+static int set_string_video_rate(void *obj, const AVOption *o, const char *val, AVRational *dst)
+{
+ int ret;
+ if (!val) {
+ ret = AVERROR(EINVAL);
+ } else {
+ ret = av_parse_video_rate(dst, val);
+ }
+ if (ret < 0)
+ av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\" as video rate\n", val);
+ return ret;
+}
+
+static int set_string_color(void *obj, const AVOption *o, const char *val, uint8_t *dst)
+{
+ int ret;
+
+ if (!val) {
+ return 0;
+ } else {
+ ret = av_parse_color(dst, val, -1, obj);
+ if (ret < 0)
+ av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\" as color\n", val);
+ return ret;
+ }
+ return 0;
+}
+
+static const char *get_bool_name(int val)
+{
+ if (val < 0)
+ return "auto";
+ return val ? "true" : "false";
+}
+
+static int set_string_bool(void *obj, const AVOption *o, const char *val, int *dst)
+{
+ int n;
+
+ if (!val)
+ return 0;
+
+ if (!strcmp(val, "auto")) {
+ n = -1;
+ } else if (av_match_name(val, "true,y,yes,enable,enabled,on")) {
+ n = 1;
+ } else if (av_match_name(val, "false,n,no,disable,disabled,off")) {
+ n = 0;
+ } else {
+ char *end = NULL;
+ n = strtol(val, &end, 10);
+ if (val + strlen(val) != end)
+ goto fail;
+ }
+
+ if (n < o->min || n > o->max)
+ goto fail;
+
+ *dst = n;
+ return 0;
+
+fail:
+ av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\" as boolean\n", val);
+ return AVERROR(EINVAL);
+}
+
+static int set_string_fmt(void *obj, const AVOption *o, const char *val, uint8_t *dst,
+ int fmt_nb, int ((*get_fmt)(const char *)), const char *desc)
+{
+ int fmt, min, max;
+
+ if (!val || !strcmp(val, "none")) {
+ fmt = -1;
+ } else {
+ fmt = get_fmt(val);
+ if (fmt == -1) {
+ char *tail;
+ fmt = strtol(val, &tail, 0);
+ if (*tail || (unsigned)fmt >= fmt_nb) {
+ av_log(obj, AV_LOG_ERROR,
+ "Unable to parse option value \"%s\" as %s\n", val, desc);
+ return AVERROR(EINVAL);
+ }
+ }
+ }
+
+ min = FFMAX(o->min, -1);
+ max = FFMIN(o->max, fmt_nb-1);
+
+ // hack for compatibility with old ffmpeg
+ if(min == 0 && max == 0) {
+ min = -1;
+ max = fmt_nb-1;
+ }
+
+ if (fmt < min || fmt > max) {
+ av_log(obj, AV_LOG_ERROR,
+ "Value %d for parameter '%s' out of %s format range [%d - %d]\n",
+ fmt, o->name, desc, min, max);
+ return AVERROR(ERANGE);
+ }
+
+ *(int *)dst = fmt;
+ return 0;
+}
+
+static int set_string_pixel_fmt(void *obj, const AVOption *o, const char *val, uint8_t *dst)
+{
+ return set_string_fmt(obj, o, val, dst,
+ AV_PIX_FMT_NB, av_get_pix_fmt, "pixel format");
+}
+
+static int set_string_sample_fmt(void *obj, const AVOption *o, const char *val, uint8_t *dst)
+{
+ return set_string_fmt(obj, o, val, dst,
+ AV_SAMPLE_FMT_NB, av_get_sample_fmt, "sample format");
+}
+
+int av_opt_set(void *obj, const char *name, const char *val, int search_flags)
+{
+ int ret = 0;
+ void *dst, *target_obj;
+ const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj);
+ if (!o || !target_obj)
+ return AVERROR_OPTION_NOT_FOUND;
+ if (!val && (o->type != AV_OPT_TYPE_STRING &&
+ o->type != AV_OPT_TYPE_PIXEL_FMT && o->type != AV_OPT_TYPE_SAMPLE_FMT &&
+ o->type != AV_OPT_TYPE_IMAGE_SIZE && o->type != AV_OPT_TYPE_VIDEO_RATE &&
+ o->type != AV_OPT_TYPE_DURATION && o->type != AV_OPT_TYPE_COLOR &&
+ o->type != AV_OPT_TYPE_CHANNEL_LAYOUT && o->type != AV_OPT_TYPE_BOOL))
+ return AVERROR(EINVAL);
+
+ if (o->flags & AV_OPT_FLAG_READONLY)
+ return AVERROR(EINVAL);
+
+ dst = ((uint8_t *)target_obj) + o->offset;
+ switch (o->type) {
+ case AV_OPT_TYPE_BOOL:
+ return set_string_bool(obj, o, val, dst);
+ case AV_OPT_TYPE_STRING:
+ return set_string(obj, o, val, dst);
+ case AV_OPT_TYPE_BINARY:
+ return set_string_binary(obj, o, val, dst);
+ 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:
+ return set_string_number(obj, target_obj, o, val, dst);
+ case AV_OPT_TYPE_IMAGE_SIZE:
+ return set_string_image_size(obj, o, val, dst);
+ case AV_OPT_TYPE_VIDEO_RATE: {
+ AVRational tmp;
+ ret = set_string_video_rate(obj, o, val, &tmp);
+ if (ret < 0)
+ return ret;
+ return write_number(obj, o, dst, 1, tmp.den, tmp.num);
+ }
+ case AV_OPT_TYPE_PIXEL_FMT:
+ return set_string_pixel_fmt(obj, o, val, dst);
+ case AV_OPT_TYPE_SAMPLE_FMT:
+ return set_string_sample_fmt(obj, o, val, dst);
+ case AV_OPT_TYPE_DURATION:
+ if (!val) {
+ *(int64_t *)dst = 0;
+ return 0;
+ } else {
+ if ((ret = av_parse_time(dst, val, 1)) < 0)
+ av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\" as duration\n", val);
+ return ret;
+ }
+ break;
+ case AV_OPT_TYPE_COLOR:
+ return set_string_color(obj, o, val, dst);
+ case AV_OPT_TYPE_CHANNEL_LAYOUT:
+ if (!val || !strcmp(val, "none")) {
+ *(int64_t *)dst = 0;
+ } else {
+ int64_t cl = av_get_channel_layout(val);
+ if (!cl) {
+ av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\" as channel layout\n", val);
+ ret = AVERROR(EINVAL);
+ }
+ *(int64_t *)dst = cl;
+ return ret;
+ }
+ break;
+ }
+
+ av_log(obj, AV_LOG_ERROR, "Invalid option type.\n");
+ return AVERROR(EINVAL);
+}
+
+#define OPT_EVAL_NUMBER(name, opttype, vartype) \
+int av_opt_eval_ ## name(void *obj, const AVOption *o, \
+ const char *val, vartype *name ## _out) \
+{ \
+ if (!o || o->type != opttype || o->flags & AV_OPT_FLAG_READONLY) \
+ return AVERROR(EINVAL); \
+ return set_string_number(obj, obj, o, val, name ## _out); \
+}
+
+OPT_EVAL_NUMBER(flags, AV_OPT_TYPE_FLAGS, int)
+OPT_EVAL_NUMBER(int, AV_OPT_TYPE_INT, int)
+OPT_EVAL_NUMBER(int64, AV_OPT_TYPE_INT64, int64_t)
+OPT_EVAL_NUMBER(float, AV_OPT_TYPE_FLOAT, float)
+OPT_EVAL_NUMBER(double, AV_OPT_TYPE_DOUBLE, double)
+OPT_EVAL_NUMBER(q, AV_OPT_TYPE_RATIONAL, AVRational)
+
+static int set_number(void *obj, const char *name, double num, int den, int64_t intnum,
+ int search_flags)
+{
+ void *dst, *target_obj;
+ const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj);
+
+ if (!o || !target_obj)
+ return AVERROR_OPTION_NOT_FOUND;
+
+ if (o->flags & AV_OPT_FLAG_READONLY)
+ return AVERROR(EINVAL);
+
+ dst = ((uint8_t *)target_obj) + o->offset;
+ return write_number(obj, o, dst, num, den, intnum);
+}
+
+int av_opt_set_int(void *obj, const char *name, int64_t val, int search_flags)
+{
+ return set_number(obj, name, 1, 1, val, search_flags);
+}
+
+int av_opt_set_double(void *obj, const char *name, double val, int search_flags)
+{
+ return set_number(obj, name, val, 1, 1, search_flags);
+}
+
+int av_opt_set_q(void *obj, const char *name, AVRational val, int search_flags)
+{
+ return set_number(obj, name, val.num, val.den, 1, search_flags);
+}
+
+int av_opt_set_bin(void *obj, const char *name, const uint8_t *val, int len, int search_flags)
+{
+ void *target_obj;
+ const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj);
+ uint8_t *ptr;
+ uint8_t **dst;
+ int *lendst;
+
+ if (!o || !target_obj)
+ return AVERROR_OPTION_NOT_FOUND;
+
+ if (o->type != AV_OPT_TYPE_BINARY || o->flags & AV_OPT_FLAG_READONLY)
+ return AVERROR(EINVAL);
+
+ ptr = len ? av_malloc(len) : NULL;
+ if (len && !ptr)
+ return AVERROR(ENOMEM);
+
+ dst = (uint8_t **)(((uint8_t *)target_obj) + o->offset);
+ lendst = (int *)(dst + 1);
+
+ av_free(*dst);
+ *dst = ptr;
+ *lendst = len;
+ if (len)
+ memcpy(ptr, val, len);
+
+ return 0;
+}
+
+int av_opt_set_image_size(void *obj, const char *name, int w, int h, int search_flags)
+{
+ void *target_obj;
+ const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj);
+
+ if (!o || !target_obj)
+ return AVERROR_OPTION_NOT_FOUND;
+ if (o->type != AV_OPT_TYPE_IMAGE_SIZE) {
+ av_log(obj, AV_LOG_ERROR,
+ "The value set by option '%s' is not an image size.\n", o->name);
+ return AVERROR(EINVAL);
+ }
+ if (w<0 || h<0) {
+ av_log(obj, AV_LOG_ERROR,
+ "Invalid negative size value %dx%d for size '%s'\n", w, h, o->name);
+ return AVERROR(EINVAL);
+ }
+ *(int *)(((uint8_t *)target_obj) + o->offset) = w;
+ *(int *)(((uint8_t *)target_obj+sizeof(int)) + o->offset) = h;
+ return 0;
+}
+
+int av_opt_set_video_rate(void *obj, const char *name, AVRational val, int search_flags)
+{
+ void *target_obj;
+ const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj);
+
+ if (!o || !target_obj)
+ return AVERROR_OPTION_NOT_FOUND;
+ if (o->type != AV_OPT_TYPE_VIDEO_RATE) {
+ av_log(obj, AV_LOG_ERROR,
+ "The value set by option '%s' is not a video rate.\n", o->name);
+ return AVERROR(EINVAL);
+ }
+ if (val.num <= 0 || val.den <= 0)
+ return AVERROR(EINVAL);
+ return set_number(obj, name, val.num, val.den, 1, search_flags);
+}
+
+static int set_format(void *obj, const char *name, int fmt, int search_flags,
+ enum AVOptionType type, const char *desc, int nb_fmts)
+{
+ void *target_obj;
+ const AVOption *o = av_opt_find2(obj, name, NULL, 0,
+ search_flags, &target_obj);
+ int min, max;
+
+ if (!o || !target_obj)
+ return AVERROR_OPTION_NOT_FOUND;
+ if (o->type != type) {
+ av_log(obj, AV_LOG_ERROR,
+ "The value set by option '%s' is not a %s format", name, desc);
+ return AVERROR(EINVAL);
+ }
+
+ min = FFMAX(o->min, -1);
+ max = FFMIN(o->max, nb_fmts-1);
+
+ if (fmt < min || fmt > max) {
+ av_log(obj, AV_LOG_ERROR,
+ "Value %d for parameter '%s' out of %s format range [%d - %d]\n",
+ fmt, name, desc, min, max);
+ return AVERROR(ERANGE);
+ }
+ *(int *)(((uint8_t *)target_obj) + o->offset) = fmt;
+ return 0;
+}
+
+int av_opt_set_pixel_fmt(void *obj, const char *name, enum AVPixelFormat fmt, int search_flags)
+{
+ return set_format(obj, name, fmt, search_flags, AV_OPT_TYPE_PIXEL_FMT, "pixel", AV_PIX_FMT_NB);
+}
+
+int av_opt_set_sample_fmt(void *obj, const char *name, enum AVSampleFormat fmt, int search_flags)
+{
+ return set_format(obj, name, fmt, search_flags, AV_OPT_TYPE_SAMPLE_FMT, "sample", AV_SAMPLE_FMT_NB);
+}
+
+int av_opt_set_channel_layout(void *obj, const char *name, int64_t cl, int search_flags)
+{
+ void *target_obj;
+ const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj);
+
+ if (!o || !target_obj)
+ return AVERROR_OPTION_NOT_FOUND;
+ if (o->type != AV_OPT_TYPE_CHANNEL_LAYOUT) {
+ av_log(obj, AV_LOG_ERROR,
+ "The value set by option '%s' is not a channel layout.\n", o->name);
+ return AVERROR(EINVAL);
+ }
+ *(int64_t *)(((uint8_t *)target_obj) + o->offset) = cl;
+ return 0;
+}
+
+int av_opt_set_dict_val(void *obj, const char *name, const AVDictionary *val,
+ int search_flags)
+{
+ void *target_obj;
+ AVDictionary **dst;
+ const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj);
+
+ if (!o || !target_obj)
+ return AVERROR_OPTION_NOT_FOUND;
+ if (o->flags & AV_OPT_FLAG_READONLY)
+ return AVERROR(EINVAL);
+
+ dst = (AVDictionary **)(((uint8_t *)target_obj) + o->offset);
+ av_dict_free(dst);
+ av_dict_copy(dst, val, 0);
+
+ return 0;
+}
+
+static void format_duration(char *buf, size_t size, int64_t d)
+{
+ char *e;
+
+ av_assert0(size >= 25);
+ if (d < 0 && d != INT64_MIN) {
+ *(buf++) = '-';
+ size--;
+ d = -d;
+ }
+ if (d == INT64_MAX)
+ snprintf(buf, size, "INT64_MAX");
+ else if (d == INT64_MIN)
+ snprintf(buf, size, "INT64_MIN");
+ else if (d > (int64_t)3600*1000000)
+ snprintf(buf, size, "%"PRId64":%02d:%02d.%06d", d / 3600000000,
+ (int)((d / 60000000) % 60),
+ (int)((d / 1000000) % 60),
+ (int)(d % 1000000));
+ else if (d > 60*1000000)
+ snprintf(buf, size, "%d:%02d.%06d",
+ (int)(d / 60000000),
+ (int)((d / 1000000) % 60),
+ (int)(d % 1000000));
+ else
+ snprintf(buf, size, "%d.%06d",
+ (int)(d / 1000000),
+ (int)(d % 1000000));
+ e = buf + strlen(buf);
+ while (e > buf && e[-1] == '0')
+ *(--e) = 0;
+ if (e > buf && e[-1] == '.')
+ *(--e) = 0;
+}
+
+int av_opt_get(void *obj, const char *name, int search_flags, uint8_t **out_val)
+{
+ void *dst, *target_obj;
+ const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj);
+ uint8_t *bin, buf[128];
+ int len, i, ret;
+ int64_t i64;
+
+ if (!o || !target_obj || (o->offset<=0 && o->type != AV_OPT_TYPE_CONST))
+ return AVERROR_OPTION_NOT_FOUND;
+
+ dst = (uint8_t *)target_obj + o->offset;
+
+ buf[0] = 0;
+ switch (o->type) {
+ case AV_OPT_TYPE_BOOL:
+ ret = snprintf(buf, sizeof(buf), "%s", (char *)av_x_if_null(get_bool_name(*(int *)dst), "invalid"));
+ break;
+ case AV_OPT_TYPE_FLAGS:
+ ret = snprintf(buf, sizeof(buf), "0x%08X", *(int *)dst);
+ break;
+ case AV_OPT_TYPE_INT:
+ ret = snprintf(buf, sizeof(buf), "%d", *(int *)dst);
+ break;
+ 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;
+ case AV_OPT_TYPE_DOUBLE:
+ ret = snprintf(buf, sizeof(buf), "%f", *(double *)dst);
+ break;
+ case AV_OPT_TYPE_VIDEO_RATE:
+ case AV_OPT_TYPE_RATIONAL:
+ ret = snprintf(buf, sizeof(buf), "%d/%d", ((AVRational *)dst)->num, ((AVRational *)dst)->den);
+ break;
+ case AV_OPT_TYPE_CONST:
+ ret = snprintf(buf, sizeof(buf), "%f", o->default_val.dbl);
+ break;
+ case AV_OPT_TYPE_STRING:
+ if (*(uint8_t **)dst) {
+ *out_val = av_strdup(*(uint8_t **)dst);
+ } else if (search_flags & AV_OPT_ALLOW_NULL) {
+ *out_val = NULL;
+ return 0;
+ } else {
+ *out_val = av_strdup("");
+ }
+ return *out_val ? 0 : AVERROR(ENOMEM);
+ case AV_OPT_TYPE_BINARY:
+ if (!*(uint8_t **)dst && (search_flags & AV_OPT_ALLOW_NULL)) {
+ *out_val = NULL;
+ return 0;
+ }
+ len = *(int *)(((uint8_t *)dst) + sizeof(uint8_t *));
+ if ((uint64_t)len * 2 + 1 > INT_MAX)
+ return AVERROR(EINVAL);
+ if (!(*out_val = av_malloc(len * 2 + 1)))
+ return AVERROR(ENOMEM);
+ if (!len) {
+ *out_val[0] = '\0';
+ return 0;
+ }
+ bin = *(uint8_t **)dst;
+ for (i = 0; i < len; i++)
+ snprintf(*out_val + i * 2, 3, "%02X", bin[i]);
+ return 0;
+ case AV_OPT_TYPE_IMAGE_SIZE:
+ ret = snprintf(buf, sizeof(buf), "%dx%d", ((int *)dst)[0], ((int *)dst)[1]);
+ break;
+ case AV_OPT_TYPE_PIXEL_FMT:
+ ret = snprintf(buf, sizeof(buf), "%s", (char *)av_x_if_null(av_get_pix_fmt_name(*(enum AVPixelFormat *)dst), "none"));
+ break;
+ case AV_OPT_TYPE_SAMPLE_FMT:
+ ret = snprintf(buf, sizeof(buf), "%s", (char *)av_x_if_null(av_get_sample_fmt_name(*(enum AVSampleFormat *)dst), "none"));
+ break;
+ case AV_OPT_TYPE_DURATION:
+ i64 = *(int64_t *)dst;
+ format_duration(buf, sizeof(buf), i64);
+ ret = strlen(buf); // no overflow possible, checked by an assert
+ break;
+ case AV_OPT_TYPE_COLOR:
+ ret = snprintf(buf, sizeof(buf), "0x%02x%02x%02x%02x",
+ (int)((uint8_t *)dst)[0], (int)((uint8_t *)dst)[1],
+ (int)((uint8_t *)dst)[2], (int)((uint8_t *)dst)[3]);
+ break;
+ case AV_OPT_TYPE_CHANNEL_LAYOUT:
+ i64 = *(int64_t *)dst;
+ ret = snprintf(buf, sizeof(buf), "0x%"PRIx64, i64);
+ break;
+ default:
+ return AVERROR(EINVAL);
+ }
+
+ if (ret >= sizeof(buf))
+ return AVERROR(EINVAL);
+ *out_val = av_strdup(buf);
+ return *out_val ? 0 : AVERROR(ENOMEM);
+}
+
+static int get_number(void *obj, const char *name, const AVOption **o_out, double *num, int *den, int64_t *intnum,
+ int search_flags)
+{
+ void *dst, *target_obj;
+ const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj);
+ if (!o || !target_obj)
+ goto error;
+
+ dst = ((uint8_t *)target_obj) + o->offset;
+
+ if (o_out) *o_out= o;
+
+ return read_number(o, dst, num, den, intnum);
+
+error:
+ *den =
+ *intnum = 0;
+ return -1;
+}
+
+int av_opt_get_int(void *obj, const char *name, int search_flags, int64_t *out_val)
+{
+ int64_t intnum = 1;
+ double num = 1;
+ int ret, den = 1;
+
+ if ((ret = get_number(obj, name, NULL, &num, &den, &intnum, search_flags)) < 0)
+ return ret;
+ *out_val = num * intnum / den;
+ return 0;
+}
+
+int av_opt_get_double(void *obj, const char *name, int search_flags, double *out_val)
+{
+ int64_t intnum = 1;
+ double num = 1;
+ int ret, den = 1;
+
+ if ((ret = get_number(obj, name, NULL, &num, &den, &intnum, search_flags)) < 0)
+ return ret;
+ *out_val = num * intnum / den;
+ return 0;
+}
+
+int av_opt_get_q(void *obj, const char *name, int search_flags, AVRational *out_val)
+{
+ int64_t intnum = 1;
+ double num = 1;
+ int ret, den = 1;
+
+ if ((ret = get_number(obj, name, NULL, &num, &den, &intnum, search_flags)) < 0)
+ return ret;
+
+ if (num == 1.0 && (int)intnum == intnum)
+ *out_val = (AVRational){intnum, den};
+ else
+ *out_val = av_d2q(num*intnum/den, 1<<24);
+ return 0;
+}
+
+int av_opt_get_image_size(void *obj, const char *name, int search_flags, int *w_out, int *h_out)
+{
+ void *dst, *target_obj;
+ const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj);
+ if (!o || !target_obj)
+ return AVERROR_OPTION_NOT_FOUND;
+ if (o->type != AV_OPT_TYPE_IMAGE_SIZE) {
+ av_log(obj, AV_LOG_ERROR,
+ "The value for option '%s' is not an image size.\n", name);
+ return AVERROR(EINVAL);
+ }
+
+ dst = ((uint8_t*)target_obj) + o->offset;
+ if (w_out) *w_out = *(int *)dst;
+ if (h_out) *h_out = *((int *)dst+1);
+ return 0;
+}
+
+int av_opt_get_video_rate(void *obj, const char *name, int search_flags, AVRational *out_val)
+{
+ int64_t intnum = 1;
+ double num = 1;
+ int ret, den = 1;
+
+ if ((ret = get_number(obj, name, NULL, &num, &den, &intnum, search_flags)) < 0)
+ return ret;
+
+ if (num == 1.0 && (int)intnum == intnum)
+ *out_val = (AVRational) { intnum, den };
+ else
+ *out_val = av_d2q(num * intnum / den, 1 << 24);
+ return 0;
+}
+
+static int get_format(void *obj, const char *name, int search_flags, int *out_fmt,
+ enum AVOptionType type, const char *desc)
+{
+ void *dst, *target_obj;
+ const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj);
+ if (!o || !target_obj)
+ return AVERROR_OPTION_NOT_FOUND;
+ if (o->type != type) {
+ av_log(obj, AV_LOG_ERROR,
+ "The value for option '%s' is not a %s format.\n", desc, name);
+ return AVERROR(EINVAL);
+ }
+
+ dst = ((uint8_t*)target_obj) + o->offset;
+ *out_fmt = *(int *)dst;
+ return 0;
+}
+
+int av_opt_get_pixel_fmt(void *obj, const char *name, int search_flags, enum AVPixelFormat *out_fmt)
+{
+ return get_format(obj, name, search_flags, out_fmt, AV_OPT_TYPE_PIXEL_FMT, "pixel");
+}
+
+int av_opt_get_sample_fmt(void *obj, const char *name, int search_flags, enum AVSampleFormat *out_fmt)
+{
+ return get_format(obj, name, search_flags, out_fmt, AV_OPT_TYPE_SAMPLE_FMT, "sample");
+}
+
+int av_opt_get_channel_layout(void *obj, const char *name, int search_flags, int64_t *cl)
+{
+ void *dst, *target_obj;
+ const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj);
+ if (!o || !target_obj)
+ return AVERROR_OPTION_NOT_FOUND;
+ if (o->type != AV_OPT_TYPE_CHANNEL_LAYOUT) {
+ av_log(obj, AV_LOG_ERROR,
+ "The value for option '%s' is not a channel layout.\n", name);
+ return AVERROR(EINVAL);
+ }
+
+ dst = ((uint8_t*)target_obj) + o->offset;
+ *cl = *(int64_t *)dst;
+ return 0;
+}
+
+int av_opt_get_dict_val(void *obj, const char *name, int search_flags, AVDictionary **out_val)
+{
+ void *target_obj;
+ AVDictionary *src;
+ const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj);
+
+ if (!o || !target_obj)
+ return AVERROR_OPTION_NOT_FOUND;
+ if (o->type != AV_OPT_TYPE_DICT)
+ return AVERROR(EINVAL);
+
+ src = *(AVDictionary **)(((uint8_t *)target_obj) + o->offset);
+ av_dict_copy(out_val, src, 0);
+
+ return 0;
+}
+
+int av_opt_flag_is_set(void *obj, const char *field_name, const char *flag_name)
+{
+ const AVOption *field = av_opt_find(obj, field_name, NULL, 0, 0);
+ const AVOption *flag = av_opt_find(obj, flag_name,
+ field ? field->unit : NULL, 0, 0);
+ int64_t res;
+
+ if (!field || !flag || flag->type != AV_OPT_TYPE_CONST ||
+ av_opt_get_int(obj, field_name, 0, &res) < 0)
+ return 0;
+ return res & flag->default_val.i64;
+}
+
+static void log_value(void *av_log_obj, int level, double d)
+{
+ if (d == INT_MAX) {
+ av_log(av_log_obj, level, "INT_MAX");
+ } else if (d == INT_MIN) {
+ av_log(av_log_obj, level, "INT_MIN");
+ } else if (d == UINT32_MAX) {
+ av_log(av_log_obj, level, "UINT32_MAX");
+ } else if (d == (double)INT64_MAX) {
+ av_log(av_log_obj, level, "I64_MAX");
+ } else if (d == INT64_MIN) {
+ av_log(av_log_obj, level, "I64_MIN");
+ } else if (d == FLT_MAX) {
+ av_log(av_log_obj, level, "FLT_MAX");
+ } else if (d == FLT_MIN) {
+ av_log(av_log_obj, level, "FLT_MIN");
+ } else if (d == -FLT_MAX) {
+ av_log(av_log_obj, level, "-FLT_MAX");
+ } else if (d == -FLT_MIN) {
+ av_log(av_log_obj, level, "-FLT_MIN");
+ } else if (d == DBL_MAX) {
+ av_log(av_log_obj, level, "DBL_MAX");
+ } else if (d == DBL_MIN) {
+ av_log(av_log_obj, level, "DBL_MIN");
+ } else if (d == -DBL_MAX) {
+ av_log(av_log_obj, level, "-DBL_MAX");
+ } else if (d == -DBL_MIN) {
+ av_log(av_log_obj, level, "-DBL_MIN");
+ } else {
+ av_log(av_log_obj, level, "%g", d);
+ }
+}
+
+static const char *get_opt_const_name(void *obj, const char *unit, int64_t value)
+{
+ const AVOption *opt = NULL;
+
+ if (!unit)
+ return NULL;
+ while ((opt = av_opt_next(obj, opt)))
+ if (opt->type == AV_OPT_TYPE_CONST && !strcmp(opt->unit, unit) &&
+ opt->default_val.i64 == value)
+ return opt->name;
+ return NULL;
+}
+
+static char *get_opt_flags_string(void *obj, const char *unit, int64_t value)
+{
+ const AVOption *opt = NULL;
+ char flags[512];
+
+ flags[0] = 0;
+ if (!unit)
+ return NULL;
+ while ((opt = av_opt_next(obj, opt))) {
+ if (opt->type == AV_OPT_TYPE_CONST && !strcmp(opt->unit, unit) &&
+ opt->default_val.i64 & value) {
+ if (flags[0])
+ av_strlcatf(flags, sizeof(flags), "+");
+ av_strlcatf(flags, sizeof(flags), "%s", opt->name);
+ }
+ }
+ if (flags[0])
+ return av_strdup(flags);
+ return NULL;
+}
+
+static void opt_list(void *obj, void *av_log_obj, const char *unit,
+ int req_flags, int rej_flags)
+{
+ const AVOption *opt = NULL;
+ AVOptionRanges *r;
+ int i;
+
+ while ((opt = av_opt_next(obj, opt))) {
+ if (!(opt->flags & req_flags) || (opt->flags & rej_flags))
+ continue;
+
+ /* Don't print CONST's on level one.
+ * Don't print anything but CONST's on level two.
+ * Only print items from the requested unit.
+ */
+ if (!unit && opt->type == AV_OPT_TYPE_CONST)
+ continue;
+ else if (unit && opt->type != AV_OPT_TYPE_CONST)
+ continue;
+ else if (unit && opt->type == AV_OPT_TYPE_CONST && strcmp(unit, opt->unit))
+ continue;
+ else if (unit && opt->type == AV_OPT_TYPE_CONST)
+ av_log(av_log_obj, AV_LOG_INFO, " %-15s ", opt->name);
+ else
+ av_log(av_log_obj, AV_LOG_INFO, " %s%-17s ",
+ (opt->flags & AV_OPT_FLAG_FILTERING_PARAM) ? "" : "-",
+ opt->name);
+
+ switch (opt->type) {
+ case AV_OPT_TYPE_FLAGS:
+ av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<flags>");
+ break;
+ case AV_OPT_TYPE_INT:
+ av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<int>");
+ break;
+ 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;
+ case AV_OPT_TYPE_FLOAT:
+ av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<float>");
+ break;
+ case AV_OPT_TYPE_STRING:
+ av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<string>");
+ break;
+ case AV_OPT_TYPE_RATIONAL:
+ av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<rational>");
+ break;
+ case AV_OPT_TYPE_BINARY:
+ av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<binary>");
+ break;
+ case AV_OPT_TYPE_IMAGE_SIZE:
+ av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<image_size>");
+ break;
+ case AV_OPT_TYPE_VIDEO_RATE:
+ av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<video_rate>");
+ break;
+ case AV_OPT_TYPE_PIXEL_FMT:
+ av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<pix_fmt>");
+ break;
+ case AV_OPT_TYPE_SAMPLE_FMT:
+ av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<sample_fmt>");
+ break;
+ case AV_OPT_TYPE_DURATION:
+ av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<duration>");
+ break;
+ case AV_OPT_TYPE_COLOR:
+ av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<color>");
+ break;
+ case AV_OPT_TYPE_CHANNEL_LAYOUT:
+ av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<channel_layout>");
+ break;
+ case AV_OPT_TYPE_BOOL:
+ av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<boolean>");
+ break;
+ case AV_OPT_TYPE_CONST:
+ default:
+ av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "");
+ break;
+ }
+ av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_ENCODING_PARAM) ? 'E' : '.');
+ av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_DECODING_PARAM) ? 'D' : '.');
+ av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_FILTERING_PARAM)? 'F' : '.');
+ av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_VIDEO_PARAM ) ? 'V' : '.');
+ av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_AUDIO_PARAM ) ? 'A' : '.');
+ av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_SUBTITLE_PARAM) ? 'S' : '.');
+ av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_EXPORT) ? 'X' : '.');
+ av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_READONLY) ? 'R' : '.');
+
+ if (opt->help)
+ av_log(av_log_obj, AV_LOG_INFO, " %s", opt->help);
+
+ if (av_opt_query_ranges(&r, obj, opt->name, AV_OPT_SEARCH_FAKE_OBJ) >= 0) {
+ 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:
+ for (i = 0; i < r->nb_ranges; i++) {
+ av_log(av_log_obj, AV_LOG_INFO, " (from ");
+ log_value(av_log_obj, AV_LOG_INFO, r->range[i]->value_min);
+ av_log(av_log_obj, AV_LOG_INFO, " to ");
+ log_value(av_log_obj, AV_LOG_INFO, r->range[i]->value_max);
+ av_log(av_log_obj, AV_LOG_INFO, ")");
+ }
+ break;
+ }
+ av_opt_freep_ranges(&r);
+ }
+
+ if (opt->type != AV_OPT_TYPE_CONST &&
+ opt->type != AV_OPT_TYPE_BINARY &&
+ !((opt->type == AV_OPT_TYPE_COLOR ||
+ opt->type == AV_OPT_TYPE_IMAGE_SIZE ||
+ opt->type == AV_OPT_TYPE_STRING ||
+ opt->type == AV_OPT_TYPE_VIDEO_RATE) &&
+ !opt->default_val.str)) {
+ av_log(av_log_obj, AV_LOG_INFO, " (default ");
+ switch (opt->type) {
+ case AV_OPT_TYPE_BOOL:
+ av_log(av_log_obj, AV_LOG_INFO, "%s", (char *)av_x_if_null(get_bool_name(opt->default_val.i64), "invalid"));
+ break;
+ case AV_OPT_TYPE_FLAGS: {
+ char *def_flags = get_opt_flags_string(obj, opt->unit, opt->default_val.i64);
+ if (def_flags) {
+ av_log(av_log_obj, AV_LOG_INFO, "%s", def_flags);
+ av_freep(&def_flags);
+ } else {
+ av_log(av_log_obj, AV_LOG_INFO, "%"PRIX64, opt->default_val.i64);
+ }
+ break;
+ }
+ case AV_OPT_TYPE_DURATION: {
+ char buf[25];
+ format_duration(buf, sizeof(buf), opt->default_val.i64);
+ av_log(av_log_obj, AV_LOG_INFO, "%s", buf);
+ 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)
+ av_log(av_log_obj, AV_LOG_INFO, "%s", def_const);
+ else
+ log_value(av_log_obj, AV_LOG_INFO, opt->default_val.i64);
+ break;
+ }
+ case AV_OPT_TYPE_DOUBLE:
+ case AV_OPT_TYPE_FLOAT:
+ log_value(av_log_obj, AV_LOG_INFO, opt->default_val.dbl);
+ break;
+ case AV_OPT_TYPE_RATIONAL: {
+ AVRational q = av_d2q(opt->default_val.dbl, INT_MAX);
+ av_log(av_log_obj, AV_LOG_INFO, "%d/%d", q.num, q.den); }
+ break;
+ case AV_OPT_TYPE_PIXEL_FMT:
+ av_log(av_log_obj, AV_LOG_INFO, "%s", (char *)av_x_if_null(av_get_pix_fmt_name(opt->default_val.i64), "none"));
+ break;
+ case AV_OPT_TYPE_SAMPLE_FMT:
+ av_log(av_log_obj, AV_LOG_INFO, "%s", (char *)av_x_if_null(av_get_sample_fmt_name(opt->default_val.i64), "none"));
+ break;
+ case AV_OPT_TYPE_COLOR:
+ case AV_OPT_TYPE_IMAGE_SIZE:
+ case AV_OPT_TYPE_STRING:
+ case AV_OPT_TYPE_VIDEO_RATE:
+ av_log(av_log_obj, AV_LOG_INFO, "\"%s\"", opt->default_val.str);
+ break;
+ case AV_OPT_TYPE_CHANNEL_LAYOUT:
+ av_log(av_log_obj, AV_LOG_INFO, "0x%"PRIx64, opt->default_val.i64);
+ break;
+ }
+ av_log(av_log_obj, AV_LOG_INFO, ")");
+ }
+
+ av_log(av_log_obj, AV_LOG_INFO, "\n");
+ if (opt->unit && opt->type != AV_OPT_TYPE_CONST)
+ opt_list(obj, av_log_obj, opt->unit, req_flags, rej_flags);
+ }
+}
+
+int av_opt_show2(void *obj, void *av_log_obj, int req_flags, int rej_flags)
+{
+ if (!obj)
+ return -1;
+
+ av_log(av_log_obj, AV_LOG_INFO, "%s AVOptions:\n", (*(AVClass **)obj)->class_name);
+
+ opt_list(obj, av_log_obj, NULL, req_flags, rej_flags);
+
+ return 0;
+}
+
+void av_opt_set_defaults(void *s)
+{
+ av_opt_set_defaults2(s, 0, 0);
+}
+
+void av_opt_set_defaults2(void *s, int mask, int flags)
+{
+ const AVOption *opt = NULL;
+ while ((opt = av_opt_next(s, opt))) {
+ void *dst = ((uint8_t*)s) + opt->offset;
+
+ if ((opt->flags & mask) != flags)
+ continue;
+
+ if (opt->flags & AV_OPT_FLAG_READONLY)
+ continue;
+
+ switch (opt->type) {
+ case AV_OPT_TYPE_CONST:
+ /* Nothing to be done here */
+ break;
+ case AV_OPT_TYPE_BOOL:
+ 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:
+ case AV_OPT_TYPE_SAMPLE_FMT:
+ write_number(s, opt, dst, 1, 1, opt->default_val.i64);
+ break;
+ case AV_OPT_TYPE_DOUBLE:
+ case AV_OPT_TYPE_FLOAT: {
+ double val;
+ val = opt->default_val.dbl;
+ write_number(s, opt, dst, val, 1, 1);
+ }
+ break;
+ case AV_OPT_TYPE_RATIONAL: {
+ AVRational val;
+ val = av_d2q(opt->default_val.dbl, INT_MAX);
+ write_number(s, opt, dst, 1, val.den, val.num);
+ }
+ break;
+ case AV_OPT_TYPE_COLOR:
+ set_string_color(s, opt, opt->default_val.str, dst);
+ break;
+ case AV_OPT_TYPE_STRING:
+ set_string(s, opt, opt->default_val.str, dst);
+ break;
+ case AV_OPT_TYPE_IMAGE_SIZE:
+ set_string_image_size(s, opt, opt->default_val.str, dst);
+ break;
+ case AV_OPT_TYPE_VIDEO_RATE:
+ set_string_video_rate(s, opt, opt->default_val.str, dst);
+ break;
+ case AV_OPT_TYPE_BINARY:
+ set_string_binary(s, opt, opt->default_val.str, dst);
+ break;
+ case AV_OPT_TYPE_DICT:
+ /* Cannot set defaults for these types */
+ break;
+ default:
+ av_log(s, AV_LOG_DEBUG, "AVOption type %d of option %s not implemented yet\n",
+ opt->type, opt->name);
+ }
+ }
+}
+
+/**
+ * Store the value in the field in ctx that is named like key.
+ * ctx must be an AVClass context, storing is done using AVOptions.
+ *
+ * @param buf the string to parse, buf will be updated to point at the
+ * separator just after the parsed key/value pair
+ * @param key_val_sep a 0-terminated list of characters used to
+ * separate key from value
+ * @param pairs_sep a 0-terminated list of characters used to separate
+ * two pairs from each other
+ * @return 0 if the key/value pair has been successfully parsed and
+ * set, or a negative value corresponding to an AVERROR code in case
+ * of error:
+ * AVERROR(EINVAL) if the key/value pair cannot be parsed,
+ * the error code issued by av_opt_set() if the key/value pair
+ * cannot be set
+ */
+static int parse_key_value_pair(void *ctx, const char **buf,
+ const char *key_val_sep, const char *pairs_sep)
+{
+ char *key = av_get_token(buf, key_val_sep);
+ char *val;
+ int ret;
+
+ if (!key)
+ return AVERROR(ENOMEM);
+
+ if (*key && strspn(*buf, key_val_sep)) {
+ (*buf)++;
+ val = av_get_token(buf, pairs_sep);
+ if (!val) {
+ av_freep(&key);
+ return AVERROR(ENOMEM);
+ }
+ } else {
+ av_log(ctx, AV_LOG_ERROR, "Missing key or no key/value separator found after key '%s'\n", key);
+ av_free(key);
+ return AVERROR(EINVAL);
+ }
+
+ av_log(ctx, AV_LOG_DEBUG, "Setting entry with key '%s' to value '%s'\n", key, val);
+
+ ret = av_opt_set(ctx, key, val, AV_OPT_SEARCH_CHILDREN);
+ if (ret == AVERROR_OPTION_NOT_FOUND)
+ av_log(ctx, AV_LOG_ERROR, "Key '%s' not found.\n", key);
+
+ av_free(key);
+ av_free(val);
+ return ret;
+}
+
+int av_set_options_string(void *ctx, const char *opts,
+ const char *key_val_sep, const char *pairs_sep)
+{
+ int ret, count = 0;
+
+ if (!opts)
+ return 0;
+
+ while (*opts) {
+ if ((ret = parse_key_value_pair(ctx, &opts, key_val_sep, pairs_sep)) < 0)
+ return ret;
+ count++;
+
+ if (*opts)
+ opts++;
+ }
+
+ return count;
+}
+
+#define WHITESPACES " \n\t\r"
+
+static int is_key_char(char c)
+{
+ return (unsigned)((c | 32) - 'a') < 26 ||
+ (unsigned)(c - '0') < 10 ||
+ c == '-' || c == '_' || c == '/' || c == '.';
+}
+
+/**
+ * Read a key from a string.
+ *
+ * The key consists of is_key_char characters and must be terminated by a
+ * character from the delim string; spaces are ignored.
+ *
+ * @return 0 for success (even with ellipsis), <0 for failure
+ */
+static int get_key(const char **ropts, const char *delim, char **rkey)
+{
+ const char *opts = *ropts;
+ const char *key_start, *key_end;
+
+ key_start = opts += strspn(opts, WHITESPACES);
+ while (is_key_char(*opts))
+ opts++;
+ key_end = opts;
+ opts += strspn(opts, WHITESPACES);
+ if (!*opts || !strchr(delim, *opts))
+ return AVERROR(EINVAL);
+ opts++;
+ if (!(*rkey = av_malloc(key_end - key_start + 1)))
+ return AVERROR(ENOMEM);
+ memcpy(*rkey, key_start, key_end - key_start);
+ (*rkey)[key_end - key_start] = 0;
+ *ropts = opts;
+ return 0;
+}
+
+int av_opt_get_key_value(const char **ropts,
+ const char *key_val_sep, const char *pairs_sep,
+ unsigned flags,
+ char **rkey, char **rval)
+{
+ int ret;
+ char *key = NULL, *val;
+ const char *opts = *ropts;
+
+ if ((ret = get_key(&opts, key_val_sep, &key)) < 0 &&
+ !(flags & AV_OPT_FLAG_IMPLICIT_KEY))
+ return AVERROR(EINVAL);
+ if (!(val = av_get_token(&opts, pairs_sep))) {
+ av_free(key);
+ return AVERROR(ENOMEM);
+ }
+ *ropts = opts;
+ *rkey = key;
+ *rval = val;
+ return 0;
+}
+
+int av_opt_set_from_string(void *ctx, const char *opts,
+ const char *const *shorthand,
+ const char *key_val_sep, const char *pairs_sep)
+{
+ int ret, count = 0;
+ const char *dummy_shorthand = NULL;
+ char *av_uninit(parsed_key), *av_uninit(value);
+ const char *key;
+
+ if (!opts)
+ return 0;
+ if (!shorthand)
+ shorthand = &dummy_shorthand;
+
+ while (*opts) {
+ ret = av_opt_get_key_value(&opts, key_val_sep, pairs_sep,
+ *shorthand ? AV_OPT_FLAG_IMPLICIT_KEY : 0,
+ &parsed_key, &value);
+ if (ret < 0) {
+ if (ret == AVERROR(EINVAL))
+ av_log(ctx, AV_LOG_ERROR, "No option name near '%s'\n", opts);
+ else
+ av_log(ctx, AV_LOG_ERROR, "Unable to parse '%s': %s\n", opts,
+ av_err2str(ret));
+ return ret;
+ }
+ if (*opts)
+ opts++;
+ if (parsed_key) {
+ key = parsed_key;
+ while (*shorthand) /* discard all remaining shorthand */
+ shorthand++;
+ } else {
+ key = *(shorthand++);
+ }
+
+ av_log(ctx, AV_LOG_DEBUG, "Setting '%s' to value '%s'\n", key, value);
+ if ((ret = av_opt_set(ctx, key, value, 0)) < 0) {
+ if (ret == AVERROR_OPTION_NOT_FOUND)
+ av_log(ctx, AV_LOG_ERROR, "Option '%s' not found\n", key);
+ av_free(value);
+ av_free(parsed_key);
+ return ret;
+ }
+
+ av_free(value);
+ av_free(parsed_key);
+ count++;
+ }
+ return count;
+}
+
+void av_opt_free(void *obj)
+{
+ const AVOption *o = NULL;
+ while ((o = av_opt_next(obj, o))) {
+ switch (o->type) {
+ case AV_OPT_TYPE_STRING:
+ case AV_OPT_TYPE_BINARY:
+ av_freep((uint8_t *)obj + o->offset);
+ break;
+
+ case AV_OPT_TYPE_DICT:
+ av_dict_free((AVDictionary **)(((uint8_t *)obj) + o->offset));
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
+int av_opt_set_dict2(void *obj, AVDictionary **options, int search_flags)
+{
+ AVDictionaryEntry *t = NULL;
+ AVDictionary *tmp = NULL;
+ int ret = 0;
+
+ if (!options)
+ return 0;
+
+ while ((t = av_dict_get(*options, "", t, AV_DICT_IGNORE_SUFFIX))) {
+ ret = av_opt_set(obj, t->key, t->value, search_flags);
+ if (ret == AVERROR_OPTION_NOT_FOUND)
+ ret = av_dict_set(&tmp, t->key, t->value, 0);
+ if (ret < 0) {
+ av_log(obj, AV_LOG_ERROR, "Error setting option %s to value %s.\n", t->key, t->value);
+ av_dict_free(&tmp);
+ return ret;
+ }
+ ret = 0;
+ }
+ av_dict_free(options);
+ *options = tmp;
+ return ret;
+}
+
+int av_opt_set_dict(void *obj, AVDictionary **options)
+{
+ return av_opt_set_dict2(obj, options, 0);
+}
+
+const AVOption *av_opt_find(void *obj, const char *name, const char *unit,
+ int opt_flags, int search_flags)
+{
+ return av_opt_find2(obj, name, unit, opt_flags, search_flags, NULL);
+}
+
+const AVOption *av_opt_find2(void *obj, const char *name, const char *unit,
+ int opt_flags, int search_flags, void **target_obj)
+{
+ const AVClass *c;
+ const AVOption *o = NULL;
+
+ if(!obj)
+ return NULL;
+
+ c= *(AVClass**)obj;
+
+ if (!c)
+ return NULL;
+
+ if (search_flags & AV_OPT_SEARCH_CHILDREN) {
+ if (search_flags & AV_OPT_SEARCH_FAKE_OBJ) {
+ const AVClass *child = NULL;
+ while (child = av_opt_child_class_next(c, child))
+ if (o = av_opt_find2(&child, name, unit, opt_flags, search_flags, NULL))
+ return o;
+ } else {
+ void *child = NULL;
+ while (child = av_opt_child_next(obj, child))
+ if (o = av_opt_find2(child, name, unit, opt_flags, search_flags, target_obj))
+ return o;
+ }
+ }
+
+ while (o = av_opt_next(obj, o)) {
+ if (!strcmp(o->name, name) && (o->flags & opt_flags) == opt_flags &&
+ ((!unit && o->type != AV_OPT_TYPE_CONST) ||
+ (unit && o->type == AV_OPT_TYPE_CONST && o->unit && !strcmp(o->unit, unit)))) {
+ if (target_obj) {
+ if (!(search_flags & AV_OPT_SEARCH_FAKE_OBJ))
+ *target_obj = obj;
+ else
+ *target_obj = NULL;
+ }
+ return o;
+ }
+ }
+ return NULL;
+}
+
+void *av_opt_child_next(void *obj, void *prev)
+{
+ const AVClass *c = *(AVClass **)obj;
+ if (c->child_next)
+ return c->child_next(obj, prev);
+ return NULL;
+}
+
+const AVClass *av_opt_child_class_next(const AVClass *parent, const AVClass *prev)
+{
+ if (parent->child_class_next)
+ return parent->child_class_next(prev);
+ return NULL;
+}
+
+void *av_opt_ptr(const AVClass *class, void *obj, const char *name)
+{
+ const AVOption *opt= av_opt_find2(&class, name, NULL, 0, AV_OPT_SEARCH_FAKE_OBJ, NULL);
+ if(!opt)
+ return NULL;
+ return (uint8_t*)obj + opt->offset;
+}
+
+static int opt_size(enum AVOptionType type)
+{
+ switch(type) {
+ case AV_OPT_TYPE_BOOL:
+ case AV_OPT_TYPE_INT:
+ case AV_OPT_TYPE_FLAGS:
+ return sizeof(int);
+ 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);
+ case AV_OPT_TYPE_FLOAT:
+ return sizeof(float);
+ case AV_OPT_TYPE_STRING:
+ return sizeof(uint8_t*);
+ case AV_OPT_TYPE_VIDEO_RATE:
+ case AV_OPT_TYPE_RATIONAL:
+ return sizeof(AVRational);
+ case AV_OPT_TYPE_BINARY:
+ return sizeof(uint8_t*) + sizeof(int);
+ case AV_OPT_TYPE_IMAGE_SIZE:
+ return sizeof(int[2]);
+ case AV_OPT_TYPE_PIXEL_FMT:
+ return sizeof(enum AVPixelFormat);
+ case AV_OPT_TYPE_SAMPLE_FMT:
+ return sizeof(enum AVSampleFormat);
+ case AV_OPT_TYPE_COLOR:
+ return 4;
+ }
+ return AVERROR(EINVAL);
+}
+
+int av_opt_copy(void *dst, const void *src)
+{
+ const AVOption *o = NULL;
+ const AVClass *c;
+ int ret = 0;
+
+ if (!src)
+ return AVERROR(EINVAL);
+
+ c = *(AVClass **)src;
+ if (!c || c != *(AVClass **)dst)
+ return AVERROR(EINVAL);
+
+ while ((o = av_opt_next(src, o))) {
+ void *field_dst = (uint8_t *)dst + o->offset;
+ void *field_src = (uint8_t *)src + o->offset;
+ uint8_t **field_dst8 = (uint8_t **)field_dst;
+ uint8_t **field_src8 = (uint8_t **)field_src;
+
+ if (o->type == AV_OPT_TYPE_STRING) {
+ if (*field_dst8 != *field_src8)
+ av_freep(field_dst8);
+ *field_dst8 = av_strdup(*field_src8);
+ if (*field_src8 && !*field_dst8)
+ ret = AVERROR(ENOMEM);
+ } else if (o->type == AV_OPT_TYPE_BINARY) {
+ int len = *(int *)(field_src8 + 1);
+ if (*field_dst8 != *field_src8)
+ av_freep(field_dst8);
+ *field_dst8 = av_memdup(*field_src8, len);
+ if (len && !*field_dst8) {
+ ret = AVERROR(ENOMEM);
+ len = 0;
+ }
+ *(int *)(field_dst8 + 1) = len;
+ } else if (o->type == AV_OPT_TYPE_CONST) {
+ // do nothing
+ } else if (o->type == AV_OPT_TYPE_DICT) {
+ AVDictionary **sdict = (AVDictionary **) field_src;
+ AVDictionary **ddict = (AVDictionary **) field_dst;
+ if (*sdict != *ddict)
+ av_dict_free(ddict);
+ *ddict = NULL;
+ av_dict_copy(ddict, *sdict, 0);
+ if (av_dict_count(*sdict) != av_dict_count(*ddict))
+ ret = AVERROR(ENOMEM);
+ } else {
+ int size = opt_size(o->type);
+ if (size < 0)
+ ret = size;
+ else
+ memcpy(field_dst, field_src, size);
+ }
+ }
+ return ret;
+}
+
+int av_opt_query_ranges(AVOptionRanges **ranges_arg, void *obj, const char *key, int flags)
+{
+ int ret;
+ const AVClass *c = *(AVClass**)obj;
+ int (*callback)(AVOptionRanges **, void *obj, const char *key, int flags) = NULL;
+
+ if (c->version > (52 << 16 | 11 << 8))
+ callback = c->query_ranges;
+
+ if (!callback)
+ callback = av_opt_query_ranges_default;
+
+ ret = callback(ranges_arg, obj, key, flags);
+ if (ret >= 0) {
+ if (!(flags & AV_OPT_MULTI_COMPONENT_RANGE))
+ ret = 1;
+ (*ranges_arg)->nb_components = ret;
+ }
+ return ret;
+}
+
+int av_opt_query_ranges_default(AVOptionRanges **ranges_arg, void *obj, const char *key, int flags)
+{
+ AVOptionRanges *ranges = av_mallocz(sizeof(*ranges));
+ AVOptionRange **range_array = av_mallocz(sizeof(void*));
+ AVOptionRange *range = av_mallocz(sizeof(*range));
+ const AVOption *field = av_opt_find(obj, key, NULL, 0, flags);
+ int ret;
+
+ *ranges_arg = NULL;
+
+ if (!ranges || !range || !range_array || !field) {
+ ret = AVERROR(ENOMEM);
+ goto fail;
+ }
+
+ ranges->range = range_array;
+ ranges->range[0] = range;
+ ranges->nb_ranges = 1;
+ ranges->nb_components = 1;
+ range->is_range = 1;
+ range->value_min = field->min;
+ range->value_max = field->max;
+
+ switch (field->type) {
+ 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:
+ case AV_OPT_TYPE_DOUBLE:
+ case AV_OPT_TYPE_DURATION:
+ case AV_OPT_TYPE_COLOR:
+ case AV_OPT_TYPE_CHANNEL_LAYOUT:
+ break;
+ case AV_OPT_TYPE_STRING:
+ range->component_min = 0;
+ range->component_max = 0x10FFFF; // max unicode value
+ range->value_min = -1;
+ range->value_max = INT_MAX;
+ break;
+ case AV_OPT_TYPE_RATIONAL:
+ range->component_min = INT_MIN;
+ range->component_max = INT_MAX;
+ break;
+ case AV_OPT_TYPE_IMAGE_SIZE:
+ range->component_min = 0;
+ range->component_max = INT_MAX/128/8;
+ range->value_min = 0;
+ range->value_max = INT_MAX/8;
+ break;
+ case AV_OPT_TYPE_VIDEO_RATE:
+ range->component_min = 1;
+ range->component_max = INT_MAX;
+ range->value_min = 1;
+ range->value_max = INT_MAX;
+ break;
+ default:
+ ret = AVERROR(ENOSYS);
+ goto fail;
+ }
+
+ *ranges_arg = ranges;
+ return 1;
+fail:
+ av_free(ranges);
+ av_free(range);
+ av_free(range_array);
+ return ret;
+}
+
+void av_opt_freep_ranges(AVOptionRanges **rangesp)
+{
+ int i;
+ AVOptionRanges *ranges = *rangesp;
+
+ if (!ranges)
+ return;
+
+ for (i = 0; i < ranges->nb_ranges * ranges->nb_components; i++) {
+ AVOptionRange *range = ranges->range[i];
+ if (range) {
+ av_freep(&range->str);
+ av_freep(&ranges->range[i]);
+ }
+ }
+ av_freep(&ranges->range);
+ av_freep(rangesp);
+}
+
+int av_opt_is_set_to_default(void *obj, const AVOption *o)
+{
+ int64_t i64;
+ double d, d2;
+ float f;
+ AVRational q;
+ int ret, w, h;
+ char *str;
+ void *dst;
+
+ if (!o || !obj)
+ return AVERROR(EINVAL);
+
+ dst = ((uint8_t*)obj) + o->offset;
+
+ switch (o->type) {
+ case AV_OPT_TYPE_CONST:
+ return 1;
+ case AV_OPT_TYPE_BOOL:
+ case AV_OPT_TYPE_FLAGS:
+ case AV_OPT_TYPE_PIXEL_FMT:
+ case AV_OPT_TYPE_SAMPLE_FMT:
+ case AV_OPT_TYPE_INT:
+ 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:
+ str = *(char **)dst;
+ if (str == o->default_val.str) //2 NULLs
+ return 1;
+ if (!str || !o->default_val.str) //1 NULL
+ return 0;
+ return !strcmp(str, o->default_val.str);
+ case AV_OPT_TYPE_DOUBLE:
+ read_number(o, dst, &d, NULL, NULL);
+ return o->default_val.dbl == d;
+ case AV_OPT_TYPE_FLOAT:
+ read_number(o, dst, &d, NULL, NULL);
+ f = o->default_val.dbl;
+ d2 = f;
+ return d2 == d;
+ case AV_OPT_TYPE_RATIONAL:
+ q = av_d2q(o->default_val.dbl, INT_MAX);
+ return !av_cmp_q(*(AVRational*)dst, q);
+ case AV_OPT_TYPE_BINARY: {
+ struct {
+ uint8_t *data;
+ int size;
+ } tmp = {0};
+ int opt_size = *(int *)((void **)dst + 1);
+ void *opt_ptr = *(void **)dst;
+ if (!opt_size && (!o->default_val.str || !strlen(o->default_val.str)))
+ return 1;
+ if (!opt_size || !o->default_val.str || !strlen(o->default_val.str ))
+ return 0;
+ if (opt_size != strlen(o->default_val.str) / 2)
+ return 0;
+ ret = set_string_binary(NULL, NULL, o->default_val.str, &tmp.data);
+ if (!ret)
+ ret = !memcmp(opt_ptr, tmp.data, tmp.size);
+ av_free(tmp.data);
+ return ret;
+ }
+ case AV_OPT_TYPE_DICT:
+ /* Binary and dict have not default support yet. Any pointer is not default. */
+ return !!(*(void **)dst);
+ case AV_OPT_TYPE_IMAGE_SIZE:
+ if (!o->default_val.str || !strcmp(o->default_val.str, "none"))
+ w = h = 0;
+ else if ((ret = av_parse_video_size(&w, &h, o->default_val.str)) < 0)
+ return ret;
+ return (w == *(int *)dst) && (h == *((int *)dst+1));
+ case AV_OPT_TYPE_VIDEO_RATE:
+ q = (AVRational){0, 0};
+ if (o->default_val.str) {
+ if ((ret = av_parse_video_rate(&q, o->default_val.str)) < 0)
+ return ret;
+ }
+ return !av_cmp_q(*(AVRational*)dst, q);
+ case AV_OPT_TYPE_COLOR: {
+ uint8_t color[4] = {0, 0, 0, 0};
+ if (o->default_val.str) {
+ if ((ret = av_parse_color(color, o->default_val.str, -1, NULL)) < 0)
+ return ret;
+ }
+ return !memcmp(color, dst, sizeof(color));
+ }
+ default:
+ av_log(obj, AV_LOG_WARNING, "Not supported option type: %d, option name: %s\n", o->type, o->name);
+ break;
+ }
+ return AVERROR_PATCHWELCOME;
+}
+
+int av_opt_is_set_to_default_by_name(void *obj, const char *name, int search_flags)
+{
+ const AVOption *o;
+ void *target;
+ if (!obj)
+ return AVERROR(EINVAL);
+ o = av_opt_find2(obj, name, NULL, 0, search_flags, &target);
+ if (!o)
+ return AVERROR_OPTION_NOT_FOUND;
+ return av_opt_is_set_to_default(target, o);
+}
+
+int av_opt_serialize(void *obj, int opt_flags, int flags, char **buffer,
+ const char key_val_sep, const char pairs_sep)
+{
+ const AVOption *o = NULL;
+ uint8_t *buf;
+ AVBPrint bprint;
+ int ret, cnt = 0;
+ const char special_chars[] = {pairs_sep, key_val_sep, '\0'};
+
+ if (pairs_sep == '\0' || key_val_sep == '\0' || pairs_sep == key_val_sep ||
+ pairs_sep == '\\' || key_val_sep == '\\') {
+ av_log(obj, AV_LOG_ERROR, "Invalid separator(s) found.");
+ return AVERROR(EINVAL);
+ }
+
+ if (!obj || !buffer)
+ return AVERROR(EINVAL);
+
+ *buffer = NULL;
+ av_bprint_init(&bprint, 64, AV_BPRINT_SIZE_UNLIMITED);
+
+ while (o = av_opt_next(obj, o)) {
+ if (o->type == AV_OPT_TYPE_CONST)
+ continue;
+ if ((flags & AV_OPT_SERIALIZE_OPT_FLAGS_EXACT) && o->flags != opt_flags)
+ continue;
+ else if (((o->flags & opt_flags) != opt_flags))
+ continue;
+ if (flags & AV_OPT_SERIALIZE_SKIP_DEFAULTS && av_opt_is_set_to_default(obj, o) > 0)
+ continue;
+ if ((ret = av_opt_get(obj, o->name, 0, &buf)) < 0) {
+ av_bprint_finalize(&bprint, NULL);
+ return ret;
+ }
+ if (buf) {
+ if (cnt++)
+ av_bprint_append_data(&bprint, &pairs_sep, 1);
+ av_bprint_escape(&bprint, o->name, special_chars, AV_ESCAPE_MODE_BACKSLASH, 0);
+ av_bprint_append_data(&bprint, &key_val_sep, 1);
+ av_bprint_escape(&bprint, buf, special_chars, AV_ESCAPE_MODE_BACKSLASH, 0);
+ av_freep(&buf);
+ }
+ }
+ av_bprint_finalize(&bprint, buffer);
+ return 0;
+}
diff --git a/media/ffvpx/libavutil/opt.h b/media/ffvpx/libavutil/opt.h
index 9430b989e..0d893795d 100644
--- a/media/ffvpx/libavutil/opt.h
+++ b/media/ffvpx/libavutil/opt.h
@@ -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'),
diff --git a/media/ffvpx/libavutil/parseutils.c b/media/ffvpx/libavutil/parseutils.c
index a2464cfc6..be4ea1ee1 100644
--- a/media/ffvpx/libavutil/parseutils.c
+++ b/media/ffvpx/libavutil/parseutils.c
@@ -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;
diff --git a/media/ffvpx/libavutil/pixdesc.c b/media/ffvpx/libavutil/pixdesc.c
index b715fce15..2cfab89c0 100644
--- a/media/ffvpx/libavutil/pixdesc.c
+++ b/media/ffvpx/libavutil/pixdesc.c
@@ -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;
+ if (!desc1) {
+ dst_pix_fmt = dst_pix_fmt2;
+ } else if (!desc2) {
+ dst_pix_fmt = dst_pix_fmt1;
+ } else {
+ 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);
+ 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;
+ 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 = desc2->nb_components < desc1->nb_components ? dst_pix_fmt2 : dst_pix_fmt1;
+ dst_pix_fmt = score1 < score2 ? 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);
+}
diff --git a/media/ffvpx/libavutil/pixdesc.h b/media/ffvpx/libavutil/pixdesc.h
index a8ad58891..fc3737c4a 100644
--- a/media/ffvpx/libavutil/pixdesc.h
+++ b/media/ffvpx/libavutil/pixdesc.h
@@ -173,6 +173,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
* of bits per sample.
@@ -240,26 +251,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.
*
* If there is no pixel format with name name, then looks for a
diff --git a/media/ffvpx/libavutil/pixfmt.h b/media/ffvpx/libavutil/pixfmt.h
index 7a3f68be7..24889c8e5 100644
--- a/media/ffvpx/libavutil/pixfmt.h
+++ b/media/ffvpx/libavutil/pixfmt.h
@@ -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.
diff --git a/media/ffvpx/libavutil/reverse.h b/media/ffvpx/libavutil/reverse.h
new file mode 100644
index 000000000..4eb612393
--- /dev/null
+++ b/media/ffvpx/libavutil/reverse.h
@@ -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 */
diff --git a/media/ffvpx/libavutil/slicethread.c b/media/ffvpx/libavutil/slicethread.c
new file mode 100644
index 000000000..c43f87a2a
--- /dev/null
+++ b/media/ffvpx/libavutil/slicethread.c
@@ -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 */
diff --git a/media/ffvpx/libavutil/slicethread.h b/media/ffvpx/libavutil/slicethread.h
new file mode 100644
index 000000000..f6f6f302c
--- /dev/null
+++ b/media/ffvpx/libavutil/slicethread.h
@@ -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
diff --git a/media/ffvpx/libavutil/thread.h b/media/ffvpx/libavutil/thread.h
index 32ddf4036..f108e2005 100644
--- a/media/ffvpx/libavutil/thread.h
+++ b/media/ffvpx/libavutil/thread.h
@@ -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)
diff --git a/media/ffvpx/libavutil/threadmessage.c b/media/ffvpx/libavutil/threadmessage.c
index 7c5cd2463..872e9392b 100644
--- a/media/ffvpx/libavutil/threadmessage.c
+++ b/media/ffvpx/libavutil/threadmessage.c
@@ -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;
diff --git a/media/ffvpx/libavutil/time.c b/media/ffvpx/libavutil/time.c
index 69419e6f3..80d1faf26 100644
--- a/media/ffvpx/libavutil/time.c
+++ b/media/ffvpx/libavutil/time.c
@@ -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;
diff --git a/media/ffvpx/libavutil/timecode.c b/media/ffvpx/libavutil/timecode.c
index fa92df1ef..c0c67c847 100644
--- a/media/ffvpx/libavutil/timecode.c
+++ b/media/ffvpx/libavutil/timecode.c
@@ -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
diff --git a/media/ffvpx/libavutil/timecode.h b/media/ffvpx/libavutil/timecode.h
index 56e3975fd..37c1361bc 100644
--- a/media/ffvpx/libavutil/timecode.h
+++ b/media/ffvpx/libavutil/timecode.h
@@ -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
diff --git a/media/ffvpx/libavutil/timer.h b/media/ffvpx/libavutil/timer.h
index ed3b04787..f7ab455df 100644
--- a/media/ffvpx/libavutil/timer.h
+++ b/media/ffvpx/libavutil/timer.h
@@ -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) { }
diff --git a/media/ffvpx/libavutil/utils.c b/media/ffvpx/libavutil/utils.c
index 36e4dd5fd..2c170db2e 100644
--- a/media/ffvpx/libavutil/utils.c
+++ b/media/ffvpx/libavutil/utils.c
@@ -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)
:
diff --git a/media/ffvpx/libavutil/version.h b/media/ffvpx/libavutil/version.h
index bdd310f85..f594dc069 100644
--- a/media/ffvpx/libavutil/version.h
+++ b/media/ffvpx/libavutil/version.h
@@ -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
/**
diff --git a/media/ffvpx/libavutil/x86/cpu.c b/media/ffvpx/libavutil/x86/cpu.c
index f3a49c677..f33088c8c 100644
--- a/media/ffvpx/libavutil/x86/cpu.c
+++ b/media/ffvpx/libavutil/x86/cpu.c
@@ -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;
+}
diff --git a/media/ffvpx/libavutil/x86/cpu.h b/media/ffvpx/libavutil/x86/cpu.h
index f171037f1..309b8e746 100644
--- a/media/ffvpx/libavutil/x86/cpu.h
+++ b/media/ffvpx/libavutil/x86/cpu.h
@@ -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)
diff --git a/media/ffvpx/libavutil/x86/emms.asm b/media/ffvpx/libavutil/x86/emms.asm
index 0aad34af3..8611762d7 100644
--- a/media/ffvpx/libavutil/x86/emms.asm
+++ b/media/ffvpx/libavutil/x86/emms.asm
@@ -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
diff --git a/media/ffvpx/libavutil/x86/emms.h b/media/ffvpx/libavutil/x86/emms.h
index 42c18e295..c21e34b45 100644
--- a/media/ffvpx/libavutil/x86/emms.h
+++ b/media/ffvpx/libavutil/x86/emms.h
@@ -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 */
diff --git a/media/ffvpx/libavutil/x86/float_dsp.asm b/media/ffvpx/libavutil/x86/float_dsp.asm
index 021ff03c8..06d2d2cfd 100644
--- a/media/ffvpx/libavutil/x86/float_dsp.asm
+++ b/media/ffvpx/libavutil/x86/float_dsp.asm
@@ -22,6 +22,9 @@
%include "x86util.asm"
+SECTION_RODATA 32
+pd_reverse: dd 7, 6, 5, 4, 3, 2, 1, 0
+
SECTION .text
;-----------------------------------------------------------------------------
@@ -149,6 +152,69 @@ 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
diff --git a/media/ffvpx/libavutil/x86/float_dsp_init.c b/media/ffvpx/libavutil/x86/float_dsp_init.c
index c836a78e1..122087a19 100644
--- a/media/ffvpx/libavutil/x86/float_dsp_init.c
+++ b/media/ffvpx/libavutil/x86/float_dsp_init.c
@@ -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;
}
}
diff --git a/media/ffvpx/libavutil/x86/imgutils.asm b/media/ffvpx/libavutil/x86/imgutils.asm
new file mode 100644
index 000000000..3cca56cdc
--- /dev/null
+++ b/media/ffvpx/libavutil/x86/imgutils.asm
@@ -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
diff --git a/media/ffvpx/libavutil/x86/imgutils_init.c b/media/ffvpx/libavutil/x86/imgutils_init.c
new file mode 100644
index 000000000..4ea398205
--- /dev/null
+++ b/media/ffvpx/libavutil/x86/imgutils_init.c
@@ -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;
+}
diff --git a/media/ffvpx/libavutil/x86/moz.build b/media/ffvpx/libavutil/x86/moz.build
index 1d1a6ca67..b56ed75ea 100644
--- a/media/ffvpx/libavutil/x86/moz.build
+++ b/media/ffvpx/libavutil/x86/moz.build
@@ -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'
]
diff --git a/media/ffvpx/libavutil/x86/x86inc.asm b/media/ffvpx/libavutil/x86/x86inc.asm
index b2e9c6019..6a054a3e0 100644
--- a/media/ffvpx/libavutil/x86/x86inc.asm
+++ b/media/ffvpx/libavutil/x86/x86inc.asm
@@ -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_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_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<<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
diff --git a/media/ffvpx/libavutil/x86/x86util.asm b/media/ffvpx/libavutil/x86/x86util.asm
index 44ed750ae..e1220dfc1 100644
--- a/media/ffvpx/libavutil/x86/x86util.asm
+++ b/media/ffvpx/libavutil/x86/x86util.asm
@@ -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