diff options
Diffstat (limited to 'src/libffmpeg/libavcodec/utils.c')
-rw-r--r-- | src/libffmpeg/libavcodec/utils.c | 177 |
1 files changed, 173 insertions, 4 deletions
diff --git a/src/libffmpeg/libavcodec/utils.c b/src/libffmpeg/libavcodec/utils.c index 6797508e1..bc7da83ef 100644 --- a/src/libffmpeg/libavcodec/utils.c +++ b/src/libffmpeg/libavcodec/utils.c @@ -23,6 +23,9 @@ void *av_mallocz(unsigned int size) { void *ptr; + + if(size == 0) fprintf(stderr, "Warning, allocating 0 bytes\n"); + ptr = av_malloc(size); if (!ptr) return NULL; @@ -30,6 +33,43 @@ void *av_mallocz(unsigned int size) return ptr; } +/* 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) +{ + 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 = 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() +{ + if (array_static) + { + unsigned i; + for (i = 0; i < last_static; i++) + { + free(*array_static[i]); + *array_static[i] = NULL; + } + 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) { @@ -49,6 +89,123 @@ void register_avcodec(AVCodec *format) format->next = NULL; } +void avcodec_get_chroma_sub_sample(int fmt, int *h_shift, int *v_shift){ + switch(fmt){ + case PIX_FMT_YUV410P: + *h_shift=2; + *v_shift=2; + break; + case PIX_FMT_YUV420P: + *h_shift=1; + *v_shift=1; + break; + case PIX_FMT_YUV411P: + *h_shift=2; + *v_shift=0; + break; + case PIX_FMT_YUV422P: + case PIX_FMT_YUV422: + *h_shift=1; + *v_shift=0; + break; + default: //RGB/... + *h_shift=0; + *v_shift=0; + break; + } +} + +typedef struct DefaultPicOpaque{ + int last_pic_num; + uint8_t *data[4]; +}DefaultPicOpaque; + +int avcodec_default_get_buffer(AVCodecContext *s, AVVideoFrame *pic){ + int i; + const int width = s->width; + const int height= s->height; + DefaultPicOpaque *opaque; + + if(pic->opaque){ + opaque= (DefaultPicOpaque *)pic->opaque; + for(i=0; i<3; i++) + pic->data[i]= opaque->data[i]; + +// printf("get_buffer %X coded_pic_num:%d last:%d\n", pic->opaque, pic->coded_picture_number, opaque->last_pic_num); + pic->age= pic->coded_picture_number - opaque->last_pic_num; + opaque->last_pic_num= pic->coded_picture_number; +//printf("age: %d %d %d\n", pic->age, c->picture_number, 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_YUV422: + pixel_size=2; + break; + case PIX_FMT_RGB24: + case PIX_FMT_BGR24: + pixel_size=3; + break; + case PIX_FMT_BGRA32: + 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; + } + + opaque= av_mallocz(sizeof(DefaultPicOpaque)); + if(opaque==NULL) return -1; + + pic->opaque= opaque; + opaque->last_pic_num= -256*256*256*64; + + for(i=0; i<3; i++){ + int h_shift= i==0 ? 0 : h_chroma_shift; + int v_shift= i==0 ? 0 : v_chroma_shift; + + pic->linesize[i]= pixel_size*w>>h_shift; + + pic->base[i]= av_mallocz((pic->linesize[i]*h>>v_shift)+16); //FIXME 16 + if(pic->base[i]==NULL) return -1; + + memset(pic->base[i], 128, pic->linesize[i]*h>>v_shift); + + if(s->flags&CODEC_FLAG_EMU_EDGE) + pic->data[i] = pic->base[i]; + else + pic->data[i] = pic->base[i] + (pic->linesize[i]*EDGE_WIDTH>>v_shift) + (EDGE_WIDTH>>h_shift); + + opaque->data[i]= pic->data[i]; + } + pic->age= 256*256*256*64; + } + + return 0; +} + +void avcodec_default_release_buffer(AVCodecContext *s, AVVideoFrame *pic){ + int i; + + for(i=0; i<3; i++) + pic->data[i]=NULL; +//printf("R%X\n", pic->opaque); +} + void avcodec_get_context_defaults(AVCodecContext *s){ s->bit_rate= 800*1000; s->bit_rate_tolerance= s->bit_rate*10; @@ -67,6 +224,8 @@ void avcodec_get_context_defaults(AVCodecContext *s){ s->frame_rate = 25 * FRAME_RATE_BASE; s->gop_size= 50; s->me_method= ME_EPZS; + s->get_buffer= avcodec_default_get_buffer; + s->release_buffer= avcodec_default_release_buffer; } /** @@ -83,6 +242,16 @@ AVCodecContext *avcodec_alloc_context(void){ return avctx; } +/** + * allocates a AVPicture and set it to defaults. + * this can be deallocated by simply calling free() + */ +AVVideoFrame *avcodec_alloc_picture(void){ + AVVideoFrame *pic= av_mallocz(sizeof(AVVideoFrame)); + + return pic; +} + int avcodec_open(AVCodecContext *avctx, AVCodec *codec) { int ret; @@ -115,7 +284,7 @@ int avcodec_encode_audio(AVCodecContext *avctx, UINT8 *buf, int buf_size, } int avcodec_encode_video(AVCodecContext *avctx, UINT8 *buf, int buf_size, - const AVPicture *pict) + const AVVideoFrame *pict) { int ret; @@ -130,17 +299,17 @@ int avcodec_encode_video(AVCodecContext *avctx, UINT8 *buf, int buf_size, /* 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, +int avcodec_decode_video(AVCodecContext *avctx, AVVideoFrame *picture, int *got_picture_ptr, UINT8 *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; |