*/
#include "config.h"
+#include "libavutil/attributes.h"
#include "libavutil/avassert.h"
#include "libavutil/avstring.h"
#include "libavutil/channel_layout.h"
#include "libavutil/crc.h"
#include "libavutil/frame.h"
+#include "libavutil/internal.h"
#include "libavutil/mathematics.h"
#include "libavutil/pixdesc.h"
#include "libavutil/imgutils.h"
#include "libavutil/samplefmt.h"
#include "libavutil/dict.h"
#include "avcodec.h"
-#include "dsputil.h"
#include "libavutil/opt.h"
+#include "me_cmp.h"
+#include "mpegvideo.h"
#include "thread.h"
#include "internal.h"
#include "bytestream.h"
+#include "version.h"
#include <stdlib.h>
#include <stdarg.h>
#include <limits.h>
#include <float.h>
static int volatile entangled_thread_counter = 0;
-static int (*ff_lockmgr_cb)(void **mutex, enum AVLockOp op);
+static int (*lockmgr_cb)(void **mutex, enum AVLockOp op);
static void *codec_mutex;
static void *avformat_mutex;
-void *av_fast_realloc(void *ptr, unsigned int *size, size_t min_size)
-{
- if (min_size < *size)
- return ptr;
-
- min_size = FFMAX(17 * min_size / 16 + 32, min_size);
-
- ptr = av_realloc(ptr, min_size);
- /* we could set this to the unmodified min_size but this is safer
- * if the user lost the ptr and uses NULL now
- */
- if (!ptr)
- min_size = 0;
-
- *size = min_size;
-
- return ptr;
-}
-
-void av_fast_malloc(void *ptr, unsigned int *size, size_t min_size)
-{
- void **p = ptr;
- if (min_size < *size)
- return;
- min_size = FFMAX(17 * min_size / 16 + 32, min_size);
- av_free(*p);
- *p = av_malloc(min_size);
- if (!*p)
- min_size = 0;
- *size = min_size;
-}
-
void av_fast_padded_malloc(void *ptr, unsigned int *size, size_t min_size)
{
void **p = ptr;
return first_avcodec;
}
-static void avcodec_init(void)
+static av_cold void avcodec_init(void)
{
static int initialized = 0;
return;
initialized = 1;
- ff_dsputil_static_init();
+ if (CONFIG_ME_CMP)
+ ff_me_cmp_init_static();
}
int av_codec_is_encoder(const AVCodec *codec)
return codec && codec->decode;
}
-void avcodec_register(AVCodec *codec)
+av_cold void avcodec_register(AVCodec *codec)
{
AVCodec **p;
avcodec_init();
p = &first_avcodec;
- while (*p != NULL)
+ while (*p)
p = &(*p)->next;
*p = codec;
codec->next = NULL;
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)
{
- s->coded_width = width;
- s->coded_height = height;
- s->width = width;
- s->height = height;
+ ff_set_dimensions(s, width, height);
+}
+#endif
+
+int ff_set_dimensions(AVCodecContext *s, int width, int height)
+{
+ int ret = av_image_check_size(width, height, 0, s);
+
+ if (ret < 0)
+ width = height = 0;
+ s->width = s->coded_width = width;
+ s->height = s->coded_height = height;
+
+ return ret;
}
-#if (ARCH_ARM && HAVE_NEON) || ARCH_PPC || HAVE_MMX
+int ff_set_sar(AVCodecContext *avctx, AVRational sar)
+{
+ int ret = av_image_check_sar(avctx->width, avctx->height, sar);
+
+ if (ret < 0) {
+ av_log(avctx, AV_LOG_WARNING, "ignoring invalid SAR: %d/%d\n",
+ sar.num, sar.den);
+ avctx->sample_aspect_ratio = (AVRational){ 0, 1 };
+ return ret;
+ } else {
+ avctx->sample_aspect_ratio = sar;
+ }
+ return 0;
+}
+
+int ff_side_data_update_matrix_encoding(AVFrame *frame,
+ enum AVMatrixEncoding matrix_encoding)
+{
+ AVFrameSideData *side_data;
+ enum AVMatrixEncoding *data;
+
+ side_data = av_frame_get_side_data(frame, AV_FRAME_DATA_MATRIXENCODING);
+ if (!side_data)
+ side_data = av_frame_new_side_data(frame, AV_FRAME_DATA_MATRIXENCODING,
+ sizeof(enum AVMatrixEncoding));
+
+ if (!side_data)
+ return AVERROR(ENOMEM);
+
+ data = (enum AVMatrixEncoding*)side_data->data;
+ *data = matrix_encoding;
+
+ return 0;
+}
+
+#if HAVE_SIMD_ALIGN_16
# define STRIDE_ALIGN 16
#else
# define STRIDE_ALIGN 8
switch (s->pix_fmt) {
case AV_PIX_FMT_YUV420P:
case AV_PIX_FMT_YUYV422:
+ case AV_PIX_FMT_YVYU422:
case AV_PIX_FMT_UYVY422:
case AV_PIX_FMT_YUV422P:
case AV_PIX_FMT_YUV440P:
case AV_PIX_FMT_YUV444P:
case AV_PIX_FMT_GBRP:
+ case AV_PIX_FMT_GBRAP:
case AV_PIX_FMT_GRAY8:
case AV_PIX_FMT_GRAY16BE:
case AV_PIX_FMT_GRAY16LE:
case AV_PIX_FMT_YUV422P9BE:
case AV_PIX_FMT_YUV422P10LE:
case AV_PIX_FMT_YUV422P10BE:
+ case AV_PIX_FMT_YUVA422P10LE:
+ case AV_PIX_FMT_YUVA422P10BE:
case AV_PIX_FMT_YUV444P9LE:
case AV_PIX_FMT_YUV444P9BE:
case AV_PIX_FMT_YUV444P10LE:
case AV_PIX_FMT_YUV444P10BE:
+ case AV_PIX_FMT_YUVA444P10LE:
+ case AV_PIX_FMT_YUVA444P10BE:
case AV_PIX_FMT_GBRP9LE:
case AV_PIX_FMT_GBRP9BE:
case AV_PIX_FMT_GBRP10LE:
avcodec_align_dimensions2(avctx, &w, &h, pool->stride_align);
- if (!(avctx->flags & CODEC_FLAG_EMU_EDGE)) {
- w += EDGE_WIDTH * 2;
- h += EDGE_WIDTH * 2;
- }
-
do {
// NOTE: do not align linesizes individually, this breaks e.g. assumptions
// that linesize[0] == 2*linesize[1] in the MPEG-encoder for 4:2:2
static int video_get_buffer(AVCodecContext *s, AVFrame *pic)
{
FramePool *pool = s->internal->pool;
- const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pic->format);
- int pixel_size = desc->comp[0].step_minus1 + 1;
- int h_chroma_shift, v_chroma_shift;
int i;
- if (pic->data[0] != NULL) {
+ if (pic->data[0]) {
av_log(s, AV_LOG_ERROR, "pic->data[0]!=NULL in avcodec_default_get_buffer\n");
return -1;
}
memset(pic->data, 0, sizeof(pic->data));
pic->extended_data = pic->data;
- av_pix_fmt_get_chroma_sub_sample(s->pix_fmt, &h_chroma_shift, &v_chroma_shift);
-
for (i = 0; i < 4 && pool->pools[i]; i++) {
- const int h_shift = i == 0 ? 0 : h_chroma_shift;
- const int v_shift = i == 0 ? 0 : v_chroma_shift;
-
pic->linesize[i] = pool->linesize[i];
pic->buf[i] = av_buffer_pool_get(pool->pools[i]);
if (!pic->buf[i])
goto fail;
- // no edge if EDGE EMU or not planar YUV
- if ((s->flags & CODEC_FLAG_EMU_EDGE) || !pool->pools[2])
- pic->data[i] = pic->buf[i]->data;
- else {
- pic->data[i] = pic->buf[i]->data +
- FFALIGN((pic->linesize[i] * EDGE_WIDTH >> v_shift) +
- (pixel_size * EDGE_WIDTH >> h_shift), pool->stride_align[i]);
- }
+ pic->data[i] = pic->buf[i]->data;
}
for (; i < AV_NUM_DATA_POINTERS; i++) {
pic->data[i] = NULL;
return ret;
#if FF_API_GET_BUFFER
+FF_DISABLE_DEPRECATION_WARNINGS
frame->type = FF_BUFFER_TYPE_INTERNAL;
+FF_ENABLE_DEPRECATION_WARNINGS
#endif
switch (avctx->codec_type) {
}
#if FF_API_GET_BUFFER
+FF_DISABLE_DEPRECATION_WARNINGS
int avcodec_default_get_buffer(AVCodecContext *avctx, AVFrame *frame)
{
return avcodec_default_get_buffer2(avctx, frame, 0);
static void compat_free_buffer(void *opaque, uint8_t *data)
{
CompatReleaseBufPriv *priv = opaque;
- priv->avctx.release_buffer(&priv->avctx, &priv->frame);
+ if (priv->avctx.release_buffer)
+ priv->avctx.release_buffer(&priv->avctx, &priv->frame);
av_freep(&priv);
}
AVBufferRef *buf = opaque;
av_buffer_unref(&buf);
}
+FF_ENABLE_DEPRECATION_WARNINGS
#endif
+int ff_decode_frame_props(AVCodecContext *avctx, AVFrame *frame)
+{
+ AVPacket *pkt = avctx->internal->pkt;
+ int i;
+ struct {
+ enum AVPacketSideDataType packet;
+ enum AVFrameSideDataType frame;
+ } sd[] = {
+ { AV_PKT_DATA_REPLAYGAIN , AV_FRAME_DATA_REPLAYGAIN },
+ { AV_PKT_DATA_DISPLAYMATRIX, AV_FRAME_DATA_DISPLAYMATRIX },
+ { AV_PKT_DATA_STEREO3D, AV_FRAME_DATA_STEREO3D },
+ { AV_PKT_DATA_AUDIO_SERVICE_TYPE, AV_FRAME_DATA_AUDIO_SERVICE_TYPE },
+ };
+
+ frame->color_primaries = avctx->color_primaries;
+ frame->color_trc = avctx->color_trc;
+ frame->colorspace = avctx->colorspace;
+ frame->color_range = avctx->color_range;
+ frame->chroma_location = avctx->chroma_sample_location;
+
+ frame->reordered_opaque = avctx->reordered_opaque;
+ if (!pkt) {
+ frame->pkt_pts = AV_NOPTS_VALUE;
+ return 0;
+ }
+
+ frame->pkt_pts = pkt->pts;
+
+ for (i = 0; i < FF_ARRAY_ELEMS(sd); i++) {
+ int size;
+ uint8_t *packet_sd = av_packet_get_side_data(pkt, sd[i].packet, &size);
+ if (packet_sd) {
+ AVFrameSideData *frame_sd = av_frame_new_side_data(frame,
+ sd[i].frame,
+ size);
+ if (!frame_sd)
+ return AVERROR(ENOMEM);
+
+ memcpy(frame_sd->data, packet_sd, size);
+ }
+ }
+
+ return 0;
+}
+
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
{
+ const AVHWAccel *hwaccel = avctx->hwaccel;
+ int override_dimensions = 1;
int ret;
switch (avctx->codec_type) {
case AVMEDIA_TYPE_VIDEO:
- if (!frame->width)
- frame->width = avctx->width;
- if (!frame->height)
- frame->height = avctx->height;
+ if (frame->width <= 0 || frame->height <= 0) {
+ frame->width = FFMAX(avctx->width, avctx->coded_width);
+ frame->height = FFMAX(avctx->height, avctx->coded_height);
+ override_dimensions = 0;
+ }
if (frame->format < 0)
frame->format = avctx->pix_fmt;
if (!frame->sample_aspect_ratio.num)
frame->sample_aspect_ratio = avctx->sample_aspect_ratio;
+ if (av_image_check_sar(frame->width, frame->height,
+ frame->sample_aspect_ratio) < 0) {
+ av_log(avctx, AV_LOG_WARNING, "ignoring invalid SAR: %u/%u\n",
+ frame->sample_aspect_ratio.num,
+ frame->sample_aspect_ratio.den);
+ frame->sample_aspect_ratio = (AVRational){ 0, 1 };
+ }
+
if ((ret = av_image_check_size(avctx->width, avctx->height, 0, avctx)) < 0)
return ret;
break;
default: return AVERROR(EINVAL);
}
- frame->pkt_pts = avctx->pkt ? avctx->pkt->pts : AV_NOPTS_VALUE;
- frame->reordered_opaque = avctx->reordered_opaque;
+ ret = ff_decode_frame_props(avctx, frame);
+ if (ret < 0)
+ return ret;
+
+ if (hwaccel) {
+ if (hwaccel->alloc_frame) {
+ ret = hwaccel->alloc_frame(avctx, frame);
+ goto end;
+ }
+ } else
+ avctx->sw_pix_fmt = avctx->pix_fmt;
#if FF_API_GET_BUFFER
+FF_DISABLE_DEPRECATION_WARNINGS
/*
* Wrap an old get_buffer()-allocated buffer in an bunch of AVBuffers.
* We wrap each plane in its own AVBuffer. Each of those has a reference to
ref_out = av_buffer_create(data, data_size, compat_release_buffer, \
dummy_ref, 0); \
if (!ref_out) { \
+ av_buffer_unref(&dummy_ref); \
av_frame_unref(frame); \
ret = AVERROR(ENOMEM); \
goto fail; \
if (avctx->codec_type == AVMEDIA_TYPE_VIDEO) {
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format);
- if (!desc) {
+ planes = av_pix_fmt_count_planes(frame->format);
+ /* workaround for AVHWAccel plane count of 0, buf[0] is used as
+ check for allocated buffers: make libavcodec happy */
+ if (desc && desc->flags & AV_PIX_FMT_FLAG_HWACCEL)
+ planes = 1;
+ if (!desc || planes <= 0) {
ret = AVERROR(EINVAL);
goto fail;
}
- planes = (desc->flags & PIX_FMT_PLANAR) ? desc->nb_components : 1;
for (i = 0; i < planes; i++) {
- int h_shift = (i == 1 || i == 2) ? desc->log2_chroma_h : 0;
- int plane_size = (frame->width >> h_shift) * frame->linesize[i];
+ int v_shift = (i == 1 || i == 2) ? desc->log2_chroma_h : 0;
+ int plane_size = (frame->height >> v_shift) * frame->linesize[i];
WRAP_PLANE(frame->buf[i], frame->data[i], plane_size);
}
av_buffer_unref(&dummy_buf);
+ frame->width = avctx->width;
+ frame->height = avctx->height;
+
return 0;
fail:
av_buffer_unref(&dummy_buf);
return ret;
}
+FF_ENABLE_DEPRECATION_WARNINGS
#endif
- return avctx->get_buffer2(avctx, frame, flags);
+ ret = avctx->get_buffer2(avctx, frame, flags);
+
+end:
+ if (avctx->codec_type == AVMEDIA_TYPE_VIDEO && !override_dimensions) {
+ frame->width = avctx->width;
+ frame->height = avctx->height;
+ }
+
+ return ret;
}
int ff_reget_buffer(AVCodecContext *avctx, AVFrame *frame)
{
- AVFrame tmp;
+ AVFrame *tmp;
int ret;
av_assert0(avctx->codec_type == AVMEDIA_TYPE_VIDEO);
return ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF);
if (av_frame_is_writable(frame))
- return 0;
+ return ff_decode_frame_props(avctx, frame);
+
+ tmp = av_frame_alloc();
+ if (!tmp)
+ return AVERROR(ENOMEM);
- av_frame_move_ref(&tmp, frame);
+ av_frame_move_ref(tmp, frame);
ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF);
if (ret < 0) {
- av_frame_unref(&tmp);
+ av_frame_free(&tmp);
return ret;
}
- av_image_copy(frame->data, frame->linesize, tmp.data, tmp.linesize,
- frame->format, frame->width, frame->height);
-
- av_frame_unref(&tmp);
+ av_frame_copy(frame, tmp);
+ av_frame_free(&tmp);
return 0;
}
int avcodec_default_reget_buffer(AVCodecContext *s, AVFrame *pic)
{
av_assert0(0);
+ return AVERROR_BUG;
}
#endif
static int is_hwaccel_pix_fmt(enum AVPixelFormat pix_fmt)
{
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
- return desc->flags & PIX_FMT_HWACCEL;
+ return desc->flags & AV_PIX_FMT_FLAG_HWACCEL;
}
enum AVPixelFormat avcodec_default_get_format(struct AVCodecContext *s, const enum AVPixelFormat *fmt)
return fmt[0];
}
+static AVHWAccel *find_hwaccel(enum AVCodecID codec_id,
+ enum AVPixelFormat pix_fmt)
+{
+ AVHWAccel *hwaccel = NULL;
+
+ while ((hwaccel = av_hwaccel_next(hwaccel)))
+ if (hwaccel->id == codec_id
+ && hwaccel->pix_fmt == pix_fmt)
+ return hwaccel;
+ return NULL;
+}
+
+static int setup_hwaccel(AVCodecContext *avctx,
+ const enum AVPixelFormat fmt,
+ const char *name)
+{
+ AVHWAccel *hwa = find_hwaccel(avctx->codec_id, fmt);
+ int ret = 0;
+
+ if (!hwa) {
+ av_log(avctx, AV_LOG_ERROR,
+ "Could not find an AVHWAccel for the pixel format: %s",
+ name);
+ return AVERROR(ENOENT);
+ }
+
+ if (hwa->priv_data_size) {
+ avctx->internal->hwaccel_priv_data = av_mallocz(hwa->priv_data_size);
+ if (!avctx->internal->hwaccel_priv_data)
+ return AVERROR(ENOMEM);
+ }
+
+ if (hwa->init) {
+ ret = hwa->init(avctx);
+ if (ret < 0) {
+ av_freep(&avctx->internal->hwaccel_priv_data);
+ return ret;
+ }
+ }
+
+ avctx->hwaccel = hwa;
+
+ return 0;
+}
+
+int ff_get_format(AVCodecContext *avctx, const enum AVPixelFormat *fmt)
+{
+ const AVPixFmtDescriptor *desc;
+ enum AVPixelFormat *choices;
+ enum AVPixelFormat ret;
+ unsigned n = 0;
+
+ while (fmt[n] != AV_PIX_FMT_NONE)
+ ++n;
+
+ av_assert0(n >= 1);
+ avctx->sw_pix_fmt = fmt[n - 1];
+ av_assert2(!is_hwaccel_pix_fmt(avctx->sw_pix_fmt));
+
+ choices = av_malloc_array(n + 1, sizeof(*choices));
+ if (!choices)
+ return AV_PIX_FMT_NONE;
+
+ memcpy(choices, fmt, (n + 1) * sizeof(*choices));
+
+ for (;;) {
+ if (avctx->hwaccel && avctx->hwaccel->uninit)
+ avctx->hwaccel->uninit(avctx);
+ av_freep(&avctx->internal->hwaccel_priv_data);
+ avctx->hwaccel = NULL;
+
+ ret = avctx->get_format(avctx, choices);
+
+ desc = av_pix_fmt_desc_get(ret);
+ if (!desc) {
+ ret = AV_PIX_FMT_NONE;
+ break;
+ }
+
+ if (!(desc->flags & AV_PIX_FMT_FLAG_HWACCEL))
+ break;
+
+ if (!setup_hwaccel(avctx, ret, desc->name))
+ break;
+
+ /* Remove failed hwaccel from choices */
+ for (n = 0; choices[n] != ret; n++)
+ av_assert0(choices[n] != AV_PIX_FMT_NONE);
+
+ do
+ choices[n] = choices[n + 1];
+ while (choices[n++] != AV_PIX_FMT_NONE);
+ }
+
+ av_freep(&choices);
+ return ret;
+}
+
+#if FF_API_AVFRAME_LAVC
void avcodec_get_frame_defaults(AVFrame *frame)
{
if (frame->extended_data != frame->data)
{
AVFrame *frame = av_mallocz(sizeof(AVFrame));
- if (frame == NULL)
+ if (!frame)
return NULL;
+FF_DISABLE_DEPRECATION_WARNINGS
avcodec_get_frame_defaults(frame);
+FF_ENABLE_DEPRECATION_WARNINGS
return frame;
}
void avcodec_free_frame(AVFrame **frame)
{
- AVFrame *f;
-
- if (!frame || !*frame)
- return;
-
- f = *frame;
-
- if (f->extended_data != f->data)
- av_freep(&f->extended_data);
-
- av_freep(frame);
+ av_frame_free(frame);
}
+#endif
int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options)
{
av_dict_copy(&tmp, *options, 0);
/* If there is a user-supplied mutex locking routine, call it. */
- if (ff_lockmgr_cb) {
- if ((*ff_lockmgr_cb)(&codec_mutex, AV_LOCK_OBTAIN))
+ if (lockmgr_cb) {
+ if ((*lockmgr_cb)(&codec_mutex, AV_LOCK_OBTAIN))
return -1;
}
entangled_thread_counter++;
- if (entangled_thread_counter != 1) {
- av_log(avctx, AV_LOG_ERROR, "insufficient thread locking around avcodec_open/close()\n");
+ if (entangled_thread_counter != 1 &&
+ !(codec->caps_internal & FF_CODEC_CAP_INIT_THREADSAFE)) {
+ av_log(avctx, AV_LOG_ERROR,
+ "Insufficient thread locking. At least %d threads are "
+ "calling avcodec_open2() at the same time right now.\n",
+ entangled_thread_counter);
ret = -1;
goto end;
}
goto free_and_end;
}
+ avctx->internal->to_free = av_frame_alloc();
+ if (!avctx->internal->to_free) {
+ ret = AVERROR(ENOMEM);
+ goto free_and_end;
+ }
+
if (codec->priv_data_size > 0) {
if (!avctx->priv_data) {
avctx->priv_data = av_mallocz(codec->priv_data_size);
if ((ret = av_opt_set_dict(avctx, &tmp)) < 0)
goto free_and_end;
- if (avctx->coded_width && avctx->coded_height)
- avcodec_set_dimensions(avctx, avctx->coded_width, avctx->coded_height);
+ if (avctx->coded_width && avctx->coded_height && !avctx->width && !avctx->height)
+ ret = ff_set_dimensions(avctx, avctx->coded_width, avctx->coded_height);
else if (avctx->width && avctx->height)
- avcodec_set_dimensions(avctx, avctx->width, avctx->height);
+ ret = ff_set_dimensions(avctx, avctx->width, avctx->height);
+ if (ret < 0)
+ goto free_and_end;
if ((avctx->coded_width || avctx->coded_height || avctx->width || avctx->height)
&& ( av_image_check_size(avctx->coded_width, avctx->coded_height, 0, avctx) < 0
|| av_image_check_size(avctx->width, avctx->height, 0, avctx) < 0)) {
av_log(avctx, AV_LOG_WARNING, "ignoring invalid width/height values\n");
- avcodec_set_dimensions(avctx, 0, 0);
+ ff_set_dimensions(avctx, 0, 0);
+ }
+
+ if (avctx->width > 0 && avctx->height > 0) {
+ if (av_image_check_sar(avctx->width, avctx->height,
+ avctx->sample_aspect_ratio) < 0) {
+ av_log(avctx, AV_LOG_WARNING, "ignoring invalid SAR: %u/%u\n",
+ avctx->sample_aspect_ratio.num,
+ avctx->sample_aspect_ratio.den);
+ avctx->sample_aspect_ratio = (AVRational){ 0, 1 };
+ }
}
/* if the decoder init function was already called previously,
avctx->time_base.den = avctx->sample_rate;
}
- if (HAVE_THREADS && !avctx->thread_opaque) {
+ if (HAVE_THREADS) {
ret = ff_thread_init(avctx);
if (ret < 0) {
goto free_and_end;
if (av_codec_is_encoder(avctx->codec)) {
int i;
+#if FF_API_CODED_FRAME
+FF_DISABLE_DEPRECATION_WARNINGS
+ avctx->coded_frame = av_frame_alloc();
+ if (!avctx->coded_frame) {
+ ret = AVERROR(ENOMEM);
+ goto free_and_end;
+ }
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
if (avctx->codec->sample_fmts) {
for (i = 0; avctx->codec->sample_fmts[i] != AV_SAMPLE_FMT_NONE; i++) {
if (avctx->sample_fmt == avctx->codec->sample_fmts[i])
ret = AVERROR(EINVAL);
goto free_and_end;
}
+ if (avctx->codec->pix_fmts[i] == AV_PIX_FMT_YUVJ420P ||
+ avctx->codec->pix_fmts[i] == AV_PIX_FMT_YUVJ422P ||
+ avctx->codec->pix_fmts[i] == AV_PIX_FMT_YUVJ440P ||
+ avctx->codec->pix_fmts[i] == AV_PIX_FMT_YUVJ444P)
+ avctx->color_range = AVCOL_RANGE_JPEG;
}
if (avctx->codec->supported_samplerates) {
for (i = 0; avctx->codec->supported_samplerates[i] != 0; i++)
}
}
+#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)) {
/* validate channel layout from the decoder */
if (avctx->channel_layout) {
ret = AVERROR(EINVAL);
goto free_and_end;
}
+
+#if FF_API_AVCTX_TIMEBASE
+ if (avctx->framerate.num > 0 && avctx->framerate.den > 0)
+ avctx->time_base = av_inv_q(avctx->framerate);
+#endif
}
end:
entangled_thread_counter--;
/* Release any user-supplied mutex. */
- if (ff_lockmgr_cb) {
- (*ff_lockmgr_cb)(&codec_mutex, AV_LOCK_RELEASE);
+ if (lockmgr_cb) {
+ (*lockmgr_cb)(&codec_mutex, AV_LOCK_RELEASE);
}
if (options) {
av_dict_free(options);
return ret;
free_and_end:
+ if (avctx->codec &&
+ (avctx->codec->caps_internal & FF_CODEC_CAP_INIT_CLEANUP))
+ avctx->codec->close(avctx);
+
+ if (avctx->priv_data && avctx->codec && avctx->codec->priv_class)
+ av_opt_free(avctx->priv_data);
+ av_opt_free(avctx);
+
+#if FF_API_CODED_FRAME
+FF_DISABLE_DEPRECATION_WARNINGS
+ av_frame_free(&avctx->coded_frame);
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+
av_dict_free(&tmp);
av_freep(&avctx->priv_data);
- if (avctx->internal)
+ if (avctx->internal) {
+ av_frame_free(&avctx->internal->to_free);
av_freep(&avctx->internal->pool);
+ }
av_freep(&avctx->internal);
avctx->codec = NULL;
goto end;
if (avpkt->data) {
AVBufferRef *buf = avpkt->buf;
#if FF_API_DESTRUCT_PACKET
+FF_DISABLE_DEPRECATION_WARNINGS
void *destruct = avpkt->destruct;
+FF_ENABLE_DEPRECATION_WARNINGS
#endif
if (avpkt->size < size)
av_init_packet(avpkt);
#if FF_API_DESTRUCT_PACKET
+FF_DISABLE_DEPRECATION_WARNINGS
avpkt->destruct = destruct;
+FF_ENABLE_DEPRECATION_WARNINGS
#endif
avpkt->buf = buf;
avpkt->size = size;
static int pad_last_frame(AVCodecContext *s, AVFrame **dst, const AVFrame *src)
{
AVFrame *frame = NULL;
- uint8_t *buf = NULL;
int ret;
- if (!(frame = avcodec_alloc_frame()))
+ if (!(frame = av_frame_alloc()))
return AVERROR(ENOMEM);
- *frame = *src;
- if ((ret = av_samples_get_buffer_size(&frame->linesize[0], s->channels,
- s->frame_size, s->sample_fmt, 0)) < 0)
+ frame->format = src->format;
+ frame->channel_layout = src->channel_layout;
+ frame->nb_samples = s->frame_size;
+ ret = av_frame_get_buffer(frame, 32);
+ if (ret < 0)
goto fail;
- if (!(buf = av_malloc(ret))) {
- ret = AVERROR(ENOMEM);
+ ret = av_frame_copy_props(frame, src);
+ if (ret < 0)
goto fail;
- }
- frame->nb_samples = s->frame_size;
- if ((ret = avcodec_fill_audio_frame(frame, s->channels, s->sample_fmt,
- buf, ret, 0)) < 0)
- goto fail;
if ((ret = av_samples_copy(frame->extended_data, src->extended_data, 0, 0,
src->nb_samples, s->channels, s->sample_fmt)) < 0)
goto fail;
return 0;
fail:
- if (frame->extended_data != frame->data)
- av_freep(&frame->extended_data);
- av_freep(&buf);
- av_freep(&frame);
+ av_frame_free(&frame);
return ret;
}
frame = &tmp;
}
+ /* extract audio service type metadata */
+ if (frame) {
+ AVFrameSideData *sd = av_frame_get_side_data(frame, AV_FRAME_DATA_AUDIO_SERVICE_TYPE);
+ if (sd && sd->size >= sizeof(enum AVAudioServiceType))
+ avctx->audio_service_type = *(enum AVAudioServiceType*)sd->data;
+ }
+
/* check for valid frame size */
if (frame) {
if (avctx->codec->capabilities & CODEC_CAP_SMALL_LAST_FRAME) {
avpkt->flags |= AV_PKT_FLAG_KEY;
end:
- if (padded_frame) {
- av_freep(&padded_frame->data[0]);
- if (padded_frame->extended_data != padded_frame->data)
- av_freep(&padded_frame->extended_data);
- av_freep(&padded_frame);
- }
+ av_frame_free(&padded_frame);
+
+#if FF_API_AUDIOENC_DELAY
+ avctx->delay = avctx->initial_padding;
+#endif
return ret;
}
return ret;
}
-static void apply_param_change(AVCodecContext *avctx, AVPacket *avpkt)
+static int apply_param_change(AVCodecContext *avctx, AVPacket *avpkt)
{
- int size = 0;
+ int size = 0, ret;
const uint8_t *data;
uint32_t flags;
- if (!(avctx->codec->capabilities & CODEC_CAP_PARAM_CHANGE))
- return;
-
data = av_packet_get_side_data(avpkt, AV_PKT_DATA_PARAM_CHANGE, &size);
- if (!data || size < 4)
- return;
+ if (!data)
+ return 0;
+
+ if (!(avctx->codec->capabilities & CODEC_CAP_PARAM_CHANGE)) {
+ av_log(avctx, AV_LOG_ERROR, "This decoder does not support parameter "
+ "changes, but PARAM_CHANGE side data was sent to it.\n");
+ return AVERROR(EINVAL);
+ }
+
+ if (size < 4)
+ goto fail;
+
flags = bytestream_get_le32(&data);
size -= 4;
- if (size < 4) /* Required for any of the changes */
- return;
+
if (flags & AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT) {
+ if (size < 4)
+ goto fail;
avctx->channels = bytestream_get_le32(&data);
size -= 4;
}
if (flags & AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_LAYOUT) {
if (size < 8)
- return;
+ goto fail;
avctx->channel_layout = bytestream_get_le64(&data);
size -= 8;
}
- if (size < 4)
- return;
if (flags & AV_SIDE_DATA_PARAM_CHANGE_SAMPLE_RATE) {
+ if (size < 4)
+ goto fail;
avctx->sample_rate = bytestream_get_le32(&data);
size -= 4;
}
if (flags & AV_SIDE_DATA_PARAM_CHANGE_DIMENSIONS) {
if (size < 8)
- return;
+ goto fail;
avctx->width = bytestream_get_le32(&data);
avctx->height = bytestream_get_le32(&data);
- avcodec_set_dimensions(avctx, avctx->width, avctx->height);
size -= 8;
+ ret = ff_set_dimensions(avctx, avctx->width, avctx->height);
+ if (ret < 0)
+ return ret;
}
+
+ return 0;
+fail:
+ av_log(avctx, AV_LOG_ERROR, "PARAM_CHANGE side data too small.\n");
+ return AVERROR_INVALIDDATA;
+}
+
+static int unrefcount_frame(AVCodecInternal *avci, AVFrame *frame)
+{
+ int ret;
+
+ /* move the original frame to our backup */
+ av_frame_unref(avci->to_free);
+ av_frame_move_ref(avci->to_free, frame);
+
+ /* now copy everything except the AVBufferRefs back
+ * note that we make a COPY of the side data, so calling av_frame_free() on
+ * the caller's frame will work properly */
+ ret = av_frame_copy_props(frame, avci->to_free);
+ if (ret < 0)
+ return ret;
+
+ memcpy(frame->data, avci->to_free->data, sizeof(frame->data));
+ memcpy(frame->linesize, avci->to_free->linesize, sizeof(frame->linesize));
+ if (avci->to_free->extended_data != avci->to_free->data) {
+ int planes = av_get_channel_layout_nb_channels(avci->to_free->channel_layout);
+ int size = planes * sizeof(*frame->extended_data);
+
+ if (!size) {
+ av_frame_unref(frame);
+ return AVERROR_BUG;
+ }
+
+ frame->extended_data = av_malloc(size);
+ if (!frame->extended_data) {
+ av_frame_unref(frame);
+ return AVERROR(ENOMEM);
+ }
+ memcpy(frame->extended_data, avci->to_free->extended_data,
+ size);
+ } else
+ frame->extended_data = frame->data;
+
+ frame->format = avci->to_free->format;
+ frame->width = avci->to_free->width;
+ frame->height = avci->to_free->height;
+ frame->channel_layout = avci->to_free->channel_layout;
+ frame->nb_samples = avci->to_free->nb_samples;
+
+ return 0;
}
int attribute_align_arg avcodec_decode_video2(AVCodecContext *avctx, AVFrame *picture,
if ((avctx->coded_width || avctx->coded_height) && av_image_check_size(avctx->coded_width, avctx->coded_height, 0, avctx))
return -1;
- avctx->pkt = avpkt;
- apply_param_change(avctx, avpkt);
-
- avcodec_get_frame_defaults(picture);
+ avctx->internal->pkt = avpkt;
+ ret = apply_param_change(avctx, avpkt);
+ if (ret < 0) {
+ av_log(avctx, AV_LOG_ERROR, "Error applying parameter changes.\n");
+ if (avctx->err_recognition & AV_EF_EXPLODE)
+ return ret;
+ }
- if (!avctx->refcounted_frames)
- av_frame_unref(&avci->to_free);
+ av_frame_unref(picture);
if ((avctx->codec->capabilities & CODEC_CAP_DELAY) || avpkt->size || (avctx->active_thread_type & FF_THREAD_FRAME)) {
if (HAVE_THREADS && avctx->active_thread_type & FF_THREAD_FRAME)
emms_c(); //needed to avoid an emms_c() call before every return;
- if (ret < 0 && picture->data[0])
- av_frame_unref(picture);
-
if (*got_picture_ptr) {
if (!avctx->refcounted_frames) {
- avci->to_free = *picture;
- avci->to_free.extended_data = avci->to_free.data;
+ int err = unrefcount_frame(avci, picture);
+ if (err < 0)
+ return err;
}
avctx->frame_number++;
- }
+ } else
+ av_frame_unref(picture);
} else
ret = 0;
- /* many decoders assign whole AVFrames, thus overwriting extended_data;
- * make sure it's set correctly */
- picture->extended_data = picture->data;
+#if FF_API_AVCTX_TIMEBASE
+ if (avctx->framerate.num > 0 && avctx->framerate.den > 0)
+ avctx->time_base = av_inv_q(avctx->framerate);
+#endif
return ret;
}
AVPacket *avpkt)
{
AVCodecInternal *avci = avctx->internal;
- int planar, channels;
int ret = 0;
*got_frame_ptr = 0;
- avctx->pkt = avpkt;
+ avctx->internal->pkt = avpkt;
if (!avpkt->data && avpkt->size) {
av_log(avctx, AV_LOG_ERROR, "invalid packet: NULL data, size != 0\n");
return AVERROR(EINVAL);
}
- apply_param_change(avctx, avpkt);
-
- avcodec_get_frame_defaults(frame);
+ ret = apply_param_change(avctx, avpkt);
+ if (ret < 0) {
+ av_log(avctx, AV_LOG_ERROR, "Error applying parameter changes.\n");
+ if (avctx->err_recognition & AV_EF_EXPLODE)
+ return ret;
+ }
- if (!avctx->refcounted_frames)
- av_frame_unref(&avci->to_free);
+ av_frame_unref(frame);
if ((avctx->codec->capabilities & CODEC_CAP_DELAY) || avpkt->size) {
ret = avctx->codec->decode(avctx, frame, got_frame_ptr, avpkt);
frame->format = avctx->sample_fmt;
if (!avctx->refcounted_frames) {
- avci->to_free = *frame;
- avci->to_free.extended_data = avci->to_free.data;
+ int err = unrefcount_frame(avci, frame);
+ if (err < 0)
+ return err;
}
- }
-
- if (ret < 0 && frame->data[0])
+ } else
av_frame_unref(frame);
}
- /* many decoders assign whole AVFrames, thus overwriting extended_data;
- * make sure it's set correctly; assume decoders that actually use
- * extended_data are doing it correctly */
- planar = av_sample_fmt_is_planar(frame->format);
- channels = av_get_channel_layout_nb_channels(frame->channel_layout);
- if (!(planar && channels > AV_NUM_DATA_POINTERS))
- frame->extended_data = frame->data;
return ret;
}
{
int ret;
- avctx->pkt = avpkt;
+ avctx->internal->pkt = avpkt;
*got_sub_ptr = 0;
ret = avctx->codec->decode(avctx, sub, got_sub_ptr, avpkt);
if (*got_sub_ptr)
av_cold int avcodec_close(AVCodecContext *avctx)
{
- /* If there is a user-supplied mutex locking routine, call it. */
- if (ff_lockmgr_cb) {
- if ((*ff_lockmgr_cb)(&codec_mutex, AV_LOCK_OBTAIN))
- return -1;
- }
-
- entangled_thread_counter++;
- if (entangled_thread_counter != 1) {
- av_log(avctx, AV_LOG_ERROR, "insufficient thread locking around avcodec_open/close()\n");
- entangled_thread_counter--;
- return -1;
- }
-
if (avcodec_is_open(avctx)) {
FramePool *pool = avctx->internal->pool;
int i;
- if (HAVE_THREADS && avctx->thread_opaque)
+ if (HAVE_THREADS && avctx->internal->thread_ctx)
ff_thread_free(avctx);
if (avctx->codec && avctx->codec->close)
avctx->codec->close(avctx);
- avctx->coded_frame = NULL;
- if (!avctx->refcounted_frames)
- av_frame_unref(&avctx->internal->to_free);
+ av_frame_free(&avctx->internal->to_free);
for (i = 0; i < FF_ARRAY_ELEMS(pool->pools); i++)
av_buffer_pool_uninit(&pool->pools[i]);
av_freep(&avctx->internal->pool);
+
+ if (avctx->hwaccel && avctx->hwaccel->uninit)
+ avctx->hwaccel->uninit(avctx);
+ av_freep(&avctx->internal->hwaccel_priv_data);
+
av_freep(&avctx->internal);
}
av_opt_free(avctx->priv_data);
av_opt_free(avctx);
av_freep(&avctx->priv_data);
- if (av_codec_is_encoder(avctx->codec))
+ if (av_codec_is_encoder(avctx->codec)) {
av_freep(&avctx->extradata);
+#if FF_API_CODED_FRAME
+FF_DISABLE_DEPRECATION_WARNINGS
+ av_frame_free(&avctx->coded_frame);
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+ }
avctx->codec = NULL;
avctx->active_thread_type = 0;
- entangled_thread_counter--;
- /* Release any user-supplied mutex. */
- if (ff_lockmgr_cb) {
- (*ff_lockmgr_cb)(&codec_mutex, AV_LOCK_RELEASE);
- }
return 0;
}
const AVCodec *p;
char buf1[32];
int bitrate;
+ int new_line = 0;
AVRational display_aspect_ratio;
if (enc->codec)
/* fake mpeg2 transport stream codec (currently not
* registered) */
codec_name = "mpeg2ts";
- } else if (enc->codec_name[0] != '\0') {
- codec_name = enc->codec_name;
} else {
/* output avi tags */
char tag_buf[32];
if (profile)
snprintf(buf + strlen(buf), buf_size - strlen(buf),
" (%s)", profile);
- if (enc->pix_fmt != AV_PIX_FMT_NONE) {
+ if (enc->codec_tag) {
+ char tag_buf[32];
+ av_get_codec_tag_string(tag_buf, sizeof(tag_buf), enc->codec_tag);
snprintf(buf + strlen(buf), buf_size - strlen(buf),
- ", %s",
+ " [%s / 0x%04X]", tag_buf, enc->codec_tag);
+ }
+
+ av_strlcat(buf, "\n ", buf_size);
+ snprintf(buf + strlen(buf), buf_size - strlen(buf),
+ "%s", enc->pix_fmt == AV_PIX_FMT_NONE ? "none" :
av_get_pix_fmt_name(enc->pix_fmt));
+
+ if (enc->color_range != AVCOL_RANGE_UNSPECIFIED)
+ snprintf(buf + strlen(buf), buf_size - strlen(buf), ", %s",
+ av_color_range_name(enc->color_range));
+ if (enc->colorspace != AVCOL_SPC_UNSPECIFIED ||
+ enc->color_primaries != AVCOL_PRI_UNSPECIFIED ||
+ enc->color_trc != AVCOL_TRC_UNSPECIFIED) {
+ new_line = 1;
+ snprintf(buf + strlen(buf), buf_size - strlen(buf), ", %s/%s/%s",
+ av_color_space_name(enc->colorspace),
+ av_color_primaries_name(enc->color_primaries),
+ av_color_transfer_name(enc->color_trc));
}
+ if (av_log_get_level() >= AV_LOG_DEBUG &&
+ enc->chroma_sample_location != AVCHROMA_LOC_UNSPECIFIED)
+ snprintf(buf + strlen(buf), buf_size - strlen(buf), ", %s",
+ av_chroma_location_name(enc->chroma_sample_location));
+
if (enc->width) {
+ av_strlcat(buf, new_line ? "\n " : ", ", buf_size);
+
snprintf(buf + strlen(buf), buf_size - strlen(buf),
- ", %dx%d",
+ "%dx%d",
enc->width, enc->height);
+
+ if (av_log_get_level() >= AV_LOG_VERBOSE &&
+ (enc->width != enc->coded_width ||
+ enc->height != enc->coded_height))
+ snprintf(buf + strlen(buf), buf_size - strlen(buf),
+ " (%dx%d)", enc->coded_width, enc->coded_height);
+
if (enc->sample_aspect_ratio.num) {
av_reduce(&display_aspect_ratio.num, &display_aspect_ratio.den,
enc->width * enc->sample_aspect_ratio.num,
if (profile)
snprintf(buf + strlen(buf), buf_size - strlen(buf),
" (%s)", profile);
+ if (enc->codec_tag) {
+ char tag_buf[32];
+ av_get_codec_tag_string(tag_buf, sizeof(tag_buf), enc->codec_tag);
+ snprintf(buf + strlen(buf), buf_size - strlen(buf),
+ " [%s / 0x%04X]", tag_buf, enc->codec_tag);
+ }
+
+ av_strlcat(buf, "\n ", buf_size);
if (enc->sample_rate) {
snprintf(buf + strlen(buf), buf_size - strlen(buf),
- ", %d Hz", enc->sample_rate);
+ "%d Hz, ", enc->sample_rate);
}
- av_strlcat(buf, ", ", buf_size);
av_get_channel_layout_string(buf + strlen(buf), buf_size - strlen(buf), enc->channels, enc->channel_layout);
if (enc->sample_fmt != AV_SAMPLE_FMT_NONE) {
snprintf(buf + strlen(buf), buf_size - strlen(buf),
ff_thread_flush(avctx);
else if (avctx->codec->flush)
avctx->codec->flush(avctx);
+
+ if (!avctx->refcounted_frames)
+ av_frame_unref(avctx->internal->to_free);
}
int av_get_exact_bits_per_sample(enum AVCodecID codec_id)
case AV_CODEC_ID_PCM_ZORK:
return 8;
case AV_CODEC_ID_PCM_S16BE:
+ case AV_CODEC_ID_PCM_S16BE_PLANAR:
case AV_CODEC_ID_PCM_S16LE:
case AV_CODEC_ID_PCM_S16LE_PLANAR:
case AV_CODEC_ID_PCM_U16BE:
case AV_CODEC_ID_PCM_S24DAUD:
case AV_CODEC_ID_PCM_S24BE:
case AV_CODEC_ID_PCM_S24LE:
+ case AV_CODEC_ID_PCM_S24LE_PLANAR:
case AV_CODEC_ID_PCM_U24BE:
case AV_CODEC_ID_PCM_U24LE:
return 24;
case AV_CODEC_ID_PCM_S32BE:
case AV_CODEC_ID_PCM_S32LE:
+ case AV_CODEC_ID_PCM_S32LE_PLANAR:
case AV_CODEC_ID_PCM_U32BE:
case AV_CODEC_ID_PCM_U32LE:
case AV_CODEC_ID_PCM_F32BE:
return i;
}
+#if FF_API_MISSING_SAMPLE
+FF_DISABLE_DEPRECATION_WARNINGS
void av_log_missing_feature(void *avc, const char *feature, int want_sample)
{
av_log(avc, AV_LOG_WARNING, "%s is not implemented. Update your Libav "
va_end(argument_list);
}
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif /* FF_API_MISSING_SAMPLE */
static AVHWAccel *first_hwaccel = NULL;
hwaccel->next = NULL;
}
-AVHWAccel *av_hwaccel_next(AVHWAccel *hwaccel)
+AVHWAccel *av_hwaccel_next(const AVHWAccel *hwaccel)
{
return hwaccel ? hwaccel->next : first_hwaccel;
}
-AVHWAccel *ff_find_hwaccel(enum AVCodecID codec_id, enum AVPixelFormat pix_fmt)
-{
- AVHWAccel *hwaccel = NULL;
-
- while ((hwaccel = av_hwaccel_next(hwaccel)))
- if (hwaccel->id == codec_id
- && hwaccel->pix_fmt == pix_fmt)
- return hwaccel;
- return NULL;
-}
-
int av_lockmgr_register(int (*cb)(void **mutex, enum AVLockOp op))
{
- if (ff_lockmgr_cb) {
- if (ff_lockmgr_cb(&codec_mutex, AV_LOCK_DESTROY))
- return -1;
- if (ff_lockmgr_cb(&avformat_mutex, AV_LOCK_DESTROY))
- return -1;
+ 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;
}
- ff_lockmgr_cb = cb;
-
- if (ff_lockmgr_cb) {
- if (ff_lockmgr_cb(&codec_mutex, AV_LOCK_CREATE))
- return -1;
- if (ff_lockmgr_cb(&avformat_mutex, AV_LOCK_CREATE))
- return -1;
- }
return 0;
}
int avpriv_lock_avformat(void)
{
- if (ff_lockmgr_cb) {
- if ((*ff_lockmgr_cb)(&avformat_mutex, AV_LOCK_OBTAIN))
+ if (lockmgr_cb) {
+ if ((*lockmgr_cb)(&avformat_mutex, AV_LOCK_OBTAIN))
return -1;
}
return 0;
int avpriv_unlock_avformat(void)
{
- if (ff_lockmgr_cb) {
- if ((*ff_lockmgr_cb)(&avformat_mutex, AV_LOCK_RELEASE))
+ if (lockmgr_cb) {
+ if ((*lockmgr_cb)(&avformat_mutex, AV_LOCK_RELEASE))
return -1;
}
return 0;
void ff_thread_release_buffer(AVCodecContext *avctx, ThreadFrame *f)
{
- av_frame_unref(f->f);
+ if (f->f)
+ av_frame_unref(f->f);
}
void ff_thread_finish_setup(AVCodecContext *avctx)
{
return !!s->internal;
}
+
+const uint8_t *avpriv_find_start_code(const uint8_t *restrict p,
+ const uint8_t *end,
+ uint32_t * restrict state)
+{
+ int i;
+
+ assert(p <= end);
+ if (p >= end)
+ return end;
+
+ for (i = 0; i < 3; i++) {
+ uint32_t tmp = *state << 8;
+ *state = tmp + *(p++);
+ if (tmp == 0x100 || p == end)
+ return p;
+ }
+
+ while (p < end) {
+ if (p[-1] > 1 ) p += 3;
+ else if (p[-2] ) p += 2;
+ else if (p[-3]|(p[-1]-1)) p++;
+ else {
+ p++;
+ break;
+ }
+ }
+
+ p = FFMIN(p, end) - 4;
+ *state = AV_RB32(p);
+
+ return p + 4;
+}