dc5cdf49783988a6c7f11e1934cce0fe84fbb705
[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_path_util.h"
45 #include "BLI_fileops.h"
46 #include "BLI_utildefines.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         NULL
102 };
103
104 const char *imb_ext_image_qt[] = {
105         ".gif",
106         ".psd",
107         ".pct", ".pict",
108         ".pntg",
109         ".qtif",
110         NULL
111 };
112
113 const char *imb_ext_movie[] = {
114         ".avi",
115         ".flc",
116         ".mov",
117         ".movie",
118         ".mp4",
119         ".m4v",
120         ".m2v",
121         ".m2t",
122         ".m2ts",
123         ".mts",
124         ".mv",
125         ".avs",
126         ".wmv",
127         ".ogv",
128         ".dv",
129         ".mpeg",
130         ".mpg",
131         ".mpg2",
132         ".vob",
133         ".mkv",
134         ".flv",
135         ".divx",
136         ".xvid",
137         ".mxf",
138         NULL
139 };
140
141 /* sort of wrong being here... */
142 const char *imb_ext_audio[] = {
143         ".wav",
144         ".ogg",
145         ".oga",
146         ".mp3",
147         ".mp2",
148         ".ac3",
149         ".aac",
150         ".flac",
151         ".wma",
152         ".eac3",
153         ".aif",
154         ".aiff",
155         ".m4a",
156         NULL
157 };
158
159 static int IMB_ispic_name(const char *name)
160 {
161         ImFileType *type;
162         struct stat st;
163         int fp, buf[10];
164
165         if (UTIL_DEBUG) printf("IMB_ispic_name: loading %s\n", name);
166         
167         if (stat(name, &st) == -1)
168                 return FALSE;
169         if (((st.st_mode) & S_IFMT) != S_IFREG)
170                 return FALSE;
171
172         if ((fp = BLI_open(name, O_BINARY | O_RDONLY, 0)) < 0)
173                 return FALSE;
174
175         if (read(fp, buf, 32) != 32) {
176                 close(fp);
177                 return FALSE;
178         }
179
180         close(fp);
181
182         /* XXX move this exception */
183         if ((BIG_LONG(buf[0]) & 0xfffffff0) == 0xffd8ffe0)
184                 return JPG;
185
186         for (type = IMB_FILE_TYPES; type->is_a; type++)
187                 if (type->is_a((uchar *)buf))
188                         return type->filetype;
189
190         return FALSE;
191 }
192
193 int IMB_ispic(const char *filename)
194 {
195         if (U.uiflag & USER_FILTERFILEEXTS) {
196                 if ((BLI_testextensie_array(filename, imb_ext_image)) ||
197                     (G.have_quicktime && BLI_testextensie_array(filename, imb_ext_image_qt)))
198                 {
199                         return IMB_ispic_name(filename);
200                 }
201                 else {
202                         return FALSE;
203                 }
204         }
205         else { /* no FILTERFILEEXTS */
206                 return IMB_ispic_name(filename);
207         }
208 }
209
210
211
212 static int isavi(const char *name)
213 {
214 #ifdef WITH_AVI
215         return AVI_is_avi(name);
216 #else
217         (void)name;
218         return FALSE;
219 #endif
220 }
221
222 #ifdef WITH_QUICKTIME
223 static int isqtime(const char *name)
224 {
225         return anim_is_quicktime(name);
226 }
227 #endif
228
229 #ifdef WITH_FFMPEG
230
231 #ifdef _MSC_VER
232 #define va_copy(dst, src) ((dst) = (src))
233 #endif
234
235 /* BLI_vsnprintf in ffmpeg_log_callback() causes invalid warning */
236 #pragma GCC diagnostic push
237 #pragma GCC diagnostic ignored "-Wmissing-format-attribute"
238
239 static char ffmpeg_last_error[1024];
240
241 static void ffmpeg_log_callback(void *ptr, int level, const char *format, va_list arg)
242 {
243         if (ELEM(level, AV_LOG_FATAL, AV_LOG_ERROR)) {
244                 size_t n;
245                 va_list arg2;
246
247                 va_copy(arg2, arg);
248
249                 n = BLI_vsnprintf(ffmpeg_last_error, sizeof(ffmpeg_last_error), format, arg2);
250
251                 /* strip trailing \n */
252                 ffmpeg_last_error[n - 1] = '\0';
253         }
254
255         if (G.debug & G_DEBUG_FFMPEG) {
256                 /* call default logger to print all message to console */
257                 av_log_default_callback(ptr, level, format, arg);
258         }
259 }
260
261 #pragma GCC diagnostic pop
262
263 void IMB_ffmpeg_init(void)
264 {
265         av_register_all();
266         avdevice_register_all();
267
268         ffmpeg_last_error[0] = '\0';
269
270         /* set own callback which could store last error to report to UI */
271         av_log_set_callback(ffmpeg_log_callback);
272 }
273
274 const char *IMB_ffmpeg_last_error(void)
275 {
276         return ffmpeg_last_error;
277 }
278
279 static int isffmpeg(const char *filename)
280 {
281         AVFormatContext *pFormatCtx = NULL;
282         unsigned int i;
283         int videoStream;
284         AVCodec *pCodec;
285         AVCodecContext *pCodecCtx;
286
287         if (BLI_testextensie(filename, ".swf") ||
288             BLI_testextensie(filename, ".jpg") ||
289             BLI_testextensie(filename, ".png") ||
290             BLI_testextensie(filename, ".dds") ||
291             BLI_testextensie(filename, ".tga") ||
292             BLI_testextensie(filename, ".bmp") ||
293             BLI_testextensie(filename, ".exr") ||
294             BLI_testextensie(filename, ".cin") ||
295             BLI_testextensie(filename, ".wav"))
296         {
297                 return 0;
298         }
299
300         if (avformat_open_input(&pFormatCtx, filename, NULL, NULL) != 0) {
301                 if (UTIL_DEBUG) fprintf(stderr, "isffmpeg: av_open_input_file failed\n");
302                 return 0;
303         }
304
305         if (av_find_stream_info(pFormatCtx) < 0) {
306                 if (UTIL_DEBUG) fprintf(stderr, "isffmpeg: av_find_stream_info failed\n");
307                 av_close_input_file(pFormatCtx);
308                 return 0;
309         }
310
311         if (UTIL_DEBUG) av_dump_format(pFormatCtx, 0, filename, 0);
312
313
314         /* Find the first video stream */
315         videoStream = -1;
316         for (i = 0; i < pFormatCtx->nb_streams; i++)
317                 if (pFormatCtx->streams[i] &&
318                     pFormatCtx->streams[i]->codec &&
319                     (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO))
320                 {
321                         videoStream = i;
322                         break;
323                 }
324
325         if (videoStream == -1) {
326                 av_close_input_file(pFormatCtx);
327                 return 0;
328         }
329
330         pCodecCtx = pFormatCtx->streams[videoStream]->codec;
331
332         /* Find the decoder for the video stream */
333         pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
334         if (pCodec == NULL) {
335                 av_close_input_file(pFormatCtx);
336                 return 0;
337         }
338
339         if (avcodec_open(pCodecCtx, pCodec) < 0) {
340                 av_close_input_file(pFormatCtx);
341                 return 0;
342         }
343
344         avcodec_close(pCodecCtx);
345         av_close_input_file(pFormatCtx);
346
347         return 1;
348 }
349 #endif
350
351 #ifdef WITH_REDCODE
352 static int isredcode(const char *filename)
353 {
354         struct redcode_handle *h = redcode_open(filename);
355         if (!h) {
356                 return 0;
357         }
358         redcode_close(h);
359         return 1;
360 }
361
362 #endif
363
364 int imb_get_anim_type(const char *name)
365 {
366         int type;
367         struct stat st;
368
369         if (UTIL_DEBUG) printf("in getanimtype: %s\n", name);
370
371 #ifndef _WIN32
372 #   ifdef WITH_QUICKTIME
373         if (isqtime(name)) return (ANIM_QTIME);
374 #   endif
375 #   ifdef WITH_FFMPEG
376         /* stat test below fails on large files > 4GB */
377         if (isffmpeg(name)) return (ANIM_FFMPEG);
378 #   endif
379         if (BLI_stat(name, &st) == -1) return(0);
380         if (((st.st_mode) & S_IFMT) != S_IFREG) return(0);
381
382         if (isavi(name)) return (ANIM_AVI);
383
384         if (ismovie(name)) return (ANIM_MOVIE);
385 #else
386         if (BLI_stat(name, &st) == -1) return(0);
387         if (((st.st_mode) & S_IFMT) != S_IFREG) return(0);
388
389         if (ismovie(name)) return (ANIM_MOVIE);
390 #   ifdef WITH_QUICKTIME
391         if (isqtime(name)) return (ANIM_QTIME);
392 #   endif
393 #   ifdef WITH_FFMPEG
394         if (isffmpeg(name)) return (ANIM_FFMPEG);
395 #   endif
396
397
398         if (isavi(name)) return (ANIM_AVI);
399 #endif
400 #ifdef WITH_REDCODE
401         if (isredcode(name)) return (ANIM_REDCODE);
402 #endif
403         type = IMB_ispic(name);
404         if (type) {
405                 return ANIM_SEQUENCE;
406         }
407
408         return ANIM_NONE;
409 }
410  
411 int IMB_isanim(const char *filename)
412 {
413         int type;
414         
415         if (U.uiflag & USER_FILTERFILEEXTS) {
416                 if (G.have_quicktime) {
417                         if (BLI_testextensie(filename, ".avi")   ||
418                             BLI_testextensie(filename, ".flc")   ||
419                             BLI_testextensie(filename, ".dv")    ||
420                             BLI_testextensie(filename, ".r3d")   ||
421                             BLI_testextensie(filename, ".mov")   ||
422                             BLI_testextensie(filename, ".movie") ||
423                             BLI_testextensie(filename, ".mv"))
424                         {
425                                 type = imb_get_anim_type(filename);
426                         }
427                         else {
428                                 return(FALSE);
429                         }
430                 }
431                 else { /* no quicktime */
432                         if (BLI_testextensie(filename, ".avi") ||
433                             BLI_testextensie(filename, ".dv")  ||
434                             BLI_testextensie(filename, ".r3d") ||
435                             BLI_testextensie(filename, ".mv"))
436                         {
437                                 type = imb_get_anim_type(filename);
438                         }
439                         else {
440                                 return(FALSE);
441                         }
442                 }
443         }
444         else { /* no FILTERFILEEXTS */
445                 type = imb_get_anim_type(filename);
446         }
447         
448         return (type && type != ANIM_SEQUENCE);
449 }