X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Futils.c;h=255406ffddf7ada1ff88086a148d7753932424af;hb=5d9ad5425f1fae4876e30c2c4500bfd0950e0d88;hp=0190e6652c499869a49cd8ae74e5e7feec6bdfe6;hpb=31d76ec2883c04d29d1f173ea99e605a6936613a;p=ffmpeg diff --git a/libavcodec/utils.c b/libavcodec/utils.c index 0190e6652c4..255406ffddf 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -25,13 +25,15 @@ * utils. */ +#include "libavutil/avassert.h" #include "libavutil/avstring.h" -#include "libavutil/integer.h" #include "libavutil/crc.h" +#include "libavutil/mathematics.h" #include "libavutil/pixdesc.h" #include "libavutil/audioconvert.h" #include "libavutil/imgutils.h" #include "libavutil/samplefmt.h" +#include "libavutil/dict.h" #include "avcodec.h" #include "dsputil.h" #include "libavutil/opt.h" @@ -39,6 +41,7 @@ #include "thread.h" #include "audioconvert.h" #include "internal.h" +#include "bytestream.h" #include #include #include @@ -47,6 +50,7 @@ static int volatile entangled_thread_counter=0; static int (*ff_lockmgr_cb)(void **mutex, enum AVLockOp op); static void *codec_mutex; +static void *avformat_mutex; void *av_fast_realloc(void *ptr, unsigned int *size, size_t min_size) { @@ -76,6 +80,19 @@ void av_fast_malloc(void *ptr, unsigned int *size, size_t min_size) *size= min_size; } +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); +} + /* encoder management */ static AVCodec *first_avcodec = NULL; @@ -84,6 +101,27 @@ AVCodec *av_codec_next(AVCodec *c){ else return first_avcodec; } +static void avcodec_init(void) +{ + static int initialized = 0; + + if (initialized != 0) + return; + initialized = 1; + + ff_dsputil_static_init(); +} + +static av_always_inline int codec_is_encoder(AVCodec *codec) +{ + return codec && (codec->encode || codec->encode2); +} + +static av_always_inline int codec_is_decoder(AVCodec *codec) +{ + return codec && codec->decode; +} + void avcodec_register(AVCodec *codec) { AVCodec **p; @@ -92,6 +130,9 @@ 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); } unsigned avcodec_get_edge_width(void) @@ -106,18 +147,12 @@ void avcodec_set_dimensions(AVCodecContext *s, int width, int height){ s->height= -((-height)>>s->lowres); } -typedef struct InternalBuffer{ - int last_pic_num; - uint8_t *base[4]; - uint8_t *data[4]; - int linesize[4]; - int width, height; - enum PixelFormat pix_fmt; -}InternalBuffer; - -#define INTERNAL_BUFFER_SIZE 32 +#define INTERNAL_BUFFER_SIZE (32+1) -void avcodec_align_dimensions2(AVCodecContext *s, int *width, int *height, int linesize_align[4]){ +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; @@ -128,6 +163,7 @@ void avcodec_align_dimensions2(AVCodecContext *s, int *width, int *height, int l case PIX_FMT_YUV422P: case PIX_FMT_YUV440P: case PIX_FMT_YUV444P: + case PIX_FMT_GBRP: case PIX_FMT_GRAY8: case PIX_FMT_GRAY16BE: case PIX_FMT_GRAY16LE: @@ -136,10 +172,24 @@ void avcodec_align_dimensions2(AVCodecContext *s, int *width, int *height, int l case PIX_FMT_YUVJ440P: case PIX_FMT_YUVJ444P: case PIX_FMT_YUVA420P: - 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) - h_align= 32; // interlaced is rounded up to 2 MBs + 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 break; case PIX_FMT_YUV411P: case PIX_FMT_UYYVYY411: @@ -182,28 +232,13 @@ void avcodec_align_dimensions2(AVCodecContext *s, int *width, int *height, int l *height+=2; // some of the optimized chroma MC reads one line too much // which is also done in mpeg decoders with lowres > 0 - 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 + for (i = 0; i < 4; i++) + linesize_align[i] = STRIDE_ALIGN; } 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 linesize_align[AV_NUM_DATA_POINTERS]; int align; avcodec_align_dimensions2(s, width, height, linesize_align); align = FFMAX(linesize_align[0], linesize_align[3]); @@ -213,39 +248,148 @@ void avcodec_align_dimensions(AVCodecContext *s, int *width, int *height){ *width=FFALIGN(*width, align); } -int avcodec_default_get_buffer(AVCodecContext *s, AVFrame *pic){ +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 audio_get_buffer(AVCodecContext *avctx, AVFrame *frame) +{ + AVCodecInternal *avci = avctx->internal; + InternalBuffer *buf; + int buf_size, ret; + + buf_size = av_samples_get_buffer_size(NULL, avctx->channels, + frame->nb_samples, avctx->sample_fmt, + 32); + if (buf_size < 0) + return AVERROR(EINVAL); + + /* 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 (!buf->data[0]) { + if (!(buf->data[0] = av_mallocz(buf_size))) + return AVERROR(ENOMEM); + buf->audio_data_size = buf_size; + } + if ((ret = avcodec_fill_audio_frame(frame, avctx->channels, + avctx->sample_fmt, buf->data[0], + buf->audio_data_size, 32))) + return ret; + + if (frame->extended_data == frame->data) + buf->extended_data = buf->data; + else + buf->extended_data = frame->extended_data; + memcpy(buf->data, frame->data, sizeof(frame->data)); + buf->linesize[0] = frame->linesize[0]; + buf->nb_channels = avctx->channels; + } else { + /* copy InternalBuffer info to the AVFrame */ + frame->extended_data = buf->extended_data; + frame->linesize[0] = buf->linesize[0]; + memcpy(frame->data, buf->data, sizeof(frame->data)); + } + + frame->type = FF_BUFFER_TYPE_INTERNAL; + + 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) +{ int i; int w= s->width; int h= s->height; InternalBuffer *buf; - int *picture_number; + 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(s->internal_buffer_count >= INTERNAL_BUFFER_SIZE) { - av_log(s, AV_LOG_ERROR, "internal_buffer_count overflow (missing release_buffer?)\n"); + 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)) return -1; - if(s->internal_buffer==NULL){ - s->internal_buffer= av_mallocz((INTERNAL_BUFFER_SIZE+1)*sizeof(InternalBuffer)); + if (!avci->buffer) { + avci->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 - (*picture_number)++; + buf = &avci->buffer[avci->buffer_count]; if(buf->base[0] && (buf->width != w || buf->height != h || buf->pix_fmt != s->pix_fmt)){ if(s->active_thread_type&FF_THREAD_FRAME) { @@ -253,22 +397,20 @@ int avcodec_default_get_buffer(AVCodecContext *s, AVFrame *pic){ return -1; } - for(i=0; i<4; i++){ + for (i = 0; i < AV_NUM_DATA_POINTERS; i++) { av_freep(&buf->base[i]); buf->data[i]= NULL; } } - if(buf->base[0]){ - pic->age= *picture_number - buf->last_pic_num; - buf->last_pic_num= *picture_number; - }else{ + if (!buf->base[0]) { int h_chroma_shift, v_chroma_shift; int size[4] = {0}; int tmpsize; int unaligned; AVPicture picture; - int stride_align[4]; + 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); @@ -300,7 +442,6 @@ int avcodec_default_get_buffer(AVCodecContext *s, AVFrame *pic){ 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)); @@ -318,67 +459,93 @@ int avcodec_default_get_buffer(AVCodecContext *s, AVFrame *pic){ if((s->flags&CODEC_FLAG_EMU_EDGE) || !size[2]) buf->data[i] = buf->base[i]; else - buf->data[i] = buf->base[i] + FFALIGN((buf->linesize[i]*EDGE_WIDTH>>v_shift) + (EDGE_WIDTH>>h_shift), stride_align[i]); + 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); buf->width = s->width; buf->height = s->height; buf->pix_fmt= s->pix_fmt; - pic->age= 256*256*256*64; } pic->type= FF_BUFFER_TYPE_INTERNAL; - for(i=0; i<4; i++){ + for (i = 0; i < AV_NUM_DATA_POINTERS; i++) { pic->base[i]= buf->base[i]; pic->data[i]= buf->data[i]; pic->linesize[i]= buf->linesize[i]; } - s->internal_buffer_count++; + pic->extended_data = pic->data; + avci->buffer_count++; if(s->pkt) pic->pkt_pts= s->pkt->pts; else pic->pkt_pts= AV_NOPTS_VALUE; pic->reordered_opaque= s->reordered_opaque; 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); + av_log(s, AV_LOG_DEBUG, "default_get_buffer called on pic %p, %d " + "buffers used\n", pic, avci->buffer_count); return 0; } +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){ int i; InternalBuffer *buf, *last; + AVCodecInternal *avci = s->internal; + + assert(s->codec_type == AVMEDIA_TYPE_VIDEO); assert(pic->type==FF_BUFFER_TYPE_INTERNAL); - assert(s->internal_buffer_count); + assert(avci->buffer_count); - buf = NULL; /* avoids warning */ - for(i=0; iinternal_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]; + 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]; - FFSWAP(InternalBuffer, *buf, *last); + if (buf != last) + FFSWAP(InternalBuffer, *buf, *last); + } - for(i=0; i<4; i++){ + for (i = 0; i < AV_NUM_DATA_POINTERS; i++) { pic->data[i]=NULL; // pic->base[i]=NULL; } //printf("R%X\n", pic->opaque); 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); + 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 */ @@ -398,7 +565,7 @@ int avcodec_default_reget_buffer(AVCodecContext *s, AVFrame *pic){ * Not internal type and reget_buffer not overridden, emulate cr buffer */ temp_pic = *pic; - for(i = 0; i < 4; i++) + for(i = 0; i < AV_NUM_DATA_POINTERS; i++) pic->data[i] = pic->base[i] = NULL; pic->opaque = NULL; /* Allocate new frame */ @@ -442,6 +609,8 @@ void avcodec_get_frame_defaults(AVFrame *pic){ pic->pts= AV_NOPTS_VALUE; pic->key_frame= 1; + pic->sample_aspect_ratio = (AVRational){0, 1}; + pic->format = -1; /* unknown */ } AVFrame *avcodec_alloc_frame(void){ @@ -454,9 +623,31 @@ AVFrame *avcodec_alloc_frame(void){ return pic; } -int attribute_align_arg avcodec_open(AVCodecContext *avctx, AVCodec *codec) +int attribute_align_arg avcodec_open2(AVCodecContext *avctx, AVCodec *codec, AVDictionary **options) { 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 (ff_lockmgr_cb) { @@ -471,8 +662,9 @@ int attribute_align_arg avcodec_open(AVCodecContext *avctx, AVCodec *codec) goto end; } - if(avctx->codec || !codec) { - ret = AVERROR(EINVAL); + avctx->internal = av_mallocz(sizeof(AVCodecInternal)); + if (!avctx->internal) { + ret = AVERROR(ENOMEM); goto end; } @@ -483,14 +675,18 @@ int attribute_align_arg avcodec_open(AVCodecContext *avctx, AVCodec *codec) ret = AVERROR(ENOMEM); goto end; } - if(codec->priv_class){ //this can be droped once all user apps use avcodec_get_context_defaults3() + if (codec->priv_class) { *(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); @@ -506,7 +702,7 @@ int attribute_align_arg avcodec_open(AVCodecContext *avctx, AVCodec *codec) /* if the decoder init function was already called previously, free the already allocated subtitle_header before overwriting it */ - if (codec->decode) + if (codec_is_decoder(codec)) av_freep(&avctx->subtitle_header); #define SANE_NB_CHANNELS 128U @@ -529,12 +725,20 @@ int attribute_align_arg avcodec_open(AVCodecContext *avctx, AVCodec *codec) } avctx->frame_number = 0; + 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; + } + if (HAVE_THREADS && !avctx->thread_opaque) { ret = ff_thread_init(avctx); if (ret < 0) { goto free_and_end; } } + if (!HAVE_THREADS && !(codec->capabilities & CODEC_CAP_AUTO_THREADS)) + avctx->thread_count = 1; 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", @@ -542,15 +746,60 @@ int attribute_align_arg avcodec_open(AVCodecContext *avctx, AVCodec *codec) ret = AVERROR(EINVAL); goto free_and_end; } - if (avctx->codec->sample_fmts && avctx->codec->encode) { + if (codec_is_encoder(avctx->codec)) { int i; - 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->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->pix_fmts) { + for (i = 0; avctx->codec->pix_fmts[i] != PIX_FMT_NONE; i++) + if (avctx->pix_fmt == avctx->codec->pix_fmts[i]) + break; + if (avctx->codec->pix_fmts[i] == PIX_FMT_NONE) { + av_log(avctx, AV_LOG_ERROR, "Specified pix_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); } } @@ -567,45 +816,339 @@ end: if (ff_lockmgr_cb) { (*ff_lockmgr_cb)(&codec_mutex, AV_LOCK_RELEASE); } + if (options) { + av_dict_free(options); + *options = tmp; + } + return ret; free_and_end: + av_dict_free(&tmp); av_freep(&avctx->priv_data); + av_freep(&avctx->internal); avctx->codec= NULL; goto end; } -int attribute_align_arg avcodec_encode_audio(AVCodecContext *avctx, uint8_t *buf, int buf_size, - const short *samples) +int ff_alloc_packet(AVPacket *avpkt, int size) { - if(buf_size < FF_MIN_BUFFER_SIZE && 0){ - av_log(avctx, AV_LOG_ERROR, "buffer smaller than minimum size\n"); - return -1; + if (size > INT_MAX - FF_INPUT_BUFFER_PADDING_SIZE) + return AVERROR(EINVAL); + + if (avpkt->data) { + uint8_t *pkt_data; + + if (avpkt->size < size) + return AVERROR(EINVAL); + + pkt_data = avpkt->data; + av_init_packet(avpkt); + avpkt->data = pkt_data; + avpkt->size = size; + return 0; + } else { + return av_new_packet(avpkt, size); } - if((avctx->codec->capabilities & CODEC_CAP_DELAY) || samples){ - int ret = avctx->codec->encode(avctx, buf, buf_size, samples); - avctx->frame_number++; - return ret; - }else +} + +int attribute_align_arg avcodec_encode_audio2(AVCodecContext *avctx, + AVPacket *avpkt, + const AVFrame *frame, + int *got_packet_ptr) +{ + int ret; + int user_packet = !!avpkt->data; + int nb_samples; + + if (!(avctx->codec->capabilities & CODEC_CAP_DELAY) && !frame) { + av_init_packet(avpkt); + avpkt->size = 0; return 0; + } + + /* check for valid frame size */ + if (frame) { + nb_samples = frame->nb_samples; + if (avctx->codec->capabilities & CODEC_CAP_SMALL_LAST_FRAME) { + if (nb_samples > avctx->frame_size) + return AVERROR(EINVAL); + } else if (!(avctx->codec->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE)) { + if (nb_samples != avctx->frame_size) + return AVERROR(EINVAL); + } + } else { + nb_samples = avctx->frame_size; + } + + if (avctx->codec->encode2) { + *got_packet_ptr = 0; + ret = avctx->codec->encode2(avctx, avpkt, frame, got_packet_ptr); + if (!ret && *got_packet_ptr) { + if (!(avctx->codec->capabilities & CODEC_CAP_DELAY)) { + avpkt->pts = frame->pts; + avpkt->duration = av_rescale_q(frame->nb_samples, + (AVRational){ 1, avctx->sample_rate }, + avctx->time_base); + } + avpkt->dts = avpkt->pts; + } else { + avpkt->size = 0; + } + } else { + /* for compatibility with encoders not supporting encode2(), we need to + allocate a packet buffer if the user has not provided one or check + the size otherwise */ + int fs_tmp = 0; + int buf_size = avpkt->size; + if (!user_packet) { + if (avctx->codec->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE) { + av_assert0(av_get_bits_per_sample(avctx->codec_id) != 0); + buf_size = nb_samples * avctx->channels * + av_get_bits_per_sample(avctx->codec_id) / 8; + } else { + /* this is a guess as to the required size. + if an encoder needs more than this, it should probably + implement encode2() */ + buf_size = 2 * avctx->frame_size * avctx->channels * + av_get_bytes_per_sample(avctx->sample_fmt); + buf_size += FF_MIN_BUFFER_SIZE; + } + } + if ((ret = ff_alloc_packet(avpkt, buf_size))) + return ret; + + /* Encoders using AVCodec.encode() that support + CODEC_CAP_SMALL_LAST_FRAME require avctx->frame_size to be set to + the smaller size when encoding the last frame. + This code can be removed once all encoders supporting + CODEC_CAP_SMALL_LAST_FRAME use encode2() */ + if ((avctx->codec->capabilities & CODEC_CAP_SMALL_LAST_FRAME) && + nb_samples < avctx->frame_size) { + fs_tmp = avctx->frame_size; + avctx->frame_size = nb_samples; + } + + /* encode the frame */ + ret = avctx->codec->encode(avctx, avpkt->data, avpkt->size, + frame ? frame->data[0] : NULL); + if (ret >= 0) { + if (!ret) { + /* no output. if the packet data was allocated by libavcodec, + free it */ + if (!user_packet) + av_freep(&avpkt->data); + } else { + if (avctx->coded_frame) + avpkt->pts = avpkt->dts = avctx->coded_frame->pts; + /* Set duration for final small packet. This can be removed + once all encoders supporting CODEC_CAP_SMALL_LAST_FRAME use + encode2() */ + if (fs_tmp) { + avpkt->duration = av_rescale_q(avctx->frame_size, + (AVRational){ 1, avctx->sample_rate }, + avctx->time_base); + } + } + avpkt->size = ret; + *got_packet_ptr = (ret > 0); + ret = 0; + } + + if (fs_tmp) + avctx->frame_size = fs_tmp; + } + if (!ret) + avctx->frame_number++; + + /* NOTE: if we add any audio encoders which output non-keyframe packets, + this needs to be moved to the encoders, but for now we can do it + here to simplify things */ + avpkt->flags |= AV_PKT_FLAG_KEY; + + return ret; } +#if FF_API_OLD_DECODE_AUDIO +int attribute_align_arg avcodec_encode_audio(AVCodecContext *avctx, + uint8_t *buf, int buf_size, + const short *samples) +{ + AVPacket pkt; + AVFrame frame0; + AVFrame *frame; + int ret, samples_size, got_packet; + + av_init_packet(&pkt); + pkt.data = buf; + pkt.size = buf_size; + + if (samples) { + frame = &frame0; + avcodec_get_frame_defaults(frame); + + if (avctx->frame_size) { + frame->nb_samples = avctx->frame_size; + } else { + /* if frame_size is not set, the number of samples must be + calculated from the buffer size */ + int64_t nb_samples; + if (!av_get_bits_per_sample(avctx->codec_id)) { + av_log(avctx, AV_LOG_ERROR, "avcodec_encode_audio() does not " + "support this codec\n"); + return AVERROR(EINVAL); + } + nb_samples = (int64_t)buf_size * 8 / + (av_get_bits_per_sample(avctx->codec_id) * + avctx->channels); + if (nb_samples >= INT_MAX) + return AVERROR(EINVAL); + frame->nb_samples = nb_samples; + } + + /* it is assumed that the samples buffer is large enough based on the + relevant parameters */ + samples_size = av_samples_get_buffer_size(NULL, avctx->channels, + frame->nb_samples, + avctx->sample_fmt, 1); + if ((ret = avcodec_fill_audio_frame(frame, avctx->channels, + avctx->sample_fmt, + samples, samples_size, 1))) + return ret; + + /* fabricate frame pts from sample count. + this is needed because the avcodec_encode_audio() API does not have + a way for the user to provide pts */ + frame->pts = av_rescale_q(avctx->internal->sample_count, + (AVRational){ 1, avctx->sample_rate }, + avctx->time_base); + avctx->internal->sample_count += frame->nb_samples; + } else { + frame = NULL; + } + + got_packet = 0; + ret = avcodec_encode_audio2(avctx, &pkt, frame, &got_packet); + if (!ret && got_packet && avctx->coded_frame) { + avctx->coded_frame->pts = pkt.pts; + avctx->coded_frame->key_frame = !!(pkt.flags & AV_PKT_FLAG_KEY); + } + /* free any side data since we cannot return it */ + if (pkt.side_data_elems > 0) { + int i; + for (i = 0; i < pkt.side_data_elems; i++) + av_free(pkt.side_data[i].data); + av_freep(&pkt.side_data); + pkt.side_data_elems = 0; + } + + if (frame && frame->extended_data != frame->data) + av_free(frame->extended_data); + + return ret ? ret : pkt.size; +} +#endif + +#if FF_API_OLD_ENCODE_VIDEO int attribute_align_arg avcodec_encode_video(AVCodecContext *avctx, uint8_t *buf, int buf_size, const AVFrame *pict) { + AVPacket pkt; + int ret, got_packet = 0; + if(buf_size < FF_MIN_BUFFER_SIZE){ av_log(avctx, AV_LOG_ERROR, "buffer smaller than minimum size\n"); return -1; } - if(av_image_check_size(avctx->width, avctx->height, 0, avctx)) - return -1; - if((avctx->codec->capabilities & CODEC_CAP_DELAY) || pict){ - int ret = avctx->codec->encode(avctx, buf, buf_size, pict); - avctx->frame_number++; - emms_c(); //needed to avoid an emms_c() call before every return; - return ret; - }else + av_init_packet(&pkt); + pkt.data = buf; + pkt.size = buf_size; + + ret = avcodec_encode_video2(avctx, &pkt, pict, &got_packet); + if (!ret && got_packet && avctx->coded_frame) { + avctx->coded_frame->pts = pkt.pts; + avctx->coded_frame->key_frame = !!(pkt.flags & AV_PKT_FLAG_KEY); + } + + /* free any side data since we cannot return it */ + if (pkt.side_data_elems > 0) { + int i; + for (i = 0; i < pkt.side_data_elems; i++) + av_free(pkt.side_data[i].data); + av_freep(&pkt.side_data); + pkt.side_data_elems = 0; + } + + return ret ? ret : pkt.size; +} +#endif + +#define MAX_CODED_FRAME_SIZE(width, height)\ + (8*(width)*(height) + FF_MIN_BUFFER_SIZE) + +int attribute_align_arg avcodec_encode_video2(AVCodecContext *avctx, + AVPacket *avpkt, + const AVFrame *frame, + int *got_packet_ptr) +{ + int ret; + int user_packet = !!avpkt->data; + + if (!(avctx->codec->capabilities & CODEC_CAP_DELAY) && !frame) { + av_init_packet(avpkt); + avpkt->size = 0; + *got_packet_ptr = 0; return 0; + } + + if (av_image_check_size(avctx->width, avctx->height, 0, avctx)) + return AVERROR(EINVAL); + + if (avctx->codec->encode2) { + *got_packet_ptr = 0; + ret = avctx->codec->encode2(avctx, avpkt, frame, got_packet_ptr); + if (!ret) { + if (!*got_packet_ptr) + avpkt->size = 0; + else if (!(avctx->codec->capabilities & CODEC_CAP_DELAY)) + avpkt->pts = avpkt->dts = frame->pts; + } + } else { + /* for compatibility with encoders not supporting encode2(), we need to + allocate a packet buffer if the user has not provided one or check + the size otherwise */ + int buf_size = avpkt->size; + + if (!user_packet) + buf_size = MAX_CODED_FRAME_SIZE(avctx->width, avctx->height); + + if ((ret = ff_alloc_packet(avpkt, buf_size))) + return ret; + + /* encode the frame */ + ret = avctx->codec->encode(avctx, avpkt->data, avpkt->size, frame); + if (ret >= 0) { + if (!ret) { + /* no output. if the packet data was allocated by libavcodec, + free it */ + if (!user_packet) + av_freep(&avpkt->data); + } else if (avctx->coded_frame) { + avpkt->pts = avctx->coded_frame->pts; + avpkt->flags |= AV_PKT_FLAG_KEY*avctx->coded_frame->key_frame; + } + + avpkt->size = ret; + *got_packet_ptr = (ret > 0); + ret = 0; + } + } + + if (!ret) + avctx->frame_number++; + + emms_c(); + return ret; } int avcodec_encode_subtitle(AVCodecContext *avctx, uint8_t *buf, int buf_size, @@ -623,6 +1166,48 @@ int avcodec_encode_subtitle(AVCodecContext *avctx, uint8_t *buf, int buf_size, return ret; } +static void apply_param_change(AVCodecContext *avctx, AVPacket *avpkt) +{ + int size = 0; + const uint8_t *data; + uint32_t flags; + + if (!(avctx->codec->capabilities & CODEC_CAP_PARAM_CHANGE)) + return; + + data = av_packet_get_side_data(avpkt, AV_PKT_DATA_PARAM_CHANGE, &size); + if (!data || size < 4) + return; + flags = bytestream_get_le32(&data); + size -= 4; + if (size < 4) /* Required for any of the changes */ + return; + if (flags & AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT) { + avctx->channels = bytestream_get_le32(&data); + size -= 4; + } + if (flags & AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_LAYOUT) { + if (size < 8) + return; + avctx->channel_layout = bytestream_get_le64(&data); + size -= 8; + } + if (size < 4) + return; + if (flags & AV_SIDE_DATA_PARAM_CHANGE_SAMPLE_RATE) { + avctx->sample_rate = bytestream_get_le32(&data); + size -= 4; + } + if (flags & AV_SIDE_DATA_PARAM_CHANGE_DIMENSIONS) { + if (size < 8) + return; + avctx->width = bytestream_get_le32(&data); + avctx->height = bytestream_get_le32(&data); + avcodec_set_dimensions(avctx, avctx->width, avctx->height); + size -= 8; + } +} + int attribute_align_arg avcodec_decode_video2(AVCodecContext *avctx, AVFrame *picture, int *got_picture_ptr, AVPacket *avpkt) @@ -634,15 +1219,20 @@ int attribute_align_arg avcodec_decode_video2(AVCodecContext *avctx, AVFrame *pi return -1; avctx->pkt = avpkt; + apply_param_change(avctx, avpkt); if((avctx->codec->capabilities & CODEC_CAP_DELAY) || avpkt->size || (avctx->active_thread_type&FF_THREAD_FRAME)){ - if (HAVE_PTHREADS && 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; + picture->sample_aspect_ratio = avctx->sample_aspect_ratio; + picture->width = avctx->width; + picture->height = avctx->height; + picture->format = avctx->pix_fmt; } emms_c(); //needed to avoid an emms_c() call before every return; @@ -655,31 +1245,79 @@ int attribute_align_arg avcodec_decode_video2(AVCodecContext *avctx, AVFrame *pi return ret; } +#if FF_API_OLD_DECODE_AUDIO int attribute_align_arg avcodec_decode_audio3(AVCodecContext *avctx, int16_t *samples, int *frame_size_ptr, AVPacket *avpkt) { - int ret; - - avctx->pkt = avpkt; + AVFrame frame; + int ret, got_frame = 0; + + if (avctx->get_buffer != avcodec_default_get_buffer) { + av_log(avctx, AV_LOG_ERROR, "Custom get_buffer() for use with" + "avcodec_decode_audio3() detected. Overriding with avcodec_default_get_buffer\n"); + av_log(avctx, AV_LOG_ERROR, "Please port your application to " + "avcodec_decode_audio4()\n"); + avctx->get_buffer = avcodec_default_get_buffer; + } - 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; + 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); } - 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; + + 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 - ret = avctx->codec->decode(avctx, samples, frame_size_ptr, avpkt); - avctx->frame_number++; - }else{ - ret= 0; - *frame_size_ptr=0; +int attribute_align_arg avcodec_decode_audio4(AVCodecContext *avctx, + AVFrame *frame, + int *got_frame_ptr, + AVPacket *avpkt) +{ + int ret = 0; + + *got_frame_ptr = 0; + + avctx->pkt = avpkt; + + if (!avpkt->data && avpkt->size) { + av_log(avctx, AV_LOG_ERROR, "invalid packet: NULL data, size != 0\n"); + return AVERROR(EINVAL); + } + + apply_param_change(avctx, avpkt); + + 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; + if (frame->format == AV_SAMPLE_FMT_NONE) + frame->format = avctx->sample_fmt; + } } return ret; } @@ -733,14 +1371,21 @@ av_cold int avcodec_close(AVCodecContext *avctx) return -1; } - if (HAVE_THREADS && avctx->thread_opaque) - ff_thread_free(avctx); - if (avctx->codec && avctx->codec->close) - avctx->codec->close(avctx); - avcodec_default_free_buffers(avctx); - avctx->coded_frame = NULL; + if (avcodec_is_open(avctx)) { + if (HAVE_THREADS && avctx->thread_opaque) + ff_thread_free(avctx); + if (avctx->codec && avctx->codec->close) + avctx->codec->close(avctx); + avcodec_default_free_buffers(avctx); + avctx->coded_frame = NULL; + av_freep(&avctx->internal); + } + + if (avctx->priv_data && avctx->codec && avctx->codec->priv_class) + av_opt_free(avctx->priv_data); + av_opt_free(avctx); av_freep(&avctx->priv_data); - if(avctx->codec && avctx->codec->encode) + if (codec_is_encoder(avctx->codec)) av_freep(&avctx->extradata); avctx->codec = NULL; avctx->active_thread_type = 0; @@ -758,7 +1403,7 @@ AVCodec *avcodec_find_encoder(enum CodecID id) AVCodec *p, *experimental=NULL; p = first_avcodec; while (p) { - if (p->encode != NULL && p->id == id) { + if (codec_is_encoder(p) && p->id == id) { if (p->capabilities & CODEC_CAP_EXPERIMENTAL && !experimental) { experimental = p; } else @@ -776,7 +1421,7 @@ AVCodec *avcodec_find_encoder_by_name(const char *name) return NULL; p = first_avcodec; while (p) { - if (p->encode != NULL && strcmp(name,p->name) == 0) + if (codec_is_encoder(p) && strcmp(name,p->name) == 0) return p; p = p->next; } @@ -788,7 +1433,7 @@ AVCodec *avcodec_find_decoder(enum CodecID id) AVCodec *p; p = first_avcodec; while (p) { - if (p->decode != NULL && p->id == id) + if (codec_is_decoder(p) && p->id == id) return p; p = p->next; } @@ -802,7 +1447,7 @@ AVCodec *avcodec_find_decoder_by_name(const char *name) return NULL; p = first_avcodec; while (p) { - if (p->decode != NULL && strcmp(name,p->name) == 0) + if (codec_is_decoder(p) && strcmp(name,p->name) == 0) return p; p = p->next; } @@ -889,7 +1534,7 @@ void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode) if (enc->pix_fmt != PIX_FMT_NONE) { snprintf(buf + strlen(buf), buf_size - strlen(buf), ", %s", - avcodec_get_pix_fmt_name(enc->pix_fmt)); + av_get_pix_fmt_name(enc->pix_fmt)); } if (enc->width) { snprintf(buf + strlen(buf), buf_size - strlen(buf), @@ -992,54 +1637,65 @@ const char *avcodec_license(void) return LICENSE_PREFIX LIBAV_LICENSE + sizeof(LICENSE_PREFIX) - 1; } -void avcodec_init(void) -{ - static int initialized = 0; - - if (initialized != 0) - return; - initialized = 1; - - dsputil_static_init(); -} - void avcodec_flush_buffers(AVCodecContext *avctx) { - if(HAVE_PTHREADS && avctx->active_thread_type&FF_THREAD_FRAME) + if(HAVE_THREADS && avctx->active_thread_type&FF_THREAD_FRAME) ff_thread_flush(avctx); - if(avctx->codec->flush) + else if(avctx->codec->flush) avctx->codec->flush(avctx); } -void avcodec_default_free_buffers(AVCodecContext *s){ +static void video_free_buffers(AVCodecContext *s) +{ + AVCodecInternal *avci = s->internal; int i, j; - if(s->internal_buffer==NULL) return; + if (!avci->buffer) + return; - if (s->internal_buffer_count) - av_log(s, AV_LOG_WARNING, "Found %i unreleased buffers!\n", s->internal_buffer_count); + if (avci->buffer_count) + av_log(s, AV_LOG_WARNING, "Found %i unreleased buffers!\n", + avci->buffer_count); for(i=0; iinternal_buffer)[i]; + InternalBuffer *buf = &avci->buffer[i]; for(j=0; j<4; j++){ av_freep(&buf->base[j]); buf->data[j]= NULL; } } - av_freep(&s->internal_buffer); + av_freep(&avci->buffer); - s->internal_buffer_count=0; + avci->buffer_count=0; } -char av_get_pict_type_char(int pict_type){ - switch(pict_type){ - case FF_I_TYPE: return 'I'; - case FF_P_TYPE: return 'P'; - case FF_B_TYPE: return 'B'; - case FF_S_TYPE: return 'S'; - case FF_SI_TYPE:return 'i'; - case FF_SP_TYPE:return 'p'; - case FF_BI_TYPE:return 'b'; - default: return '?'; +static void audio_free_buffers(AVCodecContext *avctx) +{ + AVCodecInternal *avci = avctx->internal; + InternalBuffer *buf; + + if (!avci->buffer) + return; + buf = avci->buffer; + + if (buf->extended_data) { + av_free(buf->extended_data[0]); + if (buf->extended_data != buf->data) + av_free(buf->extended_data); + } + av_freep(&avci->buffer); +} + +void avcodec_default_free_buffers(AVCodecContext *avctx) +{ + switch (avctx->codec_type) { + case AVMEDIA_TYPE_VIDEO: + video_free_buffers(avctx); + break; + case AVMEDIA_TYPE_AUDIO: + audio_free_buffers(avctx); + break; + default: + break; } } @@ -1051,11 +1707,14 @@ int av_get_bits_per_sample(enum CodecID codec_id){ return 3; case CODEC_ID_ADPCM_SBPRO_4: case CODEC_ID_ADPCM_CT: + case CODEC_ID_ADPCM_IMA_APC: case CODEC_ID_ADPCM_IMA_WAV: + case CODEC_ID_ADPCM_IMA_QT: + case CODEC_ID_ADPCM_SWF: case CODEC_ID_ADPCM_MS: case CODEC_ID_ADPCM_YAMAHA: - return 4; case CODEC_ID_ADPCM_G722: + return 4; case CODEC_ID_PCM_ALAW: case CODEC_ID_PCM_MULAW: case CODEC_ID_PCM_S8: @@ -1089,12 +1748,6 @@ int av_get_bits_per_sample(enum CodecID codec_id){ } } -#if FF_API_OLD_SAMPLE_FMT -int av_get_bits_per_sample_format(enum AVSampleFormat sample_fmt) { - return av_get_bits_per_sample_fmt(sample_fmt); -} -#endif - #if !HAVE_THREADS int ff_thread_init(AVCodecContext *s){ return -1; @@ -1126,20 +1779,24 @@ void av_log_missing_feature(void *avc, const char *feature, int want_sample) av_log(avc, AV_LOG_WARNING, "%s not implemented. Update your Libav " "version to the newest one from Git. If the problem still " "occurs, it means that your file has a feature which has not " - "been implemented.", feature); + "been implemented.\n", feature); if(want_sample) av_log_ask_for_sample(avc, NULL); - else - av_log(avc, AV_LOG_WARNING, "\n"); } -void av_log_ask_for_sample(void *avc, const char *msg) +void av_log_ask_for_sample(void *avc, const char *msg, ...) { + va_list argument_list; + + va_start(argument_list, msg); + if (msg) - av_log(avc, AV_LOG_WARNING, "%s ", msg); + av_vlog(avc, AV_LOG_WARNING, msg, argument_list); av_log(avc, AV_LOG_WARNING, "If you want to help, upload a sample " "of this file to ftp://upload.libav.org/incoming/ " "and contact the libav-devel mailing list.\n"); + + va_end(argument_list); } static AVHWAccel *first_hwaccel = NULL; @@ -1175,6 +1832,8 @@ int av_lockmgr_register(int (*cb)(void **mutex, enum AVLockOp op)) if (ff_lockmgr_cb) { if (ff_lockmgr_cb(&codec_mutex, AV_LOCK_DESTROY)) return -1; + if (ff_lockmgr_cb(&avformat_mutex, AV_LOCK_DESTROY)) + return -1; } ff_lockmgr_cb = cb; @@ -1182,11 +1841,31 @@ int av_lockmgr_register(int (*cb)(void **mutex, enum AVLockOp op)) if (ff_lockmgr_cb) { if (ff_lockmgr_cb(&codec_mutex, AV_LOCK_CREATE)) return -1; + if (ff_lockmgr_cb(&avformat_mutex, AV_LOCK_CREATE)) + return -1; + } + return 0; +} + +int avpriv_lock_avformat(void) +{ + if (ff_lockmgr_cb) { + if ((*ff_lockmgr_cb)(&avformat_mutex, AV_LOCK_OBTAIN)) + return -1; } return 0; } -unsigned int ff_toupper4(unsigned int x) +int avpriv_unlock_avformat(void) +{ + if (ff_lockmgr_cb) { + if ((*ff_lockmgr_cb)(&avformat_mutex, AV_LOCK_RELEASE)) + return -1; + } + return 0; +} + +unsigned int avpriv_toupper4(unsigned int x) { return toupper( x &0xFF) + (toupper((x>>8 )&0xFF)<<8 ) @@ -1194,7 +1873,7 @@ unsigned int ff_toupper4(unsigned int x) + (toupper((x>>24)&0xFF)<<24); } -#if !HAVE_PTHREADS +#if !HAVE_THREADS int ff_thread_get_buffer(AVCodecContext *avctx, AVFrame *f) { @@ -1220,3 +1899,22 @@ void ff_thread_await_progress(AVFrame *f, int progress, int field) } #endif + +enum AVMediaType avcodec_get_type(enum CodecID codec_id) +{ + if (codec_id <= CODEC_ID_NONE) + return AVMEDIA_TYPE_UNKNOWN; + else if (codec_id < CODEC_ID_FIRST_AUDIO) + return AVMEDIA_TYPE_VIDEO; + else if (codec_id < CODEC_ID_FIRST_SUBTITLE) + return AVMEDIA_TYPE_AUDIO; + else if (codec_id < CODEC_ID_FIRST_UNKNOWN) + return AVMEDIA_TYPE_SUBTITLE; + + return AVMEDIA_TYPE_UNKNOWN; +} + +int avcodec_is_open(AVCodecContext *s) +{ + return !!s->internal; +}