/*
* utils for libavcodec
* Copyright (c) 2001 Fabrice Bellard.
+ * Copyright (c) 2003 Michel Bardiaux for the av_log API
+ * Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
#include "avcodec.h"
#include "dsputil.h"
#include "mpegvideo.h"
+#include <stdarg.h>
void *av_mallocz(unsigned int size)
{
int last_pic_num;
uint8_t *base[4];
uint8_t *data[4];
+ int linesize[4];
}InternalBuffer;
#define INTERNAL_BUFFER_SIZE 32
+#define ALIGN(x, a) (((x)+(a)-1)&~((a)-1))
+
+void avcodec_align_dimensions(AVCodecContext *s, int *width, int *height){
+ int w_align= 1;
+ int h_align= 1;
+
+ switch(s->pix_fmt){
+ case PIX_FMT_YUV420P:
+ case PIX_FMT_YUV422:
+ case PIX_FMT_YUV422P:
+ case PIX_FMT_YUV444P:
+ case PIX_FMT_GRAY8:
+ case PIX_FMT_YUVJ420P:
+ case PIX_FMT_YUVJ422P:
+ case PIX_FMT_YUVJ444P:
+ w_align= 16; //FIXME check for non mpeg style codecs and use less alignment
+ h_align= 16;
+ break;
+ case PIX_FMT_YUV411P:
+ w_align=32;
+ h_align=8;
+ break;
+ case PIX_FMT_YUV410P:
+ if(s->codec_id == CODEC_ID_SVQ1){
+ w_align=64;
+ h_align=64;
+ }
+ break;
+ default:
+ w_align= 1;
+ h_align= 1;
+ break;
+ }
+
+ *width = ALIGN(*width , w_align);
+ *height= ALIGN(*height, h_align);
+}
+
int avcodec_default_get_buffer(AVCodecContext *s, AVFrame *pic){
int i;
- const int width = s->width;
- const int height= s->height;
+ int w= s->width;
+ int h= s->height;
InternalBuffer *buf;
+ int *picture_number;
assert(pic->data[0]==NULL);
assert(INTERNAL_BUFFER_SIZE > s->internal_buffer_count);
#endif
buf= &((InternalBuffer*)s->internal_buffer)[s->internal_buffer_count];
-
+ picture_number= &(((InternalBuffer*)s->internal_buffer)[INTERNAL_BUFFER_SIZE-1]).last_pic_num; //FIXME ugly hack
+ (*picture_number)++;
+
if(buf->base[0]){
- pic->age= pic->coded_picture_number - buf->last_pic_num;
- buf->last_pic_num= pic->coded_picture_number;
+ pic->age= *picture_number - buf->last_pic_num;
+ buf->last_pic_num= *picture_number;
}else{
- int align, h_chroma_shift, v_chroma_shift;
- int w, h, pixel_size;
+ int h_chroma_shift, v_chroma_shift;
+ int s_align, 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:
default:
pixel_size=1;
}
-
- if(s->codec_id==CODEC_ID_SVQ1) align=63;
- else align=15;
-
- w= (width +align)&~align;
- h= (height+align)&~align;
-
+
+ avcodec_align_dimensions(s, &w, &h);
+#if defined(ARCH_POWERPC) || defined(HAVE_MMI) //FIXME some cleaner check
+ s_align= 16;
+#else
+ s_align= 8;
+#endif
+
if(!(s->flags&CODEC_FLAG_EMU_EDGE)){
w+= EDGE_WIDTH*2;
h+= EDGE_WIDTH*2;
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;
+ //FIXME next ensures that linesize= 2^x uvlinesize, thats needed because some MC code assumes it
+ buf->linesize[i]= ALIGN(pixel_size*w>>h_shift, s_align<<(h_chroma_shift-h_shift));
- buf->base[i]= av_mallocz((pic->linesize[i]*h>>v_shift)+16); //FIXME 16
+ buf->base[i]= av_mallocz((buf->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);
+ memset(buf->base[i], 128, buf->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);
+ buf->data[i] = buf->base[i] + ALIGN((buf->linesize[i]*EDGE_WIDTH>>v_shift) + (EDGE_WIDTH>>h_shift), s_align);
}
pic->age= 256*256*256*64;
- pic->type= FF_BUFFER_TYPE_INTERNAL;
}
+ pic->type= FF_BUFFER_TYPE_INTERNAL;
for(i=0; i<4; i++){
pic->base[i]= buf->base[i];
pic->data[i]= buf->data[i];
+ pic->linesize[i]= buf->linesize[i];
}
s->internal_buffer_count++;
//printf("R%X\n", pic->opaque);
}
+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)
+ return 0;
+
+ /*
+ * 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 */
+ img_copy((AVPicture*)pic, (AVPicture*)&temp_pic, s->pix_fmt, s->width,
+ s->height);
+ s->release_buffer(s, &temp_pic); // Release old frame
+ return 0;
+}
+
+int avcodec_default_execute(AVCodecContext *c, int (*func)(AVCodecContext *c2, void *arg2),void **arg, int *ret, int count){
+ int i;
+
+ for(i=0; i<count; i++){
+ int r= func(c, arg[i]);
+ if(ret) ret[i]= r;
+ }
+ return 0;
+}
+
enum PixelFormat avcodec_default_get_format(struct AVCodecContext *s, enum PixelFormat * fmt){
return fmt[0];
}
void avcodec_get_context_defaults(AVCodecContext *s){
+ memset(s, 0, sizeof(AVCodecContext));
+
s->bit_rate= 800*1000;
s->bit_rate_tolerance= s->bit_rate*10;
s->qmin= 2;
s->get_buffer= avcodec_default_get_buffer;
s->release_buffer= avcodec_default_release_buffer;
s->get_format= avcodec_default_get_format;
+ s->execute= avcodec_default_execute;
+ s->thread_count=1;
s->me_subpel_quality=8;
+ s->lmin= FF_QP2LAMBDA * s->qmin;
+ s->lmax= FF_QP2LAMBDA * s->qmax;
+ s->sample_aspect_ratio= (AVRational){0,1};
+ s->ildct_cmp= FF_CMP_VSAD;
s->intra_quant_bias= FF_DEFAULT_QUANT_BIAS;
s->inter_quant_bias= FF_DEFAULT_QUANT_BIAS;
+ s->palctrl = NULL;
+ s->reget_buffer= avcodec_default_reget_buffer;
}
/**
* this can be deallocated by simply calling free()
*/
AVCodecContext *avcodec_alloc_context(void){
- AVCodecContext *avctx= av_mallocz(sizeof(AVCodecContext));
+ AVCodecContext *avctx= av_malloc(sizeof(AVCodecContext));
if(avctx==NULL) return NULL;
return avctx;
}
+void avcodec_get_frame_defaults(AVFrame *pic){
+ memset(pic, 0, sizeof(AVFrame));
+
+ pic->pts= AV_NOPTS_VALUE;
+}
+
/**
* 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));
+ AVFrame *pic= av_malloc(sizeof(AVFrame));
+
+ if(pic==NULL) return NULL;
+
+ avcodec_get_frame_defaults(pic);
return pic;
}
{
int ret;
+ if(avctx->codec)
+ return -1;
+
avctx->codec = codec;
avctx->codec_id = codec->id;
avctx->frame_number = 0;
else if (enc->sub_id == 1)
codec_name = "mp1";
}
+ } else if (enc->codec_id == CODEC_ID_MPEG2TS) {
+ /* fake mpeg2 transport stream codec (currently not
+ registered) */
+ codec_name = "mpeg2ts";
} else if (enc->codec_name[0] != '\0') {
codec_name = enc->codec_name;
} else {
break;
}
break;
+ case CODEC_TYPE_DATA:
+ snprintf(buf, buf_size, "Data: %s", codec_name);
+ bitrate = enc->bit_rate;
+ break;
default:
av_abort();
}
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;
+ int64_t gcd;
assert(den != 0);
sign= 1;
}
- for(;;){ //note is executed 1 or 2 times
- gcd = ff_gcd(nom, den);
- nom /= gcd;
- den /= gcd;
-
- larger= FFMAX(nom, den);
+ gcd = ff_gcd(nom, den);
+ nom /= gcd;
+ den /= gcd;
- 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(nom > max || den > max){
+ AVRational a0={0,1}, a1={1,0};
+ exact=0;
+
+ for(;;){
+ int64_t x= nom / den;
+ int64_t a2n= x*a1.num + a0.num;
+ int64_t a2d= x*a1.den + a0.den;
+
+ if(a2n > max || a2d > max) break;
+
+ nom %= den;
+
+ a0= a1;
+ a1= (AVRational){a2n, a2d};
+ if(nom==0) break;
+ x= nom; nom=den; den=x;
+ }
+ nom= a1.num;
+ den= a1.den;
}
+ assert(ff_gcd(nom, den) == 1);
+
if(sign) nom= -nom;
*dst_nom = nom;
return ((h/c)<<32) + l/c;
}
+
+/* av_log API */
+
+#ifdef AV_LOG_TRAP_PRINTF
+#undef stderr
+#undef fprintf
+#endif
+
+static int av_log_level = AV_LOG_DEBUG;
+
+static void av_log_default_callback(AVCodecContext* avctx, int level, const char* fmt, va_list vl)
+{
+ static int print_prefix=1;
+
+ if(level>av_log_level)
+ return;
+#undef fprintf
+ if(avctx && print_prefix)
+ fprintf(stderr, "[%s @ %p]", avctx->codec ? avctx->codec->name : "?", avctx);
+#define fprintf please_use_av_log
+
+ print_prefix= strstr(fmt, "\n") != NULL;
+
+ vfprintf(stderr, fmt, vl);
+}
+
+static void (*av_log_callback)(AVCodecContext*, int, const char*, va_list) = av_log_default_callback;
+
+void av_log(AVCodecContext* avctx, int level, const char *fmt, ...)
+{
+ va_list vl;
+ va_start(vl, fmt);
+ av_vlog(avctx, level, fmt, vl);
+ va_end(vl);
+}
+
+void av_vlog(AVCodecContext* avctx, int level, const char *fmt, va_list vl)
+{
+ av_log_callback(avctx, level, fmt, vl);
+}
+
+int av_log_get_level(void)
+{
+ return av_log_level;
+}
+
+void av_log_set_level(int level)
+{
+ av_log_level = level;
+}
+
+void av_log_set_callback(void (*callback)(AVCodecContext*, int, const char*, va_list))
+{
+ av_log_callback = callback;
+}
+