Newer
Older
* Copyright (c) 2001 Fabrice Bellard
Michael Niedermayer
committed
* Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at>
Diego Biurrun
committed
* This file is part of FFmpeg.
*
* FFmpeg 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.
Diego Biurrun
committed
* FFmpeg 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
Diego Biurrun
committed
* License along with FFmpeg; 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);
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;
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);
}
typedef struct InternalBuffer{
Michael Niedermayer
committed
int linesize[4];
Michael Niedermayer
committed
int width, height;
enum PixelFormat pix_fmt;
#define INTERNAL_BUFFER_SIZE (32+1)
Reimar Döffinger
committed
void avcodec_align_dimensions2(AVCodecContext *s, int *width, int *height, int linesize_align[4]){
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_YUV444P:
case PIX_FMT_GRAY8:
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_YUV422P10LE:
case PIX_FMT_YUV422P10BE:
case PIX_FMT_YUV444P9LE:
case PIX_FMT_YUV444P9BE:
case PIX_FMT_YUV444P10LE:
case PIX_FMT_YUV444P10BE:
w_align= 16; //FIXME check for non mpeg style codecs and use less alignment
h_align= 16;
if(s->codec_id == CODEC_ID_MPEG2VIDEO || s->codec_id == CODEC_ID_MJPEG || s->codec_id == CODEC_ID_AMV || s->codec_id == CODEC_ID_THP || s->codec_id == CODEC_ID_H264 || s->codec_id == CODEC_ID_PRORES)
h_align= 32; // interlaced is rounded up to 2 MBs
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
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
linesize_align[0] =
linesize_align[1] =
linesize_align[2] =
linesize_align[3] = STRIDE_ALIGN;
//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) {
linesize_align[0] =
linesize_align[1] =
linesize_align[2] = 16;
}
#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[4];
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);
int avcodec_default_get_buffer(AVCodecContext *s, AVFrame *pic){
Michael Niedermayer
committed
int *picture_number;
if(pic->data[0]!=NULL) {
av_log(s, AV_LOG_ERROR, "pic->data[0]!=NULL in avcodec_default_get_buffer\n");
return -1;
}
if(s->internal_buffer_count >= INTERNAL_BUFFER_SIZE) {
av_log(s, AV_LOG_ERROR, "internal_buffer_count overflow (missing release_buffer?)\n");
return -1;
}
if(av_image_check_size(w, h, 0, s))
s->internal_buffer= av_mallocz((INTERNAL_BUFFER_SIZE+1)*sizeof(InternalBuffer));
}
#if 0
s->internal_buffer= av_fast_realloc(
s->internal_buffer,
&s->internal_buffer_size,
sizeof(InternalBuffer)*FFMAX(99, s->internal_buffer_count+1)/*FIXME*/
);
#endif
buf= &((InternalBuffer*)s->internal_buffer)[s->internal_buffer_count];
picture_number= &(((InternalBuffer*)s->internal_buffer)[INTERNAL_BUFFER_SIZE]).last_pic_num; //FIXME ugly hack
Michael Niedermayer
committed
(*picture_number)++;
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;
}
Michael Niedermayer
committed
for(i=0; i<4; i++){
av_freep(&buf->base[i]);
buf->data[i]= NULL;
}
}
Michael Niedermayer
committed
pic->age= *picture_number - buf->last_pic_num;
buf->last_pic_num= *picture_number;
int size[4] = {0};
int tmpsize;
Reimar Döffinger
committed
int unaligned;
Michael Niedermayer
committed
int stride_align[4];
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]);
buf->last_pic_num= -256*256*256*64;
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]);
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<4; i++){
pic->base[i]= buf->base[i];
pic->data[i]= buf->data[i];
Michael Niedermayer
committed
pic->linesize[i]= buf->linesize[i];
}
s->internal_buffer_count++;
if (s->pkt) {
pic->pkt_pts = s->pkt->pts;
pic->pkt_pos = s->pkt->pos;
} else {
pic->pkt_pts = AV_NOPTS_VALUE;
pic->pkt_pos = -1;
}
pic->reordered_opaque= s->reordered_opaque;
pic->sample_aspect_ratio = s->sample_aspect_ratio;
pic->width = s->width;
pic->height = s->height;
pic->format = s->pix_fmt;
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, s->internal_buffer_count);
void avcodec_default_release_buffer(AVCodecContext *s, AVFrame *pic){
if(s->internal_buffer){
for(i=0; i<s->internal_buffer_count; i++){ //just 3-5 checks so is not worth to optimize
buf= &((InternalBuffer*)s->internal_buffer)[i];
if(buf->data[0] == pic->data[0])
break;
}
assert(i < s->internal_buffer_count);
s->internal_buffer_count--;
last = &((InternalBuffer*)s->internal_buffer)[s->internal_buffer_count];
FFSWAP(InternalBuffer, *buf, *last);
for(i=0; i<4; 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, s->internal_buffer_count);
int avcodec_default_reget_buffer(AVCodecContext *s, AVFrame *pic){
AVFrame temp_pic;
int i;
/* 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 < 4; 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 = pic->best_effort_timestamp = AV_NOPTS_VALUE;
pic->sample_aspect_ratio = (AVRational){0, 1};
AVFrame *pic= av_malloc(sizeof(AVFrame));
if(pic==NULL) return NULL;
avcodec_get_frame_defaults(pic);
static void avcodec_get_subtitle_defaults(AVSubtitle *sub)
{
memset(sub, 0, sizeof(*sub));
sub->pts = AV_NOPTS_VALUE;
}
#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
}
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
}
if (!HAVE_THREADS)
av_log(avctx, AV_LOG_WARNING, "Warning: not compiled with thread support, using thread emulation\n");
if (HAVE_THREADS && !avctx->thread_opaque) {
if (ret < 0) {
goto free_and_end;
}
}
if (avctx->codec->max_lowres < avctx->lowres || avctx->lowres < 0) {
av_log(avctx, AV_LOG_WARNING, "The maximum value for lowres supported by the decoder is %d\n",
avctx->lowres = avctx->codec->max_lowres;
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
avctx->pts_correction_num_faulty_pts =
avctx->pts_correction_num_faulty_dts = 0;
avctx->pts_correction_last_pts =
avctx->pts_correction_last_dts = INT64_MIN;
if(avctx->codec->init && !(avctx->active_thread_type&FF_THREAD_FRAME)){
Michael Niedermayer
committed
goto free_and_end;
ret=0;
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);
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;
}
Baptiste Coudurier
committed
ret = avctx->codec->encode(avctx, buf, buf_size, sub);
avctx->frame_number++;
return ret;
}
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
/**
* Attempt to guess proper monotonic timestamps for decoded video frames
* which might have incorrect times. Input timestamps may wrap around, in
* which case the output will as well.
*
* @param pts the pts field of the decoded AVPacket, as passed through
* AVFrame.pkt_pts
* @param dts the dts field of the decoded AVPacket
* @return one of the input values, may be AV_NOPTS_VALUE
*/
static int64_t guess_correct_pts(AVCodecContext *ctx,
int64_t reordered_pts, int64_t dts)
{
int64_t pts = AV_NOPTS_VALUE;
if (dts != AV_NOPTS_VALUE) {
ctx->pts_correction_num_faulty_dts += dts <= ctx->pts_correction_last_dts;
ctx->pts_correction_last_dts = dts;
}
if (reordered_pts != AV_NOPTS_VALUE) {
ctx->pts_correction_num_faulty_pts += reordered_pts <= ctx->pts_correction_last_pts;
ctx->pts_correction_last_pts = reordered_pts;
}
if ((ctx->pts_correction_num_faulty_pts<=ctx->pts_correction_num_faulty_dts || dts == AV_NOPTS_VALUE)
&& reordered_pts != AV_NOPTS_VALUE)
pts = reordered_pts;
else
pts = dts;
return pts;
}
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
if((avctx->codec->capabilities & CODEC_CAP_DELAY) || avpkt->size || (avctx->active_thread_type&FF_THREAD_FRAME)){
av_packet_split_side_data(avpkt);
avctx->pkt = avpkt;
if (HAVE_PTHREADS && 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;
Michael Niedermayer
committed
if(!avctx->has_b_frames){
}
//FIXME these should be under if(!avctx->has_b_frames)
if (!picture->sample_aspect_ratio.num)
picture->sample_aspect_ratio = avctx->sample_aspect_ratio;
if (!picture->width)
picture->width = avctx->width;
if (!picture->height)
picture->height = avctx->height;
if (picture->format == PIX_FMT_NONE)
picture->format = avctx->pix_fmt;
emms_c(); //needed to avoid an emms_c() call before every return;
Michael Niedermayer
committed
if (*got_picture_ptr){
avctx->frame_number++;
picture->best_effort_timestamp = guess_correct_pts(avctx,
picture->pkt_pts,
picture->pkt_dts);
}
Thilo Borgmann
committed
int attribute_align_arg avcodec_decode_audio3(AVCodecContext *avctx, int16_t *samples,
int *frame_size_ptr,
AVPacket *avpkt)
Michael Niedermayer
committed
avctx->pkt = avpkt;
Thilo Borgmann
committed
if((avctx->codec->capabilities & CODEC_CAP_DELAY) || avpkt->size){
//FIXME remove the check below _after_ ensuring that all audio check that the available space is enough
if(*frame_size_ptr < AVCODEC_MAX_AUDIO_FRAME_SIZE){
av_log(avctx, AV_LOG_ERROR, "buffer smaller than AVCODEC_MAX_AUDIO_FRAME_SIZE\n");
return -1;
}
if(*frame_size_ptr < FF_MIN_BUFFER_SIZE ||
*frame_size_ptr < avctx->channels * avctx->frame_size * sizeof(int16_t)){
av_log(avctx, AV_LOG_ERROR, "buffer %d too small\n", *frame_size_ptr);
return -1;
}
Thilo Borgmann
committed
ret = avctx->codec->decode(avctx, samples, frame_size_ptr, avpkt);
avctx->frame_number++;
Thilo Borgmann
committed
int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub,
int *got_sub_ptr,
AVPacket *avpkt)
Michael Niedermayer
committed
avctx->pkt = avpkt;
avcodec_get_subtitle_defaults(sub);
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;
if (avctx->codec && avctx->codec->priv_class)
av_opt_free(avctx->priv_data);
av_opt_free(avctx);
if(avctx->codec && avctx->codec->encode)
av_freep(&avctx->extradata);
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;
}
AVCodec *avcodec_find_encoder(enum CodecID id)
{
AVCodec *p, *experimental=NULL;
if (p->encode != NULL && p->id == id) {
if (p->capabilities & CODEC_CAP_EXPERIMENTAL && !experimental) {
experimental = p;
} else
return p;
}
return experimental;
AVCodec *avcodec_find_encoder_by_name(const char *name)
{
AVCodec *p;
if (!name)
return NULL;
p = first_avcodec;
while (p) {
if (p->encode != NULL && strcmp(name,p->name) == 0)
return p;
p = p->next;
}
return NULL;
}
AVCodec *p, *experimental=NULL;
if (p->decode != NULL && p->id == id) {
if (p->capabilities & CODEC_CAP_EXPERIMENTAL && !experimental) {
experimental = p;
} else
return p;
}
return experimental;
}
AVCodec *avcodec_find_decoder_by_name(const char *name)
{
AVCodec *p;
if (!name)
return NULL;
p = first_avcodec;
while (p) {
if (p->decode != NULL && strcmp(name,p->name) == 0)
return p;
p = p->next;
}
return NULL;
}
static int get_bit_rate(AVCodecContext *ctx)
{
int bit_rate;
int bits_per_sample;
switch(ctx->codec_type) {
case AVMEDIA_TYPE_VIDEO:
case AVMEDIA_TYPE_DATA:
case AVMEDIA_TYPE_SUBTITLE:
case AVMEDIA_TYPE_ATTACHMENT:
bit_rate = ctx->bit_rate;
break;
case AVMEDIA_TYPE_AUDIO:
bits_per_sample = av_get_bits_per_sample(ctx->codec_id);
bit_rate = bits_per_sample ? ctx->sample_rate * ctx->channels * bits_per_sample : ctx->bit_rate;
break;
default:
bit_rate = 0;
break;
}
return bit_rate;