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