xvidInterface.c

00001 /*********************************************************************** 00002 * * 00003 * ViTooKi * 00004 * * 00005 * title: xvidInterface.c * 00006 * * 00007 * * 00008 * * 00009 * ITEC institute of the University of Klagenfurt (Austria) * 00010 * http://www.itec.uni-klu.ac.at * 00011 * * 00012 * * 00013 * For more information visit the ViTooKi homepage: * 00014 * http://ViTooKi.sourceforge.net * 00015 * vitooki-user@lists.sourceforge.net * 00016 * vitooki-devel@lists.sourceforge.net * 00017 * * 00018 * This file is part of ViTooKi, a free video toolkit. * 00019 * ViTooKi is free software; you can redistribute it and/or * 00020 * modify it under the terms of the GNU General Public License * 00021 * as published by the Free Software Foundation; either version 2 * 00022 * of the License, or (at your option) any later version. * 00023 * * 00024 * This program is distributed in the hope that it will be useful, * 00025 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00026 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00027 * GNU General Public License for more details. * 00028 * * 00029 * You should have received a copy of the GNU General Public License * 00030 * along with this program; if not, write to the Free Software * 00031 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * 00032 * MA 02111-1307, USA. * 00033 * * 00034 ***********************************************************************/ 00035 00036 /*********************************************************************** 00037 * * 00038 * REVISION HISTORY: * 00039 * * 00040 * * 00041 * * 00042 ***********************************************************************/ 00043 00044 00045 #include "xvidInterface.h" //our own colorspace enum 00046 #ifdef ENABLE_XVID 00047 #ifndef ARCH_X86 00048 #define ARCH_X86 00049 #endif 00050 #define BFRAMES 00051 00052 #include "xvid.h" //the external library 00053 #ifndef WINCE 00054 #include "bitstream/bitstream.h" 00055 #endif 00056 #endif 00057 00058 00059 00060 00062 // WINDOWS CE DEFINITIONS Start 00064 00065 #ifdef WINCE 00066 00067 #include <afxwin.h> // MFC core and standard components 00068 00069 typedef DWORD dword; 00070 00071 #include "CodecAPI.h" 00072 00073 HINSTANCE hDll; 00074 void *hXvid; 00075 00076 /* 00077 #define FCC(a, b, c, d) DWORD((d<<24) | (c<<16) | (b<<8) | a) 00078 00079 00080 //void *InitCodec(dword sx, dword sy, dword fcc); 00081 typedef void * (CALLBACK *LPFNInitCodec) (DWORD sx, DWORD sy, DWORD fcc); 00082 00083 //int DecodeFrame(void *handle, const void *buf, dword sz_in, const byte *&y, const byte *&u, const byte *&v, dword &pitch); 00084 typedef int (CALLBACK *LPFNDecodeFrame) (void *, const void *, DWORD, const byte*&, const byte*&, const byte*&, DWORD &); 00085 00086 //void CloseCodec(void *handle); 00087 typedef void (CALLBACK *LPFNCloseCodec) (void *); 00088 00089 00090 00091 LPFNInitCodec InitCodec; 00092 LPFNDecodeFrame DecodeFrame; 00093 LPFNCloseCodec CloseCodec; 00094 */ 00095 00096 #endif 00097 00099 // WINDOWS CE DEFINITIONS End 00101 00102 00103 00104 #include "string.h" 00105 #include <stdio.h> 00106 #include <stdlib.h> 00107 00108 00109 #ifdef WINCE 00110 static int xvid_FrameWidth = 0; 00111 static int xvid_FrameHeight = 0; 00112 #endif 00113 00114 00115 #ifdef WINCE 00116 void XvidSetWidth(int width) 00117 { 00118 xvid_FrameWidth = width; 00119 } 00120 00121 void XvidSetHeight(int height) 00122 { 00123 xvid_FrameHeight = height; 00124 } 00125 #endif 00126 00127 00128 /* 00129 static int write_ppm(char *filename, unsigned char *image, int iWidth, int iHeight) 00130 { 00131 FILE *filehandle; 00132 filehandle=fopen(filename,"wb"); 00133 if (filehandle) 00134 { 00135 fprintf(filehandle,"P6\n\n"); 00136 fprintf(filehandle,"%d %d 255\n",iWidth,iHeight); 00137 fwrite(image,iWidth,iHeight*3,filehandle); 00138 00139 fclose(filehandle); 00140 return 0; 00141 } 00142 else 00143 return 1; 00144 } 00145 */ 00146 00147 00148 int XVIDDecoderInit2(char **pDecoderHandle, unsigned int uiWidth, unsigned int uiHeight) { 00149 #ifndef ENABLE_XVID 00150 fprintf(stderr,"XVIDDecoderInit2: xvid disabled in this build!\n"); 00151 exit(2); 00152 #else 00153 00154 00155 #ifdef WINCE 00156 /*hDll = ::LoadLibrary(_T("\\Windows\\Codecs\\xvid_ppc.dll")); 00157 InitCodec = (LPFNInitCodec) GetProcAddress(hDll, TEXT("InitCodec")); 00158 DecodeFrame = (LPFNDecodeFrame) GetProcAddress(hDll, TEXT("DecodeFrame")); 00159 CloseCodec = (LPFNCloseCodec) GetProcAddress(hDll, TEXT("CloseCodec"));*/ 00160 00161 hXvid = InitCodec(xvid_FrameWidth, xvid_FrameHeight, FCC('x', 'v', 'i', 'd')); 00162 *pDecoderHandle = (char*) hXvid; 00163 if (hXvid != NULL) 00164 return ERR_OK; 00165 else 00166 return ERR; 00167 00168 #else 00169 uint32_t temp; 00170 xvid_gbl_init_t init_param; 00171 xvid_dec_create_t param; 00172 00173 memset(&init_param, 0, sizeof(xvid_gbl_init_t)); 00174 memset(&param, 0, sizeof(xvid_dec_create_t)); 00175 init_param.version = XVID_VERSION; 00176 fprintf(stderr,"xvid: version=%d.%d.%d\n", XVID_VERSION_MAJOR(init_param.version), XVID_VERSION_MINOR(init_param.version), XVID_VERSION_PATCH(init_param.version)); 00177 init_param.debug = 0; 00178 00179 00180 init_param.cpu_flags = 0; 00181 xvid_global(NULL, 0, &init_param, NULL); 00182 00183 param.height = 0; 00184 param.width = 0; 00185 param.version = XVID_VERSION; 00186 00187 temp = xvid_decore(NULL, XVID_DEC_CREATE, &param, NULL); 00188 fprintf(stderr,"xvid_decore (init) : temp=%d\n", temp); 00189 00190 if (temp == XVID_ERR_FAIL || temp == XVID_ERR_MEMORY || temp == XVID_ERR_FORMAT || temp == XVID_ERR_VERSION || temp == XVID_ERR_END) { 00191 return ERR; 00192 } else { 00193 *pDecoderHandle = (char*)param.handle; 00194 } 00195 00196 fprintf(stderr, "xvid_init : OK!\n"); 00197 return ERR_OK; 00198 00199 #endif 00200 00201 #endif //enable xvid 00202 00203 return ERR; 00204 } 00205 00206 00207 void XVIDDecoderClose(char **pDecoderHandle) { 00208 #ifndef ENABLE_XVID 00209 fprintf(stderr,"XVIDDecoderClose: xvid disabled in this build!\n"); 00210 exit(2); 00211 #else 00212 #ifdef WINCE 00213 CloseCodec(hXvid); 00214 #else 00215 xvid_decore((DECODER*) (*pDecoderHandle), XVID_DEC_DESTROY, NULL, NULL); 00216 *pDecoderHandle = NULL; 00217 #endif 00218 #endif 00219 } 00220 00221 int XVIDDecoderGetWidth(char *pDecoderHandle) { 00222 #ifndef ENABLE_XVID 00223 fprintf(stderr,"XVIDDecoderGetWidth: xvid disabled in this build!\n"); 00224 exit(2); 00225 #else 00226 00227 #ifndef WINCE 00228 if(pDecoderHandle != NULL) 00229 { 00230 return ((DECODER *)pDecoderHandle)->width; 00231 } 00232 #else 00233 return xvid_FrameWidth; 00234 #endif 00235 00236 return 0; 00237 #endif 00238 } 00239 00240 00241 int XVIDDecoderGetHeight(char *pDecoderHandle) { 00242 #ifndef ENABLE_XVID 00243 fprintf(stderr,"XVIDDecoderGetHeight: xvid disabled in this build!\n"); 00244 exit(2); 00245 #else 00246 00247 #ifndef WINCE 00248 if(pDecoderHandle != NULL) 00249 { 00250 return ((DECODER *)pDecoderHandle)->height; 00251 } 00252 #else 00253 return xvid_FrameHeight; 00254 #endif 00255 00256 return 0; 00257 #endif 00258 } 00259 00260 00261 int XVIDDecodeFrame(char *pDecoderHandle, char *pCompressedFrame, int iCFSize, char* pYUVFrame, xvidColorSpace eColorSpace) { 00262 #ifndef ENABLE_XVID 00263 fprintf(stderr,"XVIDDecodeFrame: xvid disabled in this build!\n"); 00264 exit(2); 00265 #else 00266 00267 #ifndef WINCE 00268 xvid_dec_frame_t frame; 00269 00270 int ret = 0; 00271 00272 frame.version = XVID_VERSION; 00273 00274 if(pDecoderHandle != NULL) { 00275 frame.bitstream = pCompressedFrame; 00276 frame.length = iCFSize; 00277 frame.output.plane[0] = pYUVFrame; 00278 frame.output.stride[0] = XVIDDecoderGetWidth(pDecoderHandle); 00279 frame.output.csp = eColorSpace; 00280 00281 ret = xvid_decore(pDecoderHandle, XVID_DEC_DECODE, &frame, NULL); 00282 // fprintf(stderr, "xvid decode frame: ret=%d\n", ret); 00283 if (ret == XVID_ERR_FAIL || ret == XVID_ERR_MEMORY || ret == XVID_ERR_FORMAT || ret == XVID_ERR_VERSION || ret == XVID_ERR_END) 00284 return ret; 00285 else 00286 return frame.length; 00287 } 00288 #else 00289 DWORD pitch; 00290 byte *bufY, *bufU, *bufV; 00291 00292 00293 int mb_width = (xvid_FrameWidth + 15) / 16; 00294 int edgedWidth = (16 * mb_width + 2 * EDGE_SIZE); 00295 00296 int size = xvid_FrameHeight * edgedWidth; 00297 00298 int length = DecodeFrame(hXvid, pCompressedFrame, iCFSize, bufY, bufU, bufV, pitch); 00299 00300 if (length > 0) { 00301 00302 int size = xvid_FrameHeight * pitch; 00303 int i,j,k; 00304 for (i=0;i<xvid_FrameHeight;i++) memcpy(pYUVFrame + xvid_FrameWidth*i, bufY + pitch*i, xvid_FrameWidth); 00305 for (j=0;j<xvid_FrameHeight/2;j++) memcpy(pYUVFrame + xvid_FrameWidth*i + xvid_FrameWidth/2*j, bufU + pitch/2*j, xvid_FrameWidth/2); 00306 for (k=0;k<xvid_FrameHeight/2;k++) memcpy(pYUVFrame + xvid_FrameWidth*i + xvid_FrameWidth/2*j + xvid_FrameWidth/2*k, bufV + pitch/2*k, xvid_FrameWidth/2); 00307 00308 00309 return length; 00310 } 00311 #endif 00312 00313 return -999; 00314 #endif 00315 } 00316 00317 00318 00319 00320 #ifdef WINCE 00321 00322 int XVIDDecodeFrameCE(char *pCompressedFrame, int iCFSize, unsigned char *&y, unsigned char *&u, unsigned char *&v) { 00323 #ifndef ENABLE_XVID 00324 fprintf(stderr,"XVIDDecodeFrame: xvid disabled in this build!\n"); 00325 exit(2); 00326 #else 00327 00328 DWORD pitch; 00329 int length = DecodeFrame(hXvid, pCompressedFrame, iCFSize, y, u, v, pitch); 00330 00331 if (length > 0) { 00332 return length; 00333 } 00334 00335 return -999; 00336 #endif 00337 } 00338 00339 #endif 00340 00341 00342 00343 00344 int XVIDDecodeFile2(char *in, char *out, unsigned int uiWidth, unsigned int uiHeight, xvidColorSpace iColorSpace) { 00345 #ifndef WINCE 00346 #ifndef ENABLE_XVID 00347 fprintf(stderr,"XVIDDecodeFile2: xvid disabled in this build!\n"); 00348 exit(2); 00349 #else 00350 00351 int ch = 0; 00352 int startCode = 0; 00353 int framesRead = 0; 00354 00355 char *inBuf = (char*)malloc(sizeof(char)*MAX_FRAME_SIZE); 00356 char *outBuf = (char*)malloc(sizeof(char)*MAX_FRAME_SIZE); 00357 00358 int width, height, i=0; 00359 DECODER *dec = NULL; 00360 long readed = 0; 00361 long used; 00362 00363 FILE *fpi=fopen(in,"rb"), 00364 *fpo=fopen(out,"wb"); 00365 if (fpi == NULL || fpo==NULL){ 00366 if (fpi) 00367 fclose(fpi); 00368 if (fpo) 00369 fclose(fpo); 00370 return(ERR_FILE); 00371 } 00372 00373 // Read headers and first frame 00374 while(startCode != 0x1B6 && !feof(fpi)) 00375 { 00376 ch = getc(fpi); 00377 startCode = (startCode << 8) | ch; 00378 inBuf[readed] = (char) ch; 00379 readed++; 00380 if(startCode == 0x1B6) 00381 { 00382 if(framesRead == 1) 00383 00384 { 00385 fseek(fpi, -4, SEEK_CUR); 00386 readed -= 5; 00387 } 00388 else 00389 { 00390 framesRead = 1; 00391 startCode = 0; 00392 } 00393 } 00394 } 00395 00396 // DecoderInit((char**)(&dec), inBuf, readed); 00397 XVIDDecoderInit2((char**)(&dec), uiWidth, uiHeight); 00398 00399 if(dec != NULL) 00400 { 00401 width = XVIDDecoderGetWidth((char *)dec); 00402 height = XVIDDecoderGetHeight((char *)dec); 00403 // because START_CODE must be 32bit 00404 while(readed >= 4){ 00405 printf("Decode Frame %d ",i++); 00406 used = XVIDDecodeFrame((char *)dec, inBuf, readed, outBuf, XVIDColorSpaceI420); 00407 printf(" used %li\n", used); 00408 00409 00410 // Write decoded YUV image, size = width * height * 3 / 2 because in I420 CSP 00411 fwrite(outBuf, 1, width * height * 3 / 2, fpo); 00412 // write_ppm("test.ppm", outBuf, width, height); // RGB32 colorspace 00413 00414 fflush(fpo); 00415 00416 readed = fread(inBuf, 1, 4, fpi); 00417 startCode = 0; 00418 while(startCode != 0x1B6 && !feof(fpi)) 00419 { 00420 ch = getc(fpi); 00421 startCode = (startCode << 8) | ch; 00422 inBuf[readed] = (char) ch; 00423 readed++; 00424 if(startCode == 0x1B6) 00425 { 00426 if(framesRead == 1) 00427 00428 { 00429 fseek(fpi, -4, SEEK_CUR); 00430 readed -= 5; 00431 } 00432 else 00433 { 00434 framesRead = 1; 00435 startCode = 0; 00436 } 00437 } 00438 } 00439 } 00440 00441 XVIDDecoderClose( (char **)(&dec)); 00442 } 00443 00444 fclose(fpi); 00445 fclose(fpo); 00446 return(ERR_OK); 00447 #endif 00448 #else //wince 00449 return ERR; 00450 #endif //wince 00451 } 00452 00453 00454 00455 int XVIDEncoderInit(char **pEncoderHandle, int iWidth, int iHeight, int bitrate, int iFramerate, int numBFrames) { 00456 #ifndef ENABLE_XVID 00457 fprintf(stderr,"XVIDEncoderInit: xvid disabled in this build!\n"); 00458 exit(2); 00459 #else 00460 00461 00462 #ifdef WINCE 00463 00464 /* 00465 hDll = ::LoadLibrary(_T("\\Windows\\Codecs\\xvid_ppc.dll")); 00466 InitCodec = (LPFNInitCodec) GetProcAddress(hDll, TEXT("InitCodec")); 00467 DecodeFrame = (LPFNDecodeFrame) GetProcAddress(hDll, TEXT("DecodeFrame")); 00468 CloseCodec = (LPFNCloseCodec) GetProcAddress(hDll, TEXT("CloseCodec")); 00469 */ 00470 00471 hXvid = InitCodec(xvid_FrameWidth, xvid_FrameHeight, FCC('x', 'v', 'i', 'd')); 00472 return ERR_OK; 00473 00474 #else 00475 00476 xvid_gbl_init_t init_param; 00477 xvid_enc_create_t param; 00478 00479 int ret = 0; 00480 00481 // get Xvid core status 00482 init_param.cpu_flags = 0; 00483 xvid_global(NULL, 0, &init_param, NULL); 00484 00485 // Check API Version is 2.1? 00486 if (init_param.version != ((2<<16)|(1))) 00487 return(-2); 00488 00489 param.width = iWidth; 00490 param.height = iHeight; 00491 00492 param.profile = XVID_PROFILE_AS_L3; 00493 param.num_zones = 1; 00494 00495 00496 param.fincr = 1; // FIXME: fincr=1000 and fbase=23996 for float fps 00497 param.fbase = iFramerate; 00498 00499 param.min_quant[0] = 1; 00500 param.min_quant[0] = 31; 00501 00502 param.max_key_interval = iFramerate * 10; 00503 00504 // FIXME: how to enable b-frame encoding for xvid??? 00505 // param.max_bframes = numBFrames; 00506 // use_bidirect is only defined for divx4, not xvid 00507 // param.use_bidirect = 1;/*enable*/ 00508 00509 ret = xvid_encore(0, XVID_ENC_CREATE, &param, NULL); 00510 *pEncoderHandle = (char*)param.handle; 00511 if(ret == 0 && *pEncoderHandle != NULL) 00512 return ERR_OK; 00513 else 00514 return ERR; 00515 #endif //wince 00516 00517 #endif //enable_xvid 00518 00519 return ERR; 00520 } 00521 00522 void XVIDEncoderClose(char **pEncoderHandle) { 00523 #ifndef WINCE 00524 #ifndef ENABLE_XVID 00525 fprintf(stderr,"XVIDEncoderClose: xvid disabled in this build!\n"); 00526 exit(2); 00527 #else 00528 if (*pEncoderHandle) 00529 xvid_encore(*pEncoderHandle, XVID_ENC_DESTROY, NULL, NULL); 00530 *pEncoderHandle = NULL; 00531 #endif 00532 #endif //wince 00533 } 00534 00535 int XVIDEncodeFrame(char *pEncoderHandle, char *inBuf, char *outBuf, xvidColorSpace eColorSpace, int forceIFrame) { 00536 #ifndef WINCE 00537 #ifndef ENABLE_XVID 00538 fprintf(stderr,"XVIDEncodeFrame: xvid disabled in this build!\n"); 00539 exit(2); 00540 #else 00541 00542 xvid_enc_frame_t frame; 00543 xvid_enc_stats_t stats; 00544 00545 // set encode frame param 00546 frame.vop_flags = XVID_VOP_HALFPEL | XVID_VOP_INTER4V; 00547 frame.motion = XVID_ME_ADVANCEDDIAMOND8; 00548 frame.input.plane[0] = inBuf; 00549 00550 00551 frame.bitstream = outBuf; 00552 frame.length = MAX_FRAME_SIZE; 00553 frame.input.csp = eColorSpace; 00554 frame.quant = 0; // CBR mode 00555 00556 frame.vol_flags = XVID_VOL_MPEGQUANT; 00557 00558 frame.quant_inter_matrix = NULL; // Use default quant matrix 00559 frame.quant_intra_matrix = NULL; 00560 00561 if (forceIFrame == 1) frame.vop_flags |= XVID_TYPE_IVOP; 00562 00563 xvid_encore(pEncoderHandle, XVID_ENC_ENCODE, &frame, &stats); 00564 00565 return frame.length; 00566 #endif 00567 #else //wince 00568 return ERR; 00569 #endif //wince 00570 } 00571 00572 00573 int XVIDEncodeFile(char *in, int width, int height, int bitrate, xvidColorSpace iColorSpace, char *out) { 00574 #ifndef WINCE 00575 #ifndef ENABLE_XVID 00576 fprintf(stderr,"XVIDEncodeFile: xvid disabled in this build!\n"); 00577 exit(2); 00578 #else 00579 00580 char inBuf[MAX_FRAME_SIZE]; // Image Buffer 00581 char outBuf[MAX_FRAME_SIZE]; 00582 00583 Encoder *pEnc = NULL; // handle to encoder 00584 int num=0; // Encoded frames 00585 int len = 0; 00586 int temp; 00587 00588 FILE *fpi=fopen(in,"rb"), 00589 *fpo=fopen(out,"wb"); 00590 if (fpi == NULL || fpo==NULL){ 00591 if (fpi) 00592 fclose(fpi); 00593 if (fpo) 00594 fclose(fpo); 00595 return(ERR_FILE); 00596 } 00597 00598 if ((unsigned)(height*width*3) > sizeof(inBuf)){ 00599 fclose(fpi); 00600 fclose(fpo); 00601 return(-1); 00602 } 00603 00604 XVIDEncoderInit((char **) (&pEnc), width, height, bitrate, 25 /*GOP size*/, 0 /* BVOPs */); 00605 00606 // Encode Frame 00607 temp=fread(inBuf, 1, width*height*3/2, fpi); // Read YUV data 00608 00609 while(temp == width*height*3/2){ 00610 printf("Encode Frame=%d ",num); 00611 len = XVIDEncodeFrame((char *) pEnc, inBuf, outBuf, XVIDColorSpaceI420, 0); 00612 printf("len %d\n", len); 00613 fwrite(outBuf, 1, len, fpo); 00614 temp=fread(inBuf, 1, width*height*3/2, fpi); // Read next YUV data 00615 num++; 00616 } 00617 00618 00619 XVIDEncoderClose((char **) &pEnc); 00620 fclose(fpi); 00621 fclose(fpo); 00622 00623 00624 return(ERR_OK); 00625 #endif 00626 #else //wince 00627 return ERR; 00628 #endif //wince 00629 } 00630 00631 00632