[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--