Blender V2.61 - r43446
|
00001 /* 00002 * ***** BEGIN GPL LICENSE BLOCK ***** 00003 * 00004 * This program is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU General Public License 00006 * as published by the Free Software Foundation; either version 2 00007 * of the License, or (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software Foundation, 00016 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 * 00018 * Peter Schlaile <peter [at] schlaile [dot] de> 2011 00019 * 00020 * Contributor(s): none yet. 00021 * 00022 * ***** END GPL LICENSE BLOCK ***** 00023 */ 00024 00025 #include "IMB_indexer.h" 00026 #include "IMB_anim.h" 00027 #include "AVI_avi.h" 00028 #include "imbuf.h" 00029 #include "MEM_guardedalloc.h" 00030 00031 #include "BLI_utildefines.h" 00032 #include "BLI_blenlib.h" 00033 #include "BLI_math_base.h" 00034 00035 #include "MEM_guardedalloc.h" 00036 #include "DNA_userdef_types.h" 00037 #include "BKE_global.h" 00038 #include <stdlib.h> 00039 00040 #ifdef WITH_FFMPEG 00041 00042 #include "ffmpeg_compat.h" 00043 00044 #endif //WITH_FFMPEG 00045 00046 00047 static char magic[] = "BlenMIdx"; 00048 static char temp_ext [] = "_part"; 00049 00050 static int proxy_sizes[] = { IMB_PROXY_25, IMB_PROXY_50, IMB_PROXY_75, 00051 IMB_PROXY_100 }; 00052 static float proxy_fac[] = { 0.25, 0.50, 0.75, 1.00 }; 00053 00054 #ifdef WITH_FFMPEG 00055 static int tc_types[] = { IMB_TC_RECORD_RUN, 00056 IMB_TC_FREE_RUN, 00057 IMB_TC_INTERPOLATED_REC_DATE_FREE_RUN, 00058 IMB_TC_RECORD_RUN_NO_GAPS, 00059 }; 00060 #endif 00061 00062 #define INDEX_FILE_VERSION 1 00063 00064 /* ---------------------------------------------------------------------- 00065 - special indexers 00066 ---------------------------------------------------------------------- 00067 */ 00068 00069 extern void IMB_indexer_dv_new(anim_index_builder * idx); 00070 00071 00072 /* ---------------------------------------------------------------------- 00073 - time code index functions 00074 ---------------------------------------------------------------------- */ 00075 00076 anim_index_builder * IMB_index_builder_create(const char * name) 00077 { 00078 00079 anim_index_builder * rv 00080 = MEM_callocN( sizeof(struct anim_index_builder), 00081 "index builder"); 00082 00083 fprintf(stderr, "Starting work on index: %s\n", name); 00084 00085 BLI_strncpy(rv->name, name, sizeof(rv->name)); 00086 BLI_strncpy(rv->temp_name, name, sizeof(rv->temp_name)); 00087 00088 strcat(rv->temp_name, temp_ext); 00089 00090 BLI_make_existing_file(rv->temp_name); 00091 00092 rv->fp = fopen(rv->temp_name, "wb"); 00093 00094 if (!rv->fp) { 00095 fprintf(stderr, "Couldn't open index target: %s! " 00096 "Index build broken!\n", rv->temp_name); 00097 MEM_freeN(rv); 00098 return NULL; 00099 } 00100 00101 fprintf(rv->fp, "%s%c%.3d", magic, (ENDIAN_ORDER==B_ENDIAN)?'V':'v', 00102 INDEX_FILE_VERSION); 00103 00104 return rv; 00105 } 00106 00107 void IMB_index_builder_add_entry(anim_index_builder * fp, 00108 int frameno, unsigned long long seek_pos, 00109 unsigned long long seek_pos_dts, 00110 unsigned long long pts) 00111 { 00112 fwrite(&frameno, sizeof(int), 1, fp->fp); 00113 fwrite(&seek_pos, sizeof(unsigned long long), 1, fp->fp); 00114 fwrite(&seek_pos_dts, sizeof(unsigned long long), 1, fp->fp); 00115 fwrite(&pts, sizeof(unsigned long long), 1, fp->fp); 00116 } 00117 00118 void IMB_index_builder_proc_frame(anim_index_builder * fp, 00119 unsigned char * buffer, 00120 int data_size, 00121 int frameno, unsigned long long seek_pos, 00122 unsigned long long seek_pos_dts, 00123 unsigned long long pts) 00124 { 00125 if (fp->proc_frame) { 00126 anim_index_entry e; 00127 e.frameno = frameno; 00128 e.seek_pos = seek_pos; 00129 e.seek_pos_dts = seek_pos_dts; 00130 e.pts = pts; 00131 00132 fp->proc_frame(fp, buffer, data_size, &e); 00133 } else { 00134 IMB_index_builder_add_entry(fp, frameno, seek_pos, 00135 seek_pos_dts, pts); 00136 } 00137 } 00138 00139 void IMB_index_builder_finish(anim_index_builder * fp, int rollback) 00140 { 00141 if (fp->delete_priv_data) { 00142 fp->delete_priv_data(fp); 00143 } 00144 00145 fclose(fp->fp); 00146 00147 if (rollback) { 00148 unlink(fp->temp_name); 00149 } else { 00150 rename(fp->temp_name, fp->name); 00151 } 00152 00153 MEM_freeN(fp); 00154 } 00155 00156 struct anim_index * IMB_indexer_open(const char * name) 00157 { 00158 char header[13]; 00159 struct anim_index * idx; 00160 FILE * fp = fopen(name, "rb"); 00161 int i; 00162 00163 if (!fp) { 00164 return NULL; 00165 } 00166 00167 if (fread(header, 12, 1, fp) != 1) { 00168 fclose(fp); 00169 return NULL; 00170 } 00171 00172 header[12] = 0; 00173 00174 if (memcmp(header, magic, 8) != 0) { 00175 fclose(fp); 00176 return NULL; 00177 } 00178 00179 if (atoi(header+9) != INDEX_FILE_VERSION) { 00180 fclose(fp); 00181 return NULL; 00182 } 00183 00184 idx = MEM_callocN( sizeof(struct anim_index), "anim_index"); 00185 00186 BLI_strncpy(idx->name, name, sizeof(idx->name)); 00187 00188 fseek(fp, 0, SEEK_END); 00189 00190 idx->num_entries = (ftell(fp) - 12) 00191 / (sizeof(int) // framepos 00192 + sizeof(unsigned long long) // seek_pos 00193 + sizeof(unsigned long long) // seek_pos_dts 00194 + sizeof(unsigned long long) // pts 00195 ); 00196 00197 fseek(fp, 12, SEEK_SET); 00198 00199 idx->entries = MEM_callocN( sizeof(struct anim_index_entry) 00200 * idx->num_entries, "anim_index_entries"); 00201 00202 for (i = 0; i < idx->num_entries; i++) { 00203 fread(&idx->entries[i].frameno, 00204 sizeof(int), 1, fp); 00205 fread(&idx->entries[i].seek_pos, 00206 sizeof(unsigned long long), 1, fp); 00207 fread(&idx->entries[i].seek_pos_dts, 00208 sizeof(unsigned long long), 1, fp); 00209 fread(&idx->entries[i].pts, 00210 sizeof(unsigned long long), 1, fp); 00211 } 00212 00213 if (((ENDIAN_ORDER == B_ENDIAN) != (header[8] == 'V'))) { 00214 for (i = 0; i < idx->num_entries; i++) { 00215 SWITCH_INT(idx->entries[i].frameno); 00216 SWITCH_INT64(idx->entries[i].seek_pos); 00217 SWITCH_INT64(idx->entries[i].seek_pos_dts); 00218 SWITCH_INT64(idx->entries[i].pts); 00219 } 00220 } 00221 00222 fclose(fp); 00223 00224 return idx; 00225 } 00226 00227 unsigned long long IMB_indexer_get_seek_pos( 00228 struct anim_index * idx, int frame_index) 00229 { 00230 if (frame_index < 0) { 00231 frame_index = 0; 00232 } 00233 if (frame_index >= idx->num_entries) { 00234 frame_index = idx->num_entries - 1; 00235 } 00236 return idx->entries[frame_index].seek_pos; 00237 } 00238 00239 unsigned long long IMB_indexer_get_seek_pos_dts( 00240 struct anim_index * idx, int frame_index) 00241 { 00242 if (frame_index < 0) { 00243 frame_index = 0; 00244 } 00245 if (frame_index >= idx->num_entries) { 00246 frame_index = idx->num_entries - 1; 00247 } 00248 return idx->entries[frame_index].seek_pos_dts; 00249 } 00250 00251 int IMB_indexer_get_frame_index(struct anim_index * idx, int frameno) 00252 { 00253 int len = idx->num_entries; 00254 int half; 00255 int middle; 00256 int first = 0; 00257 00258 /* bsearch (lower bound) the right index */ 00259 00260 while (len > 0) { 00261 half = len >> 1; 00262 middle = first; 00263 00264 middle += half; 00265 00266 if (idx->entries[middle].frameno < frameno) { 00267 first = middle; 00268 ++first; 00269 len = len - half - 1; 00270 } else { 00271 len = half; 00272 } 00273 } 00274 00275 if (first == idx->num_entries) { 00276 return idx->num_entries - 1; 00277 } else { 00278 return first; 00279 } 00280 } 00281 00282 unsigned long long IMB_indexer_get_pts(struct anim_index * idx, 00283 int frame_index) 00284 { 00285 if (frame_index < 0) { 00286 frame_index = 0; 00287 } 00288 if (frame_index >= idx->num_entries) { 00289 frame_index = idx->num_entries - 1; 00290 } 00291 return idx->entries[frame_index].pts; 00292 } 00293 00294 int IMB_indexer_get_duration(struct anim_index * idx) 00295 { 00296 if (idx->num_entries == 0) { 00297 return 0; 00298 } 00299 return idx->entries[idx->num_entries-1].frameno + 1; 00300 } 00301 00302 int IMB_indexer_can_scan(struct anim_index * idx, 00303 int old_frame_index, int new_frame_index) 00304 { 00305 /* makes only sense, if it is the same I-Frame and we are not 00306 trying to run backwards in time... */ 00307 return (IMB_indexer_get_seek_pos(idx, old_frame_index) 00308 == IMB_indexer_get_seek_pos(idx, new_frame_index) && 00309 old_frame_index < new_frame_index); 00310 } 00311 00312 void IMB_indexer_close(struct anim_index * idx) 00313 { 00314 MEM_freeN(idx->entries); 00315 MEM_freeN(idx); 00316 } 00317 00318 int IMB_proxy_size_to_array_index(IMB_Proxy_Size pr_size) 00319 { 00320 switch (pr_size) { 00321 case IMB_PROXY_NONE: /* if we got here, something is broken anyways, 00322 so sane defaults... */ 00323 return 0; 00324 case IMB_PROXY_25: 00325 return 0; 00326 case IMB_PROXY_50: 00327 return 1; 00328 case IMB_PROXY_75: 00329 return 2; 00330 case IMB_PROXY_100: 00331 return 3; 00332 default: 00333 return 0; 00334 }; 00335 return 0; 00336 } 00337 00338 int IMB_timecode_to_array_index(IMB_Timecode_Type tc) 00339 { 00340 switch (tc) { 00341 case IMB_TC_NONE: /* if we got here, something is broken anyways, 00342 so sane defaults... */ 00343 return 0; 00344 case IMB_TC_RECORD_RUN: 00345 return 0; 00346 case IMB_TC_FREE_RUN: 00347 return 1; 00348 case IMB_TC_INTERPOLATED_REC_DATE_FREE_RUN: 00349 return 2; 00350 case IMB_TC_RECORD_RUN_NO_GAPS: 00351 return 3; 00352 default: 00353 return 0; 00354 }; 00355 return 0; 00356 } 00357 00358 00359 /* ---------------------------------------------------------------------- 00360 - rebuild helper functions 00361 ---------------------------------------------------------------------- */ 00362 00363 static void get_index_dir(struct anim * anim, char * index_dir) 00364 { 00365 if (!anim->index_dir[0]) { 00366 char fname[FILE_MAXFILE]; 00367 BLI_strncpy(index_dir, anim->name, FILE_MAXDIR); 00368 BLI_splitdirstring(index_dir, fname); 00369 BLI_join_dirfile(index_dir, FILE_MAXDIR, index_dir, "BL_proxy"); 00370 BLI_join_dirfile(index_dir, FILE_MAXDIR, index_dir, fname); 00371 } else { 00372 BLI_strncpy(index_dir, anim->index_dir, FILE_MAXDIR); 00373 } 00374 } 00375 00376 static void get_proxy_filename(struct anim * anim, IMB_Proxy_Size preview_size, 00377 char * fname, int temp) 00378 { 00379 char index_dir[FILE_MAXDIR]; 00380 int i = IMB_proxy_size_to_array_index(preview_size); 00381 00382 char proxy_name[256]; 00383 char proxy_temp_name[256]; 00384 char stream_suffix[20]; 00385 00386 stream_suffix[0] = 0; 00387 00388 if (anim->streamindex > 0) { 00389 BLI_snprintf(stream_suffix, sizeof(stream_suffix), "_st%d", anim->streamindex); 00390 } 00391 00392 BLI_snprintf(proxy_name, sizeof(proxy_name), "proxy_%d%s.avi", 00393 (int) (proxy_fac[i] * 100), stream_suffix); 00394 BLI_snprintf(proxy_temp_name, sizeof(proxy_temp_name), "proxy_%d%s_part.avi", 00395 (int) (proxy_fac[i] * 100), stream_suffix); 00396 00397 get_index_dir(anim, index_dir); 00398 00399 BLI_join_dirfile(fname, FILE_MAXFILE + FILE_MAXDIR, index_dir, 00400 temp ? proxy_temp_name : proxy_name); 00401 } 00402 00403 static void get_tc_filename(struct anim * anim, IMB_Timecode_Type tc, 00404 char * fname) 00405 { 00406 char index_dir[FILE_MAXDIR]; 00407 int i = IMB_timecode_to_array_index(tc); 00408 const char * index_names[] = { 00409 "record_run%s.blen_tc", 00410 "free_run%s.blen_tc", 00411 "interp_free_run%s.blen_tc", 00412 "record_run_no_gaps%s.blen_tc"}; 00413 00414 char stream_suffix[20]; 00415 char index_name[256]; 00416 00417 stream_suffix[0] = 0; 00418 00419 if (anim->streamindex > 0) { 00420 BLI_snprintf(stream_suffix, 20, "_st%d", anim->streamindex); 00421 } 00422 00423 BLI_snprintf(index_name, 256, index_names[i], stream_suffix); 00424 00425 get_index_dir(anim, index_dir); 00426 00427 BLI_join_dirfile(fname, FILE_MAXFILE + FILE_MAXDIR, 00428 index_dir, index_name); 00429 } 00430 00431 /* ---------------------------------------------------------------------- 00432 - ffmpeg rebuilder 00433 ---------------------------------------------------------------------- */ 00434 00435 #ifdef WITH_FFMPEG 00436 00437 struct proxy_output_ctx { 00438 AVFormatContext* of; 00439 AVStream* st; 00440 AVCodecContext* c; 00441 AVCodec* codec; 00442 struct SwsContext * sws_ctx; 00443 AVFrame* frame; 00444 uint8_t* video_buffer; 00445 int video_buffersize; 00446 int cfra; 00447 int proxy_size; 00448 int orig_height; 00449 struct anim * anim; 00450 }; 00451 00452 // work around stupid swscaler 16 bytes alignment bug... 00453 00454 static int round_up(int x, int mod) 00455 { 00456 return x + ((mod - (x % mod)) % mod); 00457 } 00458 00459 static struct proxy_output_ctx * alloc_proxy_output_ffmpeg( 00460 struct anim * anim, 00461 AVStream * st, int proxy_size, int width, int height, 00462 int UNUSED(quality)) 00463 { 00464 struct proxy_output_ctx * rv = MEM_callocN( 00465 sizeof(struct proxy_output_ctx), "alloc_proxy_output"); 00466 00467 char fname[FILE_MAX]; 00468 00469 // JPEG requires this 00470 width = round_up(width, 8); 00471 height = round_up(height, 8); 00472 00473 rv->proxy_size = proxy_size; 00474 rv->anim = anim; 00475 00476 get_proxy_filename(rv->anim, rv->proxy_size, fname, TRUE); 00477 BLI_make_existing_file(fname); 00478 00479 rv->of = avformat_alloc_context(); 00480 rv->of->oformat = av_guess_format("avi", NULL, NULL); 00481 00482 BLI_snprintf(rv->of->filename, sizeof(rv->of->filename), "%s", fname); 00483 00484 fprintf(stderr, "Starting work on proxy: %s\n", rv->of->filename); 00485 00486 rv->st = av_new_stream(rv->of, 0); 00487 rv->c = rv->st->codec; 00488 rv->c->codec_type = AVMEDIA_TYPE_VIDEO; 00489 rv->c->codec_id = CODEC_ID_MJPEG; 00490 rv->c->width = width; 00491 rv->c->height = height; 00492 00493 rv->of->oformat->video_codec = rv->c->codec_id; 00494 rv->codec = avcodec_find_encoder(rv->c->codec_id); 00495 00496 if (!rv->codec) { 00497 fprintf(stderr, "No ffmpeg MJPEG encoder available? " 00498 "Proxy not built!\n"); 00499 av_free(rv->of); 00500 return NULL; 00501 } 00502 00503 if (rv->codec->pix_fmts) { 00504 rv->c->pix_fmt = rv->codec->pix_fmts[0]; 00505 } else { 00506 rv->c->pix_fmt = PIX_FMT_YUVJ420P; 00507 } 00508 00509 rv->c->sample_aspect_ratio 00510 = rv->st->sample_aspect_ratio 00511 = st->codec->sample_aspect_ratio; 00512 00513 rv->c->time_base.den = 25; 00514 rv->c->time_base.num = 1; 00515 rv->st->time_base = rv->c->time_base; 00516 00517 if (rv->of->flags & AVFMT_GLOBALHEADER) { 00518 rv->c->flags |= CODEC_FLAG_GLOBAL_HEADER; 00519 } 00520 00521 if (av_set_parameters(rv->of, NULL) < 0) { 00522 fprintf(stderr, "Couldn't set output parameters? " 00523 "Proxy not built!\n"); 00524 av_free(rv->of); 00525 return 0; 00526 } 00527 00528 if (avio_open(&rv->of->pb, fname, AVIO_FLAG_WRITE) < 0) { 00529 fprintf(stderr, "Couldn't open outputfile! " 00530 "Proxy not built!\n"); 00531 av_free(rv->of); 00532 return 0; 00533 } 00534 00535 avcodec_open(rv->c, rv->codec); 00536 00537 rv->video_buffersize = 2000000; 00538 rv->video_buffer = (uint8_t*)MEM_mallocN( 00539 rv->video_buffersize, "FFMPEG video buffer"); 00540 00541 rv->orig_height = st->codec->height; 00542 00543 if (st->codec->width != width || st->codec->height != height || 00544 st->codec->pix_fmt != rv->c->pix_fmt) 00545 { 00546 rv->frame = avcodec_alloc_frame(); 00547 avpicture_fill((AVPicture*) rv->frame, 00548 MEM_mallocN(avpicture_get_size( 00549 rv->c->pix_fmt, 00550 round_up(width, 16), height), 00551 "alloc proxy output frame"), 00552 rv->c->pix_fmt, round_up(width, 16), height); 00553 00554 rv->sws_ctx = sws_getContext( 00555 st->codec->width, 00556 st->codec->height, 00557 st->codec->pix_fmt, 00558 width, height, 00559 rv->c->pix_fmt, 00560 SWS_FAST_BILINEAR | SWS_PRINT_INFO, 00561 NULL, NULL, NULL); 00562 } 00563 00564 av_write_header(rv->of); 00565 00566 return rv; 00567 } 00568 00569 static int add_to_proxy_output_ffmpeg( 00570 struct proxy_output_ctx * ctx, AVFrame * frame) 00571 { 00572 int outsize = 0; 00573 00574 if (!ctx) { 00575 return 0; 00576 } 00577 00578 if ( ctx->sws_ctx && frame && 00579 (frame->data[0] || frame->data[1] || 00580 frame->data[2] || frame->data[3])) 00581 { 00582 sws_scale(ctx->sws_ctx, (const uint8_t * const*) frame->data, 00583 frame->linesize, 0, ctx->orig_height, 00584 ctx->frame->data, ctx->frame->linesize); 00585 } 00586 00587 frame = ctx->sws_ctx ? (frame ? ctx->frame : 0) : frame; 00588 00589 if (frame) { 00590 frame->pts = ctx->cfra++; 00591 } 00592 00593 outsize = avcodec_encode_video( 00594 ctx->c, ctx->video_buffer, ctx->video_buffersize, 00595 frame); 00596 00597 if (outsize < 0) { 00598 fprintf(stderr, "Error encoding proxy frame %d for '%s'\n", 00599 ctx->cfra - 1, ctx->of->filename); 00600 return 0; 00601 } 00602 00603 if (outsize != 0) { 00604 AVPacket packet; 00605 av_init_packet(&packet); 00606 00607 if (ctx->c->coded_frame->pts != AV_NOPTS_VALUE) { 00608 packet.pts = av_rescale_q(ctx->c->coded_frame->pts, 00609 ctx->c->time_base, 00610 ctx->st->time_base); 00611 } 00612 if (ctx->c->coded_frame->key_frame) 00613 packet.flags |= AV_PKT_FLAG_KEY; 00614 00615 packet.stream_index = ctx->st->index; 00616 packet.data = ctx->video_buffer; 00617 packet.size = outsize; 00618 00619 if (av_interleaved_write_frame(ctx->of, &packet) != 0) { 00620 fprintf(stderr, "Error writing proxy frame %d " 00621 "into '%s'\n", ctx->cfra - 1, 00622 ctx->of->filename); 00623 return 0; 00624 } 00625 00626 return 1; 00627 } else { 00628 return 0; 00629 } 00630 } 00631 00632 static void free_proxy_output_ffmpeg(struct proxy_output_ctx * ctx, 00633 int rollback) 00634 { 00635 int i; 00636 char fname[FILE_MAX]; 00637 char fname_tmp[FILE_MAX]; 00638 00639 if (!ctx) { 00640 return; 00641 } 00642 00643 if (!rollback) { 00644 while (add_to_proxy_output_ffmpeg(ctx, NULL)) ; 00645 } 00646 00647 avcodec_flush_buffers(ctx->c); 00648 00649 av_write_trailer(ctx->of); 00650 00651 avcodec_close(ctx->c); 00652 00653 for (i = 0; i < ctx->of->nb_streams; i++) { 00654 if (&ctx->of->streams[i]) { 00655 av_freep(&ctx->of->streams[i]); 00656 } 00657 } 00658 00659 if (ctx->of->oformat) { 00660 if (!(ctx->of->oformat->flags & AVFMT_NOFILE)) { 00661 avio_close(ctx->of->pb); 00662 } 00663 } 00664 av_free(ctx->of); 00665 00666 MEM_freeN(ctx->video_buffer); 00667 00668 if (ctx->sws_ctx) { 00669 sws_freeContext(ctx->sws_ctx); 00670 00671 MEM_freeN(ctx->frame->data[0]); 00672 av_free(ctx->frame); 00673 } 00674 00675 get_proxy_filename(ctx->anim, ctx->proxy_size, 00676 fname_tmp, TRUE); 00677 00678 if (rollback) { 00679 unlink(fname_tmp); 00680 } else { 00681 get_proxy_filename(ctx->anim, ctx->proxy_size, 00682 fname, FALSE); 00683 rename(fname_tmp, fname); 00684 } 00685 00686 MEM_freeN(ctx); 00687 } 00688 00689 00690 static int index_rebuild_ffmpeg(struct anim * anim, 00691 IMB_Timecode_Type tcs_in_use, 00692 IMB_Proxy_Size proxy_sizes_in_use, 00693 int quality, 00694 short *stop, short *do_update, 00695 float *progress) 00696 { 00697 int i, videoStream; 00698 unsigned long long seek_pos = 0; 00699 unsigned long long last_seek_pos = 0; 00700 unsigned long long seek_pos_dts = 0; 00701 unsigned long long seek_pos_pts = 0; 00702 unsigned long long last_seek_pos_dts = 0; 00703 unsigned long long start_pts = 0; 00704 double frame_rate; 00705 double pts_time_base; 00706 int frameno = 0, frameno_gapless = 0; 00707 int start_pts_set = FALSE; 00708 00709 AVFormatContext *iFormatCtx; 00710 AVCodecContext *iCodecCtx; 00711 AVCodec *iCodec; 00712 AVStream *iStream; 00713 AVFrame* in_frame = 0; 00714 AVPacket next_packet; 00715 int streamcount; 00716 00717 struct proxy_output_ctx * proxy_ctx[IMB_PROXY_MAX_SLOT]; 00718 anim_index_builder * indexer [IMB_TC_MAX_SLOT]; 00719 00720 int num_proxy_sizes = IMB_PROXY_MAX_SLOT; 00721 int num_indexers = IMB_TC_MAX_SLOT; 00722 uint64_t stream_size; 00723 00724 memset(proxy_ctx, 0, sizeof(proxy_ctx)); 00725 memset(indexer, 0, sizeof(indexer)); 00726 00727 if(av_open_input_file(&iFormatCtx, anim->name, NULL, 0, NULL) != 0) { 00728 return 0; 00729 } 00730 00731 if (av_find_stream_info(iFormatCtx) < 0) { 00732 av_close_input_file(iFormatCtx); 00733 return 0; 00734 } 00735 00736 streamcount = anim->streamindex; 00737 00738 /* Find the video stream */ 00739 videoStream = -1; 00740 for (i = 0; i < iFormatCtx->nb_streams; i++) 00741 if(iFormatCtx->streams[i]->codec->codec_type 00742 == AVMEDIA_TYPE_VIDEO) { 00743 if (streamcount > 0) { 00744 streamcount--; 00745 continue; 00746 } 00747 videoStream = i; 00748 break; 00749 } 00750 00751 if (videoStream == -1) { 00752 av_close_input_file(iFormatCtx); 00753 return 0; 00754 } 00755 00756 iStream = iFormatCtx->streams[videoStream]; 00757 iCodecCtx = iStream->codec; 00758 00759 iCodec = avcodec_find_decoder(iCodecCtx->codec_id); 00760 00761 if (iCodec == NULL) { 00762 av_close_input_file(iFormatCtx); 00763 return 0; 00764 } 00765 00766 iCodecCtx->workaround_bugs = 1; 00767 00768 if (avcodec_open(iCodecCtx, iCodec) < 0) { 00769 av_close_input_file(iFormatCtx); 00770 return 0; 00771 } 00772 00773 in_frame = avcodec_alloc_frame(); 00774 00775 stream_size = avio_size(iFormatCtx->pb); 00776 00777 for (i = 0; i < num_proxy_sizes; i++) { 00778 if (proxy_sizes_in_use & proxy_sizes[i]) { 00779 proxy_ctx[i] = alloc_proxy_output_ffmpeg( 00780 anim, iStream, proxy_sizes[i], 00781 iCodecCtx->width * proxy_fac[i], 00782 iCodecCtx->height * proxy_fac[i], 00783 quality); 00784 if (!proxy_ctx[i]) { 00785 proxy_sizes_in_use &= ~proxy_sizes[i]; 00786 } 00787 } 00788 } 00789 00790 for (i = 0; i < num_indexers; i++) { 00791 if (tcs_in_use & tc_types[i]) { 00792 char fname[FILE_MAX]; 00793 00794 get_tc_filename(anim, tc_types[i], fname); 00795 00796 indexer[i] = IMB_index_builder_create(fname); 00797 if (!indexer[i]) { 00798 tcs_in_use &= ~tc_types[i]; 00799 } 00800 } 00801 } 00802 00803 frame_rate = av_q2d(iStream->r_frame_rate); 00804 pts_time_base = av_q2d(iStream->time_base); 00805 00806 while(av_read_frame(iFormatCtx, &next_packet) >= 0) { 00807 int frame_finished = 0; 00808 float next_progress = (float)((int)floor(((double) next_packet.pos) * 100 / 00809 ((double) stream_size)+0.5)) / 100; 00810 00811 if (*progress != next_progress) { 00812 *progress = next_progress; 00813 *do_update = 1; 00814 } 00815 00816 if (*stop) { 00817 av_free_packet(&next_packet); 00818 break; 00819 } 00820 00821 if (next_packet.stream_index == videoStream) { 00822 if (next_packet.flags & AV_PKT_FLAG_KEY) { 00823 last_seek_pos = seek_pos; 00824 last_seek_pos_dts = seek_pos_dts; 00825 seek_pos = next_packet.pos; 00826 seek_pos_dts = next_packet.dts; 00827 seek_pos_pts = next_packet.pts; 00828 } 00829 00830 avcodec_decode_video2( 00831 iCodecCtx, in_frame, &frame_finished, 00832 &next_packet); 00833 } 00834 00835 if (frame_finished) { 00836 unsigned long long s_pos = seek_pos; 00837 unsigned long long s_dts = seek_pos_dts; 00838 unsigned long long pts 00839 = av_get_pts_from_frame(iFormatCtx, in_frame); 00840 00841 for (i = 0; i < num_proxy_sizes; i++) { 00842 add_to_proxy_output_ffmpeg( 00843 proxy_ctx[i], in_frame); 00844 } 00845 00846 if (!start_pts_set) { 00847 start_pts = pts; 00848 start_pts_set = TRUE; 00849 } 00850 00851 frameno = floor((pts - start_pts) 00852 * pts_time_base * frame_rate + 0.5f); 00853 00854 /* decoding starts *always* on I-Frames, 00855 so: P-Frames won't work, even if all the 00856 information is in place, when we seek 00857 to the I-Frame presented *after* the P-Frame, 00858 but located before the P-Frame within 00859 the stream */ 00860 00861 if (pts < seek_pos_pts) { 00862 s_pos = last_seek_pos; 00863 s_dts = last_seek_pos_dts; 00864 } 00865 00866 for (i = 0; i < num_indexers; i++) { 00867 if (tcs_in_use & tc_types[i]) { 00868 int tc_frameno = frameno; 00869 00870 if(tc_types[i] == IMB_TC_RECORD_RUN_NO_GAPS) 00871 tc_frameno = frameno_gapless; 00872 00873 IMB_index_builder_proc_frame( 00874 indexer[i], 00875 next_packet.data, 00876 next_packet.size, 00877 tc_frameno, 00878 s_pos, s_dts, pts); 00879 } 00880 } 00881 00882 frameno_gapless++; 00883 } 00884 av_free_packet(&next_packet); 00885 } 00886 00887 for (i = 0; i < num_indexers; i++) { 00888 if (tcs_in_use & tc_types[i]) { 00889 IMB_index_builder_finish(indexer[i], *stop); 00890 } 00891 } 00892 00893 for (i = 0; i < num_proxy_sizes; i++) { 00894 if (proxy_sizes_in_use & proxy_sizes[i]) { 00895 free_proxy_output_ffmpeg(proxy_ctx[i], *stop); 00896 } 00897 } 00898 00899 av_free(in_frame); 00900 00901 return 1; 00902 } 00903 00904 #endif 00905 00906 /* ---------------------------------------------------------------------- 00907 - internal AVI (fallback) rebuilder 00908 ---------------------------------------------------------------------- */ 00909 00910 static AviMovie * alloc_proxy_output_avi( 00911 struct anim * anim, char * filename, int width, int height, 00912 int quality) 00913 { 00914 int x, y; 00915 AviFormat format; 00916 double framerate; 00917 AviMovie * avi; 00918 short frs_sec = 25; /* it doesn't really matter for proxies, 00919 but sane defaults help anyways...*/ 00920 float frs_sec_base = 1.0; 00921 00922 IMB_anim_get_fps(anim, &frs_sec, &frs_sec_base); 00923 00924 x = width; 00925 y = height; 00926 00927 framerate= (double) frs_sec / (double) frs_sec_base; 00928 00929 avi = MEM_mallocN (sizeof(AviMovie), "avimovie"); 00930 00931 format = AVI_FORMAT_MJPEG; 00932 00933 if (AVI_open_compress (filename, avi, 1, format) != AVI_ERROR_NONE) { 00934 MEM_freeN(avi); 00935 return NULL; 00936 } 00937 00938 AVI_set_compress_option (avi, AVI_OPTION_TYPE_MAIN, 0, AVI_OPTION_WIDTH, &x); 00939 AVI_set_compress_option (avi, AVI_OPTION_TYPE_MAIN, 0, AVI_OPTION_HEIGHT, &y); 00940 AVI_set_compress_option (avi, AVI_OPTION_TYPE_MAIN, 0, AVI_OPTION_QUALITY, &quality); 00941 AVI_set_compress_option (avi, AVI_OPTION_TYPE_MAIN, 0, AVI_OPTION_FRAMERATE, &framerate); 00942 00943 avi->interlace= 0; 00944 avi->odd_fields= 0; 00945 00946 return avi; 00947 } 00948 00949 static void index_rebuild_fallback(struct anim * anim, 00950 IMB_Timecode_Type UNUSED(tcs_in_use), 00951 IMB_Proxy_Size proxy_sizes_in_use, 00952 int quality, 00953 short *stop, short *do_update, 00954 float *progress) 00955 { 00956 int cnt = IMB_anim_get_duration(anim, IMB_TC_NONE); 00957 int i, pos; 00958 AviMovie * proxy_ctx[IMB_PROXY_MAX_SLOT]; 00959 char fname[FILE_MAX]; 00960 char fname_tmp[FILE_MAX]; 00961 00962 memset(proxy_ctx, 0, sizeof(proxy_ctx)); 00963 00964 /* since timecode indices only work with ffmpeg right now, 00965 don't know a sensible fallback here... 00966 00967 so no proxies, no game to play... 00968 */ 00969 if (proxy_sizes_in_use == IMB_PROXY_NONE) { 00970 return; 00971 } 00972 00973 for (i = 0; i < IMB_PROXY_MAX_SLOT; i++) { 00974 if (proxy_sizes_in_use & proxy_sizes[i]) { 00975 char fname[FILE_MAX]; 00976 00977 get_proxy_filename(anim, proxy_sizes[i], fname, TRUE); 00978 BLI_make_existing_file(fname); 00979 00980 proxy_ctx[i] = alloc_proxy_output_avi( 00981 anim, fname, 00982 anim->x * proxy_fac[i], 00983 anim->y * proxy_fac[i], 00984 quality); 00985 } 00986 } 00987 00988 for (pos = 0; pos < cnt; pos++) { 00989 struct ImBuf * ibuf = IMB_anim_absolute( 00990 anim, pos, IMB_TC_NONE, IMB_PROXY_NONE); 00991 int next_progress = (int) ((double) pos / (double) cnt); 00992 00993 if (*progress != next_progress) { 00994 *progress = next_progress; 00995 *do_update = 1; 00996 } 00997 00998 if (*stop) { 00999 break; 01000 } 01001 01002 IMB_flipy(ibuf); 01003 01004 for (i = 0; i < IMB_PROXY_MAX_SLOT; i++) { 01005 if (proxy_sizes_in_use & proxy_sizes[i]) { 01006 int x = anim->x * proxy_fac[i]; 01007 int y = anim->y * proxy_fac[i]; 01008 01009 struct ImBuf * s_ibuf = IMB_scalefastImBuf( 01010 ibuf, x, y); 01011 01012 IMB_convert_rgba_to_abgr(s_ibuf); 01013 01014 AVI_write_frame (proxy_ctx[i], pos, 01015 AVI_FORMAT_RGB32, 01016 s_ibuf->rect, x * y * 4); 01017 01018 /* note that libavi free's the buffer... */ 01019 s_ibuf->rect = NULL; 01020 01021 IMB_freeImBuf(s_ibuf); 01022 } 01023 } 01024 } 01025 01026 for (i = 0; i < IMB_PROXY_MAX_SLOT; i++) { 01027 if (proxy_sizes_in_use & proxy_sizes[i]) { 01028 AVI_close_compress (proxy_ctx[i]); 01029 MEM_freeN (proxy_ctx[i]); 01030 01031 get_proxy_filename(anim, proxy_sizes[i], 01032 fname_tmp, TRUE); 01033 get_proxy_filename(anim, proxy_sizes[i], 01034 fname, FALSE); 01035 01036 if (*stop) { 01037 unlink(fname_tmp); 01038 } else { 01039 rename(fname_tmp, fname); 01040 } 01041 } 01042 } 01043 } 01044 01045 /* ---------------------------------------------------------------------- 01046 - public API 01047 ---------------------------------------------------------------------- */ 01048 01049 void IMB_anim_index_rebuild(struct anim * anim, IMB_Timecode_Type tcs_in_use, 01050 IMB_Proxy_Size proxy_sizes_in_use, 01051 int quality, 01052 short *stop, short *do_update, float *progress) 01053 { 01054 switch (anim->curtype) { 01055 #ifdef WITH_FFMPEG 01056 case ANIM_FFMPEG: 01057 index_rebuild_ffmpeg(anim, tcs_in_use, proxy_sizes_in_use, 01058 quality, stop, do_update, progress); 01059 break; 01060 #endif 01061 default: 01062 index_rebuild_fallback(anim, tcs_in_use, proxy_sizes_in_use, 01063 quality, stop, do_update, progress); 01064 break; 01065 } 01066 } 01067 01068 void IMB_free_indices(struct anim * anim) 01069 { 01070 int i; 01071 01072 for (i = 0; i < IMB_PROXY_MAX_SLOT; i++) { 01073 if (anim->proxy_anim[i]) { 01074 IMB_close_anim(anim->proxy_anim[i]); 01075 anim->proxy_anim[i] = NULL; 01076 } 01077 } 01078 01079 for (i = 0; i < IMB_TC_MAX_SLOT; i++) { 01080 if (anim->curr_idx[i]) { 01081 IMB_indexer_close(anim->curr_idx[i]); 01082 anim->curr_idx[i] = NULL; 01083 } 01084 } 01085 01086 01087 anim->proxies_tried = 0; 01088 anim->indices_tried = 0; 01089 } 01090 01091 void IMB_anim_set_index_dir(struct anim * anim, const char * dir) 01092 { 01093 if (strcmp(anim->index_dir, dir) == 0) { 01094 return; 01095 } 01096 BLI_strncpy(anim->index_dir, dir, sizeof(anim->index_dir)); 01097 01098 IMB_free_indices(anim); 01099 } 01100 01101 struct anim * IMB_anim_open_proxy( 01102 struct anim * anim, IMB_Proxy_Size preview_size) 01103 { 01104 char fname[FILE_MAX]; 01105 int i = IMB_proxy_size_to_array_index(preview_size); 01106 01107 if (anim->proxy_anim[i]) { 01108 return anim->proxy_anim[i]; 01109 } 01110 01111 if (anim->proxies_tried & preview_size) { 01112 return NULL; 01113 } 01114 01115 get_proxy_filename(anim, preview_size, fname, FALSE); 01116 01117 anim->proxy_anim[i] = IMB_open_anim(fname, 0, 0); 01118 01119 anim->proxies_tried |= preview_size; 01120 01121 return anim->proxy_anim[i]; 01122 } 01123 01124 struct anim_index * IMB_anim_open_index( 01125 struct anim * anim, IMB_Timecode_Type tc) 01126 { 01127 char fname[FILE_MAX]; 01128 int i = IMB_timecode_to_array_index(tc); 01129 01130 if (anim->curr_idx[i]) { 01131 return anim->curr_idx[i]; 01132 } 01133 01134 if (anim->indices_tried & tc) { 01135 return NULL; 01136 } 01137 01138 get_tc_filename(anim, tc, fname); 01139 01140 anim->curr_idx[i] = IMB_indexer_open(fname); 01141 01142 anim->indices_tried |= tc; 01143 01144 return anim->curr_idx[i]; 01145 } 01146 01147 int IMB_anim_index_get_frame_index(struct anim * anim, IMB_Timecode_Type tc, 01148 int position) 01149 { 01150 struct anim_index * idx = IMB_anim_open_index(anim, tc); 01151 01152 if (!idx) { 01153 return position; 01154 } 01155 01156 return IMB_indexer_get_frame_index(idx, position); 01157 } 01158