summaryrefslogtreecommitdiffstats
path: root/media/ffvpx/libavcodec/utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'media/ffvpx/libavcodec/utils.c')
-rw-r--r--media/ffvpx/libavcodec/utils.c358
1 files changed, 317 insertions, 41 deletions
diff --git a/media/ffvpx/libavcodec/utils.c b/media/ffvpx/libavcodec/utils.c
index 59d41ccbb..0c47e761f 100644
--- a/media/ffvpx/libavcodec/utils.c
+++ b/media/ffvpx/libavcodec/utils.c
@@ -26,6 +26,7 @@
*/
#include "config.h"
+#include "libavutil/atomic.h"
#include "libavutil/attributes.h"
#include "libavutil/avassert.h"
#include "libavutil/avstring.h"
@@ -44,8 +45,8 @@
#include "libavutil/thread.h"
#include "avcodec.h"
#include "decode.h"
-#include "hwaccel.h"
#include "libavutil/opt.h"
+#include "me_cmp.h"
#include "mpegvideo.h"
#include "thread.h"
#include "frame_thread_encoder.h"
@@ -55,7 +56,6 @@
#include "version.h"
#include <stdlib.h>
#include <stdarg.h>
-#include <stdatomic.h>
#include <limits.h>
#include <float.h>
#if CONFIG_ICONV
@@ -65,7 +65,58 @@
#include "libavutil/ffversion.h"
const char av_codec_ffversion[] = "FFmpeg version " FFMPEG_VERSION;
-static AVMutex codec_mutex = AV_MUTEX_INITIALIZER;
+#if HAVE_PTHREADS || HAVE_W32THREADS || HAVE_OS2THREADS
+static int default_lockmgr_cb(void **arg, enum AVLockOp op)
+{
+ void * volatile * mutex = arg;
+ int err;
+
+ switch (op) {
+ case AV_LOCK_CREATE:
+ return 0;
+ case AV_LOCK_OBTAIN:
+ if (!*mutex) {
+ pthread_mutex_t *tmp = av_malloc(sizeof(pthread_mutex_t));
+ if (!tmp)
+ return AVERROR(ENOMEM);
+ if ((err = pthread_mutex_init(tmp, NULL))) {
+ av_free(tmp);
+ return AVERROR(err);
+ }
+ if (avpriv_atomic_ptr_cas(mutex, NULL, tmp)) {
+ pthread_mutex_destroy(tmp);
+ av_free(tmp);
+ }
+ }
+
+ if ((err = pthread_mutex_lock(*mutex)))
+ return AVERROR(err);
+
+ return 0;
+ case AV_LOCK_RELEASE:
+ if ((err = pthread_mutex_unlock(*mutex)))
+ return AVERROR(err);
+
+ return 0;
+ case AV_LOCK_DESTROY:
+ if (*mutex)
+ pthread_mutex_destroy(*mutex);
+ av_free(*mutex);
+ avpriv_atomic_ptr_cas(mutex, *mutex, NULL);
+ return 0;
+ }
+ return 1;
+}
+static int (*lockmgr_cb)(void **mutex, enum AVLockOp op) = default_lockmgr_cb;
+#else
+static int (*lockmgr_cb)(void **mutex, enum AVLockOp op) = NULL;
+#endif
+
+
+volatile int ff_avcodec_locked;
+static int volatile entangled_thread_counter = 0;
+static void *codec_mutex;
+static void *avformat_mutex;
void av_fast_padded_malloc(void *ptr, unsigned int *size, size_t min_size)
{
@@ -91,6 +142,30 @@ void av_fast_padded_mallocz(void *ptr, unsigned int *size, size_t min_size)
memset(*p, 0, min_size + AV_INPUT_BUFFER_PADDING_SIZE);
}
+/* encoder management */
+static AVCodec *first_avcodec = NULL;
+static AVCodec **last_avcodec = &first_avcodec;
+
+AVCodec *av_codec_next(const AVCodec *c)
+{
+ if (c)
+ return c->next;
+ else
+ return first_avcodec;
+}
+
+static av_cold void avcodec_init(void)
+{
+ static int initialized = 0;
+
+ if (initialized != 0)
+ return;
+ initialized = 1;
+
+ if (CONFIG_ME_CMP)
+ ff_me_cmp_init_static();
+}
+
int av_codec_is_encoder(const AVCodec *codec)
{
return codec && (codec->encode_sub || codec->encode2 ||codec->send_frame);
@@ -101,6 +176,38 @@ int av_codec_is_decoder(const AVCodec *codec)
return codec && (codec->decode || codec->receive_frame);
}
+av_cold void avcodec_register(AVCodec *codec)
+{
+ AVCodec **p;
+ avcodec_init();
+ p = last_avcodec;
+ codec->next = NULL;
+
+ while(*p || avpriv_atomic_ptr_cas((void * volatile *)p, NULL, codec))
+ p = &(*p)->next;
+ last_avcodec = &codec->next;
+
+ if (codec->init_static_data)
+ codec->init_static_data(codec);
+}
+
+#if FF_API_EMU_EDGE
+unsigned avcodec_get_edge_width(void)
+{
+ return EDGE_WIDTH;
+}
+#endif
+
+#if FF_API_SET_DIMENSIONS
+void avcodec_set_dimensions(AVCodecContext *s, int width, int height)
+{
+ int ret = ff_set_dimensions(s, width, height);
+ if (ret < 0) {
+ av_log(s, AV_LOG_WARNING, "Failed to set dimensions %d %d\n", width, height);
+ }
+}
+#endif
+
int ff_set_dimensions(AVCodecContext *s, int width, int height)
{
int ret = av_image_check_size2(width, height, s->max_pixels, AV_PIX_FMT_NONE, 0, s);
@@ -312,10 +419,7 @@ void avcodec_align_dimensions2(AVCodecContext *s, int *width, int *height,
*width = FFALIGN(*width, w_align);
*height = FFALIGN(*height, h_align);
- if (s->codec_id == AV_CODEC_ID_H264 || s->lowres ||
- s->codec_id == AV_CODEC_ID_VP5 || s->codec_id == AV_CODEC_ID_VP6 ||
- s->codec_id == AV_CODEC_ID_VP6F || s->codec_id == AV_CODEC_ID_VP6A
- ) {
+ if (s->codec_id == AV_CODEC_ID_H264 || s->lowres) {
// some of the optimized chroma MC reads one line too much
// which is also done in mpeg decoders with lowres > 0
*height += 2;
@@ -465,7 +569,6 @@ enum AVPixelFormat avpriv_find_pix_fmt(const PixelFormatTag *tags,
return AV_PIX_FMT_NONE;
}
-#if FF_API_CODEC_GET_SET
MAKE_ACCESSORS(AVCodecContext, codec, AVRational, pkt_timebase)
MAKE_ACCESSORS(AVCodecContext, codec, const AVCodecDescriptor *, codec_descriptor)
MAKE_ACCESSORS(AVCodecContext, codec, int, lowres)
@@ -481,7 +584,6 @@ int av_codec_get_max_lowres(const AVCodec *codec)
{
return codec->max_lowres;
}
-#endif
int avpriv_codec_get_cap_skip_frame_fill_param(const AVCodec *codec){
return !!(codec->caps_internal & FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM);
@@ -510,19 +612,6 @@ static int64_t get_bit_rate(AVCodecContext *ctx)
return bit_rate;
}
-
-static void ff_lock_avcodec(AVCodecContext *log_ctx, const AVCodec *codec)
-{
- if (!(codec->caps_internal & FF_CODEC_CAP_INIT_THREADSAFE) && codec->init)
- ff_mutex_lock(&codec_mutex);
-}
-
-static void ff_unlock_avcodec(const AVCodec *codec)
-{
- if (!(codec->caps_internal & FF_CODEC_CAP_INIT_THREADSAFE) && codec->init)
- ff_mutex_unlock(&codec_mutex);
-}
-
int attribute_align_arg ff_codec_open2_recursive(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options)
{
int ret = 0;
@@ -562,7 +651,9 @@ int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *code
if (options)
av_dict_copy(&tmp, *options, 0);
- ff_lock_avcodec(avctx, codec);
+ ret = ff_lock_avcodec(avctx, codec);
+ if (ret < 0)
+ return ret;
avctx->internal = av_mallocz(sizeof(*avctx->internal));
if (!avctx->internal) {
@@ -742,6 +833,12 @@ int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *code
avctx->lowres = avctx->codec->max_lowres;
}
+#if FF_API_VISMV
+ if (avctx->debug_mv)
+ av_log(avctx, AV_LOG_WARNING, "The 'vismv' option is deprecated, "
+ "see the codecview filter instead.\n");
+#endif
+
if (av_codec_is_encoder(avctx->codec)) {
int i;
#if FF_API_CODED_FRAME
@@ -928,6 +1025,11 @@ FF_ENABLE_DEPRECATION_WARNINGS
ret=0;
+#if FF_API_AUDIOENC_DELAY
+ if (av_codec_is_encoder(avctx->codec))
+ avctx->delay = avctx->initial_padding;
+#endif
+
if (av_codec_is_decoder(avctx->codec)) {
if (!avctx->bit_rate)
avctx->bit_rate = get_bit_rate(avctx);
@@ -1124,6 +1226,71 @@ FF_ENABLE_DEPRECATION_WARNINGS
return 0;
}
+static enum AVCodecID remap_deprecated_codec_id(enum AVCodecID id)
+{
+ switch(id){
+ //This is for future deprecatec codec ids, its empty since
+ //last major bump but will fill up again over time, please don't remove it
+ default : return id;
+ }
+}
+
+static AVCodec *find_encdec(enum AVCodecID id, int encoder)
+{
+ AVCodec *p, *experimental = NULL;
+ p = first_avcodec;
+ id= remap_deprecated_codec_id(id);
+ while (p) {
+ if ((encoder ? av_codec_is_encoder(p) : av_codec_is_decoder(p)) &&
+ p->id == id) {
+ if (p->capabilities & AV_CODEC_CAP_EXPERIMENTAL && !experimental) {
+ experimental = p;
+ } else
+ return p;
+ }
+ p = p->next;
+ }
+ return experimental;
+}
+
+AVCodec *avcodec_find_encoder(enum AVCodecID id)
+{
+ return find_encdec(id, 1);
+}
+
+AVCodec *avcodec_find_encoder_by_name(const char *name)
+{
+ AVCodec *p;
+ if (!name)
+ return NULL;
+ p = first_avcodec;
+ while (p) {
+ if (av_codec_is_encoder(p) && strcmp(name, p->name) == 0)
+ return p;
+ p = p->next;
+ }
+ return NULL;
+}
+
+AVCodec *avcodec_find_decoder(enum AVCodecID id)
+{
+ return find_encdec(id, 0);
+}
+
+AVCodec *avcodec_find_decoder_by_name(const char *name)
+{
+ AVCodec *p;
+ if (!name)
+ return NULL;
+ p = first_avcodec;
+ while (p) {
+ if (av_codec_is_decoder(p) && strcmp(name, p->name) == 0)
+ return p;
+ p = p->next;
+ }
+ return NULL;
+}
+
const char *avcodec_get_name(enum AVCodecID id)
{
const AVCodecDescriptor *cd;
@@ -1669,13 +1836,13 @@ static int get_audio_frame_duration(enum AVCodecID id, int sr, int ch, int ba,
/* calc from frame_bytes, channels, and bits_per_coded_sample */
switch (id) {
case AV_CODEC_ID_PCM_DVD:
- if(bps<4 || frame_bytes<3)
+ if(bps<4)
return 0;
- return 2 * ((frame_bytes - 3) / ((bps * 2 / 8) * ch));
+ return 2 * (frame_bytes / ((bps * 2 / 8) * ch));
case AV_CODEC_ID_PCM_BLURAY:
- if(bps<4 || frame_bytes<4)
+ if(bps<4)
return 0;
- return (frame_bytes - 4) / ((FFALIGN(ch, 2) * bps) / 8);
+ return frame_bytes / ((FFALIGN(ch, 2) * bps) / 8);
case AV_CODEC_ID_S302M:
return 2 * (frame_bytes / ((bps + 4) / 4)) / ch;
}
@@ -1744,34 +1911,143 @@ int ff_match_2uint16(const uint16_t(*tab)[2], int size, int a, int b)
return i;
}
-const AVCodecHWConfig *avcodec_get_hw_config(const AVCodec *codec, int index)
+#if FF_API_MISSING_SAMPLE
+FF_DISABLE_DEPRECATION_WARNINGS
+void av_log_missing_feature(void *avc, const char *feature, int want_sample)
{
- int i;
- if (!codec->hw_configs || index < 0)
- return NULL;
- for (i = 0; i <= index; i++)
- if (!codec->hw_configs[i])
- return NULL;
- return &codec->hw_configs[index]->public;
+ av_log(avc, AV_LOG_WARNING, "%s is not implemented. Update your FFmpeg "
+ "version to the newest one from Git. If the problem still "
+ "occurs, it means that your file has a feature which has not "
+ "been implemented.\n", feature);
+ if(want_sample)
+ av_log_ask_for_sample(avc, NULL);
}
-#if FF_API_USER_VISIBLE_AVHWACCEL
-AVHWAccel *av_hwaccel_next(const AVHWAccel *hwaccel)
+void av_log_ask_for_sample(void *avc, const char *msg, ...)
{
- return NULL;
+ va_list argument_list;
+
+ va_start(argument_list, msg);
+
+ if (msg)
+ av_vlog(avc, AV_LOG_WARNING, msg, argument_list);
+ av_log(avc, AV_LOG_WARNING, "If you want to help, upload a sample "
+ "of this file to ftp://upload.ffmpeg.org/incoming/ "
+ "and contact the ffmpeg-devel mailing list. (ffmpeg-devel@ffmpeg.org)\n");
+
+ va_end(argument_list);
}
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif /* FF_API_MISSING_SAMPLE */
+
+static AVHWAccel *first_hwaccel = NULL;
+static AVHWAccel **last_hwaccel = &first_hwaccel;
void av_register_hwaccel(AVHWAccel *hwaccel)
{
+ AVHWAccel **p = last_hwaccel;
+ hwaccel->next = NULL;
+ while(*p || avpriv_atomic_ptr_cas((void * volatile *)p, NULL, hwaccel))
+ p = &(*p)->next;
+ last_hwaccel = &hwaccel->next;
+}
+
+AVHWAccel *av_hwaccel_next(const AVHWAccel *hwaccel)
+{
+ return hwaccel ? hwaccel->next : first_hwaccel;
}
-#endif
-#if FF_API_LOCKMGR
int av_lockmgr_register(int (*cb)(void **mutex, enum AVLockOp op))
{
+ if (lockmgr_cb) {
+ // There is no good way to rollback a failure to destroy the
+ // mutex, so we ignore failures.
+ lockmgr_cb(&codec_mutex, AV_LOCK_DESTROY);
+ lockmgr_cb(&avformat_mutex, AV_LOCK_DESTROY);
+ lockmgr_cb = NULL;
+ codec_mutex = NULL;
+ avformat_mutex = NULL;
+ }
+
+ if (cb) {
+ void *new_codec_mutex = NULL;
+ void *new_avformat_mutex = NULL;
+ int err;
+ if (err = cb(&new_codec_mutex, AV_LOCK_CREATE)) {
+ return err > 0 ? AVERROR_UNKNOWN : err;
+ }
+ if (err = cb(&new_avformat_mutex, AV_LOCK_CREATE)) {
+ // Ignore failures to destroy the newly created mutex.
+ cb(&new_codec_mutex, AV_LOCK_DESTROY);
+ return err > 0 ? AVERROR_UNKNOWN : err;
+ }
+ lockmgr_cb = cb;
+ codec_mutex = new_codec_mutex;
+ avformat_mutex = new_avformat_mutex;
+ }
+
+ return 0;
+}
+
+int ff_lock_avcodec(AVCodecContext *log_ctx, const AVCodec *codec)
+{
+ if (codec->caps_internal & FF_CODEC_CAP_INIT_THREADSAFE || !codec->init)
+ return 0;
+
+ if (lockmgr_cb) {
+ if ((*lockmgr_cb)(&codec_mutex, AV_LOCK_OBTAIN))
+ return -1;
+ }
+
+ if (avpriv_atomic_int_add_and_fetch(&entangled_thread_counter, 1) != 1) {
+ av_log(log_ctx, AV_LOG_ERROR,
+ "Insufficient thread locking. At least %d threads are "
+ "calling avcodec_open2() at the same time right now.\n",
+ entangled_thread_counter);
+ if (!lockmgr_cb)
+ av_log(log_ctx, AV_LOG_ERROR, "No lock manager is set, please see av_lockmgr_register()\n");
+ ff_avcodec_locked = 1;
+ ff_unlock_avcodec(codec);
+ return AVERROR(EINVAL);
+ }
+ av_assert0(!ff_avcodec_locked);
+ ff_avcodec_locked = 1;
+ return 0;
+}
+
+int ff_unlock_avcodec(const AVCodec *codec)
+{
+ if (codec->caps_internal & FF_CODEC_CAP_INIT_THREADSAFE || !codec->init)
+ return 0;
+
+ av_assert0(ff_avcodec_locked);
+ ff_avcodec_locked = 0;
+ avpriv_atomic_int_add_and_fetch(&entangled_thread_counter, -1);
+ if (lockmgr_cb) {
+ if ((*lockmgr_cb)(&codec_mutex, AV_LOCK_RELEASE))
+ return -1;
+ }
+
+ return 0;
+}
+
+int avpriv_lock_avformat(void)
+{
+ if (lockmgr_cb) {
+ if ((*lockmgr_cb)(&avformat_mutex, AV_LOCK_OBTAIN))
+ return -1;
+ }
+ return 0;
+}
+
+int avpriv_unlock_avformat(void)
+{
+ if (lockmgr_cb) {
+ if ((*lockmgr_cb)(&avformat_mutex, AV_LOCK_RELEASE))
+ return -1;
+ }
return 0;
}
-#endif
unsigned int avpriv_toupper4(unsigned int x)
{