diff options
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); + m_bUnique = false; + } + + if (offset < 0 || (quint64) offset <= (m_lCacheBytePos / 2)) { + l_iCount --; + } + } else { + free(l_SObj); + l_SObj = NULL; + qDebug() << + "SoundSourceFFmpeg::readFramesToCache: General error in audio decode:" << + l_iRet; + } + } - l_lReturnValue = round(convertPtsToByteOffset(pts, ffmpegbase)); + av_free_packet(&l_SPacket); + l_SPacket.data = NULL; + l_SPacket.size = 0; - if ((l_lReturnValue % 4) != 0) { - l_lReturnValue += 4 - (l_lReturnValue % 4); + } else { + l_iError ++; + if (l_iError == 5) { + // Stream end and we couldn't read enough frames + l_iStop = true; + } + } + + |