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