Mercurial > hg > svcore
diff data/fileio/MP3FileReader.cpp @ 1527:710e6250a401 zoom
Merge from default branch
author | Chris Cannam |
---|---|
date | Mon, 17 Sep 2018 13:51:14 +0100 |
parents | aadfb395e933 |
children | 70e172e6cc59 |
line wrap: on
line diff
--- a/data/fileio/MP3FileReader.cpp Mon Dec 12 15:18:52 2016 +0000 +++ b/data/fileio/MP3FileReader.cpp Mon Sep 17 13:51:14 2018 +0100 @@ -32,12 +32,17 @@ #include <id3tag.h> #endif +#ifdef _WIN32 +#include <io.h> +#include <fcntl.h> +#else +#include <fcntl.h> +#include <unistd.h> +#endif + #include <QFileInfo> -#ifdef _MSC_VER -#include <io.h> -#define open _open -#endif +#include <QTextCodec> using std::string; @@ -75,13 +80,7 @@ CodedAudioFileReader::setFramesToTrim(DEFAULT_DECODER_DELAY, 0); } - struct stat stat; - if (::stat(m_path.toLocal8Bit().data(), &stat) == -1 || stat.st_size == 0) { - m_error = QString("File %1 does not exist.").arg(m_path); - return; - } - - m_fileSize = stat.st_size; + m_fileSize = 0; m_fileBuffer = 0; m_fileBufferSize = 0; @@ -89,53 +88,42 @@ m_sampleBuffer = 0; m_sampleBufferSize = 0; - int fd = -1; - if ((fd = ::open(m_path.toLocal8Bit().data(), O_RDONLY -#ifdef _WIN32 - | O_BINARY -#endif - , 0)) < 0) { - m_error = QString("Failed to open file %1 for reading.").arg(m_path); - return; - } + QFile qfile(m_path); + if (!qfile.open(QIODevice::ReadOnly)) { + m_error = QString("Failed to open file %1 for reading.").arg(m_path); + SVDEBUG << "MP3FileReader: " << m_error << endl; + return; + } + m_fileSize = qfile.size(); + try { // We need a mysterious MAD_BUFFER_GUARD (== 8) zero bytes at // end of input, to ensure libmad decodes the last frame // correctly. Otherwise the decoded audio is truncated. + SVDEBUG << "file size = " << m_fileSize << ", buffer guard = " << MAD_BUFFER_GUARD << endl; m_fileBufferSize = m_fileSize + MAD_BUFFER_GUARD; m_fileBuffer = new unsigned char[m_fileBufferSize]; memset(m_fileBuffer + m_fileSize, 0, MAD_BUFFER_GUARD); } catch (...) { m_error = QString("Out of memory"); - ::close(fd); - return; - } - - ssize_t sz = 0; - ssize_t offset = 0; - while (offset < m_fileSize) { - sz = ::read(fd, m_fileBuffer + offset, m_fileSize - offset); - if (sz < 0) { - m_error = QString("Read error for file %1 (after %2 bytes)") - .arg(m_path).arg(offset); - delete[] m_fileBuffer; - ::close(fd); - return; - } else if (sz == 0) { - SVCERR << QString("MP3FileReader::MP3FileReader: Warning: reached EOF after only %1 of %2 bytes") - .arg(offset).arg(m_fileSize) << endl; - m_fileSize = offset; - m_fileBufferSize = m_fileSize + MAD_BUFFER_GUARD; - memset(m_fileBuffer + m_fileSize, 0, MAD_BUFFER_GUARD); - break; - } - offset += sz; + SVDEBUG << "MP3FileReader: " << m_error << endl; + return; } - ::close(fd); + auto amountRead = qfile.read(reinterpret_cast<char *>(m_fileBuffer), + m_fileSize); - loadTags(); + if (amountRead < m_fileSize) { + SVCERR << QString("MP3FileReader::MP3FileReader: Warning: reached EOF after only %1 of %2 bytes") + .arg(amountRead).arg(m_fileSize) << endl; + memset(m_fileBuffer + amountRead, 0, m_fileSize - amountRead); + m_fileSize = amountRead; + } + + loadTags(qfile.handle()); + + qfile.close(); if (decodeMode == DecodeAtOnce) { @@ -148,6 +136,14 @@ if (!decode(m_fileBuffer, m_fileBufferSize)) { m_error = QString("Failed to decode file %1.").arg(m_path); } + + if (m_sampleBuffer) { + for (int c = 0; c < m_channelCount; ++c) { + delete[] m_sampleBuffer[c]; + } + delete[] m_sampleBuffer; + m_sampleBuffer = 0; + } delete[] m_fileBuffer; m_fileBuffer = 0; @@ -191,14 +187,19 @@ } void -MP3FileReader::loadTags() +MP3FileReader::loadTags(int fd) { m_title = ""; #ifdef HAVE_ID3TAG - id3_file *file = id3_file_open(m_path.toLocal8Bit().data(), - ID3_FILE_MODE_READONLY); +#ifdef _WIN32 + int id3fd = _dup(fd); +#else + int id3fd = dup(fd); +#endif + + id3_file *file = id3_file_fdopen(id3fd, ID3_FILE_MODE_READONLY); if (!file) return; // We can do this a lot more elegantly, but we'll leave that for @@ -207,7 +208,7 @@ id3_tag *tag = id3_file_tag(file); if (!tag) { SVDEBUG << "MP3FileReader::loadTags: No ID3 tag found" << endl; - id3_file_close(file); + id3_file_close(file); // also closes our dup'd fd return; } @@ -228,7 +229,7 @@ } } - id3_file_close(file); + id3_file_close(file); // also closes our dup'd fd #else SVDEBUG << "MP3FileReader::loadTags: ID3 tag support not compiled in" << endl; @@ -479,7 +480,7 @@ enum mad_flow MP3FileReader::accept(struct mad_header const *header, - struct mad_pcm *pcm) + struct mad_pcm *pcm) { int channels = pcm->channels; int frames = pcm->length; @@ -496,6 +497,10 @@ m_fileRate = pcm->samplerate; m_channelCount = channels; + SVDEBUG << "MP3FileReader::accept: file rate = " << pcm->samplerate + << ", channel count = " << channels << ", about to init " + << "decode cache" << endl; + initialiseDecodeCache(); if (m_cacheMode == CacheInTemporaryFile) { @@ -525,6 +530,9 @@ } if (!isDecodeCacheInitialised()) { + SVDEBUG << "MP3FileReader::accept: fallback case: file rate = " << pcm->samplerate + << ", channel count = " << channels << ", about to init " + << "decode cache" << endl; initialiseDecodeCache(); } @@ -548,14 +556,14 @@ for (int i = 0; i < frames; ++i) { - mad_fixed_t sample = 0; - if (ch < activeChannels) { - sample = pcm->samples[ch][i]; - } - float fsample = float(sample) / float(MAD_F_ONE); + mad_fixed_t sample = 0; + if (ch < activeChannels) { + sample = pcm->samples[ch][i]; + } + float fsample = float(sample) / float(MAD_F_ONE); m_sampleBuffer[ch][i] = fsample; - } + } } addSamplesToDecodeCache(m_sampleBuffer, frames); @@ -584,8 +592,8 @@ if (!data->reader->m_decodeErrorShown) { char buffer[256]; snprintf(buffer, 255, - "MP3 decoding error 0x%04x (%s) at byte offset %lu", - stream->error, mad_stream_errorstr(stream), ix); + "MP3 decoding error 0x%04x (%s) at byte offset %lld", + stream->error, mad_stream_errorstr(stream), (long long int)ix); SVCERR << "Warning: in file \"" << data->reader->m_path << "\": " << buffer << " (continuing; will not report any further decode errors for this file)" << endl; data->reader->m_decodeErrorShown = true;