|
Blender
V2.59
|
00001 /* 00002 * anim.c 00003 * 00004 * $Id: anim_movie.c 36960 2011-05-27 23:33:40Z schlaile $ 00005 * 00006 * ***** BEGIN GPL LICENSE BLOCK ***** 00007 * 00008 * This program is free software; you can redistribute it and/or 00009 * modify it under the terms of the GNU General Public License 00010 * as published by the Free Software Foundation; either version 2 00011 * of the License, or (at your option) any later version. 00012 * 00013 * This program is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 * GNU General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU General Public License 00019 * along with this program; if not, write to the Free Software Foundation, 00020 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00021 * 00022 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. 00023 * All rights reserved. 00024 * 00025 * The Original Code is: all of this file. 00026 * 00027 * Contributor(s): none yet. 00028 * 00029 * ***** END GPL LICENSE BLOCK ***** 00030 */ 00031 00037 #ifdef _WIN32 00038 #define INC_OLE2 00039 #include <windows.h> 00040 #include <windowsx.h> 00041 #include <mmsystem.h> 00042 #include <memory.h> 00043 #include <commdlg.h> 00044 00045 #ifndef FREE_WINDOWS 00046 #include <vfw.h> 00047 #endif 00048 00049 #undef AVIIF_KEYFRAME // redefined in AVI_avi.h 00050 #undef AVIIF_LIST // redefined in AVI_avi.h 00051 00052 #define FIXCC(fcc) if (fcc == 0) fcc = mmioFOURCC('N', 'o', 'n', 'e'); \ 00053 if (fcc == BI_RLE8) fcc = mmioFOURCC('R', 'l', 'e', '8'); 00054 #endif 00055 00056 #include <sys/types.h> 00057 #include <ctype.h> 00058 #include <stdlib.h> 00059 #include <stdio.h> 00060 #ifndef _WIN32 00061 #include <dirent.h> 00062 #else 00063 #include <io.h> 00064 #endif 00065 00066 #include "BLI_blenlib.h" /* BLI_remlink BLI_filesize BLI_addtail 00067 BLI_countlist BLI_stringdec */ 00068 #include "BLI_utildefines.h" 00069 00070 #include "MEM_guardedalloc.h" 00071 00072 #include "DNA_userdef_types.h" 00073 00074 00075 #include "BKE_global.h" 00076 #include "BKE_depsgraph.h" 00077 00078 #include "imbuf.h" 00079 00080 #include "AVI_avi.h" 00081 00082 #ifdef WITH_QUICKTIME 00083 #if defined(_WIN32) || defined(__APPLE__) 00084 #include "quicktime_import.h" 00085 #endif /* _WIN32 || __APPLE__ */ 00086 #endif /* WITH_QUICKTIME */ 00087 00088 #include "IMB_imbuf_types.h" 00089 #include "IMB_imbuf.h" 00090 00091 #include "IMB_allocimbuf.h" 00092 #include "IMB_anim.h" 00093 00094 #ifdef WITH_FFMPEG 00095 #include <libavformat/avformat.h> 00096 #include <libavcodec/avcodec.h> 00097 #include <libavutil/rational.h> 00098 #include <libswscale/swscale.h> 00099 00100 #include "ffmpeg_compat.h" 00101 00102 #endif //WITH_FFMPEG 00103 00104 #ifdef WITH_REDCODE 00105 #ifdef _WIN32 /* on windows we use the ones in extern instead */ 00106 #include "libredcode/format.h" 00107 #include "libredcode/codec.h" 00108 #else 00109 #include "libredcode/format.h" 00110 #include "libredcode/codec.h" 00111 #endif 00112 #endif 00113 00114 /****/ 00115 00116 #ifdef __sgi 00117 00118 #include <dmedia/moviefile.h> 00119 00120 static void movie_printerror(char * str) { 00121 const char * errstr = mvGetErrorStr(mvGetErrno()); 00122 00123 if (str) { 00124 if (errstr) printf("%s: %s\n", str, errstr); 00125 else printf("%s: returned error\n", str); 00126 } else printf("%s\n", errstr); 00127 } 00128 00129 static int startmovie(struct anim * anim) { 00130 if (anim == 0) return(-1); 00131 00132 if ( mvOpenFile (anim->name, O_BINARY|O_RDONLY, &anim->movie ) != DM_SUCCESS ) { 00133 printf("Can't open movie: %s\n", anim->name); 00134 return(-1); 00135 } 00136 if ( mvFindTrackByMedium (anim->movie, DM_IMAGE, &anim->track) != DM_SUCCESS ) { 00137 printf("No image track in movie: %s\n", anim->name); 00138 mvClose(anim->movie); 00139 return(-1); 00140 } 00141 00142 anim->duration = mvGetTrackLength (anim->track); 00143 anim->params = mvGetParams( anim->track ); 00144 00145 anim->x = dmParamsGetInt( anim->params, DM_IMAGE_WIDTH); 00146 anim->y = dmParamsGetInt( anim->params, DM_IMAGE_HEIGHT); 00147 anim->interlacing = dmParamsGetEnum (anim->params, DM_IMAGE_INTERLACING); 00148 anim->orientation = dmParamsGetEnum (anim->params, DM_IMAGE_ORIENTATION); 00149 anim->framesize = dmImageFrameSize(anim->params); 00150 00151 anim->curposition = 0; 00152 anim->preseek = 0; 00153 00154 /*printf("x:%d y:%d size:%d interl:%d dur:%d\n", anim->x, anim->y, anim->framesize, anim->interlacing, anim->duration);*/ 00155 return (0); 00156 } 00157 00158 static ImBuf * movie_fetchibuf(struct anim * anim, int position) { 00159 ImBuf * ibuf; 00160 /* extern rectcpy(); */ 00161 int size; 00162 unsigned int *rect1, *rect2; 00163 00164 if (anim == 0) return (0); 00165 00166 ibuf = IMB_allocImBuf(anim->x, anim->y, 24, IB_rect); 00167 00168 if ( mvReadFrames(anim->track, position, 1, ibuf->x * ibuf->y * 00169 sizeof(int), ibuf->rect ) != DM_SUCCESS ) { 00170 movie_printerror("mvReadFrames"); 00171 IMB_freeImBuf(ibuf); 00172 return(0); 00173 } 00174 00175 /* 00176 if (anim->interlacing == DM_IMAGE_INTERLACED_EVEN) { 00177 rect1 = ibuf->rect + (ibuf->x * ibuf->y) - 1; 00178 rect2 = rect1 - ibuf->x; 00179 00180 for (size = ibuf->x * (ibuf->y - 1); size > 0; size--){ 00181 *rect1-- = *rect2--; 00182 } 00183 } 00184 */ 00185 00186 if (anim->interlacing == DM_IMAGE_INTERLACED_EVEN) 00187 { 00188 rect1 = ibuf->rect; 00189 rect2 = rect1 + ibuf->x; 00190 00191 for (size = ibuf->x * (ibuf->y - 1); size > 0; size--){ 00192 *rect1++ = *rect2++; 00193 } 00194 } 00195 /*if (anim->orientation == DM_TOP_TO_BOTTOM) IMB_flipy(ibuf);*/ 00196 00197 00198 return(ibuf); 00199 } 00200 00201 static void free_anim_movie(struct anim * anim) { 00202 if (anim == NULL) return; 00203 00204 if (anim->movie) { 00205 mvClose(anim->movie); 00206 anim->movie = NULL; 00207 } 00208 anim->duration = 0; 00209 } 00210 00211 int ismovie(char *name) { 00212 return (mvIsMovieFile(name) == DM_TRUE); 00213 } 00214 00215 #else 00216 00217 int ismovie(const char *UNUSED(name)) { 00218 return 0; 00219 } 00220 00221 /* never called, just keep the linker happy */ 00222 static int startmovie(struct anim *UNUSED(anim)) { return 1; } 00223 static ImBuf * movie_fetchibuf(struct anim *UNUSED(anim), int UNUSED(position)) { return NULL; } 00224 static void free_anim_movie(struct anim *UNUSED(anim)) { ; } 00225 00226 #endif 00227 00228 #if defined(_WIN32) 00229 # define PATHSEPERATOR '\\' 00230 #else 00231 # define PATHSEPERATOR '/' 00232 #endif 00233 00234 static int an_stringdec(const char *string, char* head, char *tail, unsigned short *numlen) { 00235 unsigned short len,nume,nums=0; 00236 short i,found=FALSE; 00237 00238 len=strlen(string); 00239 nume = len; 00240 00241 for(i=len-1;i>=0;i--){ 00242 if (string[i]==PATHSEPERATOR) break; 00243 if (isdigit(string[i])) { 00244 if (found){ 00245 nums=i; 00246 } else{ 00247 nume=i; 00248 nums=i; 00249 found=TRUE; 00250 } 00251 } else{ 00252 if (found) break; 00253 } 00254 } 00255 if (found){ 00256 strcpy(tail ,&string[nume+1]); 00257 strcpy(head, string); 00258 head[nums]= '\0'; 00259 *numlen=nume-nums+1; 00260 return ((int)atoi(&(string[nums]))); 00261 } 00262 tail[0]= '\0'; 00263 strcpy(head, string); 00264 *numlen=0; 00265 return TRUE; 00266 } 00267 00268 00269 static void an_stringenc(char *string, const char *head, const char *tail, unsigned short numlen, int pic) { 00270 BLI_stringenc(string, head, tail, numlen, pic); 00271 } 00272 00273 static void free_anim_avi (struct anim *anim) { 00274 #if defined(_WIN32) && !defined(FREE_WINDOWS) 00275 int i; 00276 #endif 00277 00278 if (anim == NULL) return; 00279 if (anim->avi == NULL) return; 00280 00281 AVI_close (anim->avi); 00282 MEM_freeN (anim->avi); 00283 anim->avi = NULL; 00284 00285 #if defined(_WIN32) && !defined(FREE_WINDOWS) 00286 00287 if (anim->pgf) { 00288 AVIStreamGetFrameClose(anim->pgf); 00289 anim->pgf = NULL; 00290 } 00291 00292 for (i = 0; i < anim->avistreams; i++){ 00293 AVIStreamRelease(anim->pavi[i]); 00294 } 00295 anim->avistreams = 0; 00296 00297 if (anim->pfileopen) { 00298 AVIFileRelease(anim->pfile); 00299 anim->pfileopen = 0; 00300 AVIFileExit(); 00301 } 00302 #endif 00303 00304 anim->duration = 0; 00305 } 00306 00307 void IMB_free_anim_ibuf(struct anim * anim) { 00308 if (anim == NULL) return; 00309 00310 if (anim->ibuf1) IMB_freeImBuf(anim->ibuf1); 00311 if (anim->ibuf2) IMB_freeImBuf(anim->ibuf2); 00312 00313 anim->ibuf1 = anim->ibuf2 = NULL; 00314 } 00315 00316 #ifdef WITH_FFMPEG 00317 static void free_anim_ffmpeg(struct anim * anim); 00318 #endif 00319 #ifdef WITH_REDCODE 00320 static void free_anim_redcode(struct anim * anim); 00321 #endif 00322 00323 void IMB_free_anim(struct anim * anim) { 00324 if (anim == NULL) { 00325 printf("free anim, anim == NULL\n"); 00326 return; 00327 } 00328 00329 IMB_free_anim_ibuf(anim); 00330 free_anim_movie(anim); 00331 free_anim_avi(anim); 00332 00333 #ifdef WITH_QUICKTIME 00334 free_anim_quicktime(anim); 00335 #endif 00336 #ifdef WITH_FFMPEG 00337 free_anim_ffmpeg(anim); 00338 #endif 00339 #ifdef WITH_REDCODE 00340 free_anim_redcode(anim); 00341 #endif 00342 00343 MEM_freeN(anim); 00344 } 00345 00346 void IMB_close_anim(struct anim * anim) { 00347 if (anim == NULL) return; 00348 00349 IMB_free_anim(anim); 00350 } 00351 00352 00353 struct anim * IMB_open_anim( const char * name, int ib_flags) { 00354 struct anim * anim; 00355 00356 anim = (struct anim*)MEM_callocN(sizeof(struct anim), "anim struct"); 00357 if (anim != NULL) { 00358 strcpy(anim->name, name); /* fixme: possible buffer overflow here? */ 00359 anim->ib_flags = ib_flags; 00360 } 00361 return(anim); 00362 } 00363 00364 00365 static int startavi (struct anim *anim) { 00366 00367 AviError avierror; 00368 #if defined(_WIN32) && !defined(FREE_WINDOWS) 00369 HRESULT hr; 00370 int i, firstvideo = -1; 00371 BYTE abFormat[1024]; 00372 LONG l; 00373 LPBITMAPINFOHEADER lpbi; 00374 AVISTREAMINFO avis; 00375 #endif 00376 00377 anim->avi = MEM_callocN (sizeof(AviMovie),"animavi"); 00378 00379 if (anim->avi == NULL) { 00380 printf("Can't open avi: %s\n", anim->name); 00381 return -1; 00382 } 00383 00384 avierror = AVI_open_movie (anim->name, anim->avi); 00385 00386 #if defined(_WIN32) && !defined(FREE_WINDOWS) 00387 if (avierror == AVI_ERROR_COMPRESSION) { 00388 AVIFileInit(); 00389 hr = AVIFileOpen(&anim->pfile, anim->name, OF_READ, 0L); 00390 if (hr == 0) { 00391 anim->pfileopen = 1; 00392 for (i = 0; i < MAXNUMSTREAMS; i++) { 00393 if (AVIFileGetStream(anim->pfile, &anim->pavi[i], 0L, i) != AVIERR_OK) { 00394 break; 00395 } 00396 00397 AVIStreamInfo(anim->pavi[i], &avis, sizeof(avis)); 00398 if ((avis.fccType == streamtypeVIDEO) && (firstvideo == -1)) { 00399 anim->pgf = AVIStreamGetFrameOpen(anim->pavi[i], NULL); 00400 if (anim->pgf) { 00401 firstvideo = i; 00402 00403 // get stream length 00404 anim->avi->header->TotalFrames = AVIStreamLength(anim->pavi[i]); 00405 00406 // get information about images inside the stream 00407 l = sizeof(abFormat); 00408 AVIStreamReadFormat(anim->pavi[i], 0, &abFormat, &l); 00409 lpbi = (LPBITMAPINFOHEADER)abFormat; 00410 anim->avi->header->Height = lpbi->biHeight; 00411 anim->avi->header->Width = lpbi->biWidth; 00412 } else { 00413 FIXCC(avis.fccHandler); 00414 FIXCC(avis.fccType); 00415 printf("Can't find AVI decoder for type : %4.4hs/%4.4hs\n", 00416 (LPSTR)&avis.fccType, 00417 (LPSTR)&avis.fccHandler); 00418 } 00419 } 00420 } 00421 00422 // register number of opened avistreams 00423 anim->avistreams = i; 00424 00425 // 00426 // Couldn't get any video streams out of this file 00427 // 00428 if ((anim->avistreams == 0) || (firstvideo == -1)) { 00429 avierror = AVI_ERROR_FORMAT; 00430 } else { 00431 avierror = AVI_ERROR_NONE; 00432 anim->firstvideo = firstvideo; 00433 } 00434 } else { 00435 AVIFileExit(); 00436 } 00437 } 00438 #endif 00439 00440 if (avierror != AVI_ERROR_NONE) { 00441 AVI_print_error(avierror); 00442 printf ("Error loading avi: %s\n", anim->name); 00443 free_anim_avi(anim); 00444 return -1; 00445 } 00446 00447 anim->duration = anim->avi->header->TotalFrames; 00448 anim->params = NULL; 00449 00450 anim->x = anim->avi->header->Width; 00451 anim->y = anim->avi->header->Height; 00452 anim->interlacing = 0; 00453 anim->orientation = 0; 00454 anim->framesize = anim->x * anim->y * 4; 00455 00456 anim->curposition = 0; 00457 anim->preseek = 0; 00458 00459 /* printf("x:%d y:%d size:%d interl:%d dur:%d\n", anim->x, anim->y, anim->framesize, anim->interlacing, anim->duration);*/ 00460 00461 return 0; 00462 } 00463 00464 static ImBuf * avi_fetchibuf (struct anim *anim, int position) { 00465 ImBuf *ibuf = NULL; 00466 int *tmp; 00467 int y; 00468 00469 if (anim == NULL) return (NULL); 00470 00471 #if defined(_WIN32) && !defined(FREE_WINDOWS) 00472 if (anim->avistreams) { 00473 LPBITMAPINFOHEADER lpbi; 00474 00475 if (anim->pgf) { 00476 lpbi = AVIStreamGetFrame(anim->pgf, position + AVIStreamStart(anim->pavi[anim->firstvideo])); 00477 if (lpbi) { 00478 ibuf = IMB_ibImageFromMemory((unsigned char *) lpbi, 100, IB_rect); 00479 //Oh brother... 00480 } 00481 } 00482 } else { 00483 #else 00484 if (1) { 00485 #endif 00486 ibuf = IMB_allocImBuf (anim->x, anim->y, 24, IB_rect); 00487 00488 tmp = AVI_read_frame (anim->avi, AVI_FORMAT_RGB32, position, 00489 AVI_get_stream(anim->avi, AVIST_VIDEO, 0)); 00490 00491 if (tmp == NULL) { 00492 printf ("Error reading frame from AVI"); 00493 IMB_freeImBuf (ibuf); 00494 return NULL; 00495 } 00496 00497 for (y=0; y < anim->y; y++) { 00498 memcpy (&(ibuf->rect)[((anim->y-y)-1)*anim->x], &tmp[y*anim->x], 00499 anim->x * 4); 00500 } 00501 00502 MEM_freeN (tmp); 00503 } 00504 00505 ibuf->profile = IB_PROFILE_SRGB; 00506 00507 return ibuf; 00508 } 00509 00510 #ifdef WITH_FFMPEG 00511 00512 extern void do_init_ffmpeg(void); 00513 00514 static int startffmpeg(struct anim * anim) { 00515 int i, videoStream; 00516 00517 AVCodec *pCodec; 00518 AVFormatContext *pFormatCtx; 00519 AVCodecContext *pCodecCtx; 00520 00521 #ifdef FFMPEG_SWSCALE_COLOR_SPACE_SUPPORT 00522 /* The following for color space determination */ 00523 int srcRange, dstRange, brightness, contrast, saturation; 00524 int *table; 00525 const int *inv_table; 00526 #endif 00527 00528 if (anim == 0) return(-1); 00529 00530 do_init_ffmpeg(); 00531 00532 if(av_open_input_file(&pFormatCtx, anim->name, NULL, 0, NULL)!=0) { 00533 return -1; 00534 } 00535 00536 if(av_find_stream_info(pFormatCtx)<0) { 00537 av_close_input_file(pFormatCtx); 00538 return -1; 00539 } 00540 00541 av_dump_format(pFormatCtx, 0, anim->name, 0); 00542 00543 00544 /* Find the first video stream */ 00545 videoStream=-1; 00546 for(i=0; i<pFormatCtx->nb_streams; i++) 00547 if(pFormatCtx->streams[i]->codec->codec_type 00548 == AVMEDIA_TYPE_VIDEO) { 00549 videoStream=i; 00550 break; 00551 } 00552 00553 if(videoStream==-1) { 00554 av_close_input_file(pFormatCtx); 00555 return -1; 00556 } 00557 00558 pCodecCtx = pFormatCtx->streams[videoStream]->codec; 00559 00560 /* Find the decoder for the video stream */ 00561 pCodec=avcodec_find_decoder(pCodecCtx->codec_id); 00562 if(pCodec==NULL) { 00563 av_close_input_file(pFormatCtx); 00564 return -1; 00565 } 00566 00567 pCodecCtx->workaround_bugs = 1; 00568 00569 if(avcodec_open(pCodecCtx, pCodec)<0) { 00570 av_close_input_file(pFormatCtx); 00571 return -1; 00572 } 00573 00574 anim->duration = ceil(pFormatCtx->duration 00575 * av_q2d(pFormatCtx->streams[videoStream]->r_frame_rate) 00576 / AV_TIME_BASE); 00577 00578 anim->params = 0; 00579 00580 anim->x = pCodecCtx->width; 00581 anim->y = pCodecCtx->height; 00582 anim->interlacing = 0; 00583 anim->orientation = 0; 00584 anim->framesize = anim->x * anim->y * 4; 00585 00586 anim->curposition = -1; 00587 00588 anim->pFormatCtx = pFormatCtx; 00589 anim->pCodecCtx = pCodecCtx; 00590 anim->pCodec = pCodec; 00591 anim->videoStream = videoStream; 00592 00593 anim->pFrame = avcodec_alloc_frame(); 00594 anim->pFrameDeinterlaced = avcodec_alloc_frame(); 00595 anim->pFrameRGB = avcodec_alloc_frame(); 00596 00597 if (avpicture_get_size(PIX_FMT_RGBA, anim->x, anim->y) 00598 != anim->x * anim->y * 4) { 00599 fprintf (stderr, 00600 "ffmpeg has changed alloc scheme ... ARGHHH!\n"); 00601 avcodec_close(anim->pCodecCtx); 00602 av_close_input_file(anim->pFormatCtx); 00603 av_free(anim->pFrameRGB); 00604 av_free(anim->pFrameDeinterlaced); 00605 av_free(anim->pFrame); 00606 anim->pCodecCtx = NULL; 00607 return -1; 00608 } 00609 00610 if (anim->ib_flags & IB_animdeinterlace) { 00611 avpicture_fill((AVPicture*) anim->pFrameDeinterlaced, 00612 MEM_callocN(avpicture_get_size( 00613 anim->pCodecCtx->pix_fmt, 00614 anim->x, anim->y), 00615 "ffmpeg deinterlace"), 00616 anim->pCodecCtx->pix_fmt, anim->x, anim->y); 00617 } 00618 00619 if (pCodecCtx->has_b_frames) { 00620 anim->preseek = 25; /* FIXME: detect gopsize ... */ 00621 } else { 00622 anim->preseek = 0; 00623 } 00624 00625 anim->img_convert_ctx = sws_getContext( 00626 anim->pCodecCtx->width, 00627 anim->pCodecCtx->height, 00628 anim->pCodecCtx->pix_fmt, 00629 anim->pCodecCtx->width, 00630 anim->pCodecCtx->height, 00631 PIX_FMT_RGBA, 00632 SWS_FAST_BILINEAR | SWS_PRINT_INFO, 00633 NULL, NULL, NULL); 00634 00635 if (!anim->img_convert_ctx) { 00636 fprintf (stderr, 00637 "Can't transform color space??? Bailing out...\n"); 00638 avcodec_close(anim->pCodecCtx); 00639 av_close_input_file(anim->pFormatCtx); 00640 av_free(anim->pFrameRGB); 00641 av_free(anim->pFrameDeinterlaced); 00642 av_free(anim->pFrame); 00643 anim->pCodecCtx = NULL; 00644 return -1; 00645 } 00646 00647 #ifdef FFMPEG_SWSCALE_COLOR_SPACE_SUPPORT 00648 /* Try do detect if input has 0-255 YCbCR range (JFIF Jpeg MotionJpeg) */ 00649 if (!sws_getColorspaceDetails(anim->img_convert_ctx, (int**)&inv_table, &srcRange, 00650 &table, &dstRange, &brightness, &contrast, &saturation)) { 00651 00652 srcRange = srcRange || anim->pCodecCtx->color_range == AVCOL_RANGE_JPEG; 00653 inv_table = sws_getCoefficients(anim->pCodecCtx->colorspace); 00654 00655 if(sws_setColorspaceDetails(anim->img_convert_ctx, (int *)inv_table, srcRange, 00656 table, dstRange, brightness, contrast, saturation)) { 00657 00658 printf("Warning: Could not set libswscale colorspace details.\n"); 00659 } 00660 } 00661 else { 00662 printf("Warning: Could not set libswscale colorspace details.\n"); 00663 } 00664 #endif 00665 00666 return (0); 00667 } 00668 00669 static void ffmpeg_postprocess(struct anim * anim, ImBuf * ibuf, 00670 int * filter_y) 00671 { 00672 AVFrame * input = anim->pFrame; 00673 00674 /* This means the data wasnt read properly, 00675 this check stops crashing */ 00676 if (input->data[0]==0 && input->data[1]==0 00677 && input->data[2]==0 && input->data[3]==0){ 00678 fprintf(stderr, "ffmpeg_fetchibuf: " 00679 "data not read properly...\n"); 00680 return; 00681 } 00682 00683 if (anim->ib_flags & IB_animdeinterlace) { 00684 if (avpicture_deinterlace( 00685 (AVPicture*) 00686 anim->pFrameDeinterlaced, 00687 (const AVPicture*) 00688 anim->pFrame, 00689 anim->pCodecCtx->pix_fmt, 00690 anim->pCodecCtx->width, 00691 anim->pCodecCtx->height) 00692 < 0) { 00693 *filter_y = 1; 00694 } else { 00695 input = anim->pFrameDeinterlaced; 00696 } 00697 } 00698 00699 if (ENDIAN_ORDER == B_ENDIAN) { 00700 int * dstStride = anim->pFrameRGB->linesize; 00701 uint8_t** dst = anim->pFrameRGB->data; 00702 int dstStride2[4] = { dstStride[0], 0, 0, 0 }; 00703 uint8_t* dst2[4] = { dst[0], 0, 0, 0 }; 00704 int x,y,h,w; 00705 unsigned char* bottom; 00706 unsigned char* top; 00707 00708 sws_scale(anim->img_convert_ctx, 00709 (const uint8_t * const *)input->data, 00710 input->linesize, 00711 0, 00712 anim->pCodecCtx->height, 00713 dst2, 00714 dstStride2); 00715 00716 /* workaround: sws_scale bug 00717 sets alpha = 0 and compensate 00718 for altivec-bugs and flipy... */ 00719 00720 bottom = (unsigned char*) ibuf->rect; 00721 top = bottom + ibuf->x * (ibuf->y-1) * 4; 00722 00723 h = (ibuf->y + 1) / 2; 00724 w = ibuf->x; 00725 00726 for (y = 0; y < h; y++) { 00727 unsigned char tmp[4]; 00728 unsigned int * tmp_l = 00729 (unsigned int*) tmp; 00730 tmp[3] = 0xff; 00731 00732 for (x = 0; x < w; x++) { 00733 tmp[0] = bottom[0]; 00734 tmp[1] = bottom[1]; 00735 tmp[2] = bottom[2]; 00736 00737 bottom[0] = top[0]; 00738 bottom[1] = top[1]; 00739 bottom[2] = top[2]; 00740 bottom[3] = 0xff; 00741 00742 *(unsigned int*) top = *tmp_l; 00743 00744 bottom +=4; 00745 top += 4; 00746 } 00747 top -= 8 * w; 00748 } 00749 } else { 00750 int * dstStride = anim->pFrameRGB->linesize; 00751 uint8_t** dst = anim->pFrameRGB->data; 00752 int dstStride2[4] = { -dstStride[0], 0, 0, 0 }; 00753 uint8_t* dst2[4] = { dst[0] + (anim->y - 1)*dstStride[0], 00754 0, 0, 0 }; 00755 int i; 00756 unsigned char* r; 00757 00758 sws_scale(anim->img_convert_ctx, 00759 (const uint8_t * const *)input->data, 00760 input->linesize, 00761 0, 00762 anim->pCodecCtx->height, 00763 dst2, 00764 dstStride2); 00765 00766 r = (unsigned char*) ibuf->rect; 00767 00768 /* workaround sws_scale bug: older version of 00769 sws_scale set alpha = 0... */ 00770 if (r[3] == 0) { 00771 for (i = 0; i < ibuf->x * ibuf->y; i++) { 00772 r[3] = 0xff; 00773 r += 4; 00774 } 00775 } 00776 } 00777 } 00778 00779 static ImBuf * ffmpeg_fetchibuf(struct anim * anim, int position) { 00780 ImBuf * ibuf; 00781 int frameFinished; 00782 AVPacket packet; 00783 int64_t pts_to_search = 0; 00784 int pos_found = 1; 00785 int filter_y = 0; 00786 int seek_by_bytes= 0; 00787 int preseek_count = 0; 00788 00789 if (anim == 0) return (0); 00790 00791 ibuf = IMB_allocImBuf(anim->x, anim->y, 32, IB_rect); 00792 00793 avpicture_fill((AVPicture*) anim->pFrameRGB, 00794 (unsigned char*) ibuf->rect, 00795 PIX_FMT_RGBA, anim->x, anim->y); 00796 00797 if (position != anim->curposition + 1) { 00798 if (position > anim->curposition + 1 00799 && anim->preseek 00800 && position - (anim->curposition + 1) < anim->preseek) { 00801 while(av_read_frame(anim->pFormatCtx, &packet)>=0) { 00802 if (packet.stream_index == anim->videoStream) { 00803 avcodec_decode_video2( 00804 anim->pCodecCtx, 00805 anim->pFrame, &frameFinished, 00806 &packet); 00807 00808 if (frameFinished) { 00809 anim->curposition++; 00810 } 00811 } 00812 av_free_packet(&packet); 00813 if (position == anim->curposition+1) { 00814 break; 00815 } 00816 } 00817 } 00818 } 00819 00820 /* disable seek_by_bytes for now, since bitrates are guessed wrong! 00821 also: MPEG2TS-seeking was fixed in later versions of ffmpeg, so problem 00822 is somewhat fixed by now (until we add correct timecode management code...) 00823 */ 00824 #if 0 00825 seek_by_bytes = !!(anim->pFormatCtx->iformat->flags & AVFMT_TS_DISCONT); 00826 #else 00827 seek_by_bytes = FALSE; 00828 #endif 00829 00830 if (position != anim->curposition + 1) { 00831 double frame_rate = 00832 av_q2d(anim->pFormatCtx->streams[anim->videoStream] 00833 ->r_frame_rate); 00834 double pts_time_base = av_q2d(anim->pFormatCtx->streams[anim->videoStream]->time_base); 00835 long long pos; 00836 long long st_time = anim->pFormatCtx->start_time; 00837 int ret; 00838 00839 if (seek_by_bytes) { 00840 pos = position - anim->preseek; 00841 if (pos < 0) { 00842 pos = 0; 00843 } 00844 preseek_count = position - pos; 00845 00846 pos *= anim->pFormatCtx->bit_rate / frame_rate; 00847 pos /= 8; 00848 } else { 00849 pos = (long long) (position - anim->preseek) 00850 * AV_TIME_BASE / frame_rate; 00851 if (pos < 0) { 00852 pos = 0; 00853 } 00854 00855 if (st_time != AV_NOPTS_VALUE) { 00856 pos += st_time; 00857 } 00858 } 00859 00860 ret = av_seek_frame(anim->pFormatCtx, -1, 00861 pos, 00862 AVSEEK_FLAG_BACKWARD | ( 00863 seek_by_bytes 00864 ? AVSEEK_FLAG_ANY 00865 | AVSEEK_FLAG_BYTE : 0)); 00866 if (ret < 0) { 00867 fprintf(stderr, "error while seeking: %d\n", ret); 00868 } 00869 00870 pts_to_search = (long long) 00871 (((double) position) / pts_time_base / frame_rate); 00872 if (st_time != AV_NOPTS_VALUE) { 00873 pts_to_search += st_time / pts_time_base/ AV_TIME_BASE; 00874 } 00875 00876 pos_found = 0; 00877 avcodec_flush_buffers(anim->pCodecCtx); 00878 } 00879 00880 while(av_read_frame(anim->pFormatCtx, &packet)>=0) { 00881 if(packet.stream_index == anim->videoStream) { 00882 avcodec_decode_video2(anim->pCodecCtx, 00883 anim->pFrame, &frameFinished, 00884 &packet); 00885 00886 if (seek_by_bytes && preseek_count > 0) { 00887 preseek_count--; 00888 } 00889 00890 if (frameFinished && !pos_found) { 00891 if (seek_by_bytes) { 00892 if (!preseek_count) { 00893 pos_found = 1; 00894 anim->curposition = position; 00895 } 00896 } else { 00897 if (packet.dts >= pts_to_search) { 00898 pos_found = 1; 00899 anim->curposition = position; 00900 } 00901 } 00902 } 00903 00904 if(frameFinished && pos_found == 1) { 00905 ffmpeg_postprocess(anim, ibuf, &filter_y); 00906 av_free_packet(&packet); 00907 break; 00908 } 00909 } 00910 00911 av_free_packet(&packet); 00912 } 00913 00914 if (filter_y && ibuf) { 00915 IMB_filtery(ibuf); 00916 } 00917 00918 ibuf->profile = IB_PROFILE_SRGB; 00919 00920 return(ibuf); 00921 } 00922 00923 static void free_anim_ffmpeg(struct anim * anim) { 00924 if (anim == NULL) return; 00925 00926 if (anim->pCodecCtx) { 00927 avcodec_close(anim->pCodecCtx); 00928 av_close_input_file(anim->pFormatCtx); 00929 av_free(anim->pFrameRGB); 00930 av_free(anim->pFrame); 00931 00932 if (anim->ib_flags & IB_animdeinterlace) { 00933 MEM_freeN(anim->pFrameDeinterlaced->data[0]); 00934 } 00935 av_free(anim->pFrameDeinterlaced); 00936 sws_freeContext(anim->img_convert_ctx); 00937 } 00938 anim->duration = 0; 00939 } 00940 00941 #endif 00942 00943 #ifdef WITH_REDCODE 00944 00945 static int startredcode(struct anim * anim) { 00946 anim->redcodeCtx = redcode_open(anim->name); 00947 if (!anim->redcodeCtx) { 00948 return -1; 00949 } 00950 anim->duration = redcode_get_length(anim->redcodeCtx); 00951 00952 return 0; 00953 } 00954 00955 static ImBuf * redcode_fetchibuf(struct anim * anim, int position) { 00956 struct ImBuf * ibuf; 00957 struct redcode_frame * frame; 00958 struct redcode_frame_raw * raw_frame; 00959 00960 if (!anim->redcodeCtx) { 00961 return NULL; 00962 } 00963 00964 frame = redcode_read_video_frame(anim->redcodeCtx, position); 00965 00966 if (!frame) { 00967 return NULL; 00968 } 00969 00970 raw_frame = redcode_decode_video_raw(frame, 1); 00971 00972 redcode_free_frame(frame); 00973 00974 if (!raw_frame) { 00975 return NULL; 00976 } 00977 00978 ibuf = IMB_allocImBuf(raw_frame->width * 2, 00979 raw_frame->height * 2, 32, IB_rectfloat); 00980 00981 redcode_decode_video_float(raw_frame, ibuf->rect_float, 1); 00982 00983 return ibuf; 00984 } 00985 00986 static void free_anim_redcode(struct anim * anim) { 00987 if (anim->redcodeCtx) { 00988 redcode_close(anim->redcodeCtx); 00989 anim->redcodeCtx = 0; 00990 } 00991 anim->duration = 0; 00992 } 00993 00994 #endif 00995 00996 /* probeer volgende plaatje te lezen */ 00997 /* Geen plaatje, probeer dan volgende animatie te openen */ 00998 /* gelukt, haal dan eerste plaatje van animatie */ 00999 01000 static struct ImBuf * anim_getnew(struct anim * anim) { 01001 struct ImBuf *ibuf = NULL; 01002 01003 if (anim == NULL) return(NULL); 01004 01005 free_anim_movie(anim); 01006 free_anim_avi(anim); 01007 #ifdef WITH_QUICKTIME 01008 free_anim_quicktime(anim); 01009 #endif 01010 #ifdef WITH_FFMPEG 01011 free_anim_ffmpeg(anim); 01012 #endif 01013 #ifdef WITH_REDCODE 01014 free_anim_redcode(anim); 01015 #endif 01016 01017 01018 if (anim->curtype != 0) return (NULL); 01019 anim->curtype = imb_get_anim_type(anim->name); 01020 01021 switch (anim->curtype) { 01022 case ANIM_SEQUENCE: 01023 ibuf = IMB_loadiffname(anim->name, anim->ib_flags); 01024 if (ibuf) { 01025 strcpy(anim->first, anim->name); 01026 anim->duration = 1; 01027 } 01028 break; 01029 case ANIM_MOVIE: 01030 if (startmovie(anim)) return (NULL); 01031 ibuf = IMB_allocImBuf (anim->x, anim->y, 24, 0); /* fake */ 01032 break; 01033 case ANIM_AVI: 01034 if (startavi(anim)) { 01035 printf("couldnt start avi\n"); 01036 return (NULL); 01037 } 01038 ibuf = IMB_allocImBuf (anim->x, anim->y, 24, 0); 01039 break; 01040 #ifdef WITH_QUICKTIME 01041 case ANIM_QTIME: 01042 if (startquicktime(anim)) return (0); 01043 ibuf = IMB_allocImBuf (anim->x, anim->y, 24, 0); 01044 break; 01045 #endif 01046 #ifdef WITH_FFMPEG 01047 case ANIM_FFMPEG: 01048 if (startffmpeg(anim)) return (0); 01049 ibuf = IMB_allocImBuf (anim->x, anim->y, 24, 0); 01050 break; 01051 #endif 01052 #ifdef WITH_REDCODE 01053 case ANIM_REDCODE: 01054 if (startredcode(anim)) return (0); 01055 ibuf = IMB_allocImBuf (8, 8, 32, 0); 01056 break; 01057 #endif 01058 } 01059 return(ibuf); 01060 } 01061 01062 struct ImBuf * IMB_anim_previewframe(struct anim * anim) { 01063 struct ImBuf * ibuf = NULL; 01064 int position = 0; 01065 01066 ibuf = IMB_anim_absolute(anim, 0); 01067 if (ibuf) { 01068 IMB_freeImBuf(ibuf); 01069 position = anim->duration / 2; 01070 ibuf = IMB_anim_absolute(anim, position); 01071 } 01072 return ibuf; 01073 } 01074 01075 struct ImBuf * IMB_anim_absolute(struct anim * anim, int position) { 01076 struct ImBuf * ibuf = NULL; 01077 char head[256], tail[256]; 01078 unsigned short digits; 01079 int pic; 01080 int filter_y; 01081 if (anim == NULL) return(NULL); 01082 01083 filter_y = (anim->ib_flags & IB_animdeinterlace); 01084 01085 if (anim->curtype == 0) { 01086 ibuf = anim_getnew(anim); 01087 if (ibuf == NULL) { 01088 return(NULL); 01089 } 01090 01091 IMB_freeImBuf(ibuf); /* ???? */ 01092 ibuf= NULL; 01093 } 01094 01095 if (position < 0) return(NULL); 01096 if (position >= anim->duration) return(NULL); 01097 01098 switch(anim->curtype) { 01099 case ANIM_SEQUENCE: 01100 pic = an_stringdec(anim->first, head, tail, &digits); 01101 pic += position; 01102 an_stringenc(anim->name, head, tail, digits, pic); 01103 ibuf = IMB_loadiffname(anim->name, IB_rect); 01104 if (ibuf) { 01105 anim->curposition = position; 01106 } 01107 break; 01108 case ANIM_MOVIE: 01109 ibuf = movie_fetchibuf(anim, position); 01110 if (ibuf) { 01111 anim->curposition = position; 01112 IMB_convert_rgba_to_abgr(ibuf); 01113 ibuf->profile = IB_PROFILE_SRGB; 01114 } 01115 break; 01116 case ANIM_AVI: 01117 ibuf = avi_fetchibuf(anim, position); 01118 if (ibuf) 01119 anim->curposition = position; 01120 break; 01121 #ifdef WITH_QUICKTIME 01122 case ANIM_QTIME: 01123 ibuf = qtime_fetchibuf(anim, position); 01124 if (ibuf) 01125 anim->curposition = position; 01126 break; 01127 #endif 01128 #ifdef WITH_FFMPEG 01129 case ANIM_FFMPEG: 01130 ibuf = ffmpeg_fetchibuf(anim, position); 01131 if (ibuf) 01132 anim->curposition = position; 01133 filter_y = 0; /* done internally */ 01134 break; 01135 #endif 01136 #ifdef WITH_REDCODE 01137 case ANIM_REDCODE: 01138 ibuf = redcode_fetchibuf(anim, position); 01139 if (ibuf) anim->curposition = position; 01140 break; 01141 #endif 01142 } 01143 01144 if (ibuf) { 01145 if (filter_y) IMB_filtery(ibuf); 01146 sprintf(ibuf->name, "%s.%04d", anim->name, anim->curposition + 1); 01147 01148 } 01149 return(ibuf); 01150 } 01151 01152 /***/ 01153 01154 int IMB_anim_get_duration(struct anim *anim) { 01155 return anim->duration; 01156 } 01157 01158 void IMB_anim_set_preseek(struct anim * anim, int preseek) 01159 { 01160 anim->preseek = preseek; 01161 } 01162 01163 int IMB_anim_get_preseek(struct anim * anim) 01164 { 01165 return anim->preseek; 01166 }