aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortrialuser02 <trialuser02@90c681e8-e032-0410-971d-27865f9a5e38>2009-10-31 18:25:23 +0000
committertrialuser02 <trialuser02@90c681e8-e032-0410-971d-27865f9a5e38>2009-10-31 18:25:23 +0000
commit793a032bbba9ab1a3d3917206c54dd4e136abbc8 (patch)
treed314af565556724ce1e406a31cb2940008ff9583
parent3fa2bfef4093a9698edb49439fdfbb8d6f7cb451 (diff)
downloadqmmp-793a032bbba9ab1a3d3917206c54dd4e136abbc8.tar.gz
qmmp-793a032bbba9ab1a3d3917206c54dd4e136abbc8.tar.bz2
qmmp-793a032bbba9ab1a3d3917206c54dd4e136abbc8.zip
fixed ape seeking (thaks to Michail Zeludkov) (Closes issue 173)
git-svn-id: http://svn.code.sf.net/p/qmmp-dev/code/trunk/qmmp@1344 90c681e8-e032-0410-971d-27865f9a5e38
-rw-r--r--src/plugins/Input/ffmpeg/decoder_ffmpeg.cpp47
-rw-r--r--src/plugins/Input/ffmpeg/decoder_ffmpeg.h3
2 files changed, 48 insertions, 2 deletions
diff --git a/src/plugins/Input/ffmpeg/decoder_ffmpeg.cpp b/src/plugins/Input/ffmpeg/decoder_ffmpeg.cpp
index fbd3edf5b..71a3c1e87 100644
--- a/src/plugins/Input/ffmpeg/decoder_ffmpeg.cpp
+++ b/src/plugins/Input/ffmpeg/decoder_ffmpeg.cpp
@@ -41,6 +41,7 @@ DecoderFFmpeg::DecoderFFmpeg(const QString &path)
m_pkt.size = 0;
m_output_buf = 0;
m_output_at = 0;
+ m_skipBytes = 0;
}
@@ -61,6 +62,7 @@ bool DecoderFFmpeg::initialize()
m_bitrate = 0;
m_skip = FALSE;
m_totalTime = 0;
+ m_seekTime = -1;
avcodec_init();
avcodec_register_all();
@@ -118,6 +120,7 @@ int DecoderFFmpeg::bitrate()
qint64 DecoderFFmpeg::read(char *audio, qint64 maxSize)
{
+ m_skipBytes = 0;
if (m_skip)
{
while(m_temp_pkt.size)
@@ -132,7 +135,8 @@ qint64 DecoderFFmpeg::read(char *audio, qint64 maxSize)
qint64 len = qMin(m_output_at, maxSize);
memcpy(audio, m_output_buf, len);
m_output_at -= len;
- memmove(m_output_buf, m_output_buf + len, m_output_at);
+ memmove(m_output_buf, m_output_buf + len, m_output_at-m_skipBytes);
+
return len;
}
@@ -159,10 +163,11 @@ qint64 DecoderFFmpeg::ffmpeg_decode(uint8_t *audio)
}
void DecoderFFmpeg::seek(qint64 pos)
-{
+{
int64_t timestamp = int64_t(pos)*AV_TIME_BASE/1000;
if (ic->start_time != (qint64)AV_NOPTS_VALUE)
timestamp += ic->start_time;
+ m_seekTime = timestamp;
av_seek_frame(ic, -1, timestamp, AVSEEK_FLAG_BACKWARD);
avcodec_flush_buffers(c);
if(m_pkt.size)
@@ -182,6 +187,7 @@ void DecoderFFmpeg::fillBuffer()
}
m_temp_pkt.size = m_pkt.size;
m_temp_pkt.data = m_pkt.data;
+
if(m_pkt.stream_index != wma_idx)
{
if(m_pkt.data)
@@ -189,8 +195,45 @@ void DecoderFFmpeg::fillBuffer()
m_temp_pkt.size = 0;
continue;
}
+#if (LIBAVCODEC_VERSION_INT >= ((51<<16)+(44<<8)+0))
+ if(m_seekTime && c->codec_id == CODEC_ID_APE)
+ {
+ int64_t rescaledPts = av_rescale(m_pkt.pts,
+ AV_TIME_BASE * (int64_t)
+ ic->streams[m_pkt.stream_index]->time_base.num,
+ ic->streams[m_pkt.stream_index]->time_base.den);
+ m_skipBytes = (m_seekTime - rescaledPts) * c->sample_rate * 4 / AV_TIME_BASE;
+ }
+ else
+ m_skipBytes = 0;
+
+#endif
+ m_seekTime = 0;
+ }
+#if (LIBAVCODEC_VERSION_INT >= ((51<<16)+(44<<8)+0))
+ if(m_skipBytes > 0 && c->codec_id == CODEC_ID_APE)
+ {
+ while (m_skipBytes > 0)
+ {
+ m_output_at = ffmpeg_decode(m_output_buf);
+ m_skipBytes -= m_output_at;
+ }
+
+ if(m_skipBytes < 0)
+ {
+ m_output_at = - m_skipBytes;
+ m_output_at = m_output_at/4*4;
+ memmove(m_output_buf, m_output_buf + m_output_at, m_output_at);
+ m_skipBytes = 0;
+ }
}
+ else
+ m_output_at = ffmpeg_decode(m_output_buf);
+#else
m_output_at = ffmpeg_decode(m_output_buf);
+#endif
+
+
if(m_output_at < 0)
{
m_output_at = 0;
diff --git a/src/plugins/Input/ffmpeg/decoder_ffmpeg.h b/src/plugins/Input/ffmpeg/decoder_ffmpeg.h
index 806496568..624dcd4b3 100644
--- a/src/plugins/Input/ffmpeg/decoder_ffmpeg.h
+++ b/src/plugins/Input/ffmpeg/decoder_ffmpeg.h
@@ -72,6 +72,9 @@ private:
AVPacket m_temp_pkt;
uint8_t *m_output_buf;
qint64 m_output_at;
+
+ int64_t m_seekTime;
+ qint64 m_skipBytes;
};