Blender  V3.3
util.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 <io.h>
10 #endif
11 
12 #include <stdlib.h>
13 
14 #include "BLI_fileops.h"
15 #include "BLI_path_util.h"
16 #include "BLI_utildefines.h"
17 #ifdef _WIN32
18 # include "BLI_winstuff.h"
19 #endif
20 
21 #include "IMB_filetype.h"
22 #include "IMB_imbuf.h"
23 #include "IMB_imbuf_types.h"
24 #include "imbuf.h"
25 
26 #include "IMB_anim.h"
27 
28 #ifdef WITH_FFMPEG
29 # include "BLI_string.h" /* BLI_vsnprintf */
30 
31 # include "BKE_global.h" /* G.debug */
32 
33 # include <libavcodec/avcodec.h>
34 # include <libavdevice/avdevice.h>
35 # include <libavformat/avformat.h>
36 # include <libavutil/log.h>
37 
38 # include "ffmpeg_compat.h"
39 #endif
40 
41 #define UTIL_DEBUG 0
42 
43 const char *imb_ext_image[] = {
44  ".png", ".tga", ".bmp", ".jpg", ".jpeg", ".sgi", ".rgb", ".rgba",
45 #ifdef WITH_TIFF
46  ".tif", ".tiff", ".tx",
47 #endif
48 #ifdef WITH_OPENJPEG
49  ".jp2", ".j2c",
50 #endif
51 #ifdef WITH_HDR
52  ".hdr",
53 #endif
54 #ifdef WITH_DDS
55  ".dds",
56 #endif
57 #ifdef WITH_CINEON
58  ".dpx", ".cin",
59 #endif
60 #ifdef WITH_OPENEXR
61  ".exr",
62 #endif
63 #ifdef WITH_OPENIMAGEIO
64  ".psd", ".pdd", ".psb",
65 #endif
66 #ifdef WITH_WEBP
67  ".webp",
68 #endif
69  NULL,
70 };
71 
72 const char *imb_ext_image_filepath_only[] = {
73 #ifdef WITH_OPENIMAGEIO
74  ".psd",
75  ".pdd",
76  ".psb",
77 #endif
78  NULL,
79 };
80 
81 const char *imb_ext_movie[] = {
82  ".avi", ".flc", ".mov", ".movie", ".mp4", ".m4v", ".m2v", ".m2t", ".m2ts", ".mts",
83  ".ts", ".mv", ".avs", ".wmv", ".ogv", ".ogg", ".r3d", ".dv", ".mpeg", ".mpg",
84  ".mpg2", ".vob", ".mkv", ".flv", ".divx", ".xvid", ".mxf", ".webm", NULL,
85 };
86 
88 const char *imb_ext_audio[] = {
89  ".wav",
90  ".ogg",
91  ".oga",
92  ".mp3",
93  ".mp2",
94  ".ac3",
95  ".aac",
96  ".flac",
97  ".wma",
98  ".eac3",
99  ".aif",
100  ".aiff",
101  ".m4a",
102  ".mka",
103  NULL,
104 };
105 
106 /* Increased from 32 to 64 because of the bitmaps header size. */
107 #define HEADER_SIZE 64
108 
109 static ssize_t imb_ispic_read_header_from_filepath(const char *filepath,
110  unsigned char buf[HEADER_SIZE])
111 {
112  BLI_stat_t st;
113  int fp;
114 
115  BLI_assert(!BLI_path_is_rel(filepath));
116 
117  if (UTIL_DEBUG) {
118  printf("%s: loading %s\n", __func__, filepath);
119  }
120 
121  if (BLI_stat(filepath, &st) == -1) {
122  return -1;
123  }
124  if (((st.st_mode) & S_IFMT) != S_IFREG) {
125  return -1;
126  }
127 
128  if ((fp = BLI_open(filepath, O_BINARY | O_RDONLY, 0)) == -1) {
129  return -1;
130  }
131 
132  const ssize_t size = read(fp, buf, HEADER_SIZE);
133 
134  close(fp);
135  return size;
136 }
137 
138 int IMB_ispic_type_from_memory(const unsigned char *buf, const size_t buf_size)
139 {
141  if (type->is_a != NULL) {
142  if (type->is_a(buf, buf_size)) {
143  return type->filetype;
144  }
145  }
146  }
147 
148  return IMB_FTYPE_NONE;
149 }
150 
151 int IMB_ispic_type(const char *filepath)
152 {
153  unsigned char buf[HEADER_SIZE];
154  const ssize_t buf_size = imb_ispic_read_header_from_filepath(filepath, buf);
155  if (buf_size <= 0) {
156  return IMB_FTYPE_NONE;
157  }
158  return IMB_ispic_type_from_memory(buf, (size_t)buf_size);
159 }
160 
161 bool IMB_ispic_type_matches(const char *filepath, int filetype)
162 {
163  unsigned char buf[HEADER_SIZE];
164  const ssize_t buf_size = imb_ispic_read_header_from_filepath(filepath, buf);
165  if (buf_size <= 0) {
166  return false;
167  }
168 
169  const ImFileType *type = IMB_file_type_from_ftype(filetype);
170  if (type != NULL) {
171  /* Requesting to load a type that can't check its own header doesn't make sense.
172  * Keep the check for developers. */
173  BLI_assert(type->is_a != NULL);
174  if (type->is_a != NULL) {
175  return type->is_a(buf, (size_t)buf_size);
176  }
177  }
178  return false;
179 }
180 
181 #undef HEADER_SIZE
182 
183 bool IMB_ispic(const char *filepath)
184 {
185  return (IMB_ispic_type(filepath) != IMB_FTYPE_NONE);
186 }
187 
188 static bool isavi(const char *filepath)
189 {
190 #ifdef WITH_AVI
191  return AVI_is_avi(filepath);
192 #else
193  (void)filepath;
194  return false;
195 #endif
196 }
197 
198 #ifdef WITH_FFMPEG
199 
200 /* BLI_vsnprintf in ffmpeg_log_callback() causes invalid warning */
201 # ifdef __GNUC__
202 # pragma GCC diagnostic push
203 # pragma GCC diagnostic ignored "-Wmissing-format-attribute"
204 # endif
205 
206 static char ffmpeg_last_error[1024];
207 
208 static void ffmpeg_log_callback(void *ptr, int level, const char *format, va_list arg)
209 {
210  if (ELEM(level, AV_LOG_FATAL, AV_LOG_ERROR)) {
211  size_t n;
212  va_list args_cpy;
213 
214  va_copy(args_cpy, arg);
215  n = BLI_vsnprintf(ffmpeg_last_error, sizeof(ffmpeg_last_error), format, args_cpy);
216  va_end(args_cpy);
217 
218  /* strip trailing \n */
219  ffmpeg_last_error[n - 1] = '\0';
220  }
221 
222  if (G.debug & G_DEBUG_FFMPEG) {
223  /* call default logger to print all message to console */
224  av_log_default_callback(ptr, level, format, arg);
225  }
226 }
227 
228 # ifdef __GNUC__
229 # pragma GCC diagnostic pop
230 # endif
231 
232 void IMB_ffmpeg_init(void)
233 {
234  avdevice_register_all();
235 
236  ffmpeg_last_error[0] = '\0';
237 
238  if (G.debug & G_DEBUG_FFMPEG) {
239  av_log_set_level(AV_LOG_DEBUG);
240  }
241 
242  /* set own callback which could store last error to report to UI */
243  av_log_set_callback(ffmpeg_log_callback);
244 }
245 
246 const char *IMB_ffmpeg_last_error(void)
247 {
248  return ffmpeg_last_error;
249 }
250 
251 static int isffmpeg(const char *filepath)
252 {
253  AVFormatContext *pFormatCtx = NULL;
254  unsigned int i;
255  int videoStream;
256  const AVCodec *pCodec;
257 
258  if (BLI_path_extension_check_n(filepath,
259  ".swf",
260  ".jpg",
261  ".jp2",
262  ".j2c",
263  ".png",
264  ".dds",
265  ".tga",
266  ".bmp",
267  ".tif",
268  ".exr",
269  ".cin",
270  ".wav",
271  NULL)) {
272  return 0;
273  }
274 
275  if (avformat_open_input(&pFormatCtx, filepath, NULL, NULL) != 0) {
276  if (UTIL_DEBUG) {
277  fprintf(stderr, "isffmpeg: av_open_input_file failed\n");
278  }
279  return 0;
280  }
281 
282  if (avformat_find_stream_info(pFormatCtx, NULL) < 0) {
283  if (UTIL_DEBUG) {
284  fprintf(stderr, "isffmpeg: avformat_find_stream_info failed\n");
285  }
286  avformat_close_input(&pFormatCtx);
287  return 0;
288  }
289 
290  if (UTIL_DEBUG) {
291  av_dump_format(pFormatCtx, 0, filepath, 0);
292  }
293 
294  /* Find the first video stream */
295  videoStream = -1;
296  for (i = 0; i < pFormatCtx->nb_streams; i++) {
297  if (pFormatCtx->streams[i] && pFormatCtx->streams[i]->codecpar &&
298  (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)) {
299  videoStream = i;
300  break;
301  }
302  }
303 
304  if (videoStream == -1) {
305  avformat_close_input(&pFormatCtx);
306  return 0;
307  }
308 
309  AVCodecParameters *codec_par = pFormatCtx->streams[videoStream]->codecpar;
310 
311  /* Find the decoder for the video stream */
312  pCodec = avcodec_find_decoder(codec_par->codec_id);
313  if (pCodec == NULL) {
314  avformat_close_input(&pFormatCtx);
315  return 0;
316  }
317 
318  avformat_close_input(&pFormatCtx);
319 
320  return 1;
321 }
322 #endif
323 
324 int imb_get_anim_type(const char *filepath)
325 {
326  BLI_stat_t st;
327 
328  BLI_assert(!BLI_path_is_rel(filepath));
329 
330  if (UTIL_DEBUG) {
331  printf("%s: %s\n", __func__, filepath);
332  }
333 
334 #ifndef _WIN32
335 # ifdef WITH_FFMPEG
336  /* stat test below fails on large files > 4GB */
337  if (isffmpeg(filepath)) {
338  return ANIM_FFMPEG;
339  }
340 # endif
341  if (BLI_stat(filepath, &st) == -1) {
342  return 0;
343  }
344  if (((st.st_mode) & S_IFMT) != S_IFREG) {
345  return 0;
346  }
347 
348  if (isavi(filepath)) {
349  return ANIM_AVI;
350  }
351 
352  if (ismovie(filepath)) {
353  return ANIM_MOVIE;
354  }
355 #else /* !_WIN32 */
356  if (BLI_stat(filepath, &st) == -1) {
357  return 0;
358  }
359  if (((st.st_mode) & S_IFMT) != S_IFREG) {
360  return 0;
361  }
362 
363  if (ismovie(filepath)) {
364  return ANIM_MOVIE;
365  }
366 # ifdef WITH_FFMPEG
367  if (isffmpeg(filepath)) {
368  return ANIM_FFMPEG;
369  }
370 # endif
371 
372  if (isavi(filepath)) {
373  return ANIM_AVI;
374  }
375 #endif /* !_WIN32 */
376 
377  /* Assume a single image is part of an image sequence. */
378  if (IMB_ispic(filepath)) {
379  return ANIM_SEQUENCE;
380  }
381 
382  return ANIM_NONE;
383 }
384 
385 bool IMB_isanim(const char *filepath)
386 {
387  int type;
388 
389  type = imb_get_anim_type(filepath);
390 
391  return (type && type != ANIM_SEQUENCE);
392 }
bool AVI_is_avi(const char *name)
Definition: avi.c:187
@ G_DEBUG_FFMPEG
Definition: BKE_global.h:175
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define va_copy(a, b)
Definition: BLI_dynstr.c:29
File and directory operations.
#define O_BINARY
Definition: BLI_fileops.h:319
int BLI_stat(const char *path, BLI_stat_t *buffer) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
struct stat BLI_stat_t
Definition: BLI_fileops.h:73
int BLI_open(const char *filepath, int oflag, int pmode) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: fileops.c:920
bool BLI_path_is_rel(const char *path) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT
Definition: path_util.c:347
bool BLI_path_extension_check_n(const char *str,...) ATTR_NONNULL(1) ATTR_SENTINEL(0)
Definition: path_util.c:1304
size_t BLI_vsnprintf(char *__restrict buffer, size_t maxncpy, const char *__restrict format, va_list arg) ATTR_PRINTF_FORMAT(3
#define ELEM(...)
Compatibility-like things for windows.
SSIZE_T ssize_t
Definition: BLI_winstuff.h:71
_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 type
#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
void IMB_ffmpeg_init(void)
const char * IMB_ffmpeg_last_error(void)
int ismovie(const char *filepath)
Contains defines and structs used throughout the imbuf module.
#define IMB_FTYPE_NONE
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
SyclQueue void void size_t num_bytes void
const ImFileType * IMB_file_type_from_ftype(int ftype)
Definition: filetype.c:233
const ImFileType IMB_FILE_TYPES[]
Definition: filetype.c:29
const ImFileType * IMB_FILE_TYPES_LAST
Definition: filetype.c:231
format
Definition: logImageCore.h:38
#define G(x, y, z)
static const pxr::TfToken st("st", pxr::TfToken::Immortal)
const char * imb_ext_image_filepath_only[]
Definition: util.c:72
#define HEADER_SIZE
Definition: util.c:107
static bool isavi(const char *filepath)
Definition: util.c:188
int IMB_ispic_type_from_memory(const unsigned char *buf, const size_t buf_size)
Definition: util.c:138
const char * imb_ext_movie[]
Definition: util.c:81
int IMB_ispic_type(const char *filepath)
Definition: util.c:151
const char * imb_ext_audio[]
Definition: util.c:88
#define UTIL_DEBUG
Definition: util.c:41
bool IMB_isanim(const char *filepath)
Definition: util.c:385
static ssize_t imb_ispic_read_header_from_filepath(const char *filepath, unsigned char buf[HEADER_SIZE])
Definition: util.c:109
bool IMB_ispic_type_matches(const char *filepath, int filetype)
Definition: util.c:161
int imb_get_anim_type(const char *filepath)
Definition: util.c:324
bool IMB_ispic(const char *filepath)
Definition: util.c:183
const char * imb_ext_image[]
Definition: util.c:43
PointerRNA * ptr
Definition: wm_files.c:3480