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