[Bf-committers] libavcodec support (ffmpeg).

Robert Wenzlaff bf-committers@blender.org
Tue, 25 Nov 2003 04:19:18 -0500


--Boundary-00=_W6xw/91ODBomES5
Content-Type: text/plain;
  charset="iso-8859-1"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline


> Attached is a sample mpeg encoder I implimented this way.  Very crude,
> (03:30 is not the time to try to parse RGB into YUV4:2:0).

And 04:10 is not the time to remember atachments, either....


*********************************************
Robert Wenzlaff   rwenzlaff@soylent-green.com

--Boundary-00=_W6xw/91ODBomES5
Content-Type: text/x-csrc;
  charset="iso-8859-1";
  name="LibTest.c"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="LibTest.c"


#include <stdio.h>
#include <dlfcn.h>
#include "ffmpeg/avcodec.h"

/* To transparently link libavcodec we must make dynamic wrapper functions 
   we need to use */
void *avcodec_handle = NULL;
void (*b_avcodec_init)(void)=NULL;
void (*b_avcodec_register_all)(void)=NULL;
AVCodec *(*b_avcodec_find_encoder)(int)=NULL;
AVCodec *(*b_avcodec_find_decoder)(int)=NULL;
AVCodecContext *(*b_avcodec_alloc_context)(void)=NULL;
AVFrame *(*b_avcodec_alloc_frame)(void);
int (*b_avcodec_open)(AVCodecContext *avctx, AVCodec *codec);
int (*b_avcodec_close)(AVCodecContext *avctx);
int (*b_avcodec_encode_video)(AVCodecContext *avctx, char * buffer, int size, AVFrame *pic); 

/* Prototypes */
short InitLibAVCodec(void);
void CloseLibAVCodec(void);

#define TESTCODE 1

#if TESTCODE
int main(){
	short avcodec_loaded=0;
	AVCodec *codec;
	AVCodecContext *context;
	AVFrame *pic;
	char *output, *buffer, *inbuff;
	FILE *inf, *outf;
	int i, j ,x, y, size, outsz;
	
	/* Files to test encode */
	char basename[]="/home/bob/Blender/TV/tvan_render/tvan";
	char extn[]=".ppm";
	char fname[128];
	int numframes=210, width=720, height=480;
	float fps=30;
	
	/* File to output */
	char outname[]="testavcodec.mpg";
	
	
	avcodec_loaded=InitLibAVCodec();
	
	printf("Libavcodec loaded = %i\n", avcodec_loaded);
	if (!avcodec_loaded){
		printf("Failed to load libavcodec.\n");
		exit(1);
	}
	
	printf("%p\n",  b_avcodec_find_encoder );
	
	codec=b_avcodec_find_encoder(CODEC_ID_MPEG1VIDEO);	
	
	if (!codec) {
		printf("codec2=%p\n",  codec);
		exit(2);
	}
	
	context=b_avcodec_alloc_context();
	pic=b_avcodec_alloc_frame();
	
	/* sample parameters */
	context->bit_rate=40000;
	context->width = width;
	context->height=height;
	context->frame_rate=fps;
	context->frame_rate_base=1;
	context->gop_size=10;
	context->max_b_frames=1;
	
	if (b_avcodec_open(context, codec)<0) {
		printf("Coldn't Open Codec\n");
		exit(3);
	}
	/* Allocate bufers */
	size=height*width;
#define BUFFSIZE 100000
	output=(char *)malloc(BUFFSIZE); /* Find where this comes from */
	inbuff=(char *)malloc(size*3); 
	buffer=(char *)malloc(size*3/2); /* YUV 420 */
	
	pic->data[0]=buffer;
	pic->data[1]=buffer+size;
	pic->data[2]=pic->data[1]+size/4;
	pic->linesize[0]=width;
	pic->linesize[1]=pic->linesize[2]=width/2;
		
	/* Open pics */
	outf=fopen(outname, "w");
	
	for(i=1; i<=numframes; i++){  /* This would be done with a native Blender imbuff */
		fflush(stdout);
		sprintf(fname,"%s%04i%s",basename, i, extn); 
		printf("Opening file %s\n", fname);
		inf=fopen(fname, "r");
		fseek(inf, 15, SEEK_SET);
		fread(inbuff, 1, size*3, inf);
		fclose(inf);
		
		j=0;
		for(y=0;y<height; y++){ /*Y*/
			for(x=0;x<width;x++){
				pic->data[0][y*width +x]=0.299*inbuff[j++]+0.587*inbuff[j++]+0.144*inbuff[j++];
			}
		}
		
		j=0;
		for(y=0;y<height/2; y++){ /*Cb Cr*/
			for(x=0;x<width/2;x++){
				pic->data[1][y*width/2 +x]=120; /* 230AM, will figure this out later*/
				pic->data[2][y*width/2 +x]=56;
			}
		}
		/* encode frames*/
		outsz=b_avcodec_encode_video(context, output, BUFFSIZE, pic);
		printf("Encoding Frame %i, to %s\n", i, outname);
		fwrite(output, 1, outsz, outf);
	}
	
	/*Output delayed by max_b_frames+2 ??? Frames (says +1) */
	outsz=b_avcodec_encode_video(context, output, BUFFSIZE, pic);
	printf("Encoding Frame %i, to %s\n", i, outname);
	fwrite(output, 1, outsz, outf);

	outsz=b_avcodec_encode_video(context, output, BUFFSIZE, pic);
	printf("Encoding Frame %i, to %s\n", i, outname);
	fwrite(output, 1, outsz, outf);
	
	outsz=b_avcodec_encode_video(context, output, BUFFSIZE, pic);
	printf("Encoding Frame %i, to %s\n", i, outname);
	fwrite(output, 1, outsz, outf);
	
	/*end sequnce*/
	fwrite("\0x00\0x00\0x01\0xb7", 1, 4, outf);
	fclose(outf);
	
	CloseLibAVCodec();
	
	free(context);
	free(pic);
	
	return(0);
}
#endif


short InitLibAVCodec(void){

	char libname[5][23]={"/usr/lib", "/lib", "/usr/local/lib","/usr/lib/avcodec","/usr/lib/local/avcodec" };
	char libstr[128];
	int i=0;
	short libloaded=0;
	
/* Transparently open the lib */ 
	/* Get a handle to the lib */
	while(i<5 && !avcodec_handle){
		strcpy(libstr, libname[i++]);
		strncat(libstr,"/libavcodec.so", 128);
		printf("Trying %s \n", libstr);	
		avcodec_handle=dlopen(libstr, RTLD_LAZY);
	}
	
	/* map the lib's syms to our wrapper */
	if (avcodec_handle) {
		b_avcodec_init = dlsym(avcodec_handle, "avcodec_init");
		libloaded=(b_avcodec_init!=NULL);
		
		b_avcodec_register_all=dlsym(avcodec_handle, "avcodec_register_all");
		libloaded &= (b_avcodec_register_all!=NULL);
		
		b_avcodec_find_encoder=dlsym(avcodec_handle, "avcodec_find_encoder");
		libloaded &= (b_avcodec_find_encoder!=NULL);
		
		b_avcodec_find_decoder=dlsym(avcodec_handle, "avcodec_find_decoder");
		libloaded &= (b_avcodec_find_decoder!=NULL);
		
		b_avcodec_alloc_context=dlsym(avcodec_handle, "avcodec_alloc_context");
		libloaded &= (b_avcodec_alloc_context!=NULL);
		
		b_avcodec_alloc_frame=dlsym(avcodec_handle, "avcodec_alloc_frame");
		libloaded &= (b_avcodec_alloc_frame!=NULL);
		
		b_avcodec_open=dlsym(avcodec_handle, "avcodec_open");
		libloaded &= (b_avcodec_open!=NULL);
		
		b_avcodec_close=dlsym(avcodec_handle, "avcodec_close");
		libloaded &= (b_avcodec_close!=NULL);
		
		b_avcodec_encode_video=dlsym(avcodec_handle, "avcodec_encode_video");
		libloaded &= (b_avcodec_encode_video!=NULL);		
	}
	
	if(libloaded) {
		b_avcodec_init();
		b_avcodec_register_all();
	}
	
	return(libloaded);
}


void CloseLibAVCodec(void){

	if (avcodec_handle) dlclose(avcodec_handle);
}

--Boundary-00=_W6xw/91ODBomES5--