X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Futils.c;h=3a30e734e44e587fb7367ca328a63ae584bea683;hb=3efd4952dfcc0e452d28910758876884925c6175;hp=d3244dfff3786ab2c1a1c1220270c3b0baaadb3d;hpb=0344cd0a7cc91e49637b85221a61aede8e9bd888;p=ffmpeg diff --git a/libavcodec/utils.c b/libavcodec/utils.c index d3244dfff37..3a30e734e44 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -1,57 +1,112 @@ /* * utils for libavcodec - * Copyright (c) 2001 Gerard Lantau. + * Copyright (c) 2001 Fabrice Bellard. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * This library 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 + * version 2 of the License, or (at your option) any later version. * - * This program is distributed in the hope that it will be useful, + * This library 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 General Public License for more details. + * 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 General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include -#include -#include -#include "common.h" -#include "dsputil.h" + +/** + * @file utils.c + * utils. + */ + #include "avcodec.h" -#ifdef HAVE_MALLOC_H -#include -#else -#include -#endif +#include "dsputil.h" +#include "mpegvideo.h" -/* memory alloc */ -void *av_mallocz(int size) +void *av_mallocz(unsigned int size) { void *ptr; -#if defined ( ARCH_X86 ) && defined ( HAVE_MEMALIGN ) - ptr = memalign(64,size); - /* Why 64? - Indeed, we should align it: - on 4 for 386 - on 16 for 486 - on 32 for 586, PPro - k6-III - on 64 for K7 (maybe for P3 too). - Because L1 and L2 caches are aligned on those values. - But I don't want to code such logic here! - */ -#else - ptr = malloc(size); -#endif + + ptr = av_malloc(size); if (!ptr) return NULL; memset(ptr, 0, size); return ptr; } +char *av_strdup(const char *s) +{ + char *ptr; + int len; + len = strlen(s) + 1; + ptr = av_malloc(len); + if (!ptr) + return NULL; + memcpy(ptr, s, len); + return ptr; +} + +/** + * realloc which does nothing if the block is large enough + */ +void *av_fast_realloc(void *ptr, unsigned int *size, unsigned int min_size) +{ + if(min_size < *size) + return ptr; + + *size= min_size + 10*1024; + + return av_realloc(ptr, *size); +} + + +/* allocation of static arrays - do not use for normal allocation */ +static unsigned int last_static = 0; +static char*** array_static = NULL; +static const unsigned int grow_static = 64; // ^2 +void *__av_mallocz_static(void** location, unsigned int size) +{ + unsigned int l = (last_static + grow_static) & ~(grow_static - 1); + void *ptr = av_mallocz(size); + if (!ptr) + return NULL; + + if (location) + { + if (l > last_static) + array_static = av_realloc(array_static, l); + array_static[last_static++] = (char**) location; + *location = ptr; + } + return ptr; +} +/* free all static arrays and reset pointers to 0 */ +void av_free_static(void) +{ + if (array_static) + { + unsigned i; + for (i = 0; i < last_static; i++) + { + av_free(*array_static[i]); + *array_static[i] = NULL; + } + av_free(array_static); + array_static = 0; + } + last_static = 0; +} + +/* cannot call it directly because of 'void **' casting is not automatic */ +void __av_freep(void **ptr) +{ + av_free(*ptr); + *ptr = NULL; +} + /* encoder management */ AVCodec *first_avcodec; @@ -64,25 +119,209 @@ void register_avcodec(AVCodec *format) format->next = NULL; } +typedef struct InternalBuffer{ + int last_pic_num; + uint8_t *base[4]; + uint8_t *data[4]; +}InternalBuffer; + +#define INTERNAL_BUFFER_SIZE 32 + +int avcodec_default_get_buffer(AVCodecContext *s, AVFrame *pic){ + int i; + const int width = s->width; + const int height= s->height; + InternalBuffer *buf; + + assert(pic->data[0]==NULL); + assert(INTERNAL_BUFFER_SIZE > s->internal_buffer_count); + + if(s->internal_buffer==NULL){ + s->internal_buffer= av_mallocz(INTERNAL_BUFFER_SIZE*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]; + + if(buf->base[0]){ + pic->age= pic->coded_picture_number - buf->last_pic_num; + buf->last_pic_num= pic->coded_picture_number; + }else{ + int align, h_chroma_shift, v_chroma_shift; + int w, h, pixel_size; + + avcodec_get_chroma_sub_sample(s->pix_fmt, &h_chroma_shift, &v_chroma_shift); + switch(s->pix_fmt){ + case PIX_FMT_RGB555: + case PIX_FMT_RGB565: + case PIX_FMT_YUV422: + pixel_size=2; + break; + case PIX_FMT_RGB24: + case PIX_FMT_BGR24: + pixel_size=3; + break; + case PIX_FMT_RGBA32: + pixel_size=4; + break; + default: + pixel_size=1; + } + + if(s->codec_id==CODEC_ID_SVQ1) align=63; + else align=15; + + w= (width +align)&~align; + h= (height+align)&~align; + + if(!(s->flags&CODEC_FLAG_EMU_EDGE)){ + w+= EDGE_WIDTH*2; + h+= EDGE_WIDTH*2; + } + + buf->last_pic_num= -256*256*256*64; + + for(i=0; i<3; i++){ + const int h_shift= i==0 ? 0 : h_chroma_shift; + const int v_shift= i==0 ? 0 : v_chroma_shift; + + pic->linesize[i]= pixel_size*w>>h_shift; + + buf->base[i]= av_mallocz((pic->linesize[i]*h>>v_shift)+16); //FIXME 16 + if(buf->base[i]==NULL) return -1; + memset(buf->base[i], 128, pic->linesize[i]*h>>v_shift); + + if(s->flags&CODEC_FLAG_EMU_EDGE) + buf->data[i] = buf->base[i]; + else + buf->data[i] = buf->base[i] + (pic->linesize[i]*EDGE_WIDTH>>v_shift) + (EDGE_WIDTH>>h_shift); + } + pic->age= 256*256*256*64; + pic->type= FF_BUFFER_TYPE_INTERNAL; + } + + for(i=0; i<4; i++){ + pic->base[i]= buf->base[i]; + pic->data[i]= buf->data[i]; + } + s->internal_buffer_count++; + + return 0; +} + +void avcodec_default_release_buffer(AVCodecContext *s, AVFrame *pic){ + int i; + InternalBuffer *buf, *last, temp; + + assert(pic->type==FF_BUFFER_TYPE_INTERNAL); + + 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]; + + temp= *buf; + *buf= *last; + *last= temp; + + for(i=0; i<3; i++){ + pic->data[i]=NULL; +// pic->base[i]=NULL; + } +//printf("R%X\n", pic->opaque); +} + +enum PixelFormat avcodec_default_get_format(struct AVCodecContext *s, enum PixelFormat * fmt){ + return fmt[0]; +} + +void avcodec_get_context_defaults(AVCodecContext *s){ + s->bit_rate= 800*1000; + s->bit_rate_tolerance= s->bit_rate*10; + s->qmin= 2; + s->qmax= 31; + s->mb_qmin= 2; + s->mb_qmax= 31; + s->rc_eq= "tex^qComp"; + s->qcompress= 0.5; + s->max_qdiff= 3; + s->b_quant_factor=1.25; + s->b_quant_offset=1.25; + s->i_quant_factor=-0.8; + s->i_quant_offset=0.0; + s->error_concealment= 3; + s->error_resilience= 1; + s->workaround_bugs= FF_BUG_AUTODETECT; + s->frame_rate_base= 1; + s->frame_rate = 25; + s->gop_size= 50; + s->me_method= ME_EPZS; + s->get_buffer= avcodec_default_get_buffer; + s->release_buffer= avcodec_default_release_buffer; + s->get_format= avcodec_default_get_format; + s->me_subpel_quality=8; + + s->intra_quant_bias= FF_DEFAULT_QUANT_BIAS; + s->inter_quant_bias= FF_DEFAULT_QUANT_BIAS; +} + +/** + * allocates a AVCodecContext and set it to defaults. + * this can be deallocated by simply calling free() + */ +AVCodecContext *avcodec_alloc_context(void){ + AVCodecContext *avctx= av_mallocz(sizeof(AVCodecContext)); + + if(avctx==NULL) return NULL; + + avcodec_get_context_defaults(avctx); + + return avctx; +} + +/** + * allocates a AVPFrame and set it to defaults. + * this can be deallocated by simply calling free() + */ +AVFrame *avcodec_alloc_frame(void){ + AVFrame *pic= av_mallocz(sizeof(AVFrame)); + + return pic; +} + int avcodec_open(AVCodecContext *avctx, AVCodec *codec) { int ret; avctx->codec = codec; + avctx->codec_id = codec->id; avctx->frame_number = 0; - avctx->priv_data = av_mallocz(codec->priv_data_size); - if (!avctx->priv_data) - return -ENOMEM; + if (codec->priv_data_size > 0) { + avctx->priv_data = av_mallocz(codec->priv_data_size); + if (!avctx->priv_data) + return -ENOMEM; + } else { + avctx->priv_data = NULL; + } ret = avctx->codec->init(avctx); if (ret < 0) { - free(avctx->priv_data); - avctx->priv_data = NULL; + av_freep(&avctx->priv_data); return ret; } return 0; } -int avcodec_encode_audio(AVCodecContext *avctx, UINT8 *buf, int buf_size, +int avcodec_encode_audio(AVCodecContext *avctx, uint8_t *buf, int buf_size, const short *samples) { int ret; @@ -92,27 +331,39 @@ int avcodec_encode_audio(AVCodecContext *avctx, UINT8 *buf, int buf_size, return ret; } -int avcodec_encode_video(AVCodecContext *avctx, UINT8 *buf, int buf_size, - const AVPicture *pict) +int avcodec_encode_video(AVCodecContext *avctx, uint8_t *buf, int buf_size, + const AVFrame *pict) { int ret; ret = avctx->codec->encode(avctx, buf, buf_size, (void *)pict); + + emms_c(); //needed to avoid a emms_c() call before every return; + avctx->frame_number++; return ret; } -/* decode a frame. return -1 if error, otherwise return the number of - bytes used. If no frame could be decompressed, *got_picture_ptr is - zero. Otherwise, it is non zero */ -int avcodec_decode_video(AVCodecContext *avctx, AVPicture *picture, +/** + * decode a frame. + * @param buf bitstream buffer, must be FF_INPUT_BUFFER_PADDING_SIZE larger then the actual read bytes + * because some optimized bitstream readers read 32 or 64 bit at once and could read over the end + * @param buf_size the size of the buffer in bytes + * @param got_picture_ptr zero if no frame could be decompressed, Otherwise, it is non zero + * @return -1 if error, otherwise return the number of + * bytes used. + */ +int avcodec_decode_video(AVCodecContext *avctx, AVFrame *picture, int *got_picture_ptr, - UINT8 *buf, int buf_size) + uint8_t *buf, int buf_size) { int ret; - + ret = avctx->codec->decode(avctx, picture, got_picture_ptr, buf, buf_size); + + emms_c(); //needed to avoid a emms_c() call before every return; + if (*got_picture_ptr) avctx->frame_number++; return ret; @@ -122,9 +373,9 @@ int avcodec_decode_video(AVCodecContext *avctx, AVPicture *picture, *number of bytes used. If no frame could be decompressed, *frame_size_ptr is zero. Otherwise, it is the decompressed frame *size in BYTES. */ -int avcodec_decode_audio(AVCodecContext *avctx, INT16 *samples, +int avcodec_decode_audio(AVCodecContext *avctx, int16_t *samples, int *frame_size_ptr, - UINT8 *buf, int buf_size) + uint8_t *buf, int buf_size) { int ret; @@ -138,8 +389,7 @@ int avcodec_close(AVCodecContext *avctx) { if (avctx->codec->close) avctx->codec->close(avctx); - free(avctx->priv_data); - avctx->priv_data = NULL; + av_freep(&avctx->priv_data); avctx->codec = NULL; return 0; } @@ -204,20 +454,12 @@ AVCodec *avcodec_find(enum CodecID id) return NULL; } -const char *pix_fmt_str[] = { - "yuv420p", - "yuv422", - "rgb24", - "bgr24", - "yuv422p", - "yuv444p", -}; - void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode) { const char *codec_name; AVCodec *p; char buf1[32]; + char channels_str[100]; int bitrate; if (encode) @@ -251,13 +493,17 @@ void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode) if (enc->codec_id == CODEC_ID_RAWVIDEO) { snprintf(buf + strlen(buf), buf_size - strlen(buf), ", %s", - pix_fmt_str[enc->pix_fmt]); + avcodec_get_pix_fmt_name(enc->pix_fmt)); } if (enc->width) { snprintf(buf + strlen(buf), buf_size - strlen(buf), ", %dx%d, %0.2f fps", enc->width, enc->height, - (float)enc->frame_rate / FRAME_RATE_BASE); + (float)enc->frame_rate / enc->frame_rate_base); + } + if (encode) { + snprintf(buf + strlen(buf), buf_size - strlen(buf), + ", q=%d-%d", enc->qmin, enc->qmax); } bitrate = enc->bit_rate; break; @@ -265,12 +511,27 @@ void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode) snprintf(buf, buf_size, "Audio: %s", codec_name); + switch (enc->channels) { + case 1: + strcpy(channels_str, "mono"); + break; + case 2: + strcpy(channels_str, "stereo"); + break; + case 6: + strcpy(channels_str, "5:1"); + break; + default: + sprintf(channels_str, "%d channels", enc->channels); + break; + } if (enc->sample_rate) { snprintf(buf + strlen(buf), buf_size - strlen(buf), ", %d Hz, %s", enc->sample_rate, - enc->channels == 2 ? "stereo" : "mono"); + channels_str); } + /* for PCM codecs, compute bitrate directly */ switch(enc->codec_id) { case CODEC_ID_PCM_S16LE: @@ -291,7 +552,15 @@ void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode) } break; default: - abort(); + av_abort(); + } + if (encode) { + if (enc->flags & CODEC_FLAG_PASS1) + snprintf(buf + strlen(buf), buf_size - strlen(buf), + ", pass 1"); + if (enc->flags & CODEC_FLAG_PASS2) + snprintf(buf + strlen(buf), buf_size - strlen(buf), + ", pass 2"); } if (bitrate != 0) { snprintf(buf + strlen(buf), buf_size - strlen(buf), @@ -299,89 +568,16 @@ void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode) } } -/* Picture field are filled with 'ptr' addresses */ -void avpicture_fill(AVPicture *picture, UINT8 *ptr, - int pix_fmt, int width, int height) +unsigned avcodec_version( void ) { - int size; - - size = width * height; - switch(pix_fmt) { - case PIX_FMT_YUV420P: - picture->data[0] = ptr; - picture->data[1] = picture->data[0] + size; - picture->data[2] = picture->data[1] + size / 4; - picture->linesize[0] = width; - picture->linesize[1] = width / 2; - picture->linesize[2] = width / 2; - break; - case PIX_FMT_YUV422P: - picture->data[0] = ptr; - picture->data[1] = picture->data[0] + size; - picture->data[2] = picture->data[1] + size / 2; - picture->linesize[0] = width; - picture->linesize[1] = width / 2; - picture->linesize[2] = width / 2; - break; - case PIX_FMT_YUV444P: - picture->data[0] = ptr; - picture->data[1] = picture->data[0] + size; - picture->data[2] = picture->data[1] + size; - picture->linesize[0] = width; - picture->linesize[1] = width; - picture->linesize[2] = width; - break; - case PIX_FMT_RGB24: - case PIX_FMT_BGR24: - picture->data[0] = ptr; - picture->data[1] = NULL; - picture->data[2] = NULL; - picture->linesize[0] = width * 3; - break; - case PIX_FMT_YUV422: - picture->data[0] = ptr; - picture->data[1] = NULL; - picture->data[2] = NULL; - picture->linesize[0] = width * 2; - break; - default: - picture->data[0] = NULL; - picture->data[1] = NULL; - picture->data[2] = NULL; - break; - } + return LIBAVCODEC_VERSION_INT; } -int avpicture_get_size(int pix_fmt, int width, int height) +unsigned avcodec_build( void ) { - int size; - - size = width * height; - switch(pix_fmt) { - case PIX_FMT_YUV420P: - size = (size * 3) / 2; - break; - case PIX_FMT_YUV422P: - size = (size * 2); - break; - case PIX_FMT_YUV444P: - size = (size * 3); - break; - case PIX_FMT_RGB24: - case PIX_FMT_BGR24: - size = (size * 3); - break; - case PIX_FMT_YUV422: - size = (size * 2); - break; - default: - size = -1; - break; - } - return size; + return LIBAVCODEC_BUILD; } - /* must be called before any other functions */ void avcodec_init(void) { @@ -391,93 +587,127 @@ void avcodec_init(void) return; inited = 1; - dsputil_init(); + dsputil_static_init(); } -/* simple call to use all the codecs */ -void avcodec_register_all(void) +/* this can be called after seeking and before trying to decode the next keyframe */ +void avcodec_flush_buffers(AVCodecContext *avctx) { - static int inited = 0; + int i; + MpegEncContext *s = avctx->priv_data; - if (inited != 0) - return; - inited = 1; + switch(avctx->codec_id){ + case CODEC_ID_MPEG1VIDEO: + case CODEC_ID_H263: + case CODEC_ID_RV10: +// case CODEC_ID_MJPEG: +// case CODEC_ID_MJPEGB: + case CODEC_ID_MPEG4: + case CODEC_ID_MSMPEG4V1: + case CODEC_ID_MSMPEG4V2: + case CODEC_ID_MSMPEG4V3: + case CODEC_ID_WMV1: + case CODEC_ID_WMV2: + case CODEC_ID_H263P: + case CODEC_ID_H263I: + case CODEC_ID_SVQ1: + for(i=0; ipicture[i].data[0] && ( s->picture[i].type == FF_BUFFER_TYPE_INTERNAL + || s->picture[i].type == FF_BUFFER_TYPE_USER)) + avctx->release_buffer(avctx, (AVFrame*)&s->picture[i]); + } + s->last_picture_ptr = s->next_picture_ptr = NULL; + break; + default: + //FIXME + break; + } +} - /* encoders */ -#ifdef CONFIG_ENCODERS - register_avcodec(&ac3_encoder); - register_avcodec(&mp2_encoder); -#ifdef CONFIG_MP3LAME - register_avcodec(&mp3lame_encoder); -#endif - register_avcodec(&mpeg1video_encoder); - register_avcodec(&h263_encoder); - register_avcodec(&h263p_encoder); - register_avcodec(&rv10_encoder); - register_avcodec(&mjpeg_encoder); - register_avcodec(&mpeg4_encoder); - register_avcodec(&msmpeg4_encoder); -#endif /* CONFIG_ENCODERS */ - register_avcodec(&rawvideo_codec); - - /* decoders */ -#ifdef CONFIG_DECODERS - register_avcodec(&h263_decoder); - register_avcodec(&mpeg4_decoder); - register_avcodec(&msmpeg4_decoder); - register_avcodec(&mpeg_decoder); - register_avcodec(&h263i_decoder); - register_avcodec(&rv10_decoder); - register_avcodec(&mjpeg_decoder); - register_avcodec(&mp3_decoder); -#ifdef CONFIG_AC3 - register_avcodec(&ac3_decoder); -#endif -#endif /* CONFIG_DECODERS */ +void avcodec_default_free_buffers(AVCodecContext *s){ + int i, j; - /* pcm codecs */ + if(s->internal_buffer==NULL) return; + + for(i=0; iinternal_buffer)[i]; + for(j=0; j<4; j++){ + av_freep(&buf->base[j]); + buf->data[j]= NULL; + } + } + av_freep(&s->internal_buffer); + + s->internal_buffer_count=0; +} -#define PCM_CODEC(id, name) \ - register_avcodec(& name ## _encoder); \ - register_avcodec(& name ## _decoder); \ +char av_get_pict_type_char(int pict_type){ + switch(pict_type){ + case I_TYPE: return 'I'; + case P_TYPE: return 'P'; + case B_TYPE: return 'B'; + case S_TYPE: return 'S'; + case SI_TYPE:return 'i'; + case SP_TYPE:return 'p'; + default: return '?'; + } +} -PCM_CODEC(CODEC_ID_PCM_S16LE, pcm_s16le); -PCM_CODEC(CODEC_ID_PCM_S16BE, pcm_s16be); -PCM_CODEC(CODEC_ID_PCM_U16LE, pcm_u16le); -PCM_CODEC(CODEC_ID_PCM_U16BE, pcm_u16be); -PCM_CODEC(CODEC_ID_PCM_S8, pcm_s8); -PCM_CODEC(CODEC_ID_PCM_U8, pcm_u8); -PCM_CODEC(CODEC_ID_PCM_ALAW, pcm_alaw); -PCM_CODEC(CODEC_ID_PCM_MULAW, pcm_mulaw); +int av_reduce(int *dst_nom, int *dst_den, int64_t nom, int64_t den, int64_t max){ + int exact=1, sign=0; + int64_t gcd, larger; -#undef PCM_CODEC -} + assert(den != 0); -static int encode_init(AVCodecContext *s) -{ - return 0; + if(den < 0){ + den= -den; + nom= -nom; + } + + if(nom < 0){ + nom= -nom; + sign= 1; + } + + for(;;){ //note is executed 1 or 2 times + gcd = ff_gcd(nom, den); + nom /= gcd; + den /= gcd; + + larger= FFMAX(nom, den); + + if(larger > max){ + int64_t div= (larger + max - 1) / max; + nom = (nom + div/2)/div; + den = (den + div/2)/div; + exact=0; + }else + break; + } + + if(sign) nom= -nom; + + *dst_nom = nom; + *dst_den = den; + + return exact; } -static int decode_frame(AVCodecContext *avctx, - void *data, int *data_size, - UINT8 *buf, int buf_size) -{ - return -1; -} +int64_t av_rescale(int64_t a, int b, int c){ + uint64_t h, l; + assert(c > 0); + assert(b >=0); + + if(a<0) return -av_rescale(-a, b, c); + + h= a>>32; + if(h==0) return a*b/c; + + l= a&0xFFFFFFFF; + l *= b; + h *= b; -static int encode_frame(AVCodecContext *avctx, - unsigned char *frame, int buf_size, void *data) -{ - return -1; -} - -AVCodec rawvideo_codec = { - "rawvideo", - CODEC_TYPE_VIDEO, - CODEC_ID_RAWVIDEO, - 0, - encode_init, - encode_frame, - NULL, - decode_frame, -}; + l += (h%c)<<32; + + return ((h/c)<<32) + l/c; +}