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