Blender  V2.93
anim_movie.c
Go to the documentation of this file.
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 
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_threads.h"
59 #include "BLI_utildefines.h"
60 
61 #include "MEM_guardedalloc.h"
62 
63 #ifdef WITH_AVI
64 # include "AVI_avi.h"
65 #endif
66 
67 #include "IMB_imbuf.h"
68 #include "IMB_imbuf_types.h"
69 
70 #include "IMB_colormanagement.h"
72 
73 #include "IMB_anim.h"
74 #include "IMB_indexer.h"
75 #include "IMB_metadata.h"
76 
77 #ifdef WITH_FFMPEG
78 # include "BKE_global.h" /* ENDIAN_ORDER */
79 
80 # include <libavcodec/avcodec.h>
81 # include <libavformat/avformat.h>
82 # include <libavutil/imgutils.h>
83 # include <libavutil/rational.h>
84 # include <libswscale/swscale.h>
85 
86 # include "ffmpeg_compat.h"
87 #endif /* WITH_FFMPEG */
88 
89 int ismovie(const char *UNUSED(filepath))
90 {
91  return 0;
92 }
93 
94 /* never called, just keep the linker happy */
95 static int startmovie(struct anim *UNUSED(anim))
96 {
97  return 1;
98 }
99 static ImBuf *movie_fetchibuf(struct anim *UNUSED(anim), int UNUSED(position))
100 {
101  return NULL;
102 }
103 static void free_anim_movie(struct anim *UNUSED(anim))
104 {
105  /* pass */
106 }
107 
108 #if defined(_WIN32)
109 # define PATHSEPARATOR '\\'
110 #else
111 # define PATHSEPARATOR '/'
112 #endif
113 
114 static int an_stringdec(const char *string, char *head, char *tail, unsigned short *numlen)
115 {
116  unsigned short len, nume, nums = 0;
117  short i;
118  bool found = false;
119 
120  len = strlen(string);
121  nume = len;
122 
123  for (i = len - 1; i >= 0; i--) {
124  if (string[i] == PATHSEPARATOR) {
125  break;
126  }
127  if (isdigit(string[i])) {
128  if (found) {
129  nums = i;
130  }
131  else {
132  nume = i;
133  nums = i;
134  found = true;
135  }
136  }
137  else {
138  if (found) {
139  break;
140  }
141  }
142  }
143  if (found) {
144  strcpy(tail, &string[nume + 1]);
145  strcpy(head, string);
146  head[nums] = '\0';
147  *numlen = nume - nums + 1;
148  return ((int)atoi(&(string[nums])));
149  }
150  tail[0] = '\0';
151  strcpy(head, string);
152  *numlen = 0;
153  return true;
154 }
155 
156 static void an_stringenc(
157  char *string, const char *head, const char *tail, unsigned short numlen, int pic)
158 {
159  BLI_path_sequence_encode(string, head, tail, numlen, pic);
160 }
161 
162 #ifdef WITH_AVI
163 static void free_anim_avi(struct anim *anim)
164 {
165 # if defined(_WIN32)
166  int i;
167 # endif
168 
169  if (anim == NULL) {
170  return;
171  }
172  if (anim->avi == NULL) {
173  return;
174  }
175 
176  AVI_close(anim->avi);
177  MEM_freeN(anim->avi);
178  anim->avi = NULL;
179 
180 # if defined(_WIN32)
181 
182  if (anim->pgf) {
183  AVIStreamGetFrameClose(anim->pgf);
184  anim->pgf = NULL;
185  }
186 
187  for (i = 0; i < anim->avistreams; i++) {
188  AVIStreamRelease(anim->pavi[i]);
189  }
190  anim->avistreams = 0;
191 
192  if (anim->pfileopen) {
193  AVIFileRelease(anim->pfile);
194  anim->pfileopen = 0;
195  AVIFileExit();
196  }
197 # endif
198 
200 }
201 #endif /* WITH_AVI */
202 
203 #ifdef WITH_FFMPEG
204 static void free_anim_ffmpeg(struct anim *anim);
205 #endif
206 
207 void IMB_free_anim(struct anim *anim)
208 {
209  if (anim == NULL) {
210  printf("free anim, anim == NULL\n");
211  return;
212  }
213 
215 
216 #ifdef WITH_AVI
217  free_anim_avi(anim);
218 #endif
219 
220 #ifdef WITH_FFMPEG
221  free_anim_ffmpeg(anim);
222 #endif
225 
226  MEM_freeN(anim);
227 }
228 
229 void IMB_close_anim(struct anim *anim)
230 {
231  if (anim == NULL) {
232  return;
233  }
234 
236 }
237 
239 {
240  if (anim == NULL) {
241  return;
242  }
243 
245 }
246 
248 {
249  switch (anim->curtype) {
250  case ANIM_FFMPEG: {
251 #ifdef WITH_FFMPEG
252  AVDictionaryEntry *entry = NULL;
253 
254  BLI_assert(anim->pFormatCtx != NULL);
255  av_log(anim->pFormatCtx, AV_LOG_DEBUG, "METADATA FETCH\n");
256 
257  while (true) {
258  entry = av_dict_get(anim->pFormatCtx->metadata, "", entry, AV_DICT_IGNORE_SUFFIX);
259  if (entry == NULL) {
260  break;
261  }
262 
263  /* Delay creation of the property group until there is actual metadata to put in there. */
265  IMB_metadata_set_field(anim->metadata, entry->key, entry->value);
266  }
267 #endif
268  break;
269  }
270  case ANIM_SEQUENCE:
271  case ANIM_AVI:
272  case ANIM_MOVIE:
273  /* TODO */
274  break;
275  case ANIM_NONE:
276  default:
277  break;
278  }
279  return anim->metadata;
280 }
281 
282 struct anim *IMB_open_anim(const char *name,
283  int ib_flags,
284  int streamindex,
285  char colorspace[IM_MAX_SPACE])
286 {
287  struct anim *anim;
288 
290 
291  anim = (struct anim *)MEM_callocN(sizeof(struct anim), "anim struct");
292  if (anim != NULL) {
293  if (colorspace) {
296  }
297  else {
300  }
301 
302  BLI_strncpy(anim->name, name, sizeof(anim->name));
305  }
306  return anim;
307 }
308 
310 {
311 #if !(defined(WITH_AVI) || defined(WITH_FFMPEG))
312  UNUSED_VARS(anim);
313 #endif
314 
315 #ifdef WITH_AVI
316  if (anim->avi != NULL) {
317  return true;
318  }
319 #endif
320 #ifdef WITH_FFMPEG
321  if (anim->pCodecCtx != NULL) {
322  return true;
323  }
324 #endif
325  return false;
326 }
327 
328 void IMB_suffix_anim(struct anim *anim, const char *suffix)
329 {
330  BLI_strncpy(anim->suffix, suffix, sizeof(anim->suffix));
331 }
332 
333 #ifdef WITH_AVI
334 static int startavi(struct anim *anim)
335 {
336 
337  AviError avierror;
338 # if defined(_WIN32)
339  HRESULT hr;
340  int i, firstvideo = -1;
341  int streamcount;
342  BYTE abFormat[1024];
343  LONG l;
344  LPBITMAPINFOHEADER lpbi;
345  AVISTREAMINFO avis;
346 
347  streamcount = anim->streamindex;
348 # endif
349 
350  anim->avi = MEM_callocN(sizeof(AviMovie), "animavi");
351 
352  if (anim->avi == NULL) {
353  printf("Can't open avi: %s\n", anim->name);
354  return -1;
355  }
356 
357  avierror = AVI_open_movie(anim->name, anim->avi);
358 
359 # if defined(_WIN32)
360  if (avierror == AVI_ERROR_COMPRESSION) {
361  AVIFileInit();
362  hr = AVIFileOpen(&anim->pfile, anim->name, OF_READ, 0L);
363  if (hr == 0) {
364  anim->pfileopen = 1;
365  for (i = 0; i < MAXNUMSTREAMS; i++) {
366  if (AVIFileGetStream(anim->pfile, &anim->pavi[i], 0L, i) != AVIERR_OK) {
367  break;
368  }
369 
370  AVIStreamInfo(anim->pavi[i], &avis, sizeof(avis));
371  if ((avis.fccType == streamtypeVIDEO) && (firstvideo == -1)) {
372  if (streamcount > 0) {
373  streamcount--;
374  continue;
375  }
376  anim->pgf = AVIStreamGetFrameOpen(anim->pavi[i], NULL);
377  if (anim->pgf) {
378  firstvideo = i;
379 
380  /* get stream length */
381  anim->avi->header->TotalFrames = AVIStreamLength(anim->pavi[i]);
382 
383  /* get information about images inside the stream */
384  l = sizeof(abFormat);
385  AVIStreamReadFormat(anim->pavi[i], 0, &abFormat, &l);
386  lpbi = (LPBITMAPINFOHEADER)abFormat;
387  anim->avi->header->Height = lpbi->biHeight;
388  anim->avi->header->Width = lpbi->biWidth;
389  }
390  else {
391  FIXCC(avis.fccHandler);
392  FIXCC(avis.fccType);
393  printf("Can't find AVI decoder for type : %4.4hs/%4.4hs\n",
394  (LPSTR)&avis.fccType,
395  (LPSTR)&avis.fccHandler);
396  }
397  }
398  }
399 
400  /* register number of opened avistreams */
401  anim->avistreams = i;
402 
403  /*
404  * Couldn't get any video streams out of this file
405  */
406  if ((anim->avistreams == 0) || (firstvideo == -1)) {
407  avierror = AVI_ERROR_FORMAT;
408  }
409  else {
410  avierror = AVI_ERROR_NONE;
411  anim->firstvideo = firstvideo;
412  }
413  }
414  else {
415  AVIFileExit();
416  }
417  }
418 # endif
419 
420  if (avierror != AVI_ERROR_NONE) {
421  AVI_print_error(avierror);
422  printf("Error loading avi: %s\n", anim->name);
423  free_anim_avi(anim);
424  return -1;
425  }
426 
428  anim->start_offset = 0.0f;
429  anim->params = NULL;
430 
431  anim->x = anim->avi->header->Width;
432  anim->y = anim->avi->header->Height;
433  anim->interlacing = 0;
434  anim->orientation = 0;
435  anim->framesize = anim->x * anim->y * 4;
436 
437  anim->cur_position = 0;
438 
439 # if 0
440  printf("x:%d y:%d size:%d interl:%d dur:%d\n",
441  anim->x,
442  anim->y,
443  anim->framesize,
444  anim->interlacing,
446 # endif
447 
448  return 0;
449 }
450 #endif /* WITH_AVI */
451 
452 #ifdef WITH_AVI
453 static ImBuf *avi_fetchibuf(struct anim *anim, int position)
454 {
455  ImBuf *ibuf = NULL;
456  int *tmp;
457  int y;
458 
459  if (anim == NULL) {
460  return NULL;
461  }
462 
463 # if defined(_WIN32)
464  if (anim->avistreams) {
465  LPBITMAPINFOHEADER lpbi;
466 
467  if (anim->pgf) {
468  lpbi = AVIStreamGetFrame(anim->pgf, position + AVIStreamStart(anim->pavi[anim->firstvideo]));
469  if (lpbi) {
470  ibuf = IMB_ibImageFromMemory(
471  (const unsigned char *)lpbi, 100, IB_rect, anim->colorspace, "<avi_fetchibuf>");
472  /* Oh brother... */
473  }
474  }
475  }
476  else
477 # endif
478  {
479  ibuf = IMB_allocImBuf(anim->x, anim->y, 24, IB_rect);
480 
481  tmp = AVI_read_frame(
483 
484  if (tmp == NULL) {
485  printf("Error reading frame from AVI: '%s'\n", anim->name);
486  IMB_freeImBuf(ibuf);
487  return NULL;
488  }
489 
490  for (y = 0; y < anim->y; y++) {
491  memcpy(&(ibuf->rect)[((anim->y - y) - 1) * anim->x], &tmp[y * anim->x], anim->x * 4);
492  }
493 
494  MEM_freeN(tmp);
495  }
496 
498 
499  return ibuf;
500 }
501 #endif /* WITH_AVI */
502 
503 #ifdef WITH_FFMPEG
504 
505 BLI_INLINE bool need_aligned_ffmpeg_buffer(struct anim *anim)
506 {
507  return (anim->x & 31) != 0;
508 }
509 
510 static int startffmpeg(struct anim *anim)
511 {
512  int i, video_stream_index;
513 
514  AVCodec *pCodec;
515  AVFormatContext *pFormatCtx = NULL;
516  AVCodecContext *pCodecCtx;
517  AVRational frame_rate;
518  AVStream *video_stream;
519  int frs_num;
520  double frs_den;
521  int streamcount;
522 
523  /* The following for color space determination */
524  int srcRange, dstRange, brightness, contrast, saturation;
525  int *table;
526  const int *inv_table;
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]->codecpar->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 
566  /* Find the decoder for the video stream */
567  pCodec = avcodec_find_decoder(video_stream->codecpar->codec_id);
568  if (pCodec == NULL) {
569  avformat_close_input(&pFormatCtx);
570  return -1;
571  }
572 
573  pCodecCtx = avcodec_alloc_context3(NULL);
574  avcodec_parameters_to_context(pCodecCtx, video_stream->codecpar);
575  pCodecCtx->workaround_bugs = FF_BUG_AUTODETECT;
576 
577  if (pCodec->capabilities & AV_CODEC_CAP_AUTO_THREADS) {
578  pCodecCtx->thread_count = 0;
579  }
580  else {
581  pCodecCtx->thread_count = BLI_system_thread_count();
582  }
583 
584  if (pCodec->capabilities & AV_CODEC_CAP_FRAME_THREADS) {
585  pCodecCtx->thread_type = FF_THREAD_FRAME;
586  }
587  else if (pCodec->capabilities & AV_CODEC_CAP_SLICE_THREADS) {
588  pCodecCtx->thread_type = FF_THREAD_SLICE;
589  }
590 
591  if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) {
592  avformat_close_input(&pFormatCtx);
593  return -1;
594  }
595  if (pCodecCtx->pix_fmt == AV_PIX_FMT_NONE) {
596  avcodec_free_context(&anim->pCodecCtx);
597  avformat_close_input(&pFormatCtx);
598  return -1;
599  }
600 
601  double video_start = 0;
602  double pts_time_base = av_q2d(video_stream->time_base);
603 
604  if (video_stream->start_time != AV_NOPTS_VALUE) {
605  video_start = video_stream->start_time * pts_time_base;
606  }
607 
608  frame_rate = av_guess_frame_rate(pFormatCtx, video_stream, NULL);
610 
611  /* Take from the stream if we can. */
612  if (video_stream->nb_frames != 0) {
613  anim->duration_in_frames = video_stream->nb_frames;
614 
615  /* Sanity check on the detected duration. This is to work around corruption like reported in
616  * T68091. */
617  if (frame_rate.den != 0 && pFormatCtx->duration > 0) {
618  double stream_sec = anim->duration_in_frames * av_q2d(frame_rate);
619  double container_sec = pFormatCtx->duration / (double)AV_TIME_BASE;
620  if (stream_sec > 4.0 * container_sec) {
621  /* The stream is significantly longer than the container duration, which is
622  * suspicious. */
624  }
625  }
626  }
627  /* Fall back to manually estimating the video stream duration.
628  * This is because the video stream duration can be shorter than the pFormatCtx->duration.
629  */
630  if (anim->duration_in_frames == 0) {
631  double stream_dur;
632 
633  if (video_stream->duration != AV_NOPTS_VALUE) {
634  stream_dur = video_stream->duration * pts_time_base;
635  }
636  else {
637  double audio_start = 0;
638 
639  /* Find audio stream to guess the duration of the video.
640  * Sometimes the audio AND the video stream have a start offset.
641  * The difference between these is the offset we want to use to
642  * calculate the video duration.
643  */
644  for (i = 0; i < pFormatCtx->nb_streams; i++) {
645  if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
646  AVStream *audio_stream = pFormatCtx->streams[i];
647  if (audio_stream->start_time != AV_NOPTS_VALUE) {
648  audio_start = audio_stream->start_time * av_q2d(audio_stream->time_base);
649  }
650  break;
651  }
652  }
653 
654  if (video_start > audio_start) {
655  stream_dur = (double)pFormatCtx->duration / AV_TIME_BASE - (video_start - audio_start);
656  }
657  else {
658  /* The video stream starts before or at the same time as the audio stream!
659  * We have to assume that the video stream is as long as the full pFormatCtx->duration.
660  */
661  stream_dur = (double)pFormatCtx->duration / AV_TIME_BASE;
662  }
663  }
664  anim->duration_in_frames = (int)(stream_dur * av_q2d(frame_rate) + 0.5f);
665  }
666 
667  double ctx_start = 0;
668  if (pFormatCtx->start_time != AV_NOPTS_VALUE) {
669  ctx_start = (double)pFormatCtx->start_time / AV_TIME_BASE;
670  }
671 
672  frs_num = frame_rate.num;
673  frs_den = frame_rate.den;
674 
675  frs_den *= AV_TIME_BASE;
676 
677  while (frs_num % 10 == 0 && frs_den >= 2.0 && frs_num > 10) {
678  frs_num /= 10;
679  frs_den /= 10;
680  }
681 
682  anim->frs_sec = frs_num;
683  anim->frs_sec_base = frs_den;
684  /* Save the relative start time for the video. IE the start time in relation to where playback
685  * starts. */
686  anim->start_offset = video_start - ctx_start;
687 
688  anim->params = 0;
689 
690  anim->x = pCodecCtx->width;
691  anim->y = pCodecCtx->height;
692 
693  anim->pFormatCtx = pFormatCtx;
694  anim->pCodecCtx = pCodecCtx;
695  anim->pCodec = pCodec;
696  anim->videoStream = video_stream_index;
697 
698  anim->interlacing = 0;
699  anim->orientation = 0;
700  anim->framesize = anim->x * anim->y * 4;
701 
702  anim->cur_position = -1;
703  anim->cur_frame_final = 0;
704  anim->cur_pts = -1;
705  anim->cur_key_frame_pts = -1;
706  anim->cur_packet = av_packet_alloc();
707  anim->cur_packet->stream_index = -1;
708 
709  anim->pFrame = av_frame_alloc();
710  anim->pFrameComplete = false;
711  anim->pFrameDeinterlaced = av_frame_alloc();
712  anim->pFrameRGB = av_frame_alloc();
713 
714  if (need_aligned_ffmpeg_buffer(anim)) {
715  anim->pFrameRGB->format = AV_PIX_FMT_RGBA;
716  anim->pFrameRGB->width = anim->x;
717  anim->pFrameRGB->height = anim->y;
718 
719  if (av_frame_get_buffer(anim->pFrameRGB, 32) < 0) {
720  fprintf(stderr, "Could not allocate frame data.\n");
721  avcodec_free_context(&anim->pCodecCtx);
722  avformat_close_input(&anim->pFormatCtx);
723  av_packet_free(&anim->cur_packet);
724  av_frame_free(&anim->pFrameRGB);
725  av_frame_free(&anim->pFrameDeinterlaced);
726  av_frame_free(&anim->pFrame);
727  anim->pCodecCtx = NULL;
728  return -1;
729  }
730  }
731 
732  if (av_image_get_buffer_size(AV_PIX_FMT_RGBA, anim->x, anim->y, 1) != anim->x * anim->y * 4) {
733  fprintf(stderr, "ffmpeg has changed alloc scheme ... ARGHHH!\n");
734  avcodec_free_context(&anim->pCodecCtx);
735  avformat_close_input(&anim->pFormatCtx);
736  av_packet_free(&anim->cur_packet);
737  av_frame_free(&anim->pFrameRGB);
738  av_frame_free(&anim->pFrameDeinterlaced);
739  av_frame_free(&anim->pFrame);
740  anim->pCodecCtx = NULL;
741  return -1;
742  }
743 
745  av_image_fill_arrays(anim->pFrameDeinterlaced->data,
746  anim->pFrameDeinterlaced->linesize,
747  MEM_callocN(av_image_get_buffer_size(anim->pCodecCtx->pix_fmt,
748  anim->pCodecCtx->width,
749  anim->pCodecCtx->height,
750  1),
751  "ffmpeg deinterlace"),
752  anim->pCodecCtx->pix_fmt,
753  anim->pCodecCtx->width,
754  anim->pCodecCtx->height,
755  1);
756  }
757 
758  anim->img_convert_ctx = sws_getContext(anim->x,
759  anim->y,
760  anim->pCodecCtx->pix_fmt,
761  anim->x,
762  anim->y,
763  AV_PIX_FMT_RGBA,
764  SWS_BILINEAR | SWS_PRINT_INFO | SWS_FULL_CHR_H_INT,
765  NULL,
766  NULL,
767  NULL);
768 
769  if (!anim->img_convert_ctx) {
770  fprintf(stderr, "Can't transform color space??? Bailing out...\n");
771  avcodec_free_context(&anim->pCodecCtx);
772  avformat_close_input(&anim->pFormatCtx);
773  av_packet_free(&anim->cur_packet);
774  av_frame_free(&anim->pFrameRGB);
775  av_frame_free(&anim->pFrameDeinterlaced);
776  av_frame_free(&anim->pFrame);
777  anim->pCodecCtx = NULL;
778  return -1;
779  }
780 
781  /* Try do detect if input has 0-255 YCbCR range (JFIF Jpeg MotionJpeg) */
782  if (!sws_getColorspaceDetails(anim->img_convert_ctx,
783  (int **)&inv_table,
784  &srcRange,
785  &table,
786  &dstRange,
787  &brightness,
788  &contrast,
789  &saturation)) {
790  srcRange = srcRange || anim->pCodecCtx->color_range == AVCOL_RANGE_JPEG;
791  inv_table = sws_getCoefficients(anim->pCodecCtx->colorspace);
792 
793  if (sws_setColorspaceDetails(anim->img_convert_ctx,
794  (int *)inv_table,
795  srcRange,
796  table,
797  dstRange,
798  brightness,
799  contrast,
800  saturation)) {
801  fprintf(stderr, "Warning: Could not set libswscale colorspace details.\n");
802  }
803  }
804  else {
805  fprintf(stderr, "Warning: Could not set libswscale colorspace details.\n");
806  }
807 
808  return 0;
809 }
810 
811 /* postprocess the image in anim->pFrame and do color conversion
812  * and deinterlacing stuff.
813  *
814  * Output is anim->cur_frame_final
815  */
816 
817 static void ffmpeg_postprocess(struct anim *anim)
818 {
819  AVFrame *input = anim->pFrame;
820  ImBuf *ibuf = anim->cur_frame_final;
821  int filter_y = 0;
822 
823  if (!anim->pFrameComplete) {
824  return;
825  }
826 
827  /* This means the data wasn't read properly,
828  * this check stops crashing */
829  if (input->data[0] == 0 && input->data[1] == 0 && input->data[2] == 0 && input->data[3] == 0) {
830  fprintf(stderr,
831  "ffmpeg_fetchibuf: "
832  "data not read properly...\n");
833  return;
834  }
835 
836  av_log(anim->pFormatCtx,
837  AV_LOG_DEBUG,
838  " POSTPROC: anim->pFrame planes: %p %p %p %p\n",
839  input->data[0],
840  input->data[1],
841  input->data[2],
842  input->data[3]);
843 
845  if (av_image_deinterlace(anim->pFrameDeinterlaced,
846  anim->pFrame,
847  anim->pCodecCtx->pix_fmt,
848  anim->pCodecCtx->width,
849  anim->pCodecCtx->height) < 0) {
850  filter_y = true;
851  }
852  else {
853  input = anim->pFrameDeinterlaced;
854  }
855  }
856 
857  if (!need_aligned_ffmpeg_buffer(anim)) {
858  av_image_fill_arrays(anim->pFrameRGB->data,
859  anim->pFrameRGB->linesize,
860  (unsigned char *)ibuf->rect,
861  AV_PIX_FMT_RGBA,
862  anim->x,
863  anim->y,
864  1);
865  }
866 
867 # if defined(__x86_64__) || defined(_M_X64)
868  /* Scale and flip image over Y axis in one go, using negative strides.
869  * This doesn't work with arm/powerpc though and may be misusing the API.
870  * Limit it x86_64 where it appears to work.
871  * http://trac.ffmpeg.org/ticket/9060 */
872  int *dstStride = anim->pFrameRGB->linesize;
873  uint8_t **dst = anim->pFrameRGB->data;
874  const int dstStride2[4] = {-dstStride[0], 0, 0, 0};
875  uint8_t *dst2[4] = {dst[0] + (anim->y - 1) * dstStride[0], 0, 0, 0};
876 
877  sws_scale(anim->img_convert_ctx,
878  (const uint8_t *const *)input->data,
879  input->linesize,
880  0,
881  anim->y,
882  dst2,
883  dstStride2);
884 # else
885  /* Scale with swscale then flip image over Y axis. */
886  int *dstStride = anim->pFrameRGB->linesize;
887  uint8_t **dst = anim->pFrameRGB->data;
888  const int dstStride2[4] = {dstStride[0], 0, 0, 0};
889  uint8_t *dst2[4] = {dst[0], 0, 0, 0};
890  int x, y, h, w;
891  unsigned char *bottom;
892  unsigned char *top;
893 
894  sws_scale(anim->img_convert_ctx,
895  (const uint8_t *const *)input->data,
896  input->linesize,
897  0,
898  anim->y,
899  dst2,
900  dstStride2);
901 
902  bottom = (unsigned char *)ibuf->rect;
903  top = bottom + ibuf->x * (ibuf->y - 1) * 4;
904 
905  h = (ibuf->y + 1) / 2;
906  w = ibuf->x;
907 
908  for (y = 0; y < h; y++) {
909  unsigned char tmp[4];
910  unsigned int *tmp_l = (unsigned int *)tmp;
911 
912  for (x = 0; x < w; x++) {
913  tmp[0] = bottom[0];
914  tmp[1] = bottom[1];
915  tmp[2] = bottom[2];
916  tmp[3] = bottom[3];
917 
918  bottom[0] = top[0];
919  bottom[1] = top[1];
920  bottom[2] = top[2];
921  bottom[3] = top[3];
922 
923  *(unsigned int *)top = *tmp_l;
924 
925  bottom += 4;
926  top += 4;
927  }
928  top -= 8 * w;
929  }
930 # endif
931 
932  if (need_aligned_ffmpeg_buffer(anim)) {
933  uint8_t *buf_src = anim->pFrameRGB->data[0];
934  uint8_t *buf_dst = (uint8_t *)ibuf->rect;
935  for (int y = 0; y < anim->y; y++) {
936  memcpy(buf_dst, buf_src, anim->x * 4);
937  buf_dst += anim->x * 4;
938  buf_src += anim->pFrameRGB->linesize[0];
939  }
940  }
941 
942  if (filter_y) {
943  IMB_filtery(ibuf);
944  }
945 }
946 
947 /* decode one video frame also considering the packet read into cur_packet */
948 
949 static int ffmpeg_decode_video_frame(struct anim *anim)
950 {
951  int rval = 0;
952 
953  av_log(anim->pFormatCtx, AV_LOG_DEBUG, " DECODE VIDEO FRAME\n");
954 
955  if (anim->cur_packet->stream_index == anim->videoStream) {
956  av_packet_unref(anim->cur_packet);
957  anim->cur_packet->stream_index = -1;
958  }
959 
960  while ((rval = av_read_frame(anim->pFormatCtx, anim->cur_packet)) >= 0) {
961  av_log(anim->pFormatCtx,
962  AV_LOG_DEBUG,
963  "%sREAD: strID=%d (VID: %d) dts=%" PRId64 " pts=%" PRId64 " %s\n",
964  (anim->cur_packet->stream_index == anim->videoStream) ? "->" : " ",
965  anim->cur_packet->stream_index,
966  anim->videoStream,
967  (anim->cur_packet->dts == AV_NOPTS_VALUE) ? -1 : (int64_t)anim->cur_packet->dts,
968  (anim->cur_packet->pts == AV_NOPTS_VALUE) ? -1 : (int64_t)anim->cur_packet->pts,
969  (anim->cur_packet->flags & AV_PKT_FLAG_KEY) ? " KEY" : "");
970  if (anim->cur_packet->stream_index == anim->videoStream) {
971  anim->pFrameComplete = 0;
972 
973  avcodec_send_packet(anim->pCodecCtx, anim->cur_packet);
974  anim->pFrameComplete = avcodec_receive_frame(anim->pCodecCtx, anim->pFrame) == 0;
975 
976  if (anim->pFrameComplete) {
977  anim->cur_pts = av_get_pts_from_frame(anim->pFrame);
978 
979  if (anim->pFrame->key_frame) {
980  anim->cur_key_frame_pts = anim->cur_pts;
981  }
982  av_log(anim->pFormatCtx,
983  AV_LOG_DEBUG,
984  " FRAME DONE: cur_pts=%" PRId64 ", guessed_pts=%" PRId64 "\n",
985  (anim->pFrame->pts == AV_NOPTS_VALUE) ? -1 : (int64_t)anim->pFrame->pts,
986  (int64_t)anim->cur_pts);
987  break;
988  }
989  }
990  av_packet_unref(anim->cur_packet);
991  anim->cur_packet->stream_index = -1;
992  }
993 
994  if (rval == AVERROR_EOF) {
995  /* Flush any remaining frames out of the decoder. */
996  anim->pFrameComplete = 0;
997 
998  avcodec_send_packet(anim->pCodecCtx, NULL);
999  anim->pFrameComplete = avcodec_receive_frame(anim->pCodecCtx, anim->pFrame) == 0;
1000 
1001  if (anim->pFrameComplete) {
1002  anim->cur_pts = av_get_pts_from_frame(anim->pFrame);
1003 
1004  if (anim->pFrame->key_frame) {
1005  anim->cur_key_frame_pts = anim->cur_pts;
1006  }
1007  av_log(anim->pFormatCtx,
1008  AV_LOG_DEBUG,
1009  " FRAME DONE (after EOF): cur_pts=%" PRId64 ", guessed_pts=%" PRId64 "\n",
1010  (anim->pFrame->pts == AV_NOPTS_VALUE) ? -1 : (int64_t)anim->pFrame->pts,
1011  (int64_t)anim->cur_pts);
1012  rval = 0;
1013  }
1014  }
1015 
1016  if (rval < 0) {
1017  av_packet_unref(anim->cur_packet);
1018  anim->cur_packet->stream_index = -1;
1019 
1020  av_log(anim->pFormatCtx,
1021  AV_LOG_ERROR,
1022  " DECODE READ FAILED: av_read_frame() "
1023  "returned error: %s\n",
1024  av_err2str(rval));
1025  }
1026 
1027  return (rval >= 0);
1028 }
1029 
1030 static int match_format(const char *name, AVFormatContext *pFormatCtx)
1031 {
1032  const char *p;
1033  int len, namelen;
1034 
1035  const char *names = pFormatCtx->iformat->name;
1036 
1037  if (!name || !names) {
1038  return 0;
1039  }
1040 
1041  namelen = strlen(name);
1042  while ((p = strchr(names, ','))) {
1043  len = MAX2(p - names, namelen);
1044  if (!BLI_strncasecmp(name, names, len)) {
1045  return 1;
1046  }
1047  names = p + 1;
1048  }
1049  return !BLI_strcasecmp(name, names);
1050 }
1051 
1052 static int ffmpeg_seek_by_byte(AVFormatContext *pFormatCtx)
1053 {
1054  static const char *byte_seek_list[] = {"mpegts", 0};
1055  const char **p;
1056 
1057  if (pFormatCtx->iformat->flags & AVFMT_TS_DISCONT) {
1058  return true;
1059  }
1060 
1061  p = byte_seek_list;
1062 
1063  while (*p) {
1064  if (match_format(*p++, pFormatCtx)) {
1065  return true;
1066  }
1067  }
1068 
1069  return false;
1070 }
1071 
1072 static int64_t ffmpeg_get_seek_pts(struct anim *anim, int64_t pts_to_search)
1073 {
1074  AVStream *v_st = anim->pFormatCtx->streams[anim->videoStream];
1075  AVRational frame_rate = v_st->r_frame_rate;
1076  AVRational time_base = v_st->time_base;
1077  double steps_per_frame = (double)(frame_rate.den * time_base.den) /
1078  (double)(frame_rate.num * time_base.num);
1079  /* Step back half a frame position to make sure that we get the requested
1080  * frame and not the one after it. This is a workaround as ffmpeg will
1081  * sometimes not seek to a frame after the requested pts even if
1082  * AVSEEK_FLAG_BACKWARD is specified.
1083  */
1084  int64_t pts = pts_to_search - (steps_per_frame / 2);
1085 
1086  return pts;
1087 }
1088 
1089 /* This gives us an estimate of which pts our requested frame will have.
1090  * Note that this might be off a bit in certain video files, but it should still be close enough.
1091  */
1092 static int64_t ffmpeg_get_pts_to_search(struct anim *anim,
1093  struct anim_index *tc_index,
1094  int position)
1095 {
1096  int64_t pts_to_search;
1097 
1098  if (tc_index) {
1099  int new_frame_index = IMB_indexer_get_frame_index(tc_index, position);
1100  pts_to_search = IMB_indexer_get_pts(tc_index, new_frame_index);
1101  }
1102  else {
1103  AVStream *v_st = anim->pFormatCtx->streams[anim->videoStream];
1104  int64_t start_pts = v_st->start_time;
1105  AVRational frame_rate = v_st->r_frame_rate;
1106  AVRational time_base = v_st->time_base;
1107 
1108  double steps_per_frame = (double)(frame_rate.den * time_base.den) /
1109  (double)(frame_rate.num * time_base.num);
1110 
1111  pts_to_search = round(position * steps_per_frame);
1112 
1113  if (start_pts != AV_NOPTS_VALUE) {
1114  pts_to_search += start_pts;
1115  }
1116  }
1117  return pts_to_search;
1118 }
1119 
1120 /* Check if the pts will get us the same frame that we already have in memory from last decode. */
1121 static bool ffmpeg_pts_matches_last_frame(struct anim *anim, int64_t pts_to_search)
1122 {
1123  if (anim->pFrame && anim->cur_frame_final) {
1124  int64_t diff = pts_to_search - anim->cur_pts;
1125  return diff >= 0 && diff < anim->pFrame->pkt_duration;
1126  }
1127 
1128  return false;
1129 }
1130 
1131 static bool ffmpeg_is_first_frame_decode(struct anim *anim, int position)
1132 {
1133  return position == 0 && anim->cur_position == -1;
1134 }
1135 
1136 /* Decode frames one by one until its PTS matches pts_to_search. */
1137 static void ffmpeg_decode_video_frame_scan(struct anim *anim, int64_t pts_to_search)
1138 {
1139  av_log(anim->pFormatCtx, AV_LOG_DEBUG, "FETCH: within current GOP\n");
1140 
1141  av_log(anim->pFormatCtx,
1142  AV_LOG_DEBUG,
1143  "SCAN start: considering pts=%" PRId64 " in search of %" PRId64 "\n",
1144  (int64_t)anim->cur_pts,
1145  (int64_t)pts_to_search);
1146 
1147  int64_t start_gop_frame = anim->cur_key_frame_pts;
1148  bool scan_fuzzy = false;
1149 
1150  while (anim->cur_pts < pts_to_search) {
1151  av_log(anim->pFormatCtx,
1152  AV_LOG_DEBUG,
1153  " WHILE: pts=%" PRId64 " in search of %" PRId64 "\n",
1154  (int64_t)anim->cur_pts,
1155  (int64_t)pts_to_search);
1156  if (!ffmpeg_decode_video_frame(anim)) {
1157  break;
1158  }
1159 
1160  if (start_gop_frame != anim->cur_key_frame_pts) {
1161  break;
1162  }
1163 
1164  if (anim->cur_pts < pts_to_search &&
1165  anim->cur_pts + anim->pFrame->pkt_duration > pts_to_search) {
1166  /* Our estimate of the pts was a bit off, but we have the frame we want. */
1167  av_log(anim->pFormatCtx, AV_LOG_DEBUG, "SCAN fuzzy frame match\n");
1168  scan_fuzzy = true;
1169  break;
1170  }
1171  }
1172 
1173  if (start_gop_frame != anim->cur_key_frame_pts) {
1174  /* We went into an other GOP frame. This should never happen as we should have positioned us
1175  * correctly by seeking into the GOP frame that contains the frame we want. */
1176  av_log(anim->pFormatCtx,
1177  AV_LOG_ERROR,
1178  "SCAN failed: completely lost in stream, "
1179  "bailing out at PTS=%" PRId64 ", searching for PTS=%" PRId64 "\n",
1180  (int64_t)anim->cur_pts,
1181  (int64_t)pts_to_search);
1182  }
1183 
1184  if (scan_fuzzy || anim->cur_pts == pts_to_search) {
1185  av_log(anim->pFormatCtx, AV_LOG_DEBUG, "SCAN HAPPY: we found our PTS!\n");
1186  }
1187  else {
1188  av_log(anim->pFormatCtx, AV_LOG_ERROR, "SCAN UNHAPPY: PTS not matched!\n");
1189  }
1190 }
1191 
1192 /* Wrapper over av_seek_frame(), for formats that doesn't have its own read_seek() or
1193  * read_seek2() functions defined. When seeking in these formats, rule to seek to last
1194  * necessary I-frame is not honored. It is not even guaranteed that I-frame, that must be
1195  * decoded will be read. See https://trac.ffmpeg.org/ticket/1607 and
1196  * https://developer.blender.org/T86944. */
1197 static int ffmpeg_generic_seek_workaround(struct anim *anim,
1198  int64_t *requested_pts,
1199  int64_t pts_to_search)
1200 {
1201  AVStream *v_st = anim->pFormatCtx->streams[anim->videoStream];
1202  AVRational frame_rate = v_st->r_frame_rate;
1203  AVRational time_base = v_st->time_base;
1204 
1205  double steps_per_frame = (double)(frame_rate.den * time_base.den) /
1206  (double)(frame_rate.num * time_base.num);
1207 
1208  int64_t current_pts = *requested_pts;
1209  int64_t offset = 0;
1210 
1211  int64_t cur_pts, prev_pts = -1;
1212 
1213  /* Step backward frame by frame until we find the key frame we are looking for. */
1214  while (current_pts != 0) {
1215  current_pts = *requested_pts - (int64_t)round(offset * steps_per_frame);
1216  current_pts = MAX2(current_pts, 0);
1217 
1218  /* Seek to timestamp. */
1219  if (av_seek_frame(anim->pFormatCtx, anim->videoStream, current_pts, AVSEEK_FLAG_BACKWARD) <
1220  0) {
1221  break;
1222  }
1223 
1224  /* Read first video stream packet. */
1225  AVPacket *read_packet = av_packet_alloc();
1226  while (av_read_frame(anim->pFormatCtx, read_packet) >= 0) {
1227  if (read_packet->stream_index == anim->videoStream) {
1228  break;
1229  }
1230  av_packet_unref(read_packet);
1231  }
1232 
1233  /* If this packet contains an I-frame, this could be the frame that we need. */
1234  bool is_key_frame = read_packet->flags & AV_PKT_FLAG_KEY;
1235  /* We need to check the packet timestamp as the key frame could be for a GOP forward in the the
1236  * video stream. So if it has a larger timestamp than the frame we want, ignore it.
1237  */
1238  cur_pts = timestamp_from_pts_or_dts(read_packet->pts, read_packet->dts);
1239  av_packet_free(&read_packet);
1240 
1241  if (is_key_frame) {
1242  if (cur_pts <= pts_to_search) {
1243  /* We found the I-frame we were looking for! */
1244  break;
1245  }
1246  }
1247 
1248  if (cur_pts == prev_pts) {
1249  /* We got the same key frame packet twice.
1250  * This probably means that we have hit the beginning of the stream. */
1251  break;
1252  }
1253 
1254  prev_pts = cur_pts;
1255  offset++;
1256  }
1257 
1258  *requested_pts = current_pts;
1259 
1260  /* Re-seek to timestamp that gave I-frame, so it can be read by decode function. */
1261  return av_seek_frame(anim->pFormatCtx, anim->videoStream, current_pts, AVSEEK_FLAG_BACKWARD);
1262 }
1263 
1264 /* Seek to last necessary key frame. */
1265 static int ffmpeg_seek_to_key_frame(struct anim *anim,
1266  int position,
1267  struct anim_index *tc_index,
1268  int64_t pts_to_search)
1269 {
1270  int64_t pos;
1271  int ret;
1272 
1273  if (tc_index) {
1274  /* We can use timestamps generated from our indexer to seek. */
1275  int new_frame_index = IMB_indexer_get_frame_index(tc_index, position);
1276  int old_frame_index = IMB_indexer_get_frame_index(tc_index, anim->cur_position);
1277 
1278  if (IMB_indexer_can_scan(tc_index, old_frame_index, new_frame_index)) {
1279  /* No need to seek, return early. */
1280  return 0;
1281  }
1282  uint64_t pts;
1283  uint64_t dts;
1284 
1285  pos = IMB_indexer_get_seek_pos(tc_index, new_frame_index);
1286  pts = IMB_indexer_get_seek_pos_pts(tc_index, new_frame_index);
1287  dts = IMB_indexer_get_seek_pos_dts(tc_index, new_frame_index);
1288 
1289  anim->cur_key_frame_pts = timestamp_from_pts_or_dts(pts, dts);
1290 
1291  av_log(anim->pFormatCtx, AV_LOG_DEBUG, "TC INDEX seek pos = %" PRId64 "\n", pos);
1292  av_log(anim->pFormatCtx, AV_LOG_DEBUG, "TC INDEX seek pts = %" PRIu64 "\n", pts);
1293  av_log(anim->pFormatCtx, AV_LOG_DEBUG, "TC INDEX seek dts = %" PRIu64 "\n", dts);
1294 
1295  if (ffmpeg_seek_by_byte(anim->pFormatCtx)) {
1296  av_log(anim->pFormatCtx, AV_LOG_DEBUG, "... using BYTE pos\n");
1297 
1298  ret = av_seek_frame(anim->pFormatCtx, -1, pos, AVSEEK_FLAG_BYTE);
1299  }
1300  else {
1301  av_log(anim->pFormatCtx, AV_LOG_DEBUG, "... using PTS pos\n");
1302  ret = av_seek_frame(
1303  anim->pFormatCtx, anim->videoStream, anim->cur_key_frame_pts, AVSEEK_FLAG_BACKWARD);
1304  }
1305  }
1306  else {
1307  /* We have to manually seek with ffmpeg to get to the key frame we want to start decoding from.
1308  */
1309  pos = ffmpeg_get_seek_pts(anim, pts_to_search);
1310  av_log(anim->pFormatCtx, AV_LOG_DEBUG, "NO INDEX final seek pos = %" PRId64 "\n", pos);
1311 
1312  AVFormatContext *format_ctx = anim->pFormatCtx;
1313 
1314  if (format_ctx->iformat->read_seek2 || format_ctx->iformat->read_seek) {
1315  ret = av_seek_frame(anim->pFormatCtx, anim->videoStream, pos, AVSEEK_FLAG_BACKWARD);
1316  }
1317  else {
1318  ret = ffmpeg_generic_seek_workaround(anim, &pos, pts_to_search);
1319  av_log(anim->pFormatCtx, AV_LOG_DEBUG, "Adjusted final seek pos = %" PRId64 "\n", pos);
1320  }
1321 
1322  if (ret >= 0) {
1323  /* Double check if we need to seek and decode all packets. */
1324  AVPacket *current_gop_start_packet = av_packet_alloc();
1325  while (av_read_frame(anim->pFormatCtx, current_gop_start_packet) >= 0) {
1326  if (current_gop_start_packet->stream_index == anim->videoStream) {
1327  break;
1328  }
1329  av_packet_unref(current_gop_start_packet);
1330  }
1331  int64_t gop_pts = timestamp_from_pts_or_dts(current_gop_start_packet->pts,
1332  current_gop_start_packet->dts);
1333 
1334  av_packet_free(&current_gop_start_packet);
1335  bool same_gop = gop_pts == anim->cur_key_frame_pts;
1336 
1337  if (same_gop && position > anim->cur_position) {
1338  /* Change back to our old frame position so we can simply continue decoding from there. */
1339  int64_t cur_pts = timestamp_from_pts_or_dts(anim->cur_packet->pts, anim->cur_packet->dts);
1340 
1341  if (cur_pts == gop_pts) {
1342  /* We are already at the correct position. */
1343  return 0;
1344  }
1345  AVPacket *temp = av_packet_alloc();
1346 
1347  while (av_read_frame(anim->pFormatCtx, temp) >= 0) {
1348  int64_t temp_pts = timestamp_from_pts_or_dts(temp->pts, temp->dts);
1349  if (temp->stream_index == anim->videoStream && temp_pts == cur_pts) {
1350  break;
1351  }
1352  av_packet_unref(temp);
1353  }
1354  av_packet_free(&temp);
1355  return 0;
1356  }
1357 
1358  anim->cur_key_frame_pts = gop_pts;
1359  /* Seek back so we are at the correct position after we decoded a frame. */
1360  av_seek_frame(anim->pFormatCtx, anim->videoStream, pos, AVSEEK_FLAG_BACKWARD);
1361  }
1362  }
1363 
1364  if (ret < 0) {
1365  av_log(anim->pFormatCtx,
1366  AV_LOG_ERROR,
1367  "FETCH: "
1368  "error while seeking to DTS = %" PRId64 " (frameno = %d, PTS = %" PRId64
1369  "): errcode = %d\n",
1370  pos,
1371  position,
1372  pts_to_search,
1373  ret);
1374  }
1375  /* Flush the internal buffers of ffmpeg. This needs to be done after seeking to avoid decoding
1376  * errors. */
1377  avcodec_flush_buffers(anim->pCodecCtx);
1378 
1379  anim->cur_pts = -1;
1380 
1381  if (anim->cur_packet->stream_index == anim->videoStream) {
1382  av_packet_unref(anim->cur_packet);
1383  anim->cur_packet->stream_index = -1;
1384  }
1385 
1386  return ret;
1387 }
1388 
1389 static ImBuf *ffmpeg_fetchibuf(struct anim *anim, int position, IMB_Timecode_Type tc)
1390 {
1391  if (anim == NULL) {
1392  return NULL;
1393  }
1394 
1395  av_log(anim->pFormatCtx, AV_LOG_DEBUG, "FETCH: pos=%d\n", position);
1396 
1397  struct anim_index *tc_index = IMB_anim_open_index(anim, tc);
1398  int64_t pts_to_search = ffmpeg_get_pts_to_search(anim, tc_index, position);
1399  AVStream *v_st = anim->pFormatCtx->streams[anim->videoStream];
1400  double frame_rate = av_q2d(v_st->r_frame_rate);
1401  double pts_time_base = av_q2d(v_st->time_base);
1402  int64_t start_pts = v_st->start_time;
1403 
1404  av_log(anim->pFormatCtx,
1405  AV_LOG_DEBUG,
1406  "FETCH: looking for PTS=%" PRId64 " (pts_timebase=%g, frame_rate=%g, start_pts=%" PRId64
1407  ")\n",
1408  (int64_t)pts_to_search,
1409  pts_time_base,
1410  frame_rate,
1411  start_pts);
1412 
1413  if (ffmpeg_pts_matches_last_frame(anim, pts_to_search)) {
1414  av_log(anim->pFormatCtx,
1415  AV_LOG_DEBUG,
1416  "FETCH: frame repeat: pts: %" PRId64 "\n",
1417  (int64_t)anim->cur_pts);
1418  IMB_refImBuf(anim->cur_frame_final);
1419  anim->cur_position = position;
1420  return anim->cur_frame_final;
1421  }
1422 
1423  if (position == anim->cur_position + 1 || ffmpeg_is_first_frame_decode(anim, position)) {
1424  av_log(anim->pFormatCtx, AV_LOG_DEBUG, "FETCH: no seek necessary, just continue...\n");
1425  ffmpeg_decode_video_frame(anim);
1426  }
1427  else if (ffmpeg_seek_to_key_frame(anim, position, tc_index, pts_to_search) >= 0) {
1428  ffmpeg_decode_video_frame_scan(anim, pts_to_search);
1429  }
1430 
1431  IMB_freeImBuf(anim->cur_frame_final);
1432 
1433  /* Certain versions of FFmpeg have a bug in libswscale which ends up in crash
1434  * when destination buffer is not properly aligned. For example, this happens
1435  * in FFmpeg 4.3.1. It got fixed later on, but for compatibility reasons is
1436  * still best to avoid crash.
1437  *
1438  * This is achieved by using own allocation call rather than relying on
1439  * IMB_allocImBuf() to do so since the IMB_allocImBuf() is not guaranteed
1440  * to perform aligned allocation.
1441  *
1442  * In theory this could give better performance, since SIMD operations on
1443  * aligned data are usually faster.
1444  *
1445  * Note that even though sometimes vertical flip is required it does not
1446  * affect on alignment of data passed to sws_scale because if the X dimension
1447  * is not 32 byte aligned special intermediate buffer is allocated.
1448  *
1449  * The issue was reported to FFmpeg under ticket #8747 in the FFmpeg tracker
1450  * and is fixed in the newer versions than 4.3.1. */
1451  anim->cur_frame_final = IMB_allocImBuf(anim->x, anim->y, 32, 0);
1452  anim->cur_frame_final->rect = MEM_mallocN_aligned(
1453  (size_t)4 * anim->x * anim->y, 32, "ffmpeg ibuf");
1454  anim->cur_frame_final->mall |= IB_rect;
1455 
1456  anim->cur_frame_final->rect_colorspace = colormanage_colorspace_get_named(anim->colorspace);
1457 
1458  ffmpeg_postprocess(anim);
1459 
1460  anim->cur_position = position;
1461 
1462  IMB_refImBuf(anim->cur_frame_final);
1463 
1464  return anim->cur_frame_final;
1465 }
1466 
1467 static void free_anim_ffmpeg(struct anim *anim)
1468 {
1469  if (anim == NULL) {
1470  return;
1471  }
1472 
1473  if (anim->pCodecCtx) {
1474  avcodec_free_context(&anim->pCodecCtx);
1475  avformat_close_input(&anim->pFormatCtx);
1476  av_packet_free(&anim->cur_packet);
1477 
1478  av_frame_free(&anim->pFrame);
1479 
1480  if (!need_aligned_ffmpeg_buffer(anim)) {
1481  /* If there's no need for own aligned buffer it means that FFmpeg's
1482  * frame shares the same buffer as temporary ImBuf. In this case we
1483  * should not free the buffer when freeing the FFmpeg buffer.
1484  */
1485  av_image_fill_arrays(anim->pFrameRGB->data,
1486  anim->pFrameRGB->linesize,
1487  NULL,
1488  AV_PIX_FMT_RGBA,
1489  anim->x,
1490  anim->y,
1491  1);
1492  }
1493  av_frame_free(&anim->pFrameRGB);
1494  av_frame_free(&anim->pFrameDeinterlaced);
1495 
1496  sws_freeContext(anim->img_convert_ctx);
1497  IMB_freeImBuf(anim->cur_frame_final);
1498  }
1499  anim->duration_in_frames = 0;
1500 }
1501 
1502 #endif
1503 
1504 /* Try next picture to read */
1505 /* No picture, try to open next animation */
1506 /* Succeed, remove first image from animation */
1507 
1508 static ImBuf *anim_getnew(struct anim *anim)
1509 {
1510  struct ImBuf *ibuf = NULL;
1511 
1512  if (anim == NULL) {
1513  return NULL;
1514  }
1515 
1517 
1518 #ifdef WITH_AVI
1519  free_anim_avi(anim);
1520 #endif
1521 
1522 #ifdef WITH_FFMPEG
1523  free_anim_ffmpeg(anim);
1524 #endif
1525 
1526  if (anim->curtype != 0) {
1527  return NULL;
1528  }
1530 
1531  switch (anim->curtype) {
1532  case ANIM_SEQUENCE:
1534  if (ibuf) {
1535  BLI_strncpy(anim->first, anim->name, sizeof(anim->first));
1536  anim->duration_in_frames = 1;
1537  }
1538  break;
1539  case ANIM_MOVIE:
1540  if (startmovie(anim)) {
1541  return NULL;
1542  }
1543  ibuf = IMB_allocImBuf(anim->x, anim->y, 24, 0); /* fake */
1544  break;
1545 #ifdef WITH_AVI
1546  case ANIM_AVI:
1547  if (startavi(anim)) {
1548  printf("couldn't start avi\n");
1549  return NULL;
1550  }
1551  ibuf = IMB_allocImBuf(anim->x, anim->y, 24, 0);
1552  break;
1553 #endif
1554 #ifdef WITH_FFMPEG
1555  case ANIM_FFMPEG:
1556  if (startffmpeg(anim)) {
1557  return 0;
1558  }
1559  ibuf = IMB_allocImBuf(anim->x, anim->y, 24, 0);
1560  break;
1561 #endif
1562  }
1563  return ibuf;
1564 }
1565 
1567 {
1568  struct ImBuf *ibuf = NULL;
1569  int position = 0;
1570 
1572  if (ibuf) {
1573  IMB_freeImBuf(ibuf);
1574  position = anim->duration_in_frames / 2;
1575  ibuf = IMB_anim_absolute(anim, position, IMB_TC_NONE, IMB_PROXY_NONE);
1576  }
1577  return ibuf;
1578 }
1579 
1581  int position,
1582  IMB_Timecode_Type tc,
1583  IMB_Proxy_Size preview_size)
1584 {
1585  struct ImBuf *ibuf = NULL;
1586  char head[256], tail[256];
1587  unsigned short digits;
1588  int pic;
1589  int filter_y;
1590  if (anim == NULL) {
1591  return NULL;
1592  }
1593 
1594  filter_y = (anim->ib_flags & IB_animdeinterlace);
1595 
1596  if (preview_size == IMB_PROXY_NONE) {
1597  if (anim->curtype == 0) {
1598  ibuf = anim_getnew(anim);
1599  if (ibuf == NULL) {
1600  return NULL;
1601  }
1602 
1603  IMB_freeImBuf(ibuf); /* ???? */
1604  ibuf = NULL;
1605  }
1606 
1607  if (position < 0) {
1608  return NULL;
1609  }
1610  if (position >= anim->duration_in_frames) {
1611  return NULL;
1612  }
1613  }
1614  else {
1615  struct anim *proxy = IMB_anim_open_proxy(anim, preview_size);
1616 
1617  if (proxy) {
1618  position = IMB_anim_index_get_frame_index(anim, tc, position);
1619 
1620  return IMB_anim_absolute(proxy, position, IMB_TC_NONE, IMB_PROXY_NONE);
1621  }
1622  }
1623 
1624  switch (anim->curtype) {
1625  case ANIM_SEQUENCE:
1626  pic = an_stringdec(anim->first, head, tail, &digits);
1627  pic += position;
1628  an_stringenc(anim->name, head, tail, digits, pic);
1630  if (ibuf) {
1631  anim->cur_position = position;
1632  }
1633  break;
1634  case ANIM_MOVIE:
1635  ibuf = movie_fetchibuf(anim, position);
1636  if (ibuf) {
1637  anim->cur_position = position;
1639  }
1640  break;
1641 #ifdef WITH_AVI
1642  case ANIM_AVI:
1643  ibuf = avi_fetchibuf(anim, position);
1644  if (ibuf) {
1645  anim->cur_position = position;
1646  }
1647  break;
1648 #endif
1649 #ifdef WITH_FFMPEG
1650  case ANIM_FFMPEG:
1651  ibuf = ffmpeg_fetchibuf(anim, position, tc);
1652  if (ibuf) {
1653  anim->cur_position = position;
1654  }
1655  filter_y = 0; /* done internally */
1656  break;
1657 #endif
1658  }
1659 
1660  if (ibuf) {
1661  if (filter_y) {
1662  IMB_filtery(ibuf);
1663  }
1664  BLI_snprintf(ibuf->name, sizeof(ibuf->name), "%s.%04d", anim->name, anim->cur_position + 1);
1665  }
1666  return ibuf;
1667 }
1668 
1669 /***/
1670 
1672 {
1673  struct anim_index *idx;
1674  if (tc == IMB_TC_NONE) {
1675  return anim->duration_in_frames;
1676  }
1677 
1678  idx = IMB_anim_open_index(anim, tc);
1679  if (!idx) {
1680  return anim->duration_in_frames;
1681  }
1682 
1683  return IMB_indexer_get_duration(idx);
1684 }
1685 
1687 {
1688  return anim->start_offset;
1689 }
1690 
1691 bool IMB_anim_get_fps(struct anim *anim, short *frs_sec, float *frs_sec_base, bool no_av_base)
1692 {
1693  double frs_sec_base_double;
1694  if (anim->frs_sec) {
1695  if (anim->frs_sec > SHRT_MAX) {
1696  /* We cannot store original rational in our short/float format,
1697  * we need to approximate it as best as we can... */
1698  *frs_sec = SHRT_MAX;
1699  frs_sec_base_double = anim->frs_sec_base * (double)SHRT_MAX / (double)anim->frs_sec;
1700  }
1701  else {
1702  *frs_sec = anim->frs_sec;
1703  frs_sec_base_double = anim->frs_sec_base;
1704  }
1705 #ifdef WITH_FFMPEG
1706  if (no_av_base) {
1707  *frs_sec_base = (float)(frs_sec_base_double / AV_TIME_BASE);
1708  }
1709  else {
1710  *frs_sec_base = (float)frs_sec_base_double;
1711  }
1712 #else
1713  UNUSED_VARS(no_av_base);
1714  *frs_sec_base = (float)frs_sec_base_double;
1715 #endif
1716  BLI_assert(*frs_sec > 0);
1717  BLI_assert(*frs_sec_base > 0.0f);
1718 
1719  return true;
1720  }
1721  return false;
1722 }
1723 
1725 {
1726  return anim->x;
1727 }
1728 
1730 {
1731  return anim->y;
1732 }
AviError
Definition: AVI_avi.h:201
@ AVI_ERROR_FORMAT
Definition: AVI_avi.h:207
@ AVI_ERROR_NONE
Definition: AVI_avi.h:202
@ AVI_ERROR_COMPRESSION
Definition: AVI_avi.h:203
AviError AVI_close(AviMovie *movie)
Definition: avi.c:686
void * AVI_read_frame(AviMovie *movie, AviFormat format, int frame, int stream)
Definition: avi.c:639
#define AVIST_VIDEO
Definition: AVI_avi.h:91
@ AVI_FORMAT_RGB32
Definition: AVI_avi.h:164
AviError AVI_print_error(AviError error)
Definition: avi.c:158
int AVI_get_stream(AviMovie *movie, int avist_type, int stream_num)
Definition: avi.c:106
AviError AVI_open_movie(const char *name, AviMovie *movie)
Definition: avi.c:394
typedef float(TangentPoint)[2]
#define BLI_assert(a)
Definition: BLI_assert.h:58
#define BLI_INLINE
bool BLI_path_is_rel(const char *path) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT
Definition: path_util.c:411
void BLI_path_sequence_encode(char *string, const char *head, const char *tail, unsigned short numlen, int pic)
Definition: path_util.c:154
int BLI_strncasecmp(const char *s1, const char *s2, size_t len) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: string.c:689
int BLI_strcasecmp(const char *s1, const char *s2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: string.c:666
size_t BLI_snprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, const size_t maxncpy) ATTR_NONNULL()
Definition: string.c:108
int BLI_system_thread_count(void)
Definition: threads.cc:309
#define UNUSED_VARS(...)
#define UNUSED(x)
#define MAX2(a, b)
Compatibility-like things for windows.
typedef double(DMatrix)[4][4]
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble top
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble bottom
#define MAXNUMSTREAMS
Definition: IMB_anim.h:81
#define ANIM_MOVIE
Definition: IMB_anim.h:77
#define ANIM_SEQUENCE
Definition: IMB_anim.h:76
#define ANIM_FFMPEG
Definition: IMB_anim.h:79
#define ANIM_AVI
Definition: IMB_anim.h:78
#define ANIM_NONE
Definition: IMB_anim.h:75
@ COLOR_ROLE_DEFAULT_BYTE
struct ImBuf * IMB_allocImBuf(unsigned int x, unsigned int y, unsigned char planes, unsigned int flags)
Definition: allocimbuf.c:478
IMB_Proxy_Size
Definition: IMB_imbuf.h:317
@ IMB_PROXY_NONE
Definition: IMB_imbuf.h:318
void IMB_freeImBuf(struct ImBuf *ibuf)
Definition: allocimbuf.c:211
void IMB_filtery(struct ImBuf *ibuf)
Definition: filter.c:119
int IMB_anim_index_get_frame_index(struct anim *anim, IMB_Timecode_Type tc, int position)
Definition: indexer.c:1480
void IMB_refImBuf(struct ImBuf *ibuf)
Definition: allocimbuf.c:239
#define IM_MAX_SPACE
Definition: IMB_imbuf.h:65
struct ImBuf * IMB_loadiffname(const char *filepath, int flags, char colorspace[IM_MAX_SPACE])
Definition: readimage.c:224
void IMB_convert_rgba_to_abgr(struct ImBuf *ibuf)
Definition: imageprocess.c:45
struct ImBuf * IMB_ibImageFromMemory(const unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE], const char *descr)
Definition: readimage.c:99
int imb_get_anim_type(const char *filepath)
Definition: util.c:338
IMB_Timecode_Type
Definition: IMB_imbuf.h:298
@ IMB_TC_NONE
Definition: IMB_imbuf.h:300
Contains defines and structs used throughout the imbuf module.
@ IB_animdeinterlace
@ IB_rect
uint64_t IMB_indexer_get_seek_pos(struct anim_index *idx, int frame_index)
Definition: indexer.c:248
uint64_t IMB_indexer_get_seek_pos_pts(struct anim_index *idx, int frame_index)
Definition: indexer.c:259
struct anim_index * IMB_anim_open_index(struct anim *anim, IMB_Timecode_Type tc)
Definition: indexer.c:1454
uint64_t IMB_indexer_get_seek_pos_dts(struct anim_index *idx, int frame_index)
Definition: indexer.c:270
void IMB_free_indices(struct anim *anim)
Definition: indexer.c:1395
int IMB_indexer_get_duration(struct anim_index *idx)
Definition: indexer.c:324
struct anim * IMB_anim_open_proxy(struct anim *anim, IMB_Proxy_Size preview_size)
Definition: indexer.c:1427
int IMB_indexer_can_scan(struct anim_index *idx, int old_frame_index, int new_frame_index)
Definition: indexer.c:332
uint64_t IMB_indexer_get_pts(struct anim_index *idx, int frame_index)
Definition: indexer.c:313
int IMB_indexer_get_frame_index(struct anim_index *idx, int frameno)
Definition: indexer.c:281
void IMB_metadata_set_field(struct IDProperty *metadata, const char *key, const char *value)
Definition: metadata.c:89
void IMB_metadata_ensure(struct IDProperty **metadata)
Definition: metadata.c:41
void IMB_metadata_free(struct IDProperty *metadata)
Definition: metadata.c:51
Read Guarded memory(de)allocation.
static int an_stringdec(const char *string, char *head, char *tail, unsigned short *numlen)
Definition: anim_movie.c:114
void IMB_close_anim_proxies(struct anim *anim)
Definition: anim_movie.c:238
bool IMB_anim_get_fps(struct anim *anim, short *frs_sec, float *frs_sec_base, bool no_av_base)
Definition: anim_movie.c:1691
void IMB_free_anim(struct anim *anim)
Definition: anim_movie.c:207
int ismovie(const char *UNUSED(filepath))
Definition: anim_movie.c:89
void IMB_close_anim(struct anim *anim)
Definition: anim_movie.c:229
static ImBuf * movie_fetchibuf(struct anim *UNUSED(anim), int UNUSED(position))
Definition: anim_movie.c:99
#define PATHSEPARATOR
Definition: anim_movie.c:111
static void free_anim_movie(struct anim *UNUSED(anim))
Definition: anim_movie.c:103
int IMB_anim_get_image_height(struct anim *anim)
Definition: anim_movie.c:1729
static int startmovie(struct anim *UNUSED(anim))
Definition: anim_movie.c:95
struct anim * IMB_open_anim(const char *name, int ib_flags, int streamindex, char colorspace[IM_MAX_SPACE])
Definition: anim_movie.c:282
static void an_stringenc(char *string, const char *head, const char *tail, unsigned short numlen, int pic)
Definition: anim_movie.c:156
struct IDProperty * IMB_anim_load_metadata(struct anim *anim)
Definition: anim_movie.c:247
struct ImBuf * IMB_anim_previewframe(struct anim *anim)
Definition: anim_movie.c:1566
void IMB_suffix_anim(struct anim *anim, const char *suffix)
Definition: anim_movie.c:328
double IMD_anim_get_offset(struct anim *anim)
Definition: anim_movie.c:1686
int IMB_anim_get_image_width(struct anim *anim)
Definition: anim_movie.c:1724
struct ImBuf * IMB_anim_absolute(struct anim *anim, int position, IMB_Timecode_Type tc, IMB_Proxy_Size preview_size)
Definition: anim_movie.c:1580
static ImBuf * anim_getnew(struct anim *anim)
Definition: anim_movie.c:1508
bool IMB_anim_can_produce_frames(const struct anim *anim)
Definition: anim_movie.c:309
int IMB_anim_get_duration(struct anim *anim, IMB_Timecode_Type tc)
Definition: anim_movie.c:1671
ATTR_WARN_UNUSED_RESULT const BMLoop * l
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition: btQuadWord.h:119
void colorspace_set_default_role(char *colorspace, int size, int role)
ColorSpace * colormanage_colorspace_get_named(const char *name)
FFMPEG_INLINE int64_t timestamp_from_pts_or_dts(int64_t pts, int64_t dts)
Definition: ffmpeg_compat.h:96
FFMPEG_INLINE int64_t av_get_pts_from_frame(AVFrame *picture)
FFMPEG_INLINE int av_image_deinterlace(AVFrame *dst, const AVFrame *src, enum AVPixelFormat pix_fmt, int width, int height)
uint pos
#define PRIu64
Definition: inttypes.h:135
#define PRId64
Definition: inttypes.h:81
static char ** names
Definition: makesdna.c:162
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_mallocN_aligned)(size_t len, size_t alignment, const char *str)
Definition: mallocn.c:49
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
#define L
IMETHOD Vector diff(const Vector &a, const Vector &b, double dt=1)
return ret
__int64 int64_t
Definition: stdint.h:92
unsigned char uint8_t
Definition: stdint.h:81
unsigned __int64 uint64_t
Definition: stdint.h:93
struct ColorSpace * rect_colorspace
char name[IMB_FILENAME_SIZE]
unsigned int * rect
int TotalFrames
Definition: AVI_avi.h:78
AviMainHeader * header
Definition: AVI_avi.h:187
Definition: IMB_anim.h:87
int x
Definition: IMB_anim.h:95
int orientation
Definition: IMB_anim.h:106
struct _AviMovie * avi
Definition: IMB_anim.h:112
char first[1024]
Definition: IMB_anim.h:100
double start_offset
Definition: IMB_anim.h:94
char suffix[64]
Definition: IMB_anim.h:150
size_t framesize
Definition: IMB_anim.h:107
int ib_flags
Definition: IMB_anim.h:88
int frs_sec
Definition: IMB_anim.h:92
char colorspace[64]
Definition: IMB_anim.h:149
int interlacing
Definition: IMB_anim.h:108
int duration_in_frames
Definition: IMB_anim.h:91
struct IDProperty * metadata
Definition: IMB_anim.h:152
int y
Definition: IMB_anim.h:95
void * params
Definition: IMB_anim.h:105
int curtype
Definition: IMB_anim.h:89
int streamindex
Definition: IMB_anim.h:109
char name[1024]
Definition: IMB_anim.h:98
double frs_sec_base
Definition: IMB_anim.h:93
int cur_position
Definition: IMB_anim.h:90
uint len