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 "me_cmp.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;
void av_fast_padded_malloc(void *ptr, unsigned int *size, size_t min_size)
{
void **p = ptr;
if (min_size > SIZE_MAX - AV_INPUT_BUFFER_PADDING_SIZE) {
av_freep(p);
*size = 0;
return;
}
av_fast_malloc(p, size, min_size + AV_INPUT_BUFFER_PADDING_SIZE);
memset((uint8_t *)*p + min_size, 0, AV_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_ME_CMP)
ff_me_cmp_init_static();
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)
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_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
#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);
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
328
329
330
331
332
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: {
uint8_t *data[4];
int linesize[4];
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);
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(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 |= linesize[i] % pool->stride_align[i];
Reimar Döffinger
committed
} while (unaligned);
tmpsize = av_image_fill_pointers(data, avctx->pix_fmt, h,
NULL, linesize);
if (tmpsize < 0)
return -1;
for (i = 0; i < 3 && data[i + 1]; i++)
size[i] = data[i + 1] - data[i];
size[i] = tmpsize - (data[i] - data[0]);
for (i = 0; i < 4; i++) {
av_buffer_pool_uninit(&pool->pools[i]);
pool->linesize[i] = 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;
int i;
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));
for (i = 0; i < 4 && pool->pools[i]; i++) {
pic->linesize[i] = pool->linesize[i];
pic->buf[i] = av_buffer_pool_get(pool->pools[i]);
if (!pic->buf[i])
goto fail;
pic->data[i] = pic->buf[i]->data;
}
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;
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;
}
}
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;
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 (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;
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) {
if (hwaccel->alloc_frame) {
ret = hwaccel->alloc_frame(avctx, frame);
goto end;
}
} else
avctx->sw_pix_fmt = avctx->pix_fmt;
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);
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;
}
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
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));
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);
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);
/* If there is a user-supplied mutex locking routine, call it. */
if (!(codec->caps_internal & FF_CODEC_CAP_INIT_THREADSAFE) && codec->init) {
Derek Buitenhuis
committed
if (lockmgr_cb) {
if ((*lockmgr_cb)(&codec_mutex, AV_LOCK_OBTAIN))
return -1;
}
Derek Buitenhuis
committed
entangled_thread_counter++;
if (entangled_thread_counter != 1) {
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;
}
avctx->internal = av_mallocz(sizeof(AVCodecInternal));
if (!avctx->internal) {
ret = AVERROR(ENOMEM);
goto end;
}
avctx->internal->pool = av_mallocz(sizeof(*avctx->internal->pool));
if (!avctx->internal->pool) {
ret = AVERROR(ENOMEM);
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 (!avctx->priv_data) {
ret = AVERROR(ENOMEM);
goto end;
}
if (codec->priv_class) {
*(const AVClass **)avctx->priv_data = codec->priv_class;
av_opt_set_defaults(avctx->priv_data);
}
Michael Niedermayer
committed
}
if (codec->priv_class && (ret = av_opt_set_dict(avctx->priv_data, &tmp)) < 0)
goto free_and_end;
} else {
avctx->priv_data = NULL;
}
if ((ret = av_opt_set_dict(avctx, &tmp)) < 0)
goto free_and_end;
if (avctx->coded_width && avctx->coded_height && !avctx->width && !avctx->height)
ret = ff_set_dimensions(avctx, avctx->coded_width, avctx->coded_height);
ret = ff_set_dimensions(avctx, avctx->width, avctx->height);
if (ret < 0)
goto free_and_end;
Reimar Döffinger
committed
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");
ff_set_dimensions(avctx, 0, 0);
Reimar Döffinger
committed
}
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,
* free the already allocated subtitle_header before overwriting it */
if (av_codec_is_decoder(codec))
av_freep(&avctx->subtitle_header);
if (avctx->channels > FF_SANE_NB_CHANNELS) {
Panagiotis Issaris
committed
ret = AVERROR(EINVAL);
Michael Niedermayer
committed
goto free_and_end;
if ((avctx->codec_type == AVMEDIA_TYPE_UNKNOWN || avctx->codec_type == codec->type) &&
avctx->codec_id == AV_CODEC_ID_NONE) {
avctx->codec_type = codec->type;
avctx->codec_id = codec->id;
}
if (avctx->codec_id != codec->id || (avctx->codec_type != codec->type
&& avctx->codec_type != AVMEDIA_TYPE_ATTACHMENT)) {
Michael Niedermayer
committed
av_log(avctx, AV_LOG_ERROR, "codec type or id mismatches\n");
Justin Ruggles
committed
ret = AVERROR(EINVAL);
Michael Niedermayer
committed
goto free_and_end;
Michael Niedermayer
committed
}
if ((avctx->codec->capabilities & AV_CODEC_CAP_EXPERIMENTAL) &&
avctx->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) {
ret = AVERROR_EXPERIMENTAL;
goto free_and_end;
}
if (avctx->codec_type == AVMEDIA_TYPE_AUDIO &&
(!avctx->time_base.num || !avctx->time_base.den)) {
avctx->time_base.num = 1;
avctx->time_base.den = avctx->sample_rate;
}
ret = ff_thread_init(avctx);
if (ret < 0) {
goto free_and_end;
}
}
if (!HAVE_THREADS && !(codec->capabilities & AV_CODEC_CAP_AUTO_THREADS))
avctx->thread_count = 1;
if (av_codec_is_encoder(avctx->codec)) {
#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) {
Justin Ruggles
committed
for (i = 0; avctx->codec->sample_fmts[i] != AV_SAMPLE_FMT_NONE; i++) {
if (avctx->sample_fmt == avctx->codec->sample_fmts[i])
break;
Justin Ruggles
committed
if (avctx->channels == 1 &&
av_get_planar_sample_fmt(avctx->sample_fmt) ==
av_get_planar_sample_fmt(avctx->codec->sample_fmts[i])) {
avctx->sample_fmt = avctx->codec->sample_fmts[i];
break;
}
}
if (avctx->codec->sample_fmts[i] == AV_SAMPLE_FMT_NONE) {
av_log(avctx, AV_LOG_ERROR, "Specified sample_fmt is not supported.\n");
ret = AVERROR(EINVAL);
goto free_and_end;
}