Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--extern/audaspace/bindings/C/AUD_Special.cpp2
-rw-r--r--extern/audaspace/bindings/C/AUD_Types.h1
-rw-r--r--extern/audaspace/include/IReader.h6
-rw-r--r--extern/audaspace/include/fx/VolumeReader.h2
-rw-r--r--extern/audaspace/plugins/ffmpeg/FFMPEGReader.cpp80
-rw-r--r--extern/audaspace/plugins/ffmpeg/FFMPEGReader.h17
-rw-r--r--extern/audaspace/src/fx/VolumeReader.cpp2
-rw-r--r--source/blender/blenkernel/BKE_sound.h9
-rw-r--r--source/blender/blenkernel/intern/sound.c12
-rw-r--r--source/blender/editors/space_sequencer/sequencer_add.c16
-rw-r--r--source/blender/editors/space_sequencer/sequencer_draw.c10
-rw-r--r--source/blender/imbuf/IMB_imbuf.h5
-rw-r--r--source/blender/imbuf/intern/IMB_anim.h1
-rw-r--r--source/blender/imbuf/intern/anim_movie.c27
-rw-r--r--source/blender/makesdna/DNA_sound_types.h1
-rw-r--r--source/blender/makesrna/intern/rna_sequencer_api.c5
-rw-r--r--source/blender/sequencer/SEQ_add.h6
-rw-r--r--source/blender/sequencer/intern/sound.c7
-rw-r--r--source/blender/sequencer/intern/strip_add.c46
-rw-r--r--source/blender/sequencer/intern/strip_time.c4
20 files changed, 197 insertions, 62 deletions
diff --git a/extern/audaspace/bindings/C/AUD_Special.cpp b/extern/audaspace/bindings/C/AUD_Special.cpp
index ac876a01eb3..97e5f5540de 100644
--- a/extern/audaspace/bindings/C/AUD_Special.cpp
+++ b/extern/audaspace/bindings/C/AUD_Special.cpp
@@ -86,6 +86,7 @@ AUD_API AUD_SoundInfo AUD_getInfo(AUD_Sound* sound)
info.specs.channels = AUD_CHANNELS_INVALID;
info.specs.rate = AUD_RATE_INVALID;
info.length = 0.0f;
+ info.start_offset = 0.0f;
try
{
@@ -95,6 +96,7 @@ AUD_API AUD_SoundInfo AUD_getInfo(AUD_Sound* sound)
{
info.specs = convSpecToC(reader->getSpecs());
info.length = reader->getLength() / (float) info.specs.rate;
+ info.start_offset = reader->getStartOffset();
}
}
catch(Exception&)
diff --git a/extern/audaspace/bindings/C/AUD_Types.h b/extern/audaspace/bindings/C/AUD_Types.h
index 75e4ffae18c..c6a96d30d3f 100644
--- a/extern/audaspace/bindings/C/AUD_Types.h
+++ b/extern/audaspace/bindings/C/AUD_Types.h
@@ -176,4 +176,5 @@ typedef struct
{
AUD_Specs specs;
float length;
+ double start_offset;
} AUD_SoundInfo;
diff --git a/extern/audaspace/include/IReader.h b/extern/audaspace/include/IReader.h
index c29900ca579..f6070b0f23b 100644
--- a/extern/audaspace/include/IReader.h
+++ b/extern/audaspace/include/IReader.h
@@ -71,6 +71,12 @@ public:
virtual int getPosition() const=0;
/**
+ * Returns the start offset the sound should have to line up with related sources.
+ * \return The required start offset in seconds.
+ */
+ virtual double getStartOffset() const { return 0.0;}
+
+ /**
* Returns the specification of the reader.
* \return The Specs structure.
*/
diff --git a/extern/audaspace/include/fx/VolumeReader.h b/extern/audaspace/include/fx/VolumeReader.h
index 13b6845e931..f7169f4c78b 100644
--- a/extern/audaspace/include/fx/VolumeReader.h
+++ b/extern/audaspace/include/fx/VolumeReader.h
@@ -67,4 +67,4 @@ public:
virtual void read(int& length, bool& eos, sample_t* buffer);
};
-AUD_NAMESPACE_END \ No newline at end of file
+AUD_NAMESPACE_END
diff --git a/extern/audaspace/plugins/ffmpeg/FFMPEGReader.cpp b/extern/audaspace/plugins/ffmpeg/FFMPEGReader.cpp
index b46f65eddbf..afdc7fcfcc6 100644
--- a/extern/audaspace/plugins/ffmpeg/FFMPEGReader.cpp
+++ b/extern/audaspace/plugins/ffmpeg/FFMPEGReader.cpp
@@ -68,7 +68,7 @@ int FFMPEGReader::decode(AVPacket& packet, Buffer& buffer)
for(int i = 0; i < m_frame->nb_samples; i++)
{
std::memcpy(((data_t*)buffer.getBuffer()) + buf_pos + ((m_codecCtx->channels * i) + channel) * single_size,
- m_frame->data[channel] + i * single_size, single_size);
+ m_frame->data[channel] + i * single_size, single_size);
}
}
}
@@ -109,7 +109,7 @@ int FFMPEGReader::decode(AVPacket& packet, Buffer& buffer)
for(int i = 0; i < m_frame->nb_samples; i++)
{
std::memcpy(((data_t*)buffer.getBuffer()) + buf_pos + ((m_codecCtx->channels * i) + channel) * single_size,
- m_frame->data[channel] + i * single_size, single_size);
+ m_frame->data[channel] + i * single_size, single_size);
}
}
}
@@ -126,7 +126,10 @@ int FFMPEGReader::decode(AVPacket& packet, Buffer& buffer)
void FFMPEGReader::init()
{
m_position = 0;
+ m_start_offset = 0.0f;
m_pkgbuf_left = 0;
+ m_st_time = 0;
+ m_duration = 0;
if(avformat_find_stream_info(m_formatCtx, nullptr) < 0)
AUD_THROW(FileException, "File couldn't be read, ffmpeg couldn't find the stream info.");
@@ -134,15 +137,41 @@ void FFMPEGReader::init()
// find audio stream and codec
m_stream = -1;
+ double dur_sec = 0;
+
for(unsigned int i = 0; i < m_formatCtx->nb_streams; i++)
{
#ifdef FFMPEG_OLD_CODE
- if((m_formatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO)
+ if(m_formatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO)
#else
- if((m_formatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
+ if(m_formatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
#endif
- && (m_stream < 0))
{
+ AVStream *audio_stream = m_formatCtx->streams[i];
+ double audio_timebase = av_q2d(audio_stream->time_base);
+
+ if (audio_stream->start_time != AV_NOPTS_VALUE)
+ {
+ m_st_time = audio_stream->start_time;
+ }
+
+ int64_t ctx_start_time = 0;
+ if (m_formatCtx->start_time != AV_NOPTS_VALUE) {
+ ctx_start_time = m_formatCtx->start_time;
+ }
+
+ m_start_offset = m_st_time * audio_timebase - (double)ctx_start_time / AV_TIME_BASE;
+
+ if(audio_stream->duration != AV_NOPTS_VALUE)
+ {
+ dur_sec = audio_stream->duration * audio_timebase;
+ }
+ else
+ {
+ /* If the audio starts after the stream start time, subract this from the total duration. */
+ dur_sec = (double)m_formatCtx->duration / AV_TIME_BASE - m_start_offset;
+ }
+
m_stream=i;
break;
}
@@ -213,6 +242,7 @@ void FFMPEGReader::init()
}
m_specs.rate = (SampleRate) m_codecCtx->sample_rate;
+ m_duration = lround(dur_sec * m_codecCtx->sample_rate);
}
FFMPEGReader::FFMPEGReader(std::string filename) :
@@ -338,21 +368,17 @@ void FFMPEGReader::seek(int position)
{
if(position >= 0)
{
- uint64_t st_time = m_formatCtx->start_time;
- uint64_t seek_pos = ((uint64_t)position) * ((uint64_t)AV_TIME_BASE) / ((uint64_t)m_specs.rate);
+ double pts_time_base =
+ av_q2d(m_formatCtx->streams[m_stream]->time_base);
- if(st_time != AV_NOPTS_VALUE) {
- seek_pos += st_time;
- }
+ uint64_t seek_pts = (((uint64_t)position) / ((uint64_t)m_specs.rate)) / pts_time_base;
- double pts_time_base =
- av_q2d(m_formatCtx->streams[m_stream]->time_base);
- uint64_t pts_st_time =
- ((st_time != AV_NOPTS_VALUE) ? st_time : 0)
- / pts_time_base / (uint64_t) AV_TIME_BASE;
+ if(m_st_time != AV_NOPTS_VALUE) {
+ seek_pts += m_st_time;
+ }
// a value < 0 tells us that seeking failed
- if(av_seek_frame(m_formatCtx, -1, seek_pos,
+ if(av_seek_frame(m_formatCtx, m_stream, seek_pts,
AVSEEK_FLAG_BACKWARD | AVSEEK_FLAG_ANY) >= 0)
{
avcodec_flush_buffers(m_codecCtx);
@@ -374,7 +400,7 @@ void FFMPEGReader::seek(int position)
if(packet.pts != AV_NOPTS_VALUE)
{
// calculate real position, and read to frame!
- m_position = (packet.pts - pts_st_time) * pts_time_base * m_specs.rate;
+ m_position = (packet.pts - m_st_time) * pts_time_base * m_specs.rate;
if(m_position < position)
{
@@ -405,8 +431,7 @@ void FFMPEGReader::seek(int position)
int FFMPEGReader::getLength() const
{
// return approximated remaning size
- return (int)((m_formatCtx->duration * m_codecCtx->sample_rate)
- / AV_TIME_BASE)-m_position;
+ return m_duration - m_position;
}
int FFMPEGReader::getPosition() const
@@ -414,6 +439,11 @@ int FFMPEGReader::getPosition() const
return m_position;
}
+double FFMPEGReader::getStartOffset() const
+{
+ return m_start_offset;
+}
+
Specs FFMPEGReader::getSpecs() const
{
return m_specs.specs;
@@ -450,11 +480,13 @@ void FFMPEGReader::read(int& length, bool& eos, sample_t* buffer)
// decode the package
pkgbuf_pos = decode(packet, m_pkgbuf);
- // copy to output buffer
- data_size = std::min(pkgbuf_pos, left * sample_size);
- m_convert((data_t*) buf, (data_t*) m_pkgbuf.getBuffer(), data_size / AUD_FORMAT_SIZE(m_specs.format));
- buf += data_size / AUD_FORMAT_SIZE(m_specs.format);
- left -= data_size / sample_size;
+ if (packet.pts >= m_st_time) {
+ // copy to output buffer
+ data_size = std::min(pkgbuf_pos, left * sample_size);
+ m_convert((data_t*) buf, (data_t*) m_pkgbuf.getBuffer(), data_size / AUD_FORMAT_SIZE(m_specs.format));
+ buf += data_size / AUD_FORMAT_SIZE(m_specs.format);
+ left -= data_size / sample_size;
+ }
}
av_packet_unref(&packet);
}
diff --git a/extern/audaspace/plugins/ffmpeg/FFMPEGReader.h b/extern/audaspace/plugins/ffmpeg/FFMPEGReader.h
index f62436ac83b..d613457c220 100644
--- a/extern/audaspace/plugins/ffmpeg/FFMPEGReader.h
+++ b/extern/audaspace/plugins/ffmpeg/FFMPEGReader.h
@@ -55,6 +55,22 @@ private:
int m_position;
/**
+ * The start offset in seconds relative to the media container start time.
+ * IE how much the sound should be delayed to be kept in sync with the rest of the containter streams.
+ */
+ double m_start_offset;
+
+ /**
+ * The start time pts of the stream. All packets before this timestamp shouldn't be played back (only decoded).
+ */
+ int64_t m_st_time;
+
+ /**
+ * The duration of the audio stream in samples.
+ */
+ int64_t m_duration;
+
+ /**
* The specification of the audio data.
*/
DeviceSpecs m_specs;
@@ -182,6 +198,7 @@ public:
virtual void seek(int position);
virtual int getLength() const;
virtual int getPosition() const;
+ virtual double getStartOffset() const;
virtual Specs getSpecs() const;
virtual void read(int& length, bool& eos, sample_t* buffer);
};
diff --git a/extern/audaspace/src/fx/VolumeReader.cpp b/extern/audaspace/src/fx/VolumeReader.cpp
index ac1d4882a87..627acbac9ef 100644
--- a/extern/audaspace/src/fx/VolumeReader.cpp
+++ b/extern/audaspace/src/fx/VolumeReader.cpp
@@ -57,4 +57,4 @@ void VolumeReader::read(int& length, bool& eos, sample_t* buffer)
buffer[i] = buffer[i] * m_volumeStorage->getVolume();
}
-AUD_NAMESPACE_END \ No newline at end of file
+AUD_NAMESPACE_END
diff --git a/source/blender/blenkernel/BKE_sound.h b/source/blender/blenkernel/BKE_sound.h
index 57ce33a239f..4b257b3b8ab 100644
--- a/source/blender/blenkernel/BKE_sound.h
+++ b/source/blender/blenkernel/BKE_sound.h
@@ -97,6 +97,7 @@ typedef struct SoundInfo {
eSoundChannels channels;
} specs;
float length;
+ double start_offset;
} SoundInfo;
/* Get information about given sound. Returns truth on success., false if sound can not be loaded
@@ -139,8 +140,12 @@ void BKE_sound_remove_scene_sound(struct Scene *scene, void *handle);
void BKE_sound_mute_scene_sound(void *handle, char mute);
-void BKE_sound_move_scene_sound(
- struct Scene *scene, void *handle, int startframe, int endframe, int frameskip);
+void BKE_sound_move_scene_sound(struct Scene *scene,
+ void *handle,
+ int startframe,
+ int endframe,
+ int frameskip,
+ double audio_offset);
void BKE_sound_move_scene_sound_defaults(struct Scene *scene, struct Sequence *sequence);
void BKE_sound_update_scene_sound(void *handle, struct bSound *sound);
diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c
index fcb992e1535..9d287377545 100644
--- a/source/blender/blenkernel/intern/sound.c
+++ b/source/blender/blenkernel/intern/sound.c
@@ -709,7 +709,7 @@ void *BKE_sound_scene_add_scene_sound(
sequence->scene->sound_scene,
startframe / fps,
endframe / fps,
- frameskip / fps);
+ frameskip / fps + sequence->sound->offset_time);
}
return NULL;
}
@@ -737,7 +737,7 @@ void *BKE_sound_add_scene_sound(
sequence->sound->playback_handle,
startframe / fps,
endframe / fps,
- frameskip / fps);
+ frameskip / fps + sequence->sound->offset_time);
AUD_SequenceEntry_setMuted(handle, (sequence->flag & SEQ_MUTE) != 0);
AUD_SequenceEntry_setAnimationData(handle, AUD_AP_VOLUME, CFRA, &sequence->volume, 0);
AUD_SequenceEntry_setAnimationData(handle, AUD_AP_PITCH, CFRA, &sequence->pitch, 0);
@@ -765,11 +765,11 @@ void BKE_sound_mute_scene_sound(void *handle, char mute)
}
void BKE_sound_move_scene_sound(
- Scene *scene, void *handle, int startframe, int endframe, int frameskip)
+ Scene *scene, void *handle, int startframe, int endframe, int frameskip, double audio_offset)
{
sound_verify_evaluated_id(&scene->id);
const double fps = FPS;
- AUD_SequenceEntry_move(handle, startframe / fps, endframe / fps, frameskip / fps);
+ AUD_SequenceEntry_move(handle, startframe / fps, endframe / fps, frameskip / fps + audio_offset);
}
void BKE_sound_move_scene_sound_defaults(Scene *scene, Sequence *sequence)
@@ -780,7 +780,8 @@ void BKE_sound_move_scene_sound_defaults(Scene *scene, Sequence *sequence)
sequence->scene_sound,
sequence->startdisp,
sequence->enddisp,
- sequence->startofs + sequence->anim_startofs);
+ sequence->startofs + sequence->anim_startofs,
+ sequence->sound->offset_time);
}
}
@@ -1213,6 +1214,7 @@ static bool sound_info_from_playback_handle(void *playback_handle, SoundInfo *so
AUD_SoundInfo info = AUD_getInfo(playback_handle);
sound_info->specs.channels = (eSoundChannels)info.specs.channels;
sound_info->length = info.length;
+ sound_info->start_offset = info.start_offset;
return true;
}
diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c
index 47495eaa57a..ff8cbdb1a59 100644
--- a/source/blender/editors/space_sequencer/sequencer_add.c
+++ b/source/blender/editors/space_sequencer/sequencer_add.c
@@ -643,15 +643,17 @@ static void sequencer_add_movie_multiple_strips(bContext *C,
BLI_strncpy(load_data->name, file_only, sizeof(load_data->name));
Sequence *seq_movie = NULL;
Sequence *seq_sound = NULL;
+ double video_start_offset;
+
load_data->channel++;
- seq_movie = SEQ_add_movie_strip(bmain, scene, ed->seqbasep, load_data);
+ seq_movie = SEQ_add_movie_strip(bmain, scene, ed->seqbasep, load_data, &video_start_offset);
load_data->channel--;
if (seq_movie == NULL) {
BKE_reportf(op->reports, RPT_ERROR, "File '%s' could not be loaded", load_data->path);
}
else {
if (RNA_boolean_get(op->ptr, "sound")) {
- seq_sound = SEQ_add_sound_strip(bmain, scene, ed->seqbasep, load_data);
+ seq_sound = SEQ_add_sound_strip(bmain, scene, ed->seqbasep, load_data, video_start_offset);
}
load_data->start_frame += seq_movie->enddisp - seq_movie->startdisp;
seq_load_apply_generic_options(C, op, seq_sound);
@@ -670,8 +672,10 @@ static bool sequencer_add_movie_single_strip(bContext *C, wmOperator *op, SeqLoa
Sequence *seq_movie = NULL;
Sequence *seq_sound = NULL;
+ double video_start_offset;
+
load_data->channel++;
- seq_movie = SEQ_add_movie_strip(bmain, scene, ed->seqbasep, load_data);
+ seq_movie = SEQ_add_movie_strip(bmain, scene, ed->seqbasep, load_data, &video_start_offset);
load_data->channel--;
if (seq_movie == NULL) {
@@ -679,7 +683,7 @@ static bool sequencer_add_movie_single_strip(bContext *C, wmOperator *op, SeqLoa
return false;
}
if (RNA_boolean_get(op->ptr, "sound")) {
- seq_sound = SEQ_add_sound_strip(bmain, scene, ed->seqbasep, load_data);
+ seq_sound = SEQ_add_sound_strip(bmain, scene, ed->seqbasep, load_data, video_start_offset);
}
seq_load_apply_generic_options(C, op, seq_sound);
seq_load_apply_generic_options(C, op, seq_movie);
@@ -822,7 +826,7 @@ static void sequencer_add_sound_multiple_strips(bContext *C,
RNA_string_get(&itemptr, "name", file_only);
BLI_join_dirfile(load_data->path, sizeof(load_data->path), dir_only, file_only);
BLI_strncpy(load_data->name, file_only, sizeof(load_data->name));
- Sequence *seq = SEQ_add_sound_strip(bmain, scene, ed->seqbasep, load_data);
+ Sequence *seq = SEQ_add_sound_strip(bmain, scene, ed->seqbasep, load_data, 0.0f);
if (seq == NULL) {
BKE_reportf(op->reports, RPT_ERROR, "File '%s' could not be loaded", load_data->path);
}
@@ -840,7 +844,7 @@ static bool sequencer_add_sound_single_strip(bContext *C, wmOperator *op, SeqLoa
Scene *scene = CTX_data_scene(C);
Editing *ed = SEQ_editing_get(scene, true);
- Sequence *seq = SEQ_add_sound_strip(bmain, scene, ed->seqbasep, load_data);
+ Sequence *seq = SEQ_add_sound_strip(bmain, scene, ed->seqbasep, load_data, 0.0f);
if (seq == NULL) {
BKE_reportf(op->reports, RPT_ERROR, "File '%s' could not be loaded", load_data->path);
return false;
diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c
index 0472e1264ce..e49a88c88d2 100644
--- a/source/blender/editors/space_sequencer/sequencer_draw.c
+++ b/source/blender/editors/space_sequencer/sequencer_draw.c
@@ -284,10 +284,12 @@ static void draw_seq_waveform_overlay(View2D *v2d,
return;
}
- startsample = floor((seq->startofs + seq->anim_startofs) / FPS *
- SOUND_WAVE_SAMPLES_PER_SECOND);
- endsample = ceil((seq->startofs + seq->anim_startofs + seq->enddisp - seq->startdisp) / FPS *
- SOUND_WAVE_SAMPLES_PER_SECOND);
+ startsample = (seq->startofs + seq->anim_startofs) / FPS * SOUND_WAVE_SAMPLES_PER_SECOND;
+ startsample += seq->sound->offset_time * SOUND_WAVE_SAMPLES_PER_SECOND;
+
+ endsample = (seq->enddisp - seq->startdisp) / FPS * SOUND_WAVE_SAMPLES_PER_SECOND;
+ endsample += startsample;
+
samplestep = (endsample - startsample) * stepsize / (x2 - x1);
length = min_ii(
diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h
index d527aca184c..4ad7aa98484 100644
--- a/source/blender/imbuf/IMB_imbuf.h
+++ b/source/blender/imbuf/IMB_imbuf.h
@@ -367,6 +367,11 @@ void IMB_anim_index_rebuild_finish(struct IndexBuildContext *context, short stop
int IMB_anim_get_duration(struct anim *anim, IMB_Timecode_Type tc);
/**
+ * Return the encoded start offset (in seconds) of the given \a anim.
+ */
+double IMD_anim_get_offset(struct anim *anim);
+
+/**
* Return the fps contained in movie files (function rval is false,
* and frs_sec and frs_sec_base untouched if none available!)
*/
diff --git a/source/blender/imbuf/intern/IMB_anim.h b/source/blender/imbuf/intern/IMB_anim.h
index cfeffcca0ea..c4e2ad9da7f 100644
--- a/source/blender/imbuf/intern/IMB_anim.h
+++ b/source/blender/imbuf/intern/IMB_anim.h
@@ -91,6 +91,7 @@ struct anim {
int duration_in_frames;
int frs_sec;
double frs_sec_base;
+ double start_offset;
int x, y;
/* for number */
diff --git a/source/blender/imbuf/intern/anim_movie.c b/source/blender/imbuf/intern/anim_movie.c
index fd96110b59e..2998c4781b6 100644
--- a/source/blender/imbuf/intern/anim_movie.c
+++ b/source/blender/imbuf/intern/anim_movie.c
@@ -425,6 +425,7 @@ static int startavi(struct anim *anim)
}
anim->duration_in_frames = anim->avi->header->TotalFrames;
+ anim->start_offset = 0.0f;
anim->params = NULL;
anim->x = anim->avi->header->Width;
@@ -597,6 +598,13 @@ static int startffmpeg(struct anim *anim)
return -1;
}
+ double video_start = 0;
+ double pts_time_base = av_q2d(video_stream->time_base);
+
+ if (video_stream->start_time != AV_NOPTS_VALUE) {
+ video_start = video_stream->start_time * pts_time_base;
+ }
+
frame_rate = av_guess_frame_rate(pFormatCtx, video_stream, NULL);
anim->duration_in_frames = 0;
@@ -620,20 +628,14 @@ static int startffmpeg(struct anim *anim)
* This is because the video stream duration can be shorter than the pFormatCtx->duration.
*/
if (anim->duration_in_frames == 0) {
- double pts_time_base = av_q2d(video_stream->time_base);
double stream_dur;
if (video_stream->duration != AV_NOPTS_VALUE) {
stream_dur = video_stream->duration * pts_time_base;
}
else {
- double video_start = 0;
double audio_start = 0;
- if (video_stream->start_time != AV_NOPTS_VALUE) {
- video_start = video_stream->start_time * pts_time_base;
- }
-
/* Find audio stream to guess the duration of the video.
* Sometimes the audio AND the video stream have a start offset.
* The difference between these is the offset we want to use to
@@ -662,6 +664,11 @@ static int startffmpeg(struct anim *anim)
anim->duration_in_frames = (int)(stream_dur * av_q2d(frame_rate) + 0.5f);
}
+ double ctx_start = 0;
+ if (pFormatCtx->start_time != AV_NOPTS_VALUE) {
+ ctx_start = (double)pFormatCtx->start_time / AV_TIME_BASE;
+ }
+
frs_num = frame_rate.num;
frs_den = frame_rate.den;
@@ -674,6 +681,9 @@ static int startffmpeg(struct anim *anim)
anim->frs_sec = frs_num;
anim->frs_sec_base = frs_den;
+ /* Save the relative start time for the video. IE the start time in relation to where playback
+ * starts. */
+ anim->start_offset = video_start - ctx_start;
anim->params = 0;
@@ -1672,6 +1682,11 @@ int IMB_anim_get_duration(struct anim *anim, IMB_Timecode_Type tc)
return IMB_indexer_get_duration(idx);
}
+double IMD_anim_get_offset(struct anim *anim)
+{
+ return anim->start_offset;
+}
+
bool IMB_anim_get_fps(struct anim *anim, short *frs_sec, float *frs_sec_base, bool no_av_base)
{
double frs_sec_base_double;
diff --git a/source/blender/makesdna/DNA_sound_types.h b/source/blender/makesdna/DNA_sound_types.h
index b2bb50c56a2..e6394f0a56a 100644
--- a/source/blender/makesdna/DNA_sound_types.h
+++ b/source/blender/makesdna/DNA_sound_types.h
@@ -67,6 +67,7 @@ typedef struct bSound {
/** Runtime only, always reset in readfile. */
short tags;
char _pad[4];
+ double offset_time;
/* Unused currently. */
// int type;
diff --git a/source/blender/makesrna/intern/rna_sequencer_api.c b/source/blender/makesrna/intern/rna_sequencer_api.c
index 4895ab11618..264ccccd350 100644
--- a/source/blender/makesrna/intern/rna_sequencer_api.c
+++ b/source/blender/makesrna/intern/rna_sequencer_api.c
@@ -310,7 +310,8 @@ static Sequence *rna_Sequences_new_movie(ID *id,
SEQ_add_load_data_init(&load_data, name, file, frame_start, channel);
load_data.fit_method = fit_method;
load_data.allow_invalid_file = true;
- Sequence *seq = SEQ_add_movie_strip(bmain, scene, seqbase, &load_data);
+ double video_start_offset;
+ Sequence *seq = SEQ_add_movie_strip(bmain, scene, seqbase, &load_data, &video_start_offset);
DEG_relations_tag_update(bmain);
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
@@ -359,7 +360,7 @@ static Sequence *rna_Sequences_new_sound(ID *id,
SeqLoadData load_data;
SEQ_add_load_data_init(&load_data, name, file, frame_start, channel);
load_data.allow_invalid_file = true;
- Sequence *seq = SEQ_add_sound_strip(bmain, scene, seqbase, &load_data);
+ Sequence *seq = SEQ_add_sound_strip(bmain, scene, seqbase, &load_data, 0.0f);
if (seq == NULL) {
BKE_report(reports, RPT_ERROR, "Sequences.new_sound: unable to open sound file");
diff --git a/source/blender/sequencer/SEQ_add.h b/source/blender/sequencer/SEQ_add.h
index 2941eb6f4c0..4025f1a4a04 100644
--- a/source/blender/sequencer/SEQ_add.h
+++ b/source/blender/sequencer/SEQ_add.h
@@ -79,14 +79,16 @@ struct Sequence *SEQ_add_image_strip(struct Main *bmain,
struct Sequence *SEQ_add_sound_strip(struct Main *bmain,
struct Scene *scene,
struct ListBase *seqbase,
- struct SeqLoadData *load_data);
+ struct SeqLoadData *load_data,
+ const double audio_offset);
struct Sequence *SEQ_add_meta_strip(struct Scene *scene,
struct ListBase *seqbase,
struct SeqLoadData *load_data);
struct Sequence *SEQ_add_movie_strip(struct Main *bmain,
struct Scene *scene,
struct ListBase *seqbase,
- struct SeqLoadData *load_data);
+ struct SeqLoadData *load_data,
+ double *r_video_start_offset);
struct Sequence *SEQ_add_scene_strip(struct Scene *scene,
struct ListBase *seqbase,
struct SeqLoadData *load_data);
diff --git a/source/blender/sequencer/intern/sound.c b/source/blender/sequencer/intern/sound.c
index 1054dbeeba6..c53aacddcfe 100644
--- a/source/blender/sequencer/intern/sound.c
+++ b/source/blender/sequencer/intern/sound.c
@@ -111,7 +111,12 @@ void SEQ_sound_update_bounds(Scene *scene, Sequence *seq)
/* We have to take into account start frame of the sequence's scene! */
int startofs = seq->startofs + seq->anim_startofs + seq->scene->r.sfra;
- BKE_sound_move_scene_sound(scene, seq->scene_sound, seq->startdisp, seq->enddisp, startofs);
+ BKE_sound_move_scene_sound(scene,
+ seq->scene_sound,
+ seq->startdisp,
+ seq->enddisp,
+ startofs,
+ seq->sound->offset_time);
}
}
else {
diff --git a/source/blender/sequencer/intern/strip_add.c b/source/blender/sequencer/intern/strip_add.c
index dab5593be37..cc70cc38ebb 100644
--- a/source/blender/sequencer/intern/strip_add.c
+++ b/source/blender/sequencer/intern/strip_add.c
@@ -382,9 +382,14 @@ Sequence *SEQ_add_image_strip(Main *bmain, Scene *scene, ListBase *seqbase, SeqL
* \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. */
+ sound->offset_time = audio_offset;
SoundInfo info;
bool sound_loaded = BKE_sound_info_get(bmain, sound, &info);
@@ -398,14 +403,36 @@ Sequence *SEQ_add_sound_strip(Main *bmain, Scene *scene, ListBase *seqbase, SeqL
return NULL;
}
- Sequence *seq = SEQ_sequence_alloc(
- seqbase, load_data->start_frame, load_data->channel, SEQ_TYPE_SOUND_RAM);
+ /* If this sound it part of a video, then the sound might start after the video.
+ * 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->scene_sound = NULL;
- /* We add a very small negative offset here, because
- * ceil(132.0) == 133.0, not nice with videos, see T47135. */
- seq->len = MAX2(1, (int)ceil((double)info.length * FPS - 1e-4));
+ /* We round the frame duration as the audio sample lenghts usually does not
+ * line up with the video frames. Therefore we round this number to the
+ * 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;
/* We only need 1 element to store the filename. */
@@ -477,7 +504,11 @@ Sequence *SEQ_add_meta_strip(Scene *scene, ListBase *seqbase, SeqLoadData *load_
* \param load_data: SeqLoadData with information necessary to create 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)];
BLI_strncpy(path, load_data->path, sizeof(path));
@@ -552,6 +583,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);
+ *r_video_start_offset = IMD_anim_get_offset(anim_arr[0]);
IMB_anim_load_metadata(anim_arr[0]);
diff --git a/source/blender/sequencer/intern/strip_time.c b/source/blender/sequencer/intern/strip_time.c
index 68128690773..b73ac631693 100644
--- a/source/blender/sequencer/intern/strip_time.c
+++ b/source/blender/sequencer/intern/strip_time.c
@@ -34,6 +34,7 @@
#include "BKE_scene.h"
#include "BKE_sound.h"
+#include "DNA_sound_types.h"
#include "IMB_imbuf.h"
#include "SEQ_iterator.h"
@@ -134,7 +135,8 @@ static void seq_update_sound_bounds_recursive_impl(Scene *scene,
seq->scene_sound,
seq->start + startofs,
seq->start + seq->len - endofs,
- startofs + seq->anim_startofs);
+ startofs + seq->anim_startofs,
+ seq->sound->offset_time);
}
}
}