code cleanup: includes for imbuf, also remove double promotion.
[blender.git] / source / blender / imbuf / intern / indexer.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  * Peter Schlaile <peter [at] schlaile [dot] de> 2011
19  *
20  * Contributor(s): none yet.
21  *
22  * ***** END GPL LICENSE BLOCK *****
23  */
24
25 #include <stdlib.h>
26
27 #include "IMB_indexer.h"
28 #include "IMB_anim.h"
29 #include "AVI_avi.h"
30 #include "imbuf.h"
31 #include "MEM_guardedalloc.h"
32
33 #include "BLI_utildefines.h"
34 #include "BLI_string.h"
35 #include "BLI_path_util.h"
36 #include "BLI_fileops.h"
37 #include "BLI_math_base.h"
38
39 #include "MEM_guardedalloc.h"
40 #include "DNA_userdef_types.h"
41 #include "BKE_global.h"
42
43 #ifdef WITH_FFMPEG
44
45 #include "ffmpeg_compat.h"
46
47 #endif //WITH_FFMPEG
48
49
50 static char magic[] = "BlenMIdx";
51 static char temp_ext[] = "_part";
52
53 static int proxy_sizes[] = { IMB_PROXY_25, IMB_PROXY_50, IMB_PROXY_75,
54                                  IMB_PROXY_100 };
55 static float proxy_fac[] = { 0.25, 0.50, 0.75, 1.00 };
56
57 #ifdef WITH_FFMPEG
58 static int tc_types[] = {IMB_TC_RECORD_RUN,
59                          IMB_TC_FREE_RUN,
60                          IMB_TC_INTERPOLATED_REC_DATE_FREE_RUN,
61                          IMB_TC_RECORD_RUN_NO_GAPS};
62 #endif
63
64 #define INDEX_FILE_VERSION 1
65
66 /* ----------------------------------------------------------------------
67  * - time code index functions
68  * ---------------------------------------------------------------------- */
69
70 anim_index_builder *IMB_index_builder_create(const char *name)
71 {
72
73         anim_index_builder *rv = MEM_callocN(sizeof(struct anim_index_builder),
74                                              "index builder");
75
76         fprintf(stderr, "Starting work on index: %s\n", name);
77
78         BLI_strncpy(rv->name, name, sizeof(rv->name));
79         BLI_strncpy(rv->temp_name, name, sizeof(rv->temp_name));
80
81         strcat(rv->temp_name, temp_ext);
82
83         BLI_make_existing_file(rv->temp_name);
84
85         rv->fp = BLI_fopen(rv->temp_name, "wb");
86
87         if (!rv->fp) {
88                 fprintf(stderr, "Couldn't open index target: %s! "
89                         "Index build broken!\n", rv->temp_name);
90                 MEM_freeN(rv);
91                 return NULL;
92         }
93
94         fprintf(rv->fp, "%s%c%.3d", magic, (ENDIAN_ORDER == B_ENDIAN) ? 'V' : 'v',
95                 INDEX_FILE_VERSION);
96
97         return rv;
98 }
99
100 void IMB_index_builder_add_entry(anim_index_builder *fp,
101                                  int frameno, unsigned long long seek_pos,
102                                  unsigned long long seek_pos_dts,
103                                  unsigned long long pts)
104 {
105         fwrite(&frameno, sizeof(int), 1, fp->fp);
106         fwrite(&seek_pos, sizeof(unsigned long long), 1, fp->fp);
107         fwrite(&seek_pos_dts, sizeof(unsigned long long), 1, fp->fp);
108         fwrite(&pts, sizeof(unsigned long long), 1, fp->fp);
109 }
110
111 void IMB_index_builder_proc_frame(anim_index_builder *fp,
112                                   unsigned char *buffer,
113                                   int data_size,
114                                   int frameno, unsigned long long seek_pos,
115                                   unsigned long long seek_pos_dts,
116                                   unsigned long long pts)
117 {
118         if (fp->proc_frame) {
119                 anim_index_entry e;
120                 e.frameno = frameno;
121                 e.seek_pos = seek_pos;
122                 e.seek_pos_dts = seek_pos_dts;
123                 e.pts = pts;
124
125                 fp->proc_frame(fp, buffer, data_size, &e);
126         }
127         else {
128                 IMB_index_builder_add_entry(fp, frameno, seek_pos,
129                                             seek_pos_dts, pts);
130         }
131 }
132
133 void IMB_index_builder_finish(anim_index_builder *fp, int rollback)
134 {
135         if (fp->delete_priv_data) {
136                 fp->delete_priv_data(fp);
137         }
138
139         fclose(fp->fp);
140         
141         if (rollback) {
142                 unlink(fp->temp_name);
143         }
144         else {
145                 unlink(fp->name);
146                 BLI_rename(fp->temp_name, fp->name);
147         }
148
149         MEM_freeN(fp);
150 }
151
152 struct anim_index *IMB_indexer_open(const char *name)
153 {
154         char header[13];
155         struct anim_index *idx;
156         FILE *fp = BLI_fopen(name, "rb");
157         int i;
158
159         if (!fp) {
160                 return NULL;
161         }
162
163         if (fread(header, 12, 1, fp) != 1) {
164                 fclose(fp);
165                 return NULL;
166         }
167
168         header[12] = 0;
169
170         if (memcmp(header, magic, 8) != 0) {
171                 fclose(fp);
172                 return NULL;
173         }
174
175         if (atoi(header + 9) != INDEX_FILE_VERSION) {
176                 fclose(fp);
177                 return NULL;
178         }
179
180         idx = MEM_callocN(sizeof(struct anim_index), "anim_index");
181
182         BLI_strncpy(idx->name, name, sizeof(idx->name));
183         
184         fseek(fp, 0, SEEK_END);
185
186         idx->num_entries = (ftell(fp) - 12) /
187                            (sizeof(int) +                /* framepos */
188                             sizeof(unsigned long long) + /* seek_pos */
189                             sizeof(unsigned long long) + /* seek_pos_dts */
190                             sizeof(unsigned long long)   /* pts */
191                            );
192
193         fseek(fp, 12, SEEK_SET);
194
195         idx->entries = MEM_callocN(sizeof(struct anim_index_entry) *
196                                    idx->num_entries, "anim_index_entries");
197
198         for (i = 0; i < idx->num_entries; i++) {
199                 fread(&idx->entries[i].frameno,
200                       sizeof(int), 1, fp);
201                 fread(&idx->entries[i].seek_pos,
202                       sizeof(unsigned long long), 1, fp);
203                 fread(&idx->entries[i].seek_pos_dts,
204                       sizeof(unsigned long long), 1, fp);
205                 fread(&idx->entries[i].pts,
206                       sizeof(unsigned long long), 1, fp);
207         }
208
209         if (((ENDIAN_ORDER == B_ENDIAN) != (header[8] == 'V'))) {
210                 for (i = 0; i < idx->num_entries; i++) {
211                         SWITCH_INT(idx->entries[i].frameno);
212                         SWITCH_INT64(idx->entries[i].seek_pos);
213                         SWITCH_INT64(idx->entries[i].seek_pos_dts);
214                         SWITCH_INT64(idx->entries[i].pts);
215                 }
216         }
217
218         fclose(fp);
219
220         return idx;
221 }
222
223 unsigned long long IMB_indexer_get_seek_pos(
224     struct anim_index *idx, int frame_index)
225 {
226         if (frame_index < 0) {
227                 frame_index = 0;
228         }
229         if (frame_index >= idx->num_entries) {
230                 frame_index = idx->num_entries - 1;
231         }
232         return idx->entries[frame_index].seek_pos;
233 }
234
235 unsigned long long IMB_indexer_get_seek_pos_dts(
236     struct anim_index *idx, int frame_index)
237 {
238         if (frame_index < 0) {
239                 frame_index = 0;
240         }
241         if (frame_index >= idx->num_entries) {
242                 frame_index = idx->num_entries - 1;
243         }
244         return idx->entries[frame_index].seek_pos_dts;
245 }
246
247 int IMB_indexer_get_frame_index(struct anim_index *idx, int frameno)
248 {
249         int len = idx->num_entries;
250         int half;
251         int middle;
252         int first = 0;
253
254         /* bsearch (lower bound) the right index */
255         
256         while (len > 0) {
257                 half = len >> 1;
258                 middle = first;
259
260                 middle += half;
261
262                 if (idx->entries[middle].frameno < frameno) {
263                         first = middle;
264                         first++;
265                         len = len - half - 1;
266                 }
267                 else {
268                         len = half;
269                 }
270         }
271
272         if (first == idx->num_entries) {
273                 return idx->num_entries - 1;
274         }
275         else {
276                 return first;
277         }
278 }
279
280 unsigned long long IMB_indexer_get_pts(struct anim_index *idx,
281                                        int frame_index)
282 {
283         if (frame_index < 0) {
284                 frame_index = 0;
285         }
286         if (frame_index >= idx->num_entries) {
287                 frame_index = idx->num_entries - 1;
288         }
289         return idx->entries[frame_index].pts;
290 }
291
292 int IMB_indexer_get_duration(struct anim_index *idx)
293 {
294         if (idx->num_entries == 0) {
295                 return 0;
296         }
297         return idx->entries[idx->num_entries - 1].frameno + 1;
298 }
299
300 int IMB_indexer_can_scan(struct anim_index *idx,
301                          int old_frame_index, int new_frame_index)
302 {
303         /* makes only sense, if it is the same I-Frame and we are not
304          * trying to run backwards in time... */
305         return (IMB_indexer_get_seek_pos(idx, old_frame_index) == IMB_indexer_get_seek_pos(idx, new_frame_index) &&
306                 old_frame_index < new_frame_index);
307 }
308
309 void IMB_indexer_close(struct anim_index *idx)
310 {
311         MEM_freeN(idx->entries);
312         MEM_freeN(idx);
313 }
314
315 int IMB_proxy_size_to_array_index(IMB_Proxy_Size pr_size)
316 {
317         switch (pr_size) {
318                 case IMB_PROXY_NONE: /* if we got here, something is broken anyways,
319                                       * so sane defaults... */
320                         return 0;
321                 case IMB_PROXY_25:
322                         return 0;
323                 case IMB_PROXY_50:
324                         return 1;
325                 case IMB_PROXY_75:
326                         return 2;
327                 case IMB_PROXY_100:
328                         return 3;
329                 default:
330                         return 0;
331         };
332         return 0;
333 }
334
335 int IMB_timecode_to_array_index(IMB_Timecode_Type tc)
336 {
337         switch (tc) {
338                 case IMB_TC_NONE: /* if we got here, something is broken anyways,
339                                    * so sane defaults... */
340                         return 0;
341                 case IMB_TC_RECORD_RUN:
342                         return 0;
343                 case IMB_TC_FREE_RUN:
344                         return 1;
345                 case IMB_TC_INTERPOLATED_REC_DATE_FREE_RUN:
346                         return 2;
347                 case IMB_TC_RECORD_RUN_NO_GAPS:
348                         return 3;
349                 default:
350                         return 0;
351         };
352         return 0;
353 }
354
355
356 /* ----------------------------------------------------------------------
357  * - rebuild helper functions
358  * ---------------------------------------------------------------------- */
359
360 static void get_index_dir(struct anim *anim, char *index_dir)
361 {
362         if (!anim->index_dir[0]) {
363                 char fname[FILE_MAXFILE];
364                 BLI_strncpy(index_dir, anim->name, FILE_MAXDIR);
365                 BLI_splitdirstring(index_dir, fname);
366                 BLI_join_dirfile(index_dir, FILE_MAXDIR, index_dir, "BL_proxy");
367                 BLI_join_dirfile(index_dir, FILE_MAXDIR, index_dir, fname);
368         }
369         else {
370                 BLI_strncpy(index_dir, anim->index_dir, FILE_MAXDIR);
371         }
372 }
373
374 static void get_proxy_filename(struct anim *anim, IMB_Proxy_Size preview_size,
375                                char *fname, int temp)
376 {
377         char index_dir[FILE_MAXDIR];
378         int i = IMB_proxy_size_to_array_index(preview_size);
379
380         char proxy_name[256];
381         char proxy_temp_name[256];
382         char stream_suffix[20];
383         
384         stream_suffix[0] = 0;
385
386         if (anim->streamindex > 0) {
387                 BLI_snprintf(stream_suffix, sizeof(stream_suffix), "_st%d", anim->streamindex);
388         }
389
390         BLI_snprintf(proxy_name, sizeof(proxy_name), "proxy_%d%s.avi",
391                      (int) (proxy_fac[i] * 100), stream_suffix);
392         BLI_snprintf(proxy_temp_name, sizeof(proxy_temp_name), "proxy_%d%s_part.avi",
393                      (int) (proxy_fac[i] * 100), stream_suffix);
394
395         get_index_dir(anim, index_dir);
396
397         BLI_join_dirfile(fname, FILE_MAXFILE + FILE_MAXDIR, index_dir, 
398                          temp ? proxy_temp_name : proxy_name);
399 }
400
401 static void get_tc_filename(struct anim *anim, IMB_Timecode_Type tc,
402                             char *fname)
403 {
404         char index_dir[FILE_MAXDIR];
405         int i = IMB_timecode_to_array_index(tc);
406         const char *index_names[] = {
407                 "record_run%s.blen_tc",
408                 "free_run%s.blen_tc",
409                 "interp_free_run%s.blen_tc",
410                 "record_run_no_gaps%s.blen_tc"
411         };
412
413         char stream_suffix[20];
414         char index_name[256];
415         
416         stream_suffix[0] = 0;
417
418         if (anim->streamindex > 0) {
419                 BLI_snprintf(stream_suffix, 20, "_st%d", anim->streamindex);
420         }
421         
422         BLI_snprintf(index_name, 256, index_names[i], stream_suffix);
423
424         get_index_dir(anim, index_dir);
425         
426         BLI_join_dirfile(fname, FILE_MAXFILE + FILE_MAXDIR, 
427                          index_dir, index_name);
428 }
429
430 /* ----------------------------------------------------------------------
431  * - common rebuilder structures
432  * ---------------------------------------------------------------------- */
433
434 typedef struct IndexBuildContext {
435         int anim_type;
436 } IndexBuildContext;
437
438
439 /* ----------------------------------------------------------------------
440  * - ffmpeg rebuilder
441  * ---------------------------------------------------------------------- */
442
443 #ifdef WITH_FFMPEG
444
445 struct proxy_output_ctx {
446         AVFormatContext *of;
447         AVStream *st;
448         AVCodecContext *c;
449         AVCodec *codec;
450         struct SwsContext *sws_ctx;
451         AVFrame *frame;
452         uint8_t *video_buffer;
453         int video_buffersize;
454         int cfra;
455         int proxy_size;
456         int orig_height;
457         struct anim *anim;
458 };
459
460 // work around stupid swscaler 16 bytes alignment bug...
461
462 static int round_up(int x, int mod)
463 {
464         return x + ((mod - (x % mod)) % mod);
465 }
466
467 static struct proxy_output_ctx *alloc_proxy_output_ffmpeg(
468         struct anim *anim,
469         AVStream *st, int proxy_size, int width, int height,
470         int quality)
471 {
472         struct proxy_output_ctx *rv = MEM_callocN(
473                 sizeof(struct proxy_output_ctx), "alloc_proxy_output");
474         
475         char fname[FILE_MAX];
476         int ffmpeg_quality;
477
478         /* JPEG requires this */
479         width = round_up(width, 8);
480         height = round_up(height, 8);
481
482         rv->proxy_size = proxy_size;
483         rv->anim = anim;
484
485         get_proxy_filename(rv->anim, rv->proxy_size, fname, TRUE);
486         BLI_make_existing_file(fname);
487
488         rv->of = avformat_alloc_context();
489         rv->of->oformat = av_guess_format("avi", NULL, NULL);
490         
491         BLI_snprintf(rv->of->filename, sizeof(rv->of->filename), "%s", fname);
492
493         fprintf(stderr, "Starting work on proxy: %s\n", rv->of->filename);
494
495         rv->st = av_new_stream(rv->of, 0);
496         rv->c = rv->st->codec;
497         rv->c->codec_type = AVMEDIA_TYPE_VIDEO;
498         rv->c->codec_id = CODEC_ID_MJPEG;
499         rv->c->width = width;
500         rv->c->height = height;
501
502         rv->of->oformat->video_codec = rv->c->codec_id;
503         rv->codec = avcodec_find_encoder(rv->c->codec_id);
504
505         if (!rv->codec) {
506                 fprintf(stderr, "No ffmpeg MJPEG encoder available? "
507                         "Proxy not built!\n");
508                 av_free(rv->of);
509                 return NULL;
510         }
511
512         if (rv->codec->pix_fmts) {
513                 rv->c->pix_fmt = rv->codec->pix_fmts[0];
514         }
515         else {
516                 rv->c->pix_fmt = PIX_FMT_YUVJ420P;
517         }
518
519         rv->c->sample_aspect_ratio =
520             rv->st->sample_aspect_ratio =
521                 st->codec->sample_aspect_ratio;
522
523         rv->c->time_base.den = 25;
524         rv->c->time_base.num = 1;
525         rv->st->time_base = rv->c->time_base;
526
527         /* there's no  way to set JPEG quality in the same way as in AVI JPEG and image sequence,
528          * but this seems to be giving expected quality result */
529         ffmpeg_quality = (int)(1.0f + 30.0f * (1.0f - (float)quality / 100.0f) + 0.5f);
530         av_set_int(rv->c, "qmin", ffmpeg_quality);
531         av_set_int(rv->c, "qmax", ffmpeg_quality);
532
533         if (rv->of->flags & AVFMT_GLOBALHEADER) {
534                 rv->c->flags |= CODEC_FLAG_GLOBAL_HEADER;
535         }
536
537         if (avio_open(&rv->of->pb, fname, AVIO_FLAG_WRITE) < 0) {
538                 fprintf(stderr, "Couldn't open outputfile! "
539                         "Proxy not built!\n");
540                 av_free(rv->of);
541                 return 0;
542         }
543
544         avcodec_open(rv->c, rv->codec);
545
546         rv->video_buffersize = 2000000;
547         rv->video_buffer = (uint8_t *)MEM_mallocN(
548                 rv->video_buffersize, "FFMPEG video buffer");
549
550         rv->orig_height = st->codec->height;
551
552         if (st->codec->width != width || st->codec->height != height ||
553             st->codec->pix_fmt != rv->c->pix_fmt)
554         {
555                 rv->frame = avcodec_alloc_frame();
556                 avpicture_fill((AVPicture *) rv->frame,
557                                MEM_mallocN(avpicture_get_size(
558                                                rv->c->pix_fmt,
559                                                round_up(width, 16), height),
560                                            "alloc proxy output frame"),
561                                rv->c->pix_fmt, round_up(width, 16), height);
562
563                 rv->sws_ctx = sws_getContext(
564                         st->codec->width,
565                         st->codec->height,
566                         st->codec->pix_fmt,
567                         width, height,
568                         rv->c->pix_fmt,
569                         SWS_FAST_BILINEAR | SWS_PRINT_INFO,
570                         NULL, NULL, NULL);
571         }
572
573         if (avformat_write_header(rv->of, NULL) < 0) {
574                 fprintf(stderr, "Couldn't set output parameters? "
575                         "Proxy not built!\n");
576                 av_free(rv->of);
577                 return 0;
578         }
579
580         return rv;
581 }
582
583 static int add_to_proxy_output_ffmpeg(
584     struct proxy_output_ctx *ctx, AVFrame *frame)
585 {
586         int outsize = 0;
587
588         if (!ctx) {
589                 return 0;
590         }
591
592         if (ctx->sws_ctx && frame &&
593             (frame->data[0] || frame->data[1] ||
594              frame->data[2] || frame->data[3]))
595         {
596                 sws_scale(ctx->sws_ctx, (const uint8_t *const *) frame->data,
597                           frame->linesize, 0, ctx->orig_height,
598                           ctx->frame->data, ctx->frame->linesize);
599         }
600
601         frame = ctx->sws_ctx ? (frame ? ctx->frame : 0) : frame;
602
603         if (frame) {
604                 frame->pts = ctx->cfra++;
605         }
606
607         outsize = avcodec_encode_video(
608                 ctx->c, ctx->video_buffer, ctx->video_buffersize,
609                 frame);
610
611         if (outsize < 0) {
612                 fprintf(stderr, "Error encoding proxy frame %d for '%s'\n", 
613                         ctx->cfra - 1, ctx->of->filename);
614                 return 0;
615         }
616
617         if (outsize != 0) {
618                 AVPacket packet;
619                 av_init_packet(&packet);
620
621                 if (ctx->c->coded_frame->pts != AV_NOPTS_VALUE) {
622                         packet.pts = av_rescale_q(ctx->c->coded_frame->pts,
623                                                   ctx->c->time_base,
624                                                   ctx->st->time_base);
625                 }
626                 if (ctx->c->coded_frame->key_frame)
627                         packet.flags |= AV_PKT_FLAG_KEY;
628
629                 packet.stream_index = ctx->st->index;
630                 packet.data = ctx->video_buffer;
631                 packet.size = outsize;
632
633                 if (av_interleaved_write_frame(ctx->of, &packet) != 0) {
634                         fprintf(stderr, "Error writing proxy frame %d "
635                                 "into '%s'\n", ctx->cfra - 1,
636                                 ctx->of->filename);
637                         return 0;
638                 }
639
640                 return 1;
641         }
642         else {
643                 return 0;
644         }
645 }
646
647 static void free_proxy_output_ffmpeg(struct proxy_output_ctx *ctx,
648                                      int rollback)
649 {
650         int i;
651         char fname[FILE_MAX];
652         char fname_tmp[FILE_MAX];
653
654         if (!ctx) {
655                 return;
656         }
657
658         if (!rollback) {
659                 while (add_to_proxy_output_ffmpeg(ctx, NULL)) {}
660         }
661
662         avcodec_flush_buffers(ctx->c);
663
664         av_write_trailer(ctx->of);
665         
666         avcodec_close(ctx->c);
667         
668         for (i = 0; i < ctx->of->nb_streams; i++) {
669                 if (&ctx->of->streams[i]) {
670                         av_freep(&ctx->of->streams[i]);
671                 }
672         }
673
674         if (ctx->of->oformat) {
675                 if (!(ctx->of->oformat->flags & AVFMT_NOFILE)) {
676                         avio_close(ctx->of->pb);
677                 }
678         }
679         av_free(ctx->of);
680
681         MEM_freeN(ctx->video_buffer);
682
683         if (ctx->sws_ctx) {
684                 sws_freeContext(ctx->sws_ctx);
685
686                 MEM_freeN(ctx->frame->data[0]);
687                 av_free(ctx->frame);
688         }
689
690         get_proxy_filename(ctx->anim, ctx->proxy_size, 
691                            fname_tmp, TRUE);
692
693         if (rollback) {
694                 unlink(fname_tmp);
695         }
696         else {
697                 get_proxy_filename(ctx->anim, ctx->proxy_size, 
698                                    fname, FALSE);
699                 unlink(fname);
700                 BLI_rename(fname_tmp, fname);
701         }
702         
703         MEM_freeN(ctx);
704 }
705
706 typedef struct FFmpegIndexBuilderContext {
707         int anim_type;
708
709         AVFormatContext *iFormatCtx;
710         AVCodecContext *iCodecCtx;
711         AVCodec *iCodec;
712         AVStream *iStream;
713         int videoStream;
714
715         int num_proxy_sizes;
716         int num_indexers;
717
718         struct proxy_output_ctx *proxy_ctx[IMB_PROXY_MAX_SLOT];
719         anim_index_builder *indexer[IMB_TC_MAX_SLOT];
720
721         IMB_Timecode_Type tcs_in_use;
722         IMB_Proxy_Size proxy_sizes_in_use;
723 } FFmpegIndexBuilderContext;
724
725 static IndexBuildContext *index_ffmpeg_create_context(struct anim *anim, IMB_Timecode_Type tcs_in_use,
726                                                       IMB_Proxy_Size proxy_sizes_in_use, int quality)
727 {
728         FFmpegIndexBuilderContext *context = MEM_callocN(sizeof(FFmpegIndexBuilderContext), "FFmpeg index builder context");
729         int num_proxy_sizes = IMB_PROXY_MAX_SLOT;
730         int num_indexers = IMB_TC_MAX_SLOT;
731         int i, streamcount;
732
733         context->tcs_in_use = tcs_in_use;
734         context->proxy_sizes_in_use = proxy_sizes_in_use;
735         context->num_proxy_sizes = IMB_PROXY_MAX_SLOT;
736         context->num_indexers = IMB_TC_MAX_SLOT;
737
738         memset(context->proxy_ctx, 0, sizeof(context->proxy_ctx));
739         memset(context->indexer, 0, sizeof(context->indexer));
740
741         if (avformat_open_input(&context->iFormatCtx, anim->name, NULL, NULL) != 0) {
742                 MEM_freeN(context);
743                 return NULL;
744         }
745
746         if (av_find_stream_info(context->iFormatCtx) < 0) {
747                 av_close_input_file(context->iFormatCtx);
748                 MEM_freeN(context);
749                 return NULL;
750         }
751
752         streamcount = anim->streamindex;
753
754         /* Find the video stream */
755         context->videoStream = -1;
756         for (i = 0; i < context->iFormatCtx->nb_streams; i++)
757                 if (context->iFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
758                         if (streamcount > 0) {
759                                 streamcount--;
760                                 continue;
761                         }
762                         context->videoStream = i;
763                         break;
764                 }
765
766         if (context->videoStream == -1) {
767                 av_close_input_file(context->iFormatCtx);
768                 MEM_freeN(context);
769                 return NULL;
770         }
771
772         context->iStream = context->iFormatCtx->streams[context->videoStream];
773         context->iCodecCtx = context->iStream->codec;
774
775         context->iCodec = avcodec_find_decoder(context->iCodecCtx->codec_id);
776
777         if (context->iCodec == NULL) {
778                 av_close_input_file(context->iFormatCtx);
779                 MEM_freeN(context);
780                 return NULL;
781         }
782
783         context->iCodecCtx->workaround_bugs = 1;
784
785         if (avcodec_open(context->iCodecCtx, context->iCodec) < 0) {
786                 av_close_input_file(context->iFormatCtx);
787                 MEM_freeN(context);
788                 return NULL;
789         }
790
791         for (i = 0; i < num_proxy_sizes; i++) {
792                 if (proxy_sizes_in_use & proxy_sizes[i]) {
793                         context->proxy_ctx[i] = alloc_proxy_output_ffmpeg(
794                                 anim, context->iStream, proxy_sizes[i],
795                                 context->iCodecCtx->width * proxy_fac[i],
796                                 context->iCodecCtx->height * proxy_fac[i],
797                                 quality);
798                         if (!context->proxy_ctx[i]) {
799                                 proxy_sizes_in_use &= ~proxy_sizes[i];
800                         }
801                 }
802         }
803
804         for (i = 0; i < num_indexers; i++) {
805                 if (tcs_in_use & tc_types[i]) {
806                         char fname[FILE_MAX];
807
808                         get_tc_filename(anim, tc_types[i], fname);
809
810                         context->indexer[i] = IMB_index_builder_create(fname);
811                         if (!context->indexer[i]) {
812                                 tcs_in_use &= ~tc_types[i];
813                         }
814                 }
815         }
816
817         return (IndexBuildContext *)context;
818 }
819
820 static void index_rebuild_ffmpeg_finish(FFmpegIndexBuilderContext *context, int stop)
821 {
822         int i;
823
824         for (i = 0; i < context->num_indexers; i++) {
825                 if (context->tcs_in_use & tc_types[i]) {
826                         IMB_index_builder_finish(context->indexer[i], stop);
827                 }
828         }
829
830         for (i = 0; i < context->num_proxy_sizes; i++) {
831                 if (context->proxy_sizes_in_use & proxy_sizes[i]) {
832                         free_proxy_output_ffmpeg(context->proxy_ctx[i], stop);
833                 }
834         }
835
836         MEM_freeN(context);
837 }
838
839 static int index_rebuild_ffmpeg(FFmpegIndexBuilderContext *context,
840                                 short *stop, short *do_update, float *progress)
841 {
842         int i;
843         unsigned long long seek_pos = 0;
844         unsigned long long last_seek_pos = 0;
845         unsigned long long seek_pos_dts = 0;
846         unsigned long long seek_pos_pts = 0;
847         unsigned long long last_seek_pos_dts = 0;
848         unsigned long long start_pts = 0;
849         double frame_rate;
850         double pts_time_base;
851         int frameno = 0, frameno_gapless = 0;
852         int start_pts_set = FALSE;
853         AVFrame *in_frame = 0;
854         AVPacket next_packet;
855         uint64_t stream_size;
856
857         in_frame = avcodec_alloc_frame();
858
859         stream_size = avio_size(context->iFormatCtx->pb);
860
861         frame_rate = av_q2d(context->iStream->r_frame_rate);
862         pts_time_base = av_q2d(context->iStream->time_base);
863
864         while (av_read_frame(context->iFormatCtx, &next_packet) >= 0) {
865                 int frame_finished = 0;
866                 float next_progress =  (float)((int)floor(((double) next_packet.pos) * 100 /
867                                                           ((double) stream_size) + 0.5)) / 100;
868
869                 if (*progress != next_progress) {
870                         *progress = next_progress;
871                         *do_update = TRUE;
872                 }
873
874                 if (*stop) {
875                         av_free_packet(&next_packet);
876                         break;
877                 }
878
879                 if (next_packet.stream_index == context->videoStream) {
880                         if (next_packet.flags & AV_PKT_FLAG_KEY) {
881                                 last_seek_pos = seek_pos;
882                                 last_seek_pos_dts = seek_pos_dts;
883                                 seek_pos = next_packet.pos;
884                                 seek_pos_dts = next_packet.dts;
885                                 seek_pos_pts = next_packet.pts;
886                         }
887
888                         avcodec_decode_video2(
889                                 context->iCodecCtx, in_frame, &frame_finished,
890                                 &next_packet);
891                 }
892
893                 if (frame_finished) {
894                         unsigned long long s_pos = seek_pos;
895                         unsigned long long s_dts = seek_pos_dts;
896                         unsigned long long pts = av_get_pts_from_frame(context->iFormatCtx, in_frame);
897
898                         for (i = 0; i < context->num_proxy_sizes; i++) {
899                                 add_to_proxy_output_ffmpeg(
900                                         context->proxy_ctx[i], in_frame);
901                         }
902
903                         if (!start_pts_set) {
904                                 start_pts = pts;
905                                 start_pts_set = TRUE;
906                         }
907
908                         frameno = floor((pts - start_pts) *
909                                         pts_time_base * frame_rate + 0.5f);
910
911                         /* decoding starts *always* on I-Frames,
912                          * so: P-Frames won't work, even if all the
913                          * information is in place, when we seek
914                          * to the I-Frame presented *after* the P-Frame,
915                          * but located before the P-Frame within
916                          * the stream */
917
918                         if (pts < seek_pos_pts) {
919                                 s_pos = last_seek_pos;
920                                 s_dts = last_seek_pos_dts;
921                         }
922
923                         for (i = 0; i < context->num_indexers; i++) {
924                                 if (context->tcs_in_use & tc_types[i]) {
925                                         int tc_frameno = frameno;
926
927                                         if (tc_types[i] == IMB_TC_RECORD_RUN_NO_GAPS)
928                                                 tc_frameno = frameno_gapless;
929
930                                         IMB_index_builder_proc_frame(
931                                                 context->indexer[i],
932                                                 next_packet.data,
933                                                 next_packet.size,
934                                                 tc_frameno,
935                                                 s_pos, s_dts, pts);
936                                 }
937                         }
938
939                         frameno_gapless++;
940                 }
941                 av_free_packet(&next_packet);
942         }
943
944         av_free(in_frame);
945
946         return 1;
947 }
948
949 #endif
950
951 /* ----------------------------------------------------------------------
952  * - internal AVI (fallback) rebuilder
953  * ---------------------------------------------------------------------- */
954
955 typedef struct FallbackIndexBuilderContext {
956         int anim_type;
957
958         struct anim *anim;
959         AviMovie *proxy_ctx[IMB_PROXY_MAX_SLOT];
960         IMB_Proxy_Size proxy_sizes_in_use;
961 } FallbackIndexBuilderContext;
962
963 static AviMovie *alloc_proxy_output_avi(
964         struct anim *anim, char *filename, int width, int height,
965         int quality)
966 {
967         int x, y;
968         AviFormat format;
969         double framerate;
970         AviMovie *avi;
971         short frs_sec = 25;      /* it doesn't really matter for proxies,
972                                   * but sane defaults help anyways...*/
973         float frs_sec_base = 1.0;
974
975         IMB_anim_get_fps(anim, &frs_sec, &frs_sec_base);
976         
977         x = width;
978         y = height;
979
980         framerate = (double) frs_sec / (double) frs_sec_base;
981         
982         avi = MEM_mallocN(sizeof(AviMovie), "avimovie");
983
984         format = AVI_FORMAT_MJPEG;
985
986         if (AVI_open_compress(filename, avi, 1, format) != AVI_ERROR_NONE) {
987                 MEM_freeN(avi);
988                 return NULL;
989         }
990                         
991         AVI_set_compress_option(avi, AVI_OPTION_TYPE_MAIN, 0, AVI_OPTION_WIDTH, &x);
992         AVI_set_compress_option(avi, AVI_OPTION_TYPE_MAIN, 0, AVI_OPTION_HEIGHT, &y);
993         AVI_set_compress_option(avi, AVI_OPTION_TYPE_MAIN, 0, AVI_OPTION_QUALITY, &quality);
994         AVI_set_compress_option(avi, AVI_OPTION_TYPE_MAIN, 0, AVI_OPTION_FRAMERATE, &framerate);
995
996         avi->interlace = 0;
997         avi->odd_fields = 0;
998
999         return avi;
1000 }
1001
1002 static IndexBuildContext *index_fallback_create_context(struct anim *anim, IMB_Timecode_Type UNUSED(tcs_in_use),
1003                                                         IMB_Proxy_Size proxy_sizes_in_use, int quality)
1004 {
1005         FallbackIndexBuilderContext *context;
1006         int i;
1007
1008         /* since timecode indices only work with ffmpeg right now,
1009          * don't know a sensible fallback here...
1010          *
1011          * so no proxies, no game to play...
1012          */
1013         if (proxy_sizes_in_use == IMB_PROXY_NONE) {
1014                 return NULL;
1015         }
1016
1017         context = MEM_callocN(sizeof(FallbackIndexBuilderContext), "fallback index builder context");
1018
1019         context->anim = anim;
1020         context->proxy_sizes_in_use = proxy_sizes_in_use;
1021
1022         memset(context->proxy_ctx, 0, sizeof(context->proxy_ctx));
1023
1024         for (i = 0; i < IMB_PROXY_MAX_SLOT; i++) {
1025                 if (context->proxy_sizes_in_use & proxy_sizes[i]) {
1026                         char fname[FILE_MAX];
1027
1028                         get_proxy_filename(anim, proxy_sizes[i], fname, TRUE);
1029                         BLI_make_existing_file(fname);
1030
1031                         context->proxy_ctx[i] = alloc_proxy_output_avi(anim, fname,
1032                                                                        anim->x * proxy_fac[i], anim->y * proxy_fac[i], quality);
1033                 }
1034         }
1035
1036         return (IndexBuildContext *)context;
1037 }
1038
1039 static void index_rebuild_fallback_finish(FallbackIndexBuilderContext *context, int stop)
1040 {
1041         struct anim *anim = context->anim;
1042         char fname[FILE_MAX];
1043         char fname_tmp[FILE_MAX];
1044         int i;
1045
1046         for (i = 0; i < IMB_PROXY_MAX_SLOT; i++) {
1047                 if (context->proxy_sizes_in_use & proxy_sizes[i]) {
1048                         AVI_close_compress(context->proxy_ctx[i]);
1049                         MEM_freeN(context->proxy_ctx[i]);
1050
1051                         get_proxy_filename(anim, proxy_sizes[i], fname_tmp, TRUE);
1052                         get_proxy_filename(anim, proxy_sizes[i], fname, FALSE);
1053
1054                         if (stop) {
1055                                 unlink(fname_tmp);
1056                         }
1057                         else {
1058                                 unlink(fname);
1059                                 rename(fname_tmp, fname);
1060                         }
1061                 }
1062         }
1063 }
1064
1065 static void index_rebuild_fallback(FallbackIndexBuilderContext *context,
1066                                    short *stop, short *do_update, float *progress)
1067 {
1068         int cnt = IMB_anim_get_duration(context->anim, IMB_TC_NONE);
1069         int i, pos;
1070         struct anim *anim = context->anim;
1071
1072         for (pos = 0; pos < cnt; pos++) {
1073                 struct ImBuf *ibuf = IMB_anim_absolute(anim, pos, IMB_TC_NONE, IMB_PROXY_NONE);
1074                 struct ImBuf *tmp_ibuf = IMB_dupImBuf(ibuf);
1075                 float next_progress = (float) pos / (float) cnt;
1076
1077                 if (*progress != next_progress) {
1078                         *progress = next_progress;
1079                         *do_update = TRUE;
1080                 }
1081                 
1082                 if (*stop) {
1083                         break;
1084                 }
1085
1086                 IMB_flipy(tmp_ibuf);
1087
1088                 for (i = 0; i < IMB_PROXY_MAX_SLOT; i++) {
1089                         if (context->proxy_sizes_in_use & proxy_sizes[i]) {
1090                                 int x = anim->x * proxy_fac[i];
1091                                 int y = anim->y * proxy_fac[i];
1092
1093                                 struct ImBuf *s_ibuf = IMB_dupImBuf(tmp_ibuf);
1094
1095                                 IMB_scalefastImBuf(s_ibuf, x, y);
1096
1097                                 IMB_convert_rgba_to_abgr(s_ibuf);
1098         
1099                                 AVI_write_frame(context->proxy_ctx[i], pos,
1100                                                 AVI_FORMAT_RGB32,
1101                                                 s_ibuf->rect, x * y * 4);
1102
1103                                 /* note that libavi free's the buffer... */
1104                                 s_ibuf->rect = NULL;
1105
1106                                 IMB_freeImBuf(s_ibuf);
1107                         }
1108                 }
1109
1110                 IMB_freeImBuf(tmp_ibuf);
1111                 IMB_freeImBuf(ibuf);
1112         }
1113 }
1114
1115 /* ----------------------------------------------------------------------
1116  * - public API
1117  * ---------------------------------------------------------------------- */
1118
1119 IndexBuildContext *IMB_anim_index_rebuild_context(struct anim *anim, IMB_Timecode_Type tcs_in_use,
1120                                                   IMB_Proxy_Size proxy_sizes_in_use, int quality)
1121 {
1122         IndexBuildContext *context = NULL;
1123
1124         switch (anim->curtype) {
1125 #ifdef WITH_FFMPEG
1126                 case ANIM_FFMPEG:
1127                         context = index_ffmpeg_create_context(anim, tcs_in_use, proxy_sizes_in_use, quality);
1128                         break;
1129 #endif
1130                 default:
1131                         context = index_fallback_create_context(anim, tcs_in_use, proxy_sizes_in_use, quality);
1132                         break;
1133         }
1134
1135         if (context)
1136                 context->anim_type = anim->curtype;
1137
1138         return context;
1139 }
1140
1141 void IMB_anim_index_rebuild(struct IndexBuildContext *context,
1142                             short *stop, short *do_update, float *progress)
1143 {
1144         switch (context->anim_type) {
1145 #ifdef WITH_FFMPEG
1146                 case ANIM_FFMPEG:
1147                         index_rebuild_ffmpeg((FFmpegIndexBuilderContext *)context, stop, do_update, progress);
1148                         break;
1149 #endif
1150                 default:
1151                         index_rebuild_fallback((FallbackIndexBuilderContext *)context, stop, do_update, progress);
1152                         break;
1153         }
1154 }
1155
1156 void IMB_anim_index_rebuild_finish(IndexBuildContext *context, short stop)
1157 {
1158         switch (context->anim_type) {
1159 #ifdef WITH_FFMPEG
1160                 case ANIM_FFMPEG:
1161                         index_rebuild_ffmpeg_finish((FFmpegIndexBuilderContext *)context, stop);
1162                         break;
1163 #endif
1164                 default:
1165                         index_rebuild_fallback_finish((FallbackIndexBuilderContext *)context, stop);
1166                         break;
1167         }
1168 }
1169
1170
1171 void IMB_free_indices(struct anim *anim)
1172 {
1173         int i;
1174
1175         for (i = 0; i < IMB_PROXY_MAX_SLOT; i++) {
1176                 if (anim->proxy_anim[i]) {
1177                         IMB_close_anim(anim->proxy_anim[i]);
1178                         anim->proxy_anim[i] = NULL;
1179                 }
1180         }
1181
1182         for (i = 0; i < IMB_TC_MAX_SLOT; i++) {
1183                 if (anim->curr_idx[i]) {
1184                         IMB_indexer_close(anim->curr_idx[i]);
1185                         anim->curr_idx[i] = NULL;
1186                 }
1187         }
1188
1189
1190         anim->proxies_tried = 0;
1191         anim->indices_tried = 0;
1192 }
1193
1194 void IMB_anim_set_index_dir(struct anim *anim, const char *dir)
1195 {
1196         if (strcmp(anim->index_dir, dir) == 0) {
1197                 return;
1198         }
1199         BLI_strncpy(anim->index_dir, dir, sizeof(anim->index_dir));
1200
1201         IMB_free_indices(anim);
1202 }
1203
1204 struct anim *IMB_anim_open_proxy(
1205         struct anim *anim, IMB_Proxy_Size preview_size)
1206 {
1207         char fname[FILE_MAX];
1208         int i = IMB_proxy_size_to_array_index(preview_size);
1209
1210         if (anim->proxy_anim[i]) {
1211                 return anim->proxy_anim[i];
1212         }
1213
1214         if (anim->proxies_tried & preview_size) {
1215                 return NULL;
1216         }
1217
1218         get_proxy_filename(anim, preview_size, fname, FALSE);
1219
1220         anim->proxy_anim[i] = IMB_open_anim(fname, 0, 0);
1221         
1222         anim->proxies_tried |= preview_size;
1223
1224         return anim->proxy_anim[i];
1225 }
1226
1227 struct anim_index *IMB_anim_open_index(
1228         struct anim *anim, IMB_Timecode_Type tc)
1229 {
1230         char fname[FILE_MAX];
1231         int i = IMB_timecode_to_array_index(tc);
1232
1233         if (anim->curr_idx[i]) {
1234                 return anim->curr_idx[i];
1235         }
1236
1237         if (anim->indices_tried & tc) {
1238                 return NULL;
1239         }
1240
1241         get_tc_filename(anim, tc, fname);
1242
1243         anim->curr_idx[i] = IMB_indexer_open(fname);
1244         
1245         anim->indices_tried |= tc;
1246
1247         return anim->curr_idx[i];
1248 }
1249
1250 int IMB_anim_index_get_frame_index(struct anim *anim, IMB_Timecode_Type tc,
1251                                    int position)
1252 {
1253         struct anim_index *idx = IMB_anim_open_index(anim, tc);
1254
1255         if (!idx) {
1256                 return position;
1257         }
1258
1259         return IMB_indexer_get_frame_index(idx, position);
1260 }
1261