/*
* 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)
{
return ptr;
}
/* free all static arrays and reset pointers to 0 */
-void av_free_static()
+void av_free_static(void)
{
if (array_static)
{
format->next = NULL;
}
-typedef struct DefaultPicOpaque{
+typedef struct InternalBuffer{
int last_pic_num;
+ uint8_t *base[4];
uint8_t *data[4];
-}DefaultPicOpaque;
+ 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;
- DefaultPicOpaque *opaque;
+ int w= s->width;
+ int h= s->height;
+ InternalBuffer *buf;
+ int *picture_number;
assert(pic->data[0]==NULL);
- assert(pic->type==0 || pic->type==FF_TYPE_INTERNAL);
-
- if(pic->opaque){
- opaque= (DefaultPicOpaque *)pic->opaque;
- for(i=0; i<3; i++)
- pic->data[i]= opaque->data[i];
+ assert(INTERNAL_BUFFER_SIZE > s->internal_buffer_count);
-// 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);
+ 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];
+ picture_number= &(((InternalBuffer*)s->internal_buffer)[INTERNAL_BUFFER_SIZE-1]).last_pic_num; //FIXME ugly hack
+ (*picture_number)++;
+
+ if(buf->base[0]){
+ 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:
case PIX_FMT_YUV422:
pixel_size=2;
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;
-
+
+ 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;
}
- opaque= av_mallocz(sizeof(DefaultPicOpaque));
- if(opaque==NULL) return -1;
-
- pic->opaque= opaque;
- opaque->last_pic_num= -256*256*256*64;
+ buf->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;
+ const int h_shift= i==0 ? 0 : h_chroma_shift;
+ const int v_shift= i==0 ? 0 : v_chroma_shift;
- pic->base[i]= av_mallocz((pic->linesize[i]*h>>v_shift)+16); //FIXME 16
- if(pic->base[i]==NULL) return -1;
+ //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));
- memset(pic->base[i], 128, pic->linesize[i]*h>>v_shift);
+ 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, buf->linesize[i]*h>>v_shift);
if(s->flags&CODEC_FLAG_EMU_EDGE)
- pic->data[i] = pic->base[i];
+ buf->data[i] = buf->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];
+ 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++;
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; i<3; i++)
+ assert(s->internal_buffer_count);
+
+ buf = NULL; /* avoids warning */
+ 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];
+
+ 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);
}
+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;
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 */
+/**
+ * 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_t *buf, int buf_size)
if (p) {
codec_name = p->name;
+ if (!encode && enc->codec_id == CODEC_ID_MP3) {
+ if (enc->sub_id == 2)
+ codec_name = "mp2";
+ 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 {
case CODEC_TYPE_VIDEO:
snprintf(buf, buf_size,
"Video: %s%s",
- codec_name, enc->flags & CODEC_FLAG_HQ ? " (hq)" : "");
+ codec_name, enc->mb_decision ? " (hq)" : "");
if (enc->codec_id == CODEC_ID_RAWVIDEO) {
snprintf(buf + strlen(buf), buf_size - strlen(buf),
", %s",
break;
}
break;
+ case CODEC_TYPE_DATA:
+ snprintf(buf, buf_size, "Data: %s", codec_name);
+ bitrate = enc->bit_rate;
+ break;
default:
av_abort();
}
return;
inited = 1;
- //dsputil_init();
+ dsputil_static_init();
}
-/* this can be called after seeking and before trying to decode the next keyframe */
+/**
+ * Flush buffers, should be called when seeking or when swicthing to a different stream.
+ */
void avcodec_flush_buffers(AVCodecContext *avctx)
{
- int i;
- MpegEncContext *s = avctx->priv_data;
+ if(avctx->codec->flush)
+ avctx->codec->flush(avctx);
+}
+
+void avcodec_default_free_buffers(AVCodecContext *s){
+ int i, j;
+
+ if(s->internal_buffer==NULL) return;
- 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; i<MAX_PICTURE_COUNT; i++){
- if(s->picture[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;
+ for(i=0; i<INTERNAL_BUFFER_SIZE; i++){
+ InternalBuffer *buf= &((InternalBuffer*)s->internal_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;
+}
+
+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 '?';
}
}
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;
+ 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(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;
+}
+