Blender  V2.59
anim_movie.c
Go to the documentation of this file.
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 }