Newer
Older
* Copyright (c) 2003 Michel Bardiaux for the av_log API
Michael Niedermayer
committed
* 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
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
* 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
* Lesser General Public License for more details.
* 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 <stdarg.h>
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 */
{
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;
void register_avcodec(AVCodec *format)
{
AVCodec **p;
p = &first_avcodec;
while (*p != NULL) p = &(*p)->next;
*p = format;
format->next = NULL;
}
typedef struct InternalBuffer{
Michael Niedermayer
committed
int linesize[4];
}InternalBuffer;
#define INTERNAL_BUFFER_SIZE 32
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
#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){
Michael Niedermayer
committed
int *picture_number;
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];
Michael Niedermayer
committed
picture_number= &(((InternalBuffer*)s->internal_buffer)[INTERNAL_BUFFER_SIZE-1]).last_pic_num; //FIXME ugly hack
(*picture_number)++;
Michael Niedermayer
committed
pic->age= *picture_number - buf->last_pic_num;
buf->last_pic_num= *picture_number;
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);
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;
}
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;
}
buf->last_pic_num= -256*256*256*64;
const int h_shift= i==0 ? 0 : h_chroma_shift;
const int v_shift= i==0 ? 0 : v_chroma_shift;
Michael Niedermayer
committed
//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));
Michael Niedermayer
committed
buf->base[i]= av_mallocz((buf->linesize[i]*h>>v_shift)+16); //FIXME 16
if(buf->base[i]==NULL) return -1;
Michael Niedermayer
committed
memset(buf->base[i], 128, buf->linesize[i]*h>>v_shift);
Michael Niedermayer
committed
buf->data[i] = buf->base[i] + ALIGN((buf->linesize[i]*EDGE_WIDTH>>v_shift) + (EDGE_WIDTH>>h_shift), s_align);
Michael Niedermayer
committed
pic->type= FF_BUFFER_TYPE_INTERNAL;
for(i=0; i<4; i++){
pic->base[i]= buf->base[i];
pic->data[i]= buf->data[i];
Michael Niedermayer
committed
pic->linesize[i]= buf->linesize[i];
}
s->internal_buffer_count++;
void avcodec_default_release_buffer(AVCodecContext *s, AVFrame *pic){
InternalBuffer *buf, *last, temp;
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++){
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
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->rc_eq= "tex^qComp";
s->qcompress= 0.5;
s->max_qdiff= 3;
s->b_quant_factor=1.25;
s->b_quant_offset=1.25;
Michael Niedermayer
committed
s->i_quant_factor=-0.8;
s->error_concealment= 3;
s->workaround_bugs= FF_BUG_AUTODETECT;
Michael Niedermayer
committed
s->frame_rate_base= 1;
s->frame_rate = 25;
s->get_buffer= avcodec_default_get_buffer;
s->release_buffer= avcodec_default_release_buffer;
s->execute= avcodec_default_execute;
s->thread_count=1;
Michael Niedermayer
committed
s->lmin= FF_QP2LAMBDA * s->qmin;
s->lmax= FF_QP2LAMBDA * s->qmax;
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;
}
/**
* allocates a AVCodecContext and set it to defaults.
* this can be deallocated by simply calling free()
*/
AVCodecContext *avctx= av_malloc(sizeof(AVCodecContext));
if(avctx==NULL) return NULL;
avcodec_get_context_defaults(avctx);
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.
AVFrame *pic= av_malloc(sizeof(AVFrame));
if(pic==NULL) return NULL;
avcodec_get_frame_defaults(pic);
int avcodec_open(AVCodecContext *avctx, AVCodec *codec)
{
int ret;
if(avctx->codec)
return -1;
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;
}
int avcodec_encode_audio(AVCodecContext *avctx, uint8_t *buf, int buf_size,
const short *samples)
{
int ret;
ret = avctx->codec->encode(avctx, buf, buf_size, (void *)samples);
avctx->frame_number++;
return ret;
}
int avcodec_encode_video(AVCodecContext *avctx, uint8_t *buf, int buf_size,
{
int ret;
ret = avctx->codec->encode(avctx, buf, buf_size, (void *)pict);
emms_c(); //needed to avoid a emms_c() call before every return;
/**
* 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,
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;
}
/* decode an audio frame. return -1 if error, otherwise return the
*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_t *samples,
{
int ret;
ret = avctx->codec->decode(avctx, samples, frame_size_ptr,
buf, buf_size);
avctx->frame_number++;
return ret;
}
int avcodec_close(AVCodecContext *avctx)
{
if (avctx->codec->close)
avctx->codec->close(avctx);
avctx->codec = NULL;
return 0;
}
AVCodec *avcodec_find_encoder(enum CodecID id)
{
AVCodec *p;
p = first_avcodec;
while (p) {
if (p->encode != NULL && p->id == id)
return p;
p = p->next;
}
return NULL;
}
AVCodec *avcodec_find_encoder_by_name(const char *name)
{
AVCodec *p;
p = first_avcodec;
while (p) {
if (p->encode != NULL && strcmp(name,p->name) == 0)
return p;
p = p->next;
}
return NULL;
}
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
AVCodec *avcodec_find_decoder(enum CodecID id)
{
AVCodec *p;
p = first_avcodec;
while (p) {
if (p->decode != NULL && p->id == id)
return p;
p = p->next;
}
return NULL;
}
AVCodec *avcodec_find_decoder_by_name(const char *name)
{
AVCodec *p;
p = first_avcodec;
while (p) {
if (p->decode != NULL && strcmp(name,p->name) == 0)
return p;
p = p->next;
}
return NULL;
}
AVCodec *avcodec_find(enum CodecID id)
{
AVCodec *p;
p = first_avcodec;
while (p) {
if (p->id == id)
return p;
p = p->next;
}
return NULL;
}
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];
if (encode)
p = avcodec_find_encoder(enc->codec_id);
else
p = avcodec_find_decoder(enc->codec_id);
if (p) {
codec_name = p->name;
Fabrice Bellard
committed
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";
}
Fabrice Bellard
committed
} 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 {
/* output avi tags */
if (enc->codec_type == CODEC_TYPE_VIDEO) {
snprintf(buf1, sizeof(buf1), "%c%c%c%c",
enc->codec_tag & 0xff,
(enc->codec_tag >> 8) & 0xff,
(enc->codec_tag >> 16) & 0xff,
(enc->codec_tag >> 24) & 0xff);
} else {
snprintf(buf1, sizeof(buf1), "0x%04x", enc->codec_tag);
}
codec_name = buf1;
}
switch(enc->codec_type) {
case CODEC_TYPE_VIDEO:
snprintf(buf, buf_size,
"Video: %s%s",
codec_name, enc->mb_decision ? " (hq)" : "");
if (enc->codec_id == CODEC_ID_RAWVIDEO) {
snprintf(buf + strlen(buf), buf_size - strlen(buf),
", %s",
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,
Michael Niedermayer
committed
(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);
}
break;
case CODEC_TYPE_AUDIO:
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,
channels_str);
/* for PCM codecs, compute bitrate directly */
switch(enc->codec_id) {
case CODEC_ID_PCM_S16LE:
case CODEC_ID_PCM_S16BE:
case CODEC_ID_PCM_U16LE:
case CODEC_ID_PCM_U16BE:
break;
case CODEC_ID_PCM_S8:
case CODEC_ID_PCM_U8:
case CODEC_ID_PCM_ALAW:
case CODEC_ID_PCM_MULAW:
break;
default:
bitrate = enc->bit_rate;
break;
}
Fabrice Bellard
committed
case CODEC_TYPE_DATA:
snprintf(buf, buf_size, "Data: %s", codec_name);
bitrate = enc->bit_rate;
break;
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");
}
unsigned avcodec_version( void )
{
return LIBAVCODEC_VERSION_INT;
}
unsigned avcodec_build( void )
{
return LIBAVCODEC_BUILD;
}
/* must be called before any other functions */
void avcodec_init(void)
{
static int inited = 0;
if (inited != 0)
return;
inited = 1;
/**
* Flush buffers, should be called when seeking or when swicthing to a different stream.
*/
void avcodec_flush_buffers(AVCodecContext *avctx)
{
if(avctx->codec->flush)
avctx->codec->flush(avctx);
void avcodec_default_free_buffers(AVCodecContext *s){
int i, j;
if(s->internal_buffer==NULL) return;
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 '?';
}
}
Michael Niedermayer
committed
int av_reduce(int *dst_nom, int *dst_den, int64_t nom, int64_t den, int64_t max){
int exact=1, sign=0;
Michael Niedermayer
committed
int64_t gcd;
Michael Niedermayer
committed
assert(den != 0);
if(den < 0){
den= -den;
nom= -nom;
}
if(nom < 0){
nom= -nom;
sign= 1;
}
Michael Niedermayer
committed
gcd = ff_gcd(nom, den);
nom /= gcd;
den /= gcd;
Michael Niedermayer
committed
Michael Niedermayer
committed
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;
Michael Niedermayer
committed
}
Michael Niedermayer
committed
assert(ff_gcd(nom, den) == 1);
Michael Niedermayer
committed
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
if(sign) nom= -nom;
*dst_nom = nom;
*dst_den = den;
return exact;
}
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;
l += (h%c)<<32;
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)
{
if(level>av_log_level)
return;
Michael Niedermayer
committed
#undef fprintf
fprintf(stderr, "[%s @ %p]", avctx->codec ? avctx->codec->name : "?", avctx);
Michael Niedermayer
committed
#define fprintf please_use_av_log
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
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;
}