summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRJ Ryan <rryan@mixxx.org>2014-10-28 11:26:00 -0400
committerRJ Ryan <rryan@mixxx.org>2014-10-28 11:26:00 -0400
commit29777ea9c19b68801336a85566be68a700985c05 (patch)
treed9676aab1e84d14c227c1bb056d748dc1b068342
parent33509d1e3ff0c1db4109a66b17b906683effcd46 (diff)
parent5ff071f199f4607fbaa7b58fb0de6d8595e9fe9b (diff)
Merge remote-tracking branch 'cardinot/coverArtSupport' into
coverart_test * Update WTrackTableView changes to match new WCoverArtMenu behavior. * Remove DirectoryDAO integration for now. Conflicts: src/library/coverartcache.cpp src/library/coverartcache.h src/widget/wcoverartmenu.cpp src/widget/wcoverartmenu.h
-rw-r--r--src/dlgabout.cpp1
-rw-r--r--src/dlgpreflibrary.cpp9
-rw-r--r--src/encoder/encoderffmpegcore.cpp12
-rw-r--r--src/encoder/encoderffmpegresample.cpp68
-rw-r--r--src/encoder/encoderffmpegresample.h14
-rw-r--r--src/engine/enginebuffer.cpp2
-rw-r--r--src/engine/enginemaster.cpp4
-rw-r--r--src/library/browse/browsefeature.cpp9
-rw-r--r--src/library/dao/directorydao.cpp32
-rw-r--r--src/library/itunes/itunesfeature.cpp1
-rw-r--r--src/library/treeitemmodel.cpp6
-rw-r--r--src/skin/legacyskinparser.cpp4
-rw-r--r--src/soundsourceffmpeg.cpp819
-rw-r--r--src/soundsourceffmpeg.h43
-rw-r--r--src/soundsourcemodplug.cpp62
-rw-r--r--src/test/directorydoatest.cpp7
-rw-r--r--src/test/mixxxtest.cpp40
-rw-r--r--src/test/mixxxtest.h4
-rw-r--r--src/track/beatmap.cpp2
-rw-r--r--src/vamp/vampanalyser.cpp3
-rw-r--r--src/waveform/renderers/glwaveformrendererrgb.cpp31
-rw-r--r--src/waveform/renderers/glwaveformrendererrgb.h3
-rw-r--r--src/widget/wcoverart.cpp3
-rw-r--r--src/widget/wcoverartlabel.cpp9
-rw-r--r--src/widget/wcoverartmenu.cpp10
-rw-r--r--src/widget/wcoverartmenu.h11
-rw-r--r--src/widget/wlabel.cpp3
-rw-r--r--src/widget/wtracktableview.cpp23
-rw-r--r--src/widget/wtracktableview.h6
29 files changed, 582 insertions, 659 deletions
diff --git a/src/dlgabout.cpp b/src/dlgabout.cpp
index 25feea457a..67d949a8d7 100644
--- a/src/dlgabout.cpp
+++ b/src/dlgabout.cpp
@@ -150,6 +150,7 @@ DlgAbout::DlgAbout(QWidget* parent) : QDialog(parent), Ui::DlgAboutDlg() {
"Ryan Kramer<br>"
"Zak Reynolds<br>"
"Alex Barker<br>"
+"Dennis Rohner<br>"
"</p>"
"<p align=\"center\"><b>%3</b></p>"
diff --git a/src/dlgpreflibrary.cpp b/src/dlgpreflibrary.cpp
index d8567a792d..8b9402346d 100644
--- a/src/dlgpreflibrary.cpp
+++ b/src/dlgpreflibrary.cpp
@@ -76,11 +76,10 @@ void DlgPrefLibrary::slotHide() {
QMessageBox msgBox;
msgBox.setIcon(QMessageBox::Warning);
- msgBox.setWindowTitle(tr("Added Directory"));
- msgBox.setText(tr("Music Directory Added.\n"
- "You added one or more music directories. Contained files"
- "won't be available until you rescan your library. Would"
- "you like to rescan now?"));
+ msgBox.setWindowTitle(tr("Music Directory Added"));
+ msgBox.setText(tr("You added one or more music directories. The tracks in "
+ "these directories won't be available until you rescan "
+ "your library. Would you like to rescan now?"));
QPushButton* scanButton = msgBox.addButton(
tr("Scan"), QMessageBox::AcceptRole);
msgBox.addButton(QMessageBox::Cancel);
diff --git a/src/encoder/encoderffmpegcore.cpp b/src/encoder/encoderffmpegcore.cpp
index ed50bf7fd3..3e4caf08b9 100644
--- a/src/encoder/encoderffmpegcore.cpp
+++ b/src/encoder/encoderffmpegcore.cpp
@@ -109,10 +109,6 @@ EncoderFfmpegCore::~EncoderFfmpegCore() {
delete m_pResample;
}
-unsigned int EncoderFfmpegCore::reSample(AVFrame *inframe) {
- return m_pResample->reSample(inframe);
-}
-
//call sendPackages() or write() after 'flush()' as outlined in engineshoutcast.cpp
void EncoderFfmpegCore::flush() {
}
@@ -298,6 +294,7 @@ int EncoderFfmpegCore::writeAudioFrame(AVFormatContext *formatctx,
AVFrame *l_SFrame = avcodec_alloc_frame();
int l_iGotPacket;
int l_iRet;
+ uint8_t *l_iOut = NULL;
#ifdef av_make_error_string
char l_strErrorBuff[256];
#endif // av_make_error_string
@@ -344,7 +341,7 @@ int EncoderFfmpegCore::writeAudioFrame(AVFormatContext *formatctx,
// to something that fits..
if (l_SCodecCtx->sample_fmt != AV_SAMPLE_FMT_FLT) {
- reSample(l_SFrame);
+ m_pResample->reSample(l_SFrame, &l_iOut);
// After we have turned our samples to destination
// Format we must re-alloc l_SFrame.. it easier like this..
#if LIBAVCODEC_VERSION_INT > 3544932
@@ -362,10 +359,13 @@ int EncoderFfmpegCore::writeAudioFrame(AVFormatContext *formatctx,
l_iRet = avcodec_fill_audio_frame(l_SFrame, l_SCodecCtx->channels,
l_SCodecCtx->sample_fmt,
- (const uint8_t *)m_pResample->getBuffer(),
+ l_iOut,
m_iAudioCpyLen,
1);
+ free(l_iOut);
+ l_iOut = NULL;
+
if (l_iRet != 0) {
#ifdef av_make_error_string
qDebug() << "Can't refill FFMPEG frame: error " << l_iRet << "String '" <<
diff --git a/src/encoder/encoderffmpegresample.cpp b/src/encoder/encoderffmpegresample.cpp
index 278228ab86..81a3a47aea 100644
--- a/src/encoder/encoderffmpegresample.cpp
+++ b/src/encoder/encoderffmpegresample.cpp
@@ -21,8 +21,6 @@
EncoderFfmpegResample::EncoderFfmpegResample(AVCodecContext *codecCtx) {
m_pSwrCtx = NULL;
m_pCodecCtx = codecCtx;
- m_pOutSize = 0;
- m_pOut = NULL;
}
EncoderFfmpegResample::~EncoderFfmpegResample() {
@@ -30,7 +28,7 @@ EncoderFfmpegResample::~EncoderFfmpegResample() {
#ifndef __FFMPEGOLDAPI__
#ifdef __LIBAVRESAMPLE__
- avresample_close(m_pSwrCtx);
+ avresample_free(&m_pSwrCtx);
#else
swr_free(&m_pSwrCtx);
#endif // __LIBAVRESAMPLE__
@@ -41,11 +39,6 @@ EncoderFfmpegResample::~EncoderFfmpegResample() {
}
}
-unsigned int EncoderFfmpegResample::getBufferSize() {
- return m_pOutSize;
-}
-
-
int EncoderFfmpegResample::open(enum AVSampleFormat inSampleFmt,
enum AVSampleFormat outSampleFmt) {
m_pOutSampleFmt = outSampleFmt;
@@ -167,25 +160,7 @@ int EncoderFfmpegResample::open(enum AVSampleFormat inSampleFmt,
return 0;
}
-
-#ifndef __FFMPEGOLDAPI__
-uint8_t *EncoderFfmpegResample::getBuffer()
-#else
-short *EncoderFfmpegResample::getBuffer()
-#endif // __FFMPEGOLDAPI__
-{
- return m_pOut;
-}
-
-void EncoderFfmpegResample::removeBuffer() {
- av_freep(&m_pOut);
- m_pOut = NULL;
- m_pOutSize = 0;
-}
-
-
-
-unsigned int EncoderFfmpegResample::reSample(AVFrame *inframe) {
+unsigned int EncoderFfmpegResample::reSample(AVFrame *inframe, quint8 **outbuffer) {
if (m_pSwrCtx) {
@@ -195,16 +170,16 @@ unsigned int EncoderFfmpegResample::reSample(AVFrame *inframe) {
#if LIBAVRESAMPLE_VERSION_MAJOR == 0
void **l_pIn = (void **)inframe->extended_data;
#else
- uint8_t **l_pIn = (uint8_t **)inframe->extended_data;
+ quint8 **l_pIn = (quint8 **)inframe->extended_data;
#endif // LIBAVRESAMPLE_VERSION_MAJOR == 0
#else
- uint8_t **l_pIn = (uint8_t **)inframe->extended_data;
+ quint8 **l_pIn = (quint8 **)inframe->extended_data;
#endif // __LIBAVRESAMPLE__
// Left here for reason!
// Sometime in time we will need this!
#else
- int64_t l_lInReadBytes = av_samples_get_buffer_size(NULL, m_pCodecCtx->channels,
+ qint64 l_lInReadBytes = av_samples_get_buffer_size(NULL, m_pCodecCtx->channels,
inframe->nb_samples,
m_pCodecCtx->sample_fmt, 1);
#endif // __FFMPEGOLDAPI__
@@ -229,7 +204,7 @@ unsigned int EncoderFfmpegResample::reSample(AVFrame *inframe) {
int l_iOutSamplesLines = 0;
// Alloc too much.. if not enough we are in trouble!
- av_samples_alloc(&m_pOut, &l_iOutSamplesLines, 2, l_iOutSamples,
+ av_samples_alloc(outbuffer, &l_iOutSamplesLines, 2, l_iOutSamples,
m_pOutSampleFmt, 0);
#else
int l_iOutSamples = av_rescale_rnd(inframe->nb_samples,
@@ -242,7 +217,7 @@ unsigned int EncoderFfmpegResample::reSample(AVFrame *inframe) {
m_pOutSampleFmt, 1);
- m_pOut = (short *)malloc(l_iOutBytes * 2);
+ outbuffer = (short *)malloc(l_iOutBytes * 2);
#endif // __FFMPEGOLDAPI__
int l_iLen = 0;
@@ -254,25 +229,25 @@ unsigned int EncoderFfmpegResample::reSample(AVFrame *inframe) {
// USED IN FFMPEG 1.0 (LibAV SOMETHING!). New in FFMPEG 1.1 and libav 9
#if LIBAVRESAMPLE_VERSION_INT <= 3
// AVResample OLD
- l_iLen = avresample_convert(m_pSwrCtx, (void **)&m_pOut, 0, l_iOutSamples,
+ l_iLen = avresample_convert(m_pSwrCtx, (void **)outbuffer, 0, l_iOutSamples,
(void **)l_pIn, 0, inframe->nb_samples);
#else
//AVResample NEW
- l_iLen = avresample_convert(m_pSwrCtx, (uint8_t **)&m_pOut, 0, l_iOutSamples,
- (uint8_t **)l_pIn, 0, inframe->nb_samples);
+ l_iLen = avresample_convert(m_pSwrCtx, (quint8 **)outbuffer, 0, l_iOutSamples,
+ (quint8 **)l_pIn, 0, inframe->nb_samples);
#endif // LIBAVRESAMPLE_VERSION_INT <= 3
#else
// SWResample
- l_iLen = swr_convert(m_pSwrCtx, (uint8_t **)&m_pOut, l_iOutSamples,
- (const uint8_t **)l_pIn, inframe->nb_samples);
+ l_iLen = swr_convert(m_pSwrCtx, (quint8 **)outbuffer, l_iOutSamples,
+ (const quint8 **)l_pIn, inframe->nb_samples);
#endif // __LIBAVRESAMPLE__
l_iOutBytes = av_samples_get_buffer_size(NULL, 2, l_iLen, m_pOutSampleFmt, 1);
#else
l_iLen = audio_resample(m_pSwrCtx,
- (short *)m_pOut, (short *)inframe->data[0],
+ (short *)outbuffer, (short *)inframe->data[0],
inframe->nb_samples);
#endif // __FFMPEGOLDAPI__
@@ -280,10 +255,23 @@ unsigned int EncoderFfmpegResample::reSample(AVFrame *inframe) {
qDebug() << "Sample format conversion failed!";
return -1;
}
- m_pOutSize = l_iOutBytes;
return l_iOutBytes;
} else {
- return 0;
+ quint8 *l_ptrBuf = NULL;
+ qint64 l_lInReadBytes = av_samples_get_buffer_size(NULL, m_pCodecCtx->channels,
+ inframe->nb_samples,
+ m_pCodecCtx->sample_fmt, 1);
+
+ if(l_lInReadBytes < 0) {
+ return 0;
+ }
+
+ l_ptrBuf = (quint8 *)av_malloc(l_lInReadBytes);
+
+ memcpy(l_ptrBuf, inframe->data[0], l_lInReadBytes);
+
+ outbuffer[0] = l_ptrBuf;
+ return l_lInReadBytes;
}
return 0;
diff --git a/src/encoder/encoderffmpegresample.h b/src/encoder/encoderffmpegresample.h
index 4f1b76c26d..6a008c5d38 100644
--- a/src/encoder/encoderffmpegresample.h
+++ b/src/encoder/encoderffmpegresample.h
@@ -55,16 +55,8 @@ public:
EncoderFfmpegResample(AVCodecContext *codecCtx);
~EncoderFfmpegResample();
int open(enum AVSampleFormat inSampleFmt, enum AVSampleFormat outSampleFmt);
- unsigned int getBufferSize();
-#ifndef __FFMPEGOLDAPI__
- uint8_t *getBuffer();
-#else
- short *getBuffer();
-#endif
-
- void removeBuffer();
- unsigned int reSample(AVFrame *inframe);
+ unsigned int reSample(AVFrame *inframe, quint8 **outbuffer);
private:
AVCodecContext *m_pCodecCtx;
@@ -81,13 +73,11 @@ private:
#else
SwrContext *m_pSwrCtx;
#endif
- uint8_t *m_pOut;
+
#else
ReSampleContext *m_pSwrCtx;
- short *m_pOut;
#endif
- unsigned int m_pOutSize;
};
#endif
diff --git a/src/engine/enginebuffer.cpp b/src/engine/enginebuffer.cpp
index d35a85b3a3..df6911bc99 100644
--- a/src/engine/enginebuffer.cpp
+++ b/src/engine/enginebuffer.cpp
@@ -472,7 +472,7 @@ void EngineBuffer::setNewPlaypos(double newpos) {
// Must hold the engineLock while using m_engineControls
m_engineLock.lock();
for (QList<EngineControl*>::iterator it = m_engineControls.begin();
- it != m_engineControls.end(); it++) {
+ it != m_engineControls.end(); ++it) {
EngineControl *pControl = *it;
pControl->notifySeek(m_filepos_play);
}
diff --git a/src/engine/enginemaster.cpp b/src/engine/enginemaster.cpp
index 185bbd3e1f..e0583bb1fe 100644
--- a/src/engine/enginemaster.cpp
+++ b/src/engine/enginemaster.cpp
@@ -226,15 +226,13 @@ void EngineMaster::processChannels(unsigned int* busChannelConnectionFlags,
int iBufferSize) {
ScopedTimer timer("EngineMaster::processChannels");
- QList<ChannelInfo*>::iterator it = m_channels.begin();
-
// Clear talkover compressor for the next round of gain calculation.
m_pTalkoverDucking->clearKeys();
EngineChannel* pMasterChannel = m_pMasterSync->getMaster();
m_activeChannels.clear();
m_activeChannels.reserve(m_channels.size());
- it = m_channels.begin();
+ QList<ChannelInfo*>::iterator it = m_channels.begin();
for (unsigned int channel_number = 0;
it != m_channels.end(); ++it, ++channel_number) {
ChannelInfo* pChannelInfo = *it;
diff --git a/src/library/browse/browsefeature.cpp b/src/library/browse/browsefeature.cpp
index ff45e498ec..a2308c1e93 100644
--- a/src/library/browse/browsefeature.cpp
+++ b/src/library/browse/browsefeature.cpp
@@ -145,11 +145,10 @@ void BrowseFeature::slotAddToLibrary() {
QMessageBox msgBox;
msgBox.setIcon(QMessageBox::Warning);
// strings are dupes from DlgPrefLibrary
- msgBox.setWindowTitle(tr("Added Directory"));
- msgBox.setText(tr("Music Directory Added.\n"
- "You added one or more music directories. Contained files"
- "won't be available until you rescan your library. Would"
- "you like to rescan now?"));
+ msgBox.setWindowTitle(tr("Music Directory Added"));
+ msgBox.setText(tr("You added one or more music directories. The tracks in "
+ "these directories won't be available until you rescan "
+ "your library. Would you like to rescan now?"));
QPushButton* scanButton = msgBox.addButton(
tr("Scan"), QMessageBox::AcceptRole);
msgBox.addButton(QMessageBox::Cancel);
diff --git a/src/library/dao/directorydao.cpp b/src/library/dao/directorydao.cpp
index 27aefcfa0e..48c6fa333e 100644
--- a/src/library/dao/directorydao.cpp
+++ b/src/library/dao/directorydao.cpp
@@ -96,12 +96,12 @@ QSet<int> DirectoryDAO::relocateDirectory(const QString& oldFolder,
// location column becomes non-unique.
ScopedTransaction transaction(m_database);
QSqlQuery query(m_database);
- query.prepare("UPDATE " % DIRECTORYDAO_TABLE % " SET " % DIRECTORYDAO_DIR % "="
- ":newFolder WHERE " % DIRECTORYDAO_DIR % " = :oldFolder");
+ query.prepare("UPDATE " % DIRECTORYDAO_TABLE % " SET " % DIRECTORYDAO_DIR %
+ "=:newFolder WHERE " % DIRECTORYDAO_DIR % " = :oldFolder");
query.bindValue(":newFolder", newFolder);
query.bindValue(":oldFolder", oldFolder);
if (!query.exec()) {
- LOG_FAILED_QUERY(query) << "coud not relocate directory"
+ LOG_FAILED_QUERY(query) << "could not relocate directory"
<< oldFolder << "to" << newFolder;
return QSet<int>();
}
@@ -109,16 +109,19 @@ QSet<int> DirectoryDAO::relocateDirectory(const QString& oldFolder,
FieldEscaper escaper(m_database);
// on Windows the absolute path starts with the drive name
// we also need to check for that
- QString startsWithOldFolder = escaper.escapeStringForLike(QDir(oldFolder).absolutePath() + "/", '%') + "%";
+ QString startsWithOldFolder = escaper.escapeStringForLike(
+ QDir(oldFolder).absolutePath() + "/", '%') + "%";
+
// Also update information in the track_locations table. This is where mixxx
- // gets the location information for a track. Put marks around %1 so that this also works on windows
+ // gets the location information for a track. Put marks around %1 so that
+ // this also works on windows
query.prepare(QString("SELECT library.id, track_locations.id, track_locations.location "
"FROM library INNER JOIN track_locations ON "
"track_locations.id = library.location WHERE "
"track_locations.location LIKE '%1' ESCAPE '%'")
.arg(startsWithOldFolder));
if (!query.exec()) {
- LOG_FAILED_QUERY(query) << "coud not relocate path of tracks";
+ LOG_FAILED_QUERY(query) << "could not relocate path of tracks";
return QSet<int>();
}
@@ -131,8 +134,8 @@ QSet<int> DirectoryDAO::relocateDirectory(const QString& oldFolder,
old_locs.append(query.value(2).toString());
}
- QString replacement("UPDATE track_locations SET location = :newloc "
- "WHERE id = :id");
+ QString replacement = "UPDATE track_locations SET location = :newloc "
+ "WHERE id = :id";
query.prepare(replacement);
for (int i = 0; i < loc_ids.size(); ++i) {
QString newloc = old_locs.at(i);
@@ -140,23 +143,12 @@ QSet<int> DirectoryDAO::relocateDirectory(const QString& oldFolder,
query.bindValue("newloc", newloc);
query.bindValue("id", loc_ids.at(i));
if (!query.exec()) {
- LOG_FAILED_QUERY(query) << "coud not relocate path of tracks";
+ LOG_FAILED_QUERY(query) << "could not relocate path of tracks";
return QSet<int>();
}
}
- query.prepare(QString("SELECT location FROM track_locations"));
- if (!query.exec()) {
- LOG_FAILED_QUERY(query) << "coud not select track locations";
- return QSet<int>();
- }
-
- while (query.next()) {
- qDebug() << query.value(0).toString();
- }
-
qDebug() << "Relocated tracks:" << ids.size();
-
transaction.commit();
return ids;
}
diff --git a/src/library/itunes/itunesfeature.cpp b/src/library/itunes/itunesfeature.cpp
index 4e77907b54..c9c5f4b14b 100644
--- a/src/library/itunes/itunesfeature.cpp
+++ b/src/library/itunes/itunesfeature.cpp
@@ -689,7 +689,6 @@ void ITunesFeature::parsePlaylist(QXmlStreamReader &xml, QSqlQuery &query_insert
// When processing playlist entries, playlist name and id have
// already been processed and persisted
if (key == "Track ID") {
- track_reference = -1;
readNextStartElement(xml);
track_reference = xml.readElementText().toInt();
diff --git a/src/library/treeitemmodel.cpp b/src/library/treeitemmodel.cpp
index 90e1a4c5f3..678e8f8d59 100644
--- a/src/library/treeitemmodel.cpp
+++ b/src/library/treeitemmodel.cpp
@@ -165,10 +165,9 @@ bool TreeItemModel::insertRows(QList<TreeItem*> &data, int position, int rows, c
return true;
}
TreeItem *parentItem = getItem(parent);
- bool success;
beginInsertRows(parent, position, position + rows - 1);
- success = parentItem->insertChildren(data, position, rows);
+ bool success = parentItem->insertChildren(data, position, rows);
endInsertRows();
return success;
@@ -179,10 +178,9 @@ bool TreeItemModel::removeRows(int position, int rows, const QModelIndex &parent
return true;
}
TreeItem *parentItem = getItem(parent);
- bool success = true;
beginRemoveRows(parent, position, position + rows - 1);
- success = parentItem->removeChildren(position, rows);
+ bool success = parentItem->removeChildren(position, rows);
endRemoveRows();
return success;
diff --git a/src/skin/legacyskinparser.cpp b/src/skin/legacyskinparser.cpp
index b1bf05c604..64036235fd 100644
--- a/src/skin/legacyskinparser.cpp
+++ b/src/skin/legacyskinparser.cpp
@@ -1159,10 +1159,8 @@ QString LegacySkinParser::getLibraryStyle(QDomNode node) {
#undef ohyesithas
#endif
- QString styleHack = "";
-
// Style the library preview button with a default image.
- styleHack = (
+ QString styleHack = (
"#LibraryPreviewButton { background: transparent; border: 0; }"
"#LibraryPreviewButton:checked {"
" image: url(:/images/library/ic_library_preview_pause.png);"
diff --git a/src/soundsourceffmpeg.cpp b/src/soundsourceffmpeg.cpp
index 624c4e7bd1..76a89b682b 100644
--- a/src/soundsourceffmpeg.cpp
+++ b/src/soundsourceffmpeg.cpp
@@ -3,7 +3,7 @@
soundsourceffmpeg.cpp - ffmpeg decoder
-------------------
copyright : (C) 2007 by Cedric GESTES
- (C) 2012-2013 by Tuukka Pasanen
+ (C) 2012-2014 by Tuukka Pasanen
email : tuukka.pasanen@ilmi.fi
This one tested with FFMPEG 0.10/0.11/1.0/1.1/1.2/2,0/2,1/GIT
@@ -24,25 +24,13 @@
#include "trackinfoobject.h"
#include "soundsourceffmpeg.h"
-//#ifdef __WINDOWS__
-//#include <io.h>
-//#include <fcntl.h>
-//#endif
-
#include <QtDebug>
#include <QBuffer>
static QMutex ffmpegmutex;
-// If some point of time we don't want
-// to use buffering (mostly for debug)
-// We turn it off
-//5#define FFMPEG_USE_BUFFER_PLAY
-
-#define FFMPEG_MP3_FRAME_SIZE 1152
-#define FFMPEG_MP4_FRAME_SIZE 1024
-#define FFMPEG_OPUS_FRAME_SIZE 960
-#define FFMPEG_OGG_FRAME_SIZE 128
+#define SOUNDSOURCEFFMPEG_CACHESIZE 1000
+#define SOUNDSOURCEFFMPEG_POSDISTANCE ((1024 * 1000) / 8)
SoundSourceFFmpeg::SoundSourceFFmpeg(QString filename)
: Mixxx::SoundSource(filename)
@@ -50,37 +38,45 @@ SoundSourceFFmpeg::SoundSourceFFmpeg(QString filename)
m_iAudioStream = -1;
filelength = -1;
m_pFormatCtx = NULL;
- m_pIformat = NULL;
m_pCodecCtx = NULL;
m_pCodec = NULL;
- m_iOffset = 0;
- m_iSeekOffset = 0;
m_bIsSeeked = FALSE;
- m_iReadedBytes = 0;
- m_iNextMixxxPCMPoint = -1;
m_pResample = NULL;
- m_fMixxBytePosition = 0;
- m_iLastFirstFfmpegByteOffset = 0;
m_iCurrentMixxTs = 0;
+ m_lCacheBytePos = 0;
+ m_lCacheStartByte = 0;
+ m_lCacheEndByte = 0;
+ m_lCacheLastPos = 0;
+ m_lLastStoredPos = 0;
+ m_lStoredSeekPoint = -1;
+ m_SCache.clear();
this->setType(filename.section(".",-1).toLower());
}
SoundSourceFFmpeg::~SoundSourceFFmpeg() {
+ struct ffmpegLocationObject *l_SRmJmp = NULL;
+ clearCache();
+
if (m_pCodecCtx != NULL) {
- // Enable If needed in future
- //lock();
+ qDebug() << "~SoundSourceFFmpeg(): Clear FFMPEG stuff";
avcodec_close(m_pCodecCtx);
- //unlock();
- //lock();
avformat_close_input(&m_pFormatCtx);
- //unlock();
+ av_free(m_pFormatCtx);
}
if (m_pResample != NULL) {
+ qDebug() << "~SoundSourceFFmpeg(): Delete FFMPEG Resampler";
delete m_pResample;
}
-};
+
+ while (m_SJumpPoints.size() > 0) {
+ l_SRmJmp = m_SJumpPoints[0];
+ m_SJumpPoints.remove(0);
+ free(l_SRmJmp);
+ }
+
+}
AVCodecContext *SoundSourceFFmpeg::getCodecContext() {
return m_pCodecCtx;
@@ -94,7 +90,6 @@ int SoundSourceFFmpeg::getAudioStreamIndex() {
return m_iAudioStream;
}
-
void SoundSourceFFmpeg::lock() {
ffmpegmutex.lock();
}
@@ -103,79 +98,305 @@ void SoundSourceFFmpeg::unlock() {
ffmpegmutex.unlock();
}
-double SoundSourceFFmpeg::convertPtsToByteOffset(double pts,
- const AVRational &ffmpegtime) {
- return (pts / (double)ffmpegtime.den * (double)this->getSampleRate() *
- (double)2.);
-}
+bool SoundSourceFFmpeg::clearCache() {
+ struct ffmpegCacheObject *l_SRmObj = NULL;
-double SoundSourceFFmpeg::convertByteOffsetToPts(double byteoffset,
- const AVRational &ffmpegtime) {
- return (byteoffset / (double)this->getSampleRate() / (double)2.) *
- (double)ffmpegtime.den;
+ while (m_SCache.size() > 0) {
+ l_SRmObj = m_SCache[0];
+ m_SCache.remove(0);
+ free(l_SRmObj->bytes);
+ free(l_SRmObj);
+ }
+
+ return true;
}
-int64_t SoundSourceFFmpeg::convertPtsToByteOffsetOld(int64_t pts,
- const AVRational &ffmpegbase) {
- int64_t l_lReturnValue = 0;
+bool SoundSourceFFmpeg::readFramesToCache(unsigned int count, qint64 offset) {
+ unsigned int l_iCount = 0;
+ qint32 l_iRet = 0;
+ AVPacket l_SPacket;
+ AVFrame *l_pFrame = NULL;
+ bool l_iStop = false;
+ int l_iFrameFinished = 0;
+ struct ffmpegCacheObject *l_SObj = NULL;
+ struct ffmpegCacheObject *l_SRmObj = NULL;
+ bool m_bUnique = false;
+ qint64 l_lLastPacketPos = -1;
+ int l_iError = 0;
+ int l_iFrameCount = 0;
+
+ l_iCount = count;
+
+ l_SPacket.data = NULL;
+ l_SPacket.size = 0;
+
+
+ while (l_iCount > 0) {
+ if (l_pFrame != NULL) {
+ l_iFrameCount --;
+// FFMPEG 2.2 3561060 anb beyond
+#if LIBAVCODEC_VERSION_INT >= 3561060
+ av_frame_free(&l_pFrame);
+// FFMPEG 0.11 and below
+#elif LIBAVCODEC_VERSION_INT <= 3544932
+ av_free(l_pFrame);
+// FFMPEG 1.0 - 2.1
+#else
+ avcodec_free_frame(&l_pFrame);
+#endif
+ l_pFrame = NULL;
+
+ }
+
+ if (l_iStop == true) {
+ break;
+ }
+ l_iFrameCount ++;
+ av_init_packet(&l_SPacket);
+#if LIBAVCODEC_VERSION_INT < 3617792
+ l_pFrame = avcodec_alloc_frame();
+#else
+ l_pFrame = av_frame_alloc();
+#endif
+
+ if (av_read_frame(m_pFormatCtx, &l_SPacket) >= 0) {
+ if (l_SPacket.stream_index == m_iAudioStream) {
+ if (m_lStoredSeekPoint > 0) {
+ // Seek for correct jump point
+ if (m_lStoredSeekPoint > l_SPacket.pos &&
+ m_lStoredSeekPoint >= SOUNDSOURCEFFMPEG_POSDISTANCE) {
+ av_free_packet(&l_SPacket);
+ l_SPacket.data = NULL;
+ l_SPacket.size = 0;
+ continue;
+ }
+ m_lStoredSeekPoint = -1;
+ }
+
+ l_iRet = avcodec_decode_audio4(m_pCodecCtx,l_pFrame,&l_iFrameFinished,
+ &l_SPacket);
+
+ if (l_iRet <= 0) {
+ // An error or EOF occured,index break out and return what
+ // we have so far.
+ qDebug() << "EOF!";
+ l_iStop = true;
+ continue;
+ } else {
+ l_iRet = 0;
+ l_SObj = (struct ffmpegCacheObject *)malloc(sizeof(struct ffmpegCacheObject));
+ if (l_SObj == NULL) {
+ qDebug() << "SoundSourceFFmpeg::readFramesToCache: Not enough memory!";
+ l_iStop = true;
+ continue;
+ }
+ memset(l_SObj, 0x00, sizeof(struct ffmpegCacheObject));
+ l_iRet = m_pResample->reSample(l_pFrame, &l_SObj->bytes);
+
+ if (l_iRet > 0) {
+ // Remove from cache
+ if (m_SCache.size() >= (SOUNDSOURCEFFMPEG_CACHESIZE - 10)) {
+ l_SRmObj = m_SCache[0];
+ m_SCache.remove(0);
+ free(l_SRmObj->bytes);
+ free(l_SRmObj);
+ }
+
+ // Add to cache and store byte place to memory
+ m_SCache.append(l_SObj);
+ l_SObj->startByte = m_lCacheBytePos / 2;
+ l_SObj->length = l_iRet / 2;
+ m_lCacheBytePos += l_iRet;
+
+ // Ogg/Opus have packages pos that have many
+ // audio frames so seek next unique pos..
+ if (l_SPacket.pos != l_lLastPacketPos) {
+ m_bUnique = true;
+ l_lLastPacketPos = l_SPacket.pos;
+ }
+
+ // If we are over last storepos and we have read more than jump point need is and pos is unique we store it to memory
+ if (m_lCacheBytePos > m_lLastStoredPos &&
+ m_lCacheBytePos > (SOUNDSOURCEFFMPEG_POSDISTANCE + m_lLastStoredPos) &&
+ m_bUnique == true) {
+ struct ffmpegLocationObject *l_SJmp = (struct ffmpegLocationObject *)malloc(
+ sizeof(struct ffmpegLocationObject));
+ m_lLastStoredPos = m_lCacheBytePos;
+ l_SJmp->startByte = m_lCacheBytePos / 2;
+ l_SJmp->pos = l_SPacket.pos;
+ l_SJmp->pts = l_SPacket.pts;
+ m_SJumpPoints.append(l_SJmp);
+