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