Blender V4.3
source/blender/imbuf/intern/util.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#ifdef _WIN32
10# include <io.h>
11#endif
12
13#include <cstdlib>
14
15#include "BLI_fileops.h"
16#include "BLI_path_utils.hh"
17#include "BLI_utildefines.h"
18#ifdef _WIN32
19# include "BLI_winstuff.h"
20#endif
21
22#include "IMB_filetype.hh"
23#include "IMB_imbuf.hh"
24#include "IMB_imbuf_types.hh"
25#include "imbuf.hh"
26
27#include "IMB_anim.hh"
28
29#ifdef WITH_FFMPEG
30# include "BLI_string.h" /* BLI_vsnprintf */
31
32# include "BKE_global.hh" /* G.debug */
33
34extern "C" {
35# include <libavcodec/avcodec.h>
36# include <libavdevice/avdevice.h>
37# include <libavformat/avformat.h>
38# include <libavutil/log.h>
39
40# include "ffmpeg_compat.h" /* Keep for compatibility. */
41}
42
43#endif
44
45#define UTIL_DEBUG 0
46
47const char *imb_ext_image[] = {
48 ".png", ".tga", ".bmp", ".jpg", ".jpeg", ".sgi", ".rgb", ".rgba", ".tif", ".tiff", ".tx",
49#ifdef WITH_OPENJPEG
50 ".jp2", ".j2c",
51#endif
52 ".hdr", ".dds",
53#ifdef WITH_CINEON
54 ".dpx", ".cin",
55#endif
56#ifdef WITH_OPENEXR
57 ".exr",
58#endif
59 ".psd", ".pdd", ".psb",
60#ifdef WITH_WEBP
61 ".webp",
62#endif
63 nullptr,
64};
65
66const char *imb_ext_movie[] = {
67 ".avi", ".flc", ".mov", ".movie", ".mp4", ".m4v", ".m2v", ".m2t", ".m2ts", ".mts",
68 ".ts", ".mv", ".avs", ".wmv", ".ogv", ".ogg", ".r3d", ".dv", ".mpeg", ".mpg",
69 ".mpg2", ".vob", ".mkv", ".flv", ".divx", ".xvid", ".mxf", ".webm", ".gif", nullptr,
70};
71
74const char *imb_ext_audio[] = {
75 ".wav",
76 ".ogg",
77 ".oga",
78 ".mp3",
79 ".mp2",
80 ".ac3",
81 ".aac",
82 ".flac",
83 ".wma",
84 ".eac3",
85 ".aif",
86 ".aiff",
87 ".m4a",
88 ".mka",
89 ".opus",
90 nullptr,
91};
92
93/* OIIO will validate the entire header of some files and DPX requires 2048 */
94#define HEADER_SIZE 2048
95
97{
98 BLI_stat_t st;
99 int fp;
100
101 BLI_assert(!BLI_path_is_rel(filepath));
102
103 if (UTIL_DEBUG) {
104 printf("%s: loading %s\n", __func__, filepath);
105 }
106
107 if (BLI_stat(filepath, &st) == -1) {
108 return -1;
109 }
110 if (((st.st_mode) & S_IFMT) != S_IFREG) {
111 return -1;
112 }
113
114 if ((fp = BLI_open(filepath, O_BINARY | O_RDONLY, 0)) == -1) {
115 return -1;
116 }
117
118 const int64_t size = BLI_read(fp, buf, HEADER_SIZE);
119
120 close(fp);
121 return size;
122}
123
124int IMB_ispic_type_from_memory(const uchar *buf, const size_t buf_size)
125{
126 for (const ImFileType *type = IMB_FILE_TYPES; type < IMB_FILE_TYPES_LAST; type++) {
127 if (type->is_a != nullptr) {
128 if (type->is_a(buf, buf_size)) {
129 return type->filetype;
130 }
131 }
132 }
133
134 return IMB_FTYPE_NONE;
135}
136
137int IMB_ispic_type(const char *filepath)
138{
139 uchar buf[HEADER_SIZE];
140 const int64_t buf_size = imb_ispic_read_header_from_filepath(filepath, buf);
141 if (buf_size <= 0) {
142 return IMB_FTYPE_NONE;
143 }
144 return IMB_ispic_type_from_memory(buf, size_t(buf_size));
145}
146
147bool IMB_ispic_type_matches(const char *filepath, int filetype)
148{
149 uchar buf[HEADER_SIZE];
150 const int64_t buf_size = imb_ispic_read_header_from_filepath(filepath, buf);
151 if (buf_size <= 0) {
152 return false;
153 }
154
155 const ImFileType *type = IMB_file_type_from_ftype(filetype);
156 if (type != nullptr) {
157 /* Requesting to load a type that can't check its own header doesn't make sense.
158 * Keep the check for developers. */
159 BLI_assert(type->is_a != nullptr);
160 if (type->is_a != nullptr) {
161 return type->is_a(buf, size_t(buf_size));
162 }
163 }
164 return false;
165}
166
167#undef HEADER_SIZE
168
169bool IMB_ispic(const char *filepath)
170{
171 return (IMB_ispic_type(filepath) != IMB_FTYPE_NONE);
172}
173
174#ifdef WITH_FFMPEG
175
176/* BLI_vsnprintf in ffmpeg_log_callback() causes invalid warning */
177# ifdef __GNUC__
178# pragma GCC diagnostic push
179# pragma GCC diagnostic ignored "-Wmissing-format-attribute"
180# endif
181
182static char ffmpeg_last_error[1024];
183
184static void ffmpeg_log_callback(void *ptr, int level, const char *format, va_list arg)
185{
186 if (ELEM(level, AV_LOG_FATAL, AV_LOG_ERROR)) {
187 size_t n;
188 va_list args_cpy;
189
190 va_copy(args_cpy, arg);
191 n = VSNPRINTF(ffmpeg_last_error, format, args_cpy);
192 va_end(args_cpy);
193
194 /* strip trailing \n */
195 ffmpeg_last_error[n - 1] = '\0';
196 }
197
198 if (G.debug & G_DEBUG_FFMPEG) {
199 /* call default logger to print all message to console */
200 av_log_default_callback(ptr, level, format, arg);
201 }
202}
203
204# ifdef __GNUC__
205# pragma GCC diagnostic pop
206# endif
207
208void IMB_ffmpeg_init()
209{
210 avdevice_register_all();
211
212 ffmpeg_last_error[0] = '\0';
213
214 if (G.debug & G_DEBUG_FFMPEG) {
215 av_log_set_level(AV_LOG_DEBUG);
216 }
217
218 /* set separate callback which could store last error to report to UI */
219 av_log_set_callback(ffmpeg_log_callback);
220}
221
222const char *IMB_ffmpeg_last_error()
223{
224 return ffmpeg_last_error;
225}
226
227static int isffmpeg(const char *filepath)
228{
229 AVFormatContext *pFormatCtx = nullptr;
230 uint i;
231 int videoStream;
232 const AVCodec *pCodec;
233
234 if (BLI_path_extension_check_n(filepath,
235 ".swf",
236 ".jpg",
237 ".jp2",
238 ".j2c",
239 ".png",
240 ".dds",
241 ".tga",
242 ".bmp",
243 ".tif",
244 ".exr",
245 ".cin",
246 ".wav",
247 nullptr))
248 {
249 return 0;
250 }
251
252 if (avformat_open_input(&pFormatCtx, filepath, nullptr, nullptr) != 0) {
253 if (UTIL_DEBUG) {
254 fprintf(stderr, "isffmpeg: av_open_input_file failed\n");
255 }
256 return 0;
257 }
258
259 if (avformat_find_stream_info(pFormatCtx, nullptr) < 0) {
260 if (UTIL_DEBUG) {
261 fprintf(stderr, "isffmpeg: avformat_find_stream_info failed\n");
262 }
263 avformat_close_input(&pFormatCtx);
264 return 0;
265 }
266
267 if (UTIL_DEBUG) {
268 av_dump_format(pFormatCtx, 0, filepath, 0);
269 }
270
271 /* Find the first video stream */
272 videoStream = -1;
273 for (i = 0; i < pFormatCtx->nb_streams; i++) {
274 if (pFormatCtx->streams[i] && pFormatCtx->streams[i]->codecpar &&
275 (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO))
276 {
277 videoStream = i;
278 break;
279 }
280 }
281
282 if (videoStream == -1) {
283 avformat_close_input(&pFormatCtx);
284 return 0;
285 }
286
287 AVCodecParameters *codec_par = pFormatCtx->streams[videoStream]->codecpar;
288
289 /* Find the decoder for the video stream */
290 pCodec = avcodec_find_decoder(codec_par->codec_id);
291 if (pCodec == nullptr) {
292 avformat_close_input(&pFormatCtx);
293 return 0;
294 }
295
296 avformat_close_input(&pFormatCtx);
297
298 return 1;
299}
300#endif
301
302bool IMB_isanim(const char *filepath)
303{
304 BLI_assert(!BLI_path_is_rel(filepath));
305
306 if (UTIL_DEBUG) {
307 printf("%s: %s\n", __func__, filepath);
308 }
309
310#ifdef WITH_FFMPEG
311 if (isffmpeg(filepath)) {
312 return true;
313 }
314#endif
315
316 return false;
317}
@ G_DEBUG_FFMPEG
#define BLI_assert(a)
Definition BLI_assert.h:50
File and directory operations.
#define O_BINARY
int BLI_stat(const char *path, BLI_stat_t *buffer) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
struct stat BLI_stat_t
int BLI_open(const char *filepath, int oflag, int pmode) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
int64_t BLI_read(int fd, void *buf, size_t nbytes)
Definition fileops_c.cc:96
bool BLI_path_is_rel(const char *path) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT
bool BLI_path_extension_check_n(const char *path,...) ATTR_NONNULL(1) ATTR_SENTINEL(0)
#define VSNPRINTF(dst, format, args)
Definition BLI_string.h:600
unsigned char uchar
unsigned int uint
#define ELEM(...)
Compatibility-like things for windows.
const char * IMB_ffmpeg_last_error()
void IMB_ffmpeg_init()
@ IMB_FTYPE_NONE
Contains defines and structs used throughout the imbuf module.
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
#define printf
const ImFileType * IMB_file_type_from_ftype(int ftype)
Definition filetype.cc:222
const ImFileType IMB_FILE_TYPES[]
Definition filetype.cc:24
const ImFileType * IMB_FILE_TYPES_LAST
Definition filetype.cc:220
format
#define G(x, y, z)
int IMB_ispic_type_from_memory(const uchar *buf, const size_t buf_size)
const char * imb_ext_movie[]
int IMB_ispic_type(const char *filepath)
const char * imb_ext_audio[]
bool IMB_isanim(const char *filepath)
static int64_t imb_ispic_read_header_from_filepath(const char *filepath, uchar buf[HEADER_SIZE])
bool IMB_ispic_type_matches(const char *filepath, int filetype)
bool IMB_ispic(const char *filepath)
const char * imb_ext_image[]
__int64 int64_t
Definition stdint.h:89
PointerRNA * ptr
Definition wm_files.cc:4126