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