quiet invalid warning in ffmpeg_log_callback with -Wmissing-format-attribute.
[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         return AVI_is_avi(name);
215 }
216
217 #ifdef WITH_QUICKTIME
218 static int isqtime(const char *name)
219 {
220         return anim_is_quicktime(name);
221 }
222 #endif
223
224 #ifdef WITH_FFMPEG
225
226 /* BLI_vsnprintf in ffmpeg_log_callback() causes invalid warning */
227 #pragma GCC diagnostic push
228 #pragma GCC diagnostic ignored "-Wmissing-format-attribute"
229
230 static char ffmpeg_last_error[1024];
231
232 static void ffmpeg_log_callback(void *ptr, int level, const char *format, va_list arg)
233 {
234         if (ELEM(level, AV_LOG_FATAL, AV_LOG_ERROR)) {
235                 size_t n = BLI_vsnprintf(ffmpeg_last_error, sizeof(ffmpeg_last_error), format, arg);
236
237                 /* strip trailing \n */
238                 ffmpeg_last_error[n - 1] = '\0';
239         }
240
241         if (G.debug & G_DEBUG_FFMPEG) {
242                 /* call default logger to print all message to console */
243                 av_log_default_callback(ptr, level, format, arg);
244         }
245 }
246
247 #pragma GCC diagnostic pop
248
249 void IMB_ffmpeg_init(void)
250 {
251         av_register_all();
252         avdevice_register_all();
253
254         ffmpeg_last_error[0] = '\0';
255
256         /* set own callback which could store last error to report to UI */
257         av_log_set_callback(ffmpeg_log_callback);
258 }
259
260 const char *IMB_ffmpeg_last_error(void)
261 {
262         return ffmpeg_last_error;
263 }
264
265 static int isffmpeg(const char *filename)
266 {
267         AVFormatContext *pFormatCtx = NULL;
268         unsigned int i;
269         int videoStream;
270         AVCodec *pCodec;
271         AVCodecContext *pCodecCtx;
272
273         if (BLI_testextensie(filename, ".swf") ||
274             BLI_testextensie(filename, ".jpg") ||
275             BLI_testextensie(filename, ".png") ||
276             BLI_testextensie(filename, ".dds") ||
277             BLI_testextensie(filename, ".tga") ||
278             BLI_testextensie(filename, ".bmp") ||
279             BLI_testextensie(filename, ".exr") ||
280             BLI_testextensie(filename, ".cin") ||
281             BLI_testextensie(filename, ".wav"))
282         {
283                 return 0;
284         }
285
286         if (avformat_open_input(&pFormatCtx, filename, NULL, NULL) != 0) {
287                 if (UTIL_DEBUG) fprintf(stderr, "isffmpeg: av_open_input_file failed\n");
288                 return 0;
289         }
290
291         if (av_find_stream_info(pFormatCtx) < 0) {
292                 if (UTIL_DEBUG) fprintf(stderr, "isffmpeg: av_find_stream_info failed\n");
293                 av_close_input_file(pFormatCtx);
294                 return 0;
295         }
296
297         if (UTIL_DEBUG) av_dump_format(pFormatCtx, 0, filename, 0);
298
299
300         /* Find the first video stream */
301         videoStream = -1;
302         for (i = 0; i < pFormatCtx->nb_streams; i++)
303                 if (pFormatCtx->streams[i] &&
304                     pFormatCtx->streams[i]->codec &&
305                     (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO))
306                 {
307                         videoStream = i;
308                         break;
309                 }
310
311         if (videoStream == -1) {
312                 av_close_input_file(pFormatCtx);
313                 return 0;
314         }
315
316         pCodecCtx = pFormatCtx->streams[videoStream]->codec;
317
318         /* Find the decoder for the video stream */
319         pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
320         if (pCodec == NULL) {
321                 av_close_input_file(pFormatCtx);
322                 return 0;
323         }
324
325         if (avcodec_open(pCodecCtx, pCodec) < 0) {
326                 av_close_input_file(pFormatCtx);
327                 return 0;
328         }
329
330         avcodec_close(pCodecCtx);
331         av_close_input_file(pFormatCtx);
332
333         return 1;
334 }
335 #endif
336
337 #ifdef WITH_REDCODE
338 static int isredcode(const char *filename)
339 {
340         struct redcode_handle *h = redcode_open(filename);
341         if (!h) {
342                 return 0;
343         }
344         redcode_close(h);
345         return 1;
346 }
347
348 #endif
349
350 int imb_get_anim_type(const char *name)
351 {
352         int type;
353         struct stat st;
354
355         if (UTIL_DEBUG) printf("in getanimtype: %s\n", name);
356
357 #ifndef _WIN32
358 #   ifdef WITH_QUICKTIME
359         if (isqtime(name)) return (ANIM_QTIME);
360 #   endif
361 #   ifdef WITH_FFMPEG
362         /* stat test below fails on large files > 4GB */
363         if (isffmpeg(name)) return (ANIM_FFMPEG);
364 #   endif
365         if (BLI_stat(name, &st) == -1) return(0);
366         if (((st.st_mode) & S_IFMT) != S_IFREG) return(0);
367
368         if (isavi(name)) return (ANIM_AVI);
369
370         if (ismovie(name)) return (ANIM_MOVIE);
371 #else
372         if (BLI_stat(name, &st) == -1) return(0);
373         if (((st.st_mode) & S_IFMT) != S_IFREG) return(0);
374
375         if (ismovie(name)) return (ANIM_MOVIE);
376 #   ifdef WITH_QUICKTIME
377         if (isqtime(name)) return (ANIM_QTIME);
378 #   endif
379 #   ifdef WITH_FFMPEG
380         if (isffmpeg(name)) return (ANIM_FFMPEG);
381 #   endif
382
383
384         if (isavi(name)) return (ANIM_AVI);
385 #endif
386 #ifdef WITH_REDCODE
387         if (isredcode(name)) return (ANIM_REDCODE);
388 #endif
389         type = IMB_ispic(name);
390         if (type) {
391                 return ANIM_SEQUENCE;
392         }
393
394         return ANIM_NONE;
395 }
396  
397 int IMB_isanim(const char *filename)
398 {
399         int type;
400         
401         if (U.uiflag & USER_FILTERFILEEXTS) {
402                 if (G.have_quicktime) {
403                         if (BLI_testextensie(filename, ".avi")   ||
404                             BLI_testextensie(filename, ".flc")   ||
405                             BLI_testextensie(filename, ".dv")    ||
406                             BLI_testextensie(filename, ".r3d")   ||
407                             BLI_testextensie(filename, ".mov")   ||
408                             BLI_testextensie(filename, ".movie") ||
409                             BLI_testextensie(filename, ".mv"))
410                         {
411                                 type = imb_get_anim_type(filename);
412                         }
413                         else {
414                                 return(FALSE);                  
415                         }
416                 }
417                 else { /* no quicktime */
418                         if (BLI_testextensie(filename, ".avi") ||
419                             BLI_testextensie(filename, ".dv")  ||
420                             BLI_testextensie(filename, ".r3d") ||
421                             BLI_testextensie(filename, ".mv"))
422                         {
423                                 type = imb_get_anim_type(filename);
424                         }
425                         else {
426                                 return(FALSE);
427                         }
428                 }
429         }
430         else { /* no FILTERFILEEXTS */
431                 type = imb_get_anim_type(filename);
432         }
433         
434         return (type && type != ANIM_SEQUENCE);
435 }