Newer
Older
Michael Niedermayer
committed
* Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at>
Diego Biurrun
committed
* This file is part of FFmpeg.
*
* FFmpeg 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
Diego Biurrun
committed
* version 2.1 of the License, or (at your option) any later version.
Diego Biurrun
committed
* FFmpeg 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
Diego Biurrun
committed
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Michael Niedermayer
committed
#include "integer.h"
#include <stdarg.h>
Michael Niedermayer
committed
#include <limits.h>
#ifdef __MINGW32__
#include <fcntl.h>
#endif
Roine Gustafsson
committed
const uint8_t ff_reverse[256]={
0x00,0x80,0x40,0xC0,0x20,0xA0,0x60,0xE0,0x10,0x90,0x50,0xD0,0x30,0xB0,0x70,0xF0,
0x08,0x88,0x48,0xC8,0x28,0xA8,0x68,0xE8,0x18,0x98,0x58,0xD8,0x38,0xB8,0x78,0xF8,
0x04,0x84,0x44,0xC4,0x24,0xA4,0x64,0xE4,0x14,0x94,0x54,0xD4,0x34,0xB4,0x74,0xF4,
0x0C,0x8C,0x4C,0xCC,0x2C,0xAC,0x6C,0xEC,0x1C,0x9C,0x5C,0xDC,0x3C,0xBC,0x7C,0xFC,
0x02,0x82,0x42,0xC2,0x22,0xA2,0x62,0xE2,0x12,0x92,0x52,0xD2,0x32,0xB2,0x72,0xF2,
0x0A,0x8A,0x4A,0xCA,0x2A,0xAA,0x6A,0xEA,0x1A,0x9A,0x5A,0xDA,0x3A,0xBA,0x7A,0xFA,
0x06,0x86,0x46,0xC6,0x26,0xA6,0x66,0xE6,0x16,0x96,0x56,0xD6,0x36,0xB6,0x76,0xF6,
0x0E,0x8E,0x4E,0xCE,0x2E,0xAE,0x6E,0xEE,0x1E,0x9E,0x5E,0xDE,0x3E,0xBE,0x7E,0xFE,
0x01,0x81,0x41,0xC1,0x21,0xA1,0x61,0xE1,0x11,0x91,0x51,0xD1,0x31,0xB1,0x71,0xF1,
0x09,0x89,0x49,0xC9,0x29,0xA9,0x69,0xE9,0x19,0x99,0x59,0xD9,0x39,0xB9,0x79,0xF9,
0x05,0x85,0x45,0xC5,0x25,0xA5,0x65,0xE5,0x15,0x95,0x55,0xD5,0x35,0xB5,0x75,0xF5,
0x0D,0x8D,0x4D,0xCD,0x2D,0xAD,0x6D,0xED,0x1D,0x9D,0x5D,0xDD,0x3D,0xBD,0x7D,0xFD,
0x03,0x83,0x43,0xC3,0x23,0xA3,0x63,0xE3,0x13,0x93,0x53,0xD3,0x33,0xB3,0x73,0xF3,
0x0B,0x8B,0x4B,0xCB,0x2B,0xAB,0x6B,0xEB,0x1B,0x9B,0x5B,0xDB,0x3B,0xBB,0x7B,0xFB,
0x07,0x87,0x47,0xC7,0x27,0xA7,0x67,0xE7,0x17,0x97,0x57,0xD7,0x37,0xB7,0x77,0xF7,
0x0F,0x8F,0x4F,0xCF,0x2F,0xAF,0x6F,0xEF,0x1F,0x9F,0x5F,0xDF,0x3F,0xBF,0x7F,0xFF,
};
static int volatile entangled_thread_counter=0;
/**
* realloc which does nothing if the block is large enough
*/
void *av_fast_realloc(void *ptr, unsigned int *size, unsigned int min_size)
return ptr;
*size= FFMAX(17*min_size/16 + 32, min_size);
return av_realloc(ptr, *size);
}
static unsigned int last_static = 0;
static unsigned int allocated_static = 0;
static void** array_static = NULL;
/**
* allocation of static arrays - do not use for normal allocation.
*/
void *av_mallocz_static(unsigned int size)
{
void *ptr = av_mallocz(size);
array_static =av_fast_realloc(array_static, &allocated_static, sizeof(void*)*(last_static+1));
if(!array_static)
return NULL;
array_static[last_static++] = ptr;
return ptr;
}
Burkhard Plaum
committed
/**
* same as above, but does realloc
*/
void *av_realloc_static(void *ptr, unsigned int size)
{
int i;
if(!ptr)
return av_mallocz_static(size);
/* Look for the old ptr */
for(i = 0; i < last_static; i++) {
if(array_static[i] == ptr) {
array_static[i] = av_realloc(array_static[i], size);
return array_static[i];
}
}
return NULL;
}
/**
* free all static arrays and reset pointers to 0.
*/
while(last_static){
av_freep(&array_static[--last_static]);
av_freep(&array_static);
Burkhard Plaum
committed
/**
* Call av_free_static automatically before it's too late
*/
static void do_free(void) __attribute__ ((destructor));
Burkhard Plaum
committed
Burkhard Plaum
committed
{
av_free_static();
}
Michael Niedermayer
committed
AVCodec *first_avcodec = NULL;
void register_avcodec(AVCodec *format)
{
AVCodec **p;
p = &first_avcodec;
while (*p != NULL) p = &(*p)->next;
*p = format;
format->next = NULL;
}
void avcodec_set_dimensions(AVCodecContext *s, int width, int height){
s->coded_width = width;
s->coded_height= height;
s->width = -((-width )>>s->lowres);
s->height= -((-height)>>s->lowres);
}
typedef struct InternalBuffer{
Michael Niedermayer
committed
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_UYVY422:
case PIX_FMT_YUV422P:
case PIX_FMT_YUV444P:
case PIX_FMT_GRAY8:
case PIX_FMT_GRAY16BE:
case PIX_FMT_GRAY16LE:
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;
}
case PIX_FMT_RGB555:
if(s->codec_id == CODEC_ID_RPZA){
w_align=4;
h_align=4;
}
case PIX_FMT_PAL8:
if(s->codec_id == CODEC_ID_SMC){
w_align=4;
h_align=4;
}
case PIX_FMT_BGR24:
if((s->codec_id == CODEC_ID_MSZH) || (s->codec_id == CODEC_ID_ZLIB)){
w_align=4;
h_align=4;
}
break;
default:
w_align= 1;
h_align= 1;
break;
}
*width = ALIGN(*width , w_align);
*height= ALIGN(*height, h_align);
}
int avcodec_check_dimensions(void *av_log_ctx, unsigned int w, unsigned int h){
if((int)w>0 && (int)h>0 && (w+128)*(uint64_t)(h+128) < INT_MAX/4)
return 0;
av_log(av_log_ctx, AV_LOG_ERROR, "picture size invalid (%ux%u)\n", w, h);
return -1;
}
int avcodec_default_get_buffer(AVCodecContext *s, AVFrame *pic){
Michael Niedermayer
committed
int *picture_number;
assert(INTERNAL_BUFFER_SIZE > s->internal_buffer_count);
if(avcodec_check_dimensions(s,w,h))
return -1;
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 pixel_size, size[3];
AVPicture picture;
avcodec_get_chroma_sub_sample(s->pix_fmt, &h_chroma_shift, &v_chroma_shift);
avcodec_align_dimensions(s, &w, &h);
if(!(s->flags&CODEC_FLAG_EMU_EDGE)){
w+= EDGE_WIDTH*2;
h+= EDGE_WIDTH*2;
}
avpicture_fill(&picture, NULL, s->pix_fmt, w, h);
pixel_size= picture.linesize[0]*8 / w;
//av_log(NULL, AV_LOG_ERROR, "%d %d %d %d\n", (int)picture.data[1], w, h, s->pix_fmt);
assert(pixel_size>=1);
//FIXME next ensures that linesize= 2^x uvlinesize, thats needed because some MC code assumes it
if(pixel_size == 3*8)
w= ALIGN(w, STRIDE_ALIGN<<h_chroma_shift);
else
w= ALIGN(pixel_size*w, STRIDE_ALIGN<<(h_chroma_shift+3)) / pixel_size;
size[1] = avpicture_fill(&picture, NULL, s->pix_fmt, w, h);
size[0] = picture.linesize[0] * h;
size[1] -= size[0];
if(picture.data[2])
size[1]= size[2]= size[1]/2;
else
size[2]= 0;
buf->last_pic_num= -256*256*256*64;
memset(buf->base, 0, sizeof(buf->base));
memset(buf->data, 0, sizeof(buf->data));
const int h_shift= i==0 ? 0 : h_chroma_shift;
const int v_shift= i==0 ? 0 : v_chroma_shift;
buf->linesize[i]= picture.linesize[i];
buf->base[i]= av_malloc(size[i]+16); //FIXME 16
if(buf->base[i]==NULL) return -1;
memset(buf->base[i], 128, size[i]);
// no edge if EDEG EMU or not planar YUV, we check for PAL8 redundantly to protect against a exploitable bug regression ...
if((s->flags&CODEC_FLAG_EMU_EDGE) || (s->pix_fmt == PIX_FMT_PAL8) || !size[2])
buf->data[i] = buf->base[i] + ALIGN((buf->linesize[i]*EDGE_WIDTH>>v_shift) + (EDGE_WIDTH>>h_shift), STRIDE_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++){
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
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, const enum PixelFormat * fmt){
static const char* context_to_name(void* ptr) {
AVCodecContext *avc= ptr;
if(avc && avc->codec && avc->codec->name)
#define OFFSET(x) offsetof(AVCodecContext,x)
#define DEFAULT 0 //should be NAN but it doesnt work as its not a constant in glibc as required by ANSI/ISO C
//these names are too long to be readable
#define V AV_OPT_FLAG_VIDEO_PARAM
#define A AV_OPT_FLAG_AUDIO_PARAM
#define S AV_OPT_FLAG_SUBTITLE_PARAM
#define E AV_OPT_FLAG_ENCODING_PARAM
Panagiotis Issaris
committed
#define AV_CODEC_DEFAULT_BITRATE 200*1000
static const AVOption options[]={
{"b", "set video bitrate (in bits/s)", OFFSET(bit_rate), FF_OPT_TYPE_INT, AV_CODEC_DEFAULT_BITRATE, INT_MIN, INT_MAX, V|A|E},
{"bt", "set video bitrate tolerance (in bits/s)", OFFSET(bit_rate_tolerance), FF_OPT_TYPE_INT, AV_CODEC_DEFAULT_BITRATE*20, INT_MIN, INT_MAX, V|E},
{"flags", NULL, OFFSET(flags), FF_OPT_TYPE_FLAGS, DEFAULT, INT_MIN, INT_MAX, V|A|E|D, "flags"},
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
{"mv4", "use four motion vector by macroblock (mpeg4)", 0, FF_OPT_TYPE_CONST, CODEC_FLAG_4MV, INT_MIN, INT_MAX, V|E, "flags"},
{"obmc", "use overlapped block motion compensation (h263+)", 0, FF_OPT_TYPE_CONST, CODEC_FLAG_OBMC, INT_MIN, INT_MAX, V|E, "flags"},
{"qpel", "use 1/4 pel motion compensation", 0, FF_OPT_TYPE_CONST, CODEC_FLAG_QPEL, INT_MIN, INT_MAX, V|E, "flags"},
{"loop", "use loop filter", 0, FF_OPT_TYPE_CONST, CODEC_FLAG_LOOP_FILTER, INT_MIN, INT_MAX, V|E, "flags"},
{"qscale", "use fixed qscale", 0, FF_OPT_TYPE_CONST, CODEC_FLAG_QSCALE, INT_MIN, INT_MAX, 0, "flags"},
{"gmc", "use gmc", 0, FF_OPT_TYPE_CONST, CODEC_FLAG_GMC, INT_MIN, INT_MAX, V
Loading
Loading full blame...