| 
									
										
										
										
											2020-11-05 13:33:27 +01:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * This program is free software; you can redistribute it and/or | 
					
						
							|  |  |  |  * modify it under the terms of the GNU General Public License | 
					
						
							|  |  |  |  * as published by the Free Software Foundation; either version 2 | 
					
						
							|  |  |  |  * of the License, or (at your option) any later version. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  |  * GNU General Public License for more details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  |  * along with this program; if not, write to the Free Software Foundation, | 
					
						
							|  |  |  |  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. | 
					
						
							|  |  |  |  * All rights reserved. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * - Blender Foundation, 2003-2009 | 
					
						
							|  |  |  |  * - Peter Schlaile <peter [at] schlaile [dot] de> 2005/2006 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** \file
 | 
					
						
							|  |  |  |  * \ingroup bke | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "MEM_guardedalloc.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "DNA_anim_types.h"
 | 
					
						
							|  |  |  | #include "DNA_scene_types.h"
 | 
					
						
							|  |  |  | #include "DNA_sequence_types.h"
 | 
					
						
							|  |  |  | #include "DNA_space_types.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "BLI_fileops.h"
 | 
					
						
							|  |  |  | #include "BLI_listbase.h"
 | 
					
						
							|  |  |  | #include "BLI_path_util.h"
 | 
					
						
							|  |  |  | #include "BLI_string.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef WIN32
 | 
					
						
							|  |  |  | #  include "BLI_winstuff.h"
 | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | #  include <unistd.h>
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "BKE_global.h"
 | 
					
						
							|  |  |  | #include "BKE_image.h"
 | 
					
						
							|  |  |  | #include "BKE_main.h"
 | 
					
						
							|  |  |  | #include "BKE_scene.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "DEG_depsgraph.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "IMB_colormanagement.h"
 | 
					
						
							|  |  |  | #include "IMB_imbuf.h"
 | 
					
						
							|  |  |  | #include "IMB_imbuf_types.h"
 | 
					
						
							|  |  |  | #include "IMB_metadata.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-19 06:44:57 +01:00
										 |  |  | #include "SEQ_proxy.h"
 | 
					
						
							| 
									
										
										
										
											2021-03-16 18:47:23 +01:00
										 |  |  | #include "SEQ_relations.h"
 | 
					
						
							| 
									
										
										
										
											2020-12-19 06:44:57 +01:00
										 |  |  | #include "SEQ_render.h"
 | 
					
						
							| 
									
										
										
										
											2020-11-16 05:02:30 +01:00
										 |  |  | #include "SEQ_sequencer.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "multiview.h"
 | 
					
						
							| 
									
										
										
										
											2020-11-05 13:33:27 +01:00
										 |  |  | #include "proxy.h"
 | 
					
						
							|  |  |  | #include "render.h"
 | 
					
						
							|  |  |  | #include "sequencer.h"
 | 
					
						
							| 
									
										
										
										
											2020-11-16 05:02:30 +01:00
										 |  |  | #include "strip_time.h"
 | 
					
						
							|  |  |  | #include "utils.h"
 | 
					
						
							| 
									
										
										
										
											2020-11-05 13:33:27 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | typedef struct SeqIndexBuildContext { | 
					
						
							|  |  |  |   struct IndexBuildContext *index_context; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   int tc_flags; | 
					
						
							|  |  |  |   int size_flags; | 
					
						
							|  |  |  |   int quality; | 
					
						
							|  |  |  |   bool overwrite; | 
					
						
							|  |  |  |   int view_id; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Main *bmain; | 
					
						
							|  |  |  |   Depsgraph *depsgraph; | 
					
						
							|  |  |  |   Scene *scene; | 
					
						
							|  |  |  |   Sequence *seq, *orig_seq; | 
					
						
							|  |  |  | } SeqIndexBuildContext; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int SEQ_rendersize_to_proxysize(int render_size) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   switch (render_size) { | 
					
						
							|  |  |  |     case SEQ_RENDER_SIZE_PROXY_25: | 
					
						
							|  |  |  |       return IMB_PROXY_25; | 
					
						
							|  |  |  |     case SEQ_RENDER_SIZE_PROXY_50: | 
					
						
							|  |  |  |       return IMB_PROXY_50; | 
					
						
							|  |  |  |     case SEQ_RENDER_SIZE_PROXY_75: | 
					
						
							|  |  |  |       return IMB_PROXY_75; | 
					
						
							|  |  |  |     case SEQ_RENDER_SIZE_PROXY_100: | 
					
						
							|  |  |  |       return IMB_PROXY_100; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return IMB_PROXY_NONE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-05 14:05:25 +01:00
										 |  |  | double SEQ_rendersize_to_scale_factor(int render_size) | 
					
						
							| 
									
										
										
										
											2020-11-05 13:33:27 +01:00
										 |  |  | { | 
					
						
							|  |  |  |   switch (render_size) { | 
					
						
							|  |  |  |     case SEQ_RENDER_SIZE_PROXY_25: | 
					
						
							|  |  |  |       return 0.25; | 
					
						
							|  |  |  |     case SEQ_RENDER_SIZE_PROXY_50: | 
					
						
							|  |  |  |       return 0.50; | 
					
						
							|  |  |  |     case SEQ_RENDER_SIZE_PROXY_75: | 
					
						
							|  |  |  |       return 0.75; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return 1.0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool seq_proxy_get_custom_file_fname(Sequence *seq, char *name, const int view_id) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   char fname[FILE_MAXFILE]; | 
					
						
							|  |  |  |   char suffix[24]; | 
					
						
							|  |  |  |   StripProxy *proxy = seq->strip->proxy; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (proxy == NULL) { | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   BLI_join_dirfile(fname, PROXY_MAXFILE, proxy->dir, proxy->file); | 
					
						
							|  |  |  |   BLI_path_abs(fname, BKE_main_blendfile_path_from_global()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (view_id > 0) { | 
					
						
							|  |  |  |     BLI_snprintf(suffix, sizeof(suffix), "_%d", view_id); | 
					
						
							|  |  |  |     /* TODO(sergey): This will actually append suffix after extension
 | 
					
						
							|  |  |  |      * which is weird but how was originally coded in multi-view branch. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     BLI_snprintf(name, PROXY_MAXFILE, "%s_%s", fname, suffix); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							|  |  |  |     BLI_strncpy(name, fname, PROXY_MAXFILE); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static bool seq_proxy_get_fname(Editing *ed, | 
					
						
							|  |  |  |                                 Sequence *seq, | 
					
						
							| 
									
										
										
										
											2020-11-06 14:10:59 +01:00
										 |  |  |                                 int timeline_frame, | 
					
						
							| 
									
										
										
										
											2020-11-05 13:33:27 +01:00
										 |  |  |                                 eSpaceSeq_Proxy_RenderSize render_size, | 
					
						
							|  |  |  |                                 char *name, | 
					
						
							|  |  |  |                                 const int view_id) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   char dir[PROXY_MAXFILE]; | 
					
						
							|  |  |  |   char suffix[24] = {'\0'}; | 
					
						
							|  |  |  |   StripProxy *proxy = seq->strip->proxy; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (proxy == NULL) { | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* Multi-view suffix. */ | 
					
						
							|  |  |  |   if (view_id > 0) { | 
					
						
							|  |  |  |     BLI_snprintf(suffix, sizeof(suffix), "_%d", view_id); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* Per strip with Custom file situation is handled separately. */ | 
					
						
							|  |  |  |   if (proxy->storage & SEQ_STORAGE_PROXY_CUSTOM_FILE && | 
					
						
							|  |  |  |       ed->proxy_storage != SEQ_EDIT_PROXY_DIR_STORAGE) { | 
					
						
							|  |  |  |     if (seq_proxy_get_custom_file_fname(seq, name, view_id)) { | 
					
						
							|  |  |  |       return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (ed->proxy_storage == SEQ_EDIT_PROXY_DIR_STORAGE) { | 
					
						
							|  |  |  |     /* Per project default. */ | 
					
						
							|  |  |  |     if (ed->proxy_dir[0] == 0) { | 
					
						
							|  |  |  |       BLI_strncpy(dir, "//BL_proxy", sizeof(dir)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { /* Per project with custom dir. */ | 
					
						
							|  |  |  |       BLI_strncpy(dir, ed->proxy_dir, sizeof(dir)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     BLI_path_abs(name, BKE_main_blendfile_path_from_global()); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							|  |  |  |     /* Pre strip with custom dir. */ | 
					
						
							|  |  |  |     if (proxy->storage & SEQ_STORAGE_PROXY_CUSTOM_DIR) { | 
					
						
							|  |  |  |       BLI_strncpy(dir, seq->strip->proxy->dir, sizeof(dir)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { /* Per strip default. */ | 
					
						
							|  |  |  |       BLI_snprintf(dir, PROXY_MAXFILE, "%s/BL_proxy", seq->strip->dir); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* Proxy size number to be used in path. */ | 
					
						
							| 
									
										
										
										
											2020-11-05 14:05:25 +01:00
										 |  |  |   int proxy_size_number = SEQ_rendersize_to_scale_factor(render_size) * 100; | 
					
						
							| 
									
										
										
										
											2020-11-05 13:33:27 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |   BLI_snprintf(name, | 
					
						
							|  |  |  |                PROXY_MAXFILE, | 
					
						
							|  |  |  |                "%s/images/%d/%s_proxy%s", | 
					
						
							|  |  |  |                dir, | 
					
						
							|  |  |  |                proxy_size_number, | 
					
						
							| 
									
										
										
										
											2020-11-06 14:10:59 +01:00
										 |  |  |                SEQ_render_give_stripelem(seq, timeline_frame)->name, | 
					
						
							| 
									
										
										
										
											2020-11-05 13:33:27 +01:00
										 |  |  |                suffix); | 
					
						
							|  |  |  |   BLI_path_abs(name, BKE_main_blendfile_path_from_global()); | 
					
						
							|  |  |  |   strcat(name, ".jpg"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-16 17:59:30 +01:00
										 |  |  | bool SEQ_can_use_proxy(const struct SeqRenderData *context, Sequence *seq, int psize) | 
					
						
							| 
									
										
										
										
											2020-11-05 13:33:27 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-03-16 17:59:30 +01:00
										 |  |  |   if (seq->strip->proxy == NULL || !context->use_proxies) { | 
					
						
							| 
									
										
										
										
											2020-11-05 13:33:27 +01:00
										 |  |  |     return false; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2021-03-16 17:59:30 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-05 13:33:27 +01:00
										 |  |  |   short size_flags = seq->strip->proxy->build_size_flags; | 
					
						
							|  |  |  |   return (seq->flag & SEQ_USE_PROXY) != 0 && psize != IMB_PROXY_NONE && (size_flags & psize) != 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-06 14:10:59 +01:00
										 |  |  | ImBuf *seq_proxy_fetch(const SeqRenderData *context, Sequence *seq, int timeline_frame) | 
					
						
							| 
									
										
										
										
											2020-11-05 13:33:27 +01:00
										 |  |  | { | 
					
						
							|  |  |  |   char name[PROXY_MAXFILE]; | 
					
						
							|  |  |  |   StripProxy *proxy = seq->strip->proxy; | 
					
						
							|  |  |  |   const eSpaceSeq_Proxy_RenderSize psize = context->preview_render_size; | 
					
						
							|  |  |  |   Editing *ed = context->scene->ed; | 
					
						
							|  |  |  |   StripAnim *sanim; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* only use proxies, if they are enabled (even if present!) */ | 
					
						
							| 
									
										
										
										
											2021-03-16 17:59:30 +01:00
										 |  |  |   if (!SEQ_can_use_proxy(context, seq, SEQ_rendersize_to_proxysize(psize))) { | 
					
						
							| 
									
										
										
										
											2020-11-05 13:33:27 +01:00
										 |  |  |     return NULL; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (proxy->storage & SEQ_STORAGE_PROXY_CUSTOM_FILE) { | 
					
						
							| 
									
										
										
										
											2020-11-06 14:10:59 +01:00
										 |  |  |     int frameno = (int)seq_give_frame_index(seq, timeline_frame) + seq->anim_startofs; | 
					
						
							| 
									
										
										
										
											2020-11-05 13:33:27 +01:00
										 |  |  |     if (proxy->anim == NULL) { | 
					
						
							| 
									
										
										
										
											2020-11-06 14:10:59 +01:00
										 |  |  |       if (seq_proxy_get_fname(ed, seq, timeline_frame, psize, name, context->view_id) == 0) { | 
					
						
							| 
									
										
										
										
											2020-11-05 13:33:27 +01:00
										 |  |  |         return NULL; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       proxy->anim = openanim(name, IB_rect, 0, seq->strip->colorspace_settings.name); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (proxy->anim == NULL) { | 
					
						
							|  |  |  |       return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     seq_open_anim_file(context->scene, seq, true); | 
					
						
							|  |  |  |     sanim = seq->anims.first; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     frameno = IMB_anim_index_get_frame_index( | 
					
						
							|  |  |  |         sanim ? sanim->anim : NULL, seq->strip->proxy->tc, frameno); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return IMB_anim_absolute(proxy->anim, frameno, IMB_TC_NONE, IMB_PROXY_NONE); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-06 14:10:59 +01:00
										 |  |  |   if (seq_proxy_get_fname(ed, seq, timeline_frame, psize, name, context->view_id) == 0) { | 
					
						
							| 
									
										
										
										
											2020-11-05 13:33:27 +01:00
										 |  |  |     return NULL; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (BLI_exists(name)) { | 
					
						
							|  |  |  |     ImBuf *ibuf = IMB_loadiffname(name, IB_rect, NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (ibuf) { | 
					
						
							|  |  |  |       seq_imbuf_assign_spaces(context->scene, ibuf); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return ibuf; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void seq_proxy_build_frame(const SeqRenderData *context, | 
					
						
							|  |  |  |                                   SeqRenderState *state, | 
					
						
							|  |  |  |                                   Sequence *seq, | 
					
						
							| 
									
										
										
										
											2020-11-06 14:10:59 +01:00
										 |  |  |                                   int timeline_frame, | 
					
						
							| 
									
										
										
										
											2020-11-05 13:33:27 +01:00
										 |  |  |                                   int proxy_render_size, | 
					
						
							|  |  |  |                                   const bool overwrite) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   char name[PROXY_MAXFILE]; | 
					
						
							|  |  |  |   int quality; | 
					
						
							|  |  |  |   int rectx, recty; | 
					
						
							|  |  |  |   ImBuf *ibuf_tmp, *ibuf; | 
					
						
							|  |  |  |   Editing *ed = context->scene->ed; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-06 14:10:59 +01:00
										 |  |  |   if (!seq_proxy_get_fname(ed, seq, timeline_frame, proxy_render_size, name, context->view_id)) { | 
					
						
							| 
									
										
										
										
											2020-11-05 13:33:27 +01:00
										 |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (!overwrite && BLI_exists(name)) { | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-06 14:10:59 +01:00
										 |  |  |   ibuf_tmp = seq_render_strip(context, state, seq, timeline_frame); | 
					
						
							| 
									
										
										
										
											2020-11-05 13:33:27 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |   rectx = (proxy_render_size * ibuf_tmp->x) / 100; | 
					
						
							|  |  |  |   recty = (proxy_render_size * ibuf_tmp->y) / 100; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (ibuf_tmp->x != rectx || ibuf_tmp->y != recty) { | 
					
						
							|  |  |  |     ibuf = IMB_dupImBuf(ibuf_tmp); | 
					
						
							|  |  |  |     IMB_metadata_copy(ibuf, ibuf_tmp); | 
					
						
							|  |  |  |     IMB_freeImBuf(ibuf_tmp); | 
					
						
							|  |  |  |     IMB_scalefastImBuf(ibuf, (short)rectx, (short)recty); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							|  |  |  |     ibuf = ibuf_tmp; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* depth = 32 is intentionally left in, otherwise ALPHA channels
 | 
					
						
							|  |  |  |    * won't work... */ | 
					
						
							|  |  |  |   quality = seq->strip->proxy->quality; | 
					
						
							|  |  |  |   ibuf->ftype = IMB_FTYPE_JPG; | 
					
						
							|  |  |  |   ibuf->foptions.quality = quality; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* unsupported feature only confuses other s/w */ | 
					
						
							|  |  |  |   if (ibuf->planes == 32) { | 
					
						
							|  |  |  |     ibuf->planes = 24; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   BLI_make_existing_file(name); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-11 16:14:05 +11:00
										 |  |  |   const bool ok = IMB_saveiff(ibuf, name, IB_rect | IB_zbuf | IB_zbuffloat); | 
					
						
							|  |  |  |   if (ok == false) { | 
					
						
							| 
									
										
										
										
											2020-11-05 13:33:27 +01:00
										 |  |  |     perror(name); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   IMB_freeImBuf(ibuf); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * Returns whether the file this context would read from even exist, | 
					
						
							|  |  |  |  * if not, don't create the context | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static bool seq_proxy_multiview_context_invalid(Sequence *seq, Scene *scene, const int view_id) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if ((scene->r.scemode & R_MULTIVIEW) == 0) { | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ((seq->type == SEQ_TYPE_IMAGE) && (seq->views_format == R_IMF_VIEWS_INDIVIDUAL)) { | 
					
						
							|  |  |  |     static char prefix[FILE_MAX]; | 
					
						
							|  |  |  |     static const char *ext = NULL; | 
					
						
							|  |  |  |     char str[FILE_MAX]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (view_id == 0) { | 
					
						
							|  |  |  |       char path[FILE_MAX]; | 
					
						
							|  |  |  |       BLI_join_dirfile(path, sizeof(path), seq->strip->dir, seq->strip->stripdata->name); | 
					
						
							|  |  |  |       BLI_path_abs(path, BKE_main_blendfile_path_from_global()); | 
					
						
							|  |  |  |       BKE_scene_multiview_view_prefix_get(scene, path, prefix, &ext); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |       prefix[0] = '\0'; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (prefix[0] == '\0') { | 
					
						
							|  |  |  |       return view_id != 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     seq_multiview_name(scene, view_id, prefix, ext, str, FILE_MAX); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (BLI_access(str, R_OK) == 0) { | 
					
						
							|  |  |  |       return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return view_id != 0; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * This returns the maximum possible number of required contexts | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static int seq_proxy_context_count(Sequence *seq, Scene *scene) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   int num_views = 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ((scene->r.scemode & R_MULTIVIEW) == 0) { | 
					
						
							|  |  |  |     return 1; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   switch (seq->type) { | 
					
						
							|  |  |  |     case SEQ_TYPE_MOVIE: { | 
					
						
							|  |  |  |       num_views = BLI_listbase_count(&seq->anims); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     case SEQ_TYPE_IMAGE: { | 
					
						
							|  |  |  |       switch (seq->views_format) { | 
					
						
							|  |  |  |         case R_IMF_VIEWS_INDIVIDUAL: | 
					
						
							|  |  |  |           num_views = BKE_scene_multiview_num_views_get(&scene->r); | 
					
						
							|  |  |  |           break; | 
					
						
							|  |  |  |         case R_IMF_VIEWS_STEREO_3D: | 
					
						
							|  |  |  |           num_views = 2; | 
					
						
							|  |  |  |           break; | 
					
						
							|  |  |  |         case R_IMF_VIEWS_MULTIVIEW: | 
					
						
							|  |  |  |           /* not supported at the moment */ | 
					
						
							|  |  |  |           /* pass through */ | 
					
						
							|  |  |  |         default: | 
					
						
							|  |  |  |           num_views = 1; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return num_views; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-16 18:47:23 +01:00
										 |  |  | static bool seq_proxy_need_rebuild(Sequence *seq, struct anim *anim) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if ((seq->strip->proxy->build_flags & SEQ_PROXY_SKIP_EXISTING) == 0) { | 
					
						
							|  |  |  |     return true; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   IMB_Proxy_Size required_proxies = seq->strip->proxy->build_size_flags; | 
					
						
							|  |  |  |   IMB_Proxy_Size built_proxies = IMB_anim_proxy_get_existing(anim); | 
					
						
							|  |  |  |   return (required_proxies & built_proxies) != required_proxies; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-05 14:05:25 +01:00
										 |  |  | bool SEQ_proxy_rebuild_context(Main *bmain, | 
					
						
							|  |  |  |                                Depsgraph *depsgraph, | 
					
						
							|  |  |  |                                Scene *scene, | 
					
						
							|  |  |  |                                Sequence *seq, | 
					
						
							|  |  |  |                                struct GSet *file_list, | 
					
						
							|  |  |  |                                ListBase *queue) | 
					
						
							| 
									
										
										
										
											2020-11-05 13:33:27 +01:00
										 |  |  | { | 
					
						
							|  |  |  |   SeqIndexBuildContext *context; | 
					
						
							|  |  |  |   Sequence *nseq; | 
					
						
							|  |  |  |   LinkData *link; | 
					
						
							|  |  |  |   int num_files; | 
					
						
							|  |  |  |   int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (!seq->strip || !seq->strip->proxy) { | 
					
						
							|  |  |  |     return true; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (!(seq->flag & SEQ_USE_PROXY)) { | 
					
						
							|  |  |  |     return true; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   num_files = seq_proxy_context_count(seq, scene); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for (i = 0; i < num_files; i++) { | 
					
						
							|  |  |  |     if (seq_proxy_multiview_context_invalid(seq, scene, i)) { | 
					
						
							|  |  |  |       continue; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-16 18:47:23 +01:00
										 |  |  |     /* Check if proxies are already built here, because actually opening anims takes a lot of
 | 
					
						
							|  |  |  |      * time. */ | 
					
						
							|  |  |  |     seq_open_anim_file(scene, seq, false); | 
					
						
							|  |  |  |     StripAnim *sanim = BLI_findlink(&seq->anims, i); | 
					
						
							|  |  |  |     if (sanim->anim && !seq_proxy_need_rebuild(seq, sanim->anim)) { | 
					
						
							|  |  |  |       continue; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     SEQ_relations_sequence_free_anim(seq); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-05 13:33:27 +01:00
										 |  |  |     context = MEM_callocN(sizeof(SeqIndexBuildContext), "seq proxy rebuild context"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-19 05:57:27 +01:00
										 |  |  |     nseq = SEQ_sequence_dupli_recursive(scene, scene, NULL, seq, 0); | 
					
						
							| 
									
										
										
										
											2020-11-05 13:33:27 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     context->tc_flags = nseq->strip->proxy->build_tc_flags; | 
					
						
							|  |  |  |     context->size_flags = nseq->strip->proxy->build_size_flags; | 
					
						
							|  |  |  |     context->quality = nseq->strip->proxy->quality; | 
					
						
							|  |  |  |     context->overwrite = (nseq->strip->proxy->build_flags & SEQ_PROXY_SKIP_EXISTING) == 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     context->bmain = bmain; | 
					
						
							|  |  |  |     context->depsgraph = depsgraph; | 
					
						
							|  |  |  |     context->scene = scene; | 
					
						
							|  |  |  |     context->orig_seq = seq; | 
					
						
							|  |  |  |     context->seq = nseq; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     context->view_id = i; /* only for images */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (nseq->type == SEQ_TYPE_MOVIE) { | 
					
						
							|  |  |  |       seq_open_anim_file(scene, nseq, true); | 
					
						
							|  |  |  |       sanim = BLI_findlink(&nseq->anims, i); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-08 18:51:47 +02:00
										 |  |  |       if (sanim->anim) { | 
					
						
							|  |  |  |         context->index_context = IMB_anim_index_rebuild_context(sanim->anim, | 
					
						
							|  |  |  |                                                                 context->tc_flags, | 
					
						
							|  |  |  |                                                                 context->size_flags, | 
					
						
							|  |  |  |                                                                 context->quality, | 
					
						
							|  |  |  |                                                                 context->overwrite, | 
					
						
							|  |  |  |                                                                 file_list); | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2021-04-08 18:36:55 +02:00
										 |  |  |       if (!context->index_context) { | 
					
						
							|  |  |  |         MEM_freeN(context); | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2020-11-05 13:33:27 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     link = BLI_genericNodeN(context); | 
					
						
							|  |  |  |     BLI_addtail(queue, link); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2021-03-16 18:47:23 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-05 13:33:27 +01:00
										 |  |  |   return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-05 14:05:25 +01:00
										 |  |  | void SEQ_proxy_rebuild(SeqIndexBuildContext *context, | 
					
						
							|  |  |  |                        short *stop, | 
					
						
							|  |  |  |                        short *do_update, | 
					
						
							|  |  |  |                        float *progress) | 
					
						
							| 
									
										
										
										
											2020-11-05 13:33:27 +01:00
										 |  |  | { | 
					
						
							|  |  |  |   const bool overwrite = context->overwrite; | 
					
						
							|  |  |  |   SeqRenderData render_context; | 
					
						
							|  |  |  |   Sequence *seq = context->seq; | 
					
						
							|  |  |  |   Scene *scene = context->scene; | 
					
						
							|  |  |  |   Main *bmain = context->bmain; | 
					
						
							| 
									
										
										
										
											2020-11-06 14:10:59 +01:00
										 |  |  |   int timeline_frame; | 
					
						
							| 
									
										
										
										
											2020-11-05 13:33:27 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (seq->type == SEQ_TYPE_MOVIE) { | 
					
						
							|  |  |  |     if (context->index_context) { | 
					
						
							|  |  |  |       IMB_anim_index_rebuild(context->index_context, stop, do_update, progress); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (!(seq->flag & SEQ_USE_PROXY)) { | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* that's why it is called custom... */ | 
					
						
							|  |  |  |   if (seq->strip->proxy && seq->strip->proxy->storage & SEQ_STORAGE_PROXY_CUSTOM_FILE) { | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* fail safe code */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-05 14:05:25 +01:00
										 |  |  |   SEQ_render_new_render_data(bmain, | 
					
						
							|  |  |  |                              context->depsgraph, | 
					
						
							|  |  |  |                              context->scene, | 
					
						
							|  |  |  |                              roundf((scene->r.size * (float)scene->r.xsch) / 100.0f), | 
					
						
							|  |  |  |                              roundf((scene->r.size * (float)scene->r.ysch) / 100.0f), | 
					
						
							|  |  |  |                              100, | 
					
						
							|  |  |  |                              false, | 
					
						
							|  |  |  |                              &render_context); | 
					
						
							| 
									
										
										
										
											2020-11-05 13:33:27 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |   render_context.skip_cache = true; | 
					
						
							|  |  |  |   render_context.is_proxy_render = true; | 
					
						
							|  |  |  |   render_context.view_id = context->view_id; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   SeqRenderState state; | 
					
						
							|  |  |  |   seq_render_state_init(&state); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-06 14:10:59 +01:00
										 |  |  |   for (timeline_frame = seq->startdisp + seq->startstill; | 
					
						
							|  |  |  |        timeline_frame < seq->enddisp - seq->endstill; | 
					
						
							|  |  |  |        timeline_frame++) { | 
					
						
							| 
									
										
										
										
											2020-11-05 13:33:27 +01:00
										 |  |  |     if (context->size_flags & IMB_PROXY_25) { | 
					
						
							| 
									
										
										
										
											2020-11-06 14:10:59 +01:00
										 |  |  |       seq_proxy_build_frame(&render_context, &state, seq, timeline_frame, 25, overwrite); | 
					
						
							| 
									
										
										
										
											2020-11-05 13:33:27 +01:00
										 |  |  |     } | 
					
						
							|  |  |  |     if (context->size_flags & IMB_PROXY_50) { | 
					
						
							| 
									
										
										
										
											2020-11-06 14:10:59 +01:00
										 |  |  |       seq_proxy_build_frame(&render_context, &state, seq, timeline_frame, 50, overwrite); | 
					
						
							| 
									
										
										
										
											2020-11-05 13:33:27 +01:00
										 |  |  |     } | 
					
						
							|  |  |  |     if (context->size_flags & IMB_PROXY_75) { | 
					
						
							| 
									
										
										
										
											2020-11-06 14:10:59 +01:00
										 |  |  |       seq_proxy_build_frame(&render_context, &state, seq, timeline_frame, 75, overwrite); | 
					
						
							| 
									
										
										
										
											2020-11-05 13:33:27 +01:00
										 |  |  |     } | 
					
						
							|  |  |  |     if (context->size_flags & IMB_PROXY_100) { | 
					
						
							| 
									
										
										
										
											2020-11-06 14:10:59 +01:00
										 |  |  |       seq_proxy_build_frame(&render_context, &state, seq, timeline_frame, 100, overwrite); | 
					
						
							| 
									
										
										
										
											2020-11-05 13:33:27 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-06 14:10:59 +01:00
										 |  |  |     *progress = (float)(timeline_frame - seq->startdisp - seq->startstill) / | 
					
						
							| 
									
										
										
										
											2020-11-05 13:33:27 +01:00
										 |  |  |                 (seq->enddisp - seq->endstill - seq->startdisp - seq->startstill); | 
					
						
							|  |  |  |     *do_update = true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (*stop || G.is_break) { | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-05 14:05:25 +01:00
										 |  |  | void SEQ_proxy_rebuild_finish(SeqIndexBuildContext *context, bool stop) | 
					
						
							| 
									
										
										
										
											2020-11-05 13:33:27 +01:00
										 |  |  | { | 
					
						
							|  |  |  |   if (context->index_context) { | 
					
						
							|  |  |  |     StripAnim *sanim; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (sanim = context->seq->anims.first; sanim; sanim = sanim->next) { | 
					
						
							|  |  |  |       IMB_close_anim_proxies(sanim->anim); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (sanim = context->orig_seq->anims.first; sanim; sanim = sanim->next) { | 
					
						
							|  |  |  |       IMB_close_anim_proxies(sanim->anim); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     IMB_anim_index_rebuild_finish(context->index_context, stop); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   seq_free_sequence_recurse(NULL, context->seq, true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   MEM_freeN(context); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-05 14:05:25 +01:00
										 |  |  | void SEQ_proxy_set(struct Sequence *seq, bool value) | 
					
						
							| 
									
										
										
										
											2020-11-05 13:33:27 +01:00
										 |  |  | { | 
					
						
							|  |  |  |   if (value) { | 
					
						
							|  |  |  |     seq->flag |= SEQ_USE_PROXY; | 
					
						
							|  |  |  |     if (seq->strip->proxy == NULL) { | 
					
						
							|  |  |  |       seq->strip->proxy = MEM_callocN(sizeof(struct StripProxy), "StripProxy"); | 
					
						
							| 
									
										
										
										
											2021-04-14 14:09:27 +02:00
										 |  |  |       seq->strip->proxy->quality = 50; | 
					
						
							| 
									
										
										
										
											2020-11-05 13:33:27 +01:00
										 |  |  |       seq->strip->proxy->build_tc_flags = SEQ_PROXY_TC_ALL; | 
					
						
							|  |  |  |       seq->strip->proxy->build_size_flags = SEQ_PROXY_IMAGE_SIZE_25; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							|  |  |  |     seq->flag &= ~SEQ_USE_PROXY; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2020-11-16 05:02:30 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | void seq_proxy_index_dir_set(struct anim *anim, const char *base_dir) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   char dir[FILE_MAX]; | 
					
						
							|  |  |  |   char fname[FILE_MAXFILE]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   IMB_anim_get_fname(anim, fname, FILE_MAXFILE); | 
					
						
							|  |  |  |   BLI_strncpy(dir, base_dir, sizeof(dir)); | 
					
						
							|  |  |  |   BLI_path_append(dir, sizeof(dir), fname); | 
					
						
							|  |  |  |   IMB_anim_set_index_dir(anim, dir); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void free_proxy_seq(Sequence *seq) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (seq->strip && seq->strip->proxy && seq->strip->proxy->anim) { | 
					
						
							|  |  |  |     IMB_free_anim(seq->strip->proxy->anim); | 
					
						
							|  |  |  |     seq->strip->proxy->anim = NULL; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } |