/* * OpenDivX AVI file writer */ #include #include #include #include "config.h" #include "video_out.h" #include "video_out_internal.h" LIBVO_EXTERN(odivx) #include #include #include #include #include "../encore/encore.h" static vo_info_t vo_info = { "OpenDivX AVI File writer", "odivx", "Arpad Gereoffy ", "" }; static uint8_t *image=NULL; static int image_width=0; static int image_height=0; static char *buffer=NULL; static int frameno=0; extern char* encode_name; extern char* encode_index_name; static uint32_t draw_slice(uint8_t *src[], uint32_t slice_num) { uint8_t *d; // copy Y d=image; memcpy(d+(slice_num<<4)*image_width,src[0],image_width*16); // copy U d+=image_width*image_height; memcpy(d+(slice_num<<2)*image_width,src[1],image_width*4); // copy V d+=image_width*image_height/4; memcpy(d+(slice_num<<2)*image_width,src[2],image_width*4); return 0; } static uint32_t draw_frame(uint8_t *src[]) { uint8_t *d; // copy Y d=image; memcpy(d,src[0],image_width*image_height); // copy U d+=image_width*image_height; memcpy(d,src[1],image_width*image_height/4); // copy V d+=image_width*image_height/4; memcpy(d,src[2],image_width*image_height/4); return 0; } typedef unsigned int DWORD; typedef struct { DWORD ckid; DWORD dwFlags; DWORD dwChunkOffset; // Position of chunk DWORD dwChunkLength; // Length of chunk } AVIINDEXENTRY; static void flip_page(void) { // we are rady to encode this frame ENC_FRAME enc_frame; ENC_RESULT enc_result; if(++frameno<10) return; enc_frame.bmp=image; enc_frame.bitstream=buffer; enc_frame.length=0; encore(0x123,0,&enc_frame,&enc_result); printf("coded length: %d \n",enc_frame.length); if(encode_name){ AVIINDEXENTRY i; FILE *file; i.ckid=('c'<<24)|('d'<<16)|('0'<<8)|'0'; // "00dc" i.dwFlags=enc_result.isKeyFrame?0x10:0; i.dwChunkLength=enc_frame.length; // Write AVI chunk: if((file=fopen(encode_name,"ab"))){ unsigned char zerobyte=0; i.dwChunkOffset=ftell(file); fwrite(&i.ckid,4,1,file); fwrite(&enc_frame.length,4,1,file); fwrite(buffer,enc_frame.length,1,file); if(enc_frame.length&1) fwrite(&zerobyte,1,1,file); // padding fclose(file); } // Write AVI index: if(encode_index_name && (file=fopen(encode_index_name,"ab"))){ fwrite(&i,sizeof(i),1,file); fclose(file); } } } static uint32_t query_format(uint32_t format) { switch(format){ case IMGFMT_YV12: // case IMGFMT_YUY2: // case IMGFMT_RGB|24: // case IMGFMT_BGR|24: return 1; } return 0; } static uint32_t init(uint32_t width, uint32_t height, uint32_t d_width, uint32_t d_height, uint32_t fullscreen, char *title, uint32_t format) { uint32_t frame_size; ENC_PARAM enc_param; buffer=malloc(0x100000); if(!buffer) return -1; // file = fopen("encoded.odvx","wb"); // if(!file) return -1; frame_size=width*height+width*height/2; image_width=width; image_height=height; image=malloc(frame_size); //clear the buffer memset(image,0x80,frame_size); // encoding parameters: enc_param.framerate=25.0; enc_param.bitrate=400000; //780000; enc_param.rc_period=300; enc_param.max_quantizer=15; enc_param.min_quantizer=1; enc_param.search_range=128; // init codec: enc_param.x_dim=width; enc_param.y_dim=height; enc_param.flip=2; // 0=RGB 1=flippedRGB 2=planarYUV format encore(0x123,ENC_OPT_INIT,&enc_param,NULL); return 0; } static const vo_info_t* get_info(void) { return &vo_info; }