Changeset View
Changeset View
Standalone View
Standalone View
source/blender/sequencer/intern/strip_add.c
| Show First 20 Lines • Show All 90 Lines • ▼ Show 20 Lines | void SEQ_add_load_data_init(SeqLoadData *load_data, | ||||
| } | } | ||||
| if (path != NULL) { | if (path != NULL) { | ||||
| BLI_strncpy(load_data->path, path, sizeof(load_data->path)); | BLI_strncpy(load_data->path, path, sizeof(load_data->path)); | ||||
| } | } | ||||
| load_data->start_frame = start_frame; | load_data->start_frame = start_frame; | ||||
| load_data->channel = channel; | load_data->channel = channel; | ||||
| } | } | ||||
| static void seq_add_generic_update(Scene *scene, ListBase *seqbase, Sequence *seq) | static void seq_add_generic_update(Scene *scene, ListBase *UNUSED(seqbase), Sequence *seq) | ||||
| { | { | ||||
| SEQ_sequence_base_unique_name_recursive(seqbase, seq); | SEQ_sequence_base_unique_name_recursive(&scene->ed->seqbase, seq); | ||||
| SEQ_time_update_sequence_bounds(scene, seq); | SEQ_time_update_sequence_bounds(scene, seq); | ||||
| SEQ_sort(scene); | SEQ_sort(scene); | ||||
| SEQ_relations_invalidate_cache_composite(scene, seq); | SEQ_relations_invalidate_cache_composite(scene, seq); | ||||
| } | } | ||||
| static void seq_add_set_name(Sequence *seq, SeqLoadData *load_data) | static void seq_add_set_name(Sequence *seq, SeqLoadData *load_data) | ||||
| { | { | ||||
| if (load_data->name[0] != '\0') { | if (load_data->name[0] != '\0') { | ||||
| ▲ Show 20 Lines • Show All 267 Lines • ▼ Show 20 Lines | |||||
| * | * | ||||
| * \param main: Main reference | * \param main: Main reference | ||||
| * \param scene: Scene where strips will be added | * \param scene: Scene where strips will be added | ||||
| * \param seqbase: ListBase where strips will be added | * \param seqbase: ListBase where strips will be added | ||||
| * \param load_data: SeqLoadData with information necessary to create strip | * \param load_data: SeqLoadData with information necessary to create strip | ||||
| * \return created strip | * \return created strip | ||||
| */ | */ | ||||
| Sequence *SEQ_add_sound_strip(Main *bmain, Scene *scene, ListBase *seqbase, SeqLoadData *load_data) | Sequence *SEQ_add_sound_strip(Main *bmain, | ||||
| Scene *scene, | |||||
| ListBase *seqbase, | |||||
| SeqLoadData *load_data, | |||||
| const double audio_offset) | |||||
| { | { | ||||
| bSound *sound = BKE_sound_new_file(bmain, load_data->path); /* Handles relative paths. */ | bSound *sound = BKE_sound_new_file(bmain, load_data->path); /* Handles relative paths. */ | ||||
| sound->offset_time = audio_offset; | |||||
| SoundInfo info; | SoundInfo info; | ||||
| bool sound_loaded = BKE_sound_info_get(bmain, sound, &info); | bool sound_loaded = BKE_sound_info_get(bmain, sound, &info); | ||||
| if (!sound_loaded && !load_data->allow_invalid_file) { | if (!sound_loaded && !load_data->allow_invalid_file) { | ||||
| BKE_id_free(bmain, sound); | BKE_id_free(bmain, sound); | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| if (info.specs.channels == SOUND_CHANNELS_INVALID && !load_data->allow_invalid_file) { | if (info.specs.channels == SOUND_CHANNELS_INVALID && !load_data->allow_invalid_file) { | ||||
| BKE_id_free(bmain, sound); | BKE_id_free(bmain, sound); | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| Sequence *seq = SEQ_sequence_alloc( | /* If this sound it part of a video, then the sound might start after the video. | ||||
| seqbase, load_data->start_frame, load_data->channel, SEQ_TYPE_SOUND_RAM); | * In this case we need to then offset the start frame of the audio so it syncs up | ||||
| * properly with the video. | |||||
| */ | |||||
| int start_frame_offset = info.start_offset * FPS; | |||||
| double start_frame_offset_remainer = (info.start_offset * FPS - start_frame_offset) / FPS; | |||||
| if (start_frame_offset_remainer > FLT_EPSILON) { | |||||
| /* We can't represent a fraction of a frame, so skip the first frame fraction of sound so we | |||||
| * start on a "whole" frame. | |||||
| */ | |||||
| start_frame_offset++; | |||||
| } | |||||
| sound->offset_time += start_frame_offset_remainer; | |||||
| Sequence *seq = SEQ_sequence_alloc(seqbase, | |||||
| load_data->start_frame + start_frame_offset, | |||||
| load_data->channel, | |||||
| SEQ_TYPE_SOUND_RAM); | |||||
| seq->sound = sound; | seq->sound = sound; | ||||
| seq->scene_sound = NULL; | seq->scene_sound = NULL; | ||||
| /* We add a very small negative offset here, because | /* We round the frame duration as the audio sample lenghts usually does not | ||||
| * ceil(132.0) == 133.0, not nice with videos, see T47135. */ | * line up with the video frames. Therefore we round this number to the | ||||
| seq->len = MAX2(1, (int)ceil((double)info.length * FPS - 1e-4)); | * nearsest frame as the audio track usually overshoots or undershoots the | ||||
| * end frame ofthe video by a little bit. | |||||
| * See T47135 for under shoot example. | |||||
| */ | |||||
| seq->len = MAX2(1, round((info.length - sound->offset_time) * FPS)); | |||||
| Strip *strip = seq->strip; | Strip *strip = seq->strip; | ||||
| /* We only need 1 element to store the filename. */ | /* We only need 1 element to store the filename. */ | ||||
| StripElem *se = strip->stripdata = se = MEM_callocN(sizeof(StripElem), "stripelem"); | StripElem *se = strip->stripdata = se = MEM_callocN(sizeof(StripElem), "stripelem"); | ||||
| BLI_split_dirfile(load_data->path, strip->dir, se->name, sizeof(strip->dir), sizeof(se->name)); | BLI_split_dirfile(load_data->path, strip->dir, se->name, sizeof(strip->dir), sizeof(se->name)); | ||||
| if (seq != NULL && seq->sound != NULL) { | if (seq != NULL && seq->sound != NULL) { | ||||
| if (load_data->flags & SEQ_LOAD_SOUND_MONO) { | if (load_data->flags & SEQ_LOAD_SOUND_MONO) { | ||||
| ▲ Show 20 Lines • Show All 55 Lines • ▼ Show 20 Lines | |||||
| * Add movie strip. | * Add movie strip. | ||||
| * | * | ||||
| * \param main: Main reference | * \param main: Main reference | ||||
| * \param scene: Scene where strips will be added | * \param scene: Scene where strips will be added | ||||
| * \param seqbase: ListBase where strips will be added | * \param seqbase: ListBase where strips will be added | ||||
| * \param load_data: SeqLoadData with information necessary to create strip | * \param load_data: SeqLoadData with information necessary to create strip | ||||
| * \return created strip | * \return created strip | ||||
| */ | */ | ||||
| Sequence *SEQ_add_movie_strip(Main *bmain, Scene *scene, ListBase *seqbase, SeqLoadData *load_data) | Sequence *SEQ_add_movie_strip(Main *bmain, | ||||
| Scene *scene, | |||||
| ListBase *seqbase, | |||||
| SeqLoadData *load_data, | |||||
| double *r_video_start_offset) | |||||
| { | { | ||||
| char path[sizeof(load_data->path)]; | char path[sizeof(load_data->path)]; | ||||
| BLI_strncpy(path, load_data->path, sizeof(path)); | BLI_strncpy(path, load_data->path, sizeof(path)); | ||||
| BLI_path_abs(path, BKE_main_blendfile_path(bmain)); | BLI_path_abs(path, BKE_main_blendfile_path(bmain)); | ||||
| char colorspace[64] = "\0"; /* MAX_COLORSPACE_NAME */ | char colorspace[64] = "\0"; /* MAX_COLORSPACE_NAME */ | ||||
| bool is_multiview_loaded = false; | bool is_multiview_loaded = false; | ||||
| const int totfiles = seq_num_files(scene, load_data->views_format, load_data->use_multiview); | const int totfiles = seq_num_files(scene, load_data->views_format, load_data->use_multiview); | ||||
| ▲ Show 20 Lines • Show All 55 Lines • ▼ Show 20 Lines | for (i = 0; i < totfiles; i++) { | ||||
| else { | else { | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| seq->blend_mode = SEQ_TYPE_CROSS; /* so alpha adjustment fade to the strip below */ | seq->blend_mode = SEQ_TYPE_CROSS; /* so alpha adjustment fade to the strip below */ | ||||
| if (anim_arr[0] != NULL) { | if (anim_arr[0] != NULL) { | ||||
| seq->anim_preseek = IMB_anim_get_preseek(anim_arr[0]); | |||||
| seq->len = IMB_anim_get_duration(anim_arr[0], IMB_TC_RECORD_RUN); | seq->len = IMB_anim_get_duration(anim_arr[0], IMB_TC_RECORD_RUN); | ||||
| *r_video_start_offset = IMD_anim_get_offset(anim_arr[0]); | |||||
| IMB_anim_load_metadata(anim_arr[0]); | IMB_anim_load_metadata(anim_arr[0]); | ||||
| /* Adjust scene's frame rate settings to match. */ | /* Adjust scene's frame rate settings to match. */ | ||||
| if (load_data->flags & SEQ_LOAD_MOVIE_SYNC_FPS) { | if (load_data->flags & SEQ_LOAD_MOVIE_SYNC_FPS) { | ||||
| IMB_anim_get_fps(anim_arr[0], &scene->r.frs_sec, &scene->r.frs_sec_base, true); | IMB_anim_get_fps(anim_arr[0], &scene->r.frs_sec, &scene->r.frs_sec_base, true); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 124 Lines • ▼ Show 20 Lines | case SEQ_TYPE_MOVIE: { | ||||
| return; | return; | ||||
| } | } | ||||
| IMB_anim_load_metadata(sanim->anim); | IMB_anim_load_metadata(sanim->anim); | ||||
| seq->len = IMB_anim_get_duration( | seq->len = IMB_anim_get_duration( | ||||
| sanim->anim, seq->strip->proxy ? seq->strip->proxy->tc : IMB_TC_RECORD_RUN); | sanim->anim, seq->strip->proxy ? seq->strip->proxy->tc : IMB_TC_RECORD_RUN); | ||||
| seq->anim_preseek = IMB_anim_get_preseek(sanim->anim); | |||||
| seq->len -= seq->anim_startofs; | seq->len -= seq->anim_startofs; | ||||
| seq->len -= seq->anim_endofs; | seq->len -= seq->anim_endofs; | ||||
| if (seq->len < 0) { | if (seq->len < 0) { | ||||
| seq->len = 0; | seq->len = 0; | ||||
| } | } | ||||
| break; | break; | ||||
| } | } | ||||
| case SEQ_TYPE_MOVIECLIP: | case SEQ_TYPE_MOVIECLIP: | ||||
| ▲ Show 20 Lines • Show All 118 Lines • Show Last 20 Lines | |||||