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