diff options
-rw-r--r-- | source/blender/imbuf/IMB_imbuf.h | 22 | ||||
-rw-r--r-- | source/blender/imbuf/IMB_imbuf_types.h | 8 | ||||
-rw-r--r-- | source/blender/imbuf/SConscript | 5 | ||||
-rw-r--r-- | source/blender/imbuf/intern/IMB_anim.h | 16 | ||||
-rw-r--r-- | source/blender/imbuf/intern/Makefile | 5 | ||||
-rw-r--r-- | source/blender/imbuf/intern/allocimbuf.c | 108 | ||||
-rw-r--r-- | source/blender/imbuf/intern/anim.c | 311 | ||||
-rw-r--r-- | source/blender/imbuf/intern/cmap.c | 2 | ||||
-rw-r--r-- | source/blender/imbuf/intern/util.c | 104 |
9 files changed, 568 insertions, 13 deletions
diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h index ae7a7f527f1..e78ee5901e9 100644 --- a/source/blender/imbuf/IMB_imbuf.h +++ b/source/blender/imbuf/IMB_imbuf.h @@ -176,6 +176,28 @@ struct ImBuf *IMB_allocImBuf(short x, short y, /** * + * Increase reference count to imbuf + * (to delete an imbuf you have to call freeImBuf as many times as it + * is referenced) + * + * @attention Defined in allocimbuf.c + */ + +void IMB_refImBuf(struct ImBuf * ibuf); + +/** + * + * @attention Defined in allocimbuf.c + */ +void IMB_cache_limiter_insert(struct ImBuf * i); +void IMB_cache_limiter_unmanage(struct ImBuf * i); +void IMB_cache_limiter_touch(struct ImBuf * i); +void IMB_cache_limiter_ref(struct ImBuf * i); +void IMB_cache_limiter_unref(struct ImBuf * i); +int IMB_cache_limiter_get_refcount(struct ImBuf * i); + +/** + * * @attention Defined in allocimbuf.c */ struct ImBuf *IMB_dupImBuf(struct ImBuf *ibuf1); diff --git a/source/blender/imbuf/IMB_imbuf_types.h b/source/blender/imbuf/IMB_imbuf_types.h index ef1aa631fc6..fe82b852eaa 100644 --- a/source/blender/imbuf/IMB_imbuf_types.h +++ b/source/blender/imbuf/IMB_imbuf_types.h @@ -94,7 +94,11 @@ typedef struct ImBuf{ unsigned char *encodedbuffer; /**< Compressed image only used with png currently */ unsigned int encodedsize; /**< Size of data written to encodedbuffer */ unsigned int encodedbuffersize; /**< Size of encodedbuffer */ + float *rect_float; /**< floating point Rect equivilant */ + + struct MEM_CacheLimiterHandle_s * c_handle; /**< handle for cache limiter */ + int refcounter; /**< Refcounter for multiple users */ } ImBuf; /* Moved from BKE_bmfont_types.h because it is a userflag bit mask. */ @@ -133,8 +137,8 @@ typedef enum { #define IB_zbuf (1 << 13) #define IB_mem (1 << 14) -#define IB_rectfloat (1 << 15) -#define IB_zbuffloat (1 << 16) +#define IB_rectfloat (1 << 15) +#define IB_zbuffloat (1 << 16) /* * The bit flag is stored in the ImBuf.ftype variable. diff --git a/source/blender/imbuf/SConscript b/source/blender/imbuf/SConscript index 938e306e7f6..ff6cad0deb1 100644 --- a/source/blender/imbuf/SConscript +++ b/source/blender/imbuf/SConscript @@ -3,7 +3,7 @@ Import ('env') sources = env.Glob('intern/*.c') -incs = '. ../makesdna #/intern/guardedalloc ../blenlib' +incs = '. ../makesdna #/intern/guardedalloc #/intern/memutil ../blenlib' incs += ' ../avi ../quicktime ../blenkernel' incs += ' ' + env['BF_JPEG_INC'] @@ -16,6 +16,9 @@ defs = [] if env['WITH_BF_OPENEXR'] == 1: defs.append('WITH_OPENEXR') +if env['WITH_BF_FFMPEG'] == 1: + defs += ' WITH_FFMPEG' + if env['WITH_BF_QUICKTIME']==1: incs += ' ' + env['BF_QUICKTIME_INC'] defs.append('WITH_QUICKTIME') diff --git a/source/blender/imbuf/intern/IMB_anim.h b/source/blender/imbuf/intern/IMB_anim.h index 77958f82e42..5d597aa5463 100644 --- a/source/blender/imbuf/intern/IMB_anim.h +++ b/source/blender/imbuf/intern/IMB_anim.h @@ -78,6 +78,11 @@ #endif /* _WIN32 || __APPLE__ */ #endif /* WITH_QUICKTIME */ +#ifdef WITH_FFMPEG +#include <ffmpeg/avformat.h> +#include <ffmpeg/avcodec.h> +#endif + #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" @@ -112,6 +117,7 @@ #define ANIM_MDEC (1 << 5) #define ANIM_AVI (1 << 6) #define ANIM_QTIME (1 << 7) +#define ANIM_FFMPEG (1 << 8) #define ANIM5_MMAP 0 #define ANIM5_MALLOC 1 @@ -168,6 +174,16 @@ struct anim { /* quicktime */ struct _QuicktimeMovie *qtime; #endif /* WITH_QUICKTIME */ + +#ifdef WITH_FFMPEG + AVFormatContext *pFormatCtx; + AVCodecContext *pCodecCtx; + AVCodec *pCodec; + AVFrame *pFrameRGB; + AVFrame *pFrame; + int videoStream; +#endif + }; #endif diff --git a/source/blender/imbuf/intern/Makefile b/source/blender/imbuf/intern/Makefile index 6f8fc7d31bb..4efba0cd988 100644 --- a/source/blender/imbuf/intern/Makefile +++ b/source/blender/imbuf/intern/Makefile @@ -62,6 +62,7 @@ CPPFLAGS += -I../../avi CPPFLAGS += -I../../quicktime # path to the guarded memory allocator CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include +CPPFLAGS += -I$(NAN_MEMUTIL)/include # This is not really needed, but until /include is cleaned, it must be # there for proper compilation. # - No, it is also needed in antialias, for listbase (nzc) @@ -73,3 +74,7 @@ ifeq ($(WITH_QUICKTIME), true) CPPFLAGS += -DWITH_QUICKTIME endif +ifeq ($(WITH_FFMPEG), true) + CPPFLAGS += -DWITH_FFMPEG +endif + diff --git a/source/blender/imbuf/intern/allocimbuf.c b/source/blender/imbuf/intern/allocimbuf.c index 0c1d182f4b2..89873b92f3d 100644 --- a/source/blender/imbuf/intern/allocimbuf.c +++ b/source/blender/imbuf/intern/allocimbuf.c @@ -43,6 +43,7 @@ #include "IMB_divers.h" #include "IMB_allocimbuf.h" +#include "MEM_CacheLimiterC-Api.h" static unsigned int dfltcmap[16] = { 0x00000000, 0xffffffff, 0x777777ff, 0xccccccff, @@ -135,17 +136,27 @@ void IMB_freecmapImBuf(struct ImBuf * ibuf) void IMB_freeImBuf(struct ImBuf * ibuf) { if (ibuf){ - imb_freeplanesImBuf(ibuf); - imb_freerectImBuf(ibuf); - imb_freerectfloatImBuf(ibuf); - IMB_freezbufImBuf(ibuf); - IMB_freezbuffloatImBuf(ibuf); - IMB_freecmapImBuf(ibuf); - freeencodedbufferImBuf(ibuf); - MEM_freeN(ibuf); + if (ibuf->refcounter > 0) { + ibuf->refcounter--; + } else { + imb_freeplanesImBuf(ibuf); + imb_freerectImBuf(ibuf); + imb_freerectfloatImBuf(ibuf); + IMB_freezbufImBuf(ibuf); + IMB_freezbuffloatImBuf(ibuf); + IMB_freecmapImBuf(ibuf); + freeencodedbufferImBuf(ibuf); + IMB_cache_limiter_unmanage(ibuf); + MEM_freeN(ibuf); + } } } +void IMB_refImBuf(struct ImBuf * ibuf) +{ + ibuf->refcounter++; +} + short addzbufImBuf(struct ImBuf * ibuf) { int size; @@ -444,7 +455,8 @@ struct ImBuf *IMB_dupImBuf(struct ImBuf *ibuf1) // set malloc flag tbuf.mall = ibuf2->mall; - + tbuf.c_handle = 0; + *ibuf2 = tbuf; if (ibuf1->cmap){ @@ -454,3 +466,81 @@ struct ImBuf *IMB_dupImBuf(struct ImBuf *ibuf1) return(ibuf2); } + +/* support for cache limiting */ + +static void imbuf_cache_destructor(void * data) +{ + struct ImBuf * ibuf = (struct ImBuf*) data; + + imb_freeplanesImBuf(ibuf); + imb_freerectImBuf(ibuf); + IMB_freezbufImBuf(ibuf); + IMB_freecmapImBuf(ibuf); + freeencodedbufferImBuf(ibuf); + + ibuf->c_handle = 0; +} + +static MEM_CacheLimiterC ** get_imbuf_cache_limiter() +{ + static MEM_CacheLimiterC * c = 0; + if (!c) { + c = new_MEM_CacheLimiter(imbuf_cache_destructor); + } + return &c; +} + +void IMB_free_cache_limiter() +{ + delete_MEM_CacheLimiter(*get_imbuf_cache_limiter()); + *get_imbuf_cache_limiter() = 0; +} + +void IMB_cache_limiter_insert(struct ImBuf * i) +{ + if (!i->c_handle) { + i->c_handle = MEM_CacheLimiter_insert( + *get_imbuf_cache_limiter(), i); + MEM_CacheLimiter_ref(i->c_handle); + MEM_CacheLimiter_enforce_limits( + *get_imbuf_cache_limiter()); + MEM_CacheLimiter_unref(i->c_handle); + } +} + +void IMB_cache_limiter_unmanage(struct ImBuf * i) +{ + if (i->c_handle) { + MEM_CacheLimiter_unmanage(i->c_handle); + i->c_handle = 0; + } +} + +void IMB_cache_limiter_touch(struct ImBuf * i) +{ + if (i->c_handle) { + MEM_CacheLimiter_touch(i->c_handle); + } +} + +void IMB_cache_limiter_ref(struct ImBuf * i) +{ + if (i->c_handle) { + MEM_CacheLimiter_ref(i->c_handle); + } +} + +void IMB_cache_limiter_unref(struct ImBuf * i) +{ + if (i->c_handle) { + MEM_CacheLimiter_unref(i->c_handle); + } +} + +int IMB_cache_limiter_get_refcount(struct ImBuf * i) +{ + if (i->c_handle) { + MEM_CacheLimiter_get_refcount(i->c_handle); + } +} diff --git a/source/blender/imbuf/intern/anim.c b/source/blender/imbuf/intern/anim.c index 51fadc5c06a..ad563cc3bb2 100644 --- a/source/blender/imbuf/intern/anim.c +++ b/source/blender/imbuf/intern/anim.c @@ -85,6 +85,17 @@ #include "IMB_anim.h" #include "IMB_anim5.h" +#ifdef WITH_FFMPEG +#include <ffmpeg/avformat.h> +#include <ffmpeg/avcodec.h> + +#if LIBAVFORMAT_VERSION_INT < (49 << 16) +#define FFMPEG_OLD_FRAME_RATE 1 +#else +#define FFMPEG_CODEC_IS_POINTER 1 +#endif + +#endif /****/ @@ -293,6 +304,7 @@ void IMB_free_anim_ibuf(struct anim * anim) { anim->ibuf1 = anim->ibuf2 = NULL; } +static void free_anim_ffmpeg(struct anim * anim); void IMB_free_anim(struct anim * anim) { if (anim == NULL) { @@ -308,6 +320,9 @@ void IMB_free_anim(struct anim * anim) { #ifdef WITH_QUICKTIME free_anim_quicktime(anim); #endif +#ifdef WITH_FFMPEG + free_anim_ffmpeg(anim); +#endif free(anim); } @@ -473,6 +488,287 @@ static ImBuf * avi_fetchibuf (struct anim *anim, int position) { return ibuf; } +#ifdef WITH_FFMPEG + +extern void do_init_ffmpeg(); + +static int startffmpeg(struct anim * anim) { + int i, videoStream; + + AVCodec *pCodec; + AVFormatContext *pFormatCtx; + AVCodecContext *pCodecCtx; + + if (anim == 0) return(-1); + + do_init_ffmpeg(); + + if(av_open_input_file(&pFormatCtx, anim->name, NULL, 0, NULL)!=0) { + return -1; + } + + if(av_find_stream_info(pFormatCtx)<0) { + av_close_input_file(pFormatCtx); + return -1; + } + + dump_format(pFormatCtx, 0, anim->name, 0); + + + /* Find the first video stream */ + videoStream=-1; + for(i=0; i<pFormatCtx->nb_streams; i++) +#ifdef FFMPEG_CODEC_IS_POINTER + if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO) +#else + if(pFormatCtx->streams[i]->codec.codec_type==CODEC_TYPE_VIDEO) +#endif + { + videoStream=i; + break; + } + + if(videoStream==-1) { + av_close_input_file(pFormatCtx); + return -1; + } + +#ifdef FFMPEG_CODEC_IS_POINTER + pCodecCtx=pFormatCtx->streams[videoStream]->codec; +#else + pCodecCtx=&pFormatCtx->streams[videoStream]->codec; +#endif + + /* Find the decoder for the video stream */ + pCodec=avcodec_find_decoder(pCodecCtx->codec_id); + if(pCodec==NULL) { + avcodec_close(pCodecCtx); + av_close_input_file(pFormatCtx); + return -1; + } + + pCodecCtx->workaround_bugs = 1; + pCodecCtx->lowres = 0; + pCodecCtx->idct_algo= FF_IDCT_AUTO; + pCodecCtx->skip_frame= AVDISCARD_DEFAULT; + pCodecCtx->skip_idct= AVDISCARD_DEFAULT; + pCodecCtx->skip_loop_filter= AVDISCARD_DEFAULT; + pCodecCtx->error_resilience= FF_ER_CAREFUL; + pCodecCtx->error_concealment= 3; + + if(avcodec_open(pCodecCtx, pCodec)<0) { + avcodec_close(pCodecCtx); + av_close_input_file(pFormatCtx); + return -1; + } + +#ifdef FFMPEG_OLD_FRAME_RATE + if(pCodecCtx->frame_rate>1000 && pCodecCtx->frame_rate_base==1) + pCodecCtx->frame_rate_base=1000; + + + anim->duration = pFormatCtx->duration * pCodecCtx->frame_rate + / pCodecCtx->frame_rate_base / AV_TIME_BASE; +#else + anim->duration = pFormatCtx->duration * av_q2d(pFormatCtx->streams[videoStream]->r_frame_rate) / AV_TIME_BASE; + +#endif + anim->params = 0; + + anim->x = pCodecCtx->width; + anim->y = pCodecCtx->height; + anim->interlacing = 0; + anim->orientation = 0; + anim->framesize = anim->x * anim->y * 4; + + anim->curposition = -1; + + anim->pFormatCtx = pFormatCtx; + anim->pCodecCtx = pCodecCtx; + anim->pCodec = pCodec; + anim->videoStream = videoStream; + + anim->pFrame = avcodec_alloc_frame(); + anim->pFrameRGB = avcodec_alloc_frame(); + + if (avpicture_get_size(PIX_FMT_RGBA32, anim->x, anim->y) + != anim->x * anim->y * 4) { + fprintf (stderr, + "ffmpeg has changed alloc scheme ... ARGHHH!\n"); + avcodec_close(anim->pCodecCtx); + av_close_input_file(anim->pFormatCtx); + av_free(anim->pFrameRGB); + av_free(anim->pFrame); + return -1; + } + + /*printf("x:%d y:%d size:%d interl:%d dur:%d\n", anim->x, anim->y, anim->framesize, anim->interlacing, anim->duration);*/ + return (0); +} + +static ImBuf * ffmpeg_fetchibuf(struct anim * anim, int position) { + ImBuf * ibuf; + int frameFinished; + AVPacket packet; + offset_t pos_to_match = AV_NOPTS_VALUE; + int pos_found = 1; + + if (anim == 0) return (0); + + ibuf = IMB_allocImBuf(anim->x, anim->y, 24, IB_rect, 0); + + avpicture_fill((AVPicture *)anim->pFrameRGB, + (unsigned char*) ibuf->rect, + PIX_FMT_RGBA32, anim->x, anim->y); + + if (position != anim->curposition + 1) { + int keyframe_found = 0; + int scan_pos = position; + int max_scan = 18; /* max mpeg 1/2 gop size */ +#ifdef FFMPEG_OLD_FRAME_RATE + long long pos = (long long) anim->pCodecCtx->frame_rate_base + * position * AV_TIME_BASE + / anim->pCodecCtx->frame_rate; +#else + long long pos = (long long) position * AV_TIME_BASE + / av_q2d(anim->pFormatCtx->streams[anim->videoStream] + ->r_frame_rate); +#endif + long long st_time = anim->pFormatCtx + ->streams[anim->videoStream]->start_time; + if (st_time != AV_NOPTS_VALUE) { + pos += st_time; + } + + av_seek_frame(anim->pFormatCtx, -1, + pos, AVSEEK_FLAG_ANY | AVSEEK_FLAG_BACKWARD ); + + while(av_read_frame(anim->pFormatCtx, &packet)>=0) { + if(packet.stream_index == anim->videoStream) { + pos_to_match + = url_ftell(&anim->pFormatCtx->pb); + if ((packet.flags & PKT_FLAG_KEY) != 0) { + keyframe_found = 1; + } + av_free_packet(&packet); + break; + } + av_free_packet(&packet); + } + /* if all ffmpeg seek bugs are fixed, the following + loop is obsolete ... (but does not hurt very much...) + */ + + while (!keyframe_found && max_scan--) { + scan_pos--; +#ifdef FFMPEG_OLD_FRAME_RATE + pos = (long long) + anim->pCodecCtx->frame_rate_base + * scan_pos * AV_TIME_BASE + / anim->pCodecCtx->frame_rate; +#else + pos = (long long) scan_pos * AV_TIME_BASE + / av_q2d(anim->pFormatCtx + ->streams[anim->videoStream] + ->r_frame_rate); +#endif + av_seek_frame(anim->pFormatCtx, -1, + pos, + AVSEEK_FLAG_ANY | AVSEEK_FLAG_BACKWARD); + + while(av_read_frame(anim->pFormatCtx, &packet)>=0) { + if(packet.stream_index == anim->videoStream) { + if ((packet.flags & PKT_FLAG_KEY) + != 0) { + keyframe_found = 1; + } + av_free_packet(&packet); + break; + } + av_free_packet(&packet); + } + } + + if (max_scan <= 0) { + fprintf(stderr, + "Warning: Key frame not found, " + "doesn't hurt, but _slow_...!\n"); + } + + av_seek_frame(anim->pFormatCtx, -1, + pos, AVSEEK_FLAG_ANY | AVSEEK_FLAG_BACKWARD); + + pos_found = 0; + avcodec_flush_buffers(anim->pCodecCtx); + } + + while(av_read_frame(anim->pFormatCtx, &packet)>=0) { + if (packet.stream_index == anim->videoStream + && !pos_found) { + if (url_ftell(&anim->pFormatCtx->pb) == pos_to_match) { + pos_found = 1; + } + } + if(packet.stream_index == anim->videoStream) { + avcodec_decode_video(anim->pCodecCtx, + anim->pFrame, &frameFinished, + packet.data, packet.size); + + if(frameFinished && pos_found) { + unsigned char * p =(unsigned char*) ibuf->rect; + unsigned char * e = p + anim->x * anim->y * 4; + + img_convert((AVPicture *)anim->pFrameRGB, + PIX_FMT_RGBA32, + (AVPicture*)anim->pFrame, + anim->pCodecCtx->pix_fmt, + anim->pCodecCtx->width, + anim->pCodecCtx->height); + IMB_flipy(ibuf); + if (G.order == L_ENDIAN) { + /* BGRA -> RGBA */ + while (p != e) { + unsigned char a = p[0]; + p[0] = p[2]; + p[2] = a; + p += 4; + } + } else { + /* ARGB -> RGBA */ + while (p != e) { + unsigned long a = + *(unsigned long*) p; + a = (a << 8) | p[0]; + *(unsigned long*) p = a; + p += 4; + } + } + av_free_packet(&packet); + break; + } + } + + av_free_packet(&packet); + } + + return(ibuf); +} + +static void free_anim_ffmpeg(struct anim * anim) { + if (anim == NULL) return; + + if (anim->pCodecCtx) { + avcodec_close(anim->pCodecCtx); + av_close_input_file(anim->pFormatCtx); + av_free(anim->pFrameRGB); + av_free(anim->pFrame); + } + anim->duration = 0; +} + +#endif + + /* probeer volgende plaatje te lezen */ /* Geen plaatje, probeer dan volgende animatie te openen */ /* gelukt, haal dan eerste plaatje van animatie */ @@ -488,6 +784,9 @@ static struct ImBuf * anim_getnew(struct anim * anim) { #ifdef WITH_QUICKTIME free_anim_quicktime(anim); #endif +#ifdef WITH_FFMPEG + free_anim_ffmpeg(anim); +#endif if (anim->curtype != 0) return (0); anim->curtype = imb_get_anim_type(anim->name); @@ -521,6 +820,12 @@ static struct ImBuf * anim_getnew(struct anim * anim) { ibuf = IMB_allocImBuf (anim->x, anim->y, 24, 0, 0); break; #endif +#ifdef WITH_FFMPEG + case ANIM_FFMPEG: + if (startffmpeg(anim)) return (0); + ibuf = IMB_allocImBuf (anim->x, anim->y, 24, 0, 0); + break; +#endif } return(ibuf); @@ -585,6 +890,12 @@ struct ImBuf * IMB_anim_absolute(struct anim * anim, int position) { if (ibuf) anim->curposition = position; break; #endif +#ifdef WITH_FFMPEG + case ANIM_FFMPEG: + ibuf = ffmpeg_fetchibuf(anim, position); + if (ibuf) anim->curposition = position; + break; +#endif } if (ibuf) { diff --git a/source/blender/imbuf/intern/cmap.c b/source/blender/imbuf/intern/cmap.c index c955fbf7e60..7b4962d8837 100644 --- a/source/blender/imbuf/intern/cmap.c +++ b/source/blender/imbuf/intern/cmap.c @@ -49,6 +49,7 @@ static short lastmincol; static short lastcbits; short alpha_col0 = FALSE; +extern void IMB_free_cache_limiter(); /* * there still is a bug here. If you want to convert an image to a 1 bit colormap you get @@ -61,6 +62,7 @@ void IMB_freeImBufdata(void) lastcube= 0; if (lastcoltab) free(lastcoltab); lastcoltab= 0; + IMB_free_cache_limiter(); } diff --git a/source/blender/imbuf/intern/util.c b/source/blender/imbuf/intern/util.c index 8110a115471..fdb1bed3870 100644 --- a/source/blender/imbuf/intern/util.c +++ b/source/blender/imbuf/intern/util.c @@ -58,6 +58,18 @@ #include "quicktime_import.h" #endif +#ifdef WITH_FFMPEG +#include <ffmpeg/avcodec.h> +#include <ffmpeg/avformat.h> + +#if LIBAVFORMAT_VERSION_INT < (49 << 16) +#define FFMPEG_OLD_FRAME_RATE 1 +#else +#define FFMPEG_CODEC_IS_POINTER 1 +#endif + +#endif + #define UTIL_DEBUG 0 /* from misc_util: flip the bytes from x */ @@ -195,15 +207,103 @@ static int isqtime (char *name) { } #endif +#ifdef WITH_FFMPEG +void do_init_ffmpeg() +{ + static int ffmpeg_init = 0; + if (!ffmpeg_init) { + ffmpeg_init = 1; + av_register_all(); + } +} + + +static int isffmpeg (char *filename) { + AVFormatContext *pFormatCtx; + int i, videoStream; + AVCodec *pCodec; + AVCodecContext *pCodecCtx; + + do_init_ffmpeg(); + + if(av_open_input_file(&pFormatCtx, filename, NULL, 0, NULL)!=0) { + fprintf(stderr, "isffmpeg: av_open_input_file failed\n"); + return 0; + } + + if(av_find_stream_info(pFormatCtx)<0) { + fprintf(stderr, "isffmpeg: av_find_stream_info failed\n"); + av_close_input_file(pFormatCtx); + return 0; + } + + dump_format(pFormatCtx, 0, filename, 0); + + + /* Find the first video stream */ + videoStream=-1; + for(i=0; i<pFormatCtx->nb_streams; i++) +#ifdef FFMPEG_CODEC_IS_POINTER + if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO) +#else + if(pFormatCtx->streams[i]->codec.codec_type==CODEC_TYPE_VIDEO) +#endif + { + videoStream=i; + break; + } + +#ifdef FFMPEG_CODEC_IS_POINTER + pCodecCtx=pFormatCtx->streams[videoStream]->codec; +#else + pCodecCtx=&pFormatCtx->streams[videoStream]->codec; +#endif + + if(videoStream==-1) { + avcodec_close(pCodecCtx); + av_close_input_file(pFormatCtx); + return 0; + } + + + /* Find the decoder for the video stream */ + pCodec=avcodec_find_decoder(pCodecCtx->codec_id); + if(pCodec==NULL) { + avcodec_close(pCodecCtx); + av_close_input_file(pFormatCtx); + return 0; + } + + if(pCodec->capabilities & CODEC_CAP_TRUNCATED) + pCodecCtx->flags|=CODEC_FLAG_TRUNCATED; + + if(avcodec_open(pCodecCtx, pCodec)<0) { + avcodec_close(pCodecCtx); + av_close_input_file(pFormatCtx); + return 0; + } + + avcodec_close(pCodecCtx); + av_close_input_file(pFormatCtx); + + return 1; +} +#endif + int imb_get_anim_type(char * name) { int type; struct stat st; if(UTIL_DEBUG) printf("in getanimtype: %s\n", name); +#ifdef WITH_FFMPEG + /* stat test below fails on large files > 4GB */ + if (isffmpeg(name)) return (ANIM_FFMPEG); +#endif + if (ib_stat(name,&st) == -1) return(0); if (((st.st_mode) & S_IFMT) != S_IFREG) return(0); - + if (isavi(name)) return (ANIM_AVI); if (ismovie(name)) return (ANIM_MOVIE); @@ -223,6 +323,7 @@ int IMB_isanim(char *filename) { if (G.have_quicktime){ if( BLI_testextensie(filename, ".avi") || BLI_testextensie(filename, ".flc") + || BLI_testextensie(filename, ".dv") || BLI_testextensie(filename, ".mov") || BLI_testextensie(filename, ".movie") || BLI_testextensie(filename, ".mv")) { @@ -232,6 +333,7 @@ int IMB_isanim(char *filename) { } } else { // no quicktime if( BLI_testextensie(filename, ".avi") + || BLI_testextensie(filename, ".dv") || BLI_testextensie(filename, ".mv")) { type = imb_get_anim_type(filename); } |