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