diff options
Diffstat (limited to 'extern/audaspace')
-rw-r--r-- | extern/audaspace/bindings/C/AUD_Special.cpp | 2 | ||||
-rw-r--r-- | extern/audaspace/bindings/C/AUD_Types.h | 1 | ||||
-rw-r--r-- | extern/audaspace/include/IReader.h | 6 | ||||
-rw-r--r-- | extern/audaspace/include/fx/VolumeReader.h | 2 | ||||
-rw-r--r-- | extern/audaspace/plugins/ffmpeg/FFMPEGReader.cpp | 80 | ||||
-rw-r--r-- | extern/audaspace/plugins/ffmpeg/FFMPEGReader.h | 17 | ||||
-rw-r--r-- | extern/audaspace/src/fx/VolumeReader.cpp | 2 |
7 files changed, 84 insertions, 26 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 |