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
buf->linesize[i]= ALIGN(pixel_size*w>>h_shift, s_align);
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++){
294
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
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;
}
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->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;
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_mallocz(sizeof(AVCodecContext));
if(avctx==NULL) return NULL;
avcodec_get_context_defaults(avctx);
return avctx;
}
* allocates a AVPFrame and set it to defaults.
AVFrame *avcodec_alloc_frame(void){
AVFrame *pic= av_mallocz(sizeof(AVFrame));
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;
}
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
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
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
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;
fprintf(stderr, "[%s @ %p]", avctx->codec ? avctx->codec->name : "?", avctx);
print_prefix= (int)strstr(fmt, "\n");
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
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;
}