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 * Peter Schlaile <peter [at] schlaile [dot] de> 2011
20 * Contributor(s): none yet.
22 * ***** END GPL LICENSE BLOCK *****
25 #include "IMB_indexer.h"
29 #include "MEM_guardedalloc.h"
31 #include "BLI_utildefines.h"
32 #include "BLI_blenlib.h"
33 #include "BLI_math_base.h"
35 #include "MEM_guardedalloc.h"
36 #include "DNA_userdef_types.h"
37 #include "BKE_global.h"
42 #include "ffmpeg_compat.h"
47 static char magic[] = "BlenMIdx";
48 static char temp_ext [] = "_part";
50 static int proxy_sizes[] = { IMB_PROXY_25, IMB_PROXY_50, IMB_PROXY_75,
52 static float proxy_fac[] = { 0.25, 0.50, 0.75, 1.00 };
55 static int tc_types[] = { IMB_TC_RECORD_RUN,
57 IMB_TC_INTERPOLATED_REC_DATE_FREE_RUN,
58 IMB_TC_RECORD_RUN_NO_GAPS,
62 #define INDEX_FILE_VERSION 1
64 /* ----------------------------------------------------------------------
66 ----------------------------------------------------------------------
69 extern void IMB_indexer_dv_new(anim_index_builder * idx);
72 /* ----------------------------------------------------------------------
73 - time code index functions
74 ---------------------------------------------------------------------- */
76 anim_index_builder * IMB_index_builder_create(const char * name)
79 anim_index_builder * rv
80 = MEM_callocN( sizeof(struct anim_index_builder),
83 fprintf(stderr, "Starting work on index: %s\n", name);
85 BLI_strncpy(rv->name, name, sizeof(rv->name));
86 BLI_strncpy(rv->temp_name, name, sizeof(rv->temp_name));
88 strcat(rv->temp_name, temp_ext);
90 BLI_make_existing_file(rv->temp_name);
92 rv->fp = fopen(rv->temp_name, "wb");
95 fprintf(stderr, "Couldn't open index target: %s! "
96 "Index build broken!\n", rv->temp_name);
101 fprintf(rv->fp, "%s%c%.3d", magic, (ENDIAN_ORDER==B_ENDIAN)?'V':'v',
107 void IMB_index_builder_add_entry(anim_index_builder * fp,
108 int frameno, unsigned long long seek_pos,
109 unsigned long long seek_pos_dts,
110 unsigned long long pts)
112 fwrite(&frameno, sizeof(int), 1, fp->fp);
113 fwrite(&seek_pos, sizeof(unsigned long long), 1, fp->fp);
114 fwrite(&seek_pos_dts, sizeof(unsigned long long), 1, fp->fp);
115 fwrite(&pts, sizeof(unsigned long long), 1, fp->fp);
118 void IMB_index_builder_proc_frame(anim_index_builder * fp,
119 unsigned char * buffer,
121 int frameno, unsigned long long seek_pos,
122 unsigned long long seek_pos_dts,
123 unsigned long long pts)
125 if (fp->proc_frame) {
128 e.seek_pos = seek_pos;
129 e.seek_pos_dts = seek_pos_dts;
132 fp->proc_frame(fp, buffer, data_size, &e);
134 IMB_index_builder_add_entry(fp, frameno, seek_pos,
139 void IMB_index_builder_finish(anim_index_builder * fp, int rollback)
141 if (fp->delete_priv_data) {
142 fp->delete_priv_data(fp);
148 unlink(fp->temp_name);
150 rename(fp->temp_name, fp->name);
156 struct anim_index * IMB_indexer_open(const char * name)
159 struct anim_index * idx;
160 FILE * fp = fopen(name, "rb");
167 if (fread(header, 12, 1, fp) != 1) {
174 if (memcmp(header, magic, 8) != 0) {
179 if (atoi(header+9) != INDEX_FILE_VERSION) {
184 idx = MEM_callocN( sizeof(struct anim_index), "anim_index");
186 BLI_strncpy(idx->name, name, sizeof(idx->name));
188 fseek(fp, 0, SEEK_END);
190 idx->num_entries = (ftell(fp) - 12)
191 / (sizeof(int) // framepos
192 + sizeof(unsigned long long) // seek_pos
193 + sizeof(unsigned long long) // seek_pos_dts
194 + sizeof(unsigned long long) // pts
197 fseek(fp, 12, SEEK_SET);
199 idx->entries = MEM_callocN( sizeof(struct anim_index_entry)
200 * idx->num_entries, "anim_index_entries");
202 for (i = 0; i < idx->num_entries; i++) {
203 fread(&idx->entries[i].frameno,
205 fread(&idx->entries[i].seek_pos,
206 sizeof(unsigned long long), 1, fp);
207 fread(&idx->entries[i].seek_pos_dts,
208 sizeof(unsigned long long), 1, fp);
209 fread(&idx->entries[i].pts,
210 sizeof(unsigned long long), 1, fp);
213 if (((ENDIAN_ORDER == B_ENDIAN) != (header[8] == 'V'))) {
214 for (i = 0; i < idx->num_entries; i++) {
215 SWITCH_INT(idx->entries[i].frameno);
216 SWITCH_INT64(idx->entries[i].seek_pos);
217 SWITCH_INT64(idx->entries[i].seek_pos_dts);
218 SWITCH_INT64(idx->entries[i].pts);
227 unsigned long long IMB_indexer_get_seek_pos(
228 struct anim_index * idx, int frame_index)
230 if (frame_index < 0) {
233 if (frame_index >= idx->num_entries) {
234 frame_index = idx->num_entries - 1;
236 return idx->entries[frame_index].seek_pos;
239 unsigned long long IMB_indexer_get_seek_pos_dts(
240 struct anim_index * idx, int frame_index)
242 if (frame_index < 0) {
245 if (frame_index >= idx->num_entries) {
246 frame_index = idx->num_entries - 1;
248 return idx->entries[frame_index].seek_pos_dts;
251 int IMB_indexer_get_frame_index(struct anim_index * idx, int frameno)
253 int len = idx->num_entries;
258 /* bsearch (lower bound) the right index */
266 if (idx->entries[middle].frameno < frameno) {
269 len = len - half - 1;
275 if (first == idx->num_entries) {
276 return idx->num_entries - 1;
282 unsigned long long IMB_indexer_get_pts(struct anim_index * idx,
285 if (frame_index < 0) {
288 if (frame_index >= idx->num_entries) {
289 frame_index = idx->num_entries - 1;
291 return idx->entries[frame_index].pts;
294 int IMB_indexer_get_duration(struct anim_index * idx)
296 if (idx->num_entries == 0) {
299 return idx->entries[idx->num_entries-1].frameno + 1;
302 int IMB_indexer_can_scan(struct anim_index * idx,
303 int old_frame_index, int new_frame_index)
305 /* makes only sense, if it is the same I-Frame and we are not
306 trying to run backwards in time... */
307 return (IMB_indexer_get_seek_pos(idx, old_frame_index)
308 == IMB_indexer_get_seek_pos(idx, new_frame_index) &&
309 old_frame_index < new_frame_index);
312 void IMB_indexer_close(struct anim_index * idx)
314 MEM_freeN(idx->entries);
318 int IMB_proxy_size_to_array_index(IMB_Proxy_Size pr_size)
321 case IMB_PROXY_NONE: /* if we got here, something is broken anyways,
322 so sane defaults... */
338 int IMB_timecode_to_array_index(IMB_Timecode_Type tc)
341 case IMB_TC_NONE: /* if we got here, something is broken anyways,
342 so sane defaults... */
344 case IMB_TC_RECORD_RUN:
346 case IMB_TC_FREE_RUN:
348 case IMB_TC_INTERPOLATED_REC_DATE_FREE_RUN:
350 case IMB_TC_RECORD_RUN_NO_GAPS:
359 /* ----------------------------------------------------------------------
360 - rebuild helper functions
361 ---------------------------------------------------------------------- */
363 static void get_index_dir(struct anim * anim, char * index_dir)
365 if (!anim->index_dir[0]) {
366 char fname[FILE_MAXFILE];
367 BLI_strncpy(index_dir, anim->name, FILE_MAXDIR);
368 BLI_splitdirstring(index_dir, fname);
369 BLI_join_dirfile(index_dir, FILE_MAXDIR, index_dir, "BL_proxy");
370 BLI_join_dirfile(index_dir, FILE_MAXDIR, index_dir, fname);
372 BLI_strncpy(index_dir, anim->index_dir, FILE_MAXDIR);
376 static void get_proxy_filename(struct anim * anim, IMB_Proxy_Size preview_size,
377 char * fname, int temp)
379 char index_dir[FILE_MAXDIR];
380 int i = IMB_proxy_size_to_array_index(preview_size);
382 char proxy_name[256];
383 char proxy_temp_name[256];
384 char stream_suffix[20];
386 stream_suffix[0] = 0;
388 if (anim->streamindex > 0) {
389 BLI_snprintf(stream_suffix, sizeof(stream_suffix), "_st%d", anim->streamindex);
392 BLI_snprintf(proxy_name, sizeof(proxy_name), "proxy_%d%s.avi",
393 (int) (proxy_fac[i] * 100), stream_suffix);
394 BLI_snprintf(proxy_temp_name, sizeof(proxy_temp_name), "proxy_%d%s_part.avi",
395 (int) (proxy_fac[i] * 100), stream_suffix);
397 get_index_dir(anim, index_dir);
399 BLI_join_dirfile(fname, FILE_MAXFILE + FILE_MAXDIR, index_dir,
400 temp ? proxy_temp_name : proxy_name);
403 static void get_tc_filename(struct anim * anim, IMB_Timecode_Type tc,
406 char index_dir[FILE_MAXDIR];
407 int i = IMB_timecode_to_array_index(tc);
408 const char * index_names[] = {
409 "record_run%s.blen_tc",
410 "free_run%s.blen_tc",
411 "interp_free_run%s.blen_tc",
412 "record_run_no_gaps%s.blen_tc"};
414 char stream_suffix[20];
415 char index_name[256];
417 stream_suffix[0] = 0;
419 if (anim->streamindex > 0) {
420 BLI_snprintf(stream_suffix, 20, "_st%d", anim->streamindex);
423 BLI_snprintf(index_name, 256, index_names[i], stream_suffix);
425 get_index_dir(anim, index_dir);
427 BLI_join_dirfile(fname, FILE_MAXFILE + FILE_MAXDIR,
428 index_dir, index_name);
431 /* ----------------------------------------------------------------------
433 ---------------------------------------------------------------------- */
437 struct proxy_output_ctx {
442 struct SwsContext * sws_ctx;
444 uint8_t* video_buffer;
445 int video_buffersize;
452 // work around stupid swscaler 16 bytes alignment bug...
454 static int round_up(int x, int mod)
456 return x + ((mod - (x % mod)) % mod);
459 static struct proxy_output_ctx * alloc_proxy_output_ffmpeg(
461 AVStream * st, int proxy_size, int width, int height,
464 struct proxy_output_ctx * rv = MEM_callocN(
465 sizeof(struct proxy_output_ctx), "alloc_proxy_output");
467 char fname[FILE_MAX];
469 // JPEG requires this
470 width = round_up(width, 8);
471 height = round_up(height, 8);
473 rv->proxy_size = proxy_size;
476 get_proxy_filename(rv->anim, rv->proxy_size, fname, TRUE);
477 BLI_make_existing_file(fname);
479 rv->of = avformat_alloc_context();
480 rv->of->oformat = av_guess_format("avi", NULL, NULL);
482 BLI_snprintf(rv->of->filename, sizeof(rv->of->filename), "%s", fname);
484 fprintf(stderr, "Starting work on proxy: %s\n", rv->of->filename);
486 rv->st = av_new_stream(rv->of, 0);
487 rv->c = rv->st->codec;
488 rv->c->codec_type = AVMEDIA_TYPE_VIDEO;
489 rv->c->codec_id = CODEC_ID_MJPEG;
490 rv->c->width = width;
491 rv->c->height = height;
493 rv->of->oformat->video_codec = rv->c->codec_id;
494 rv->codec = avcodec_find_encoder(rv->c->codec_id);
497 fprintf(stderr, "No ffmpeg MJPEG encoder available? "
498 "Proxy not built!\n");
503 if (rv->codec->pix_fmts) {
504 rv->c->pix_fmt = rv->codec->pix_fmts[0];
506 rv->c->pix_fmt = PIX_FMT_YUVJ420P;
509 rv->c->sample_aspect_ratio
510 = rv->st->sample_aspect_ratio
511 = st->codec->sample_aspect_ratio;
513 rv->c->time_base.den = 25;
514 rv->c->time_base.num = 1;
515 rv->st->time_base = rv->c->time_base;
517 if (rv->of->flags & AVFMT_GLOBALHEADER) {
518 rv->c->flags |= CODEC_FLAG_GLOBAL_HEADER;
521 if (av_set_parameters(rv->of, NULL) < 0) {
522 fprintf(stderr, "Couldn't set output parameters? "
523 "Proxy not built!\n");
528 if (avio_open(&rv->of->pb, fname, AVIO_FLAG_WRITE) < 0) {
529 fprintf(stderr, "Couldn't open outputfile! "
530 "Proxy not built!\n");
535 avcodec_open(rv->c, rv->codec);
537 rv->video_buffersize = 2000000;
538 rv->video_buffer = (uint8_t*)MEM_mallocN(
539 rv->video_buffersize, "FFMPEG video buffer");
541 rv->orig_height = st->codec->height;
543 if (st->codec->width != width || st->codec->height != height ||
544 st->codec->pix_fmt != rv->c->pix_fmt)
546 rv->frame = avcodec_alloc_frame();
547 avpicture_fill((AVPicture*) rv->frame,
548 MEM_mallocN(avpicture_get_size(
550 round_up(width, 16), height),
551 "alloc proxy output frame"),
552 rv->c->pix_fmt, round_up(width, 16), height);
554 rv->sws_ctx = sws_getContext(
560 SWS_FAST_BILINEAR | SWS_PRINT_INFO,
564 av_write_header(rv->of);
569 static int add_to_proxy_output_ffmpeg(
570 struct proxy_output_ctx * ctx, AVFrame * frame)
578 if ( ctx->sws_ctx && frame &&
579 (frame->data[0] || frame->data[1] ||
580 frame->data[2] || frame->data[3]))
582 sws_scale(ctx->sws_ctx, (const uint8_t * const*) frame->data,
583 frame->linesize, 0, ctx->orig_height,
584 ctx->frame->data, ctx->frame->linesize);
587 frame = ctx->sws_ctx ? (frame ? ctx->frame : 0) : frame;
590 frame->pts = ctx->cfra++;
593 outsize = avcodec_encode_video(
594 ctx->c, ctx->video_buffer, ctx->video_buffersize,
598 fprintf(stderr, "Error encoding proxy frame %d for '%s'\n",
599 ctx->cfra - 1, ctx->of->filename);
605 av_init_packet(&packet);
607 if (ctx->c->coded_frame->pts != AV_NOPTS_VALUE) {
608 packet.pts = av_rescale_q(ctx->c->coded_frame->pts,
612 if (ctx->c->coded_frame->key_frame)
613 packet.flags |= AV_PKT_FLAG_KEY;
615 packet.stream_index = ctx->st->index;
616 packet.data = ctx->video_buffer;
617 packet.size = outsize;
619 if (av_interleaved_write_frame(ctx->of, &packet) != 0) {
620 fprintf(stderr, "Error writing proxy frame %d "
621 "into '%s'\n", ctx->cfra - 1,
632 static void free_proxy_output_ffmpeg(struct proxy_output_ctx * ctx,
636 char fname[FILE_MAX];
637 char fname_tmp[FILE_MAX];
644 while (add_to_proxy_output_ffmpeg(ctx, NULL)) ;
647 avcodec_flush_buffers(ctx->c);
649 av_write_trailer(ctx->of);
651 avcodec_close(ctx->c);
653 for (i = 0; i < ctx->of->nb_streams; i++) {
654 if (&ctx->of->streams[i]) {
655 av_freep(&ctx->of->streams[i]);
659 if (ctx->of->oformat) {
660 if (!(ctx->of->oformat->flags & AVFMT_NOFILE)) {
661 avio_close(ctx->of->pb);
666 MEM_freeN(ctx->video_buffer);
669 sws_freeContext(ctx->sws_ctx);
671 MEM_freeN(ctx->frame->data[0]);
675 get_proxy_filename(ctx->anim, ctx->proxy_size,
681 get_proxy_filename(ctx->anim, ctx->proxy_size,
683 rename(fname_tmp, fname);
690 static int index_rebuild_ffmpeg(struct anim * anim,
691 IMB_Timecode_Type tcs_in_use,
692 IMB_Proxy_Size proxy_sizes_in_use,
694 short *stop, short *do_update,
698 unsigned long long seek_pos = 0;
699 unsigned long long last_seek_pos = 0;
700 unsigned long long seek_pos_dts = 0;
701 unsigned long long seek_pos_pts = 0;
702 unsigned long long last_seek_pos_dts = 0;
703 unsigned long long start_pts = 0;
705 double pts_time_base;
706 int frameno = 0, frameno_gapless = 0;
707 int start_pts_set = FALSE;
709 AVFormatContext *iFormatCtx;
710 AVCodecContext *iCodecCtx;
713 AVFrame* in_frame = 0;
714 AVPacket next_packet;
717 struct proxy_output_ctx * proxy_ctx[IMB_PROXY_MAX_SLOT];
718 anim_index_builder * indexer [IMB_TC_MAX_SLOT];
720 int num_proxy_sizes = IMB_PROXY_MAX_SLOT;
721 int num_indexers = IMB_TC_MAX_SLOT;
722 uint64_t stream_size;
724 memset(proxy_ctx, 0, sizeof(proxy_ctx));
725 memset(indexer, 0, sizeof(indexer));
727 if(av_open_input_file(&iFormatCtx, anim->name, NULL, 0, NULL) != 0) {
731 if (av_find_stream_info(iFormatCtx) < 0) {
732 av_close_input_file(iFormatCtx);
736 streamcount = anim->streamindex;
738 /* Find the video stream */
740 for (i = 0; i < iFormatCtx->nb_streams; i++)
741 if(iFormatCtx->streams[i]->codec->codec_type
742 == AVMEDIA_TYPE_VIDEO) {
743 if (streamcount > 0) {
751 if (videoStream == -1) {
752 av_close_input_file(iFormatCtx);
756 iStream = iFormatCtx->streams[videoStream];
757 iCodecCtx = iStream->codec;
759 iCodec = avcodec_find_decoder(iCodecCtx->codec_id);
761 if (iCodec == NULL) {
762 av_close_input_file(iFormatCtx);
766 iCodecCtx->workaround_bugs = 1;
768 if (avcodec_open(iCodecCtx, iCodec) < 0) {
769 av_close_input_file(iFormatCtx);
773 in_frame = avcodec_alloc_frame();
775 stream_size = avio_size(iFormatCtx->pb);
777 for (i = 0; i < num_proxy_sizes; i++) {
778 if (proxy_sizes_in_use & proxy_sizes[i]) {
779 proxy_ctx[i] = alloc_proxy_output_ffmpeg(
780 anim, iStream, proxy_sizes[i],
781 iCodecCtx->width * proxy_fac[i],
782 iCodecCtx->height * proxy_fac[i],
785 proxy_sizes_in_use &= ~proxy_sizes[i];
790 for (i = 0; i < num_indexers; i++) {
791 if (tcs_in_use & tc_types[i]) {
792 char fname[FILE_MAX];
794 get_tc_filename(anim, tc_types[i], fname);
796 indexer[i] = IMB_index_builder_create(fname);
798 tcs_in_use &= ~tc_types[i];
803 frame_rate = av_q2d(iStream->r_frame_rate);
804 pts_time_base = av_q2d(iStream->time_base);
806 while(av_read_frame(iFormatCtx, &next_packet) >= 0) {
807 int frame_finished = 0;
808 float next_progress = (float)((int)floor(((double) next_packet.pos) * 100 /
809 ((double) stream_size)+0.5)) / 100;
811 if (*progress != next_progress) {
812 *progress = next_progress;
817 av_free_packet(&next_packet);
821 if (next_packet.stream_index == videoStream) {
822 if (next_packet.flags & AV_PKT_FLAG_KEY) {
823 last_seek_pos = seek_pos;
824 last_seek_pos_dts = seek_pos_dts;
825 seek_pos = next_packet.pos;
826 seek_pos_dts = next_packet.dts;
827 seek_pos_pts = next_packet.pts;
830 avcodec_decode_video2(
831 iCodecCtx, in_frame, &frame_finished,
835 if (frame_finished) {
836 unsigned long long s_pos = seek_pos;
837 unsigned long long s_dts = seek_pos_dts;
838 unsigned long long pts
839 = av_get_pts_from_frame(iFormatCtx, in_frame);
841 for (i = 0; i < num_proxy_sizes; i++) {
842 add_to_proxy_output_ffmpeg(
843 proxy_ctx[i], in_frame);
846 if (!start_pts_set) {
848 start_pts_set = TRUE;
851 frameno = floor((pts - start_pts)
852 * pts_time_base * frame_rate + 0.5f);
854 /* decoding starts *always* on I-Frames,
855 so: P-Frames won't work, even if all the
856 information is in place, when we seek
857 to the I-Frame presented *after* the P-Frame,
858 but located before the P-Frame within
861 if (pts < seek_pos_pts) {
862 s_pos = last_seek_pos;
863 s_dts = last_seek_pos_dts;
866 for (i = 0; i < num_indexers; i++) {
867 if (tcs_in_use & tc_types[i]) {
868 int tc_frameno = frameno;
870 if(tc_types[i] == IMB_TC_RECORD_RUN_NO_GAPS)
871 tc_frameno = frameno_gapless;
873 IMB_index_builder_proc_frame(
884 av_free_packet(&next_packet);
887 for (i = 0; i < num_indexers; i++) {
888 if (tcs_in_use & tc_types[i]) {
889 IMB_index_builder_finish(indexer[i], *stop);
893 for (i = 0; i < num_proxy_sizes; i++) {
894 if (proxy_sizes_in_use & proxy_sizes[i]) {
895 free_proxy_output_ffmpeg(proxy_ctx[i], *stop);
906 /* ----------------------------------------------------------------------
907 - internal AVI (fallback) rebuilder
908 ---------------------------------------------------------------------- */
910 static AviMovie * alloc_proxy_output_avi(
911 struct anim * anim, char * filename, int width, int height,
918 short frs_sec = 25; /* it doesn't really matter for proxies,
919 but sane defaults help anyways...*/
920 float frs_sec_base = 1.0;
922 IMB_anim_get_fps(anim, &frs_sec, &frs_sec_base);
927 framerate= (double) frs_sec / (double) frs_sec_base;
929 avi = MEM_mallocN (sizeof(AviMovie), "avimovie");
931 format = AVI_FORMAT_MJPEG;
933 if (AVI_open_compress (filename, avi, 1, format) != AVI_ERROR_NONE) {
938 AVI_set_compress_option (avi, AVI_OPTION_TYPE_MAIN, 0, AVI_OPTION_WIDTH, &x);
939 AVI_set_compress_option (avi, AVI_OPTION_TYPE_MAIN, 0, AVI_OPTION_HEIGHT, &y);
940 AVI_set_compress_option (avi, AVI_OPTION_TYPE_MAIN, 0, AVI_OPTION_QUALITY, &quality);
941 AVI_set_compress_option (avi, AVI_OPTION_TYPE_MAIN, 0, AVI_OPTION_FRAMERATE, &framerate);
949 static void index_rebuild_fallback(struct anim * anim,
950 IMB_Timecode_Type UNUSED(tcs_in_use),
951 IMB_Proxy_Size proxy_sizes_in_use,
953 short *stop, short *do_update,
956 int cnt = IMB_anim_get_duration(anim, IMB_TC_NONE);
958 AviMovie * proxy_ctx[IMB_PROXY_MAX_SLOT];
959 char fname[FILE_MAX];
960 char fname_tmp[FILE_MAX];
962 memset(proxy_ctx, 0, sizeof(proxy_ctx));
964 /* since timecode indices only work with ffmpeg right now,
965 don't know a sensible fallback here...
967 so no proxies, no game to play...
969 if (proxy_sizes_in_use == IMB_PROXY_NONE) {
973 for (i = 0; i < IMB_PROXY_MAX_SLOT; i++) {
974 if (proxy_sizes_in_use & proxy_sizes[i]) {
975 char fname[FILE_MAX];
977 get_proxy_filename(anim, proxy_sizes[i], fname, TRUE);
978 BLI_make_existing_file(fname);
980 proxy_ctx[i] = alloc_proxy_output_avi(
982 anim->x * proxy_fac[i],
983 anim->y * proxy_fac[i],
988 for (pos = 0; pos < cnt; pos++) {
989 struct ImBuf * ibuf = IMB_anim_absolute(
990 anim, pos, IMB_TC_NONE, IMB_PROXY_NONE);
991 int next_progress = (int) ((double) pos / (double) cnt);
993 if (*progress != next_progress) {
994 *progress = next_progress;
1004 for (i = 0; i < IMB_PROXY_MAX_SLOT; i++) {
1005 if (proxy_sizes_in_use & proxy_sizes[i]) {
1006 int x = anim->x * proxy_fac[i];
1007 int y = anim->y * proxy_fac[i];
1009 struct ImBuf * s_ibuf = IMB_scalefastImBuf(
1012 IMB_convert_rgba_to_abgr(s_ibuf);
1014 AVI_write_frame (proxy_ctx[i], pos,
1016 s_ibuf->rect, x * y * 4);
1018 /* note that libavi free's the buffer... */
1019 s_ibuf->rect = NULL;
1021 IMB_freeImBuf(s_ibuf);
1026 for (i = 0; i < IMB_PROXY_MAX_SLOT; i++) {
1027 if (proxy_sizes_in_use & proxy_sizes[i]) {
1028 AVI_close_compress (proxy_ctx[i]);
1029 MEM_freeN (proxy_ctx[i]);
1031 get_proxy_filename(anim, proxy_sizes[i],
1033 get_proxy_filename(anim, proxy_sizes[i],
1039 rename(fname_tmp, fname);
1045 /* ----------------------------------------------------------------------
1047 ---------------------------------------------------------------------- */
1049 void IMB_anim_index_rebuild(struct anim * anim, IMB_Timecode_Type tcs_in_use,
1050 IMB_Proxy_Size proxy_sizes_in_use,
1052 short *stop, short *do_update, float *progress)
1054 switch (anim->curtype) {
1057 index_rebuild_ffmpeg(anim, tcs_in_use, proxy_sizes_in_use,
1058 quality, stop, do_update, progress);
1062 index_rebuild_fallback(anim, tcs_in_use, proxy_sizes_in_use,
1063 quality, stop, do_update, progress);
1068 void IMB_free_indices(struct anim * anim)
1072 for (i = 0; i < IMB_PROXY_MAX_SLOT; i++) {
1073 if (anim->proxy_anim[i]) {
1074 IMB_close_anim(anim->proxy_anim[i]);
1075 anim->proxy_anim[i] = NULL;
1079 for (i = 0; i < IMB_TC_MAX_SLOT; i++) {
1080 if (anim->curr_idx[i]) {
1081 IMB_indexer_close(anim->curr_idx[i]);
1082 anim->curr_idx[i] = NULL;
1087 anim->proxies_tried = 0;
1088 anim->indices_tried = 0;
1091 void IMB_anim_set_index_dir(struct anim * anim, const char * dir)
1093 if (strcmp(anim->index_dir, dir) == 0) {
1096 BLI_strncpy(anim->index_dir, dir, sizeof(anim->index_dir));
1098 IMB_free_indices(anim);
1101 struct anim * IMB_anim_open_proxy(
1102 struct anim * anim, IMB_Proxy_Size preview_size)
1104 char fname[FILE_MAX];
1105 int i = IMB_proxy_size_to_array_index(preview_size);
1107 if (anim->proxy_anim[i]) {
1108 return anim->proxy_anim[i];
1111 if (anim->proxies_tried & preview_size) {
1115 get_proxy_filename(anim, preview_size, fname, FALSE);
1117 anim->proxy_anim[i] = IMB_open_anim(fname, 0, 0);
1119 anim->proxies_tried |= preview_size;
1121 return anim->proxy_anim[i];
1124 struct anim_index * IMB_anim_open_index(
1125 struct anim * anim, IMB_Timecode_Type tc)
1127 char fname[FILE_MAX];
1128 int i = IMB_timecode_to_array_index(tc);
1130 if (anim->curr_idx[i]) {
1131 return anim->curr_idx[i];
1134 if (anim->indices_tried & tc) {
1138 get_tc_filename(anim, tc, fname);
1140 anim->curr_idx[i] = IMB_indexer_open(fname);
1142 anim->indices_tried |= tc;
1144 return anim->curr_idx[i];
1147 int IMB_anim_index_get_frame_index(struct anim * anim, IMB_Timecode_Type tc,
1150 struct anim_index * idx = IMB_anim_open_index(anim, tc);
1156 return IMB_indexer_get_frame_index(idx, position);