Newer
Older
* Copyright (c) 2001 Fabrice Bellard
Michael Niedermayer
committed
* Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at>
* This file is part of Libav.
Diego Biurrun
committed
*
* Libav 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
Diego Biurrun
committed
* version 2.1 of the License, or (at your option) any later version.
* Libav 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 Libav; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#include "config.h"
#include "libavutil/attributes.h"
Justin Ruggles
committed
#include "libavutil/avassert.h"
#include "libavutil/avstring.h"
#include "libavutil/channel_layout.h"
#include "libavutil/crc.h"
#include "libavutil/internal.h"
#include "libavutil/mathematics.h"
Reimar Döffinger
committed
#include "libavutil/pixdesc.h"
#include "libavutil/imgutils.h"
#include "libavutil/samplefmt.h"
#include "libavutil/dict.h"
#include "libavutil/opt.h"
#include "thread.h"
#include "internal.h"
#include "bytestream.h"
#include "version.h"
Aurelien Jacobs
committed
#include <stdlib.h>
#include <stdarg.h>
Michael Niedermayer
committed
#include <limits.h>
static int volatile entangled_thread_counter = 0;
static int (*lockmgr_cb)(void **mutex, enum AVLockOp op);
static void *avformat_mutex;
#if FF_API_FAST_MALLOC && CONFIG_SHARED && HAVE_SYMVER
FF_SYMVER(void*, av_fast_realloc, (void *ptr, unsigned int *size, size_t min_size), "LIBAVCODEC_55")
return av_fast_realloc(ptr, size, min_size);
FF_SYMVER(void, av_fast_malloc, (void *ptr, unsigned int *size, size_t min_size), "LIBAVCODEC_55")
Reimar Döffinger
committed
{
av_fast_malloc(ptr, size, min_size);
Reimar Döffinger
committed
}
Reimar Döffinger
committed
void av_fast_padded_malloc(void *ptr, unsigned int *size, size_t min_size)
{
void **p = ptr;
if (min_size > SIZE_MAX - FF_INPUT_BUFFER_PADDING_SIZE) {
av_freep(p);
*size = 0;
return;
}
av_fast_malloc(p, size, min_size + FF_INPUT_BUFFER_PADDING_SIZE);
if (*size)
memset((uint8_t *)*p + min_size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
}
static AVCodec *first_avcodec = NULL;
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_DSPUTIL)
ff_dsputil_static_init();
int av_codec_is_encoder(const AVCodec *codec)
Justin Ruggles
committed
{
return codec && (codec->encode_sub || codec->encode2);
Justin Ruggles
committed
}
int av_codec_is_decoder(const AVCodec *codec)
Justin Ruggles
committed
{
return codec && codec->decode;
}
av_cold void avcodec_register(AVCodec *codec)
while (*p != NULL)
p = &(*p)->next;
*p = codec;
codec->next = NULL;
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)
{
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;
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_NEON || ARCH_PPC || HAVE_MMX
# define STRIDE_ALIGN 16
#else
# define STRIDE_ALIGN 8
#endif
void avcodec_align_dimensions2(AVCodecContext *s, int *width, int *height,
int linesize_align[AV_NUM_DATA_POINTERS])
{
int i;
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_GRAY8:
case AV_PIX_FMT_GRAY16BE:
case AV_PIX_FMT_GRAY16LE:
case AV_PIX_FMT_YUVJ420P:
case AV_PIX_FMT_YUVJ422P:
case AV_PIX_FMT_YUVJ440P:
case AV_PIX_FMT_YUVJ444P:
case AV_PIX_FMT_YUVA420P:
case AV_PIX_FMT_YUVA422P:
case AV_PIX_FMT_YUVA444P:
case AV_PIX_FMT_YUV420P9LE:
case AV_PIX_FMT_YUV420P9BE:
case AV_PIX_FMT_YUV420P10LE:
case AV_PIX_FMT_YUV420P10BE:
case AV_PIX_FMT_YUV422P9LE:
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:
case AV_PIX_FMT_GBRP10BE:
w_align = 16; //FIXME assume 16 pixel per macroblock
h_align = 16 * 2; // interlaced needs 2 macroblocks height
case AV_PIX_FMT_YUV411P:
case AV_PIX_FMT_UYYVYY411:
case AV_PIX_FMT_YUV410P:
if (s->codec_id == AV_CODEC_ID_SVQ1) {
w_align = 64;
h_align = 64;
case AV_PIX_FMT_RGB555:
if (s->codec_id == AV_CODEC_ID_RPZA) {
w_align = 4;
h_align = 4;
case AV_PIX_FMT_PAL8:
case AV_PIX_FMT_BGR8:
case AV_PIX_FMT_RGB8:
if (s->codec_id == AV_CODEC_ID_SMC) {
w_align = 4;
h_align = 4;
case AV_PIX_FMT_BGR24:
if ((s->codec_id == AV_CODEC_ID_MSZH) ||
(s->codec_id == AV_CODEC_ID_ZLIB)) {
w_align = 4;
h_align = 4;
}
break;
*width = FFALIGN(*width, w_align);
*height = FFALIGN(*height, h_align);
if (s->codec_id == AV_CODEC_ID_H264)
// some of the optimized chroma MC reads one line too much
*height += 2;
Reimar Döffinger
committed
for (i = 0; i < 4; i++)
linesize_align[i] = STRIDE_ALIGN;
Reimar Döffinger
committed
}
void avcodec_align_dimensions(AVCodecContext *s, int *width, int *height)
{
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(s->pix_fmt);
int chroma_shift = desc->log2_chroma_w;
int linesize_align[AV_NUM_DATA_POINTERS];
Reimar Döffinger
committed
int align;
Reimar Döffinger
committed
avcodec_align_dimensions2(s, width, height, linesize_align);
align = FFMAX(linesize_align[0], linesize_align[3]);
Reimar Döffinger
committed
linesize_align[1] <<= chroma_shift;
linesize_align[2] <<= chroma_shift;
align = FFMAX3(align, linesize_align[1], linesize_align[2]);
*width = FFALIGN(*width, align);
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
int avcodec_fill_audio_frame(AVFrame *frame, int nb_channels,
enum AVSampleFormat sample_fmt, const uint8_t *buf,
int buf_size, int align)
{
int ch, planar, needed_size, ret = 0;
needed_size = av_samples_get_buffer_size(NULL, nb_channels,
frame->nb_samples, sample_fmt,
align);
if (buf_size < needed_size)
return AVERROR(EINVAL);
planar = av_sample_fmt_is_planar(sample_fmt);
if (planar && nb_channels > AV_NUM_DATA_POINTERS) {
if (!(frame->extended_data = av_mallocz(nb_channels *
sizeof(*frame->extended_data))))
return AVERROR(ENOMEM);
} else {
frame->extended_data = frame->data;
}
if ((ret = av_samples_fill_arrays(frame->extended_data, &frame->linesize[0],
buf, nb_channels, frame->nb_samples,
sample_fmt, align)) < 0) {
if (frame->extended_data != frame->data)
av_free(frame->extended_data);
return ret;
}
if (frame->extended_data != frame->data) {
for (ch = 0; ch < AV_NUM_DATA_POINTERS; ch++)
frame->data[ch] = frame->extended_data[ch];
}
return ret;
}
static int update_frame_pool(AVCodecContext *avctx, AVFrame *frame)
FramePool *pool = avctx->internal->pool;
int i, ret;
switch (avctx->codec_type) {
case AVMEDIA_TYPE_VIDEO: {
int size[4] = { 0 };
int w = frame->width;
int h = frame->height;
int tmpsize, unaligned;
if (pool->format == frame->format &&
pool->width == frame->width && pool->height == frame->height)
return 0;
avcodec_align_dimensions2(avctx, &w, &h, pool->stride_align);
if (!(avctx->flags & CODEC_FLAG_EMU_EDGE)) {
Reimar Döffinger
committed
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
av_image_fill_linesizes(picture.linesize, avctx->pix_fmt, w);
Reimar Döffinger
committed
// increase alignment of w for next try (rhs gives the lowest bit set in w)
Reimar Döffinger
committed
unaligned = 0;
unaligned |= picture.linesize[i] % pool->stride_align[i];
Reimar Döffinger
committed
} while (unaligned);
tmpsize = av_image_fill_pointers(picture.data, avctx->pix_fmt, h,
NULL, picture.linesize);
if (tmpsize < 0)
return -1;
for (i = 0; i < 3 && picture.data[i + 1]; i++)
size[i] = picture.data[i + 1] - picture.data[i];
size[i] = tmpsize - (picture.data[i] - picture.data[0]);
for (i = 0; i < 4; i++) {
av_buffer_pool_uninit(&pool->pools[i]);
pool->linesize[i] = picture.linesize[i];
if (size[i]) {
pool->pools[i] = av_buffer_pool_init(size[i] + 16, NULL);
if (!pool->pools[i]) {
ret = AVERROR(ENOMEM);
goto fail;
}
}
}
pool->format = frame->format;
pool->width = frame->width;
pool->height = frame->height;
break;
}
case AVMEDIA_TYPE_AUDIO: {
int ch = av_get_channel_layout_nb_channels(frame->channel_layout);
int planar = av_sample_fmt_is_planar(frame->format);
int planes = planar ? ch : 1;
if (pool->format == frame->format && pool->planes == planes &&
pool->channels == ch && frame->nb_samples == pool->samples)
return 0;
av_buffer_pool_uninit(&pool->pools[0]);
ret = av_samples_get_buffer_size(&pool->linesize[0], ch,
frame->nb_samples, frame->format, 0);
if (ret < 0)
goto fail;
pool->pools[0] = av_buffer_pool_init(pool->linesize[0], NULL);
if (!pool->pools[0]) {
ret = AVERROR(ENOMEM);
goto fail;
}
pool->format = frame->format;
pool->planes = planes;
pool->channels = ch;
pool->samples = frame->nb_samples;
break;
}
default: av_assert0(0);
}
return 0;
fail:
for (i = 0; i < 4; i++)
av_buffer_pool_uninit(&pool->pools[i]);
pool->format = -1;
pool->planes = pool->channels = pool->samples = 0;
pool->width = pool->height = 0;
return ret;
}
static int audio_get_buffer(AVCodecContext *avctx, AVFrame *frame)
{
FramePool *pool = avctx->internal->pool;
int planes = pool->planes;
int i;
frame->linesize[0] = pool->linesize[0];
if (planes > AV_NUM_DATA_POINTERS) {
frame->extended_data = av_mallocz(planes * sizeof(*frame->extended_data));
frame->nb_extended_buf = planes - AV_NUM_DATA_POINTERS;
frame->extended_buf = av_mallocz(frame->nb_extended_buf *
sizeof(*frame->extended_buf));
if (!frame->extended_data || !frame->extended_buf) {
av_freep(&frame->extended_data);
av_freep(&frame->extended_buf);
return AVERROR(ENOMEM);
}
} else
frame->extended_data = frame->data;
for (i = 0; i < FFMIN(planes, AV_NUM_DATA_POINTERS); i++) {
frame->buf[i] = av_buffer_pool_get(pool->pools[0]);
if (!frame->buf[i])
goto fail;
frame->extended_data[i] = frame->data[i] = frame->buf[i]->data;
for (i = 0; i < frame->nb_extended_buf; i++) {
frame->extended_buf[i] = av_buffer_pool_get(pool->pools[0]);
if (!frame->extended_buf[i])
goto fail;
frame->extended_data[i + AV_NUM_DATA_POINTERS] = frame->extended_buf[i]->data;
}
if (avctx->debug & FF_DEBUG_BUFFERS)
av_log(avctx, AV_LOG_DEBUG, "default_get_buffer called on frame %p", frame);
return 0;
fail:
av_frame_unref(frame);
return AVERROR(ENOMEM);
}
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) {
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));
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
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]);
}
}
for (; i < AV_NUM_DATA_POINTERS; i++) {
pic->data[i] = NULL;
pic->linesize[i] = 0;
}
if (pic->data[1] && !pic->data[2])
avpriv_set_systematic_pal2((uint32_t *)pic->data[1], s->pix_fmt);
av_log(s, AV_LOG_DEBUG, "default_get_buffer called on pic %p\n", pic);
Alexander Strange
committed
fail:
av_frame_unref(pic);
return AVERROR(ENOMEM);
int avcodec_default_get_buffer2(AVCodecContext *avctx, AVFrame *frame, int flags)
int ret;
if ((ret = update_frame_pool(avctx, frame)) < 0)
return ret;
#if FF_API_GET_BUFFER
FF_DISABLE_DEPRECATION_WARNINGS
frame->type = FF_BUFFER_TYPE_INTERNAL;
FF_ENABLE_DEPRECATION_WARNINGS
switch (avctx->codec_type) {
case AVMEDIA_TYPE_VIDEO:
return video_get_buffer(avctx, frame);
case AVMEDIA_TYPE_AUDIO:
return audio_get_buffer(avctx, frame);
default:
return -1;
}
}
FF_DISABLE_DEPRECATION_WARNINGS
int avcodec_default_get_buffer(AVCodecContext *avctx, AVFrame *frame)
return avcodec_default_get_buffer2(avctx, frame, 0);
}
typedef struct CompatReleaseBufPriv {
AVCodecContext avctx;
AVFrame frame;
} CompatReleaseBufPriv;
static void compat_free_buffer(void *opaque, uint8_t *data)
{
CompatReleaseBufPriv *priv = opaque;
if (priv->avctx.release_buffer)
priv->avctx.release_buffer(&priv->avctx, &priv->frame);
av_freep(&priv);
}
static void compat_release_buffer(void *opaque, uint8_t *data)
{
AVBufferRef *buf = opaque;
av_buffer_unref(&buf);
}
FF_ENABLE_DEPRECATION_WARNINGS
int ff_decode_frame_props(AVCodecContext *avctx, AVFrame *frame)
{
AVPacket *pkt = avctx->internal->pkt;
uint8_t *packet_sd;
int size;
AVFrameSideData *frame_sd;
frame->reordered_opaque = avctx->reordered_opaque;
if (!pkt) {
frame->pkt_pts = AV_NOPTS_VALUE;
return 0;
}
frame->pkt_pts = pkt->pts;
/* copy the replaygain data to the output frame */
packet_sd = av_packet_get_side_data(pkt, AV_PKT_DATA_REPLAYGAIN, &size);
if (packet_sd) {
frame_sd = av_frame_new_side_data(frame, AV_FRAME_DATA_REPLAYGAIN, size);
if (!frame_sd)
return AVERROR(ENOMEM);
memcpy(frame_sd->data, packet_sd, size);
}
/* copy the displaymatrix to the output frame */
packet_sd = av_packet_get_side_data(pkt, AV_PKT_DATA_DISPLAYMATRIX, &size);
if (packet_sd) {
frame_sd = av_frame_new_side_data(frame, AV_FRAME_DATA_DISPLAYMATRIX, 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;
switch (avctx->codec_type) {
case AVMEDIA_TYPE_VIDEO:
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 ((ret = av_image_check_size(avctx->width, avctx->height, 0, avctx)) < 0)
return ret;
break;
case AVMEDIA_TYPE_AUDIO:
if (!frame->sample_rate)
frame->sample_rate = avctx->sample_rate;
if (frame->format < 0)
frame->format = avctx->sample_fmt;
if (!frame->channel_layout) {
if (avctx->channel_layout) {
if (av_get_channel_layout_nb_channels(avctx->channel_layout) !=
avctx->channels) {
av_log(avctx, AV_LOG_ERROR, "Inconsistent channel "
"configuration.\n");
return AVERROR(EINVAL);
}
frame->channel_layout = avctx->channel_layout;
} else {
if (avctx->channels > FF_SANE_NB_CHANNELS) {
av_log(avctx, AV_LOG_ERROR, "Too many channels: %d.\n",
avctx->channels);
return AVERROR(ENOSYS);
}
frame->channel_layout = av_get_default_channel_layout(avctx->channels);
if (!frame->channel_layout)
frame->channel_layout = (1ULL << avctx->channels) - 1;
}
}
break;
default: return AVERROR(EINVAL);
}
ret = ff_decode_frame_props(avctx, frame);
if (ret < 0)
return ret;
if (hwaccel && hwaccel->alloc_frame) {
ret = hwaccel->alloc_frame(avctx, frame);
goto end;
}
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
* a dummy AVBuffer as its private data, unreffing it on free.
* When all the planes are freed, the dummy buffer's free callback calls
* release_buffer().
*/
if (avctx->get_buffer) {
CompatReleaseBufPriv *priv = NULL;
AVBufferRef *dummy_buf = NULL;
int planes, i, ret;
if (flags & AV_GET_BUFFER_FLAG_REF)
frame->reference = 1;
ret = avctx->get_buffer(avctx, frame);
if (ret < 0)
return ret;
/* return if the buffers are already set up
* this would happen e.g. when a custom get_buffer() calls
* avcodec_default_get_buffer
*/
if (frame->buf[0])
return 0;
priv = av_mallocz(sizeof(*priv));
if (!priv) {
ret = AVERROR(ENOMEM);
goto fail;
}
priv->avctx = *avctx;
priv->frame = *frame;
dummy_buf = av_buffer_create(NULL, 0, compat_free_buffer, priv, 0);
if (!dummy_buf) {
ret = AVERROR(ENOMEM);
goto fail;
#define WRAP_PLANE(ref_out, data, data_size) \
do { \
AVBufferRef *dummy_ref = av_buffer_ref(dummy_buf); \
if (!dummy_ref) { \
ret = AVERROR(ENOMEM); \
goto fail; \
} \
ref_out = av_buffer_create(data, data_size, compat_release_buffer, \
dummy_ref, 0); \
if (!ref_out) { \
av_frame_unref(frame); \
ret = AVERROR(ENOMEM); \
goto fail; \
} \
} while (0)
if (avctx->codec_type == AVMEDIA_TYPE_VIDEO) {
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format);
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;
}
for (i = 0; i < planes; i++) {
int v_shift = (i == 1 || i == 2) ? desc->log2_chroma_h : 0;
int plane_size = (frame->height >> v_shift) * frame->linesize[i];
Alexander Strange
committed
WRAP_PLANE(frame->buf[i], frame->data[i], plane_size);
}
} else {
int planar = av_sample_fmt_is_planar(frame->format);
planes = planar ? avctx->channels : 1;
if (planes > FF_ARRAY_ELEMS(frame->buf)) {
frame->nb_extended_buf = planes - FF_ARRAY_ELEMS(frame->buf);
frame->extended_buf = av_malloc(sizeof(*frame->extended_buf) *
frame->nb_extended_buf);
if (!frame->extended_buf) {
ret = AVERROR(ENOMEM);
goto fail;
}
}
for (i = 0; i < FFMIN(planes, FF_ARRAY_ELEMS(frame->buf)); i++)
WRAP_PLANE(frame->buf[i], frame->extended_data[i], frame->linesize[0]);
for (i = 0; i < frame->nb_extended_buf; i++)
WRAP_PLANE(frame->extended_buf[i],
frame->extended_data[i + FF_ARRAY_ELEMS(frame->buf)],
frame->linesize[0]);
}
av_buffer_unref(&dummy_buf);
frame->width = avctx->width;
frame->height = avctx->height;
fail:
avctx->release_buffer(avctx, frame);
av_freep(&priv);
av_buffer_unref(&dummy_buf);
return ret;
FF_ENABLE_DEPRECATION_WARNINGS
ret = avctx->get_buffer2(avctx, frame, flags);
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)
{
av_assert0(avctx->codec_type == AVMEDIA_TYPE_VIDEO);
if (!frame->data[0])
return ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF);
if (av_frame_is_writable(frame))
return ff_decode_frame_props(avctx, frame);
tmp = av_frame_alloc();
if (!tmp)
return AVERROR(ENOMEM);
av_frame_move_ref(tmp, frame);
ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF);
if (ret < 0) {
av_frame_free(&tmp);
}
av_frame_copy(frame, tmp);
av_frame_free(&tmp);
#if FF_API_GET_BUFFER
void avcodec_default_release_buffer(AVCodecContext *s, AVFrame *pic)
{
av_frame_unref(pic);
}
int avcodec_default_reget_buffer(AVCodecContext *s, AVFrame *pic)
{
av_assert0(0);
return AVERROR_BUG;
int avcodec_default_execute(AVCodecContext *c, int (*func)(AVCodecContext *c2, void *arg2), void *arg, int *ret, int count, int size)
{
for (i = 0; i < count; i++) {
int r = func(c, (char *)arg + i * size);
if (ret)
ret[i] = r;
int avcodec_default_execute2(AVCodecContext *c, int (*func)(AVCodecContext *c2, void *arg2, int jobnr, int threadnr), void *arg, int *ret, int count)
{
Reimar Döffinger
committed
int i;
for (i = 0; i < count; i++) {
int r = func(c, arg, i, 0);
if (ret)
ret[i] = r;
Reimar Döffinger
committed
}
return 0;
}
static int is_hwaccel_pix_fmt(enum AVPixelFormat pix_fmt)
{
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
return desc->flags & AV_PIX_FMT_FLAG_HWACCEL;
enum AVPixelFormat avcodec_default_get_format(struct AVCodecContext *s, const enum AVPixelFormat *fmt)
while (*fmt != AV_PIX_FMT_NONE && is_hwaccel_pix_fmt(*fmt))
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;
}
int ff_get_format(AVCodecContext *avctx, const enum AVPixelFormat *fmt)
{
const AVPixFmtDescriptor *desc;
enum AVPixelFormat ret = avctx->get_format(avctx, fmt);
desc = av_pix_fmt_desc_get(ret);
if (!desc)
return AV_PIX_FMT_NONE;
if (avctx->hwaccel && avctx->hwaccel->uninit)
avctx->hwaccel->uninit(avctx);
av_freep(&avctx->internal->hwaccel_priv_data);
avctx->hwaccel = NULL;
if (desc->flags & AV_PIX_FMT_FLAG_HWACCEL) {
AVHWAccel *hwaccel;
int err;
hwaccel = find_hwaccel(avctx->codec_id, ret);
if (!hwaccel) {
av_log(avctx, AV_LOG_ERROR,
"Could not find an AVHWAccel for the pixel format: %s",
desc->name);
return AV_PIX_FMT_NONE;
}
if (hwaccel->priv_data_size) {
avctx->internal->hwaccel_priv_data = av_mallocz(hwaccel->priv_data_size);
if (!avctx->internal->hwaccel_priv_data)
return AV_PIX_FMT_NONE;
}
if (hwaccel->init) {
err = hwaccel->init(avctx);
if (err < 0) {
av_freep(&avctx->internal->hwaccel_priv_data);
return AV_PIX_FMT_NONE;
}
}
avctx->hwaccel = hwaccel;
}
return ret;
void avcodec_get_frame_defaults(AVFrame *frame)
if (frame->extended_data != frame->data)
av_freep(&frame->extended_data);
memset(frame, 0, sizeof(AVFrame));
frame->pts = AV_NOPTS_VALUE;
frame->key_frame = 1;
frame->sample_aspect_ratio = (AVRational) {0, 1 };
frame->format = -1; /* unknown */
frame->extended_data = frame->data;
AVFrame *frame = av_mallocz(sizeof(AVFrame));
if (frame == NULL)
FF_DISABLE_DEPRECATION_WARNINGS
avcodec_get_frame_defaults(frame);
FF_ENABLE_DEPRECATION_WARNINGS
return frame;
void avcodec_free_frame(AVFrame **frame)
{
int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options)
Justin Ruggles
committed
int ret = 0;
AVDictionary *tmp = NULL;
if (avcodec_is_open(avctx))
return 0;
if ((!codec && !avctx->codec)) {
av_log(avctx, AV_LOG_ERROR, "No codec provided to avcodec_open2().\n");
return AVERROR(EINVAL);
}
if ((codec && avctx->codec && codec != avctx->codec)) {
av_log(avctx, AV_LOG_ERROR, "This AVCodecContext was allocated for %s, "
"but %s passed to avcodec_open2().\n", avctx->codec->name, codec->name);
return AVERROR(EINVAL);
}
if (!codec)
codec = avctx->codec;
if (avctx->extradata_size < 0 || avctx->extradata_size >= FF_MAX_EXTRADATA_SIZE)
return AVERROR(EINVAL);
if (options)
av_dict_copy(&tmp, *options, 0);