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 "libavutil/avstring.h"
#include "libavutil/crc.h"
#include "libavutil/mathematics.h"
Reimar Döffinger
committed
#include "libavutil/pixdesc.h"
#include "libavutil/audioconvert.h"
#include "libavutil/imgutils.h"
#include "libavutil/samplefmt.h"
#include "libavutil/dict.h"
#include "libavutil/opt.h"
#include "thread.h"
#include "audioconvert.h"
#include "internal.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 (*ff_lockmgr_cb)(void **mutex, enum AVLockOp op);
static void *avformat_mutex;
void *av_fast_realloc(void *ptr, unsigned int *size, size_t min_size)
return ptr;
Michael Niedermayer
committed
min_size= FFMAX(17*min_size/16 + 32, min_size);
Michael Niedermayer
committed
ptr= av_realloc(ptr, min_size);
if(!ptr) //we could set this to the unmodified min_size but this is safer if the user lost the ptr and uses NULL now
Michael Niedermayer
committed
min_size= 0;
*size= min_size;
return ptr;
void av_fast_malloc(void *ptr, unsigned int *size, size_t min_size)
Reimar Döffinger
committed
{
void **p = ptr;
if (min_size < *size)
return;
Michael Niedermayer
committed
min_size= FFMAX(17*min_size/16 + 32, min_size);
Reimar Döffinger
committed
av_free(*p);
Michael Niedermayer
committed
*p = av_malloc(min_size);
if (!*p) min_size = 0;
*size= min_size;
Reimar Döffinger
committed
}
static AVCodec *first_avcodec = NULL;
AVCodec *av_codec_next(AVCodec *c){
if(c) return c->next;
else return first_avcodec;
}
#if !FF_API_AVCODEC_INIT
static
#endif
void avcodec_init(void)
{
static int initialized = 0;
if (initialized != 0)
return;
initialized = 1;
dsputil_static_init();
}
void avcodec_register(AVCodec *codec)
p = &first_avcodec;
while (*p != NULL) p = &(*p)->next;
*p = codec;
codec->next = NULL;
if (codec->init_static_data)
codec->init_static_data(codec);
unsigned avcodec_get_edge_width(void)
{
return EDGE_WIDTH;
}
void avcodec_set_dimensions(AVCodecContext *s, int width, int height){
s->coded_width = width;
s->coded_height= height;
s->width = -((-width )>>s->lowres);
s->height= -((-height)>>s->lowres);
}
#define INTERNAL_BUFFER_SIZE (32+1)
void avcodec_align_dimensions2(AVCodecContext *s, int *width, int *height,
int linesize_align[AV_NUM_DATA_POINTERS])
{
int i;
int w_align= 1;
int h_align= 1;
switch(s->pix_fmt){
case PIX_FMT_YUV420P:
case PIX_FMT_YUYV422:
case PIX_FMT_UYVY422:
case PIX_FMT_YUV440P:
case PIX_FMT_GRAY16BE:
case PIX_FMT_GRAY16LE:
case PIX_FMT_YUVJ420P:
case PIX_FMT_YUVJ422P:
case PIX_FMT_YUVJ440P:
case PIX_FMT_YUVA420P:
case PIX_FMT_YUV420P9LE:
case PIX_FMT_YUV420P9BE:
case PIX_FMT_YUV420P10LE:
case PIX_FMT_YUV420P10BE:
case PIX_FMT_YUV422P9LE:
case PIX_FMT_YUV422P9BE:
case PIX_FMT_YUV422P10LE:
case PIX_FMT_YUV422P10BE:
case PIX_FMT_YUV444P9LE:
case PIX_FMT_YUV444P9BE:
case PIX_FMT_YUV444P10LE:
case PIX_FMT_YUV444P10BE:
case PIX_FMT_GBRP9LE:
case PIX_FMT_GBRP9BE:
case PIX_FMT_GBRP10LE:
case PIX_FMT_GBRP10BE:
w_align = 16; //FIXME assume 16 pixel per macroblock
h_align = 16 * 2; // interlaced needs 2 macroblocks height
case PIX_FMT_UYYVYY411:
w_align=32;
h_align=8;
break;
case PIX_FMT_YUV410P:
if(s->codec_id == CODEC_ID_SVQ1){
w_align=64;
h_align=64;
}
case PIX_FMT_RGB555:
if(s->codec_id == CODEC_ID_RPZA){
w_align=4;
h_align=4;
}
case PIX_FMT_PAL8:
case PIX_FMT_BGR8:
case PIX_FMT_RGB8:
if(s->codec_id == CODEC_ID_SMC){
w_align=4;
h_align=4;
}
case PIX_FMT_BGR24:
if((s->codec_id == CODEC_ID_MSZH) || (s->codec_id == CODEC_ID_ZLIB)){
w_align=4;
h_align=4;
}
break;
default:
w_align= 1;
h_align= 1;
break;
}
*width = FFALIGN(*width , w_align);
*height= FFALIGN(*height, h_align);
if(s->codec_id == CODEC_ID_H264 || s->lowres)
*height+=2; // some of the optimized chroma MC reads one line too much
// which is also done in mpeg decoders with lowres > 0
Reimar Döffinger
committed
for (i = 0; i < AV_NUM_DATA_POINTERS; i++)
linesize_align[i] = STRIDE_ALIGN;
Reimar Döffinger
committed
//STRIDE_ALIGN is 8 for SSE* but this does not work for SVQ1 chroma planes
//we could change STRIDE_ALIGN to 16 for x86/sse but it would increase the
//picture size unneccessarily in some cases. The solution here is not
//pretty and better ideas are welcome!
#if HAVE_MMX
if(s->codec_id == CODEC_ID_SVQ1 || s->codec_id == CODEC_ID_VP5 ||
s->codec_id == CODEC_ID_VP6 || s->codec_id == CODEC_ID_VP6F ||
s->codec_id == CODEC_ID_VP6A) {
for (i = 0; i < AV_NUM_DATA_POINTERS; i++)
linesize_align[i] = 16;
Reimar Döffinger
committed
}
#endif
}
void avcodec_align_dimensions(AVCodecContext *s, int *width, int *height){
int chroma_shift = av_pix_fmt_descriptors[s->pix_fmt].log2_chroma_w;
int linesize_align[AV_NUM_DATA_POINTERS];
Reimar Döffinger
committed
int align;
avcodec_align_dimensions2(s, width, height, linesize_align);
align = FFMAX(linesize_align[0], linesize_align[3]);
linesize_align[1] <<= chroma_shift;
linesize_align[2] <<= chroma_shift;
align = FFMAX3(align, linesize_align[1], linesize_align[2]);
*width=FFALIGN(*width, align);
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
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
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
static int audio_get_buffer(AVCodecContext *avctx, AVFrame *frame)
{
AVCodecInternal *avci = avctx->internal;
InternalBuffer *buf;
int buf_size, ret, i, needs_extended_data;
buf_size = av_samples_get_buffer_size(NULL, avctx->channels,
frame->nb_samples, avctx->sample_fmt,
32);
if (buf_size < 0)
return AVERROR(EINVAL);
needs_extended_data = av_sample_fmt_is_planar(avctx->sample_fmt) &&
avctx->channels > AV_NUM_DATA_POINTERS;
/* allocate InternalBuffer if needed */
if (!avci->buffer) {
avci->buffer = av_mallocz(sizeof(InternalBuffer));
if (!avci->buffer)
return AVERROR(ENOMEM);
}
buf = avci->buffer;
/* if there is a previously-used internal buffer, check its size and
channel count to see if we can reuse it */
if (buf->extended_data) {
/* if current buffer is too small, free it */
if (buf->extended_data[0] && buf_size > buf->audio_data_size) {
av_free(buf->extended_data[0]);
if (buf->extended_data != buf->data)
av_free(&buf->extended_data);
buf->extended_data = NULL;
buf->data[0] = NULL;
}
/* if number of channels has changed, reset and/or free extended data
pointers but leave data buffer in buf->data[0] for reuse */
if (buf->nb_channels != avctx->channels) {
if (buf->extended_data != buf->data)
av_free(buf->extended_data);
buf->extended_data = NULL;
}
}
/* if there is no previous buffer or the previous buffer cannot be used
as-is, allocate a new buffer and/or rearrange the channel pointers */
if (!buf->extended_data) {
/* if the channel pointers will fit, just set extended_data to data,
otherwise allocate the extended_data channel pointers */
if (needs_extended_data) {
buf->extended_data = av_mallocz(avctx->channels *
sizeof(*buf->extended_data));
if (!buf->extended_data)
return AVERROR(ENOMEM);
} else {
buf->extended_data = buf->data;
}
/* if there is a previous buffer and it is large enough, reuse it and
just fill-in new channel pointers and linesize, otherwise allocate
a new buffer */
if (buf->extended_data[0]) {
ret = av_samples_fill_arrays(buf->extended_data, &buf->linesize[0],
buf->extended_data[0], avctx->channels,
frame->nb_samples, avctx->sample_fmt,
32);
} else {
ret = av_samples_alloc(buf->extended_data, &buf->linesize[0],
avctx->channels, frame->nb_samples,
avctx->sample_fmt, 32);
}
if (ret)
return ret;
/* if data was not used for extended_data, we need to copy as many of
the extended_data channel pointers as will fit */
if (needs_extended_data) {
for (i = 0; i < AV_NUM_DATA_POINTERS; i++)
buf->data[i] = buf->extended_data[i];
}
buf->audio_data_size = buf_size;
buf->nb_channels = avctx->channels;
}
/* copy InternalBuffer info to the AVFrame */
frame->type = FF_BUFFER_TYPE_INTERNAL;
frame->extended_data = buf->extended_data;
frame->linesize[0] = buf->linesize[0];
memcpy(frame->data, buf->data, sizeof(frame->data));
if (avctx->pkt) frame->pkt_pts = avctx->pkt->pts;
else frame->pkt_pts = AV_NOPTS_VALUE;
frame->reordered_opaque = avctx->reordered_opaque;
if (avctx->debug & FF_DEBUG_BUFFERS)
av_log(avctx, AV_LOG_DEBUG, "default_get_buffer called on frame %p, "
"internal audio buffer used\n", frame);
return 0;
}
static int video_get_buffer(AVCodecContext *s, AVFrame *pic)
{
AVCodecInternal *avci = s->internal;
if(pic->data[0]!=NULL) {
av_log(s, AV_LOG_ERROR, "pic->data[0]!=NULL in avcodec_default_get_buffer\n");
return -1;
}
if(avci->buffer_count >= INTERNAL_BUFFER_SIZE) {
av_log(s, AV_LOG_ERROR, "buffer_count overflow (missing release_buffer?)\n");
return -1;
}
if(av_image_check_size(w, h, 0, s))
if (!avci->buffer) {
avci->buffer = av_mallocz((INTERNAL_BUFFER_SIZE+1) *
sizeof(InternalBuffer));
buf = &avci->buffer[avci->buffer_count];
Michael Niedermayer
committed
if(buf->base[0] && (buf->width != w || buf->height != h || buf->pix_fmt != s->pix_fmt)){
if(s->active_thread_type&FF_THREAD_FRAME) {
av_log_missing_feature(s, "Width/height changing with frame threads is", 0);
return -1;
}
for (i = 0; i < AV_NUM_DATA_POINTERS; i++) {
Michael Niedermayer
committed
av_freep(&buf->base[i]);
buf->data[i]= NULL;
}
}
int size[4] = {0};
int tmpsize;
Reimar Döffinger
committed
int unaligned;
int stride_align[AV_NUM_DATA_POINTERS];
const int pixel_size = av_pix_fmt_descriptors[s->pix_fmt].comp[0].step_minus1+1;
avcodec_get_chroma_sub_sample(s->pix_fmt, &h_chroma_shift, &v_chroma_shift);
Reimar Döffinger
committed
avcodec_align_dimensions2(s, &w, &h, stride_align);
if(!(s->flags&CODEC_FLAG_EMU_EDGE)){
w+= EDGE_WIDTH*2;
h+= EDGE_WIDTH*2;
}
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, s->pix_fmt, w);
Reimar Döffinger
committed
// increase alignment of w for next try (rhs gives the lowest bit set in w)
w += w & ~(w-1);
Reimar Döffinger
committed
unaligned = 0;
Reimar Döffinger
committed
unaligned |= picture.linesize[i] % stride_align[i];
Reimar Döffinger
committed
} while (unaligned);
tmpsize = av_image_fill_pointers(picture.data, s->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]);
memset(buf->base, 0, sizeof(buf->base));
memset(buf->data, 0, sizeof(buf->data));
for(i=0; i<4 && size[i]; i++){
const int h_shift= i==0 ? 0 : h_chroma_shift;
const int v_shift= i==0 ? 0 : v_chroma_shift;
buf->linesize[i]= picture.linesize[i];
buf->base[i]= av_malloc(size[i]+16); //FIXME 16
if(buf->base[i]==NULL) return -1;
memset(buf->base[i], 128, size[i]);
if((s->flags&CODEC_FLAG_EMU_EDGE) || !size[2])
buf->data[i] = buf->base[i] + FFALIGN((buf->linesize[i]*EDGE_WIDTH>>v_shift) + (pixel_size*EDGE_WIDTH>>h_shift), stride_align[i]);
for (; i < AV_NUM_DATA_POINTERS; i++) {
buf->base[i] = buf->data[i] = NULL;
buf->linesize[i] = 0;
}
if(size[1] && !size[2])
ff_set_systematic_pal2((uint32_t*)buf->data[1], s->pix_fmt);
Michael Niedermayer
committed
buf->width = s->width;
buf->height = s->height;
buf->pix_fmt= s->pix_fmt;
Michael Niedermayer
committed
pic->type= FF_BUFFER_TYPE_INTERNAL;
for (i = 0; i < AV_NUM_DATA_POINTERS; i++) {
pic->base[i]= buf->base[i];
pic->data[i]= buf->data[i];
Michael Niedermayer
committed
pic->linesize[i]= buf->linesize[i];
avci->buffer_count++;
Michael Niedermayer
committed
if(s->pkt) pic->pkt_pts= s->pkt->pts;
else pic->pkt_pts= AV_NOPTS_VALUE;
pic->reordered_opaque= s->reordered_opaque;
Alexander Strange
committed
if(s->debug&FF_DEBUG_BUFFERS)
av_log(s, AV_LOG_DEBUG, "default_get_buffer called on pic %p, %d "
"buffers used\n", pic, avci->buffer_count);
Alexander Strange
committed
int avcodec_default_get_buffer(AVCodecContext *avctx, AVFrame *frame)
{
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;
}
}
void avcodec_default_release_buffer(AVCodecContext *s, AVFrame *pic){
AVCodecInternal *avci = s->internal;
assert(s->codec_type == AVMEDIA_TYPE_VIDEO);
assert(avci->buffer_count);
if (avci->buffer) {
buf = NULL; /* avoids warning */
for (i = 0; i < avci->buffer_count; i++) { //just 3-5 checks so is not worth to optimize
buf = &avci->buffer[i];
if (buf->data[0] == pic->data[0])
break;
}
assert(i < avci->buffer_count);
avci->buffer_count--;
last = &avci->buffer[avci->buffer_count];
if (buf != last)
FFSWAP(InternalBuffer, *buf, *last);
for (i = 0; i < AV_NUM_DATA_POINTERS; i++) {
Alexander Strange
committed
if(s->debug&FF_DEBUG_BUFFERS)
av_log(s, AV_LOG_DEBUG, "default_release_buffer called on pic %p, %d "
"buffers used\n", pic, avci->buffer_count);
int avcodec_default_reget_buffer(AVCodecContext *s, AVFrame *pic){
AVFrame temp_pic;
int i;
assert(s->codec_type == AVMEDIA_TYPE_VIDEO);
/* If no picture return a new buffer */
if(pic->data[0] == NULL) {
/* We will copy from buffer, so must be readable */
pic->buffer_hints |= FF_BUFFER_HINTS_READABLE;
return s->get_buffer(s, pic);
}
/* If internal buffer type return the same buffer */
if(pic->type == FF_BUFFER_TYPE_INTERNAL) {
if(s->pkt) pic->pkt_pts= s->pkt->pts;
else pic->pkt_pts= AV_NOPTS_VALUE;
pic->reordered_opaque= s->reordered_opaque;
}
/*
* Not internal type and reget_buffer not overridden, emulate cr buffer
*/
temp_pic = *pic;
for(i = 0; i < AV_NUM_DATA_POINTERS; i++)
pic->data[i] = pic->base[i] = NULL;
pic->opaque = NULL;
/* Allocate new frame */
if (s->get_buffer(s, pic))
return -1;
/* Copy image data from old buffer to new buffer */
Panagiotis Issaris
committed
av_picture_copy((AVPicture*)pic, (AVPicture*)&temp_pic, s->pix_fmt, s->width,
s->height);
s->release_buffer(s, &temp_pic); // Release old frame
return 0;
}
Roman Shaposhnik
committed
int avcodec_default_execute(AVCodecContext *c, int (*func)(AVCodecContext *c2, void *arg2),void *arg, int *ret, int count, int size){
int i;
for(i=0; i<count; i++){
Roman Shaposhnik
committed
int r= func(c, (char*)arg + i*size);
if(ret) ret[i]= r;
}
return 0;
}
Reimar Döffinger
committed
int avcodec_default_execute2(AVCodecContext *c, int (*func)(AVCodecContext *c2, void *arg2, int jobnr, int threadnr),void *arg, int *ret, int count){
int i;
for(i=0; i<count; i++){
int r= func(c, arg, i, 0);
if(ret) ret[i]= r;
}
return 0;
}
enum PixelFormat avcodec_default_get_format(struct AVCodecContext *s, const enum PixelFormat *fmt){
while (*fmt != PIX_FMT_NONE && ff_is_hwaccel_pix_fmt(*fmt))
++fmt;
void avcodec_get_frame_defaults(AVFrame *pic){
memset(pic, 0, sizeof(AVFrame));
pic->pts= AV_NOPTS_VALUE;
AVFrame *pic= av_malloc(sizeof(AVFrame));
if(pic==NULL) return NULL;
avcodec_get_frame_defaults(pic);
#if FF_API_AVCODEC_OPEN
int attribute_align_arg avcodec_open(AVCodecContext *avctx, AVCodec *codec)
{
return avcodec_open2(avctx, codec, NULL);
}
#endif
int attribute_align_arg avcodec_open2(AVCodecContext *avctx, AVCodec *codec, AVDictionary **options)
Justin Ruggles
committed
int ret = 0;
AVDictionary *tmp = NULL;
if (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))
return -1;
}
entangled_thread_counter++;
if(entangled_thread_counter != 1){
av_log(avctx, AV_LOG_ERROR, "insufficient thread locking around avcodec_open/close()\n");
Justin Ruggles
committed
ret = -1;
Justin Ruggles
committed
if(avctx->codec || !codec) {
ret = AVERROR(EINVAL);
Justin Ruggles
committed
}
avctx->internal = av_mallocz(sizeof(AVCodecInternal));
if (!avctx->internal) {
ret = AVERROR(ENOMEM);
goto end;
}
if (codec->priv_data_size > 0) {
Michael Niedermayer
committed
if(!avctx->priv_data){
avctx->priv_data = av_mallocz(codec->priv_data_size);
if (!avctx->priv_data) {
ret = AVERROR(ENOMEM);
}
if (codec->priv_class) {
Michael Niedermayer
committed
*(AVClass**)avctx->priv_data= codec->priv_class;
av_opt_set_defaults(avctx->priv_data);
}
}
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)
avcodec_set_dimensions(avctx, avctx->coded_width, avctx->coded_height);
else if(avctx->width && avctx->height)
avcodec_set_dimensions(avctx, avctx->width, avctx->height);
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");
avcodec_set_dimensions(avctx, 0, 0);
}
/* if the decoder init function was already called previously,
free the already allocated subtitle_header before overwriting it */
if (codec->decode)
av_freep(&avctx->subtitle_header);
#define SANE_NB_CHANNELS 128U
Reimar Döffinger
committed
if (avctx->channels > 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 == 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
}
Dustin Brody
committed
#if FF_API_ER
av_log(avctx, AV_LOG_DEBUG, "err{or,}_recognition separate: %d; %d\n",
avctx->error_recognition, avctx->err_recognition);
/* FF_ER_CAREFUL (==1) implies AV_EF_CRCCHECK (== 1<<1 - 1),
FF_ER_COMPLIANT (==2) implies AV_EF_{CRCCHECK,BITSTREAM} (== 1<<2 - 1), et cetera} */
avctx->err_recognition |= (1<<(avctx->error_recognition-(avctx->error_recognition>=FF_ER_VERY_AGGRESSIVE))) - 1;
av_log(avctx, AV_LOG_DEBUG, "err{or,}_recognition combined: %d; %d\n",
avctx->error_recognition, avctx->err_recognition);
#endif
if (HAVE_THREADS && !avctx->thread_opaque) {
ret = ff_thread_init(avctx);
if (ret < 0) {
goto free_and_end;
}
}
if (avctx->codec->max_lowres < avctx->lowres) {
av_log(avctx, AV_LOG_ERROR, "The maximum value for lowres supported by the decoder is %d\n",
avctx->codec->max_lowres);
Justin Ruggles
committed
ret = AVERROR(EINVAL);
if (avctx->codec->encode) {
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])
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;
}
}
if (avctx->codec->supported_samplerates) {
for (i = 0; avctx->codec->supported_samplerates[i] != 0; i++)
if (avctx->sample_rate == avctx->codec->supported_samplerates[i])
break;
if (avctx->codec->supported_samplerates[i] == 0) {
av_log(avctx, AV_LOG_ERROR, "Specified sample_rate is not supported\n");
ret = AVERROR(EINVAL);
goto free_and_end;
}
}
if (avctx->codec->channel_layouts) {
if (!avctx->channel_layout) {
av_log(avctx, AV_LOG_WARNING, "channel_layout not specified\n");
} else {
for (i = 0; avctx->codec->channel_layouts[i] != 0; i++)
if (avctx->channel_layout == avctx->codec->channel_layouts[i])
break;
if (avctx->codec->channel_layouts[i] == 0) {
av_log(avctx, AV_LOG_ERROR, "Specified channel_layout is not supported\n");
ret = AVERROR(EINVAL);
goto free_and_end;
}
}
}
if (avctx->channel_layout && avctx->channels) {
if (av_get_channel_layout_nb_channels(avctx->channel_layout) != avctx->channels) {
av_log(avctx, AV_LOG_ERROR, "channel layout does not match number of channels\n");
ret = AVERROR(EINVAL);
goto free_and_end;
}
} else if (avctx->channel_layout) {
avctx->channels = av_get_channel_layout_nb_channels(avctx->channel_layout);
}
Carl Eugen Hoyos
committed
if(avctx->codec->init && !(avctx->active_thread_type&FF_THREAD_FRAME)){
Michael Niedermayer
committed
goto free_and_end;
end:
entangled_thread_counter--;
/* Release any user-supplied mutex. */
if (ff_lockmgr_cb) {
(*ff_lockmgr_cb)(&codec_mutex, AV_LOCK_RELEASE);
}
if (options) {
av_dict_free(options);
*options = tmp;
}
Michael Niedermayer
committed
free_and_end:
av_dict_free(&tmp);
Michael Niedermayer
committed
av_freep(&avctx->priv_data);
av_freep(&avctx->internal);
Michael Niedermayer
committed
avctx->codec= NULL;
goto end;
int attribute_align_arg avcodec_encode_audio(AVCodecContext *avctx, uint8_t *buf, int buf_size,
if(buf_size < FF_MIN_BUFFER_SIZE && 0){
av_log(avctx, AV_LOG_ERROR, "buffer smaller than minimum size\n");
if((avctx->codec->capabilities & CODEC_CAP_DELAY) || samples){
Baptiste Coudurier
committed
int ret = avctx->codec->encode(avctx, buf, buf_size, samples);
avctx->frame_number++;
return ret;
}else
return 0;
int attribute_align_arg avcodec_encode_video(AVCodecContext *avctx, uint8_t *buf, int buf_size,
if(buf_size < FF_MIN_BUFFER_SIZE){
av_log(avctx, AV_LOG_ERROR, "buffer smaller than minimum size\n");
if(av_image_check_size(avctx->width, avctx->height, 0, avctx))
if((avctx->codec->capabilities & CODEC_CAP_DELAY) || pict){
Baptiste Coudurier
committed
int ret = avctx->codec->encode(avctx, buf, buf_size, pict);
emms_c(); //needed to avoid an emms_c() call before every return;
return ret;
}else
return 0;
int avcodec_encode_subtitle(AVCodecContext *avctx, uint8_t *buf, int buf_size,
if(sub->start_display_time) {
av_log(avctx, AV_LOG_ERROR, "start_display_time must be 0.\n");
return -1;
}
if(sub->num_rects == 0 || !sub->rects)
return -1;
Baptiste Coudurier
committed
ret = avctx->codec->encode(avctx, buf, buf_size, sub);
avctx->frame_number++;
return ret;
}
Thilo Borgmann
committed
int attribute_align_arg avcodec_decode_video2(AVCodecContext *avctx, AVFrame *picture,
int *got_picture_ptr,
AVPacket *avpkt)
if((avctx->coded_width||avctx->coded_height) && av_image_check_size(avctx->coded_width, avctx->coded_height, 0, avctx))
Michael Niedermayer
committed
avctx->pkt = avpkt;
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)
ret = ff_thread_decode_frame(avctx, picture, got_picture_ptr,
avpkt);
else {
ret = avctx->codec->decode(avctx, picture, got_picture_ptr,
avpkt);
picture->pkt_dts= avpkt->dts;
}
emms_c(); //needed to avoid an emms_c() call before every return;
avctx->frame_number++;
}else
ret= 0;
Thilo Borgmann
committed
int attribute_align_arg avcodec_decode_audio3(AVCodecContext *avctx, int16_t *samples,
int *frame_size_ptr,
AVPacket *avpkt)
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
AVFrame frame;
int ret, got_frame = 0;
if (avctx->get_buffer != avcodec_default_get_buffer) {
av_log(avctx, AV_LOG_ERROR, "A custom get_buffer() cannot be used with "
"avcodec_decode_audio3()\n");
return AVERROR(EINVAL);
}
ret = avcodec_decode_audio4(avctx, &frame, &got_frame, avpkt);
if (ret >= 0 && got_frame) {
int ch, plane_size;
int planar = av_sample_fmt_is_planar(avctx->sample_fmt);
int data_size = av_samples_get_buffer_size(&plane_size, avctx->channels,
frame.nb_samples,
avctx->sample_fmt, 1);
if (*frame_size_ptr < data_size) {
av_log(avctx, AV_LOG_ERROR, "output buffer size is too small for "
"the current frame (%d < %d)\n", *frame_size_ptr, data_size);
return AVERROR(EINVAL);
}
memcpy(samples, frame.extended_data[0], plane_size);
if (planar && avctx->channels > 1) {
uint8_t *out = ((uint8_t *)samples) + plane_size;
for (ch = 1; ch < avctx->channels; ch++) {
memcpy(out, frame.extended_data[ch], plane_size);
out += plane_size;
}
}
*frame_size_ptr = data_size;
} else {
*frame_size_ptr = 0;
}
return ret;
}
#endif
int attribute_align_arg avcodec_decode_audio4(AVCodecContext *avctx,
AVFrame *frame,
int *got_frame_ptr,
AVPacket *avpkt)
{
int ret = 0;
*got_frame_ptr = 0;
Michael Niedermayer
committed
avctx->pkt = avpkt;
if (!avpkt->data && avpkt->size) {
av_log(avctx, AV_LOG_ERROR, "invalid packet: NULL data, size != 0\n");
return AVERROR(EINVAL);
}
if ((avctx->codec->capabilities & CODEC_CAP_DELAY) || avpkt->size) {
ret = avctx->codec->decode(avctx, frame, got_frame_ptr, avpkt);
if (ret >= 0 && *got_frame_ptr) {
avctx->frame_number++;
frame->pkt_dts = avpkt->dts;
}
Thilo Borgmann
committed
int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub,
int *got_sub_ptr,
AVPacket *avpkt)
Michael Niedermayer
committed
avctx->pkt = avpkt;
Thilo Borgmann
committed
ret = avctx->codec->decode(avctx, sub, got_sub_ptr, avpkt);
if (*got_sub_ptr)
avctx->frame_number++;
return ret;
}
void avsubtitle_free(AVSubtitle *sub)
{
int i;
for (i = 0; i < sub->num_rects; i++)
{
av_freep(&sub->rects[i]->pict.data[0]);
av_freep(&sub->rects[i]->pict.data[1]);
av_freep(&sub->rects[i]->pict.data[2]);
av_freep(&sub->rects[i]->pict.data[3]);
av_freep(&sub->rects[i]->text);
av_freep(&sub->rects[i]->ass);
av_freep(&sub->rects[i]);
av_freep(&sub->rects);
memset(sub, 0, sizeof(AVSubtitle));
}
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;
}
Aurelien Jacobs
committed
if (HAVE_THREADS && avctx->thread_opaque)
Michael Niedermayer
committed
if (avctx->codec && avctx->codec->close)
avctx->coded_frame = NULL;
av_freep(&avctx->internal);
if (avctx->codec && avctx->codec->priv_class)
av_opt_free(avctx->priv_data);