WIP: FFmpeg: Remove timecode support #108059

Draft
Richard Antalik wants to merge 1 commits from iss/blender:bye-indexer into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
31 changed files with 170 additions and 935 deletions

View File

@ -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()

View File

@ -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"

View File

@ -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);

View File

@ -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) {

View File

@ -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;
}

View File

@ -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,14 +1539,12 @@ 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),
IMB_Proxy_Size(clip->proxy.build_size_flag),
clip->proxy.quality,
true,
nullptr,
false);
pj->index_context = IMB_anim_proxy_rebuild_context(clip->anim,
IMB_Proxy_Size(clip->proxy.build_size_flag),
clip->proxy.quality,
true,
nullptr,
false);
}
WM_jobs_customdata_set(wm_job, pj, proxy_freejob);
@ -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;

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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)) {

View File

@ -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;

View File

@ -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

View File

@ -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 */);
/**

View File

@ -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 */

View File

@ -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);

View File

@ -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);

View File

@ -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,26 +1125,19 @@ 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;
AVStream *v_st = anim->pFormatCtx->streams[anim->videoStream];
int64_t start_pts = v_st->start_time;
pts_to_search = round(position * ffmpeg_steps_per_frame_get(anim));
pts_to_search = round(position * ffmpeg_steps_per_frame_get(anim));
if (start_pts != AV_NOPTS_VALUE) {
pts_to_search += start_pts;
}
if (start_pts != AV_NOPTS_VALUE) {
pts_to_search += start_pts;
}
return pts_to_search;
}
@ -1297,70 +1290,29 @@ 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);
/* 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);
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;
AVFormatContext *format_ctx = anim->pFormatCtx;
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);
}
if (format_ctx->iformat->read_seek2 || format_ctx->iformat->read_seek) {
ret = av_seek_frame(anim->pFormatCtx, anim->videoStream, seek_pos, 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);
ret = ffmpeg_generic_seek_workaround(anim, &seek_pos, pts_to_search);
av_log(
anim->pFormatCtx, AV_LOG_DEBUG, "NO INDEX final seek seek_pos = %" PRId64 "\n", seek_pos);
anim->pFormatCtx, AV_LOG_DEBUG, "Adjusted final seek seek_pos = %" PRId64 "\n", seek_pos);
}
AVFormatContext *format_ctx = anim->pFormatCtx;
if (format_ctx->iformat->read_seek2 || format_ctx->iformat->read_seek) {
ret = av_seek_frame(anim->pFormatCtx, anim->videoStream, seek_pos, AVSEEK_FLAG_BACKWARD);
}
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);
}
if (ret <= 0 && !ffmpeg_seek_buffers_need_flushing(anim, position, seek_pos)) {
return 0;
}
if (ret <= 0 && !ffmpeg_seek_buffers_need_flushing(anim, position, seek_pos)) {
return 0;
}
if (ret < 0) {
@ -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);
return anim->duration_in_frames;
}
double IMD_anim_get_offset(struct anim *anim)

View File

@ -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,8 +738,8 @@ 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,
const double time_period)
static int get_decode_rate_performance(FFmpegProxyBuilderContext *context,
const double time_period)
{
AVFrame *in_frame = av_frame_alloc();
AVPacket *packet = av_packet_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;

View File

@ -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);
}

View File

@ -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, \
}

View File

@ -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 {

View File

@ -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,

View File

@ -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);
}
}

View File

@ -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");

View File

@ -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");

View File

@ -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;

View File

@ -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);

View File

@ -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)

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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;
}