WIP: FFmpeg: Remove timecode support #108059
|
@ -1123,7 +1123,7 @@ class CLIP_PT_proxy(CLIP_PT_clip_view_panel, Panel):
|
|||
bl_space_type = 'CLIP_EDITOR'
|
||||
bl_region_type = 'UI'
|
||||
bl_category = "Footage"
|
||||
bl_label = "Proxy/Timecode"
|
||||
bl_label = "Proxy"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
def draw_header(self, context):
|
||||
|
@ -1166,14 +1166,7 @@ class CLIP_PT_proxy(CLIP_PT_clip_view_panel, Panel):
|
|||
col.prop(clip.proxy, "directory")
|
||||
|
||||
col.operator(
|
||||
"clip.rebuild_proxy",
|
||||
text="Build Proxy / Timecode" if clip.source == 'MOVIE'
|
||||
else "Build Proxy"
|
||||
)
|
||||
|
||||
if clip.source == 'MOVIE':
|
||||
col2 = col.column()
|
||||
col2.prop(clip.proxy, "timecode", text="Timecode Index")
|
||||
"clip.rebuild_proxy", text="Build Proxy")
|
||||
|
||||
col.separator()
|
||||
|
||||
|
|
|
@ -2233,7 +2233,7 @@ class SEQUENCER_PT_proxy_settings(SequencerButtonsPanel, Panel):
|
|||
|
||||
|
||||
class SEQUENCER_PT_strip_proxy(SequencerButtonsPanel, Panel):
|
||||
bl_label = "Strip Proxy & Timecode"
|
||||
bl_label = "Strip Proxy"
|
||||
bl_category = "Proxy"
|
||||
|
||||
@classmethod
|
||||
|
@ -2287,11 +2287,6 @@ class SEQUENCER_PT_strip_proxy(SequencerButtonsPanel, Panel):
|
|||
col = layout.column()
|
||||
col.prop(proxy, "quality", text="Quality")
|
||||
|
||||
if strip.type == 'MOVIE':
|
||||
col = layout.column()
|
||||
|
||||
col.prop(proxy, "timecode", text="Timecode Index")
|
||||
|
||||
|
||||
class SEQUENCER_PT_strip_cache(SequencerButtonsPanel, Panel):
|
||||
bl_label = "Strip Cache"
|
||||
|
|
|
@ -1584,7 +1584,8 @@ void BKE_image_free_all_textures(Main *bmain)
|
|||
}
|
||||
|
||||
for (tex = static_cast<Tex *>(bmain->textures.first); tex;
|
||||
tex = static_cast<Tex *>(tex->id.next)) {
|
||||
tex = static_cast<Tex *>(tex->id.next))
|
||||
{
|
||||
if (tex->ima) {
|
||||
tex->ima->id.tag |= LIB_TAG_DOIT;
|
||||
}
|
||||
|
@ -2631,7 +2632,7 @@ struct anim *openanim(const char *filepath,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
ibuf = IMB_anim_absolute(anim, 0, IMB_TC_NONE, IMB_PROXY_NONE);
|
||||
ibuf = IMB_anim_absolute(anim, 0, IMB_PROXY_NONE);
|
||||
if (ibuf == nullptr) {
|
||||
if (BLI_exists(filepath)) {
|
||||
printf("not an anim: %s\n", filepath);
|
||||
|
@ -2703,7 +2704,8 @@ static void image_viewer_create_views(const RenderData *rd, Image *ima)
|
|||
}
|
||||
else {
|
||||
for (SceneRenderView *srv = static_cast<SceneRenderView *>(rd->views.first); srv;
|
||||
srv = srv->next) {
|
||||
srv = srv->next)
|
||||
{
|
||||
if (BKE_scene_multiview_is_render_view_active(rd, srv) == false) {
|
||||
continue;
|
||||
}
|
||||
|
@ -3175,7 +3177,8 @@ void BKE_image_signal(Main *bmain, Image *ima, ImageUser *iuser, int signal)
|
|||
else {
|
||||
ImagePackedFile *imapf;
|
||||
for (imapf = static_cast<ImagePackedFile *>(ima->packedfiles.first); imapf;
|
||||
imapf = imapf->next) {
|
||||
imapf = imapf->next)
|
||||
{
|
||||
PackedFile *pf;
|
||||
pf = BKE_packedfile_new(nullptr, imapf->filepath, ID_BLEND_PATH(bmain, &ima->id));
|
||||
if (pf) {
|
||||
|
@ -3706,7 +3709,8 @@ void BKE_image_multiview_index(const Image *ima, ImageUser *iuser)
|
|||
}
|
||||
else {
|
||||
if ((iuser->view < 0) ||
|
||||
(iuser->view >= BLI_listbase_count_at_most(&ima->views, iuser->view + 1))) {
|
||||
(iuser->view >= BLI_listbase_count_at_most(&ima->views, iuser->view + 1)))
|
||||
{
|
||||
iuser->multi_index = iuser->view = 0;
|
||||
}
|
||||
else {
|
||||
|
@ -4052,12 +4056,12 @@ static ImBuf *load_movie_single(Image *ima, ImageUser *iuser, int frame, const i
|
|||
|
||||
/* let's initialize this user */
|
||||
if (ia->anim && iuser && iuser->frames == 0) {
|
||||
iuser->frames = IMB_anim_get_duration(ia->anim, IMB_TC_RECORD_RUN);
|
||||
iuser->frames = IMB_anim_get_duration(ia->anim);
|
||||
}
|
||||
}
|
||||
|
||||
if (ia->anim) {
|
||||
int dur = IMB_anim_get_duration(ia->anim, IMB_TC_RECORD_RUN);
|
||||
int dur = IMB_anim_get_duration(ia->anim);
|
||||
int fra = frame - 1;
|
||||
|
||||
if (fra < 0) {
|
||||
|
@ -4066,7 +4070,7 @@ static ImBuf *load_movie_single(Image *ima, ImageUser *iuser, int frame, const i
|
|||
if (fra > (dur - 1)) {
|
||||
fra = dur - 1;
|
||||
}
|
||||
ibuf = IMB_makeSingleUser(IMB_anim_absolute(ia->anim, fra, IMB_TC_RECORD_RUN, IMB_PROXY_NONE));
|
||||
ibuf = IMB_makeSingleUser(IMB_anim_absolute(ia->anim, fra, IMB_PROXY_NONE));
|
||||
|
||||
if (ibuf) {
|
||||
image_init_after_load(ima, iuser, ibuf);
|
||||
|
|
|
@ -465,15 +465,6 @@ static int rendersize_to_number(int render_size)
|
|||
return 100;
|
||||
}
|
||||
|
||||
static int get_timecode(MovieClip *clip, int flag)
|
||||
{
|
||||
if ((flag & MCLIP_USE_PROXY) == 0) {
|
||||
return IMB_TC_NONE;
|
||||
}
|
||||
|
||||
return clip->proxy.tc;
|
||||
}
|
||||
|
||||
static void get_sequence_filepath(const MovieClip *clip,
|
||||
const int framenr,
|
||||
char filepath[FILE_MAX])
|
||||
|
@ -682,7 +673,7 @@ static void movieclip_open_anim_file(MovieClip *clip)
|
|||
char dir[FILE_MAX];
|
||||
STRNCPY(dir, clip->proxy.dir);
|
||||
BLI_path_abs(dir, BKE_main_blendfile_path_from_global());
|
||||
IMB_anim_set_index_dir(clip->anim, dir);
|
||||
IMB_anim_set_proxy_dir(clip->anim, dir);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -694,7 +685,6 @@ static ImBuf *movieclip_load_movie_file(MovieClip *clip,
|
|||
int flag)
|
||||
{
|
||||
ImBuf *ibuf = NULL;
|
||||
int tc = get_timecode(clip, flag);
|
||||
int proxy = rendersize_to_proxy(user, flag);
|
||||
|
||||
movieclip_open_anim_file(clip);
|
||||
|
@ -702,7 +692,7 @@ static ImBuf *movieclip_load_movie_file(MovieClip *clip,
|
|||
if (clip->anim) {
|
||||
int fra = framenr - clip->start_frame + clip->frame_offset;
|
||||
|
||||
ibuf = IMB_anim_absolute(clip->anim, fra, tc, proxy);
|
||||
ibuf = IMB_anim_absolute(clip->anim, fra, proxy);
|
||||
}
|
||||
|
||||
return ibuf;
|
||||
|
@ -714,7 +704,7 @@ static void movieclip_calc_length(MovieClip *clip)
|
|||
movieclip_open_anim_file(clip);
|
||||
|
||||
if (clip->anim) {
|
||||
clip->len = IMB_anim_get_duration(clip->anim, clip->proxy.tc);
|
||||
clip->len = IMB_anim_get_duration(clip->anim);
|
||||
}
|
||||
}
|
||||
else if (clip->source == MCLIP_SRC_SEQUENCE) {
|
||||
|
|
|
@ -843,9 +843,6 @@ void blo_do_versions_260(FileData *fd, Library *UNUSED(lib), Main *bmain)
|
|||
clip->aspy = 1.0f;
|
||||
}
|
||||
|
||||
clip->proxy.build_tc_flag = IMB_TC_RECORD_RUN | IMB_TC_FREE_RUN |
|
||||
IMB_TC_INTERPOLATED_REC_DATE_FREE_RUN;
|
||||
|
||||
if (clip->proxy.build_size_flag == 0) {
|
||||
clip->proxy.build_size_flag = IMB_PROXY_25;
|
||||
}
|
||||
|
@ -981,8 +978,6 @@ void blo_do_versions_260(FileData *fd, Library *UNUSED(lib), Main *bmain)
|
|||
MovieTracking *tracking = &clip->tracking;
|
||||
MovieTrackingObject *tracking_object = tracking->objects.first;
|
||||
|
||||
clip->proxy.build_tc_flag |= IMB_TC_RECORD_RUN_NO_GAPS;
|
||||
|
||||
if (!tracking->settings.object_distance) {
|
||||
tracking->settings.object_distance = 1.0f;
|
||||
}
|
||||
|
|
|
@ -1173,7 +1173,7 @@ typedef struct ProxyBuildJob {
|
|||
MovieClip *clip;
|
||||
int clip_flag;
|
||||
bool stop;
|
||||
struct IndexBuildContext *index_context;
|
||||
struct ProxyBuildContext *index_context;
|
||||
} ProxyJob;
|
||||
|
||||
static void proxy_freejob(void *pjv)
|
||||
|
@ -1228,7 +1228,7 @@ static void do_movie_proxy(void *pjv,
|
|||
struct MovieDistortion *distortion = nullptr;
|
||||
|
||||
if (pj->index_context) {
|
||||
IMB_anim_index_rebuild(pj->index_context, stop, do_update, progress);
|
||||
IMB_anim_proxy_rebuild(pj->index_context, stop, do_update, progress);
|
||||
}
|
||||
|
||||
if (!build_undistort_count) {
|
||||
|
@ -1497,7 +1497,7 @@ static void proxy_endjob(void *pjv)
|
|||
}
|
||||
|
||||
if (pj->index_context) {
|
||||
IMB_anim_index_rebuild_finish(pj->index_context, pj->stop);
|
||||
IMB_anim_proxy_rebuild_finish(pj->index_context, pj->stop);
|
||||
}
|
||||
|
||||
if (pj->clip->source == MCLIP_SRC_MOVIE) {
|
||||
|
@ -1539,9 +1539,7 @@ static int clip_rebuild_proxy_exec(bContext *C, wmOperator * /*op*/)
|
|||
pj->clip_flag = clip->flag & MCLIP_TIMECODE_FLAGS;
|
||||
|
||||
if (clip->anim) {
|
||||
pj->index_context = IMB_anim_index_rebuild_context(
|
||||
clip->anim,
|
||||
IMB_Timecode_Type(clip->proxy.build_tc_flag),
|
||||
pj->index_context = IMB_anim_proxy_rebuild_context(clip->anim,
|
||||
IMB_Proxy_Size(clip->proxy.build_size_flag),
|
||||
clip->proxy.quality,
|
||||
true,
|
||||
|
@ -1564,9 +1562,9 @@ static int clip_rebuild_proxy_exec(bContext *C, wmOperator * /*op*/)
|
|||
void CLIP_OT_rebuild_proxy(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "Rebuild Proxy and Timecode Indices";
|
||||
ot->name = "Rebuild Proxy";
|
||||
ot->idname = "CLIP_OT_rebuild_proxy";
|
||||
ot->description = "Rebuild all selected proxies and timecode indices in the background";
|
||||
ot->description = "Rebuild all selected proxies in the background";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec = clip_rebuild_proxy_exec;
|
||||
|
|
|
@ -1243,7 +1243,7 @@ void uiTemplateImageInfo(uiLayout *layout, bContext *C, Image *ima, ImageUser *i
|
|||
if (ima->source == IMA_SRC_MOVIE && BKE_image_has_anim(ima)) {
|
||||
struct anim *anim = ((ImageAnim *)ima->anims.first)->anim;
|
||||
if (anim) {
|
||||
duration = IMB_anim_get_duration(anim, IMB_TC_RECORD_RUN);
|
||||
duration = IMB_anim_get_duration(anim);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1705,7 +1705,7 @@ static int image_match_len_exec(bContext *C, wmOperator *UNUSED(op))
|
|||
if (!anim) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
iuser->frames = IMB_anim_get_duration(anim, IMB_TC_RECORD_RUN);
|
||||
iuser->frames = IMB_anim_get_duration(anim);
|
||||
BKE_image_user_frame_calc(ima, iuser, scene->r.cfra);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
|
|
|
@ -538,7 +538,7 @@ static void prefetch_data_fn(void *custom_data,
|
|||
struct anim *anim = openanim(job_data->path, IB_rect, 0, colorspace);
|
||||
|
||||
if (anim != NULL) {
|
||||
g_drop_coords.strip_len = IMB_anim_get_duration(anim, IMB_TC_NONE);
|
||||
g_drop_coords.strip_len = IMB_anim_get_duration(anim);
|
||||
short frs_sec;
|
||||
float frs_sec_base;
|
||||
if (IMB_anim_get_fps(anim, &frs_sec, &frs_sec_base, true)) {
|
||||
|
|
|
@ -124,7 +124,7 @@ static int sequencer_rebuild_proxy_exec(bContext *C, wmOperator *UNUSED(op))
|
|||
SEQ_proxy_rebuild_context(bmain, depsgraph, scene, seq, file_list, &queue, false);
|
||||
|
||||
for (link = queue.first; link; link = link->next) {
|
||||
struct SeqIndexBuildContext *context = link->data;
|
||||
struct SeqProxyBuildContext *context = link->data;
|
||||
SEQ_proxy_rebuild(context, &stop, &do_update, &progress);
|
||||
SEQ_proxy_rebuild_finish(context, false);
|
||||
}
|
||||
|
@ -140,9 +140,9 @@ static int sequencer_rebuild_proxy_exec(bContext *C, wmOperator *UNUSED(op))
|
|||
void SEQUENCER_OT_rebuild_proxy(wmOperatorType *ot)
|
||||
{
|
||||
/* Identifiers. */
|
||||
ot->name = "Rebuild Proxy and Timecode Indices";
|
||||
ot->name = "Rebuild Proxis";
|
||||
ot->idname = "SEQUENCER_OT_rebuild_proxy";
|
||||
ot->description = "Rebuild all selected proxies and timecode indices using the job system";
|
||||
ot->description = "Rebuild all selected proxies using the job system";
|
||||
|
||||
/* Api callbacks. */
|
||||
ot->invoke = sequencer_rebuild_proxy_invoke;
|
||||
|
|
|
@ -36,7 +36,7 @@ set(SRC
|
|||
intern/format_targa.cc
|
||||
intern/format_tiff.cc
|
||||
intern/imageprocess.cc
|
||||
intern/indexer.cc
|
||||
intern/proxy.cc
|
||||
intern/iris.cc
|
||||
intern/jpeg.cc
|
||||
intern/metadata.cc
|
||||
|
@ -67,7 +67,7 @@ set(SRC
|
|||
intern/IMB_colormanagement_intern.h
|
||||
intern/IMB_filetype.h
|
||||
intern/IMB_filter.h
|
||||
intern/IMB_indexer.h
|
||||
intern/IMB_proxy.h
|
||||
intern/imbuf.h
|
||||
|
||||
# orphan include
|
||||
|
|
|
@ -293,30 +293,6 @@ void IMB_rectblend_threaded(struct ImBuf *dbuf,
|
|||
* \attention Defined in indexer.c
|
||||
*/
|
||||
|
||||
typedef enum IMB_Timecode_Type {
|
||||
/** Don't use time-code files at all. */
|
||||
IMB_TC_NONE = 0,
|
||||
/**
|
||||
* Use images in the order as they are recorded
|
||||
* (currently, this is the only one implemented
|
||||
* and is a sane default).
|
||||
*/
|
||||
IMB_TC_RECORD_RUN = 1,
|
||||
/**
|
||||
* Use global timestamp written by recording
|
||||
* device (prosumer camcorders e.g. can do that).
|
||||
*/
|
||||
IMB_TC_FREE_RUN = 2,
|
||||
/**
|
||||
* Interpolate a global timestamp using the
|
||||
* record date and time written by recording
|
||||
* device (*every* consumer camcorder can do that).
|
||||
*/
|
||||
IMB_TC_INTERPOLATED_REC_DATE_FREE_RUN = 4,
|
||||
IMB_TC_RECORD_RUN_NO_GAPS = 8,
|
||||
IMB_TC_MAX_SLOT = 4,
|
||||
} IMB_Timecode_Type;
|
||||
|
||||
typedef enum IMB_Proxy_Size {
|
||||
IMB_PROXY_NONE = 0,
|
||||
IMB_PROXY_25 = 1,
|
||||
|
@ -334,20 +310,19 @@ typedef enum eIMBInterpolationFilterMode {
|
|||
/**
|
||||
* Defaults to BL_proxy within the directory of the animation.
|
||||
*/
|
||||
void IMB_anim_set_index_dir(struct anim *anim, const char *dir);
|
||||
void IMB_anim_set_proxy_dir(struct anim *anim, const char *dir);
|
||||
void IMB_anim_get_filename(struct anim *anim, char *filename, int filename_maxncpy);
|
||||
|
||||
int IMB_anim_index_get_frame_index(struct anim *anim, IMB_Timecode_Type tc, int position);
|
||||
int IMB_anim_index_get_frame_index(struct anim *anim, int position);
|
||||
|
||||
int IMB_anim_proxy_get_existing(struct anim *anim);
|
||||
|
||||
struct IndexBuildContext;
|
||||
struct ProxyBuildContext;
|
||||
|
||||
/**
|
||||
* Prepare context for proxies/time-codes builder
|
||||
*/
|
||||
struct IndexBuildContext *IMB_anim_index_rebuild_context(struct anim *anim,
|
||||
IMB_Timecode_Type tcs_in_use,
|
||||
struct ProxyBuildContext *IMB_anim_proxy_rebuild_context(struct anim *anim,
|
||||
int proxy_sizes_in_use,
|
||||
int quality,
|
||||
const bool overwrite,
|
||||
|
@ -357,7 +332,7 @@ struct IndexBuildContext *IMB_anim_index_rebuild_context(struct anim *anim,
|
|||
/**
|
||||
* Will rebuild all used indices and proxies at once.
|
||||
*/
|
||||
void IMB_anim_index_rebuild(struct IndexBuildContext *context,
|
||||
void IMB_anim_proxy_rebuild(struct ProxyBuildContext *context,
|
||||
bool *stop,
|
||||
bool *do_update,
|
||||
float *progress);
|
||||
|
@ -365,12 +340,12 @@ void IMB_anim_index_rebuild(struct IndexBuildContext *context,
|
|||
/**
|
||||
* Finish rebuilding proxies/time-codes and free temporary contexts used.
|
||||
*/
|
||||
void IMB_anim_index_rebuild_finish(struct IndexBuildContext *context, bool stop);
|
||||
void IMB_anim_proxy_rebuild_finish(struct ProxyBuildContext *context, bool stop);
|
||||
|
||||
/**
|
||||
* Return the length (in frames) of the given \a anim.
|
||||
*/
|
||||
int IMB_anim_get_duration(struct anim *anim, IMB_Timecode_Type tc);
|
||||
int IMB_anim_get_duration(struct anim *anim);
|
||||
|
||||
/**
|
||||
* Return the encoded start offset (in seconds) of the given \a anim.
|
||||
|
@ -410,7 +385,6 @@ bool IMB_get_gop_decode_time(struct anim *anim);
|
|||
|
||||
struct ImBuf *IMB_anim_absolute(struct anim *anim,
|
||||
int position,
|
||||
IMB_Timecode_Type tc /* = 1 = IMB_TC_RECORD_RUN */,
|
||||
IMB_Proxy_Size preview_size /* = 0 = IMB_PROXY_NONE */);
|
||||
|
||||
/**
|
||||
|
|
|
@ -135,7 +135,6 @@ struct anim {
|
|||
int indices_tried;
|
||||
|
||||
struct anim *proxy_anim[IMB_PROXY_MAX_SLOT];
|
||||
struct anim_index *curr_idx[IMB_TC_MAX_SLOT];
|
||||
|
||||
char colorspace[64];
|
||||
char suffix[64]; /* MAX_NAME - multiview */
|
||||
|
|
|
@ -1,104 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#pragma once
|
||||
|
||||
/** \file
|
||||
* \ingroup imbuf
|
||||
*/
|
||||
|
||||
#ifdef WIN32
|
||||
# include <io.h>
|
||||
#endif
|
||||
|
||||
#include "IMB_anim.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
/*
|
||||
* separate animation index files to solve the following problems:
|
||||
*
|
||||
* a) different time-codes within one file (like DTS/PTS, Time-code-Track,
|
||||
* "implicit" time-codes within DV-files and HDV-files etc.)
|
||||
* b) seeking difficulties within FFMPEG for files with timestamp holes
|
||||
* c) broken files that miss several frames / have varying frame-rates
|
||||
* d) use proxies accordingly
|
||||
*
|
||||
* ... we need index files, that provide us with
|
||||
*
|
||||
* the binary(!) position, where we have to seek into the file *and*
|
||||
* the continuous frame number (ignoring the holes) starting from the
|
||||
* beginning of the file, so that we know, which proxy frame to serve.
|
||||
*
|
||||
* This index has to be only built once for a file and is written into
|
||||
* the BL_proxy directory structure for later reuse in different blender files.
|
||||
*/
|
||||
|
||||
typedef struct anim_index_entry {
|
||||
int frameno;
|
||||
uint64_t seek_pos;
|
||||
uint64_t seek_pos_pts;
|
||||
uint64_t seek_pos_dts;
|
||||
uint64_t pts;
|
||||
} anim_index_entry;
|
||||
|
||||
struct anim_index {
|
||||
char filepath[1024];
|
||||
|
||||
int num_entries;
|
||||
struct anim_index_entry *entries;
|
||||
};
|
||||
|
||||
struct anim_index_builder;
|
||||
|
||||
typedef struct anim_index_builder {
|
||||
FILE *fp;
|
||||
char filepath[FILE_MAX];
|
||||
char filepath_temp[FILE_MAX];
|
||||
|
||||
void *private_data;
|
||||
|
||||
void (*delete_priv_data)(struct anim_index_builder *idx);
|
||||
void (*proc_frame)(struct anim_index_builder *idx,
|
||||
unsigned char *buffer,
|
||||
int data_size,
|
||||
struct anim_index_entry *entry);
|
||||
} anim_index_builder;
|
||||
|
||||
anim_index_builder *IMB_index_builder_create(const char *filepath);
|
||||
void IMB_index_builder_add_entry(anim_index_builder *fp,
|
||||
int frameno,
|
||||
uint64_t seek_pos,
|
||||
uint64_t seek_pos_pts,
|
||||
uint64_t seek_pos_dts,
|
||||
uint64_t pts);
|
||||
|
||||
void IMB_index_builder_proc_frame(anim_index_builder *fp,
|
||||
unsigned char *buffer,
|
||||
int data_size,
|
||||
int frameno,
|
||||
uint64_t seek_pos,
|
||||
uint64_t seek_pos_pts,
|
||||
uint64_t seek_pos_dts,
|
||||
uint64_t pts);
|
||||
|
||||
void IMB_index_builder_finish(anim_index_builder *fp, int rollback);
|
||||
|
||||
struct anim_index *IMB_indexer_open(const char *name);
|
||||
uint64_t IMB_indexer_get_seek_pos(struct anim_index *idx, int frame_index);
|
||||
uint64_t IMB_indexer_get_seek_pos_pts(struct anim_index *idx, int frame_index);
|
||||
uint64_t IMB_indexer_get_seek_pos_dts(struct anim_index *idx, int frame_index);
|
||||
|
||||
int IMB_indexer_get_frame_index(struct anim_index *idx, int frameno);
|
||||
uint64_t IMB_indexer_get_pts(struct anim_index *idx, int frame_index);
|
||||
int IMB_indexer_get_duration(struct anim_index *idx);
|
||||
|
||||
int IMB_indexer_can_scan(struct anim_index *idx, int old_frame_index, int new_frame_index);
|
||||
|
||||
void IMB_indexer_close(struct anim_index *idx);
|
||||
|
||||
void IMB_free_indices(struct anim *anim);
|
||||
|
||||
struct anim *IMB_anim_open_proxy(struct anim *anim, IMB_Proxy_Size preview_size);
|
||||
struct anim_index *IMB_anim_open_index(struct anim *anim, IMB_Timecode_Type tc);
|
||||
|
||||
int IMB_proxy_size_to_array_index(IMB_Proxy_Size pr_size);
|
||||
int IMB_timecode_to_array_index(IMB_Timecode_Type tc);
|
|
@ -0,0 +1,18 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#pragma once
|
||||
|
||||
/** \file
|
||||
* \ingroup imbuf
|
||||
*/
|
||||
|
||||
#ifdef WIN32
|
||||
# include <io.h>
|
||||
#endif
|
||||
|
||||
#include "IMB_anim.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
void IMB_free_proxies(struct anim *anim);
|
||||
struct anim *IMB_anim_open_proxy(struct anim *anim, IMB_Proxy_Size preview_size);
|
|
@ -57,8 +57,8 @@
|
|||
#include "IMB_colormanagement_intern.h"
|
||||
|
||||
#include "IMB_anim.h"
|
||||
#include "IMB_indexer.h"
|
||||
#include "IMB_metadata.h"
|
||||
#include "IMB_proxy.h"
|
||||
|
||||
#ifdef WITH_FFMPEG
|
||||
# include "BKE_global.h" /* ENDIAN_ORDER */
|
||||
|
@ -213,7 +213,7 @@ void IMB_free_anim(struct anim *anim)
|
|||
#ifdef WITH_FFMPEG
|
||||
free_anim_ffmpeg(anim);
|
||||
#endif
|
||||
IMB_free_indices(anim);
|
||||
IMB_free_proxies(anim);
|
||||
IMB_metadata_free(anim->metadata);
|
||||
|
||||
MEM_freeN(anim);
|
||||
|
@ -234,7 +234,7 @@ void IMB_close_anim_proxies(struct anim *anim)
|
|||
return;
|
||||
}
|
||||
|
||||
IMB_free_indices(anim);
|
||||
IMB_free_proxies(anim);
|
||||
}
|
||||
|
||||
struct IDProperty *IMB_anim_load_metadata(struct anim *anim)
|
||||
|
@ -1125,17 +1125,10 @@ static int64_t ffmpeg_get_seek_pts(struct anim *anim, int64_t pts_to_search)
|
|||
/* This gives us an estimate of which pts our requested frame will have.
|
||||
* Note that this might be off a bit in certain video files, but it should still be close enough.
|
||||
*/
|
||||
static int64_t ffmpeg_get_pts_to_search(struct anim *anim,
|
||||
struct anim_index *tc_index,
|
||||
int position)
|
||||
static int64_t ffmpeg_get_pts_to_search(struct anim *anim, int position)
|
||||
{
|
||||
int64_t pts_to_search;
|
||||
|
||||
if (tc_index) {
|
||||
int new_frame_index = IMB_indexer_get_frame_index(tc_index, position);
|
||||
pts_to_search = IMB_indexer_get_pts(tc_index, new_frame_index);
|
||||
}
|
||||
else {
|
||||
AVStream *v_st = anim->pFormatCtx->streams[anim->videoStream];
|
||||
int64_t start_pts = v_st->start_time;
|
||||
|
||||
|
@ -1144,7 +1137,7 @@ static int64_t ffmpeg_get_pts_to_search(struct anim *anim,
|
|||
if (start_pts != AV_NOPTS_VALUE) {
|
||||
pts_to_search += start_pts;
|
||||
}
|
||||
}
|
||||
|
||||
return pts_to_search;
|
||||
}
|
||||
|
||||
|
@ -1297,53 +1290,15 @@ static bool ffmpeg_seek_buffers_need_flushing(struct anim *anim, int position, i
|
|||
}
|
||||
|
||||
/* Seek to last necessary key frame. */
|
||||
static int ffmpeg_seek_to_key_frame(struct anim *anim,
|
||||
int position,
|
||||
struct anim_index *tc_index,
|
||||
int64_t pts_to_search)
|
||||
static int ffmpeg_seek_to_key_frame(struct anim *anim, int position, int64_t pts_to_search)
|
||||
{
|
||||
int64_t seek_pos;
|
||||
int ret;
|
||||
|
||||
if (tc_index) {
|
||||
/* We can use timestamps generated from our indexer to seek. */
|
||||
int new_frame_index = IMB_indexer_get_frame_index(tc_index, position);
|
||||
int old_frame_index = IMB_indexer_get_frame_index(tc_index, anim->cur_position);
|
||||
|
||||
if (IMB_indexer_can_scan(tc_index, old_frame_index, new_frame_index)) {
|
||||
/* No need to seek, return early. */
|
||||
return 0;
|
||||
}
|
||||
uint64_t pts;
|
||||
uint64_t dts;
|
||||
|
||||
seek_pos = IMB_indexer_get_seek_pos(tc_index, new_frame_index);
|
||||
pts = IMB_indexer_get_seek_pos_pts(tc_index, new_frame_index);
|
||||
dts = IMB_indexer_get_seek_pos_dts(tc_index, new_frame_index);
|
||||
|
||||
anim->cur_key_frame_pts = timestamp_from_pts_or_dts(pts, dts);
|
||||
|
||||
av_log(anim->pFormatCtx, AV_LOG_DEBUG, "TC INDEX seek seek_pos = %" PRId64 "\n", seek_pos);
|
||||
av_log(anim->pFormatCtx, AV_LOG_DEBUG, "TC INDEX seek pts = %" PRIu64 "\n", pts);
|
||||
av_log(anim->pFormatCtx, AV_LOG_DEBUG, "TC INDEX seek dts = %" PRIu64 "\n", dts);
|
||||
|
||||
if (ffmpeg_seek_by_byte(anim->pFormatCtx)) {
|
||||
av_log(anim->pFormatCtx, AV_LOG_DEBUG, "... using BYTE seek_pos\n");
|
||||
|
||||
ret = av_seek_frame(anim->pFormatCtx, -1, seek_pos, AVSEEK_FLAG_BYTE);
|
||||
}
|
||||
else {
|
||||
av_log(anim->pFormatCtx, AV_LOG_DEBUG, "... using PTS seek_pos\n");
|
||||
ret = av_seek_frame(
|
||||
anim->pFormatCtx, anim->videoStream, anim->cur_key_frame_pts, AVSEEK_FLAG_BACKWARD);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* We have to manually seek with ffmpeg to get to the key frame we want to start decoding from.
|
||||
*/
|
||||
seek_pos = ffmpeg_get_seek_pts(anim, pts_to_search);
|
||||
av_log(
|
||||
anim->pFormatCtx, AV_LOG_DEBUG, "NO INDEX final seek seek_pos = %" PRId64 "\n", seek_pos);
|
||||
av_log(anim->pFormatCtx, AV_LOG_DEBUG, "NO INDEX final seek seek_pos = %" PRId64 "\n", seek_pos);
|
||||
|
||||
AVFormatContext *format_ctx = anim->pFormatCtx;
|
||||
|
||||
|
@ -1352,16 +1307,13 @@ static int ffmpeg_seek_to_key_frame(struct anim *anim,
|
|||
}
|
||||
else {
|
||||
ret = ffmpeg_generic_seek_workaround(anim, &seek_pos, pts_to_search);
|
||||
av_log(anim->pFormatCtx,
|
||||
AV_LOG_DEBUG,
|
||||
"Adjusted final seek seek_pos = %" PRId64 "\n",
|
||||
seek_pos);
|
||||
av_log(
|
||||
anim->pFormatCtx, AV_LOG_DEBUG, "Adjusted final seek seek_pos = %" PRId64 "\n", seek_pos);
|
||||
}
|
||||
|
||||
if (ret <= 0 && !ffmpeg_seek_buffers_need_flushing(anim, position, seek_pos)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
av_log(anim->pFormatCtx,
|
||||
|
@ -1396,7 +1348,7 @@ static bool ffmpeg_must_seek(struct anim *anim, int position)
|
|||
return must_seek;
|
||||
}
|
||||
|
||||
static ImBuf *ffmpeg_fetchibuf(struct anim *anim, int position, IMB_Timecode_Type tc)
|
||||
static ImBuf *ffmpeg_fetchibuf(struct anim *anim, int position)
|
||||
{
|
||||
if (anim == nullptr) {
|
||||
return nullptr;
|
||||
|
@ -1404,8 +1356,7 @@ static ImBuf *ffmpeg_fetchibuf(struct anim *anim, int position, IMB_Timecode_Typ
|
|||
|
||||
av_log(anim->pFormatCtx, AV_LOG_DEBUG, "FETCH: seek_pos=%d\n", position);
|
||||
|
||||
struct anim_index *tc_index = IMB_anim_open_index(anim, tc);
|
||||
int64_t pts_to_search = ffmpeg_get_pts_to_search(anim, tc_index, position);
|
||||
int64_t pts_to_search = ffmpeg_get_pts_to_search(anim, position);
|
||||
AVStream *v_st = anim->pFormatCtx->streams[anim->videoStream];
|
||||
double frame_rate = av_q2d(v_st->r_frame_rate);
|
||||
double pts_time_base = av_q2d(v_st->time_base);
|
||||
|
@ -1421,7 +1372,7 @@ static ImBuf *ffmpeg_fetchibuf(struct anim *anim, int position, IMB_Timecode_Typ
|
|||
start_pts);
|
||||
|
||||
if (ffmpeg_must_seek(anim, position)) {
|
||||
ffmpeg_seek_to_key_frame(anim, position, tc_index, pts_to_search);
|
||||
ffmpeg_seek_to_key_frame(anim, position, pts_to_search);
|
||||
}
|
||||
|
||||
ffmpeg_decode_video_frame_scan(anim, pts_to_search);
|
||||
|
@ -1575,19 +1526,16 @@ struct ImBuf *IMB_anim_previewframe(struct anim *anim)
|
|||
struct ImBuf *ibuf = nullptr;
|
||||
int position = 0;
|
||||
|
||||
ibuf = IMB_anim_absolute(anim, 0, IMB_TC_NONE, IMB_PROXY_NONE);
|
||||
ibuf = IMB_anim_absolute(anim, 0, IMB_PROXY_NONE);
|
||||
if (ibuf) {
|
||||
IMB_freeImBuf(ibuf);
|
||||
position = anim->duration_in_frames / 2;
|
||||
ibuf = IMB_anim_absolute(anim, position, IMB_TC_NONE, IMB_PROXY_NONE);
|
||||
ibuf = IMB_anim_absolute(anim, position, IMB_PROXY_NONE);
|
||||
}
|
||||
return ibuf;
|
||||
}
|
||||
|
||||
struct ImBuf *IMB_anim_absolute(struct anim *anim,
|
||||
int position,
|
||||
IMB_Timecode_Type tc,
|
||||
IMB_Proxy_Size preview_size)
|
||||
struct ImBuf *IMB_anim_absolute(struct anim *anim, int position, IMB_Proxy_Size preview_size)
|
||||
{
|
||||
struct ImBuf *ibuf = nullptr;
|
||||
char head[256], tail[256];
|
||||
|
@ -1618,9 +1566,7 @@ struct ImBuf *IMB_anim_absolute(struct anim *anim,
|
|||
struct anim *proxy = IMB_anim_open_proxy(anim, preview_size);
|
||||
|
||||
if (proxy) {
|
||||
position = IMB_anim_index_get_frame_index(anim, tc, position);
|
||||
|
||||
return IMB_anim_absolute(proxy, position, IMB_TC_NONE, IMB_PROXY_NONE);
|
||||
return IMB_anim_absolute(proxy, position, IMB_PROXY_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1651,7 +1597,7 @@ struct ImBuf *IMB_anim_absolute(struct anim *anim,
|
|||
#endif
|
||||
#ifdef WITH_FFMPEG
|
||||
case ANIM_FFMPEG:
|
||||
ibuf = ffmpeg_fetchibuf(anim, position, tc);
|
||||
ibuf = ffmpeg_fetchibuf(anim, position);
|
||||
if (ibuf) {
|
||||
anim->cur_position = position;
|
||||
}
|
||||
|
@ -1671,19 +1617,9 @@ struct ImBuf *IMB_anim_absolute(struct anim *anim,
|
|||
|
||||
/***/
|
||||
|
||||
int IMB_anim_get_duration(struct anim *anim, IMB_Timecode_Type tc)
|
||||
int IMB_anim_get_duration(struct anim *anim)
|
||||
{
|
||||
struct anim_index *idx;
|
||||
if (tc == IMB_TC_NONE) {
|
||||
return anim->duration_in_frames;
|
||||
}
|
||||
|
||||
idx = IMB_anim_open_index(anim, tc);
|
||||
if (!idx) {
|
||||
return anim->duration_in_frames;
|
||||
}
|
||||
|
||||
return IMB_indexer_get_duration(idx);
|
||||
}
|
||||
|
||||
double IMD_anim_get_offset(struct anim *anim)
|
||||
|
|
|
@ -27,7 +27,6 @@
|
|||
|
||||
#include "IMB_anim.h"
|
||||
#include "IMB_imbuf.h"
|
||||
#include "IMB_indexer.h"
|
||||
#include "imbuf.h"
|
||||
|
||||
#ifdef WITH_AVI
|
||||
|
@ -48,294 +47,6 @@ static const IMB_Proxy_Size proxy_sizes[] = {
|
|||
IMB_PROXY_25, IMB_PROXY_50, IMB_PROXY_75, IMB_PROXY_100};
|
||||
static const float proxy_fac[] = {0.25, 0.50, 0.75, 1.00};
|
||||
|
||||
#ifdef WITH_FFMPEG
|
||||
static IMB_Timecode_Type tc_types[] = {
|
||||
IMB_TC_RECORD_RUN,
|
||||
IMB_TC_FREE_RUN,
|
||||
IMB_TC_INTERPOLATED_REC_DATE_FREE_RUN,
|
||||
IMB_TC_RECORD_RUN_NO_GAPS,
|
||||
};
|
||||
#endif
|
||||
|
||||
#define INDEX_FILE_VERSION 2
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
* - time code index functions
|
||||
* ---------------------------------------------------------------------- */
|
||||
|
||||
anim_index_builder *IMB_index_builder_create(const char *filepath)
|
||||
{
|
||||
|
||||
anim_index_builder *rv = MEM_cnew<anim_index_builder>("index builder");
|
||||
|
||||
fprintf(stderr, "Starting work on index: %s\n", filepath);
|
||||
|
||||
STRNCPY(rv->filepath, filepath);
|
||||
|
||||
STRNCPY(rv->filepath_temp, filepath);
|
||||
BLI_string_join(rv->filepath_temp, sizeof(rv->filepath_temp), filepath, temp_ext);
|
||||
|
||||
BLI_file_ensure_parent_dir_exists(rv->filepath_temp);
|
||||
|
||||
rv->fp = BLI_fopen(rv->filepath_temp, "wb");
|
||||
|
||||
if (!rv->fp) {
|
||||
fprintf(stderr,
|
||||
"Couldn't open index target: %s! "
|
||||
"Index build broken!\n",
|
||||
rv->filepath_temp);
|
||||
MEM_freeN(rv);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
fprintf(rv->fp,
|
||||
"%s%c%.3d",
|
||||
binary_header_str,
|
||||
(ENDIAN_ORDER == B_ENDIAN) ? 'V' : 'v',
|
||||
INDEX_FILE_VERSION);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
void IMB_index_builder_add_entry(anim_index_builder *fp,
|
||||
int frameno,
|
||||
uint64_t seek_pos,
|
||||
uint64_t seek_pos_pts,
|
||||
uint64_t seek_pos_dts,
|
||||
uint64_t pts)
|
||||
{
|
||||
fwrite(&frameno, sizeof(int), 1, fp->fp);
|
||||
fwrite(&seek_pos, sizeof(uint64_t), 1, fp->fp);
|
||||
fwrite(&seek_pos_pts, sizeof(uint64_t), 1, fp->fp);
|
||||
fwrite(&seek_pos_dts, sizeof(uint64_t), 1, fp->fp);
|
||||
fwrite(&pts, sizeof(uint64_t), 1, fp->fp);
|
||||
}
|
||||
|
||||
void IMB_index_builder_proc_frame(anim_index_builder *fp,
|
||||
uchar *buffer,
|
||||
int data_size,
|
||||
int frameno,
|
||||
uint64_t seek_pos,
|
||||
uint64_t seek_pos_pts,
|
||||
uint64_t seek_pos_dts,
|
||||
uint64_t pts)
|
||||
{
|
||||
if (fp->proc_frame) {
|
||||
anim_index_entry e;
|
||||
e.frameno = frameno;
|
||||
e.seek_pos = seek_pos;
|
||||
e.seek_pos_pts = seek_pos_pts;
|
||||
e.seek_pos_dts = seek_pos_dts;
|
||||
e.pts = pts;
|
||||
|
||||
fp->proc_frame(fp, buffer, data_size, &e);
|
||||
}
|
||||
else {
|
||||
IMB_index_builder_add_entry(fp, frameno, seek_pos, seek_pos_pts, seek_pos_dts, pts);
|
||||
}
|
||||
}
|
||||
|
||||
void IMB_index_builder_finish(anim_index_builder *fp, int rollback)
|
||||
{
|
||||
if (fp->delete_priv_data) {
|
||||
fp->delete_priv_data(fp);
|
||||
}
|
||||
|
||||
fclose(fp->fp);
|
||||
|
||||
if (rollback) {
|
||||
unlink(fp->filepath_temp);
|
||||
}
|
||||
else {
|
||||
unlink(fp->filepath);
|
||||
BLI_rename_overwrite(fp->filepath_temp, fp->filepath);
|
||||
}
|
||||
|
||||
MEM_freeN(fp);
|
||||
}
|
||||
|
||||
struct anim_index *IMB_indexer_open(const char *filepath)
|
||||
{
|
||||
char header[13];
|
||||
struct anim_index *idx;
|
||||
FILE *fp = BLI_fopen(filepath, "rb");
|
||||
int i;
|
||||
|
||||
if (!fp) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (fread(header, 12, 1, fp) != 1) {
|
||||
fprintf(stderr, "Couldn't read indexer file: %s\n", filepath);
|
||||
fclose(fp);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
header[12] = 0;
|
||||
|
||||
if (memcmp(header, binary_header_str, 8) != 0) {
|
||||
fprintf(stderr, "Error reading %s: Binary file type string mismatch\n", filepath);
|
||||
fclose(fp);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (atoi(header + 9) != INDEX_FILE_VERSION) {
|
||||
fprintf(stderr, "Error reading %s: File version mismatch\n", filepath);
|
||||
fclose(fp);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
idx = MEM_cnew<anim_index>("anim_index");
|
||||
|
||||
STRNCPY(idx->filepath, filepath);
|
||||
|
||||
fseek(fp, 0, SEEK_END);
|
||||
|
||||
idx->num_entries = (ftell(fp) - 12) / (sizeof(int) + /* framepos */
|
||||
sizeof(uint64_t) + /* seek_pos */
|
||||
sizeof(uint64_t) + /* seek_pos_pts */
|
||||
sizeof(uint64_t) + /* seek_pos_dts */
|
||||
sizeof(uint64_t) /* pts */
|
||||
);
|
||||
|
||||
fseek(fp, 12, SEEK_SET);
|
||||
|
||||
idx->entries = static_cast<anim_index_entry *>(
|
||||
MEM_callocN(sizeof(anim_index_entry) * idx->num_entries, "anim_index_entries"));
|
||||
|
||||
size_t items_read = 0;
|
||||
for (i = 0; i < idx->num_entries; i++) {
|
||||
items_read += fread(&idx->entries[i].frameno, sizeof(int), 1, fp);
|
||||
items_read += fread(&idx->entries[i].seek_pos, sizeof(uint64_t), 1, fp);
|
||||
items_read += fread(&idx->entries[i].seek_pos_pts, sizeof(uint64_t), 1, fp);
|
||||
items_read += fread(&idx->entries[i].seek_pos_dts, sizeof(uint64_t), 1, fp);
|
||||
items_read += fread(&idx->entries[i].pts, sizeof(uint64_t), 1, fp);
|
||||
}
|
||||
|
||||
if (UNLIKELY(items_read != idx->num_entries * 5)) {
|
||||
fprintf(stderr, "Error: Element data size mismatch in: %s\n", filepath);
|
||||
MEM_freeN(idx->entries);
|
||||
MEM_freeN(idx);
|
||||
fclose(fp);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if ((ENDIAN_ORDER == B_ENDIAN) != (header[8] == 'V')) {
|
||||
for (i = 0; i < idx->num_entries; i++) {
|
||||
BLI_endian_switch_int32(&idx->entries[i].frameno);
|
||||
BLI_endian_switch_uint64(&idx->entries[i].seek_pos);
|
||||
BLI_endian_switch_uint64(&idx->entries[i].seek_pos_pts);
|
||||
BLI_endian_switch_uint64(&idx->entries[i].seek_pos_dts);
|
||||
BLI_endian_switch_uint64(&idx->entries[i].pts);
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
uint64_t IMB_indexer_get_seek_pos(struct anim_index *idx, int frame_index)
|
||||
{
|
||||
/* This is hard coded, because our current timecode files return non zero seek position for index
|
||||
* 0. Only when seeking to 0 it is guaranteed, that first packet will be read. */
|
||||
if (frame_index <= 0) {
|
||||
return 0;
|
||||
}
|
||||
if (frame_index >= idx->num_entries) {
|
||||
frame_index = idx->num_entries - 1;
|
||||
}
|
||||
return idx->entries[frame_index].seek_pos;
|
||||
}
|
||||
|
||||
uint64_t IMB_indexer_get_seek_pos_pts(struct anim_index *idx, int frame_index)
|
||||
{
|
||||
if (frame_index < 0) {
|
||||
frame_index = 0;
|
||||
}
|
||||
if (frame_index >= idx->num_entries) {
|
||||
frame_index = idx->num_entries - 1;
|
||||
}
|
||||
return idx->entries[frame_index].seek_pos_pts;
|
||||
}
|
||||
|
||||
uint64_t IMB_indexer_get_seek_pos_dts(struct anim_index *idx, int frame_index)
|
||||
{
|
||||
if (frame_index < 0) {
|
||||
frame_index = 0;
|
||||
}
|
||||
if (frame_index >= idx->num_entries) {
|
||||
frame_index = idx->num_entries - 1;
|
||||
}
|
||||
return idx->entries[frame_index].seek_pos_dts;
|
||||
}
|
||||
|
||||
int IMB_indexer_get_frame_index(struct anim_index *idx, int frameno)
|
||||
{
|
||||
int len = idx->num_entries;
|
||||
int half;
|
||||
int middle;
|
||||
int first = 0;
|
||||
|
||||
/* Binary-search (lower bound) the right index. */
|
||||
|
||||
while (len > 0) {
|
||||
half = len >> 1;
|
||||
middle = first;
|
||||
|
||||
middle += half;
|
||||
|
||||
if (idx->entries[middle].frameno < frameno) {
|
||||
first = middle;
|
||||
first++;
|
||||
len = len - half - 1;
|
||||
}
|
||||
else {
|
||||
len = half;
|
||||
}
|
||||
}
|
||||
|
||||
if (first == idx->num_entries) {
|
||||
return idx->num_entries - 1;
|
||||
}
|
||||
|
||||
return first;
|
||||
}
|
||||
|
||||
uint64_t IMB_indexer_get_pts(struct anim_index *idx, int frame_index)
|
||||
{
|
||||
if (frame_index < 0) {
|
||||
frame_index = 0;
|
||||
}
|
||||
if (frame_index >= idx->num_entries) {
|
||||
frame_index = idx->num_entries - 1;
|
||||
}
|
||||
return idx->entries[frame_index].pts;
|
||||
}
|
||||
|
||||
int IMB_indexer_get_duration(struct anim_index *idx)
|
||||
{
|
||||
if (idx->num_entries == 0) {
|
||||
return 0;
|
||||
}
|
||||
return idx->entries[idx->num_entries - 1].frameno + 1;
|
||||
}
|
||||
|
||||
int IMB_indexer_can_scan(struct anim_index *idx, int old_frame_index, int new_frame_index)
|
||||
{
|
||||
/* makes only sense, if it is the same I-Frame and we are not
|
||||
* trying to run backwards in time... */
|
||||
return (IMB_indexer_get_seek_pos(idx, old_frame_index) ==
|
||||
IMB_indexer_get_seek_pos(idx, new_frame_index) &&
|
||||
old_frame_index < new_frame_index);
|
||||
}
|
||||
|
||||
void IMB_indexer_close(struct anim_index *idx)
|
||||
{
|
||||
MEM_freeN(idx->entries);
|
||||
MEM_freeN(idx);
|
||||
}
|
||||
|
||||
int IMB_proxy_size_to_array_index(IMB_Proxy_Size pr_size)
|
||||
{
|
||||
switch (pr_size) {
|
||||
|
@ -355,30 +66,11 @@ int IMB_proxy_size_to_array_index(IMB_Proxy_Size pr_size)
|
|||
}
|
||||
}
|
||||
|
||||
int IMB_timecode_to_array_index(IMB_Timecode_Type tc)
|
||||
{
|
||||
switch (tc) {
|
||||
case IMB_TC_NONE:
|
||||
return -1;
|
||||
case IMB_TC_RECORD_RUN:
|
||||
return 0;
|
||||
case IMB_TC_FREE_RUN:
|
||||
return 1;
|
||||
case IMB_TC_INTERPOLATED_REC_DATE_FREE_RUN:
|
||||
return 2;
|
||||
case IMB_TC_RECORD_RUN_NO_GAPS:
|
||||
return 3;
|
||||
default:
|
||||
BLI_assert_msg(0, "Unhandled timecode type enum!");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
* - rebuild helper functions
|
||||
* ---------------------------------------------------------------------- */
|
||||
|
||||
static void get_index_dir(struct anim *anim, char *index_dir, size_t index_dir_maxncpy)
|
||||
static void get_proxy_dir(struct anim *anim, char *index_dir, size_t index_dir_maxncpy)
|
||||
{
|
||||
if (!anim->index_dir[0]) {
|
||||
char filename[FILE_MAXFILE];
|
||||
|
@ -418,7 +110,7 @@ static bool get_proxy_filepath(struct anim *anim,
|
|||
|
||||
SNPRINTF(proxy_name, name, int(proxy_fac[i] * 100), stream_suffix, anim->suffix);
|
||||
|
||||
get_index_dir(anim, index_dir, sizeof(index_dir));
|
||||
get_proxy_dir(anim, index_dir, sizeof(index_dir));
|
||||
|
||||
if (BLI_path_ncmp(anim->filepath, index_dir, FILE_MAXDIR) == 0) {
|
||||
return false;
|
||||
|
@ -428,41 +120,11 @@ static bool get_proxy_filepath(struct anim *anim,
|
|||
return true;
|
||||
}
|
||||
|
||||
static void get_tc_filename(struct anim *anim, IMB_Timecode_Type tc, char *filepath)
|
||||
{
|
||||
char index_dir[FILE_MAXDIR];
|
||||
int i = IMB_timecode_to_array_index(tc);
|
||||
|
||||
BLI_assert(i >= 0);
|
||||
|
||||
const char *index_names[] = {
|
||||
"record_run%s%s.blen_tc",
|
||||
"free_run%s%s.blen_tc",
|
||||
"interp_free_run%s%s.blen_tc",
|
||||
"record_run_no_gaps%s%s.blen_tc",
|
||||
};
|
||||
|
||||
char stream_suffix[20];
|
||||
char index_name[256];
|
||||
|
||||
stream_suffix[0] = 0;
|
||||
|
||||
if (anim->streamindex > 0) {
|
||||
SNPRINTF(stream_suffix, "_st%d", anim->streamindex);
|
||||
}
|
||||
|
||||
SNPRINTF(index_name, index_names[i], stream_suffix, anim->suffix);
|
||||
|
||||
get_index_dir(anim, index_dir, sizeof(index_dir));
|
||||
|
||||
BLI_path_join(filepath, FILE_MAXFILE + FILE_MAXDIR, index_dir, index_name);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
* - common rebuilder structures
|
||||
* ---------------------------------------------------------------------- */
|
||||
|
||||
typedef struct IndexBuildContext {
|
||||
typedef struct ProxyBuildContext {
|
||||
int anim_type;
|
||||
} IndexBuildContext;
|
||||
|
||||
|
@ -790,7 +452,7 @@ static void free_proxy_output_ffmpeg(struct proxy_output_ctx *ctx, int rollback)
|
|||
MEM_freeN(ctx);
|
||||
}
|
||||
|
||||
typedef struct FFmpegIndexBuilderContext {
|
||||
typedef struct FFmpegProxyBuilderContext {
|
||||
int anim_type;
|
||||
|
||||
AVFormatContext *iFormatCtx;
|
||||
|
@ -800,12 +462,9 @@ typedef struct FFmpegIndexBuilderContext {
|
|||
int videoStream;
|
||||
|
||||
int num_proxy_sizes;
|
||||
int num_indexers;
|
||||
|
||||
struct proxy_output_ctx *proxy_ctx[IMB_PROXY_MAX_SLOT];
|
||||
anim_index_builder *indexer[IMB_TC_MAX_SLOT];
|
||||
|
||||
int tcs_in_use;
|
||||
int proxy_sizes_in_use;
|
||||
|
||||
uint64_t seek_pos;
|
||||
|
@ -824,26 +483,21 @@ typedef struct FFmpegIndexBuilderContext {
|
|||
bool building_cancelled;
|
||||
} FFmpegIndexBuilderContext;
|
||||
|
||||
static IndexBuildContext *index_ffmpeg_create_context(struct anim *anim,
|
||||
int tcs_in_use,
|
||||
static ProxyBuildContext *proxy_ffmpeg_create_context(struct anim *anim,
|
||||
int proxy_sizes_in_use,
|
||||
int quality,
|
||||
bool build_only_on_bad_performance)
|
||||
{
|
||||
FFmpegIndexBuilderContext *context = MEM_cnew<FFmpegIndexBuilderContext>(
|
||||
FFmpegProxyBuilderContext *context = MEM_cnew<FFmpegProxyBuilderContext>(
|
||||
"FFmpeg index builder context");
|
||||
int num_proxy_sizes = IMB_PROXY_MAX_SLOT;
|
||||
int num_indexers = IMB_TC_MAX_SLOT;
|
||||
int i, streamcount;
|
||||
|
||||
context->tcs_in_use = tcs_in_use;
|
||||
context->proxy_sizes_in_use = proxy_sizes_in_use;
|
||||
context->num_proxy_sizes = IMB_PROXY_MAX_SLOT;
|
||||
context->num_indexers = IMB_TC_MAX_SLOT;
|
||||
context->build_only_on_bad_performance = build_only_on_bad_performance;
|
||||
|
||||
memset(context->proxy_ctx, 0, sizeof(context->proxy_ctx));
|
||||
memset(context->indexer, 0, sizeof(context->indexer));
|
||||
|
||||
if (avformat_open_input(&context->iFormatCtx, anim->filepath, nullptr, nullptr) != 0) {
|
||||
MEM_freeN(context);
|
||||
|
@ -935,34 +589,15 @@ static IndexBuildContext *index_ffmpeg_create_context(struct anim *anim,
|
|||
return nullptr; /* Nothing to transcode. */
|
||||
}
|
||||
|
||||
for (i = 0; i < num_indexers; i++) {
|
||||
if (tcs_in_use & tc_types[i]) {
|
||||
char filepath[FILE_MAX];
|
||||
|
||||
get_tc_filename(anim, tc_types[i], filepath);
|
||||
|
||||
context->indexer[i] = IMB_index_builder_create(filepath);
|
||||
if (!context->indexer[i]) {
|
||||
tcs_in_use &= ~int(tc_types[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (IndexBuildContext *)context;
|
||||
return (ProxyBuildContext *)context;
|
||||
}
|
||||
|
||||
static void index_rebuild_ffmpeg_finish(FFmpegIndexBuilderContext *context, const bool stop)
|
||||
static void proxy_rebuild_ffmpeg_finish(FFmpegProxyBuilderContext *context, const bool stop)
|
||||
{
|
||||
int i;
|
||||
|
||||
const bool do_rollback = stop || context->building_cancelled;
|
||||
|
||||
for (i = 0; i < context->num_indexers; i++) {
|
||||
if (context->tcs_in_use & tc_types[i]) {
|
||||
IMB_index_builder_finish(context->indexer[i], do_rollback);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < context->num_proxy_sizes; i++) {
|
||||
if (context->proxy_sizes_in_use & proxy_sizes[i]) {
|
||||
free_proxy_output_ffmpeg(context->proxy_ctx[i], do_rollback);
|
||||
|
@ -975,8 +610,7 @@ static void index_rebuild_ffmpeg_finish(FFmpegIndexBuilderContext *context, cons
|
|||
MEM_freeN(context);
|
||||
}
|
||||
|
||||
static void index_rebuild_ffmpeg_proc_decoded_frame(FFmpegIndexBuilderContext *context,
|
||||
AVPacket *curr_packet,
|
||||
static void proxy_rebuild_ffmpeg_proc_decoded_frame(FFmpegProxyBuilderContext *context,
|
||||
AVFrame *in_frame)
|
||||
{
|
||||
int i;
|
||||
|
@ -1009,29 +643,10 @@ static void index_rebuild_ffmpeg_proc_decoded_frame(FFmpegIndexBuilderContext *c
|
|||
s_dts = context->last_seek_pos_dts;
|
||||
}
|
||||
|
||||
for (i = 0; i < context->num_indexers; i++) {
|
||||
if (context->tcs_in_use & tc_types[i]) {
|
||||
int tc_frameno = context->frameno;
|
||||
|
||||
if (tc_types[i] == IMB_TC_RECORD_RUN_NO_GAPS) {
|
||||
tc_frameno = context->frameno_gapless;
|
||||
}
|
||||
|
||||
IMB_index_builder_proc_frame(context->indexer[i],
|
||||
curr_packet->data,
|
||||
curr_packet->size,
|
||||
tc_frameno,
|
||||
s_pos,
|
||||
s_pts,
|
||||
s_dts,
|
||||
pts);
|
||||
}
|
||||
}
|
||||
|
||||
context->frameno_gapless++;
|
||||
}
|
||||
|
||||
static int index_rebuild_ffmpeg(FFmpegIndexBuilderContext *context,
|
||||
static int proxy_rebuild_ffmpeg(FFmpegProxyBuilderContext *context,
|
||||
const bool *stop,
|
||||
bool *do_update,
|
||||
float *progress)
|
||||
|
@ -1085,7 +700,7 @@ static int index_rebuild_ffmpeg(FFmpegIndexBuilderContext *context,
|
|||
context->seek_pos_dts = in_frame->pkt_dts;
|
||||
}
|
||||
|
||||
index_rebuild_ffmpeg_proc_decoded_frame(context, next_packet, in_frame);
|
||||
proxy_rebuild_ffmpeg_proc_decoded_frame(context, in_frame);
|
||||
}
|
||||
}
|
||||
av_packet_unref(next_packet);
|
||||
|
@ -1112,7 +727,7 @@ static int index_rebuild_ffmpeg(FFmpegIndexBuilderContext *context,
|
|||
fprintf(stderr, "Error flushing proxy frame: %s\n", error_str);
|
||||
break;
|
||||
}
|
||||
index_rebuild_ffmpeg_proc_decoded_frame(context, next_packet, in_frame);
|
||||
proxy_rebuild_ffmpeg_proc_decoded_frame(context, in_frame);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1123,7 +738,7 @@ static int index_rebuild_ffmpeg(FFmpegIndexBuilderContext *context,
|
|||
}
|
||||
|
||||
/* Get number of frames, that can be decoded in specified time period. */
|
||||
static int indexer_performance_get_decode_rate(FFmpegIndexBuilderContext *context,
|
||||
static int get_decode_rate_performance(FFmpegProxyBuilderContext *context,
|
||||
const double time_period)
|
||||
{
|
||||
AVFrame *in_frame = av_frame_alloc();
|
||||
|
@ -1174,7 +789,7 @@ static int indexer_performance_get_decode_rate(FFmpegIndexBuilderContext *contex
|
|||
/* Read up to 10k movie packets and return max GOP size detected.
|
||||
* Number of packets is arbitrary. It should be as large as possible, but processed within
|
||||
* reasonable time period, so detected GOP size is as close to real as possible. */
|
||||
static int indexer_performance_get_max_gop_size(FFmpegIndexBuilderContext *context)
|
||||
static int get_max_gop_size(FFmpegProxyBuilderContext *context)
|
||||
{
|
||||
AVPacket *packet = av_packet_alloc();
|
||||
|
||||
|
@ -1215,18 +830,18 @@ static int indexer_performance_get_max_gop_size(FFmpegIndexBuilderContext *conte
|
|||
* Since proxies use GOP size of 10 frames, skip building if detected GOP size is less or
|
||||
* equal.
|
||||
*/
|
||||
static bool indexer_need_to_build_proxy(FFmpegIndexBuilderContext *context)
|
||||
static bool need_to_build_proxy(FFmpegProxyBuilderContext *context)
|
||||
{
|
||||
if (!context->build_only_on_bad_performance) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Make sure, that file is not cold read. */
|
||||
indexer_performance_get_decode_rate(context, 0.1);
|
||||
get_decode_rate_performance(context, 0.1);
|
||||
/* Get decode rate per 100ms. This is arbitrary, but seems to be good baseline cadence of
|
||||
* seeking. */
|
||||
const int decode_rate = indexer_performance_get_decode_rate(context, 0.1);
|
||||
const int max_gop_size = indexer_performance_get_max_gop_size(context);
|
||||
const int decode_rate = get_decode_rate_performance(context, 0.1);
|
||||
const int max_gop_size = get_max_gop_size(context);
|
||||
|
||||
if (max_gop_size <= 10 || max_gop_size < decode_rate) {
|
||||
printf("Skipping proxy building for %s: Decoding performance is already good.\n",
|
||||
|
@ -1245,7 +860,7 @@ static bool indexer_need_to_build_proxy(FFmpegIndexBuilderContext *context)
|
|||
* ---------------------------------------------------------------------- */
|
||||
|
||||
#ifdef WITH_AVI
|
||||
typedef struct FallbackIndexBuilderContext {
|
||||
typedef struct FallbackProxyBuilderContext {
|
||||
int anim_type;
|
||||
|
||||
struct anim *anim;
|
||||
|
@ -1291,12 +906,11 @@ static AviMovie *alloc_proxy_output_avi(
|
|||
return avi;
|
||||
}
|
||||
|
||||
static IndexBuildContext *index_fallback_create_context(struct anim *anim,
|
||||
int /*tcs_in_use*/,
|
||||
static ProxyBuildContext *proxy_fallback_create_context(struct anim *anim,
|
||||
int proxy_sizes_in_use,
|
||||
int quality)
|
||||
{
|
||||
FallbackIndexBuilderContext *context;
|
||||
FallbackProxyBuilderContext *context;
|
||||
int i;
|
||||
|
||||
/* since timecode indices only work with ffmpeg right now,
|
||||
|
@ -1308,7 +922,7 @@ static IndexBuildContext *index_fallback_create_context(struct anim *anim,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
context = MEM_cnew<FallbackIndexBuilderContext>("fallback index builder context");
|
||||
context = MEM_cnew<FallbackProxyBuilderContext>("fallback index builder context");
|
||||
|
||||
context->anim = anim;
|
||||
context->proxy_sizes_in_use = proxy_sizes_in_use;
|
||||
|
@ -1327,10 +941,10 @@ static IndexBuildContext *index_fallback_create_context(struct anim *anim,
|
|||
}
|
||||
}
|
||||
|
||||
return (IndexBuildContext *)context;
|
||||
return (ProxyBuildContext *)context;
|
||||
}
|
||||
|
||||
static void index_rebuild_fallback_finish(FallbackIndexBuilderContext *context, const bool stop)
|
||||
static void proxy_rebuild_fallback_finish(FallbackProxyBuilderContext *context, const bool stop)
|
||||
{
|
||||
struct anim *anim = context->anim;
|
||||
char filepath[FILE_MAX];
|
||||
|
@ -1356,17 +970,17 @@ static void index_rebuild_fallback_finish(FallbackIndexBuilderContext *context,
|
|||
}
|
||||
}
|
||||
|
||||
static void index_rebuild_fallback(FallbackIndexBuilderContext *context,
|
||||
static void proxy_rebuild_fallback(FallbackProxyBuilderContext *context,
|
||||
const bool *stop,
|
||||
bool *do_update,
|
||||
float *progress)
|
||||
{
|
||||
int count = IMB_anim_get_duration(context->anim, IMB_TC_NONE);
|
||||
int count = IMB_anim_get_duration(context->anim);
|
||||
int i, pos;
|
||||
struct anim *anim = context->anim;
|
||||
|
||||
for (pos = 0; pos < count; pos++) {
|
||||
struct ImBuf *ibuf = IMB_anim_absolute(anim, pos, IMB_TC_NONE, IMB_PROXY_NONE);
|
||||
struct ImBuf *ibuf = IMB_anim_absolute(anim, pos, IMB_PROXY_NONE);
|
||||
struct ImBuf *tmp_ibuf = IMB_dupImBuf(ibuf);
|
||||
float next_progress = float(pos) / float(count);
|
||||
|
||||
|
@ -1412,15 +1026,14 @@ static void index_rebuild_fallback(FallbackIndexBuilderContext *context,
|
|||
* - public API
|
||||
* ---------------------------------------------------------------------- */
|
||||
|
||||
IndexBuildContext *IMB_anim_index_rebuild_context(struct anim *anim,
|
||||
IMB_Timecode_Type tcs_in_use,
|
||||
ProxyBuildContext *IMB_anim_proxy_rebuild_context(struct anim *anim,
|
||||
int proxy_sizes_in_use,
|
||||
int quality,
|
||||
const bool overwrite,
|
||||
GSet *file_list,
|
||||
bool build_only_on_bad_performance)
|
||||
{
|
||||
IndexBuildContext *context = nullptr;
|
||||
ProxyBuildContext *context = nullptr;
|
||||
int proxy_sizes_to_build = proxy_sizes_in_use;
|
||||
int i;
|
||||
|
||||
|
@ -1472,8 +1085,8 @@ IndexBuildContext *IMB_anim_index_rebuild_context(struct anim *anim,
|
|||
switch (anim->curtype) {
|
||||
#ifdef WITH_FFMPEG
|
||||
case ANIM_FFMPEG:
|
||||
context = index_ffmpeg_create_context(
|
||||
anim, tcs_in_use, proxy_sizes_to_build, quality, build_only_on_bad_performance);
|
||||
context = proxy_ffmpeg_create_context(
|
||||
anim, proxy_sizes_to_build, quality, build_only_on_bad_performance);
|
||||
break;
|
||||
#else
|
||||
UNUSED_VARS(build_only_on_bad_performance);
|
||||
|
@ -1481,7 +1094,7 @@ IndexBuildContext *IMB_anim_index_rebuild_context(struct anim *anim,
|
|||
|
||||
default:
|
||||
#ifdef WITH_AVI
|
||||
context = index_fallback_create_context(anim, tcs_in_use, proxy_sizes_to_build, quality);
|
||||
context = proxy_fallback_create_context(anim, proxy_sizes_to_build, quality);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
@ -1492,10 +1105,10 @@ IndexBuildContext *IMB_anim_index_rebuild_context(struct anim *anim,
|
|||
|
||||
return context;
|
||||
|
||||
UNUSED_VARS(tcs_in_use, proxy_sizes_in_use, quality);
|
||||
UNUSED_VARS(proxy_sizes_in_use, quality);
|
||||
}
|
||||
|
||||
void IMB_anim_index_rebuild(struct IndexBuildContext *context,
|
||||
void IMB_anim_proxy_rebuild(struct ProxyBuildContext *context,
|
||||
/* NOLINTNEXTLINE: readability-non-const-parameter. */
|
||||
bool *stop,
|
||||
/* NOLINTNEXTLINE: readability-non-const-parameter. */
|
||||
|
@ -1506,14 +1119,14 @@ void IMB_anim_index_rebuild(struct IndexBuildContext *context,
|
|||
switch (context->anim_type) {
|
||||
#ifdef WITH_FFMPEG
|
||||
case ANIM_FFMPEG:
|
||||
if (indexer_need_to_build_proxy((FFmpegIndexBuilderContext *)context)) {
|
||||
index_rebuild_ffmpeg((FFmpegIndexBuilderContext *)context, stop, do_update, progress);
|
||||
if (need_to_build_proxy((FFmpegProxyBuilderContext *)context)) {
|
||||
proxy_rebuild_ffmpeg((FFmpegProxyBuilderContext *)context, stop, do_update, progress);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
#ifdef WITH_AVI
|
||||
index_rebuild_fallback((FallbackIndexBuilderContext *)context, stop, do_update, progress);
|
||||
proxy_rebuild_fallback((FallbackProxyBuilderContext *)context, stop, do_update, progress);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
@ -1521,17 +1134,17 @@ void IMB_anim_index_rebuild(struct IndexBuildContext *context,
|
|||
UNUSED_VARS(stop, do_update, progress);
|
||||
}
|
||||
|
||||
void IMB_anim_index_rebuild_finish(IndexBuildContext *context, const bool stop)
|
||||
void IMB_anim_proxy_rebuild_finish(ProxyBuildContext *context, const bool stop)
|
||||
{
|
||||
switch (context->anim_type) {
|
||||
#ifdef WITH_FFMPEG
|
||||
case ANIM_FFMPEG:
|
||||
index_rebuild_ffmpeg_finish((FFmpegIndexBuilderContext *)context, stop);
|
||||
proxy_rebuild_ffmpeg_finish((FFmpegProxyBuilderContext *)context, stop);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
#ifdef WITH_AVI
|
||||
index_rebuild_fallback_finish((FallbackIndexBuilderContext *)context, stop);
|
||||
proxy_rebuild_fallback_finish((FallbackProxyBuilderContext *)context, stop);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
@ -1540,7 +1153,7 @@ void IMB_anim_index_rebuild_finish(IndexBuildContext *context, const bool stop)
|
|||
UNUSED_VARS(stop, proxy_sizes);
|
||||
}
|
||||
|
||||
void IMB_free_indices(struct anim *anim)
|
||||
void IMB_free_proxies(struct anim *anim)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -1551,25 +1164,15 @@ void IMB_free_indices(struct anim *anim)
|
|||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < IMB_TC_MAX_SLOT; i++) {
|
||||
if (anim->curr_idx[i]) {
|
||||
IMB_indexer_close(anim->curr_idx[i]);
|
||||
anim->curr_idx[i] = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
anim->proxies_tried = 0;
|
||||
anim->indices_tried = 0;
|
||||
}
|
||||
|
||||
void IMB_anim_set_index_dir(struct anim *anim, const char *dir)
|
||||
void IMB_anim_set_proxy_dir(struct anim *anim, const char *dir)
|
||||
{
|
||||
if (STREQ(anim->index_dir, dir)) {
|
||||
return;
|
||||
}
|
||||
STRNCPY(anim->index_dir, dir);
|
||||
|
||||
IMB_free_indices(anim);
|
||||
}
|
||||
|
||||
struct anim *IMB_anim_open_proxy(struct anim *anim, IMB_Proxy_Size preview_size)
|
||||
|
@ -1599,43 +1202,6 @@ struct anim *IMB_anim_open_proxy(struct anim *anim, IMB_Proxy_Size preview_size)
|
|||
return anim->proxy_anim[i];
|
||||
}
|
||||
|
||||
struct anim_index *IMB_anim_open_index(struct anim *anim, IMB_Timecode_Type tc)
|
||||
{
|
||||
char filepath[FILE_MAX];
|
||||
int i = IMB_timecode_to_array_index(tc);
|
||||
|
||||
if (i < 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (anim->curr_idx[i]) {
|
||||
return anim->curr_idx[i];
|
||||
}
|
||||
|
||||
if (anim->indices_tried & tc) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
get_tc_filename(anim, tc, filepath);
|
||||
|
||||
anim->curr_idx[i] = IMB_indexer_open(filepath);
|
||||
|
||||
anim->indices_tried |= tc;
|
||||
|
||||
return anim->curr_idx[i];
|
||||
}
|
||||
|
||||
int IMB_anim_index_get_frame_index(struct anim *anim, IMB_Timecode_Type tc, int position)
|
||||
{
|
||||
struct anim_index *idx = IMB_anim_open_index(anim, tc);
|
||||
|
||||
if (!idx) {
|
||||
return position;
|
||||
}
|
||||
|
||||
return IMB_indexer_get_frame_index(idx, position);
|
||||
}
|
||||
|
||||
int IMB_anim_proxy_get_existing(struct anim *anim)
|
||||
{
|
||||
const int num_proxy_sizes = IMB_PROXY_MAX_SLOT;
|
|
@ -381,7 +381,7 @@ static ImBuf *thumb_create_ex(const char *file_path,
|
|||
struct anim *anim = nullptr;
|
||||
anim = IMB_open_anim(file_path, IB_rect | IB_metadata, 0, nullptr);
|
||||
if (anim != nullptr) {
|
||||
img = IMB_anim_absolute(anim, 0, IMB_TC_NONE, IMB_PROXY_NONE);
|
||||
img = IMB_anim_absolute(anim, 0, IMB_PROXY_NONE);
|
||||
if (img == nullptr) {
|
||||
printf("not an anim; %s\n", file_path);
|
||||
}
|
||||
|
|
|
@ -16,8 +16,6 @@
|
|||
#define _DNA_DEFAULT_MovieClipProxy \
|
||||
{ \
|
||||
.build_size_flag = IMB_PROXY_25, \
|
||||
.build_tc_flag = IMB_TC_RECORD_RUN | IMB_TC_FREE_RUN | \
|
||||
IMB_TC_INTERPOLATED_REC_DATE_FREE_RUN | IMB_TC_RECORD_RUN_NO_GAPS, \
|
||||
.quality = 50, \
|
||||
}
|
||||
|
||||
|
|
|
@ -34,14 +34,11 @@ typedef struct MovieClipProxy {
|
|||
/** 768=FILE_MAXDIR custom directory for index and proxy files (defaults to BL_proxy). */
|
||||
char dir[768];
|
||||
|
||||
/** Time code in use. */
|
||||
short tc;
|
||||
short _pad0[2];
|
||||
/** Proxy build quality. */
|
||||
short quality;
|
||||
/** Size flags (see below) of all proxies to build. */
|
||||
short build_size_flag;
|
||||
/** Time code flags (see below) of all tc indices to build. */
|
||||
short build_tc_flag;
|
||||
} MovieClipProxy;
|
||||
|
||||
typedef struct MovieClip_RuntimeGPUTexture {
|
||||
|
|
|
@ -631,20 +631,13 @@ enum {
|
|||
#define SEQ_COLOR_BALANCE_INVERSE_OFFSET 16
|
||||
#define SEQ_COLOR_BALANCE_INVERSE_POWER 32
|
||||
|
||||
/* !!! has to be same as IMB_imbuf.h IMB_PROXY_... and IMB_TC_... */
|
||||
/* !!! has to be same as IMB_imbuf.h IMB_PROXY_... */
|
||||
|
||||
#define SEQ_PROXY_IMAGE_SIZE_25 1
|
||||
#define SEQ_PROXY_IMAGE_SIZE_50 2
|
||||
#define SEQ_PROXY_IMAGE_SIZE_75 4
|
||||
#define SEQ_PROXY_IMAGE_SIZE_100 8
|
||||
|
||||
#define SEQ_PROXY_TC_NONE 0
|
||||
#define SEQ_PROXY_TC_RECORD_RUN 1
|
||||
#define SEQ_PROXY_TC_FREE_RUN 2
|
||||
#define SEQ_PROXY_TC_INTERP_REC_DATE_FREE_RUN 4
|
||||
#define SEQ_PROXY_TC_RECORD_RUN_NO_GAPS 8
|
||||
#define SEQ_PROXY_TC_ALL 15
|
||||
|
||||
/** SeqProxy.build_flags */
|
||||
enum {
|
||||
SEQ_PROXY_SKIP_EXISTING = 1,
|
||||
|
|
|
@ -580,7 +580,7 @@ static int rna_Image_frame_duration_get(PointerRNA *ptr)
|
|||
if (BKE_image_has_anim(ima)) {
|
||||
struct anim *anim = ((ImageAnim *)ima->anims.first)->anim;
|
||||
if (anim) {
|
||||
duration = IMB_anim_get_duration(anim, IMB_TC_RECORD_RUN);
|
||||
duration = IMB_anim_get_duration(anim);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -141,32 +141,6 @@ static void rna_def_movieclip_proxy(BlenderRNA *brna)
|
|||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
|
||||
static const EnumPropertyItem clip_tc_items[] = {
|
||||
{IMB_TC_NONE, "NONE", 0, "None", ""},
|
||||
{IMB_TC_RECORD_RUN,
|
||||
"RECORD_RUN",
|
||||
0,
|
||||
"Record Run",
|
||||
"Use images in the order they are recorded"},
|
||||
{IMB_TC_FREE_RUN,
|
||||
"FREE_RUN",
|
||||
0,
|
||||
"Free Run",
|
||||
"Use global timestamp written by recording device"},
|
||||
{IMB_TC_INTERPOLATED_REC_DATE_FREE_RUN,
|
||||
"FREE_RUN_REC_DATE",
|
||||
0,
|
||||
"Free Run (rec date)",
|
||||
"Interpolate a global timestamp using the record date and time "
|
||||
"written by recording device"},
|
||||
{IMB_TC_RECORD_RUN_NO_GAPS,
|
||||
"FREE_RUN_NO_GAPS",
|
||||
0,
|
||||
"Free Run No Gaps",
|
||||
"Record run, but ignore timecode, changes in framerate or dropouts"},
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
srna = RNA_def_struct(brna, "MovieClipProxy", NULL);
|
||||
RNA_def_struct_ui_text(srna, "Movie Clip Proxy", "Proxy parameters for a movie clip");
|
||||
RNA_def_struct_sdna(srna, "MovieClipProxy");
|
||||
|
@ -220,24 +194,6 @@ static void rna_def_movieclip_proxy(BlenderRNA *brna)
|
|||
RNA_def_property_ui_text(
|
||||
prop, "100%", "Build proxy resolution 100% of the original undistorted footage dimension");
|
||||
|
||||
/* Build time-codes. */
|
||||
prop = RNA_def_property(srna, "build_record_run", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "build_tc_flag", IMB_TC_RECORD_RUN);
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_ui_text(prop, "Rec Run", "Build record run time code index");
|
||||
|
||||
prop = RNA_def_property(srna, "build_free_run", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "build_tc_flag", IMB_TC_FREE_RUN);
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_ui_text(prop, "Free Run", "Build free run time code index");
|
||||
|
||||
prop = RNA_def_property(srna, "build_free_run_rec_date", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(
|
||||
prop, NULL, "build_tc_flag", IMB_TC_INTERPOLATED_REC_DATE_FREE_RUN);
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_ui_text(
|
||||
prop, "Free Run (Rec Date)", "Build free run time code index using Record Date/Time");
|
||||
|
||||
/* quality of proxied image */
|
||||
prop = RNA_def_property(srna, "quality", PROP_INT, PROP_UNSIGNED);
|
||||
RNA_def_property_int_sdna(prop, NULL, "quality");
|
||||
|
@ -245,13 +201,6 @@ static void rna_def_movieclip_proxy(BlenderRNA *brna)
|
|||
RNA_def_property_ui_text(prop, "Quality", "JPEG quality of proxy images");
|
||||
RNA_def_property_ui_range(prop, 1, 100, 1, -1);
|
||||
|
||||
prop = RNA_def_property(srna, "timecode", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, NULL, "tc");
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_enum_items(prop, clip_tc_items);
|
||||
RNA_def_property_ui_text(prop, "Timecode", "");
|
||||
RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, "rna_MovieClip_reload_update");
|
||||
|
||||
/* directory */
|
||||
prop = RNA_def_property(srna, "directory", PROP_STRING, PROP_DIRPATH);
|
||||
RNA_def_property_string_sdna(prop, NULL, "dir");
|
||||
|
|
|
@ -1712,33 +1712,6 @@ static void rna_def_strip_proxy(BlenderRNA *brna)
|
|||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
|
||||
static const EnumPropertyItem seq_tc_items[] = {
|
||||
{SEQ_PROXY_TC_NONE, "NONE", 0, "None", ""},
|
||||
{SEQ_PROXY_TC_RECORD_RUN,
|
||||
"RECORD_RUN",
|
||||
0,
|
||||
"Record Run",
|
||||
"Use images in the order as they are recorded"},
|
||||
{SEQ_PROXY_TC_FREE_RUN,
|
||||
"FREE_RUN",
|
||||
0,
|
||||
"Free Run",
|
||||
"Use global timestamp written by recording device"},
|
||||
{SEQ_PROXY_TC_INTERP_REC_DATE_FREE_RUN,
|
||||
"FREE_RUN_REC_DATE",
|
||||
0,
|
||||
"Free Run (rec date)",
|
||||
"Interpolate a global timestamp using the "
|
||||
"record date and time written by recording device"},
|
||||
{SEQ_PROXY_TC_RECORD_RUN_NO_GAPS,
|
||||
"RECORD_RUN_NO_GAPS",
|
||||
0,
|
||||
"Record Run No Gaps",
|
||||
"Like record run, but ignore timecode, "
|
||||
"changes in framerate or dropouts"},
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
srna = RNA_def_struct(brna, "SequenceProxy", NULL);
|
||||
RNA_def_struct_ui_text(srna, "Sequence Proxy", "Proxy parameters for a sequence strip");
|
||||
RNA_def_struct_sdna(srna, "StripProxy");
|
||||
|
@ -1777,31 +1750,11 @@ static void rna_def_strip_proxy(BlenderRNA *brna)
|
|||
RNA_def_property_boolean_sdna(prop, NULL, "build_size_flags", SEQ_PROXY_IMAGE_SIZE_100);
|
||||
RNA_def_property_ui_text(prop, "100%", "Build 100% proxy resolution");
|
||||
|
||||
prop = RNA_def_property(srna, "build_record_run", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "build_tc_flags", SEQ_PROXY_TC_RECORD_RUN);
|
||||
RNA_def_property_ui_text(prop, "Rec Run", "Build record run time code index");
|
||||
|
||||
prop = RNA_def_property(srna, "build_free_run", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "build_tc_flags", SEQ_PROXY_TC_FREE_RUN);
|
||||
RNA_def_property_ui_text(prop, "Free Run", "Build free run time code index");
|
||||
|
||||
prop = RNA_def_property(srna, "build_free_run_rec_date", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(
|
||||
prop, NULL, "build_tc_flags", SEQ_PROXY_TC_INTERP_REC_DATE_FREE_RUN);
|
||||
RNA_def_property_ui_text(
|
||||
prop, "Free Run (Rec Date)", "Build free run time code index using Record Date/Time");
|
||||
|
||||
prop = RNA_def_property(srna, "quality", PROP_INT, PROP_UNSIGNED);
|
||||
RNA_def_property_int_sdna(prop, NULL, "quality");
|
||||
RNA_def_property_ui_text(prop, "Quality", "Quality of proxies to build");
|
||||
RNA_def_property_ui_range(prop, 1, 100, 1, -1);
|
||||
|
||||
prop = RNA_def_property(srna, "timecode", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, NULL, "tc");
|
||||
RNA_def_property_enum_items(prop, seq_tc_items);
|
||||
RNA_def_property_ui_text(prop, "Timecode", "Method for reading the inputs timecode");
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_tcindex_update");
|
||||
|
||||
prop = RNA_def_property(srna, "use_proxy_custom_directory", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "storage", SEQ_STORAGE_PROXY_CUSTOM_DIR);
|
||||
RNA_def_property_ui_text(prop, "Proxy Custom Directory", "Use a custom directory to store data");
|
||||
|
|
|
@ -64,7 +64,7 @@ static void node_geo_exec(GeoNodeExecParams params)
|
|||
if (ImageAnim *ianim = static_cast<ImageAnim *>(image->anims.first)) {
|
||||
auto *anim = ianim->anim;
|
||||
if (anim) {
|
||||
frames = IMB_anim_get_duration(anim, IMB_TC_NONE);
|
||||
frames = IMB_anim_get_duration(anim);
|
||||
|
||||
short fps_sec = 0;
|
||||
float fps_sec_base = 0.0f;
|
||||
|
|
|
@ -17,7 +17,7 @@ struct ListBase;
|
|||
struct ListBase;
|
||||
struct Main;
|
||||
struct Scene;
|
||||
struct SeqIndexBuildContext;
|
||||
struct SeqProxyBuildContext;
|
||||
struct SeqRenderData;
|
||||
struct Sequence;
|
||||
|
||||
|
@ -28,11 +28,11 @@ bool SEQ_proxy_rebuild_context(struct Main *bmain,
|
|||
struct GSet *file_list,
|
||||
struct ListBase *queue,
|
||||
bool build_only_on_bad_performance);
|
||||
void SEQ_proxy_rebuild(struct SeqIndexBuildContext *context,
|
||||
void SEQ_proxy_rebuild(struct SeqProxyBuildContext *context,
|
||||
bool *stop,
|
||||
bool *do_update,
|
||||
float *progress);
|
||||
void SEQ_proxy_rebuild_finish(struct SeqIndexBuildContext *context, bool stop);
|
||||
void SEQ_proxy_rebuild_finish(struct SeqProxyBuildContext *context, bool stop);
|
||||
void SEQ_proxy_set(struct Sequence *seq, bool value);
|
||||
bool SEQ_can_use_proxy(const struct SeqRenderData *context, struct Sequence *seq, int psize);
|
||||
int SEQ_rendersize_to_proxysize(int render_size);
|
||||
|
|
|
@ -52,8 +52,8 @@
|
|||
#include "strip_time.h"
|
||||
#include "utils.h"
|
||||
|
||||
typedef struct SeqIndexBuildContext {
|
||||
struct IndexBuildContext *index_context;
|
||||
typedef struct SeqProxyBuildContext {
|
||||
struct ProxyBuildContext *index_context;
|
||||
|
||||
int tc_flags;
|
||||
int size_flags;
|
||||
|
@ -66,7 +66,7 @@ typedef struct SeqIndexBuildContext {
|
|||
Scene *scene;
|
||||
Sequence *seq, *orig_seq;
|
||||
SessionUUID orig_seq_uuid;
|
||||
} SeqIndexBuildContext;
|
||||
} SeqProxyBuildContext;
|
||||
|
||||
int SEQ_rendersize_to_proxysize(int render_size)
|
||||
{
|
||||
|
@ -229,10 +229,7 @@ ImBuf *seq_proxy_fetch(const SeqRenderData *context, Sequence *seq, int timeline
|
|||
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);
|
||||
return IMB_anim_absolute(proxy->anim, frameno, IMB_PROXY_NONE);
|
||||
}
|
||||
|
||||
if (seq_proxy_get_fname(
|
||||
|
@ -409,7 +406,7 @@ bool SEQ_proxy_rebuild_context(Main *bmain,
|
|||
ListBase *queue,
|
||||
bool build_only_on_bad_performance)
|
||||
{
|
||||
SeqIndexBuildContext *context;
|
||||
SeqProxyBuildContext *context;
|
||||
Sequence *nseq;
|
||||
LinkData *link;
|
||||
int num_files;
|
||||
|
@ -440,7 +437,7 @@ bool SEQ_proxy_rebuild_context(Main *bmain,
|
|||
|
||||
SEQ_relations_sequence_free_anim(seq);
|
||||
|
||||
context = MEM_callocN(sizeof(SeqIndexBuildContext), "seq proxy rebuild context");
|
||||
context = MEM_callocN(sizeof(SeqProxyBuildContext), "seq proxy rebuild context");
|
||||
|
||||
nseq = SEQ_sequence_dupli_recursive(scene, scene, NULL, seq, 0);
|
||||
|
||||
|
@ -463,8 +460,7 @@ bool SEQ_proxy_rebuild_context(Main *bmain,
|
|||
sanim = BLI_findlink(&nseq->anims, i);
|
||||
|
||||
if (sanim->anim) {
|
||||
context->index_context = IMB_anim_index_rebuild_context(sanim->anim,
|
||||
context->tc_flags,
|
||||
context->index_context = IMB_anim_proxy_rebuild_context(sanim->anim,
|
||||
context->size_flags,
|
||||
context->quality,
|
||||
context->overwrite,
|
||||
|
@ -484,7 +480,7 @@ bool SEQ_proxy_rebuild_context(Main *bmain,
|
|||
return true;
|
||||
}
|
||||
|
||||
void SEQ_proxy_rebuild(SeqIndexBuildContext *context, bool *stop, bool *do_update, float *progress)
|
||||
void SEQ_proxy_rebuild(SeqProxyBuildContext *context, bool *stop, bool *do_update, float *progress)
|
||||
{
|
||||
const bool overwrite = context->overwrite;
|
||||
SeqRenderData render_context;
|
||||
|
@ -495,7 +491,7 @@ void SEQ_proxy_rebuild(SeqIndexBuildContext *context, bool *stop, bool *do_updat
|
|||
|
||||
if (seq->type == SEQ_TYPE_MOVIE) {
|
||||
if (context->index_context) {
|
||||
IMB_anim_index_rebuild(context->index_context, stop, do_update, progress);
|
||||
IMB_anim_proxy_rebuild(context->index_context, stop, do_update, progress);
|
||||
}
|
||||
|
||||
return;
|
||||
|
@ -552,7 +548,7 @@ void SEQ_proxy_rebuild(SeqIndexBuildContext *context, bool *stop, bool *do_updat
|
|||
}
|
||||
}
|
||||
|
||||
void SEQ_proxy_rebuild_finish(SeqIndexBuildContext *context, bool stop)
|
||||
void SEQ_proxy_rebuild_finish(SeqProxyBuildContext *context, bool stop)
|
||||
{
|
||||
if (context->index_context) {
|
||||
StripAnim *sanim;
|
||||
|
@ -561,7 +557,7 @@ void SEQ_proxy_rebuild_finish(SeqIndexBuildContext *context, bool stop)
|
|||
IMB_close_anim_proxies(sanim->anim);
|
||||
}
|
||||
|
||||
IMB_anim_index_rebuild_finish(context->index_context, stop);
|
||||
IMB_anim_proxy_rebuild_finish(context->index_context, stop);
|
||||
}
|
||||
|
||||
seq_free_sequence_recurse(NULL, context->seq, true);
|
||||
|
@ -589,7 +585,7 @@ void seq_proxy_index_dir_set(struct anim *anim, const char *base_dir)
|
|||
|
||||
IMB_anim_get_filename(anim, filename, FILE_MAXFILE);
|
||||
BLI_path_join(dirname, sizeof(dirname), base_dir, filename);
|
||||
IMB_anim_set_index_dir(anim, dirname);
|
||||
IMB_anim_set_proxy_dir(anim, dirname);
|
||||
}
|
||||
|
||||
void free_proxy_seq(Sequence *seq)
|
||||
|
|
|
@ -47,7 +47,7 @@ static void proxy_startjob(void *pjv, bool *stop, bool *do_update, float *progre
|
|||
LinkData *link;
|
||||
|
||||
for (link = pj->queue.first; link; link = link->next) {
|
||||
struct SeqIndexBuildContext *context = link->data;
|
||||
struct SeqProxyBuildContext *context = link->data;
|
||||
|
||||
SEQ_proxy_rebuild(context, stop, do_update, progress);
|
||||
|
||||
|
|
|
@ -680,7 +680,8 @@ static ImBuf *seq_render_preprocess_ibuf(const SeqRenderData *context,
|
|||
const bool is_proxy_image)
|
||||
{
|
||||
if (context->is_proxy_render == false &&
|
||||
(ibuf->x != context->rectx || ibuf->y != context->recty)) {
|
||||
(ibuf->x != context->rectx || ibuf->y != context->recty))
|
||||
{
|
||||
use_preprocess = true;
|
||||
}
|
||||
|
||||
|
@ -1049,16 +1050,7 @@ static ImBuf *seq_render_movie_strip_custom_file_proxy(const SeqRenderData *cont
|
|||
|
||||
int frameno = (int)SEQ_give_frame_index(context->scene, seq, timeline_frame) +
|
||||
seq->anim_startofs;
|
||||
return IMB_anim_absolute(proxy->anim, frameno, IMB_TC_NONE, IMB_PROXY_NONE);
|
||||
}
|
||||
|
||||
static IMB_Timecode_Type seq_render_movie_strip_timecode_get(Sequence *seq)
|
||||
{
|
||||
bool use_timecodes = (seq->flag & SEQ_USE_PROXY) != 0;
|
||||
if (!use_timecodes) {
|
||||
return IMB_TC_NONE;
|
||||
}
|
||||
return seq->strip->proxy ? seq->strip->proxy->tc : IMB_TC_NONE;
|
||||
return IMB_anim_absolute(proxy->anim, frameno, IMB_PROXY_NONE);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1083,10 +1075,7 @@ static ImBuf *seq_render_movie_strip_view(const SeqRenderData *context,
|
|||
ibuf = seq_render_movie_strip_custom_file_proxy(context, seq, timeline_frame);
|
||||
}
|
||||
else {
|
||||
ibuf = IMB_anim_absolute(sanim->anim,
|
||||
frame_index + seq->anim_startofs,
|
||||
seq_render_movie_strip_timecode_get(seq),
|
||||
psize);
|
||||
ibuf = IMB_anim_absolute(sanim->anim, frame_index + seq->anim_startofs, psize);
|
||||
}
|
||||
|
||||
if (ibuf != NULL) {
|
||||
|
@ -1096,10 +1085,7 @@ static ImBuf *seq_render_movie_strip_view(const SeqRenderData *context,
|
|||
|
||||
/* Fetching for requested proxy size failed, try fetching the original instead. */
|
||||
if (ibuf == NULL) {
|
||||
ibuf = IMB_anim_absolute(sanim->anim,
|
||||
frame_index + seq->anim_startofs,
|
||||
seq_render_movie_strip_timecode_get(seq),
|
||||
IMB_PROXY_NONE);
|
||||
ibuf = IMB_anim_absolute(sanim->anim, frame_index + seq->anim_startofs, IMB_PROXY_NONE);
|
||||
}
|
||||
if (ibuf == NULL) {
|
||||
return NULL;
|
||||
|
|
|
@ -470,7 +470,7 @@ Sequence *SEQ_add_movie_strip(Main *bmain, Scene *scene, ListBase *seqbase, SeqL
|
|||
}
|
||||
|
||||
if (anim_arr[0] != NULL) {
|
||||
seq->len = IMB_anim_get_duration(anim_arr[0], IMB_TC_RECORD_RUN);
|
||||
seq->len = IMB_anim_get_duration(anim_arr[0]);
|
||||
|
||||
IMB_anim_load_metadata(anim_arr[0]);
|
||||
|
||||
|
@ -612,8 +612,7 @@ void SEQ_add_reload_new_file(Main *bmain, Scene *scene, Sequence *seq, const boo
|
|||
|
||||
IMB_anim_load_metadata(sanim->anim);
|
||||
|
||||
seq->len = IMB_anim_get_duration(
|
||||
sanim->anim, seq->strip->proxy ? seq->strip->proxy->tc : IMB_TC_RECORD_RUN);
|
||||
seq->len = IMB_anim_get_duration(sanim->anim);
|
||||
|
||||
seq->len -= seq->anim_startofs;
|
||||
seq->len -= seq->anim_endofs;
|
||||
|
|
|
@ -349,7 +349,7 @@ static ImBuf *ibuf_from_picture(PlayAnimPict *pic)
|
|||
ibuf = pic->ibuf;
|
||||
}
|
||||
else if (pic->anim) {
|
||||
ibuf = IMB_anim_absolute(pic->anim, pic->frame, IMB_TC_NONE, IMB_PROXY_NONE);
|
||||
ibuf = IMB_anim_absolute(pic->anim, pic->frame, IMB_PROXY_NONE);
|
||||
}
|
||||
else if (pic->mem) {
|
||||
/* use correct colorspace here */
|
||||
|
@ -630,13 +630,13 @@ static void build_pict_list_ex(
|
|||
struct anim *anim = IMB_open_anim(filepath_first, IB_rect, 0, NULL);
|
||||
if (anim) {
|
||||
int pic;
|
||||
struct ImBuf *ibuf = IMB_anim_absolute(anim, 0, IMB_TC_NONE, IMB_PROXY_NONE);
|
||||
struct ImBuf *ibuf = IMB_anim_absolute(anim, 0, IMB_PROXY_NONE);
|
||||
if (ibuf) {
|
||||
playanim_toscreen(ps, NULL, ibuf, fontid, fstep);
|
||||
IMB_freeImBuf(ibuf);
|
||||
}
|
||||
|
||||
for (pic = 0; pic < IMB_anim_get_duration(anim, IMB_TC_NONE); pic++) {
|
||||
for (pic = 0; pic < IMB_anim_get_duration(anim); pic++) {
|
||||
PlayAnimPict *picture = (PlayAnimPict *)MEM_callocN(sizeof(PlayAnimPict), "Pict");
|
||||
picture->anim = anim;
|
||||
picture->frame = pic;
|
||||
|
@ -1526,7 +1526,7 @@ static char *wm_main_playanim_intern(int argc, const char **argv)
|
|||
struct anim *anim;
|
||||
anim = IMB_open_anim(filepath, IB_rect, 0, NULL);
|
||||
if (anim) {
|
||||
ibuf = IMB_anim_absolute(anim, 0, IMB_TC_NONE, IMB_PROXY_NONE);
|
||||
ibuf = IMB_anim_absolute(anim, 0, IMB_PROXY_NONE);
|
||||
IMB_close_anim(anim);
|
||||
anim = NULL;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue