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