2 * ***** BEGIN GPL LICENSE BLOCK *****
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.
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.
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.
18 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19 * All rights reserved.
21 * The Original Code is: all of this file.
23 * Contributor(s): none yet.
25 * ***** END GPL LICENSE BLOCK *****
30 /** \file blender/imbuf/intern/util.c
44 #include "BLI_path_util.h"
45 #include "BLI_fileops.h"
46 #include "BLI_utildefines.h"
47 #include "BLI_string.h"
49 #include "DNA_userdef_types.h"
50 #include "BKE_global.h"
53 #include "IMB_imbuf_types.h"
54 #include "IMB_imbuf.h"
55 #include "IMB_filetype.h"
60 #include "quicktime_import.h"
64 #include <libavcodec/avcodec.h>
65 #include <libavformat/avformat.h>
66 #include <libavdevice/avdevice.h>
67 #include <libavutil/log.h>
69 #include "ffmpeg_compat.h"
75 const char *imb_ext_image[] = {
80 ".sgi", ".rgb", ".rgba",
82 ".tif", ".tiff", ".tx",
104 const char *imb_ext_image_qt[] = {
113 const char *imb_ext_movie[] = {
141 /* sort of wrong being here... */
142 const char *imb_ext_audio[] = {
159 static int IMB_ispic_name(const char *name)
165 if (UTIL_DEBUG) printf("IMB_ispic_name: loading %s\n", name);
167 if (stat(name, &st) == -1)
169 if (((st.st_mode) & S_IFMT) != S_IFREG)
172 if ((fp = BLI_open(name, O_BINARY | O_RDONLY, 0)) < 0)
175 if (read(fp, buf, 32) != 32) {
182 /* XXX move this exception */
183 if ((BIG_LONG(buf[0]) & 0xfffffff0) == 0xffd8ffe0)
186 for (type = IMB_FILE_TYPES; type->is_a; type++)
187 if (type->is_a((uchar *)buf))
188 return type->filetype;
193 int IMB_ispic(const char *filename)
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)))
199 return IMB_ispic_name(filename);
205 else { /* no FILTERFILEEXTS */
206 return IMB_ispic_name(filename);
212 static int isavi(const char *name)
215 return AVI_is_avi(name);
222 #ifdef WITH_QUICKTIME
223 static int isqtime(const char *name)
225 return anim_is_quicktime(name);
232 #define va_copy(dst, src) ((dst) = (src))
235 /* BLI_vsnprintf in ffmpeg_log_callback() causes invalid warning */
237 # pragma GCC diagnostic push
238 # pragma GCC diagnostic ignored "-Wmissing-format-attribute"
241 static char ffmpeg_last_error[1024];
243 static void ffmpeg_log_callback(void *ptr, int level, const char *format, va_list arg)
245 if (ELEM(level, AV_LOG_FATAL, AV_LOG_ERROR)) {
251 n = BLI_vsnprintf(ffmpeg_last_error, sizeof(ffmpeg_last_error), format, arg2);
253 /* strip trailing \n */
254 ffmpeg_last_error[n - 1] = '\0';
257 if (G.debug & G_DEBUG_FFMPEG) {
258 /* call default logger to print all message to console */
259 av_log_default_callback(ptr, level, format, arg);
264 # pragma GCC diagnostic pop
267 void IMB_ffmpeg_init(void)
270 avdevice_register_all();
272 ffmpeg_last_error[0] = '\0';
274 /* set own callback which could store last error to report to UI */
275 av_log_set_callback(ffmpeg_log_callback);
278 const char *IMB_ffmpeg_last_error(void)
280 return ffmpeg_last_error;
283 static int isffmpeg(const char *filename)
285 AVFormatContext *pFormatCtx = NULL;
289 AVCodecContext *pCodecCtx;
291 if (BLI_testextensie(filename, ".swf") ||
292 BLI_testextensie(filename, ".jpg") ||
293 BLI_testextensie(filename, ".png") ||
294 BLI_testextensie(filename, ".dds") ||
295 BLI_testextensie(filename, ".tga") ||
296 BLI_testextensie(filename, ".bmp") ||
297 BLI_testextensie(filename, ".exr") ||
298 BLI_testextensie(filename, ".cin") ||
299 BLI_testextensie(filename, ".wav"))
304 if (avformat_open_input(&pFormatCtx, filename, NULL, NULL) != 0) {
305 if (UTIL_DEBUG) fprintf(stderr, "isffmpeg: av_open_input_file failed\n");
309 if (av_find_stream_info(pFormatCtx) < 0) {
310 if (UTIL_DEBUG) fprintf(stderr, "isffmpeg: av_find_stream_info failed\n");
311 av_close_input_file(pFormatCtx);
315 if (UTIL_DEBUG) av_dump_format(pFormatCtx, 0, filename, 0);
318 /* Find the first video stream */
320 for (i = 0; i < pFormatCtx->nb_streams; i++)
321 if (pFormatCtx->streams[i] &&
322 pFormatCtx->streams[i]->codec &&
323 (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO))
329 if (videoStream == -1) {
330 av_close_input_file(pFormatCtx);
334 pCodecCtx = pFormatCtx->streams[videoStream]->codec;
336 /* Find the decoder for the video stream */
337 pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
338 if (pCodec == NULL) {
339 av_close_input_file(pFormatCtx);
343 if (avcodec_open(pCodecCtx, pCodec) < 0) {
344 av_close_input_file(pFormatCtx);
348 avcodec_close(pCodecCtx);
349 av_close_input_file(pFormatCtx);
356 static int isredcode(const char *filename)
358 struct redcode_handle *h = redcode_open(filename);
368 int imb_get_anim_type(const char *name)
373 if (UTIL_DEBUG) printf("in getanimtype: %s\n", name);
376 # ifdef WITH_QUICKTIME
377 if (isqtime(name)) return (ANIM_QTIME);
380 /* stat test below fails on large files > 4GB */
381 if (isffmpeg(name)) return (ANIM_FFMPEG);
383 if (BLI_stat(name, &st) == -1) return(0);
384 if (((st.st_mode) & S_IFMT) != S_IFREG) return(0);
386 if (isavi(name)) return (ANIM_AVI);
388 if (ismovie(name)) return (ANIM_MOVIE);
390 if (BLI_stat(name, &st) == -1) return(0);
391 if (((st.st_mode) & S_IFMT) != S_IFREG) return(0);
393 if (ismovie(name)) return (ANIM_MOVIE);
394 # ifdef WITH_QUICKTIME
395 if (isqtime(name)) return (ANIM_QTIME);
398 if (isffmpeg(name)) return (ANIM_FFMPEG);
402 if (isavi(name)) return (ANIM_AVI);
405 if (isredcode(name)) return (ANIM_REDCODE);
407 type = IMB_ispic(name);
409 return ANIM_SEQUENCE;
415 int IMB_isanim(const char *filename)
419 if (U.uiflag & USER_FILTERFILEEXTS) {
420 if (G.have_quicktime) {
421 if (BLI_testextensie(filename, ".avi") ||
422 BLI_testextensie(filename, ".flc") ||
423 BLI_testextensie(filename, ".dv") ||
424 BLI_testextensie(filename, ".r3d") ||
425 BLI_testextensie(filename, ".mov") ||
426 BLI_testextensie(filename, ".movie") ||
427 BLI_testextensie(filename, ".mv"))
429 type = imb_get_anim_type(filename);
435 else { /* no quicktime */
436 if (BLI_testextensie(filename, ".avi") ||
437 BLI_testextensie(filename, ".dv") ||
438 BLI_testextensie(filename, ".r3d") ||
439 BLI_testextensie(filename, ".mv"))
441 type = imb_get_anim_type(filename);
448 else { /* no FILTERFILEEXTS */
449 type = imb_get_anim_type(filename);
452 return (type && type != ANIM_SEQUENCE);