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