Code cleanup: use bools where possible
[blender.git] / source / blender / imbuf / intern / util.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): none yet.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  * util.c
27  *
28  */
29
30 /** \file blender/imbuf/intern/util.c
31  *  \ingroup imbuf
32  */
33
34
35 #ifdef _WIN32
36 #  include <io.h>
37 #  define open _open
38 #  define read _read
39 #  define close _close
40 #endif
41
42 #include <stdlib.h>
43
44 #include "BLI_utildefines.h"
45 #include "BLI_path_util.h"
46 #include "BLI_fileops.h"
47 #include "BLI_string.h"
48
49 #include "DNA_userdef_types.h"
50 #include "BKE_global.h"
51
52 #include "imbuf.h"
53 #include "IMB_imbuf_types.h"
54 #include "IMB_imbuf.h"
55 #include "IMB_filetype.h"
56
57 #include "IMB_anim.h"
58
59 #ifdef WITH_QUICKTIME
60 #include "quicktime_import.h"
61 #endif
62
63 #ifdef WITH_FFMPEG
64 #include <libavcodec/avcodec.h>
65 #include <libavformat/avformat.h>
66 #include <libavdevice/avdevice.h>
67 #include <libavutil/log.h>
68
69 #include "ffmpeg_compat.h"
70
71 #endif
72
73 #define UTIL_DEBUG 0
74
75 const char *imb_ext_image[] = {
76         ".png",
77         ".tga",
78         ".bmp",
79         ".jpg", ".jpeg",
80         ".sgi", ".rgb", ".rgba",
81 #ifdef WITH_TIFF
82         ".tif", ".tiff", ".tx",
83 #endif
84 #ifdef WITH_OPENJPEG
85         ".jp2",
86         ".j2c",
87 #endif
88 #ifdef WITH_HDR
89         ".hdr",
90 #endif
91 #ifdef WITH_DDS
92         ".dds",
93 #endif
94 #ifdef WITH_CINEON
95         ".dpx",
96         ".cin",
97 #endif
98 #ifdef WITH_OPENEXR
99         ".exr",
100 #endif
101 #ifdef WITH_OPENIMAGEIO
102         ".psd", ".pdd", ".psb",
103 #endif
104         NULL
105 };
106
107 const char *imb_ext_image_filepath_only[] = {
108 #ifdef WITH_OPENIMAGEIO
109         ".psd", ".pdd", ".psb",
110 #endif
111         NULL
112 };
113
114 const char *imb_ext_image_qt[] = {
115         ".gif",
116         ".psd",
117         ".pct", ".pict",
118         ".pntg",
119         ".qtif",
120         NULL
121 };
122
123 const char *imb_ext_movie_qt[] = {
124         ".avi",   
125         ".flc",   
126         ".dv",    
127         ".r3d",   
128         ".mov",   
129         ".movie", 
130         ".mv",
131         NULL
132 };
133
134 const char *imb_ext_movie[] = {
135         ".avi",
136         ".flc",
137         ".mov",
138         ".movie",
139         ".mp4",
140         ".m4v",
141         ".m2v",
142         ".m2t",
143         ".m2ts",
144         ".mts",
145         ".ts",
146         ".mv",
147         ".avs",
148         ".wmv",
149         ".ogv",
150         ".ogg",
151         ".r3d",
152         ".dv",
153         ".mpeg",
154         ".mpg",
155         ".mpg2",
156         ".vob",
157         ".mkv",
158         ".flv",
159         ".divx",
160         ".xvid",
161         ".mxf",
162         ".webm",
163         NULL
164 };
165
166 /* sort of wrong being here... */
167 const char *imb_ext_audio[] = {
168         ".wav",
169         ".ogg",
170         ".oga",
171         ".mp3",
172         ".mp2",
173         ".ac3",
174         ".aac",
175         ".flac",
176         ".wma",
177         ".eac3",
178         ".aif",
179         ".aiff",
180         ".m4a",
181         NULL
182 };
183
184 static int IMB_ispic_name(const char *name)
185 {
186         /* increased from 32 to 64 because of the bitmaps header size */
187 #define HEADER_SIZE 64
188
189         unsigned char buf[HEADER_SIZE];
190         ImFileType *type;
191         struct stat st;
192         int fp;
193
194         if (UTIL_DEBUG) printf("IMB_ispic_name: loading %s\n", name);
195         
196         if (BLI_stat(name, &st) == -1)
197                 return FALSE;
198         if (((st.st_mode) & S_IFMT) != S_IFREG)
199                 return FALSE;
200
201         if ((fp = BLI_open(name, O_BINARY | O_RDONLY, 0)) < 0)
202                 return FALSE;
203
204         memset(buf, 0, sizeof(buf));
205         if (read(fp, buf, HEADER_SIZE) <= 0) {
206                 close(fp);
207                 return FALSE;
208         }
209
210         close(fp);
211
212         /* XXX move this exception */
213         if ((BIG_LONG(((int *)buf)[0]) & 0xfffffff0) == 0xffd8ffe0)
214                 return JPG;
215
216         for (type = IMB_FILE_TYPES; type < IMB_FILE_TYPES_LAST; type++) {
217                 if (type->is_a) {
218                         if (type->is_a(buf)) {
219                                 return type->filetype;
220                         }
221                 }
222                 else if (type->is_a_filepath) {
223                         if (type->is_a_filepath(name)) {
224                                 return type->filetype;
225                         }
226                 }
227         }
228
229         return FALSE;
230
231 #undef HEADER_SIZE
232 }
233
234 int IMB_ispic(const char *filename)
235 {
236         if (U.uiflag & USER_FILTERFILEEXTS) {
237                 if ((BLI_testextensie_array(filename, imb_ext_image)) ||
238                     (G.have_quicktime && BLI_testextensie_array(filename, imb_ext_image_qt)))
239                 {
240                         return IMB_ispic_name(filename);
241                 }
242                 else {
243                         return FALSE;
244                 }
245         }
246         else { /* no FILTERFILEEXTS */
247                 return IMB_ispic_name(filename);
248         }
249 }
250
251
252
253 static int isavi(const char *name)
254 {
255 #ifdef WITH_AVI
256         return AVI_is_avi(name);
257 #else
258         (void)name;
259         return FALSE;
260 #endif
261 }
262
263 #ifdef WITH_QUICKTIME
264 static int isqtime(const char *name)
265 {
266         return anim_is_quicktime(name);
267 }
268 #endif
269
270 #ifdef WITH_FFMPEG
271
272 #ifdef _MSC_VER
273 #define va_copy(dst, src) ((dst) = (src))
274 #endif
275
276 /* BLI_vsnprintf in ffmpeg_log_callback() causes invalid warning */
277 #ifdef __GNUC__
278 #  pragma GCC diagnostic push
279 #  pragma GCC diagnostic ignored "-Wmissing-format-attribute"
280 #endif
281
282 static char ffmpeg_last_error[1024];
283
284 static void ffmpeg_log_callback(void *ptr, int level, const char *format, va_list arg)
285 {
286         if (ELEM(level, AV_LOG_FATAL, AV_LOG_ERROR)) {
287                 size_t n;
288                 va_list args_cpy;
289
290                 va_copy(args_cpy, arg);
291                 n = BLI_vsnprintf(ffmpeg_last_error, sizeof(ffmpeg_last_error), format, args_cpy);
292                 va_end(args_cpy);
293
294                 /* strip trailing \n */
295                 ffmpeg_last_error[n - 1] = '\0';
296         }
297
298         if (G.debug & G_DEBUG_FFMPEG) {
299                 /* call default logger to print all message to console */
300                 av_log_default_callback(ptr, level, format, arg);
301         }
302 }
303
304 #ifdef __GNUC__
305 #  pragma GCC diagnostic pop
306 #endif
307
308 void IMB_ffmpeg_init(void)
309 {
310         av_register_all();
311         avdevice_register_all();
312
313         ffmpeg_last_error[0] = '\0';
314
315         if (G.debug & G_DEBUG_FFMPEG)
316                 av_log_set_level(AV_LOG_DEBUG);
317
318         /* set own callback which could store last error to report to UI */
319         av_log_set_callback(ffmpeg_log_callback);
320 }
321
322 const char *IMB_ffmpeg_last_error(void)
323 {
324         return ffmpeg_last_error;
325 }
326
327 static int isffmpeg(const char *filename)
328 {
329         AVFormatContext *pFormatCtx = NULL;
330         unsigned int i;
331         int videoStream;
332         AVCodec *pCodec;
333         AVCodecContext *pCodecCtx;
334
335         if (BLI_testextensie_n(
336                 filename,
337                 ".swf", ".jpg", ".png", ".dds", ".tga", ".bmp", ".tif", ".exr", ".cin", ".wav", NULL))
338         {
339                 return 0;
340         }
341
342         if (avformat_open_input(&pFormatCtx, filename, NULL, NULL) != 0) {
343                 if (UTIL_DEBUG) fprintf(stderr, "isffmpeg: av_open_input_file failed\n");
344                 return 0;
345         }
346
347         if (avformat_find_stream_info(pFormatCtx, NULL) < 0) {
348                 if (UTIL_DEBUG) fprintf(stderr, "isffmpeg: avformat_find_stream_info failed\n");
349                 avformat_close_input(&pFormatCtx);
350                 return 0;
351         }
352
353         if (UTIL_DEBUG) av_dump_format(pFormatCtx, 0, filename, 0);
354
355
356         /* Find the first video stream */
357         videoStream = -1;
358         for (i = 0; i < pFormatCtx->nb_streams; i++)
359                 if (pFormatCtx->streams[i] &&
360                     pFormatCtx->streams[i]->codec &&
361                     (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO))
362                 {
363                         videoStream = i;
364                         break;
365                 }
366
367         if (videoStream == -1) {
368                 avformat_close_input(&pFormatCtx);
369                 return 0;
370         }
371
372         pCodecCtx = pFormatCtx->streams[videoStream]->codec;
373
374         /* Find the decoder for the video stream */
375         pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
376         if (pCodec == NULL) {
377                 avformat_close_input(&pFormatCtx);
378                 return 0;
379         }
380
381         if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) {
382                 avformat_close_input(&pFormatCtx);
383                 return 0;
384         }
385
386         avcodec_close(pCodecCtx);
387         avformat_close_input(&pFormatCtx);
388
389         return 1;
390 }
391 #endif
392
393 #ifdef WITH_REDCODE
394 static int isredcode(const char *filename)
395 {
396         struct redcode_handle *h = redcode_open(filename);
397         if (!h) {
398                 return 0;
399         }
400         redcode_close(h);
401         return 1;
402 }
403
404 #endif
405
406 int imb_get_anim_type(const char *name)
407 {
408         int type;
409         struct stat st;
410
411         if (UTIL_DEBUG) printf("in getanimtype: %s\n", name);
412
413 #ifndef _WIN32
414 #   ifdef WITH_QUICKTIME
415         if (isqtime(name)) return (ANIM_QTIME);
416 #   endif
417 #   ifdef WITH_FFMPEG
418         /* stat test below fails on large files > 4GB */
419         if (isffmpeg(name)) return (ANIM_FFMPEG);
420 #   endif
421         if (BLI_stat(name, &st) == -1) return(0);
422         if (((st.st_mode) & S_IFMT) != S_IFREG) return(0);
423
424         if (isavi(name)) return (ANIM_AVI);
425
426         if (ismovie(name)) return (ANIM_MOVIE);
427 #else
428         if (BLI_stat(name, &st) == -1) return(0);
429         if (((st.st_mode) & S_IFMT) != S_IFREG) return(0);
430
431         if (ismovie(name)) return (ANIM_MOVIE);
432 #   ifdef WITH_QUICKTIME
433         if (isqtime(name)) return (ANIM_QTIME);
434 #   endif
435 #   ifdef WITH_FFMPEG
436         if (isffmpeg(name)) return (ANIM_FFMPEG);
437 #   endif
438
439
440         if (isavi(name)) return (ANIM_AVI);
441 #endif
442 #ifdef WITH_REDCODE
443         if (isredcode(name)) return (ANIM_REDCODE);
444 #endif
445         type = IMB_ispic(name);
446         if (type) {
447                 return ANIM_SEQUENCE;
448         }
449
450         return ANIM_NONE;
451 }
452  
453 bool IMB_isanim(const char *filename)
454 {
455         int type;
456         
457         if (U.uiflag & USER_FILTERFILEEXTS) {
458                 if (G.have_quicktime) {
459                         if (BLI_testextensie_array(filename, imb_ext_movie_qt)) {       
460                                 type = imb_get_anim_type(filename);
461                         }
462                         else {
463                                 return(FALSE);
464                         }
465                 }
466                 else { /* no quicktime */
467                         if (BLI_testextensie_array(filename, imb_ext_movie)) {
468                                 type = imb_get_anim_type(filename);
469                         }
470                         else {
471                                 return(FALSE);
472                         }
473                 }
474         }
475         else { /* no FILTERFILEEXTS */
476                 type = imb_get_anim_type(filename);
477         }
478         
479         return (type && type != ANIM_SEQUENCE);
480 }