Camera tracking integration
[blender-staging.git] / source / blender / imbuf / intern / anim_movie.c
1 /*
2  * anim.c
3  *
4  * $Id$
5  *
6  * ***** BEGIN GPL LICENSE BLOCK *****
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software Foundation,
20  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21  *
22  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
23  * All rights reserved.
24  *
25  * The Original Code is: all of this file.
26  *
27  * Contributor(s): none yet.
28  *
29  * ***** END GPL LICENSE BLOCK *****
30  */
31
32 /** \file blender/imbuf/intern/anim_movie.c
33  *  \ingroup imbuf
34  */
35
36
37 #ifdef _WIN32
38 #define INC_OLE2
39 #include <windows.h>
40 #include <windowsx.h>
41 #include <mmsystem.h>
42 #include <memory.h>
43 #include <commdlg.h>
44
45 #ifndef FREE_WINDOWS
46 #include <vfw.h>
47 #endif
48
49 #undef AVIIF_KEYFRAME // redefined in AVI_avi.h
50 #undef AVIIF_LIST // redefined in AVI_avi.h
51
52 #define FIXCC(fcc)  if (fcc == 0)       fcc = mmioFOURCC('N', 'o', 'n', 'e'); \
53                 if (fcc == BI_RLE8) fcc = mmioFOURCC('R', 'l', 'e', '8');
54 #endif
55
56 #include <sys/types.h>
57 #include <ctype.h>
58 #include <stdlib.h>
59 #include <stdio.h>
60 #include <math.h>
61 #ifndef _WIN32
62 #include <dirent.h>
63 #else
64 #include <io.h>
65 #endif
66
67 #include "BLI_blenlib.h" /* BLI_remlink BLI_filesize BLI_addtail
68                                                         BLI_countlist BLI_stringdec */
69 #include "BLI_utildefines.h"
70
71 #include "MEM_guardedalloc.h"
72
73 #include "DNA_userdef_types.h"
74
75
76 #include "BKE_global.h"
77 #include "BKE_depsgraph.h"
78
79 #include "imbuf.h"
80
81 #include "AVI_avi.h"
82
83 #ifdef WITH_QUICKTIME
84 #if defined(_WIN32) || defined(__APPLE__)
85 #include "quicktime_import.h"
86 #endif /* _WIN32 || __APPLE__ */
87 #endif /* WITH_QUICKTIME */
88
89 #include "IMB_imbuf_types.h"
90 #include "IMB_imbuf.h"
91
92 #include "IMB_allocimbuf.h"
93 #include "IMB_anim.h"
94 #include "IMB_indexer.h"
95
96 #ifdef WITH_FFMPEG
97 #include <libavformat/avformat.h>
98 #include <libavcodec/avcodec.h>
99 #include <libavutil/rational.h>
100 #include <libswscale/swscale.h>
101
102 #include "ffmpeg_compat.h"
103
104 #endif //WITH_FFMPEG
105
106 #ifdef WITH_REDCODE
107 #ifdef _WIN32 /* on windows we use the ones in extern instead */
108 #include "libredcode/format.h"
109 #include "libredcode/codec.h"
110 #else
111 #include "libredcode/format.h"
112 #include "libredcode/codec.h"
113 #endif
114 #endif
115
116 /****/
117
118 #ifdef __sgi
119
120 #include <dmedia/moviefile.h>
121
122 static void movie_printerror(char * str) {
123         const char * errstr = mvGetErrorStr(mvGetErrno());
124
125         if (str) {
126                 if (errstr) printf("%s: %s\n", str, errstr);
127                 else printf("%s: returned error\n", str);
128         } else printf("%s\n", errstr);
129 }
130
131 static int startmovie(struct anim * anim) {
132         if (anim == 0) return(-1);
133
134         if ( mvOpenFile (anim->name, O_BINARY|O_RDONLY, &anim->movie ) != DM_SUCCESS ) {
135                 printf("Can't open movie: %s\n", anim->name);
136                 return(-1);
137         }
138         if ( mvFindTrackByMedium (anim->movie, DM_IMAGE, &anim->track) != DM_SUCCESS ) {
139                 printf("No image track in movie: %s\n", anim->name);
140                 mvClose(anim->movie);
141                 return(-1);
142         }
143
144         anim->duration = mvGetTrackLength (anim->track);
145         anim->params = mvGetParams( anim->track );
146
147         anim->x = dmParamsGetInt( anim->params, DM_IMAGE_WIDTH);
148         anim->y = dmParamsGetInt( anim->params, DM_IMAGE_HEIGHT);
149         anim->interlacing = dmParamsGetEnum (anim->params, DM_IMAGE_INTERLACING);
150         anim->orientation = dmParamsGetEnum (anim->params, DM_IMAGE_ORIENTATION);
151         anim->framesize = dmImageFrameSize(anim->params);
152
153         anim->curposition = 0;
154         anim->preseek = 0;
155
156         /*printf("x:%d y:%d size:%d interl:%d dur:%d\n", anim->x, anim->y, anim->framesize, anim->interlacing, anim->duration);*/
157         return (0);
158 }
159
160 static ImBuf * movie_fetchibuf(struct anim * anim, int position) {
161         ImBuf * ibuf;
162 /*      extern rectcpy(); */
163         int size;
164         unsigned int *rect1, *rect2;
165
166         if (anim == 0) return (0);
167
168         ibuf = IMB_allocImBuf(anim->x, anim->y, 24, IB_rect);
169
170         if ( mvReadFrames(anim->track, position, 1, ibuf->x * ibuf->y * 
171                 sizeof(int), ibuf->rect ) != DM_SUCCESS ) {
172                 movie_printerror("mvReadFrames");
173                 IMB_freeImBuf(ibuf);
174                 return(0);
175         }
176
177 /*
178         if (anim->interlacing == DM_IMAGE_INTERLACED_EVEN) {
179                 rect1 = ibuf->rect + (ibuf->x * ibuf->y) - 1;
180                 rect2 = rect1 - ibuf->x;
181
182                 for (size = ibuf->x * (ibuf->y - 1); size > 0; size--){
183                         *rect1-- = *rect2--;
184                 }
185         }
186 */
187
188         if (anim->interlacing == DM_IMAGE_INTERLACED_EVEN)
189         {
190                 rect1 = ibuf->rect;
191                 rect2 = rect1 + ibuf->x;
192
193                 for (size = ibuf->x * (ibuf->y - 1); size > 0; size--){
194                         *rect1++ = *rect2++;
195                 }
196         }
197         /*if (anim->orientation == DM_TOP_TO_BOTTOM) IMB_flipy(ibuf);*/
198
199
200         return(ibuf);
201 }
202
203 static void free_anim_movie(struct anim * anim) {
204         if (anim == NULL) return;
205
206         if (anim->movie) {
207                 mvClose(anim->movie);
208                 anim->movie = NULL;
209         }
210         anim->duration = 0;
211 }
212
213 int ismovie(char *name) {
214         return (mvIsMovieFile(name) == DM_TRUE);
215 }
216
217 #else
218
219 int ismovie(const char *UNUSED(name)) {
220         return 0;
221 }
222
223         /* never called, just keep the linker happy */
224 static int startmovie(struct anim *UNUSED(anim)) { return 1; }
225 static ImBuf * movie_fetchibuf(struct anim *UNUSED(anim), int UNUSED(position)) { return NULL; }
226 static void free_anim_movie(struct anim *UNUSED(anim)) { ; }
227
228 #endif
229
230 #if defined(_WIN32)
231 # define PATHSEPERATOR '\\'
232 #else
233 # define PATHSEPERATOR '/'
234 #endif
235
236 static int an_stringdec(const char *string, char* head, char *tail, unsigned short *numlen) {
237         unsigned short len,nume,nums=0;
238         short i,found=FALSE;
239
240         len=strlen(string);
241         nume = len;
242
243         for(i=len-1;i>=0;i--){
244                 if (string[i]==PATHSEPERATOR) break;
245                 if (isdigit(string[i])) {
246                         if (found){
247                                 nums=i;
248                         } else{
249                                 nume=i;
250                                 nums=i;
251                                 found=TRUE;
252                         }
253                 } else{
254                         if (found) break;
255                 }
256         }
257         if (found){
258                 strcpy(tail ,&string[nume+1]);
259                 strcpy(head, string);
260                 head[nums]= '\0';
261                 *numlen=nume-nums+1;
262                 return ((int)atoi(&(string[nums])));
263         }
264         tail[0]= '\0';
265         strcpy(head, string);
266         *numlen=0;
267         return TRUE;
268 }
269
270
271 static void an_stringenc(char *string, const char *head, const char *tail, unsigned short numlen, int pic) {
272         BLI_stringenc(string, head, tail, numlen, pic);
273 }
274
275 static void free_anim_avi (struct anim *anim) {
276 #if defined(_WIN32) && !defined(FREE_WINDOWS)
277         int i;
278 #endif
279
280         if (anim == NULL) return;
281         if (anim->avi == NULL) return;
282
283         AVI_close (anim->avi);
284         MEM_freeN (anim->avi);
285         anim->avi = NULL;
286
287 #if defined(_WIN32) && !defined(FREE_WINDOWS)
288
289         if (anim->pgf) {
290                 AVIStreamGetFrameClose(anim->pgf);
291                 anim->pgf = NULL;
292         }
293
294         for (i = 0; i < anim->avistreams; i++){
295                 AVIStreamRelease(anim->pavi[i]);
296         }
297         anim->avistreams = 0;
298
299         if (anim->pfileopen) {
300                 AVIFileRelease(anim->pfile);
301                 anim->pfileopen = 0;
302                 AVIFileExit();
303         }
304 #endif
305
306         anim->duration = 0;
307 }
308
309 #ifdef WITH_FFMPEG
310 static void free_anim_ffmpeg(struct anim * anim);
311 #endif
312 #ifdef WITH_REDCODE
313 static void free_anim_redcode(struct anim * anim);
314 #endif
315
316 void IMB_free_anim(struct anim * anim) {
317         if (anim == NULL) {
318                 printf("free anim, anim == NULL\n");
319                 return;
320         }
321
322         free_anim_movie(anim);
323         free_anim_avi(anim);
324
325 #ifdef WITH_QUICKTIME
326         free_anim_quicktime(anim);
327 #endif
328 #ifdef WITH_FFMPEG
329         free_anim_ffmpeg(anim);
330 #endif
331 #ifdef WITH_REDCODE
332         free_anim_redcode(anim);
333 #endif
334         IMB_free_indices(anim);
335
336         MEM_freeN(anim);
337 }
338
339 void IMB_close_anim(struct anim * anim) {
340         if (anim == NULL) return;
341
342         IMB_free_anim(anim);
343 }
344
345
346 struct anim * IMB_open_anim( const char * name, int ib_flags) {
347         struct anim * anim;
348
349         anim = (struct anim*)MEM_callocN(sizeof(struct anim), "anim struct");
350         if (anim != NULL) {
351                 strcpy(anim->name, name);  /* fixme: possible buffer overflow here? */
352                 anim->ib_flags = ib_flags;
353         }
354         return(anim);
355 }
356
357
358 static int startavi (struct anim *anim) {
359
360         AviError avierror;
361 #if defined(_WIN32) && !defined(FREE_WINDOWS)
362         HRESULT hr;
363         int i, firstvideo = -1;
364         BYTE abFormat[1024];
365         LONG l;
366         LPBITMAPINFOHEADER lpbi;
367         AVISTREAMINFO avis;
368 #endif
369
370         anim->avi = MEM_callocN (sizeof(AviMovie),"animavi");
371
372         if (anim->avi == NULL) {
373                 printf("Can't open avi: %s\n", anim->name);
374                 return -1;
375         }
376
377         avierror = AVI_open_movie (anim->name, anim->avi);
378
379 #if defined(_WIN32) && !defined(FREE_WINDOWS)
380         if (avierror == AVI_ERROR_COMPRESSION) {
381                 AVIFileInit();
382                 hr = AVIFileOpen(&anim->pfile, anim->name, OF_READ, 0L);
383                 if (hr == 0) {
384                         anim->pfileopen = 1;
385                         for (i = 0; i < MAXNUMSTREAMS; i++) {
386                                 if (AVIFileGetStream(anim->pfile, &anim->pavi[i], 0L, i) != AVIERR_OK) {
387                                         break;
388                                 }
389                                 
390                                 AVIStreamInfo(anim->pavi[i], &avis, sizeof(avis));
391                                 if ((avis.fccType == streamtypeVIDEO) && (firstvideo == -1)) {
392                                         anim->pgf = AVIStreamGetFrameOpen(anim->pavi[i], NULL);
393                                         if (anim->pgf) {
394                                                 firstvideo = i;
395
396                                                 // get stream length
397                                                 anim->avi->header->TotalFrames = AVIStreamLength(anim->pavi[i]);
398                                                 
399                                                 // get information about images inside the stream
400                                                 l = sizeof(abFormat);
401                                                 AVIStreamReadFormat(anim->pavi[i], 0, &abFormat, &l);
402                                                 lpbi = (LPBITMAPINFOHEADER)abFormat;
403                                                 anim->avi->header->Height = lpbi->biHeight;
404                                                 anim->avi->header->Width = lpbi->biWidth;
405                                         } else {
406                                                 FIXCC(avis.fccHandler);
407                                                 FIXCC(avis.fccType);
408                                                 printf("Can't find AVI decoder for type : %4.4hs/%4.4hs\n",
409                                                         (LPSTR)&avis.fccType,
410                                                         (LPSTR)&avis.fccHandler);
411                                         }
412                                 }
413                         }
414
415                         // register number of opened avistreams
416                         anim->avistreams = i;
417
418                         //
419                         // Couldn't get any video streams out of this file
420                         //
421                         if ((anim->avistreams == 0) || (firstvideo == -1)) {
422                                 avierror = AVI_ERROR_FORMAT;
423                         } else {
424                                 avierror = AVI_ERROR_NONE;
425                                 anim->firstvideo = firstvideo;
426                         }
427                 } else {
428                         AVIFileExit();
429                 }
430         }
431 #endif
432
433         if (avierror != AVI_ERROR_NONE) {
434                 AVI_print_error(avierror);
435                 printf ("Error loading avi: %s\n", anim->name);         
436                 free_anim_avi(anim);
437                 return -1;
438         }
439         
440         anim->duration = anim->avi->header->TotalFrames;
441         anim->params = NULL;
442
443         anim->x = anim->avi->header->Width;
444         anim->y = anim->avi->header->Height;
445         anim->interlacing = 0;
446         anim->orientation = 0;
447         anim->framesize = anim->x * anim->y * 4;
448
449         anim->curposition = 0;
450         anim->preseek = 0;
451
452         /*  printf("x:%d y:%d size:%d interl:%d dur:%d\n", anim->x, anim->y, anim->framesize, anim->interlacing, anim->duration);*/
453
454         return 0;
455 }
456
457 static ImBuf * avi_fetchibuf (struct anim *anim, int position) {
458         ImBuf *ibuf = NULL;
459         int *tmp;
460         int y;
461         
462         if (anim == NULL) return (NULL);
463
464 #if defined(_WIN32) && !defined(FREE_WINDOWS)
465         if (anim->avistreams) {
466                 LPBITMAPINFOHEADER lpbi;
467
468                 if (anim->pgf) {
469                         lpbi = AVIStreamGetFrame(anim->pgf, position + AVIStreamStart(anim->pavi[anim->firstvideo]));
470                         if (lpbi) {
471                                 ibuf = IMB_ibImageFromMemory((unsigned char *) lpbi, 100, IB_rect);
472 //Oh brother...
473                         }
474                 }
475         } else {
476 #else
477         if (1) {
478 #endif
479                 ibuf = IMB_allocImBuf (anim->x, anim->y, 24, IB_rect);
480
481                 tmp = AVI_read_frame (anim->avi, AVI_FORMAT_RGB32, position,
482                         AVI_get_stream(anim->avi, AVIST_VIDEO, 0));
483                 
484                 if (tmp == NULL) {
485                         printf ("Error reading frame from AVI");
486                         IMB_freeImBuf (ibuf);
487                         return NULL;
488                 }
489
490                 for (y=0; y < anim->y; y++) {
491                         memcpy (&(ibuf->rect)[((anim->y-y)-1)*anim->x],  &tmp[y*anim->x],  
492                                 anim->x * 4);
493                 }
494                 
495                 MEM_freeN (tmp);
496         }
497         
498         ibuf->profile = IB_PROFILE_SRGB;
499         
500         return ibuf;
501 }
502
503 #ifdef WITH_FFMPEG
504
505 extern void do_init_ffmpeg(void);
506
507 static int startffmpeg(struct anim * anim) {
508         int            i, videoStream;
509
510         AVCodec *pCodec;
511         AVFormatContext *pFormatCtx;
512         AVCodecContext *pCodecCtx;
513         int frs_num;
514         double frs_den;
515
516 #ifdef FFMPEG_SWSCALE_COLOR_SPACE_SUPPORT
517         /* The following for color space determination */
518         int srcRange, dstRange, brightness, contrast, saturation;
519         int *table;
520         const int *inv_table;
521 #endif
522
523         if (anim == 0) return(-1);
524
525         do_init_ffmpeg();
526
527         if(av_open_input_file(&pFormatCtx, anim->name, NULL, 0, NULL)!=0) {
528                 return -1;
529         }
530
531         if(av_find_stream_info(pFormatCtx)<0) {
532                 av_close_input_file(pFormatCtx);
533                 return -1;
534         }
535
536         av_dump_format(pFormatCtx, 0, anim->name, 0);
537
538
539                 /* Find the first video stream */
540         videoStream=-1;
541         for(i=0; i<pFormatCtx->nb_streams; i++)
542                 if(pFormatCtx->streams[i]->codec->codec_type
543                    == AVMEDIA_TYPE_VIDEO) {
544                         videoStream=i;
545                         break;
546                 }
547
548         if(videoStream==-1) {
549                 av_close_input_file(pFormatCtx);
550                 return -1;
551         }
552
553         pCodecCtx = pFormatCtx->streams[videoStream]->codec;
554
555                 /* Find the decoder for the video stream */
556         pCodec=avcodec_find_decoder(pCodecCtx->codec_id);
557         if(pCodec==NULL) {
558                 av_close_input_file(pFormatCtx);
559                 return -1;
560         }
561
562         pCodecCtx->workaround_bugs = 1;
563
564         if(avcodec_open(pCodecCtx, pCodec)<0) {
565                 av_close_input_file(pFormatCtx);
566                 return -1;
567         }
568
569         anim->duration = ceil(pFormatCtx->duration
570                 * av_q2d(pFormatCtx->streams[videoStream]->r_frame_rate) 
571                 / AV_TIME_BASE);
572
573         frs_num = pFormatCtx->streams[videoStream]->r_frame_rate.num;
574         frs_den = pFormatCtx->streams[videoStream]->r_frame_rate.den;
575
576         frs_den *= AV_TIME_BASE;
577
578         while (frs_num % 10 == 0 && frs_den >= 2.0 && frs_num > 10) {
579                 frs_num /= 10;
580                 frs_den /= 10;
581         }
582
583         anim->frs_sec = frs_num;
584         anim->frs_sec_base = frs_den;
585
586         anim->params = 0;
587
588         anim->x = pCodecCtx->width;
589         anim->y = pCodecCtx->height;
590         anim->interlacing = 0;
591         anim->orientation = 0;
592         anim->framesize = anim->x * anim->y * 4;
593
594         anim->curposition = -1;
595         anim->last_frame = 0;
596         anim->last_pts = -1;
597         anim->next_pts = -1;
598         anim->next_undecoded_pts = -1;
599         anim->next_packet.stream_index = -1;
600
601         anim->pFormatCtx = pFormatCtx;
602         anim->pCodecCtx = pCodecCtx;
603         anim->pCodec = pCodec;
604         anim->videoStream = videoStream;
605
606         anim->pFrame = avcodec_alloc_frame();
607         anim->pFrameDeinterlaced = avcodec_alloc_frame();
608         anim->pFrameRGB = avcodec_alloc_frame();
609
610         if (avpicture_get_size(PIX_FMT_RGBA, anim->x, anim->y)
611                 != anim->x * anim->y * 4) {
612                 fprintf (stderr,
613                          "ffmpeg has changed alloc scheme ... ARGHHH!\n");
614                 avcodec_close(anim->pCodecCtx);
615                 av_close_input_file(anim->pFormatCtx);
616                 av_free(anim->pFrameRGB);
617                 av_free(anim->pFrameDeinterlaced);
618                 av_free(anim->pFrame);
619                 anim->pCodecCtx = NULL;
620                 return -1;
621         }
622
623         if (anim->ib_flags & IB_animdeinterlace) {
624                 avpicture_fill((AVPicture*) anim->pFrameDeinterlaced, 
625                                    MEM_callocN(avpicture_get_size(
626                                                    anim->pCodecCtx->pix_fmt,
627                                                    anim->x, anim->y), 
628                                            "ffmpeg deinterlace"), 
629                                    anim->pCodecCtx->pix_fmt, anim->x, anim->y);
630         }
631
632         if (pCodecCtx->has_b_frames) {
633                 anim->preseek = 25; /* FIXME: detect gopsize ... */
634         } else {
635                 anim->preseek = 0;
636         }
637         
638         anim->img_convert_ctx = sws_getContext(
639                 anim->pCodecCtx->width,
640                 anim->pCodecCtx->height,
641                 anim->pCodecCtx->pix_fmt,
642                 anim->pCodecCtx->width,
643                 anim->pCodecCtx->height,
644                 PIX_FMT_RGBA,
645                 SWS_FAST_BILINEAR | SWS_PRINT_INFO,
646                 NULL, NULL, NULL);
647                 
648         if (!anim->img_convert_ctx) {
649                 fprintf (stderr,
650                          "Can't transform color space??? Bailing out...\n");
651                 avcodec_close(anim->pCodecCtx);
652                 av_close_input_file(anim->pFormatCtx);
653                 av_free(anim->pFrameRGB);
654                 av_free(anim->pFrameDeinterlaced);
655                 av_free(anim->pFrame);
656                 anim->pCodecCtx = NULL;
657                 return -1;
658         }
659
660 #ifdef FFMPEG_SWSCALE_COLOR_SPACE_SUPPORT
661         /* Try do detect if input has 0-255 YCbCR range (JFIF Jpeg MotionJpeg) */
662         if (!sws_getColorspaceDetails(anim->img_convert_ctx, (int**)&inv_table, &srcRange,
663                 &table, &dstRange, &brightness, &contrast, &saturation)) {
664
665                 srcRange = srcRange || anim->pCodecCtx->color_range == AVCOL_RANGE_JPEG;
666                 inv_table = sws_getCoefficients(anim->pCodecCtx->colorspace);
667
668                 if(sws_setColorspaceDetails(anim->img_convert_ctx, (int *)inv_table, srcRange,
669                         table, dstRange, brightness, contrast, saturation)) {
670
671                         printf("Warning: Could not set libswscale colorspace details.\n");
672                         }
673         }
674         else {
675                 printf("Warning: Could not set libswscale colorspace details.\n");
676         }
677 #endif
678                 
679         return (0);
680 }
681
682 /* postprocess the image in anim->pFrame and do color conversion
683    and deinterlacing stuff.
684
685    Output is anim->last_frame
686 */
687
688 static void ffmpeg_postprocess(struct anim * anim)
689 {
690         AVFrame * input = anim->pFrame;
691         ImBuf * ibuf = anim->last_frame;
692         int filter_y = 0;
693
694         ibuf->profile = IB_PROFILE_SRGB;
695
696         /* This means the data wasnt read properly, 
697            this check stops crashing */
698         if (input->data[0]==0 && input->data[1]==0 
699             && input->data[2]==0 && input->data[3]==0){
700                 fprintf(stderr, "ffmpeg_fetchibuf: "
701                         "data not read properly...\n");
702                 return;
703         }
704
705         if (anim->ib_flags & IB_animdeinterlace) {
706                 if (avpicture_deinterlace(
707                             (AVPicture*) 
708                             anim->pFrameDeinterlaced,
709                             (const AVPicture*)
710                             anim->pFrame,
711                             anim->pCodecCtx->pix_fmt,
712                             anim->pCodecCtx->width,
713                             anim->pCodecCtx->height)
714                     < 0) {
715                         filter_y = TRUE;
716                 } else {
717                         input = anim->pFrameDeinterlaced;
718                 }
719         }
720         
721         avpicture_fill((AVPicture*) anim->pFrameRGB, 
722                        (unsigned char*) ibuf->rect, 
723                        PIX_FMT_RGBA, anim->x, anim->y);
724
725         if (ENDIAN_ORDER == B_ENDIAN) {
726                 int * dstStride   = anim->pFrameRGB->linesize;
727                 uint8_t** dst     = anim->pFrameRGB->data;
728                 int dstStride2[4] = { dstStride[0], 0, 0, 0 };
729                 uint8_t* dst2[4]  = { dst[0], 0, 0, 0 };
730                 int x,y,h,w;
731                 unsigned char* bottom;
732                 unsigned char* top;
733                 
734                 sws_scale(anim->img_convert_ctx,
735                           (const uint8_t * const *)input->data,
736                           input->linesize,
737                           0,
738                           anim->pCodecCtx->height,
739                           dst2,
740                           dstStride2);
741                 
742                 /* workaround: sws_scale bug
743                    sets alpha = 0 and compensate
744                    for altivec-bugs and flipy... */
745                 
746                 bottom = (unsigned char*) ibuf->rect;
747                 top = bottom + ibuf->x * (ibuf->y-1) * 4;
748                 
749                 h = (ibuf->y + 1) / 2;
750                 w = ibuf->x;
751                 
752                 for (y = 0; y < h; y++) {
753                         unsigned char tmp[4];
754                         unsigned int * tmp_l =
755                                 (unsigned int*) tmp;
756                         tmp[3] = 0xff;
757                         
758                         for (x = 0; x < w; x++) {
759                                 tmp[0] = bottom[0];
760                                 tmp[1] = bottom[1];
761                                 tmp[2] = bottom[2];
762                                 
763                                 bottom[0] = top[0];
764                                 bottom[1] = top[1];
765                                 bottom[2] = top[2];
766                                 bottom[3] = 0xff;
767                                 
768                                 *(unsigned int*) top = *tmp_l;
769                                 
770                                 bottom +=4;
771                                 top += 4;
772                         }
773                         top -= 8 * w;
774                 }
775         } else {
776                 int * dstStride   = anim->pFrameRGB->linesize;
777                 uint8_t** dst     = anim->pFrameRGB->data;
778                 int dstStride2[4] = { -dstStride[0], 0, 0, 0 };
779                 uint8_t* dst2[4]  = { dst[0] + (anim->y - 1)*dstStride[0],
780                                       0, 0, 0 };
781                 int i;
782                 unsigned char* r;
783                 
784                 sws_scale(anim->img_convert_ctx,
785                           (const uint8_t * const *)input->data,
786                           input->linesize,
787                           0,
788                           anim->pCodecCtx->height,
789                           dst2,
790                           dstStride2);
791                 
792                 r = (unsigned char*) ibuf->rect;
793                 
794                 /* workaround sws_scale bug: older version of 
795                    sws_scale set alpha = 0... */
796                 if (r[3] == 0) {
797                         for (i = 0; i < ibuf->x * ibuf->y; i++) {
798                                 r[3] = 0xff;
799                                 r += 4;
800                         }
801                 }
802         }
803
804         if (filter_y) {
805                 IMB_filtery(ibuf);
806         }
807 }
808
809 /* decode one video frame and load the next packet into anim->packet,
810    so that we can obtain next_pts and next undecoded pts */
811
812 static int ffmpeg_decode_video_frame(struct anim * anim)
813 {
814         int frameFinished = 0;
815         int rval = 0;
816
817         av_log(anim->pFormatCtx, AV_LOG_DEBUG, "  DECODE VIDEO FRAME\n");
818
819         anim->next_undecoded_pts = -1;
820
821         if (anim->next_packet.stream_index == anim->videoStream) {
822                 av_log(anim->pFormatCtx, AV_LOG_DEBUG, 
823                        "  DECODE: cached next packet\n");
824
825                 avcodec_decode_video2(anim->pCodecCtx, 
826                                       anim->pFrame, &frameFinished, 
827                                       &anim->next_packet);
828
829                 if (frameFinished) {
830                         av_log(anim->pFormatCtx, 
831                                AV_LOG_DEBUG, 
832                                "  FRAME DONE: "
833                                 "next_pts=%lld pkt_pts=%lld\n",
834                                 (anim->pFrame->pts == AV_NOPTS_VALUE) ? 
835                                 -1 : anim->pFrame->pts, 
836                                 (anim->pFrame->pkt_pts == AV_NOPTS_VALUE) ?
837                                 -1 : anim->pFrame->pkt_pts);
838                         anim->next_pts = 
839                                 av_get_pts_from_frame(anim->pFormatCtx,
840                                                       anim->pFrame);
841                 }
842
843                 av_free_packet(&anim->next_packet);
844                 anim->next_packet.stream_index = -1;
845         }
846         
847         while((rval = av_read_frame(anim->pFormatCtx, &anim->next_packet)) >= 0) {
848                 av_log(anim->pFormatCtx, 
849                        AV_LOG_DEBUG, 
850                        "%sREAD: strID=%d (VID: %d) dts=%lld pts=%lld "
851                        "%s\n",
852                        (anim->next_packet.stream_index == anim->videoStream)
853                        ? "->" : "  ",
854                        anim->next_packet.stream_index, 
855                        anim->videoStream,
856                        (anim->next_packet.dts == AV_NOPTS_VALUE) ? -1:
857                        anim->next_packet.dts,
858                        (anim->next_packet.pts == AV_NOPTS_VALUE) ? -1:
859                        anim->next_packet.pts,
860                        (anim->next_packet.flags & AV_PKT_FLAG_KEY) ? 
861                        " KEY" : "");
862                 if (anim->next_packet.stream_index == anim->videoStream) {
863                         if (frameFinished) {
864                                 av_log(anim->pFormatCtx,
865                                        AV_LOG_DEBUG,
866                                        "  FRAME finished, we leave\n");
867                                 anim->next_undecoded_pts 
868                                         = anim->next_packet.dts;
869                                 break;
870                         }
871
872                         avcodec_decode_video2(
873                                 anim->pCodecCtx, 
874                                 anim->pFrame, &frameFinished, 
875                                 &anim->next_packet);
876
877                         if (frameFinished) {
878                                 anim->next_pts = av_get_pts_from_frame(
879                                         anim->pFormatCtx, anim->pFrame);
880
881                                 av_log(anim->pFormatCtx,
882                                        AV_LOG_DEBUG,
883                                        "  FRAME DONE: next_pts=%lld "
884                                        "pkt_pts=%lld, guessed_pts=%lld\n",
885                                        (anim->pFrame->pts == AV_NOPTS_VALUE) ?
886                                        -1 : anim->pFrame->pts, 
887                                        (anim->pFrame->pkt_pts 
888                                         == AV_NOPTS_VALUE) ?
889                                        -1 : anim->pFrame->pkt_pts,
890                                         anim->next_pts);
891                         }
892                 }
893                 av_free_packet(&anim->next_packet);
894                 anim->next_packet.stream_index = -1;
895         }
896         
897         if (rval < 0) {
898                 av_log(anim->pFormatCtx,
899                        AV_LOG_ERROR, "  DECODE READ FAILED: av_read_frame() "
900                        "returned error: %d\n",  rval);
901         }
902         return (rval >= 0);
903 }
904
905 static void ffmpeg_decode_video_frame_scan(
906         struct anim * anim, int64_t pts_to_search)
907 {
908         /* there seem to exist *very* silly GOP lengths out in the wild... */
909         int count = 1000;
910
911         av_log(anim->pFormatCtx,
912                AV_LOG_DEBUG, 
913                "SCAN start: considering pts=%lld in search of %lld\n", 
914                anim->next_pts, pts_to_search);
915
916         while (count > 0 && anim->next_pts < pts_to_search) {
917                 av_log(anim->pFormatCtx,
918                        AV_LOG_DEBUG, 
919                        "  WHILE: pts=%lld in search of %lld\n", 
920                        anim->next_pts, pts_to_search);
921                 if (!ffmpeg_decode_video_frame(anim)) {
922                         break;
923                 }
924                 count--;
925         }
926         if (count == 0) {
927                 av_log(anim->pFormatCtx,
928                        AV_LOG_ERROR, 
929                        "SCAN failed: completely lost in stream, "
930                        "bailing out at PTS=%lld, searching for PTS=%lld\n", 
931                        anim->next_pts, pts_to_search);
932         }
933         if (anim->next_pts == pts_to_search) {
934                 av_log(anim->pFormatCtx,
935                        AV_LOG_DEBUG, "SCAN HAPPY: we found our PTS!\n");
936         } else {
937                 av_log(anim->pFormatCtx,
938                        AV_LOG_ERROR, "SCAN UNHAPPY: PTS not matched!\n");
939         }
940 }
941
942 static int match_format(const char *name, AVFormatContext * pFormatCtx)
943 {
944         const char *p;
945         int len, namelen;
946
947         const char *names = pFormatCtx->iformat->name;
948
949         if (!name || !names)
950                 return 0;
951
952         namelen = strlen(name);
953         while ((p = strchr(names, ','))) {
954                 len = MAX2(p - names, namelen);
955                 if (!BLI_strncasecmp(name, names, len))
956                         return 1;
957                 names = p+1;
958         }
959         return !BLI_strcasecmp(name, names);
960 }
961
962 static int ffmpeg_seek_by_byte(AVFormatContext *pFormatCtx)
963 {
964         static const char * byte_seek_list [] = { "dv", "mpegts", 0 };
965         const char ** p;
966
967         if (pFormatCtx->iformat->flags & AVFMT_TS_DISCONT) {
968                 return TRUE;
969         }
970
971         p = byte_seek_list;
972
973         while (*p) {
974                 if (match_format(*p++, pFormatCtx)) {
975                         return TRUE;
976                 }
977         }
978
979         return FALSE;
980 }
981
982 static ImBuf * ffmpeg_fetchibuf(struct anim * anim, int position,
983                                 IMB_Timecode_Type tc) {
984         int64_t pts_to_search = 0;
985         double frame_rate;
986         double pts_time_base;
987         long long st_time; 
988         struct anim_index * tc_index = 0;
989         AVStream * v_st;
990         int new_frame_index;
991         int old_frame_index;
992
993         if (anim == 0) return (0);
994
995         av_log(anim->pFormatCtx, AV_LOG_DEBUG, "FETCH: pos=%d\n", position);
996
997         if (tc != IMB_TC_NONE) {
998                 tc_index = IMB_anim_open_index(anim, tc);
999         }
1000
1001         v_st = anim->pFormatCtx->streams[anim->videoStream];
1002
1003         frame_rate = av_q2d(v_st->r_frame_rate);
1004
1005         st_time = anim->pFormatCtx->start_time;
1006         pts_time_base = av_q2d(v_st->time_base);
1007
1008         if (tc_index) {
1009                 new_frame_index = IMB_indexer_get_frame_index(
1010                         tc_index, position);
1011                 old_frame_index = IMB_indexer_get_frame_index(
1012                         tc_index, anim->curposition);
1013                 pts_to_search = IMB_indexer_get_pts(
1014                         tc_index, new_frame_index);
1015         } else {
1016                 pts_to_search = (long long) 
1017                         rint(((double) position) / pts_time_base / frame_rate);
1018
1019                 if (st_time != AV_NOPTS_VALUE) {
1020                         pts_to_search += st_time / pts_time_base 
1021                                 / AV_TIME_BASE;
1022                 }
1023         }
1024
1025         av_log(anim->pFormatCtx, AV_LOG_DEBUG, 
1026                "FETCH: looking for PTS=%lld "
1027                "(pts_timebase=%g, frame_rate=%g, st_time=%lld)\n", 
1028                pts_to_search, pts_time_base, frame_rate, st_time);
1029
1030         if (anim->last_frame && 
1031             anim->last_pts <= pts_to_search && anim->next_pts > pts_to_search){
1032                 av_log(anim->pFormatCtx, AV_LOG_DEBUG, 
1033                        "FETCH: frame repeat: last: %lld next: %lld\n",
1034                        anim->last_pts, anim->next_pts);
1035                 IMB_refImBuf(anim->last_frame);
1036                 anim->curposition = position;
1037                 return anim->last_frame;
1038         }
1039          
1040         IMB_freeImBuf(anim->last_frame);
1041
1042         if (anim->next_pts <= pts_to_search && 
1043             anim->next_undecoded_pts > pts_to_search) {
1044                 av_log(anim->pFormatCtx, AV_LOG_DEBUG, 
1045                        "FETCH: no seek necessary: "
1046                         "next: %lld next undecoded: %lld\n",
1047                         anim->next_pts, anim->next_undecoded_pts);
1048
1049                 /* we are already done :) */
1050
1051         } else if (position > anim->curposition + 1 
1052                    && anim->preseek 
1053                    && !tc_index
1054                    && position - (anim->curposition + 1) < anim->preseek) {
1055
1056                 av_log(anim->pFormatCtx, AV_LOG_DEBUG, 
1057                        "FETCH: within preseek interval (no index)\n");
1058
1059                 ffmpeg_decode_video_frame_scan(anim, pts_to_search);
1060         } else if (tc_index && 
1061                    IMB_indexer_can_scan(tc_index, old_frame_index,
1062                                         new_frame_index)) {
1063
1064                 av_log(anim->pFormatCtx, AV_LOG_DEBUG, 
1065                        "FETCH: within preseek interval "
1066                        "(index tells us)\n");
1067
1068                 ffmpeg_decode_video_frame_scan(anim, pts_to_search);
1069         } else if (position != anim->curposition + 1) { 
1070                 long long pos;
1071                 int ret;
1072
1073                 if (tc_index) {
1074                         unsigned long long dts;
1075
1076                         pos = IMB_indexer_get_seek_pos(
1077                                 tc_index, new_frame_index);
1078                         dts = IMB_indexer_get_seek_pos_dts(
1079                                 tc_index, new_frame_index);
1080
1081                         av_log(anim->pFormatCtx, AV_LOG_DEBUG, 
1082                                "TC INDEX seek pos = %lld\n", pos);
1083                         av_log(anim->pFormatCtx, AV_LOG_DEBUG, 
1084                                "TC INDEX seek dts = %lld\n", dts);
1085
1086                         if (ffmpeg_seek_by_byte(anim->pFormatCtx)) {
1087                                 av_log(anim->pFormatCtx, AV_LOG_DEBUG, 
1088                                        "... using BYTE pos\n");
1089
1090                                 ret = av_seek_frame(anim->pFormatCtx, 
1091                                                     -1,
1092                                                     pos, AVSEEK_FLAG_BYTE);
1093                                 av_update_cur_dts(anim->pFormatCtx, v_st, dts);
1094                         } else {
1095                                 av_log(anim->pFormatCtx, AV_LOG_DEBUG, 
1096                                        "... using DTS pos\n");
1097                                 ret = av_seek_frame(anim->pFormatCtx, 
1098                                                     anim->videoStream, 
1099                                                     dts, AVSEEK_FLAG_BACKWARD);
1100                         }
1101                 } else {
1102                         pos = (long long) (position - anim->preseek) 
1103                                 * AV_TIME_BASE / frame_rate;
1104                         if (pos < 0) {
1105                                 pos = 0;
1106                         }
1107                 
1108                         if (st_time != AV_NOPTS_VALUE) {
1109                                 pos += st_time;
1110                         }
1111
1112                         ret = av_seek_frame(anim->pFormatCtx, -1, 
1113                                             pos, AVSEEK_FLAG_BACKWARD);
1114                 }
1115
1116                 if (ret < 0) {
1117                         av_log(anim->pFormatCtx, AV_LOG_ERROR, 
1118                                "FETCH: "
1119                                "error while seeking to DTS = %lld "
1120                                "(frameno = %d, PTS = %lld): errcode = %d\n", 
1121                                pos, position, pts_to_search, ret);
1122                 }
1123
1124                 avcodec_flush_buffers(anim->pCodecCtx);
1125
1126                 anim->next_pts = -1;
1127
1128                 if (anim->next_packet.stream_index == anim->videoStream) {
1129                         av_free_packet(&anim->next_packet);
1130                         anim->next_packet.stream_index = -1;
1131                 }
1132
1133                 /* memset(anim->pFrame,...) ?? */
1134
1135                 if (ret >= 0) {
1136                         ffmpeg_decode_video_frame_scan(anim, pts_to_search);
1137                 }
1138         } else if (position == 0 && anim->curposition == -1) {
1139                 /* first frame without seeking special case... */
1140                 ffmpeg_decode_video_frame(anim);
1141         }
1142
1143         anim->last_frame = IMB_allocImBuf(anim->x, anim->y, 32, IB_rect);
1144
1145         ffmpeg_postprocess(anim);
1146         
1147         anim->last_pts = anim->next_pts;
1148         
1149         ffmpeg_decode_video_frame(anim);
1150         
1151         anim->curposition = position;
1152         
1153         IMB_refImBuf(anim->last_frame);
1154         
1155         return anim->last_frame;
1156 }
1157
1158 static void free_anim_ffmpeg(struct anim * anim) {
1159         if (anim == NULL) return;
1160
1161         if (anim->pCodecCtx) {
1162                 avcodec_close(anim->pCodecCtx);
1163                 av_close_input_file(anim->pFormatCtx);
1164                 av_free(anim->pFrameRGB);
1165                 av_free(anim->pFrame);
1166
1167                 if (anim->ib_flags & IB_animdeinterlace) {
1168                         MEM_freeN(anim->pFrameDeinterlaced->data[0]);
1169                 }
1170                 av_free(anim->pFrameDeinterlaced);
1171                 sws_freeContext(anim->img_convert_ctx);
1172                 IMB_freeImBuf(anim->last_frame);
1173                 if (anim->next_packet.stream_index != -1) {
1174                         av_free_packet(&anim->next_packet);
1175                 }
1176         }
1177         anim->duration = 0;
1178 }
1179
1180 #endif
1181
1182 #ifdef WITH_REDCODE
1183
1184 static int startredcode(struct anim * anim) {
1185         anim->redcodeCtx = redcode_open(anim->name);
1186         if (!anim->redcodeCtx) {
1187                 return -1;
1188         }
1189         anim->duration = redcode_get_length(anim->redcodeCtx);
1190         
1191         return 0;
1192 }
1193
1194 static ImBuf * redcode_fetchibuf(struct anim * anim, int position) {
1195         struct ImBuf * ibuf;
1196         struct redcode_frame * frame;
1197         struct redcode_frame_raw * raw_frame;
1198
1199         if (!anim->redcodeCtx) {
1200                 return NULL;
1201         }
1202
1203         frame = redcode_read_video_frame(anim->redcodeCtx, position);
1204         
1205         if (!frame) {
1206                 return NULL;
1207         }
1208
1209         raw_frame = redcode_decode_video_raw(frame, 1);
1210
1211         redcode_free_frame(frame);
1212
1213         if (!raw_frame) {
1214                 return NULL;
1215         }
1216         
1217                 ibuf = IMB_allocImBuf(raw_frame->width * 2, 
1218                                   raw_frame->height * 2, 32, IB_rectfloat);
1219
1220         redcode_decode_video_float(raw_frame, ibuf->rect_float, 1);
1221
1222         return ibuf;
1223 }
1224
1225 static void free_anim_redcode(struct anim * anim) {
1226         if (anim->redcodeCtx) {
1227                 redcode_close(anim->redcodeCtx);
1228                 anim->redcodeCtx = 0;
1229         }
1230         anim->duration = 0;
1231 }
1232
1233 #endif
1234
1235 /* probeer volgende plaatje te lezen */
1236 /* Geen plaatje, probeer dan volgende animatie te openen */
1237 /* gelukt, haal dan eerste plaatje van animatie */
1238
1239 static struct ImBuf * anim_getnew(struct anim * anim) {
1240         struct ImBuf *ibuf = NULL;
1241
1242         if (anim == NULL) return(NULL);
1243
1244         free_anim_movie(anim);
1245         free_anim_avi(anim);
1246 #ifdef WITH_QUICKTIME
1247         free_anim_quicktime(anim);
1248 #endif
1249 #ifdef WITH_FFMPEG
1250         free_anim_ffmpeg(anim);
1251 #endif
1252 #ifdef WITH_REDCODE
1253         free_anim_redcode(anim);
1254 #endif
1255
1256
1257         if (anim->curtype != 0) return (NULL);
1258         anim->curtype = imb_get_anim_type(anim->name);  
1259
1260         switch (anim->curtype) {
1261         case ANIM_SEQUENCE:
1262                 ibuf = IMB_loadiffname(anim->name, anim->ib_flags);
1263                 if (ibuf) {
1264                         strcpy(anim->first, anim->name);
1265                         anim->duration = 1;
1266                 }
1267                 break;
1268         case ANIM_MOVIE:
1269                 if (startmovie(anim)) return (NULL);
1270                 ibuf = IMB_allocImBuf (anim->x, anim->y, 24, 0); /* fake */
1271                 break;
1272         case ANIM_AVI:
1273                 if (startavi(anim)) {
1274                         printf("couldnt start avi\n"); 
1275                         return (NULL);
1276                 }
1277                 ibuf = IMB_allocImBuf (anim->x, anim->y, 24, 0);
1278                 break;
1279 #ifdef WITH_QUICKTIME
1280         case ANIM_QTIME:
1281                 if (startquicktime(anim)) return (0);
1282                 ibuf = IMB_allocImBuf (anim->x, anim->y, 24, 0);
1283                 break;
1284 #endif
1285 #ifdef WITH_FFMPEG
1286         case ANIM_FFMPEG:
1287                 if (startffmpeg(anim)) return (0);
1288                 ibuf = IMB_allocImBuf (anim->x, anim->y, 24, 0);
1289                 break;
1290 #endif
1291 #ifdef WITH_REDCODE
1292         case ANIM_REDCODE:
1293                 if (startredcode(anim)) return (0);
1294                 ibuf = IMB_allocImBuf (8, 8, 32, 0);
1295                 break;
1296 #endif
1297         }
1298         return(ibuf);
1299 }
1300
1301 struct ImBuf * IMB_anim_previewframe(struct anim * anim) {
1302         struct ImBuf * ibuf = NULL;
1303         int position = 0;
1304         
1305         ibuf = IMB_anim_absolute(anim, 0, IMB_TC_NONE, IMB_PROXY_NONE);
1306         if (ibuf) {
1307                 IMB_freeImBuf(ibuf);
1308                 position = anim->duration / 2;
1309                 ibuf = IMB_anim_absolute(anim, position, IMB_TC_NONE,
1310                                          IMB_PROXY_NONE);
1311         }
1312         return ibuf;
1313 }
1314
1315 struct ImBuf * IMB_anim_absolute(struct anim * anim, int position,
1316                                  IMB_Timecode_Type tc,
1317                                  IMB_Proxy_Size preview_size) {
1318         struct ImBuf * ibuf = NULL;
1319         char head[256], tail[256];
1320         unsigned short digits;
1321         int pic;
1322         int filter_y;
1323         if (anim == NULL) return(NULL);
1324
1325         filter_y = (anim->ib_flags & IB_animdeinterlace);
1326
1327         if (anim->curtype == 0) {
1328                 ibuf = anim_getnew(anim);
1329                 if (ibuf == NULL) {
1330                         return(NULL);
1331                 }
1332
1333                 IMB_freeImBuf(ibuf); /* ???? */
1334                 ibuf= NULL;
1335         }
1336
1337         if (position < 0) return(NULL);
1338         if (position >= anim->duration) return(NULL);
1339
1340         if (preview_size != IMB_PROXY_NONE) {
1341                 struct anim * proxy = IMB_anim_open_proxy(anim, preview_size);
1342
1343                 if (proxy) {
1344                         position = IMB_anim_index_get_frame_index(
1345                                 anim, tc, position);
1346                         return IMB_anim_absolute(
1347                                 proxy, position,
1348                                 IMB_TC_NONE, IMB_PROXY_NONE);
1349                 }
1350         }
1351
1352         switch(anim->curtype) {
1353         case ANIM_SEQUENCE:
1354                 pic = an_stringdec(anim->first, head, tail, &digits);
1355                 pic += position;
1356                 an_stringenc(anim->name, head, tail, digits, pic);
1357                 ibuf = IMB_loadiffname(anim->name, IB_rect);
1358                 if (ibuf) {
1359                         anim->curposition = position;
1360                 }
1361                 break;
1362         case ANIM_MOVIE:
1363                 ibuf = movie_fetchibuf(anim, position);
1364                 if (ibuf) {
1365                         anim->curposition = position;
1366                         IMB_convert_rgba_to_abgr(ibuf);
1367                         ibuf->profile = IB_PROFILE_SRGB;
1368                 }
1369                 break;
1370         case ANIM_AVI:
1371                 ibuf = avi_fetchibuf(anim, position);
1372                 if (ibuf)
1373                         anim->curposition = position;
1374                 break;
1375 #ifdef WITH_QUICKTIME
1376         case ANIM_QTIME:
1377                 ibuf = qtime_fetchibuf(anim, position);
1378                 if (ibuf)
1379                         anim->curposition = position;
1380                 break;
1381 #endif
1382 #ifdef WITH_FFMPEG
1383         case ANIM_FFMPEG:
1384                 ibuf = ffmpeg_fetchibuf(anim, position, tc);
1385                 if (ibuf)
1386                         anim->curposition = position;
1387                 filter_y = 0; /* done internally */
1388                 break;
1389 #endif
1390 #ifdef WITH_REDCODE
1391         case ANIM_REDCODE:
1392                 ibuf = redcode_fetchibuf(anim, position);
1393                 if (ibuf) anim->curposition = position;
1394                 break;
1395 #endif
1396         }
1397
1398         if (ibuf) {
1399                 if (filter_y) IMB_filtery(ibuf);
1400                 sprintf(ibuf->name, "%s.%04d", anim->name, anim->curposition + 1);
1401                 
1402         }
1403         return(ibuf);
1404 }
1405
1406 /***/
1407
1408 int IMB_anim_get_duration(struct anim *anim, IMB_Timecode_Type tc) {
1409         struct anim_index * idx;
1410         if (tc == IMB_TC_NONE) {
1411                 return anim->duration;
1412         }
1413         
1414         idx = IMB_anim_open_index(anim, tc);
1415         if (!idx) {
1416                 return anim->duration;
1417         }
1418
1419         return IMB_indexer_get_duration(idx);
1420 }
1421
1422 int IMB_anim_get_fps(struct anim * anim, 
1423                      short * frs_sec, float * frs_sec_base)
1424 {
1425         if (anim->frs_sec) {
1426                 *frs_sec = anim->frs_sec;
1427                 *frs_sec_base = anim->frs_sec_base;
1428                 return TRUE;
1429         }
1430         return FALSE;
1431 }
1432
1433 void IMB_anim_set_preseek(struct anim * anim, int preseek)
1434 {
1435         anim->preseek = preseek;
1436 }
1437
1438 int IMB_anim_get_preseek(struct anim * anim)
1439 {
1440         return anim->preseek;
1441 }